HDLBits第十一章练习及答案

时序逻辑2:计数器

1、四位二进制计数器

构建一个从0到15的4位二进制计数器,周期为16。同步复位,复位应该将计数器重置为0。
HDLBits第十一章练习及答案
代码实现:

module top_module (
    input clk,
    input reset,      // Synchronous active-high reset
    output [3:0] q);
	
    always@(posedge clk) begin
        if(!reset)
        	q <= q + 1'b1;
        else
            q <= 4'b0;
    end
        
endmodule

验证结果:
HDLBits第十一章练习及答案

2、十进制计数器1

构建一个从0到9(包括9)的十进制计数器,其周期为10。同步复位,复位应该将计数器重置为0。
HDLBits第十一章练习及答案
代码实现:

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

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

验证结果:
HDLBits第十一章练习及答案

3、十进制计数器2

制作一个从1到10的10进制计数器。同步复位,复位应该将计数器复位为1。
HDLBits第十一章练习及答案
代码实现:

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

    always@(posedge clk) begin
        if(reset)
           q <= 4'd1; 
        else begin
            if(q < 10)
                q <= q + 1'b1;
            else
                q <= 4'd1;
        end  
    end
    
endmodule

验证结果:
HDLBits第十一章练习及答案

4、延迟十进制计数器

构建一个从0到9(包括9)的十进制计数器,其周期为10。同步复位,复位应该将计数器重置为0。我们希望能够暂停计数器,而不是总是在每个时钟周期中递增,因此slowena输入指示计数器应该何时递增。
HDLBits第十一章练习及答案
代码实现:

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

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

验证结果:
HDLBits第十一章练习及答案
HDLBits第十一章练习及答案

5、1-12的计数器

设计一个具有以下输入和输出的 1-12 计数器:
Reset :同步高电平有效复位,强制计数器为 1
Enable: 计数器运行设置为高电平
Clk: 上升沿触发时钟输入
Q[3:0] :计数器的输出
c_enable, c_load, c_d[3:0]:控制信号到提供的4位计数器,这样就可以验证操作是否正确。

您可以使用以下组件:

(1)下面的4位二进制计数器(coun4),它具有使能和同步并行负载输入(负载优先级高于使能)。count4模块提供给您。在你的电路中实例化它。
(2)逻辑门

module count4(
	input clk,
	input enable,
	input load,
	input [3:0] d,
	output reg [3:0] Q
);

c_enable、c_load和c_d输出分别是到内部计数器的enable、load和d输入的信号。它们的目的是为了检查这些信号的正确性。

代码实现:

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

    assign c_enable = enable;
    assign c_load = reset | ((Q == 4'd12) && (enable == 1'b1));
    assign c_d = c_load ? 4'b1 : 4'b0;
    
    count4 counter(clk,c_enable,c_load,c_d,Q);
    
endmodule

验证结果:
HDLBits第十一章练习及答案

6、 1kHz→1Hz 计数器

从 1000 Hz 时钟导出一个 1 Hz 信号,称为OneHertz,可以用来驱动一组小时/分钟/秒计数器的启用信号,以创建一个数字挂钟。因为我们想让时钟每秒计数一次,所以 1 Hz 信号必须精确地保持每秒一个周期。建立分频器使用模10 (BCD)计数器和尽可能少的其他门。还从您使用的每个 BCD 计数器输出启用信号(c_enable[0] 表示最快的计数器,c_enable[2] 表示最慢的计数器)。
为您提供了以下 BCD 计数器。Enable必须为高电平才能运行计数器。复位是同步的并设置为高电平以强制计数器归零。电路中的所有计数器必须直接使用相同的 1000 Hz 信号。

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

