0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

构建一个4位二进制计数器

OpenFPGA 来源:OpenFPGA 作者:碎碎思 2022-12-02 09:20 次阅读

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

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

Problem 98-Count15

题目说明

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

60c4fdc0-71d9-11ed-8abf-dac502259ad0.png

图片来自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 == 4'd15) q <= '0 ;
        else  q <= q + 1 ;
    end
            

endmodule


60e0080e-71d9-11ed-8abf-dac502259ad0.png

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

6100e3da-71d9-11ed-8abf-dac502259ad0.png

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

这一题就结束了。

Problem 99-Count10

题目说明

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

612e96a4-71d9-11ed-8abf-dac502259ad0.png

图片来自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 == 4'd9)  q <= '0 ;
        else                q <= q + 1;
    end
 
endmodule

61422d40-71d9-11ed-8abf-dac502259ad0.png

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

616719e8-71d9-11ed-8abf-dac502259ad0.png

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

这一题就结束了。

Problem 100-Count1to10

题目说明

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

61a9ee80-71d9-11ed-8abf-dac502259ad0.png

图片来自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<= 4'd1;
        else if(q == 4'd10) q <= 4'd1;
        else                q <= q + 1;
    end
endmodule


61c4ffcc-71d9-11ed-8abf-dac502259ad0.png

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

61ebd110-71d9-11ed-8abf-dac502259ad0.png

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

这一题就结束了。

Problem 101-Countslow

题目说明

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

622fa476-71d9-11ed-8abf-dac502259ad0.png

图片来自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==4'd9) q <= '0 ;
        else if(slowena & q!=4'd9) q <= q + 1 ;
        else                       q <= q  ;
    end
endmodule


62778a2a-71d9-11ed-8abf-dac502259ad0.png

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

629e79e6-71d9-11ed-8abf-dac502259ad0.png

注意图中的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==4'd12)&&enable);
assignc_d=c_load?4'd1:4'd0;

endmodule

62d018c0-71d9-11ed-8abf-dac502259ad0.png

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

62fb0206-71d9-11ed-8abf-dac502259ad0.png

注意图中的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==4'd9&&ten==4'd9,unit==4'd9,1'b1};
assignOneHertz=(unit==4'd9&&ten==4'd9&&hundred==4'd9);

bcdcountcounter0(clk,reset,c_enable[0],unit);
bcdcountcounter1(clk,reset,c_enable[1],ten);
bcdcountcounter2(clk,reset,c_enable[2],hundred);

endmodule

6329de6e-71d9-11ed-8abf-dac502259ad0.png

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

634e9146-71d9-11ed-8abf-dac502259ad0.png

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

这一题就结束了。

Problem 104-Countbcd

题目说明

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

6373080a-71d9-11ed-8abf-dac502259ad0.png

图片来自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<= 4'd0;
        else if(ones == 4'd9)   ones <= 4'd0;
        else                    ones <= ones + 4'd1 ;
    end
    
    always@(posedge clk)begin
        if(reset)               tens <= 4'd0;
            
        else if(tens == 4'd9 && ones == 4'd9)  
                                tens <= 4'd0;
        else if(ones == 4'd9)   tens <= tens + 4'd1;
    end
    
    always@(posedge clk)begin
        if(reset)               hundreds <= 4'd0;
            
        else if(hundreds == 4'd9 && tens == 4'd9 && ones == 4'd9)
                                hundreds <= 4'd0;
        else if(tens == 4'd9 && ones == 4'd9) 
                                hundreds <= hundreds + 4'd1;
    end
    
    always@(posedge clk)begin
        if(reset)               thousands <= 4'd0;
        else if(thousands == 4'd9 && hundreds == 4'd9 && tens == 4'd9 && ones == 4'd9)
                                thousands <= 4'd0;
        else if(hundreds == 4'd9 && tens == 4'd9 && ones == 4'd9) 
                                thousands <= thousands + 4'd1;
    end
    
    assign q = {thousands, hundreds, tens, ones};
    assign ena[1] = (ones == 4'd9) ? 1'b1 : 1'b0;
    assign ena[2] = (tens == 4'd9 && ones == 4'd9) ? 1'b1 : 1'b0;
    assign ena[3] = (hundreds == 4'd9 && tens == 4'd9 && ones == 4'd9) ? 1'b1 : 1'b0;
 
endmodule

63877ce0-71d9-11ed-8abf-dac502259ad0.png

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

63b9b0de-71d9-11ed-8abf-dac502259ad0.png

注意图中的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的变化。

63eb3fbe-71d9-11ed-8abf-dac502259ad0.png

图片来自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==4'd9);

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 + 4'd1 ;
        end
    end
    
    assign ena_ss_ten = rst_ss_one ;
    assign rst_ss_ten = ena_ss_ten && (ss_ten == 4'd5) ;
    
    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 + 4'd1 ;
        end
    end
   
    
    //mm cout part
    
    assign ena_mm_one = rst_ss_ten ;
    assign rst_mm_one = ena_mm_one && (mm_one == 4'd9) ;
       
    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 + 4'd1 ;
        end
    end 
    
    
    assign ena_mm_ten = rst_mm_one ;
    assign rst_mm_ten = ena_mm_ten && (mm_ten == 4'd5) ;
    
    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 + 4'd1 ;
        end
    end
    
    //hh cout part
    
    assign ena_hh_one = rst_mm_ten ;
    assign rst_hh_one_0 = ena_hh_one && (hh_one == 4'd9) ;
    assign rst_hh_one_1 = ena_hh_one && (hh_one == 4'd2 && hh_ten == 4'd1) ;
    
    always_ff@(posedge clk) begin
        if(reset)             hh_one <= 4'd2 ;
        else if(ena_hh_one) begin
            if(rst_hh_one_0)  hh_one <= 4'd0 ;
            else if(rst_hh_one_1)           
                              hh_one <= 4'd1 ;
            else              hh_one <= hh_one + 4'd1 ;
        end
    end 
    
    
    assign ena_hh_ten = ena_hh_one ;
    assign rst_hh_ten_0 = ena_hh_ten && (hh_one == 4'd2 && hh_ten == 4'd1) ;
    assign rst_hh_ten_1 = ena_hh_ten && (hh_one == 4'd9) ;
    
    always_ff@(posedge clk) begin
        if(reset)             hh_ten <= 4'd1 ;
        else if(ena_hh_ten) begin
            if(rst_hh_ten_0)  hh_ten <= 4'd0 ;
            else if(rst_hh_ten_1)            
                              hh_ten <= 4'd1 ;
        end
    end
    
    
    //pm display part
    
    assign rev_pm = (hh_ten == 4'd1) && (hh_one == 4'd1) && 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


6404635e-71d9-11ed-8abf-dac502259ad0.png64389a7a-71d9-11ed-8abf-dac502259ad0.png64586e36-71d9-11ed-8abf-dac502259ad0.png

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

648e195a-71d9-11ed-8abf-dac502259ad0.png

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

这一题就结束了。

总结

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

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


审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 二进制
    +关注

    关注

    2

    文章

    705

    浏览量

    41248
  • 计数器
    +关注

    关注

    32

    文章

    2121

    浏览量

    92968
  • 时序电路
    +关注

    关注

    1

    文章

    113

    浏览量

    21586
  • CLK
    CLK
    +关注

    关注

    0

    文章

    122

    浏览量

    16908
  • Verilog语言
    +关注

    关注

    0

    文章

    113

    浏览量

    8159

原文标题:HDLBits: 在线学习 SystemVerilog(十六)-Problem 98-105(计数器)

文章出处:【微信号:Open_FPGA,微信公众号:OpenFPGA】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    二进制计数器选择不同的开关

    二进制计数器实现控制选择不同的开关,电路输入信号为路方波,当此信号的第一个方波信号输入时,电路使用开关1,当此信号的第二个方波信号输入时
    发表于 06-26 09:30

    如何使用USART接收二进制

    我想制作以8LED的形式实现二进制计数器。该计数器通过USART发送
    发表于 10-08 14:07

    怎么使用LUT设计4二进制上变频计数器

    嗨,我需要使用LUT设计4二进制上变频计数器。我正在尝试遵循多路复用器方法。任何想法都非常
    发表于 02-14 11:29

    集成四二进制计数器

    目录1. 集成四二进制计数器【74LVC161】(1) 逻辑符号(2) 功能表(3) 应用① 构成任意模数的计数器a. 反馈清零法b. 反馈置数法c. 位数拓展② 构成分频
    发表于 07-29 07:20

    12位二进制计数器

    12位二进制计数器
    发表于 09-16 15:56 6139次阅读
    12位<b class='flag-5'>二进制</b><b class='flag-5'>计数器</b>

    异步二进制计数器

    异步二进制计数器 1.  电路构成与工作原理  
    发表于 09-30 18:33 1.4w次阅读
    异步<b class='flag-5'>二进制</b><b class='flag-5'>计数器</b>

    同步二进制计数器

    同步二进制计数器 1.   同步与异步二进制加法计数器比较态序表和工作波形一样电路结构不同:  异步二进制加法
    发表于 09-30 18:37 1.1w次阅读
    同步<b class='flag-5'>二进制</b><b class='flag-5'>计数器</b>

    什么是二进制计数器,二进制计数器原理是什么?

    什么是二进制计数器,二进制计数器原理是什么? 计数器是数字系统中用得较多的基本逻辑器件。它不仅能记录输入时钟脉冲的个数,还可以实现
    发表于 03-08 13:16 3w次阅读

    3位二进制计数器

    基于VHDL的EDA实验---3位二进制计数器
    发表于 11-08 17:45 1次下载

    二进制计数器浅析

    二进制计数器
    发表于 11-24 14:31 6次下载

    数字二进制计数器的设计和实现

    二进制数视为元胞自动机可能有助于数字二进制计数器的设计和实现吗?
    发表于 07-28 11:47 1278次阅读
    数字<b class='flag-5'>二进制</b><b class='flag-5'>计数器</b>的设计和实现

    STEM项目之构建基于继电器的二进制计数器

    电子发烧友网站提供《STEM项目之构建基于继电器的二进制计数器.zip》资料免费下载
    发表于 10-18 09:19 0次下载
    STEM项目之<b class='flag-5'>构建</b>基于继电器的<b class='flag-5'>二进制</b><b class='flag-5'>计数器</b>

    12级二进制纹波计数器-HEF4040B

    12级二进制纹波计数器-HEF4040B
    发表于 02-15 18:40 0次下载
    12级<b class='flag-5'>二进制</b>纹波<b class='flag-5'>计数器</b>-HEF4040B

    构建LED二进制计数器

    电子发烧友网站提供《构建LED二进制计数器.zip》资料免费下载
    发表于 06-12 09:54 0次下载
    <b class='flag-5'>构建</b>LED<b class='flag-5'>二进制</b><b class='flag-5'>计数器</b>

    使用Arduino UNO构建4位二进制计数器

    电子发烧友网站提供《使用Arduino UNO构建4位二进制计数器.zip》资料免费下载
    发表于 06-25 11:38 0次下载
    使用Arduino UNO<b class='flag-5'>构建</b>4位<b class='flag-5'>二进制</b><b class='flag-5'>计数器</b>