赞
踩
本节为时序电路的设计,需要重点掌握。
第一题:4-bits binary counters:
构建一个4位二进制计数器,计数从0到15(包括15),周期为16。复位输入是同步的,应该将计数器复位为0。
正确答案:
时序电路中,我总结了一个这样的习惯:
先设置清零的条件、其次为复位的条件、最后为计数(else);
注意在时序电路中如果要给输出赋值,应该使用<=符号,一般逻辑赋值语句使用=;
该题正确答案:因为该题的最大值即15,无需设置复位,4bits直接就是0-15;
- module top_module (
- input clk,
- input reset, // Synchronous active-high reset
- output [3:0] q);
- always@(posedge clk)begin
- if(reset)begin
- q[3:0] <= 0;
- end
- else begin
- q[3:0] <= q[3:0]+1'b1;
- end
- end
- endmodule
第二题:count10:
构建一个从0到9(包括9)的十进制计数器,周期为10。复位输入是同步的,应该将计数器复位为0。上题已经讲过:一般时序电路我们可以以清零、复位(或进一)、计数(else)的逻辑先后顺序来进行。
正确答案:
- module top_module (
- input clk,
- input reset, // Synchronous active-high reset
- output [3:0] q);
- always@(posedge clk)begin
- if(reset)begin
- q[3:0]<=0;
- end
- else if(q[3:0]==4'd9)begin
- q[3:0]<=0;
- end
- else begin
- q[3:0]<=q[3:0]+4'b1;
- end
- end
- endmodule
解析:第一个if是清零信号,当reset==1时,可使q<=0;
第二个else if是复位信号,当q[3:0]==9时(注意4'd9指的是该位为4bits,d指的是十进制,9为十进制中的9)。
第三个else 指的是其他情况下(posedge clk)都可以进行计数。
本题也可以将清零和复位信号结合起来:
-
- always@(posedge clk)begin
- if(reset||q[3:0]==4'd9)begin
- q[3:0]<=0;
- end
- else begin
- q[3:0]<=q[3:0]+4'b1;
- end
- end
第三题:Count1to10:
制作一个从1数到10的10秒计数器。复位输入是同步的,应该将计数器复位为1。
正确答案:
- module top_module (
- input clk,
- input reset,
- output [3:0] q);
- always@(posedge clk)begin
- if(reset||q[3:0]==4'd10)begin
- q[3:0]<=4'd1;
- end
- else begin
- q[3:0]<=q[3:0]+4'd1;
- end
- end
- endmodule
第四题:Countslow:
本题需要在slowena为1时才能计数,所以计数的该条件(slowena==1)为置数和计数的必要条件。
正确答案:
- module top_module (
- input clk,
- input slowena,
- input reset,
- output [3:0] q);
- always@(posedge clk)begin
- if(reset)begin
- q[3:0]<=0;
- end
- else if(slowena&&q[3:0]==4'd9)begin
- q[3:0]<=0;
- end
- else if(slowena&&q[3:0]<4'd9)begin
- q[3:0]<=q[3:0]+4'd1;
- end
- end
- endmodule
第五题:exams:
设计1-12计数器,要求如下:
Reset同步活动高电平复位,强制计数器为1;
设置计数器运行的高值;
Clk正极触发时钟输入;
Q[3:0]计数器的输出;
c_enable, c_load, c_d[3:0]进入提供的4位计数器的控制信号,因此可以验证正确的操作。
c_enable、c_load和c_d输出分别是进入内部计数器的enable、load和d输入的信号。它们的目的是允许检查这些信号的正确性。
正确答案:
- 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||((enable)&&(Q[3:0]==4'd12));
- assign c_d = c_load?4'd1:4'd0;
- endmodule
第六题:Counter1000
正确答案:
- module top_module (
- input clk,
- input reset,
- output OneHertz,
- output [2:0] c_enable
- ); //
-
- wire [3:0]a,b,c;
-
- assign OneHertz = (a[3:0]==4'd9)&&(b[3:0]==4'd9)&&(c[3:0]==4'd9);
- assign c_enable = {(a[3:0]==4'd9&&b[3:0]==4'd9),(a[3:0]==4'd9),1'b1};
- bcdcount counter0 (clk, reset, c_enable[0],a);
- bcdcount counter1 (clk, reset, c_enable[1],b);
- bcdcount counter2 (clk, reset, c_enable[2],c); //分频器大概是把1000分成三部分的
- endmodule
第七题:CountBCD:
构建一个4位BCD(二进制编码的十进制)计数器。每个十进制数字用4位编码:q[3:0]是个位数,q[7:4]是十位,等等。对于数字[3:1],还输出一个enable信号,指示何时应增加前三位数字中的每一位。enable信号有三位,其实就是这个四位数的前面三位一个一个地进位,个位进位使enable[1]=1;十位进位使enable[2]=1,以此类推。
您可以实例化或修改一些十位计数器。
先尝试写出来:
正确答案:
- module top_module (
- input clk,
- input reset, // Synchronous active-high reset
- output [3:1] ena,
- output [15:0] q);
-
-
- //分开写,千位
- always@(posedge clk)begin
- if(reset)begin
- q[15:12]<=0;
- end
- else if(q[15:12]==4'd9&&q[11:8]==4'd9&&q[7:4]==4'd9&&q[3:0]==4'd9)begin
- q[15:12]<=0;
- end
- else if(q[11:8]==4'd9&&q[7:4]==4'd9&&q[3:0]==4'd9)begin
- q[15:12]<=q[15:12]+1'b1;
- end
- end
-
- //百位:
- always@(posedge clk)begin
- if(reset)begin
- q[11:8]<=0;
- end
- else if(q[11:8]==4'd9&&q[7:4]==4'd9&&q[3:0]==4'd9)begin
- q[11:8]<=0;
- end
- else if(q[7:4]==4'd9&&q[3:0]==4'd9)begin
- q[11:8]<=q[11:8]+1'b1;
- end
- end
- //十位
- always@(posedge clk)begin
- if(reset)begin
- q[7:4]<=0;
- end
- else if(q[7:4]==4'd9&&q[3:0]==4'd9)begin
- q[7:4]<=0;
- end
- else if(q[3:0]==4'd9)begin
- q[7:4]<=q[7:4]+1'b1;
- end
- end
-
- //个位:
- always@(posedge clk)begin
- if(reset)begin
- q[3:0]<=0;
- end
- else if(q[3:0]==4'd9)begin
- q[3:0]<=0;
- end
- else begin q[3:0]<=q[3:0]+1'b1;
- end
- end
-
- assign ena[1] = q[3:0]==4'd9;
- assign ena[2] = q[7:4]==4'd9&&ena[1];
- assign ena[3] = q[11:8]==4'd9&&ena[2];
- endmodule
第八题:Count Clock
本题要求:
创建一组适合作为12小时时钟使用的计数器(带有am/pm指示器)。您的计数器由一个快速运行的时钟进行计时,每当您的时钟应该增加时(即每秒一次),就会有一个脉冲。
reset将时钟重置到12:00 AM。pm是0表示AM, 1表示pm。hh、mm和ss是两个BCD(二进制编码十进制)数字,分别表示小时(01-12)、分钟(00-59)和秒(00-59)。Reset具有比enable更高的优先级,并且即使在未启用时也可能发生。
下面的时间图显示了从11:59:59 AM到12:00:00 PM的滚动行为以及同步重置和启用行为。
正确答案:
PM的翻转模块,该模块仅仅是判断十二点时的早晚状态的,所以只需要写关于11:59:59&&ena的逻辑便可,再将值赋到output PM 上。
然后即秒个位(ena2_ss)、秒十位(ena1_ss)、分个位(ena2_mm)、分十位(ena1_mm)的逻辑编写,大同小异,都是在前一个位数满足跳变的基础上再加上ena电平给这个判断成功条件;如分个位(ena2_mm)是ena&&秒设置为59才可以触发。我在其中为了使代码看起来更简洁,将一些条件赋值为wire中间向量了。
其中时的设计有些难写,首先要满足假如时钟点为12的时候,计数器就变成01,然后再是判断ena&&09:59:59的复位情况,这种情况ena&&9X"59"59与情况12无关,所以我们要分开判断,不能在条件里嵌套,不然会非常混乱。
最后才是计数的判断,是出复位判断以外的ena&&09"59"59的条件,这是复位情况的母条件,所以可以嵌套来写。
整体就是这样的思路:需要注意的是,你必须将分、秒的个位十位都分开写,逻辑思路清晰的前提下,可以尽可能地使用赋值语句使代码更简洁,最后就是翻转模块。
正确答案:
- module top_module(
- input clk,
- input reset,
- input ena,
- output pm,
- output [7:0] hh,
- output [7:0] mm,
- output [7:0] ss);
- //思路:pm模块、时、分、秒十位个位分写的逻辑模块
-
- //声明部分:
- //1指的是十位的使能、复位、翻转
- wire [3:0]ena1_ss,end1_ss;//秒的十位
- wire [3:0]ena1_mm,end1_mm;//分的十位
- wire [3:0]ena1_hh,end1_hh;//包括使能键、复位键、翻转键,时的十位
-
- //2指的都是个位的使能、复位、翻转
- wire [3:0]ena2_ss,end2_ss;//秒的十位
- wire [3:0]ena2_mm,end2_mm;//分的十位
- wire [3:0]ena2_hh,end2_hh;//包括使能键、复位键\时的十位
-
-
- reg ena_pm;//时置一的信号
- wire ss1,ss2,mm1,mm2,hh1;
-
-
- assign ena2_ss = ss[3:0];
- assign ena1_ss = ss[7:4];
- assign ena2_mm = mm[3:0];
- assign ena1_mm = mm[7:4];
- assign ena2_hh = hh[3:0];
- assign ena1_hh = hh[7:4];
-
-
-
- assign ss1 = ena2_ss==4'd9;
- assign ss2 = ss1&&ena1_ss==4'd5;
- assign mm1 = ss2&&ena2_mm==4'd9;
- assign mm2 = mm1&&ena1_mm==4'd5;
- assign hh1 = mm2&&ena2_hh==4'd9;
-
- //时、分、秒
- always@(posedge clk)begin //时针的十位
- if(reset)begin //清零
- hh[7:4]<=1;
- end
- else if(ena2_hh==4'd2&&ena1_hh==4'd1&&ena&&mm2)begin
- hh[7:4]<=4'd0;
- end
- else if(ena&&hh1)begin //复位、翻转
- if(ena1_hh==4'd9)begin
- hh[7:4]<=4'd0;
- end
- else begin //计数
- hh[7:4]<=hh[7:4]+1'b1;
- end
- end
- end
-
-
- always@(posedge clk)begin //时针的个位
- if(reset)begin //清零
- hh[3:0]<=2;
- end
- else if(ena&&mm2&&ena2_hh==4'd2&&ena1_hh==4'd1)begin //复位、翻转
- hh[3:0]<=4'd1;
- end
- else if(ena&&mm2)begin
- if(ena2_hh==4'd9)begin
- hh[3:0]<=4'd0;
- end
- else begin //计数
- hh[3:0]<=hh[3:0]+1'b1;
- end
- end
- end
-
-
-
- always@(posedge clk)begin //分针的十位
- if(reset)begin //清零
- mm[7:4]<=0;
- end
-
- else if(ena&&mm1)begin //复位、进一
- if(ena1_mm==4'd5)begin
- mm[7:4]<=4'd0;
- end
- else begin //计数
- mm[7:4]<=mm[7:4]+1'b1;
- end
- end
- end
-
-
- always@(posedge clk)begin //分针的个位
- if(reset)begin //清零
- mm[3:0]<=0;
- end
- else if(ena&&ss2)begin
- if(ena2_mm==4'd9)begin//复位、进一
- mm[3:0]<=4'd0;
- end
- else begin //计数
- mm[3:0]<=mm[3:0]+1'b1;
- end
- end
- end
-
-
- always@(posedge clk)begin //秒针的十位
- if(reset)begin //清零
- ss[7:4]<=0;
- end
- else if(ena&&ss1)begin
- if(ena1_ss==4'd5)begin//复位、进一
- ss[7:4]<=4'd0;
- end
- else begin //计数
- ss[7:4]<=ss[7:4]+1'b1;
- end
- end
- end
-
- always@(posedge clk)begin //秒针的个位
- if(reset)begin //清零
- ss[3:0]<=0;
- end
- else if(ena)begin
- if(ss1)begin //复位、进一
- ss[3:0]<=4'd0;
- end
- else begin //计数
- ss[3:0]<=ss[3:0]+1'b1;
- end
- end
- end
-
- //ena_pm模块
-
- // PM位 start
- always @(posedge clk) begin
- if (reset) begin
- pm <= 0;
- end
- else if (ena_pm) begin
- pm <= ~pm; // pm信号翻转
- end
- end
- assign ena_pm = (ena&&mm2)&&(hh[7:4]==4'd1) && (hh[3:0]==4'd1);
- endmodule
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。