HDLBits:在线学习 Verilog (二十一 · Problem 100 – 104)

转载自:知乎
作者:木帅宇

首先附上传送门:

Count1to10 – HDLBits​

Problem 100 Decade counter again

牛刀小试

本题和Problem 99 类似,还是1~10的计数器,唯一不同是同步复位为1.

解答与解析

module top_module (
    input clk,
    input reset,
    output [3:0] q);

    always @ (posedge clk)
        begin
            if(reset)
                q <= 4'b0001;
            else if(q <= 4'b1001)
                q <= q + 1'b1;
            else 
                q <= 4'b0001;

        end

endmodule

Problem 101 Slow decade counter

牛刀小试

设计一个0~9的计数器,共10个周期。该计数器采用同步复位且复位为0。但是本题是希望该计数器并不是随着clk的变化而递增,而是随着一个slowena使能信号来控制增加。时序图如下图所示

解答与解析

本题相比于之前的计数器,不同点在于多了一个enable信号来控制计数器的增加。

module top_module (
    input clk,
    input slowena,
    input reset,
    output [3:0] q);

    reg [3:0] cnt;
    //period is 10 
    //What is supposed to happen when the counter is 9 and not enabled?
    always @ (posedge clk)
        begin
            if(reset)
                cnt <= 4'b0;
            else if(slowena == 1'b1)
                //slowena 为高,计数器才能正常运行
                begin
                    if(cnt == 4'd9)
                        cnt <= 4'b0;
                    //因为题目要求周期为10,所以0~9之后下一个为0;
                    else 
                        cnt <= cnt + 4'd1;
                end
        end

    assign q = cnt;

endmodule

Problem 102 Counter 1-12

牛刀小试

根据以下输入输出信号设计一个计算1~12的计数器

Reset:同步复位信号,高复位,将计数器复位为1.

Enable:使能信号高有效

Clk:时钟上升沿触发计数器工作

Q[3:0]:计数器输出

c\_enable, c\_load, c\_d[3:0]:题目中给我们提供了一个4-bit的计数器,这三个信号是用于该4-bit计数器的控制信号。

题目提供给我们4-bit计数器

  1. 有enable信号,带复位和置位的计数器,将该计数器例化至我们的代码中。
  2. 再用一些其他的逻辑门来完成本题
//题目提供的4-bit计数器代码
module count4(
    input clk,
    input enable,
    input load,
    input [3:0] d,
    output reg [3:0] Q
);

解答与解析

本题相当于用c\_enale、c\_load和c\_d[3:0]三个控制信号来控制题目中给我们提供的4-bit计数器,使得该计数器的技术范围改变为1~12.

就是上图所示的样子。

module top_module (
    input clk,
    input reset,
    input enable,
    output [3:0] Q,
    output c_enable,
    output c_load,
    output [3:0] c_d
); //

    reg [3:0] temp;

    //4-bit计数器的控制信号
    assign c_enable = enable;
    //带复位和置位,
    assign c_load   = reset | (Q == 4'd12 & enable == 1'b1);
    assign c_d      = 4'b1;

//    count4 the_counter (clk, c_enable, c_load, c_d, Q );
    count4 Inst_count4
    (
        .clk(clk),
        .enable(c_enable),
        .load(c_load),
        .d(c_d),
        .Q(Q)
    );

endmodule

Problem 103 Counter 1000

牛刀小试

从1000Hz中分离出1Hz的信号,叫做OneHertz。这个主要用作与数字时钟中。利用一个模10的BCD计数器和尽量少的逻辑门来建立一个时钟分频器。同时输出每个BCD计算器的使能信号(c\_enable[0]为高位,c\_enable[2]为低位)。

题目已经给我们提供了BCD计数器。Enable信号高有效。Reset信号高有效且复位为0。我们设计的电路中均要采用1000Hz的时钟。

module bcdcount (
    input clk,
    input reset,
    input enable,
    output reg [3:0] Q
);

解答与解析

本题可以这样考虑,假设三个定时器a,b,c都是模10的计数器,a的输入时钟是1000Hz,每当a计到10的时候,给b一个使能,相当于a计10次,b才计1次,b是a的十分之一,故b的时钟是100Hz。同理c是a的百分之1为10Hz。所以到999是输出就为1Hz了。

module top_module (
    input clk,
    input reset,
    output OneHertz,
    output [2:0] c_enable
); //

    wire [3:0] q0, q1, q2;

    assign c_enable = {q1 == 4'd9 && q0 == 4'd9, q0 == 4'd9, 1'b1};
    assign OneHertz = {q2 == 4'd9 && q1 == 4'd9 && q0 == 4'd9};

    bcdcount counter0 (clk, reset, c_enable[0], q0);
    bcdcount counter1 (clk, reset, c_enable[1], q1);
    bcdcount counter2 (clk, reset, c_enable[2], q2);

endmodule

Problem 104 4-digit decimal counter

牛刀小试

设计一个4位BCD(二进制编码十进制)计数器。每个十进制数字使用4-bit来表示:q[3:0]是个位,q[7:4]是十位等。对于ena[3:1],该信号用来表示个位、十位和百位的进位。时序图如下图所示:

解答与解析

module top_module (
    input clk,
    input reset,   // Synchronous active-high reset
    output [3:1] ena,
    output [15:0] q);

    //one
    count Inst1_count
    (
        .clk(clk),
        .reset(reset),
        .ena(1'b1),
        .q(q[3:0])
    );

    //ten 
    count Inst2_count
    (
        .clk(clk),
        .reset(reset),
        .ena(q[3:0] == 4'd9),
        .q(q[7:4])
    );

    //hundred
    count Inst3_count
    (
        .clk(clk),
        .reset(reset),
        .ena(q[7:4] == 4'd9 && q[3:0] == 4'd9),
        .q(q[11:8])
    );

    //thousand
    count Inst4_count
    (
        .clk(clk),
        .reset(reset),
        .ena(q[11:8] == 4'd9 && q[7:4] == 4'd9 && q[3:0] == 4'd9),
        .q(q[15:12])
    );

    //用来表示进位
    assign ena = {q[11:8] == 4'd9 && q[7:4] == 4'd9 && q[3:0] == 4'd9, q[7:4] == 4'd9 && q[3:0] == 4'd9, q[3:0] == 4'd9};

endmodule

module count
(
    input clk,
    input reset,
    input ena,
    output reg[3:0] q
);

    always @ (posedge clk)
        begin
            if(reset)
                q <= 4'b0;
            else if (ena)
                begin
                    if(q == 4'd9) 
                        q <= 4'd0;
                    else
                        q <= q + 1'b1;
                end
        end

endmodule

推荐阅读

  • HDLBits:在线学习 Verilog (十九 · Problem 90 – 94)
  • HDLBits:在线学习 Verilog (十八 · Problem 85-89)
  • HDLBits:在线学习 Verilog (十七 · Problem 80-84)
  • HDLBits:在线学习 Verilog (十六 · Problem 75 – 79)
  • HDLBits:在线学习 Verilog (十五 · Problem 70 – 74)

关注此系列,请关注专栏FPGA的逻辑

发表评论

邮箱地址不会被公开。 必填项已用*标注