【HDLBits 刷题 7】Circuits(3)Sequential Logic---Counters

发布时间:2026/5/20 4:24:41

【HDLBits 刷题 7】Circuits(3)Sequential Logic---Counters 目录写在前面CountersCount15Count10CountslowCounter1-12Counter1000CountbcdCount clock总结写在前面本篇博客对 Circuits 部分的组合逻辑前两节做答案和部分解析一些比较简单的题目就直接给出答案有些难度再稍作讲解每道题的答案不一定唯一可以有多种解决方案欢迎共同讨论。CountersCount15生成一个4位二进制计数器其计数范围为0到15包括0和15周期为16。复位输入是同步的应将计数器复位为0。module top_module ( input clk, input reset, output [3:0] q ); always (posedge clk) begin if (reset) begin q d0; end else begin q q d1; end end endmoduleCount10构建一个计数从 0 到 9包括 0 和 9的计数器周期为 10。复位输入是同步的应将计数器复位为0。module top_module ( input clk, input reset, output [3:0] q ); always (posedge clk) begin if (reset) begin q d0; end else if (q d9) begin q d0; end else begin q q d1; end end endmoduleCount1to10制作一个计数为 1 到 10包括 1的计数器。复位输入是同步的应将计数器复位为1。module top_module ( input clk, input reset, output [3:0] q ); always (posedge clk) begin if (reset) begin q d1; end else if (q d10) begin q d1; end else begin q q d1; end end endmoduleCountslow构建一个计数从 0 到 9包括 0 和 9的计数器周期为 10。复位输入是同步的应将计数器复位为0。我们希望能够暂停计数器而不是总是在每个时钟周期递增因此 slowena 输入指示计数器何时应该递增。module top_module ( input clk, input slowena, input reset, output [3:0] q ); always (posedge clk) begin if (reset) begin q d0; end else if (q d9 slowena) begin q d0; end else if (q d9 slowena) begin q q d1; end end endmoduleCounter1-12设计具有以下输入和输出的 1-12 计数器重置同步高电平有效复位强制计数器达到1.使设置高使计数器运行.时钟正边沿触发时钟输入.问[30]计数器的输出.c_enable、c_load c_d[30]控制信号进入提供的4位计数器因此可以验证正确的操作。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 4d12) (enable 1b1)); assign c_d c_load ? 4d1 : 4d0; count4 the_counter (clk, c_enable, c_load, c_d , Q); endmoduleCounter1000从 1000 Hz 时钟导出一个 1 Hz 信号称为 OneHertz可用于驱动一组小时/分/秒计数器的 Enable 信号以创建数字挂钟。由于我们希望时钟每秒计数一次因此必须每秒断言一个周期的OneHertz信号。使用模-10 BCD 计数器和尽可能少的其他门构建分频器。同时输出来自您使用的每个BCD计数器的使能信号最快的计数器c_enable[0]最慢的计数器c_enable[2]。为您提供了以下 BCD 计数器。启用必须为高电平才能运行计数器。复位是同步的设置为高电平以强制计数器归零。电路中的所有计数器必须直接使用相同的 1000 Hz 信号。module top_module ( input clk, input reset, output OneHertz, output [2:0] c_enable ); wire [3:0] a,b,c; assign c_enable {bd9 ad9,ad9,1b1}; assign OneHertz ad9 bd9 cd9; bcdcount counter0 (clk, reset, c_enable[0], a); bcdcount counter1 (clk, reset, c_enable[1], b); bcdcount counter2 (clk, reset, c_enable[2], c); endmoduleCountbcd生成 4 位 BCD二进制编码十进制计数器。每个十进制数字使用4位编码q[30]是1位数字q[74]是十位数字依此类推。对于数字 [31]还要输出一个使能信号指示何时应递增上述三位数字中的每一位。module top_module ( input clk, input reset, output [3:1] ena, output [15:0] q ); reg [3:0] one,ten,hundred,thousand; //one always (posedge clk) begin if (reset) begin one d0; end else if (one d9) begin one d0; end else begin one one d1; end end //ten always (posedge clk) begin if (reset) begin ten d0; end else if (ten d9 one d9) begin ten d0; end else if (ena[1]) begin ten ten d1; end else begin ten ten; end end //hundred always (posedge clk) begin if (reset) begin hundred d0; end else if (hundred d9 ten d9 one d9) begin hundred d0; end else if (ena[2]) begin hundred hundred d1; end else begin hundred hundred; end end //thousand always (posedge clk) begin if (reset) begin thousand d0; end else if (thousand d9 hundred d9 ten d9 one d9) begin thousand d0; end else if (ena[3]) begin thousand thousand d1; end else begin thousand thousand; end end //ena[1] ena[2] ena[3] assign ena[1] (oned9); assign ena[2] (tend9 oned9); assign ena[3] (hundredd9 tend9 oned9); //q assign q {thousand, hundred, ten, one}; endmoduleCount clock创建一组适合用作 12 小时制的计数器带有 am/pm 指示器。计数器由快速运行的 clk 计时只要您的时钟递增即每秒一次就会有一个脉冲。重置将时钟重置为 1200 AM。pm 对于 AM为 0对于 PM 为 1。hh、mm 和 ss 是两个 BCD二进制编码十进制数字分别表示小时01-12、分钟 00-59和秒00-59。重置的优先级高于启用即使未启用也可能发生重置。以下时序图显示了从115959 AM到120000 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 pm_temp; //pm值寄存 reg [3:0] ss_ones; //ss个位部分 reg [3:0] ss_tens; //ss十位部分 reg [3:0] mm_ones; //mm个位部分 reg [3:0] mm_tens; //mm十位部分 reg [3:0] hh_ones; //hh个位部分 reg [3:0] hh_tens; //hh十位部分 wire add_ss_ones; //ss个位计数开始信号 wire end_ss_ones; //ss个位计数结束信号 wire add_ss_tens; //ss十位计数开始信号 wire end_ss_tens; //ss十位计数结束信号 wire add_mm_ones; //mm个位计数开始信号 wire end_mm_ones; //mm个位计数结束信号 wire add_mm_tens; //mm十位计数开始信号 wire end_mm_tens; //mm十位计数结束信号 wire add_hh_ones; //hh个位计数开始信号 wire end_hh_ones_0; //hh个位计数结束信号十位为0 wire end_hh_ones_1; //hh个位计数结束信号十位为1 wire add_hh_tens; //hh十位计数开始信号 wire end_hh_tens_0; //hh十位计数置0标志信号 wire end_hh_tens_1; //hh十位计数置1标志信号 wire pm_ding; //pm翻转标志信号 assign add_ss_ones ena; assign end_ss_ones add_ss_ones (ss_ones 4d9); always (posedge clk)begin if(reset)begin ss_ones 4b0; end else if(add_ss_ones)begin if(end_ss_ones)begin ss_ones 4b0; end else begin ss_ones ss_ones 4b1; end end end assign add_ss_tens end_ss_ones; assign end_ss_tens add_ss_tens (ss_tens 4d5); always (posedge clk)begin if(reset)begin ss_tens 4b0; end else if(add_ss_tens)begin if(end_ss_tens)begin ss_tens 4b0; end else begin ss_tens ss_tens 4b1; end end end assign add_mm_ones end_ss_tens; assign end_mm_ones add_mm_ones (mm_ones 4d9); always (posedge clk)begin if(reset)begin mm_ones 4b0; end else if(add_mm_ones)begin if(end_mm_ones)begin mm_ones 4b0; end else begin mm_ones mm_ones 4b1; end end end assign add_mm_tens end_mm_ones; assign end_mm_tens add_mm_tens (mm_tens 4d5); always (posedge clk)begin if(reset)begin mm_tens 4b0; end else if(add_mm_tens)begin if(end_mm_tens)begin mm_tens 4b0; end else begin mm_tens mm_tens 4b1; end end end assign add_hh_ones end_mm_tens; assign end_hh_ones_0 add_hh_ones (hh_ones 4d9); assign end_hh_ones_1 add_hh_ones ((hh_ones 4d2) (hh_tens 4d1)); always (posedge clk)begin if(reset)begin hh_ones 4d2; end else if(add_hh_ones)begin if(end_hh_ones_0)begin hh_ones 4b0; end else if(end_hh_ones_1)begin hh_ones 4b1; end else begin hh_ones hh_ones4b1; end 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)begin hh_tens 4b1; end else if(add_hh_tens)begin if(end_hh_tens_0)begin hh_tens 4b0; end else if(end_hh_tens_1)begin hh_tens hh_tens 4b1; end end end always(posedge clk)begin if(reset)begin pm_temp 1b0; end else if(pm_ding)begin pm_temp ~pm_temp; end end assign pm_ding hh_tens 4d1 hh_ones 4d1 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总结这部分主要学习计数器的使用这个在实际设计中用的非常多尤其是在处理数据的时候计数器设计不难但是需要注意计数值到边缘时的处理是否有延时等情况。

相关新闻