FP设计应用教程 答案 4_第1页
FP设计应用教程 答案 4_第2页
FP设计应用教程 答案 4_第3页
FP设计应用教程 答案 4_第4页
FP设计应用教程 答案 4_第5页
已阅读5页,还剩29页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

习题5-1试用模块例化的方式实现4位二进制比较器。参考答案:要使用1位二进制比较器作为子模块,通过模块例化的方式实现4位二进制比较器,要对例5.1的二进制比较器进行修改。为了方便进行模块连接,需要增加一位使能信号en,且把电路输出变成低电平有效。修改1位比较器程序如下:modulecomp_1bit(x,y,en,gt,eq,lt);//修改例5.1的1位比较器inputx,y;inputen;outputreggt,eq,lt;always@*begingt=1;eq=1;lt=1;if(en)begin if(x>y) gt=0; if(x==y) eq=0; if(x<y) lt=0; end else {gt,eq,lt}=3'b111;endendmodule4位二进制比较器的结构化建模程序如下:modulecomp_4bit(input[3:0]A,B,inputen,outputgt,eq,lt);wireeq_bit3,eq_bit2,eq_bit1;wire[3:0]GT,LT;comp_1bitbit3_comp(.x(A[3]),.y(B[3]),.en(en),.gt(GT[3]),.eq(eq_bit3),.lt(LT[3]));comp_1bitbit2_comp(.x(A[2]),.y(B[2]),.en(eq_bit3),.gt(GT[2]),.eq(eq_bit2),.lt(LT[2]));comp_1bitbit1_comp(.x(A[1]),.y(B[1]),.en(eq_bit2),.gt(GT[1]),.eq(eq_bit1),.lt(LT[1]));comp_1bitbit0_comp(.x(A[0]),.y(B[0]),.en(eq_bit1),.gt(GT[0]),.eq(eq),.lt(LT[0]));andand_gt(gt,GT[3],GT[2],GT[1],GT[0]);andand_lt(t,LT[3],LT[2],LT[1],LT[0]);endmodule习题5-2用VerilogHDL设计一个三人表决器,当三个输入中有两个或三个为高电平时,输出为高电平。参考答案:这是一个组合逻辑电路,当2个或3个输入为1时输出1,逻辑表达式为Y=AB+BC+AC,可以用多种形式实现。①数据流方式modulemajority_voter_3(inputwireA,inputwireB,inputwireC,outputwireY);assignY=(A&B)|(B&C)|(A&C);endmodule②行为描述方式modulemajority_voter_3(inputwireA,inputwireB,inputwireC,outputregY);always@(*)begincase({A,B,C})3'b000:Y=1'b0;//0个13'b001:Y=1'b0;//1个13'b010:Y=1'b0;//1个13'b011:Y=1'b1;//2个13'b100:Y=1'b0;//1个13'b101:Y=1'b1;//2个13'b110:Y=1'b1;//2个13'b111:Y=1'b1;//3个1endcaseendendmodule习题5-3用VerilogHDL实现用两个4选1选择器设计一个8选1选择器。参考答案:用两个4选1Mux设计一个8选1Mux,要求进行结构化建模。先设计4选1Mux作为子模块,程序如下:modulemux4to1(data_in,sel,out);input[3:0]data_in;//需要4个数据输入端input[1:0]sel;outputregout;always@(*)begincase(sel)2'b00:out=data_in[0];2'b01:out=data_in[1];2'b10:out=data_in[2];2'b11:out=data_in[3];default:out=1'b0;endcaseendendmodule再对子模块例化2次,再增加一位片选信号,实现8选1Mux的顶层设计。modulemux8to1_structural();input[7:0]data_in;//需要8个数据输入端input[2:0]sel;//最高位实现片选功能,低两位实现数据的4选1outputout;wireout_low,out_high;//处理低4位数据data_in[3:0]mux4to1mux_low(.data_in(data_in[3:0]),.sel(sel[1:0]),.out(out_low));/处理高4位数据(data_in[7:4])mux4to1mux_high(.data_in(data_in[7:4]),.sel(sel[1:0]),.out(out_high));//使用sel[2]选择使用哪个4选1选择器assignout=sel[2]?out_high:out_low;endmodule习题5-4试编写Verilog程序,用3线-8线译码器74138和基本逻辑门实现函数发生器F=Σm(1,3,6,7)。参考答案:这也是一个需要使用结构建模方式解决的问题。译码器74138作为子模块,结合模块例化和门级例化语句实现顶层设计。译码器74138程序可以写作:moduledecoder_74138(A,B,C,G1,G2A_n,G2B_n,Y_n);inputA,B,C;//输入信号inputG1,G2A_n,G2B_n;//使能信号outputreg[7:0]Y_n;//输出信号(低电平有效)//只有当G1=1且G2A_n=0且G2B_n=0时,译码器工作always@(*)beginif(G1&&~G2A_n&&~G2B_n)begincase({C,B,A})3'b000:Y_n=8'b11111110;//Y0_n有效3'b001:Y_n=8'b11111101;//Y1_n有效3'b010:Y_n=8'b11111011;//Y2_n有效3'b011:Y_n=8'b11110111;//Y3_n有效3'b100:Y_n=8'b11101111;//Y4_n有效3'b101:Y_n=8'b11011111;//Y5_n有效3'b110:Y_n=8'b10111111;//Y6_n有效3'b111:Y_n=8'b01111111;//Y7_n有效default:Y_n=8'b11111111;endcaseendelsebeginY_n=8'b11111111;//所有输出无效endendendmodule函数F=Σm(1,3,6,7)表示当输入组合为最小项1、3、6、7时,输出为1。最小项对应关系(假设C为最高位,A为最低位),即:m1:CBA=001(C=0,B=0,A=1)m3:CBA=011(C=0,B=1,A=1)m6:CBA=110(C=1,B=1,A=0)m7:CBA=111(C=1,B=1,A=1)顶层设计代码如下:modulefunction_generator(A,B,C,F);inputA,B,C;outputF;wire[7:0]Y_n;//74138输出(低电平有效)wireG1=1'b1;wireG2A_n=1'b0;wireG2B_n=1'b0;decoder_74138u_decoder(.A(A),.B(B),.C(C),.G1(G1),.G2A_n(G2A_n),.G2B_n(G2B_n),.Y_n(Y_n));nandU1(F,Y_n[1],Y_n[3],Y_n[6],Y_n[7]);endmodule习题5-5用VerilogHDL实现一个8线-3线优先编码器,其真值表如表5-9所示。表5-98线-3线优先编码器真值表in7in6in5in4in3in2in1in0out2out1out0000000010000000001X001000001XX01000001XXX0110001XXXX100001XXXXX10101XXXXXX1101XXXXXXX111参考答案:modulepriority_encoder_8to3(in,out);input[7:0]in,outputreg[2:0]out,always@(*)beginif(in[7])//Highestpriority:in7out=3'b111;elseif(in[6])out=3'b110;elseif(in[5])out=3'b101;elseif(in[4])out=3'b100;elseif(in[3])out=3'b011;elseif(in[2])out=3'b010;elseif(in[1])out=3'b001;elseif(in[0])out=3'b000;else//所有输入为0时out=3'bxxx;endendmodule习题5-6写出十进制数在两个七段数码管上显示的VerilogHDL程序。参考答案:十进制数为0~9,显示方式和十六进制数类似。modulehex_7seg(sev_seg,hex);outputreg[6:0]sev_seg;input[3:0]DEC;always@(DEC)begin case(DEC)//sev_seg的显示顺序为abcdefg,七段码共阳极 4'h0:sev_seg=7'b0000001; 4'h1:sev_seg=7'b1001111; 4'h2:sev_seg=7'b0010010; 4'h3:sev_seg=7'b0000110; 4'h4:sev_seg=7'b1001100; 4'h5:sev_seg=7'b0100100; 4'h6:sev_seg=7'b0100000; 4'h7:sev_seg=7'b0001111; 4'h8:sev_seg=7'b0000000; 4'h9:sev_seg=7'b0000100; default:sev_seg=7'b1; endcaseendendmodule习题5-7用VerilogHDL实现两位十进制数在七段数码管上的显示。参考答案:两位十进制数分别在两个七段数码管上显示“十位”和“个位”数字。modulecode_2_SEG7(count32,seg10,seg01);input[4:0]count32;output[6:0]seg10,seg01;SEG7u1(count32/10,seg10);//显示十位数SEG7u2(count32%10,seg01);//显示个位数endmodule//子模块:七段数码管显示moduleSEG7(count,SSEG);input[3:0]count;outputreg[6:0]SSEG;//a~g,七段码共阴极always@(count)begin case(count) 8'd0:SSEG<=8'b1111110;//unitsis0 8'd1:SSEG<=8'b0110000;//unitsis1 8'd2:SSEG<=8'b1101101;//unitsis2 8'd3:SSEG<=8'b1111001;//unitsis3 8'd4:SSEG<=8'b0110011;//unitsis4 8'd5:SSEG<=8'b1011011;//unitsis5 8'd6:SSEG<=8'b1011111;//unitsis6 8'd7:SSEG<=8'b1110000;//unitsis7 8'd8:SSEG<=8'b1111111;//unitsis8 8'd9:SSEG<=8'b1111011;//unitsis9 default:SSEG<=8'b0; endcaseendendmodule习题5-8用VerilogHDL设计带有消隐控制端RBI/RBO的七段数码管显示器,使多个数码管显示时不需要显示的零可以隐藏。参考答案:RBI(RippleBlankingInput,脉动消隐输入)和RBO(RippleBlankingOutput,脉动消隐输出)是用于多位数码管显示时,实现前导零消隐的控制信号,核心作用是隐藏无意义的高位零,让显示更简洁。多位级联时,高位RBO直接接低位RBI。最高位的RBI必须接0才能开启前导零消隐功能;若最高位RBI接1,则所有位的0都会正常显示。实现代码如下:moduleseg_RBI_RBO(digit,RBI,segments,RBO);input[3:0]digit;//输入BCD码inputRBI;//消隐控制,低电平有效outputreg[6:0]segments;//输出段码,低电平点亮outputregRBO;//消隐输出,低电平有效always@(*)beginif(RBI==1'b0&&digit==4'd0)beginsegments=7'b1111111;//消隐RBO=1'b0;//下一位也消隐end elsebegincase(digit)4'd0:segments=7'b0000001;//七段码4'd1:segments=7'b1001111;4'd2:segments=7'b0010010;4'd3:segments=7'b0000110;4'd4:segments=7'b1001100;4'd5:segments=7'b0100100;4'd6:segments=7'b0100000;4'd7:segments=7'b0001111;4'd8:segments=7'b0000000;4'd9:segments=7'b0000100;default:segments=7'b1111111;endcaseRBO=1'b1;//不输出消隐endendendmodule习题5-9思考:格雷码(循环二进制单位距离码)是任意两个相邻数的代码只有一位二进制数不同的编码,位值计算式为G其中G表示格雷码,B表示二进制码。用VerilogHDL设计二进制转化成4位格雷码的电路。参考答案: 根据逻辑表达式写出二进制转化成4位格雷码的真值表如下。二进制格雷码00000000000100010010001100110010010001100101011101100101011101001000110010011101101011111011111011001010110110111110100111111000可用行为描述case语句写出代码:modulebinary2Gray(bin4,Gray);input[3:0]bin4;outputreg[3:0]Gray;always@(*)begin case(bin4) 4’d0:Gray=0000; 4’d1:Gray=0001;4’d2:Gray=0011;4’d3:Gray=0010;4’d4:Gray=0110;4’d5:Gray=0111;4’d6:Gray=0101;4’d7:Gray=0100;4’d8:Gray=1100;4’d9:Gray=1101;4’d10:Gray=1111;4’d11:Gray=1110;4’d12:Gray=1010;4’d13:Gray=1011;4’d14:Gray=1001;4’d15:Gray=1000;default:Gray=4’bz;endendmodule习题5-10用VerilogHDL设计1位半减器?其真值表如表5-10所示。表5-101位半减器真值表输入输出xyDiffb0000011110101100参考答案: 根据真值表可以总写出逻辑表达式,用数据流描述如下:modulehalf_subtractor(x,y,Diff,b);inputx,y;//输入outputDiff,b;//输出:差值、借位assignDiff=x^y;//异或运算assignb=~x&y;//与非运算endmodule习题5-11用VerilogHDL设计1位全减器?全减器的真值表如表5-11所示。表5-111位全减器真值表输入输出xybo_inDiffbo_out0000000111010110110110010101001100011111参考答案:根据真值表可以总写出逻辑表达式,用数据流描述如下:modulefull_subtractor(x,y,bo_in,Diff,bo_out);inputx,y,bo_in,;//输入:被减数、减数、低位借位outputDiff,bo_out;//输出:差值、高位借位assignDiff=x^y^bo_in;assignbo_out=(~x&y)|(~x&bo_in)|(y&bo_in);endmodule习题5-12用VerilogHDL设计一个4位奇偶校验生成器,要求当输入数据中1的个数为奇数时输出1,否则输出0。参考答案:奇偶校验位可以通过对所有输入位进行异或(XOR)运算得到。偶数个1,异或结果为0,否则为1。代码如下:moduleparity_generator_4bit(data,parity);input[3:0]data;outputparity;assignparity=data[3]^data[2]^data[1]^data[0];endmodule习题5-13设计一个4位算术逻辑单元(ALU),要求支持加(add)、减(sub)、与(and)、或(or)四种操作,通过2位控制信号S1和S0选择运算模式。参考答案:加减运算涉及进位和借位,与或运算不涉及。代码如下:modulealu_4bit(A,B,S1,S0,result,carry);input[3:0]A,B;//4位操作数inputS1,S0;//2位操作控制信号outputregresult;//4位运算结果outputregcarry;//进位/借位输出wire[4:0]sum,difference;//和与差assignsum={1'b0,A}+{1'b0,B};//加法计算assigndifference={1'b0,A}-{1'b0,B};//减法计算always@(*)begincase({S1,S0})2'b00:begin//加法result=sum[3:0];carry=sum[4];end2'b01:begin//减法result=difference[3:0];carry=difference[4];//借位end2'b10:begin//与运算result=A&B;carry=1'b0;//逻辑运算无进位/借位end2'b11:begin//或运算result=A|B;carry=1'b0;//逻辑运算无进位/借位enddefault:beginresult=4'b0000;carry=1'b0;endendcaseendendmodule习题5-14分别使用行为建模和模块例化的方式设计一个T触发器。参考答案:T触发器是一种常用的时序逻辑元件,其特性如下:当输入T=0时,在时钟触发沿,触发器的输出Q保持原值不变。当输入T=1时,在时钟触发沿,触发器的输出Q翻转(Toggle)。根据其特性编写Verilog程序如下:①行为建模modulet_ff_behavioral(clk,rst_n,T,Q,Q_n);inputclk,rst_n,T;outputQ,Q_n;always@(posedgeclkornegedgerst_n)beginif(!rst_n)beginQ<=1'b0;endelsebeginif(t)Q<=~Q;//T=1时翻转elseQ<=Q;//T=0时保持endendassignQ_n=~Q;endmodule②模块例化(结构化建模)模块例化方式通过组合D触发器实现T触发器。moduled_ff(clk,rst_n,d,q);//D触发器inputclk,rst_n,d;outputregq;always@(posedgeclkornegedgerst_n)beginif(!rst_n)q<=1'b0;elseq<=d;endendmodulemodulet_ff_instantiation(clk,rst_n,T,Q,Q_n);inputclk,rst_n,t,outputQ,Q_n;wired;assignd=Q^T;assignQ_n=~Q;d_ffd_ff_inst(.clk(clk),.rst_n(rst_n),.d(d),.Q(Q));//例化D触发器endmodule习题5-15设计一个VerilogHDL程序实现SIPO存储功能,使8位数据依次输入,存满之后并行输出。参考答案:SIPO(Serial-InParallel-Out,串入并出)存储功能,实现8位数据串行输入和寄存器存满8位数据后的一次性并行输出。modulesipo_8bit(inputclk,inputrst_n,inputdin,outputreg[7:0]dout,outputregvalid//输出有效标志(存满8位后单周期高电平));reg[2:0]cnt;always@(posedgeclkornegedgerst_n)beginif(!rst_n)begin//复位初始化:计数器清零、输出清零、有效标志置低dout<=8'b0;valid<=1'b0;cnt<=3'b0;endelsebegindout<={dout[6:0],din};//计数器与有效标志控制逻辑if(cnt==3'd7)begin//第8个数据已存入,此时dout为完整8位数据valid<=1'b1;//输出有效标志置高(单周期脉冲)cnt<=3'b0;end//计数器清零,准备下一轮存储elsebegin//未存满8位,有效标志保持低电平,计数器递增valid<=1'b0;cnt<=cnt+1'b1;endendendendmodule习题5-16基于74HC161功能使用VerilogHDL设计一个十进制计数器,功能表如表5-12所示。表5-1274HC161功能表CLRCLKLOADENPENTDCBAQDQCQBQARCO0xxxxx000001↑0xxDCBADCBA1↑111x计数1↑10xx保持1↑1x0x保持0参考答案:基于74161功能设计十进制计数器,可以使用结构化建模方式,也可以在设计74161功能模块上增加设计使之实现十进制。moduleM10_counter(CLR,CLK,LOAD,ENP,ENT,DCBA,Q,RCO);//基于74161功能设计十进制计数器inputCLR,CLK,LOAD,ENP,ENT;input[3:0]DCBA;//4位数据输入outputreg[3:0]Q;outputRCO; always@(posedgeCLK,negedgeCLR)begin if(!CLR)begin Q<=4’b0; RCO<=1’b0; endelseif(LOAD) Q<=DCBA; elseif(ENP&ENT==1’b1) if(Q==4’b1001)begin Q<=Q+1; RCO<=1’b1; endelsebegin Q<=Q;RCO<=1’b1; endendendmodule习题5-17使用VerilogHDL语言设计一个带有异步复位和同步使能端口的N进制计数器。参考答案: N进制计数器重点在于参数N的设定。N是计数范围,对应所需的输出端口位数通常取log2(N),如16进制计数器需要4位数,程序中使用Verilog-2001标准中的系统函数$clog2,用于计算以2为底的对数的上限值。代码如下:modulen_counter(inputclk,inputrst_n,inputen,outputreg[$clog2(N-1):0]q,outputregco);parameterN=10;//计数范围always@(posedgeclkornegedgerst_n)beginif(!rst_n)beginq<='b0;co<=1'b0;endelseif(en)beginif(q==N-1)beginq<='b0;//归零计数器co<=1'b1;//产生单周期进位脉冲endelsebeginq<=q+1'b1;//正常递增co<=1'b0;endendelsebeginq<=q;co<=1'b0;//强制清零防止残留脉冲endendendmodule习题5-18使用VerilogHD实现带使能的4位环形计数器,使能低电平有效。计数器初始状态为0001,输出为0001→0010→0100→1000→0001...参考答案:环形计数器通过循环移位操作实现1在各个位之间顺序游走。程序如下:modulering_counter_4bit(clk,rst_n,en_n,q);inputclk,rst_n,en_n;outputreg[3:0]q;always@(posedgeclkornegedgerst_n)beginif(!rst_n)beginq<=4'b0001;endelseif(!en_n)beginq<={q[2:0],q[3]};end//循环左移elsebeginq<=q;endendendmodule习题5-19使用VerilogHDL设计一个N分频的分频电路。参考答案:教材中提供了基本的分频电路设计程序,这里需要把分频的具体数值用参数N代替以实现标准化。分频电路与计数器相关,如果是N分频,即分频系数为N,那么计数器的范围是0到N-1,计数器位数为log2(N),写程序需要使用系统函数$clog2。modulen_divider#(parameterN=50)(inputrst_n,inputclk_in,outputregclk_out);reg[$clog2(N)-1:0]cnt;//精确位宽always@(posedgeclk_inornegedgerst_n)beginif(!rst_n)begincnt<='b0;clk_out<=1'b0;endelseif(cnt==N-1)begin//唯一合法翻转点cnt<='b0;clk_out<=~clk_out;//单次翻转保证N分频endelsebegincnt<=cnt+1'b1;endendendmodule习题5-20使用结构化描述的方式设计二十四进制BCD码计数器。参考答案: 二十四进制BCD码计数器需要用到两组BCD码,十位数BCD码计数范围是0~2,个位数BCD码计数范围是0~9。它可以由两个74161器件和一些基本逻辑门构成,采用结构化描述方式,分为两个层次进行模块设计。 程序如下:moduleLS74161(inputCLK,inputCR,//异步清零,低电平有效inputLD,//同步置数,低电平有效inputET,//计数使能1,高电平有效inputEP,//计数使能2,高电平有效input[3:0]D,//置数数据outputreg[3:0]Q);always@(posedgeCLKornegedgeCR)beginif(!CR)begin//异步清零,优先级最高Q<=4'b0000;endelseif(!LD)begin//同步置数Q<=D;endelseif(ET&&EP)begin//计数Q<=Q+1'b1;endelsebegin//保持Q<=Q;endendendmodulemoduleBCD_M24(inputclk,inputrst_n,output[3:0]QH,//十位:0~2(BCD码)output[3:0]QL,//个位:0~9(BCD码)outputcycle_end//循环溢出标志);//内部同步控制信号:所有控制信号通过时钟同步生成,避免组合逻辑毛刺regstate_23;//23状态标志:1=当前为23,0=非23regql_en_sync;//个位计数使能,同步信号regqh_en_sync;//十位计数使能,同步信号regcr_ctrl_sync;//清零控制同步信号(转换为低有效,驱动CR)//核心同步逻辑:在时钟沿同步更新所有控制信号,避免组合逻辑风险always@(posedgeclkornegedgerst_n)beginif(!rst_n)beginstate_23<=1'b0;ql_en_sync<=1'b0;qh_en_sync<=1'b0;cr_ctrl_sync<=1'b1;//CR高电平,不触发清零endelsebegin//同步检测23状态:QH=2(0010)且QL=9(1001)state_23<=(QH==4'd2)&&(QL==4'd9);//生成同步清零控制信号:23状态时,下一个时钟沿触发清零(CR低有效)if(state_23)begincr_ctrl_sync<=1'b0;endelsebegincr_ctrl_sync<=1'b1;end//生成个位计数使能:非23状态,且个位未计满9时,允许计数if(!state_23)beginql_en_sync<=(QL!=4'd9);endelseql_en_sync<=1'b0;//23状态时,禁止个位计数,等待清零//生成十位计数使能:非23状态,且个位计满9时,允许十位进位if(!state_23)beginqh_en_sync<=(QL==4'd9);endelseqh_en_sync<=1'b0;//23状态时,禁止十位进位,等待清零endend//清零信号:同步控制信号转异步清零所需的低有效信号(直接输出到CR)wireCR=cr_ctrl_sync?1'b1:1'b0;//同步信号转CR:cr_ctrl_sync=1时,CR=1不触发清零;cr_ctrl_sync=0时,CR=0触发清零//计数使能:同步使能信号直接输出到ET/EP(高有效,)wireql_en=ql_en_sync;//个位使能:同步信号直接输出wireqh_en=qh_en_sync;//十位使能:同步信号直接输出//个位计数器(0~9)LS74161U_QL(.CLK(clk),.CR(CR),//异步清零,低有效,由同步信号控制.LD(1'b1),//同步置数禁用,固定为高电平.ET(ql_en),.EP(ql_en),.D(4'b0000),//置数数据,仅清零或置数生效.Q(QL));//十位计数器(0~2)LS74161U_QH(.CLK(clk),.CR(CR),//与个位共用清零信号,同步清零.LD(1'b1),//同步置数禁用.ET(qh_en),.EP(qh_en),.D(4'b0000),.Q(QH));//循环溢出标志:同步检测23状态,与时钟同步,无毛刺assigncycle_end=state_23;endmodule习题5-21设计可调占空比的PWM发生器模块,要求系统时钟100MHz,输出频率1kHz,占空比通过4位输入信号调节(16级可调)。参考答案: PWM发生器模块的系统时钟100MHz,输出频率1kHz,那么一个PWM周期的系统时钟周期数为:N=fclk/fpwm=100MHz​/1kHz=100000占空比16级可调节,需设定一个四位的输入值duty作为等级调控,实际实现的占空比为:D=(duty+1)/16每100000个系统时钟周期对应一个PWM模块时钟周期,前N×D个系统时钟周期对应PWM输出高电平,之后是低电平。例如duty=7即第8级,占空比为D=(7+1)/16=50%,在100000个系统时钟周期里,前50000个周期里PWM输出为高电平,后50000个周期里PWM输出为低电平。因此需要设定一个变量C=N×D为比较阈值,便于控制计数器的计数范围。程序代码如下://PWM发生器模块:系统时钟100MHz,输出频率1kHz,4位输入实现16级占空比调节modulepwm_generator(inputclk,//系统时钟:100MHzinputrst_n,//异步复位,低电平有效input[3:0]duty,//4位占空比调节输入,范围0~15outputregpwm_out//PWM输出信号,频率1kHz,占空比可调);//参数定义。一个PWM周期对应的系统时钟数:100MHz/1kHz=100000parameterN=100000;//计数器位宽:N=100000,二进制为17位(2^16=65536<100000,2^17=131072>100000)parameterCNT_WIDTH=17;reg[CNT_WIDTH-1:0]cnt;//周期计数器,0~N-1循环计数reg[CNT_WIDTH-1:0]compare_val;//比较阈值:cnt<compare_val时输出高电平reg[3:0]duty_sync;//占空比输入同步信号,消除异步毛刺//输入信号同步always@(posedgeclkornegedgerst_n)beginif(!rst_n)beginduty_sync<=4'd0;endelsebeginduty_sync<=duty;//时钟沿同步锁存duty,消除异步跳变毛刺endend//比较阈值计算//计算逻辑:占空比D=(duty+1)/16,阈值C=N*D=N*(duty+1)/16always@(posedgeclkornegedgerst_n)beginif(!rst_n)begincompare_val<=0;endelsebegincompare_val<=(N*(duty_sync+1))/16;endend//周期计数器(循环计数,实现1kHz频率输出)always@(posedgeclkornegedgerst_n)beginif(!rst_n)begincnt<=0;endelsebeginif(cnt==N-1)begincnt<=0;//计数到N-1后清零,一个PWM周期结束endelsebegincnt<=cnt+1'b1;//累加计数endendend//PWM输出控制always@(posedgeclkornegedgerst_n)beginif(!rst_n)beginpwm_out<=1'b0;endelsebegin//计数器小于阈值时输出高电平,否则输出低电平if(cnt<compare_val)beginpwm_out<=1'b1;endelsebeginpwm_out<=1'b0;endendendendmodule习题5-22为简易数字时钟设计一个基于24小时制定时的闹钟。参考答案:在教材第5章例5.21的基础上增加一个定时闹钟。//闹钟模块:支持时、分设置,到达设定时间后闹铃输出modulealarm_clock(inputclk,//1Hz时钟inputreset,//系统复位inputset_alarm,//设置闹钟使能(高电平有效)input[5:0]alarm_hour_in,//闹钟小时设置(0~23)input[5:0]alarm_min_in,//闹钟分钟设置(0~59)input[5:0]cur_hour,//当前小时(来自时钟模块)input[5:0]cur_min,//当前分钟(来自时钟模块)outputregalarm_out,//闹铃输出(高电平有效)outputregalarm_en//闹钟使能状态(1=已启用));//闹钟寄存器:存储设定的时间reg[5:0]alarm_hour_reg;reg[5:0]alarm_min_reg;//闹钟触发标志:用于产生持续1分钟的闹铃regalarm_triggered;reg[5:0]alarm_cnt;//闹铃计时器(0~59)//闹钟设置逻辑(仅在set_alarm有效时更新)always@(posedgeclkornegedgereset)beginif(!reset)beginalarm_hour_reg<=6'd0;alarm_min_reg<=6'd0;alarm_en<=1'b0;endelseif(set_alarm)begin//设置闹钟:锁存输入值,并启用闹钟alarm_hour_reg<=alarm_hour_in;alarm_min_reg<=alarm_min_in;alarm_en<=1'b1;endend//闹钟触发和闹铃控制逻辑always@(posedgeclkornegedgereset)beginif(!reset)beginalarm_triggered<=1'b0;alarm_cnt<=6'd0;alarm_out<=1'b0;endelsebegin//默认值:闹铃结束时自动清零if(alarm_cnt==6'd59&&alarm_triggered)beginalarm_out<=1'b0;alarm_triggered<=1'b0;alarm_cnt<=6'd0;endelseif(alarm_triggered)begin//闹铃持续中,计数器递增alarm_cnt<=alarm_cnt+1'b1;alarm_out<=1'b1;endelseif(alarm_en&&cur_hour==alarm_hour_reg&&cur_min==alarm_min_reg)begin//到达闹钟设定时间,触发闹铃alarm_triggered<=1'b1;alarm_out<=1'b1;alarm_cnt<=6'd0;endelsealarm_out<=1'b0;endendendmodule//改进后的计时模块(增加分钟/小时输出,供闹钟使用)modulecount_time_adv(outputreg[5:0]second,minute,hour,output[3:0]dot,inputclk,//1Hz时钟inputreset);always@(posedgeclkornegedgereset)beginif(!reset)beginsecond<=6'b0;minute<=6'b0;hour<=6'b0;endelseif(hour==23&&minute==59&&second==59)beginsecond<=6'b0;minute<=6'b0;hour<=6'b0;endelseif(minute==59&&second==59)beginsecond<=6'b0;minute<=6'b0;hour<=hour+1'b1;endelseif(second==59)beginsecond<=6'b0;minute<=minute+1'b1;endelsebeginsecond<=second+1'b1;endend//点闪烁(每2秒闪烁一次)regdd;always@(posedgeclkornegedgereset)beginif(!reset)dd<=1'b0;elsedd<=~dd;endassigndot={4{dd}};endmodule//七段译码显示模块moduledisplay(outputreg[6:0]seg_h,seg_l,input[5:0]digit);always@(*)begincase(digit/10)//十位数3'b000:seg_h=7'b0000001;3'b001:seg_h=7'b1001111;3'b010:seg_h=7'b0010010;3'b011:seg_h=7'b0000110;3'b100:seg_h=7'b1001100;3'b101:seg_h=7'b0100100;default:seg_h=7'b1111111;//熄灭endcasecase(digit%10)//个位数4'h0:seg_l=7'b0000001;4'h1:seg_l=7'b1001111;4'h2:seg_l=7'b0010010;4'h3:seg_l=7'b0000110;4'h4:seg_l=7'b1001100;4'h5:seg_l=7'b0100100;4'h6:seg_l=7'b0100000;4'h7:seg_l=7'b0001111;4'h8:seg_l=7'b0000000;4'h9:seg_l=7'b0000100;default:seg_l=7'b1111111;endcaseendendmodule//闹钟设置模块:通过按键选择时/分并递增modulealarm_setter(inputclk,inputreset,inputset_mode,//设置模式选择(循环:时→分→完成)inputinc,//递增按键outputreg[5:0]alarm_hour,outputreg[5:0]alarm_min,outputregset_alarm//闹钟设置完成信号);reg[1:0]mode;//0:空闲,1:设置小时,2:设置分钟,3:完成always@(posedgeclkornegedgereset)beginif(!reset)beginmode<=2'b0;alarm_hour<=6'd0;alarm_min<=6'd0;set_alarm<=1'b0;endelsebeginset_alarm<=1'b0;//默认不触发case(mode)2'b00:begin//空闲等待if(set_mode)beginmode<=2'b01;endend2'b01:begin//设置小时if(inc)beginif(alarm_hour==6'd23)alarm_hour<=6'd0;elsealarm_hour<=alarm_hour+1'b1;endif(set_mode)beginmode<=2'b10;endend2'b10:begin//设置分钟if(inc)beginif(alarm_min==6'd59)alarm_min<=6'd0;elsealarm_min<=alarm_min+1'b1;endif(set_mode)beginmode<=2'b11;endend2'b11:begin//完成设置set_alarm<=1'b1;mode<=2'b00;enddefault:mode<=2'b00;endcaseendendendmodule//顶层模块:带闹钟功能的数字时钟moduledigital_clock_with_alarm(//显示输出output[6:0]seg_h1,seg_h0,//小时十位、个位output[6:0]seg_m1,seg_m0,//分钟十位、个位output[6:0]seg_s1,seg_s0,//秒十位、个位output[3:0]dot,//闪烁点outputalarm_led,//闹铃输出(接蜂鸣器或LED)//闹钟设置输入inputset_alarm_btn,//闹钟设置按键(进入设置模式)inputinc_btn,//递增按键(设置时/分)//系统输入inputclk,//1Hz时钟inputreset//复位);//计时模块输出wire[5:0]second,minute,hour;//闹钟设置模块输出wire[5:0]alarm_hour,alarm_min;wireset_alarm;//闹钟模块输出wirealarm_out;wirealarm_en;//实例化计时模块count_time_advu_count(.second(second),.minute(minute),.hour(hour),.dot(dot),.clk(clk),.reset(reset));//实例化闹钟设置模块alarm_setteru_setter(.clk(clk),.reset(reset),.set_mode(set_alarm_btn),.inc(inc_btn),.alarm_hour(alarm_hour),.alarm_min(alarm_min),.set_alarm(set_alarm));//实例化闹钟模块alarm_clocku_alarm(.clk(clk),.reset(reset),.set_alarm(set_alarm),.alarm_hour_in(alarm_hour),.alarm_min_in(alarm_min),.cur_hour(hour),.cur_min(minute),.alarm_out(a

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论