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

从今天开始新的一章-时序电路,包括触发器、计数器、移位寄存器、状态机等。
今天更新计数器,这也是fpga部分非常重要的设计技巧。
problem 98-count15
题目说明
构建一个4位二进制计数器,计数范围从0到15(包括0和15),计数周期为16。同步复位输入时,将计数器重置为0。
图片来自hdlbits
模块端口声明
module top_module (    input clk,    input reset,      // synchronous active-high reset    output [3:0] q);  
题目解析
这是一个基本计数器。同步复位情况下,复位不放在敏感列表里。
module top_module (    input logic clk,    input logic reset,      // synchronous active-high reset    output logic [3:0] q);        always_ff@(posedge clk) begin        if(reset)  q <= '0 ;        else if(q == 4'd15) q <= '0 ;        else  q <= q + 1 ;    end            endmodule  
点击submit,等待一会就能看到下图结果:
注意图中的ref是参考波形,yours是你的代码生成的波形,网站会对比这两个波形,一旦这两者不匹配,仿真结果会变红。
这一题就结束了。
problem 99-count10
题目说明
构建一个十进制计数器,从0到9(包括0和9)计数,计数周期为10。同步复位输入时,将计数器重置为0。
图片来自hdlbits
模块端口声明
module top_module (    input clk,    input reset,        // synchronous active-high reset    output [3:0] q);  
题目解析
和上一题类似。
module top_module (    input logic clk,    input logic reset,        // synchronous active-high reset    output logic [3:0] q);        always_ff@(posedge clk) begin        if(reset)           q <= '0 ;        else if(q == 4'd9)  q <= '0 ;        else                q <= q + 1;    end endmodule  
点击submit,等待一会就能看到下图结果:
注意图中的ref是参考波形,yours是你的代码生成的波形,网站会对比这两个波形,一旦这两者不匹配,仿真结果会变红。
这一题就结束了。
problem 100-count1to10
题目说明
做一个十进制计数器,从1到10(包括1和10)计数,计数周期为10。同步复位输入时,将计数器重置为1。
图片来自hdlbits
模块端口声明
module top_module (    input clk,    input reset,    output [3:0] q);  
题目解析
和上一节一样,上一节是从0到9,这题从1到10,计数结束条件和重置条件不一样,其他一样。
module top_module (    input logic clk,    input logic reset,    output logic [3:0] q);        always_ff@(posedge clk)begin        if(reset)           q <= 4'd1;        else if(q == 4'd10) q <= 4'd1;        else                q <= q + 1;    endendmodule  
点击submit,等待一会就能看到下图结果:
注意图中的ref是参考波形,yours是你的代码生成的波形,网站会对比这两个波形,一旦这两者不匹配,仿真结果会变红。
这一题就结束了。
problem 101-countslow
题目说明
构建一个十进制计数器,从0到9(包括0和9)计数,计数周期为10。同步复位输入时,将计数器重置为0。但是本题是希望该计数器并不是随着clk的变化而递增,而是随着一个slowena使能信号来控制增加。时序图如下图所示:
图片来自hdlbits
模块端口声明
module top_module (    input clk,    input slowena,    input reset,    output [3:0] q);  
题目解析
本题相比于之前的计数器,不同点在于多了一个enable信号来控制计数器的增加(这应该叫使能同步计数器(战术后仰))。
module top_module (    input logic clk,    input logic slowena,    input logic reset,    output logic [3:0] q);    always_ff@(posedge clk) 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  ;    endendmodule  
点击submit,等待一会就能看到下图结果:
注意图中的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计数器代码module count4(    input clk,    input enable,    input load,    input [3:0] d,    output reg [3:0] q);  
模块端口声明
module top_module (    input clk,    input reset,    input enable,    output [3:0] q,    output c_enable,    output c_load,    output [3:0] c_d);   
题目解析
本题相当于用c_enale、c_load和c_d[3:0]三个控制信号来控制题目中给我们提供的4-bit计数器,使得该计数器的技术范围改变为1~12.
module top_module (    input logic clk,    input logic reset,    input logic enable,    output logic [3:0] q,    output logic c_enable,    output logic c_load,    output logic [3:0] c_d); //    count4 u1_count4 (clk, c_enable, c_load, c_d ,q);        assign c_enable = enable ;    assign c_load   = reset | ((q == 4'd12)&&enable) ;    assign c_d      = c_load ? 4'd1:4'd0 ;endmodule  
点击submit,等待一会就能看到下图结果:
注意图中的ref是参考波形,yours是你的代码生成的波形,网站会对比这两个波形,一旦这两者不匹配,仿真结果会变红。
这一题就结束了。
problem 103-ece241_2014_q7b
题目说明
从1000hz中分离出1hz的信号,叫做onehertz。这个主要用作与数字时钟中。利用一个模10的bcd计数器和尽量少的逻辑门来建立一个时钟分频器。同时输出每个bcd计算器的使能信号(c_enable[0]为高位,c_enable[2]为低位)。
题目已经给我们提供了bcd计数器。enable信号高有效。reset信号高有效且复位为0。我们设计的电路中均要采用1000hz的时钟。
module bcdcount (    input clk,    input reset,    input enable,    output reg [3:0] q);  
模块端口声明
module top_module (    input clk,    input reset,    output onehertz,    output [2:0] c_enable);   
题目解析
题目已经提供了一个模块,但是是个模10的bcd计数器,1000hz提取1hz,那么需要3个上面的计数器(1000/10/10/10=1).
module top_module (    input logic clk,    input logic reset,    output logic onehertz,    output logic [2:0] c_enable); //    wire logic [3:0] unit, ten, hundred;        assign c_enable = {unit == 4'd9 && ten == 4'd9, unit == 4'd9, 1'b1};    assign onehertz = (unit == 4'd9 && ten == 4'd9 && hundred == 4'd9);     bcdcount counter0 (clk, reset, c_enable[0], unit);    bcdcount counter1 (clk, reset, c_enable[1], ten);    bcdcount counter2 (clk, reset, c_enable[2], hundred); endmodule  
点击submit,等待一会就能看到下图结果:
注意图中的ref是参考波形,yours是你的代码生成的波形,网站会对比这两个波形,一旦这两者不匹配,仿真结果会变红。
这一题就结束了。
problem 104-countbcd
题目说明
构建一个4位bcd(二进制编码十进制)计数器。每个十进制数字使用4位进行编码:q[3:0]是一位数字,q[7:4]是十位数字,等等。对于ena[3:1],该信号用来表示个位、十位和百位的进位。时序图如下图所示:
图片来自hdlbits
模块端口声明
module top_module (    input clk,    input reset,   // synchronous active-high reset    output [3:1] ena,    output [15:0] q);  
题目解析
这是一个数字时钟的一部分。
module top_module (    input logic clk,    input logic reset,   // synchronous active-high reset    output logic [3:1] ena,    output logic [15:0] q);        reg [3:0] ones;    reg [3:0] tens;    reg [3:0] hundreds;    reg [3:0] thousands;        always@(posedge clk)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  
点击submit,等待一会就能看到下图结果:
注意图中的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的变化。
图片来自hdlbits
模块端口声明
module top_module(    input clk,    input reset,    input ena,    output pm,    output [7:0] hh,    output [7:0] mm,    output [7:0] ss);   
题目解析
module top_module(    input logic clk,    input logic reset,    input logic ena,    output logic pm,    output logic [7:0] hh,    output logic [7:0] mm,    output logic [7:0] ss);         //ss var    var logic [3:0] ss_one , ss_ten ;    var logic ena_ss_one , ena_ss_ten ;    var logic rst_ss_one , rst_ss_ten ;        //mm var    var logic [3:0] mm_one , mm_ten ;    var logic ena_mm_one , ena_mm_ten ;    var logic rst_mm_one , rst_mm_ten ;        //hh var    var logic [3:0] hh_one , hh_ten ;    var logic ena_hh_one , ena_hh_ten ;    var logic rst_hh_one_0 , rst_hh_one_1 , rst_hh_ten_0 , rst_hh_ten_1 ;        //pm var    var logic rev_pm ;            //ss cout part    assign ena_ss_one = ena ;    assign rst_ss_one = ena_ss_one && (ss_one == 4'd9) ;        always_ff@(posedge clk) 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  
点击submit,等待一会就能看到下图结果:
注意图中的ref是参考波形,yours是你的代码生成的波形,网站会对比这两个波形,一旦这两者不匹配,仿真结果会变红。
这一题就结束了。
总结
今天的几道题就结束了,对于计数器的设计真的需要掌握,不仅是时序电路的基础,同时在后续fpga设计也是一个重要的设计技巧。
最后我这边做题的代码也是个人理解使用,有错误欢迎大家批评指正,祝大家学习愉快~


诺基亚3310,终将成为一位倒下的巨人
ADC需要注意的参数有哪些呢?
华为MDC 810设备生产问题影响国产旗舰车款交付
SiC的物性和特征
雅玛尔202号卫星参数表
构建一个4位二进制计数器
温度采集器选YXC扬兴科技:YSO110TR低启动时间与多电压兼容性
嵌入式10大算法的了解
网络应用中的低损耗同轴线缆的知识详解
Micro LED激光巨量转移技术剖析
华为反击战全面打响!用西方人对付西方人
防腐磁翻板液位计安装及使用的注意事项
开发转向系统,您需要MXsteerHiL的五大理由
电流型开关电源中的UC3842电压反馈电路
高品质的LED制造探讨
低压线性恒流驱动芯片的产品特性与应用领域
什么是光纤放大器?
单片机常用的载波频率是什么
信号继电器的基本原理
深度学习怎样可以提高的汽车的感知能力