【HDLBits习题 2】Circuit - Sequential Logic(2)Counters

1. Count15(Four-bit binary counter)

        由于输出q为4-bit,当执行到15+1时,会自动回到0,故不需要设计清零步骤。

module top_module (
    input        clk, reset, 
    output [3:0] q
);
    always @(posedge clk) begin
        if (reset) begin
            q <= 0;
        end
        else begin
            q <= q + 1'b1;
        end
    end
endmodule

2. Count10(Decade counter)

        由于我们要用十六进制计数器设计十进制计数器,故要设计清零步骤。这里采用清零法,当技术到9时,在下一个时钟信号上升沿对q进行清零。

module top_module (
    input        clk, reset, 
    output [3:0] q
);
    always @(posedge clk) begin
        if (reset || q==4'h9) begin
            q <= 0;
        end
        else begin
            q <= q + 1'b1;
        end
    end
endmodule

3. Count1to10(Decade counter again)

        虽同为十进制计数器,但与上一个不同,前者为0-9计数,后者为1-10计数。故这里使用置数法设计清零步骤,当计数到10时,在下一个时钟信号上升沿将q置数为1。

module top_module (
    input        clk, reset,
    output [3:0] q
);
    always @(posedge clk) begin
        if (reset || q==4'ha) begin
            q <= 4'h1;
        end
        else begin
            q <= q + 1'b1;
        end
    end
endmodule

4. Countslow(Slow decade counter)

        该题的清零步骤(不考虑reset清零)又与第二题的设计有所不同,此题的清零需要在slowena处于高电平时才能执行,否则q的值保持不变。

module top_module (
    input        clk, slowena, reset,
    output [3:0] q
);
    always @(posedge clk) begin
        if (reset) begin
            q <= 0;
        end
        else if (slowena && q<4'h9) begin
            q <= q + 1'b1;
        end
        else if (slowena && q==4'h9) begin
            q <= 0;
        end
    end
endmodule

5. Exams/ece241 2014 q7a(Counter 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
);

    count4 the_counter ( clk, c_enable, c_load, c_d, Q );

    assign c_enable = enable;
    assign c_load   = reset || ((Q==4'd12) && (enable==1'b1));
    assign c_d		= c_load ? 4'd1 : 4'd0;
endmodule

6. Exams/ece241 2014 q7b(Counter 1000)

  方法1:

module top_module (
    input        clk, 
    input        reset, 
    output       OneHertz, 
    output [2:0] c_enable
);
    wire [3:0] a, b, c;
    
    assign c_enable	= { (a==4'd9)&&(b==4'd9), (a==4'd9), 1'b1 };
    assign OneHertz = (a[0]&&b[0]&&c[0]) && (a[3]&&b[3]&&c[3]);
    
    bcdcount counter0 ( clk, reset, c_enable[0], a );
    bcdcount counter1 ( clk, reset, c_enable[1], b );
    bcdcount counter2 ( clk, reset, c_enable[2], c );
endmodule

  方法2:

module top_module (
    input        clk, 
    input        reset, 
    output       OneHertz, 
    output [2:0] c_enable
);
    wire [3:0] a, b, c;
    
    assign c_enable	= { (a==4'd9)&&(b==4'd9), (a==4'd9), 1'b1 };
    assign OneHertz = (a==4'd9) && (b==4'd9) && (c==4'd9);
    
    bcdcount counter0 ( clk, reset, c_enable[0], a );
    bcdcount counter1 ( clk, reset, c_enable[1], b );
    bcdcount counter2 ( clk, reset, c_enable[2], c );
endmodule

7. Countbcd(4-digit decimal counter)

module top_module (
    input         clk,
    input         reset, 
    output [3:1]  ena,
    output [15:0] q
);
    countbcd M1 ( .q(q[3:0]),   .clk(clk), .reset(reset), .enable(1'b1) );
    countbcd M2 ( .q(q[7:4]),   .clk(clk), .reset(reset), .enable(ena[1]) );
    countbcd M3 ( .q(q[11:8]),  .clk(clk), .reset(reset), .enable(ena[2]) );
    countbcd M4 ( .q(q[15:12]), .clk(clk), .reset(reset), .enable(ena[3]) );
    
    assign ena = { ((q[3:0]==4'd9) && (q[7:4]==4'd9) && (q[11:8]==4'd9)), 
                   ((q[3:0]==4'd9) && (q[7:4]==4'd9)), 
                    (q[3:0]==4'd9)};
endmodule

module countbcd (
    output reg [3:0] q,
    input            clk, 
    input            reset, 
    input            enable
);
    always @(posedge clk) begin
        if (reset) begin
            q <= 0;
        end
        else if (enable && q==4'd9) begin
            q <= 0;
        end
        else if (enable && q<4'd9) begin
            q <= q + 1'b1;
        end
    end
endmodule

8. Count clock(12-hour clock)

这里有个比较迷惑的点就是PM位的循环,它与时钟的循环是错开了一个周期的。

时钟的循环范围是(1-12),而PM的循环范围是(0-11),相当于

1 AM  ➡️  11 AM  ➡️  12 PM  ➡️  1PM  ➡️  11PM   ➡️  12AM   ➡️  1AM   ➡️  ...

所以实际上PM的循环范围是(0(12)-11)【钟表上0与12是重合的】。

  方法1:

module top_module(
    output pm,
    output [7:0] hh,
    output [7:0] mm,
    output [7:0] ss, 
    input  clk,
    input  reset,
    input  ena
);
    wire sso_ena, sst_ena;	// sso使能信号,sst使能信号
    wire mmo_ena, mmt_ena;	// mmo使能信号,mmt使能信号
    wire hho_ena;			// hho使能信号
    wire hht_ena;			// hht使能信号
    wire h_cycle;			// hht、hho置数信号
    wire pm_ena;			// pm翻转信号
    
    wire [3:0] sso, sst;	// 秒钟个位、秒钟十位
    wire [3:0] mmo, mmt;	// 分钟个位、分钟十位
    wire [7:0] hto;			// 时钟

    assign hh = hto;			// 时钟输出赋值
    assign mm = {mmt, mmo};		// 分钟输出赋值
    assign ss = {sst, sso};		// 秒钟输出赋值

    PM		  M1 ( .P(pm),  .CLK(clk), .RST(reset), .ENP(pm_ena) );
    Count_h   M2 ( .Q(hto), .CLK(clk), .RST(reset), .ENT(hht_ena), .ENO(hho_ena), .ENC(h_cycle) );
    Count_ten M3 ( .Q(mmt), .CLK(clk), .RST(reset), .EN(mmt_ena) );
    Count_one M4 ( .Q(mmo), .CLK(clk), .RST(reset), .EN(mmo_ena) );
    Count_ten M5 ( .Q(sst), .CLK(clk), .RST(reset), .EN(sst_ena) );
    Count_one M6 ( .Q(sso), .CLK(clk), .RST(reset), .EN(sso_ena) );
    
    // 各例化模块的使能信号
    assign pm_ena  = hho_ena && (hto[7:4]==4'd1) && (hto[3:0]==4'd1);
    assign h_cycle = hho_ena && (hto[7:4]==4'd1) && (hto[3:0]==4'd2);
    assign hht_ena = hho_ena && (hto[3:0]==4'd9);
    assign hho_ena = mmt_ena && (mmt==4'd5);
    assign mmt_ena = mmo_ena && (mmo==4'd9);
    assign mmo_ena = sst_ena && (sst==4'd5);
    assign sst_ena = sso_ena && (sso==4'd9);
    assign sso_ena = ena;
endmodule


// PM位模块
module PM (
	output P, 
    inout  CLK, RST, 
    input  ENP
);
    always @(posedge CLK) begin
        if (RST) begin
            P <= 1'b0;
        end
        else if (ENP) begin
            P <= ~P;
        end
    end
endmodule


// 时钟模块
module Count_h (
    output reg [7:0] Q,
    input			 CLK, RST, 
    input			 ENT, ENO, ENC
);
    always @(posedge CLK) begin
        if (RST) begin
            Q[7:4] <= 4'd1;
        end
        else if (ENC) begin
            Q[7:4] <= 4'd0;
        end
        else if (ENT) begin
            Q[7:4] <= Q[7:4] + 1'b1;
        end
    end
    
    always @(posedge CLK) begin
        if (RST) begin
            Q[3:0] <= 4'd2;
        end
        else if (ENC) begin
            Q[3:0] <= 4'd1;
        end
        else if (ENO && Q==4'd9) begin
            Q[3:0] <= 4'd0;
        end
        else if (ENO) begin
            Q[3:0] <= Q[3:0] + 1'b1;
        end
    end
endmodule


// 十位片模块
module Count_ten (
    output reg [3:0] Q,
    input			 CLK, RST, 
    input 			 EN
);
    always @(posedge CLK) begin
        if (RST) begin
            Q <= 4'd0;
        end
        else if (EN) begin
            if (Q==4'd5) begin
                Q <= 4'd0;
            end
            else begin
                Q <= Q + 1'b1;
            end
        end
    end
endmodule


// 个位片模块
module Count_one (
    output reg [3:0] Q,
    input			 CLK, RST, 
    input 			 EN
);
    always @(posedge CLK) begin
        if (RST) begin
            Q <= 4'd0;
        end
        else if (EN) begin
            if (Q==4'd9) begin
                Q <= 4'd0;
            end
            else begin
                Q <= Q + 1'b1;
            end
        end
    end
endmodule

  方法2:

module top_module (
    output reg pm,
    output reg [7:0] hh,
    output reg [7:0] mm,
    output reg [7:0] ss, 
    input clk,
    input reset,
    input ena
);
    wire sso_sta, sso_end;					// sso使能信号、sso清零信号
    wire sst_sta, sst_end;					// sst使能信号、sst清零信号
    wire mmo_sta, mmo_end;					// mmo使能信号、mmo清零信号
    wire mmt_sta, mmt_end;					// mmt使能信号、mmt清零信号
    wire hho_sta, hho_end_0, hho_end_1;		// hho使能信号、hho清零信号、hho置1信号
    wire hht_sta, hht_end;					// hht使能信号、hht清零信号
    wire pm_ena;							// pm翻转信号
    
    // PM位 		start
    always @(posedge clk) begin
        if (reset) begin
            pm <= 0;
        end
        else if (pm_ena) begin
            pm <= ~pm;				// pm信号翻转
        end
    end
    
    // 当hh[7:4]==8'd11, mm[7:4]==8'd59, ss[7:4]==8'd59(即11:59:59)时,pm翻转信号为1。
    assign pm_ena = hho_sta && (hh[7:4]==4'd1) && (hh[3:0]==4'd1);
    // 			end
    
    // 时钟十位hht start
    always @(posedge clk) begin
        if (reset) begin
            hh[7:4] <= 1;
        end
        else if (hht_end) begin
            hh[7:4] <= 0;
        end
        else if (hht_sta) begin
            hh[7:4] <= hh[7:4] + 1;
        end
    end
    
    assign hht_sta = hho_end_0;
    assign hht_end = hho_end_1;
    // 			end
    
    
    // 时钟个位hho start
    always @(posedge clk) begin
        if (reset) begin
            hh[3:0] <= 2;
        end
        else if (hho_end_0) begin
            hh[3:0] <= 0;
        end
        else if (hho_end_1) begin
            hh[3:0] <= 1;
        end
        else if (hho_sta) begin
            hh[3:0] <= hh[3:0] + 1;
        end
    end
    
    assign hho_sta = mmt_end;
    assign hho_end_0 = hho_sta && (hh[3:0]==4'd9);
    assign hho_end_1 = hho_sta && (hh[7:4]==4'd1) && (hh[3:0]==4'd2);
    // 			end
    
    
    // 分钟十位mmt start
    always @(posedge clk) begin
        if (reset) begin
            mm[7:4] <= 0;
        end
        else if (mmt_end) begin
            mm[7:4] <= 0;
        end
        else if (mmt_sta) begin
            mm[7:4] <= mm[7:4] + 1;
        end
    end
    
    assign mmt_sta = mmo_end;
    assign mmt_end = mmt_sta && mm[7:4]==4'd5;
    // 			end

    
    // 分钟个位mmo start
    always @(posedge clk) begin
        if (reset) begin
            mm[3:0] <= 0;
        end
        else if (mmo_end) begin
            mm[3:0] <= 0;
        end
        else if (mmo_sta) begin
            mm[3:0] <= mm[3:0] + 1;
        end
    end
    
    assign mmo_sta = sst_end;
    assign mmo_end = mmo_sta && mm[3:0]==4'd9;
    // 			end
    
    
    // 秒钟十位sst start
    always @(posedge clk) begin
        if (reset) begin
            ss[7:4] <= 0;
        end
        else if (sst_end) begin
            ss[7:4] <= 0;
        end
        else if (sst_sta) begin
            ss[7:4] <= ss[7:4] + 1;
        end
    end
    
    assign sst_sta = sso_end;
    assign sst_end = sst_sta && ss[7:4]==4'd5;
    // 			end

    
    // 秒钟个位sso start
    always @(posedge clk) begin
        if (reset) begin
            ss[3:0] <= 0;
        end
        else if (sso_end) begin
            ss[3:0] <= 0;
        end
        else if (sso_sta) begin
            ss[3:0] <= ss[3:0] + 1;
        end
    end
    
    assign sso_sta = ena;
    assign sso_end = sso_sta && (ss[3:0]==4'd9);
    // 			end
endmodule
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值