HDLBits(16)4.19

3 电路

3.2 时序逻辑

3.2.2 计数器

  •  Count1to10(Decade counter again)

与上题一样,区别是复位为1

module top_module(
    input clk,
    input reset,
    output [3:0] q);
    
    always @(posedge clk)
        begin
            if(reset)
                q <= 4'b0001;    //复位为1
            else if(q <= 4'b1001)
                q <= q + 1'b1;
            else
                q <= 4'b0001;
        end
endmodule
  •  Coutslow(Slow decade couter)

一个0-9,同步复位且复位为0的计数器,但计数器不随clk变化而递增,而是由slowena使能信号控制

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 == 1'b1)
                begin
                    if(q == 4'd9)
                        q <= 4'b0;
                    else 
                        q <= q + 4'd1;
                end
        end

endmodule
  •  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. 再用一些其他的逻辑门来完成本题
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);
endmodule
  •  Counter1000

OneHertz: 从1000Hz中分离出1Hz的信号;这个信号主要用作于数字时钟中。

利用一个模10的BCD计数器和尽量少的逻辑门建立一个时钟分频器。同时输出每个BCD计算器的使能信号(c_enable[0]为高位,c_enable[2]为低位)

module bcdcount (
    input clk,
    input reset,
    output OneHertz,
    output [2:0] c_enable
);
    wire [3:0] q0,q1,q2;  //1000 -> 100(q2) -> 10(q1) -> 1(q0)
    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
  • Countbcd(4-digit decimal counter)

设计一个4位BCD计数器。每个十进制数字使用4-bit来表示:q[3:0]是个位,q[4:7]是十位等,ena[3:1]表示个位、十位、百位的进位

module top_module (
    input clk,
    input reset,
    output [3:1] ena,
    outout [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
//不用子模块的方法,但此方法用到求余(%),实际FPGA中应避免使用除法和求余,因为需要使用很多资源
module top_module (
    input clk,
    input reset, // Synchronous active-high reset
    output [3:1] ena,
    output [15:0] q
);

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
};

always @(posedge clk)
    if(reset)
        q <= 16'b0;
    else
        begin
                q[3:0] <= (q[3:0] + 1) % 10;
            if(ena[1])
                q[7:4] <= (q[7:4] + 1) % 10;
            if(ena[2])
                q[11:8] <= (q[11:8] + 1) % 10;
            if(ena[3])
                q[15:12] <= (q[15:12] + 1) % 10;
        end

endmodule
  •  Count clock

用计数器设计一个带AM/PM的12小时时钟。该计数器通过一个CLK进行计时,用ena使能信号来驱动时钟的递增。

reset信号将时钟复位为12:00 AM。 信号pm为0代表AM,为1代表PM。hh、mm和ss由数两个BCD计器构成hours(01~12), minutes(00~59) , second(00~59)。Reset信号比enable信号有更高的优先级,即使没有enable信号也可以进行复位操作。

Hint:需要注意的是从11:59:59 PM 到12:00:00 AM和从12:59:59 PM到01:00:00 PM的变化。

module top_module 
    (
        input clk,
        input reset,
        input ena,
        output pm,
        output [7:0] hh,
        output [7:0] mm,
        output [7:0] ss
    );

reg p;  //0 is am, 1 is pm
reg [7:0] h;
reg [7:0] m;
reg [7:0] s;

always @ (posedge clk)
    begin
        if(reset)   //reset to 12:00:00 AM
            begin
                p <= 0;
                h <= 8'h12;    //为什么采用16进制?
                m <= 8'h00;
                s <= 8'h00;
            end
        else
            begin
                if(ena)
                    begin
                        if(s < 8'h59)
                            begin
                                if(s[3:0] < 4'h9)   //s[3:0] is ones digit
                                    begin
                                        s[3:0] <= s[3:0] + 1'h1; 
                                    end
                                else
                                    begin
                                        s[3:0] <= 0;    //59->00
                                        s[7:4] <= s[7:4] + 1'h1; //tens digit 
                                    end 
                            end
                        else
                            begin
                                s <= 0; //s清零
                                if(m < 8'h59)   //m同理s
                                    begin
                                        if(m[3:0] < 4'h9)
                                            begin
                                                m[3:0] <= m[3:0] + 1'h1; 
                                            end 
                                        else
                                            begin
                                                m[3:0] <= 0;
                                                m[7:4] <= m[7:4] + 1'h1;
                                            end
                                    end
                                else
                                    begin
                                        m <= 1'h0;
                                        if(h == 8'h11)  //AM / PM 转换
                                            p = !p;
                                        if(h < 8'h12)
                                            begin
                                                if(h[3:0] < 4'h9)
                                                    h[3:0] <= h[3:0] + 1'h1;
                                                else
                                                    begin
                                                        h[3:0] <= 4'h0;
                                                        h[7:4] <= h[7:4] + 1'h1;
                                                    end
                                            end
                                        else
                                            begin //hour 12 -> 1
                                                h <= 1'h1; 
                                            end
                                    end
                            end
                    end
            end
    end

assign pm = p;
assign hh = h;
assign mm = m;
assign ss = s;

endmodule

3.2.3 移位寄存器

  • Shift4(4-bit shift register)

设计一个4bit异步复位,拥有同步置位和使能的右移移位寄存器

areset : 寄存器复位为0

load : 将data[3:0]输入至移位寄存器中

ena : 使能信号控制向右移动(q[3]q[2]q[1]q[0] ---> 0q[3]q[2]q[1],q[0]在移动后消失了,原先q[3]的位置变为0)

q : 移位寄存器中的数据

如果ena和load同时为高,load有更高的优先级。

module top_module(
    input clk,
    input areset,
    input load,
    input ena,
    input [3:0] data,
    output reg [3:0] q
);
    always @ (posedge clk or posedge areset)
        begin
            if(areset)
                q <= 4'b0;
            else if (load)
                q <= data;
            else if (ena)
                begin
                    q[3:0] <= {1'b0,q[3:1]};
                end
        end
endmodule

 

posted @ 2023-04-18 20:59  LhTian21  阅读(35)  评论(0)    收藏  举报