代码实现:

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

    wire [3:0] one,ten,hundred;
    assign c_enable = {one ==4'd9 && ten == 4'd9, one ==4'd9 ,1'd1};
    assign OneHertz = {one ==4'd9 && ten == 4'd9 && hundred ==4'd9};
        
    bcdcount counter0 (clk, reset, c_enable[0],one);
    bcdcount counter1 (clk, reset, c_enable[1],ten);
    bcdcount counter2 (clk, reset, c_enable[2],hundred);

endmodule

验证结果:
HDLBits第十一章练习及答案
HDLBits第十一章练习及答案
HDLBits第十一章练习及答案

7、 四位十进制计数器

构建一个4位BCD(二进制编码的十进制)计数器。每个十进制数字使用4位进行编码:q[3:0]是个位,q[7:4]是十位,以此类推。各进制上的进位时也需输出一个使能信号,指示三位数字何时应该增加。
HDLBits第十一章练习及答案
代码实现:

module top_module (
    input clk,
    input reset,   // Synchronous active-high reset
    output [3:1] ena,
    output [15:0] q);
    
    reg [3:0] ones,tens,hundreds,thousands;
    
    always @(posedge clk) begin
        if(reset)
            ones <= 4'b0;
        else if(ones == 4'd9)
            ones <=4'b0;
        else
            ones <= ones + 4'd1;
    end
    
    always @(posedge clk)begin
        if(reset)
            tens <= 4'b0;
        else if(tens == 4'd9 && ones == 4'd9)
            tens <= 4'b0;
        else if(ones == 4'd9)
            tens <= tens + 4'd1;
    end
    
    always @(posedge clk)begin
        if(reset)
            hundreds <= 4'b0;
        else if(hundreds == 4'd9 && tens == 4'd9 && ones == 4'd9)
            hundreds <= 4'b0;
        else if(tens == 4'd9 && ones == 4'd9) 
            hundreds <= hundreds + 4'd1;
    end
    
    always @(posedge clk)begin
        if(reset)
            thousands <= 4'b0;
        else if(thousands == 4'd9 && hundreds == 4'd9 && tens == 4'd9 && ones == 4'd9)
            thousands <= 4'b0;
        else if(hundreds == 4'd9 && tens == 4'd9 && ones == 4'd9)
            thousands <= thousands + 4'd1;
    end
    
    assign q = {thousands,hundreds,tens,ones};
    assign ena[1] = (ones == 4'd9) ? 1'b1 : 1'b0;
    assign ena[2] = ((ones == 4'd9) && (tens == 4'd9)) ? 1'b1 : 1'b0;
    assign ena[3] = ((ones == 4'd9) && (tens == 4'd9) && (hundreds == 4'd9)) ? 1'b1 : 1'b0;
    
endmodule

验证结果:
HDLBits第十一章练习及答案
HDLBits第十一章练习及答案

8、 12小时的时钟

创建一组适合作为12小时的时钟使用的计数器(带有am/pm指示器)。你的计数器是由一个快速运行的clk驱动,每次时钟增加时ena必须为1。reset将时钟重置到中午12点。上午时pm=0,下午时pm=0。hh,mm和ss分别是小时(01-12)、分钟(00-59)和秒(00-59)的两个BCD(二进制编码的十进制)数字。

Reset比enable具有更高的优先级,并且即使在没有启用时也会发生。

下面的时序图显示了从11:59:59 AM到12:00:00 PM的翻转行为以及同步的Reset和enable行为。
HDLBits第十一章练习及答案
代码实现:

module top_module(
    input clk,
    input reset,
    input ena,
    output pm,
    output [7:0] hh,
    output [7:0] mm,
    output [7:0] ss); 
    
    reg pm_temp;
    reg [3:0] ss_ones,ss_tens,mm_ones,mm_tens,hh_ones,hh_tens;
    
    wire	add_ss_ones,end_ss_ones,add_ss_tens,end_ss_tens;
    wire	add_mm_ones,end_mm_ones,add_mm_tens,end_mm_tens;
    wire	add_hh_ones,end_hh_ones_0,end_hh_ones_1,add_hh_tens,end_hh_tens_0,end_hh_tens_1;
    wire	pm_ding;
    
    assign add_ss_ones = ena;
    assign end_ss_ones = add_ss_ones && (ss_ones == 4'd9);
    always @(posedge clk)begin
        if(reset)begin
            ss_ones <= 4'b0;
        end
        else if(add_ss_ones)begin
            if(end_ss_ones)
                ss_ones <= 4'b0;
            else 
                ss_ones <= ss_ones + 4'b1;
        end
    end
    
    assign add_ss_tens = end_ss_ones;
    assign end_ss_tens = add_ss_tens && (ss_tens == 4'd5);
    always @(posedge clk)begin
        if(reset)
            ss_tens <= 4'b0;
        else if(add_ss_tens)begin
            if(end_ss_tens)
                ss_tens <= 4'b0;
            else 
                ss_tens <= ss_tens + 4'b1;
        end
    end
    
    assign add_mm_ones = end_ss_tens;
    assign end_mm_ones = add_mm_ones && (mm_ones == 4'd9);
    always @(posedge clk)begin
        if(reset)
            mm_ones <= 4'b0;
        else if(add_mm_ones)begin
            if(end_mm_ones)
                mm_ones <= 4'b0;
            else
                mm_ones <= mm_ones + 4'b1;
        end
    end
    
    assign add_mm_tens = end_mm_ones;
    assign end_mm_tens = add_mm_tens && (mm_tens == 4'd5);
	always @(posedge clk)begin
        if(reset)
            mm_tens <= 4'b0;
        else if(add_mm_tens)begin
            if(end_mm_tens)
                mm_tens <= 4'b0;
            else 
                mm_tens <= mm_tens + 4'b1;
        end
    end
    
    assign add_hh_ones = end_mm_tens;
    assign end_hh_ones_0 = add_hh_ones && (hh_ones == 4'd9);
    assign end_hh_ones_1 = add_hh_ones && ((hh_ones == 4'd2) && (hh_tens == 4'd1));
    always @(posedge clk)begin
        if(reset)
            hh_ones <= 4'd2;
        else if(add_hh_ones)begin
            if(end_hh_ones_0)
                hh_ones <= 4'b0;
            else if(end_hh_ones_1)
                hh_ones <= 4'b1;
            else 
                hh_ones <= hh_ones + 4'b1;
        end
    end

    assign add_hh_tens = end_mm_tens;
    assign end_hh_tens_0 = add_hh_tens && end_hh_ones_1;
    assign end_hh_tens_1 = add_hh_tens && end_hh_ones_0;
    always @(posedge clk)begin
        if(reset)
            hh_tens <= 4'b1;
        else if(add_hh_tens)begin
            if(end_hh_tens_0)
                hh_tens <= 4'b0;
            else if(end_hh_tens_1)
                hh_tens <= hh_tens + 4'b1;
        end
    end
    
    always@(posedge clk)begin
        if(reset)
            pm_temp <= 1'b0;
        else if(pm_ding)
            pm_temp <= ~pm_temp;
    end
    
    assign pm_ding = hh_tens == 4'd1 && hh_ones == 4'd1 && end_mm_tens;
    
    assign ss = {ss_tens, ss_ones};
    assign mm = {mm_tens, mm_ones};
    assign hh = {hh_tens, hh_ones};
    assign pm = pm_temp;
    
endmodule

验证结果:
HDLBits第十一章练习及答案
HDLBits第十一章练习及答案
HDLBits第十一章练习及答案
HDLBits第十一章练习及答案
参考资料: Verilog计数器.

上一篇:LAMP 源码编译安装及论坛搭建实验


下一篇:centos7源码安装php-7.0.3