首页 > 行业资讯 > 正文

从今天开始新的一章-时序电路,包括触发器、计数器、移位寄存器、状态机等。

今天更新计数器,这也是FPGA部分非常重要的设计技巧。

Problem 98-Count15

题目说明

构建一个4位二进制计数器,计数范围从0到15(包括0和15),计数周期为16。同步复位输入时,将计数器重置为0。

构建一个4位二进制计数器-用一个4位二进制并行加法器和6个与门设计 图片来自HDLBits

模块端口声明

moduletop_module( inputclk, inputreset,//Synchronousactive-highreset output[3:0]q);

题目解析

这是一个基本计数器。同步复位情况下,复位不放在敏感列表里。

moduletop_module( inputlogicclk, inputlogicreset,//Synchronousactive-highreset outputlogic[3:0]q); always_ff@(posedgeclk)begin if(reset)q<= 0 ;         else if(q == 4d15) q <= 0 ;         else  q <= q + 1 ;     end              endmodule 构建一个4位二进制计数器-用一个4位二进制并行加法器和6个与门设计1

点击Submit,等待一会就能看到下图结果:

构建一个4位二进制计数器-用一个4位二进制并行加法器和6个与门设计2

注意图中的Ref是参考波形,Yours是你的代码生成的波形,网站会对比这两个波形,一旦这两者不匹配,仿真结果会变红。

这一题就结束了。

Problem 99-Count10

题目说明

构建一个十进制计数器,从0到9(包括0和9)计数,计数周期为10。同步复位输入时,将计数器重置为0。

构建一个4位二进制计数器-用一个4位二进制并行加法器和6个与门设计3 图片来自HDLBits

模块端口声明

moduletop_module( inputclk, inputreset,//Synchronousactive-highreset output[3:0]q);

题目解析

和上一题类似。

moduletop_module( inputlogicclk, inputlogicreset,//Synchronousactive-highreset outputlogic[3:0]q); always_ff@(posedgeclk)begin if(reset)q<= 0 ;         else if(q == 4d9)  q <= 0 ;         else                q <= q + 1;     end   endmodule 构建一个4位二进制计数器-用一个4位二进制并行加法器和6个与门设计4

点击Submit,等待一会就能看到下图结果:

构建一个4位二进制计数器-用一个4位二进制并行加法器和6个与门设计5

注意图中的Ref是参考波形,Yours是你的代码生成的波形,网站会对比这两个波形,一旦这两者不匹配,仿真结果会变红。

这一题就结束了。

Problem 100-Count1to10

题目说明

做一个十进制计数器,从1到10(包括1和10)计数,计数周期为10。同步复位输入时,将计数器重置为1。

构建一个4位二进制计数器-用一个4位二进制并行加法器和6个与门设计6 图片来自HDLBits

模块端口声明

moduletop_module( inputclk, inputreset, output[3:0]q);

题目解析

和上一节一样,上一节是从0到9,这题从1到10,计数结束条件和重置条件不一样,其他一样。

moduletop_module( inputlogicclk, inputlogicreset, outputlogic[3:0]q); always_ff@(posedgeclk)begin if(reset)q<= 4d1;         else if(q == 4d10) q <= 4d1;         else                q <= q + 1;     end endmodule 构建一个4位二进制计数器-用一个4位二进制并行加法器和6个与门设计7

点击Submit,等待一会就能看到下图结果:

构建一个4位二进制计数器-用一个4位二进制并行加法器和6个与门设计8

注意图中的Ref是参考波形,Yours是你的代码生成的波形,网站会对比这两个波形,一旦这两者不匹配,仿真结果会变红。

这一题就结束了。

Problem 101-Countslow

题目说明

构建一个十进制计数器,从0到9(包括0和9)计数,计数周期为10。同步复位输入时,将计数器重置为0。但是本题是希望该计数器并不是随着clk的变化而递增,而是随着一个slowena使能信号来控制增加。时序图如下图所示:

构建一个4位二进制计数器-用一个4位二进制并行加法器和6个与门设计9 图片来自HDLBits

模块端口声明

moduletop_module( inputclk, inputslowena, inputreset, output[3:0]q);

题目解析

本题相比于之前的计数器,不同点在于多了一个enable信号来控制计数器的增加(这应该叫使能同步计数器(战术后仰))。

moduletop_module( inputlogicclk, inputlogicslowena, inputlogicreset, outputlogic[3:0]q); always_ff@(posedgeclk)begin if(reset)q<= 0 ;         else if(slowena & q==4d9) q <= 0 ;         else if(slowena & q!=4d9) q <= q + 1 ;         else                       q <= q  ;     end endmodule 构建一个4位二进制计数器-用一个4位二进制并行加法器和6个与门设计10

点击Submit,等待一会就能看到下图结果:

构建一个4位二进制计数器-用一个4位二进制并行加法器和6个与门设计11

注意图中的Ref是参考波形,Yours是你的代码生成的波形,网站会对比这两个波形,一旦这两者不匹配,仿真结果会变红。

这一题就结束了。

Problem 102-ece241_2014_q7a

题目说明

根据以下输入输出信号设计一个计算1~12的计数器

Reset:同步复位信号,高复位,将计数器复位为1.

Enable:使能信号高有效

Clk:时钟上升沿触发计数器工作

Q[3:0]:计数器输出

c_enable, c_load, c_d[3:0]:题目中给我们提供了一个4-bit的计数器,这三个信号是用于该4-bit计数器的控制信号。

题目提供给我们4-bit计数器

有enable信号,带复位和置位的计数器,将该计数器例化至我们的代码中。

再用一些其他的逻辑门来完成本题

//题目提供的4-bit计数器代码 modulecount4( inputclk, inputenable, inputload, input[3:0]d, outputreg[3:0]Q );

模块端口声明

moduletop_module( inputclk, inputreset, inputenable, output[3:0]Q, outputc_enable, outputc_load, output[3:0]c_d );

题目解析

本题相当于用c_enale、c_load和c_d[3:0]三个控制信号来控制题目中给我们提供的4-bit计数器,使得该计数器的技术范围改变为1~12.

moduletop_module( inputlogicclk, inputlogicreset, inputlogicenable, outputlogic[3:0]Q, outputlogicc_enable, outputlogicc_load, outputlogic[3:0]c_d );// count4u1_count4(clk,c_enable,c_load,c_d,Q); assignc_enable=enable; assignc_load=reset|((Q==4d12)&&enable); assignc_d=c_load?4d1:4d0; endmodule 构建一个4位二进制计数器-用一个4位二进制并行加法器和6个与门设计12

点击Submit,等待一会就能看到下图结果:

构建一个4位二进制计数器-用一个4位二进制并行加法器和6个与门设计13

注意图中的Ref是参考波形,Yours是你的代码生成的波形,网站会对比这两个波形,一旦这两者不匹配,仿真结果会变红。

这一题就结束了。

Problem 103-ece241_2014_q7b

题目说明

从1000Hz中分离出1Hz的信号,叫做OneHertz。这个主要用作与数字时钟中。利用一个模10的BCD计数器和尽量少的逻辑门来建立一个时钟分频器。同时输出每个BCD计算器的使能信号(c_enable[0]为高位,c_enable[2]为低位)。

题目已经给我们提供了BCD计数器。Enable信号高有效。Reset信号高有效且复位为0。我们设计的电路中均要采用1000Hz的时钟。

modulebcdcount( inputclk, inputreset, inputenable, outputreg[3:0]Q );

模块端口声明

moduletop_module( inputclk, inputreset, outputOneHertz, output[2:0]c_enable );

题目解析

题目已经提供了一个模块,但是是个模10的BCD计数器,1000Hz提取1Hz,那么需要3个上面的计数器(1000/10/10/10=1).

moduletop_module( inputlogicclk, inputlogicreset, outputlogicOneHertz, outputlogic[2:0]c_enable );// wirelogic[3:0]unit,ten,hundred; assignc_enable={unit==4d9&&ten==4d9,unit==4d9,1b1}; assignOneHertz=(unit==4d9&&ten==4d9&&hundred==4d9); bcdcountcounter0(clk,reset,c_enable[0],unit); bcdcountcounter1(clk,reset,c_enable[1],ten); bcdcountcounter2(clk,reset,c_enable[2],hundred); endmodule 构建一个4位二进制计数器-用一个4位二进制并行加法器和6个与门设计14

点击Submit,等待一会就能看到下图结果:

构建一个4位二进制计数器-用一个4位二进制并行加法器和6个与门设计15

注意图中的Ref是参考波形,Yours是你的代码生成的波形,网站会对比这两个波形,一旦这两者不匹配,仿真结果会变红。

这一题就结束了。

Problem 104-Countbcd

题目说明

构建一个4位BCD(二进制编码十进制)计数器。每个十进制数字使用4位进行编码:q[3:0]是一位数字,q[7:4]是十位数字,等等。对于ena[3:1],该信号用来表示个位、十位和百位的进位。时序图如下图所示:

构建一个4位二进制计数器-用一个4位二进制并行加法器和6个与门设计16 图片来自HDLBits

模块端口声明

moduletop_module( inputclk, inputreset,//Synchronousactive-highreset output[3:1]ena, output[15:0]q);

题目解析

这是一个数字时钟的一部分。

moduletop_module( inputlogicclk, inputlogicreset,//Synchronousactive-highreset outputlogic[3:1]ena, outputlogic[15:0]q); reg[3:0]ones; reg[3:0]tens; reg[3:0]hundreds; reg[3:0]thousands; always@(posedgeclk)begin if(reset)ones<= 4d0;         else if(ones == 4d9)   ones <= 4d0;         else                    ones <= ones + 4d1 ;     end          always@(posedge clk)begin         if(reset)               tens <= 4d0;                      else if(tens == 4d9 && ones == 4d9)                                   tens <= 4d0;         else if(ones == 4d9)   tens <= tens + 4d1;     end          always@(posedge clk)begin         if(reset)               hundreds <= 4d0;                      else if(hundreds == 4d9 && tens == 4d9 && ones == 4d9)                                 hundreds <= 4d0;         else if(tens == 4d9 && ones == 4d9)                                  hundreds <= hundreds + 4d1;     end          always@(posedge clk)begin         if(reset)               thousands <= 4d0;         else if(thousands == 4d9 && hundreds == 4d9 && tens == 4d9 && ones == 4d9)                                 thousands <= 4d0;         else if(hundreds == 4d9 && tens == 4d9 && ones == 4d9)                                  thousands <= thousands + 4d1;     end          assign q = {thousands, hundreds, tens, ones};     assign ena[1] = (ones == 4d9) ? 1b1 : 1b0;     assign ena[2] = (tens == 4d9 && ones == 4d9) ? 1b1 : 1b0;     assign ena[3] = (hundreds == 4d9 && tens == 4d9 && ones == 4d9) ? 1b1 : 1b0;   endmodule 构建一个4位二进制计数器-用一个4位二进制并行加法器和6个与门设计17

点击Submit,等待一会就能看到下图结果:

构建一个4位二进制计数器-用一个4位二进制并行加法器和6个与门设计18

注意图中的Ref是参考波形,Yours是你的代码生成的波形,网站会对比这两个波形,一旦这两者不匹配,仿真结果会变红。

这一题就结束了。

Problem 105-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信号也可以进行复位操作。

下图所示的时序图给出了从1159 AM 到12 :00 : 00 PM的变化。

构建一个4位二进制计数器-用一个4位二进制并行加法器和6个与门设计19 图片来自HDLBits

模块端口声明

moduletop_module( inputclk, inputreset, inputena, outputpm, output[7:0]hh, output[7:0]mm, output[7:0]ss);

题目解析

moduletop_module( inputlogicclk, inputlogicreset, inputlogicena, outputlogicpm, outputlogic[7:0]hh, outputlogic[7:0]mm, outputlogic[7:0]ss); //ssvar varlogic[3:0]ss_one,ss_ten; varlogicena_ss_one,ena_ss_ten; varlogicrst_ss_one,rst_ss_ten; //mmvar varlogic[3:0]mm_one,mm_ten; varlogicena_mm_one,ena_mm_ten; varlogicrst_mm_one,rst_mm_ten; //hhvar varlogic[3:0]hh_one,hh_ten; varlogicena_hh_one,ena_hh_ten; varlogicrst_hh_one_0,rst_hh_one_1,rst_hh_ten_0,rst_hh_ten_1; //pmvar varlogicrev_pm; //sscoutpart assignena_ss_one=ena; assignrst_ss_one=ena_ss_one&&(ss_one==4d9); always_ff@(posedgeclk)begin if(reset)ss_one<= 0 ;         else if(ena_ss_one) begin             if(rst_ss_one)  ss_one <= 0 ;             else            ss_one <= ss_one + 4d1 ;         end     end          assign ena_ss_ten = rst_ss_one ;     assign rst_ss_ten = ena_ss_ten && (ss_ten == 4d5) ;          always_ff@(posedge clk) begin         if(reset)           ss_ten <= 0 ;         else if(ena_ss_ten) begin             if(rst_ss_ten)  ss_ten <= 0 ;             else            ss_ten <= ss_ten + 4d1 ;         end     end              //mm cout part          assign ena_mm_one = rst_ss_ten ;     assign rst_mm_one = ena_mm_one && (mm_one == 4d9) ;             always_ff@(posedge clk) begin         if(reset)           mm_one <= 0 ;         else if(ena_mm_one) begin             if(rst_mm_one)  mm_one <= 0 ;             else            mm_one <= mm_one + 4d1 ;         end     end                assign ena_mm_ten = rst_mm_one ;     assign rst_mm_ten = ena_mm_ten && (mm_ten == 4d5) ;          always_ff@(posedge clk) begin         if(reset)           mm_ten <= 0 ;         else if(ena_mm_ten) begin             if(rst_mm_ten)  mm_ten <= 0 ;             else            mm_ten <= mm_ten + 4d1 ;         end     end          //hh cout part          assign ena_hh_one = rst_mm_ten ;     assign rst_hh_one_0 = ena_hh_one && (hh_one == 4d9) ;     assign rst_hh_one_1 = ena_hh_one && (hh_one == 4d2 && hh_ten == 4d1) ;          always_ff@(posedge clk) begin         if(reset)             hh_one <= 4d2 ;         else if(ena_hh_one) begin             if(rst_hh_one_0)  hh_one <= 4d0 ;             else if(rst_hh_one_1)                                          hh_one <= 4d1 ;             else              hh_one <= hh_one + 4d1 ;         end     end                assign ena_hh_ten = ena_hh_one ;     assign rst_hh_ten_0 = ena_hh_ten && (hh_one == 4d2 && hh_ten == 4d1) ;     assign rst_hh_ten_1 = ena_hh_ten && (hh_one == 4d9) ;          always_ff@(posedge clk) begin         if(reset)             hh_ten <= 4d1 ;         else if(ena_hh_ten) begin             if(rst_hh_ten_0)  hh_ten <= 4d0 ;             else if(rst_hh_ten_1)                                           hh_ten <= 4d1 ;         end     end               //pm display part          assign rev_pm = (hh_ten == 4d1) && (hh_one == 4d1) && ena_hh_one ;          always_ff@(posedge clk) begin         if(reset)       pm <= 0  ;         else if(rev_pm) pm <= ~pm ;     end          //assign time output          assign ss = {ss_ten,ss_one} ;     assign mm = {mm_ten,mm_one} ;     assign hh = {hh_ten,hh_one} ; endmodule 构建一个4位二进制计数器-用一个4位二进制并行加法器和6个与门设计20构建一个4位二进制计数器-用一个4位二进制并行加法器和6个与门设计21构建一个4位二进制计数器-用一个4位二进制并行加法器和6个与门设计22

点击Submit,等待一会就能看到下图结果:

构建一个4位二进制计数器-用一个4位二进制并行加法器和6个与门设计23

注意图中的Ref是参考波形,Yours是你的代码生成的波形,网站会对比这两个波形,一旦这两者不匹配,仿真结果会变红。

这一题就结束了。

总结

今天的几道题就结束了,对于计数器的设计真的需要掌握,不仅是时序电路的基础,同时在后续FPGA设计也是一个重要的设计技巧。

最后我这边做题的代码也是个人理解使用,有错误欢迎大家批评指正,祝大家学习愉快~

审核编辑:刘清

猜你喜欢