Four-bit binary counter

Solution

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

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

Decade counter

Solution

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

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

Decade counter again

Solution

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

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

Slow decade counter

暂停功能:仅当 slowena 为高电平时,计数器才会在时钟上升沿递增;否则保持当前值。

Solution

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

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

Counter 1-12

同步复位reset 高电平时,时钟上升沿将计数器同步复位到 1

使能控制enable 高电平时,计数器运行(计数);enable 低电平时,计数器保持当前值(暂停)。

**load 的核心作用:

- **立即覆盖当前值**:当 `load=1` 时,无论计数器当前状态如何,都会在下一个时钟上升沿将 `d` 端口的值加载到计数器输出 `Q`。
- **优先级高于 `enable`**:即使 `enable=0`(计数器暂停),只要 `load=1`,计数器仍会加载 `d` 的值。

计数器的四种状态:

loadenable计数器行为
1X加载 d 的值(例如复位到 1 或回绕到 1)
01正常计数(Q = Q + 1)
00保持当前值(暂停)
10仍加载 d 的值(load 优先级更高)

已知:

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

Solution

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);
    assign c_d = c_load ? 4'b1 : 4'b0;
    
    count4 the_counter (
        .clk(clk), 
        .enable(c_enable), 
        .load(c_load), 
        .d(c_d),
        .Q(Q)
    );

endmodule

Counter 1000

题中给出了一个十进制的模块,所以需要使用三次以达到把1000Hz降到1Hz.

已知:

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

Solution

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

    wire [3:0] one, ten, hundred;
    
    // 实例化三个 bcdcount 模块,分别表示个位、十位、百位
    bcdcount counter0 (clk, reset, c_enable[0], one);     // 个位
    bcdcount counter1 (clk, reset, c_enable[1], ten);     // 十位
    bcdcount counter2 (clk, reset, c_enable[2], hundred); // 百位
    
    // 使能信号控制逻辑
    assign c_enable[0] = 1'b1;                            // 个位始终使能(持续计数)
    assign c_enable[1] = (one == 4'd9);                   // 十位仅在个位达到9时使能
    assign c_enable[2] = (ten == 4'd9) && (one == 4'd9);  // 百位仅在个位和十位都为9时使能

    // 生成1Hz脉冲:当且仅当计数器达到999时,OneHertz输出高电平
    assign OneHertz = (hundred == 4'd9) && (ten == 4'd9) && (one == 4'd9);
endmodule

4-digit decimal counter

题目要求:
构建一个 4 位 BCD(二进制编码十进制)计数器

  1. 位分配:每个十进制位用 4 位二进制编码:

    • q[3:0] → 个位(0~9),
    • q[7:4] → 十位(0~9),
    • q[11:8] → 百位(0~9),
    • q[15:12] → 千位(0~9)(共 4 位,构成 0000~9999 的循环)。
  2. 使能信号:对于 十位、百位、千位(即高位的三位),需输出对应的使能信号(如 ena[1] 对应十位、ena[2] 对应百位、ena[3] 对应千位),指示该高位何时应递增(例如:个位计满 9 时,触发十位的使能信号)。
  3. 实现方式:可通过 实例化或修改 1 位十进制计数器(如 “十进制计数器模块”,实现 0~9 循环)来级联构建。
  4. 信号解读:
  5. clk:时钟信号(上升沿触发计数)。
  6. reset:同步复位信号(高电平时,计数器复位到 0)。
  7. q[3:0]:个位的 BCD 值(如波形中依次为 7→8→9→0→1…,实现 0~9 循环)。
  8. ena[1]:十位的使能信号(仅当个位计满 9 时,ena[1] 置高,触发十位递增)。
  9. q[7:4]:十位的 BCD 值(如波形中 5→6→0…,受 ena[1] 控制,计满 9 后回 0)。

Solution

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

    //实例化四个1位十进制计数器,分别表示个位、十位、百位、千位
    count1bit u1 (clk,reset,enas,q[3:0]);
    count1bit u2 (clk,reset,ena[1],q[7:4]);
    count1bit u3 (clk,reset,ena[2],q[11:8]);
    count1bit u4 (clk,reset,ena[3],q[15:12]);
    
    //其中:
    wire enas;
    assign enas = 1'b1;  //个位始终使能

    // 生成十位的使能信号:当个位达到9时,ena[1]置高,触发十位计数
    assign ena[1] = (q[3:0] == 4'b1001) ? 1'b1 : 1'b0;
    // 生成百位的使能信号:当十位和个位都达到9时,ena[2]置高,触发百位计数
    assign ena[2] = ((q[7:4] == 4'b1001) && (q[3:0] == 4'b1001)) ? 1'b1 : 1'b0;
    assign ena[3] = ((q[11:8] == 4'b1001) && (q[7:4] == 4'b1001) && (q[3:0] == 4'b1001)) ? 1'b1 : 1'b0;
    
endmodule

//自主构建 1位十进制计数器
module count1bit (
    input clk,
    input reset,
    input ena,       // 使能信号:若高电平,则允许该计数器计数
    output [3:0] q   //4为BCD输出
);

    always @(posedge clk) begin
        if(reset)
           q <= 4'b0000;
        else if(ena) begin
            if(q == 4'b1001)
            q <= 4'b0000;
            else
                q <= q + 1;
        end
        else
            q <= q;  //使能无效时,保持当前值
    end
                    
endmodule

12-hour clock

Solution

module top_module(
    input clk,
    input reset,
    input ena,
    output pm,
    output [7:0] hh,
    output [7:0] mm,
    output [7:0] ss); 
    
    //------------------- 秒计数器(00-59) ---------------------
    always @(posedge clk) begin 
        if (reset) 
            ss <= 8'd0;
        else if (ena) begin 
            if (ss[3:0] == 4'd9) begin //低位到9 
                ss[3:0] <= 4'd0;       //清零低位
                if (ss[7:4] == 4'd5)   //低位到9并且高位到5 
                    ss[7:4] <= 4'd0;   //清零高位
                else  
                    ss[7:4] <= ss[7:4] + 4'd1; 
            end 
            else 
                ss[3:0] <= ss[3:0] + 4'd1; 
        end
    end
    
      //------------------- 分计数器(00-59) ---------------------
    always @(posedge clk) begin 
        if (reset) 
            mm <= 8'd0;
        else if (ena && ss[7:4] == 4'd5 && ss[3:0] == 4'd9) begin //ena有效并且秒数为59时触发使能
            if (mm[3:0] == 4'd9)begin  //低位到9 
                mm[3:0] <= 4'd0;       //清零低位
                if (mm[7:4] == 4'd5)   //低位到9并且高位到5 
                    mm[7:4] <= 4'd0;   //清零高位
                else  
                    mm[7:4] <= mm[7:4] + 4'd1; 
            end 
            else
                mm[3:0] <= mm[3:0] + 4'd1;
        end
    end 
    
      //------------------- 时计数器(01-12) ---------------------
    always @(posedge clk) begin 
        if (reset) begin
            hh[7:4] <= 4'd1;    //若直接写hh <= 8'd12; 是错误的,因为这是BCD码。
            hh[3:0] <= 4'd2;
            pm <= 1'd0;   
        end
        else if (ena &&
            mm[7:4] == 4'd5 && mm[3:0] == 4'd9 &&
            ss[7:4] == 4'd5 && ss[3:0] == 4'd9) begin //ena有效,并且秒数和分钟都为59时,触发使能
            
            //低位到9并且高位为0 (09:59:59->10:00:00)
            if (hh[3:0] == 4'd9 && hh[7:4] == 4'd0) begin 
                hh[3:0] <= 4'd0;
                hh[7:4] <= 4'd1; 
            end
            
            //低位到2并且高位到1 (12:59:59->01:00:00) ,回绕回01
            else if (hh[3:0] == 4'd2 && hh[7:4] == 4'd1) begin 
                hh[7:4] <= 4'd0;
                hh[3:0] <= 4'd1;
            end
                
            //低位到1并且高位到1 (11:59:59->12:00:00) ,pm需要转换 
            else if (hh[3:0] == 4'd1 && hh[7:4] == 4'd1) begin 
                hh[7:4] <= 4'd1;
                hh[3:0] <= 4'd2;
                pm <= ~pm;
            end

            else
                hh[3:0] <= hh[3:0] + 4'd1;    
        end  
    end     

endmodule

一些小问题:
「在 Verilog 中,always块中赋值的信号必须声明为reg。你的代码中,pmhhmmss均在always块中被赋值,但声明时使用了默认的wire型(output pmoutput [7:0] hh等),这会导致编译错误(“非法在 always 块中赋值 wire 型信号”)。」但是,在本问题中,直接赋值依然可以Success,这是因为本网站对语法检查不够严格.