verilog的15个经典设计实例
Verilog设计练习十例及答案
设计练习进阶前言:在前面九章学习的基础上,通过本章的练习,一定能逐步掌握Verilog HDL设计的要点。
我们可以先理解样板模块中每一条语句的作用,然后对样板模块进行综合前和综合后仿真,再独立完成每一阶段规定的练习。
当十个阶段的练习做完后,便可以开始设计一些简单的逻辑电路和系统。
很快我们就能过渡到设计相当复杂的数字逻辑系统。
当然,复杂的数字逻辑系统的设计和验证,不但需要系统结构的知识和经验的积累,还需要了解更多的语法现象和掌握高级的Verilog HDL系统任务,以及与C语言模块接口的方法(即PLI),这些已超出的本书的范围。
有兴趣的同学可以阅读Verilog语法参考资料和有关文献,自己学习,我们将在下一本书中介绍Verilog较高级的用法。
练习一.简单的组合逻辑设计目的: 掌握基本组合逻辑电路的实现方法。
这是一个可综合的数据比较器,很容易看出它的功能是比较数据a与数据b,如果两个数据相同,则给出结果1,否则给出结果0。
在Verilog HDL中,描述组合逻辑时常使用assign 结构。
注意equal=(a==b)1:0,这是一种在组合逻辑实现分支判断时常使用的格式。
模块源代码:" qual(equal),.a(a),.b(b)); 简单时序逻辑电路的设计目的:掌握基本时序逻辑电路的实现。
在Verilog HDL中,相对于组合逻辑电路,时序逻辑电路也有规定的表述方式。
在可综合的Verilog HDL模型,我们通常使用always块和@(posedge clk)或@(negedge clk)的结构来表述时序逻辑。
下面是一个1/2分频器的可综合模型。
eset(reset),.clk_in(clk),.clk_out(clk_out));endmodule仿真波形:练习:依然作clk_in的二分频clk_out,要求输出与上例的输出正好反相。
编写测试模块,给出仿真波形。
练习三. 利用条件语句实现较复杂的时序逻辑电路目的:掌握条件语句在Verilog HDL中的使用。
Verilog的135个经典设计实例
Verilog的135个经典设计实例1、立即数放大器:立即数放大器是一种用于将输入电平放大到更高电平的电路,它可以实现任意输入到输出的映射,并且可以在Verilog中使用。
立即数放大器的Verilog实现如下:module immedamp(in, out);input in;output out;reg [3:0] immed;assign out = immed[3];begincase (in)4'b0000: immed = 4'b1000;4'b0001: immed = 4'b1001;4'b0010: immed = 4'b1010;4'b0011: immed = 4'b1011;4'b0100: immed = 4'b1100;4'b0101: immed = 4'b1101;4'b0110: immed = 4'b1110;4'b0111: immed = 4'b1111;4'b1000: immed = 4'b1000;4'b1001: immed = 4'b1001;4'b1010: immed = 4'b1010;4'b1011: immed = 4'b1011;4'b1100: immed = 4'b1100;4'b1101: immed = 4'b1101;4'b1110: immed = 4'b1110;4'b1111: immed = 4'b1111;endcaseendendmodule2、多路复用器:多路复用器是一种用于将多个输入选择转换为单个输出的电路,它可以实现由多种方式选择的输出,并可以使用Verilog实现。
verilog_FPGA实例
一、组合逻辑实验 (2)实验13X8译码器程序 (2)实验2二-十进制译码器 (2)实验3BCD码—七段数码管显示译码器 (3)实验48-3编码器 (4)实验58-3优先编码器 (4)实验6十—二进制编码器 (5)实验7三选一数据选择器 (5)实验8半加器 (6)实验9全加器 (7)实验10半减器 (8)实验11全减器 (8)实验12多位数值比较器 (9)实验13奇偶校验 (9)实验14补码生成 (10)实验158位硬件加法器的设计 (10)实验164位并行乘法器 (10)实验17七人表决器 (10)实验18格雷码变换 (11)二、时序逻辑实验 (11)实验1D触发器 (11)实验2JK触发器 (12)实验3四位移位寄存器 (12)实验4异步计数器 (13)实验5同步计数器 (14)实验6可逆计数器 (15)实验7步长可变的加减计数器 (16)实验8含异步清0和同步时钟使能的4位加法计数器 (17)实验9顺序脉冲发生器 (18)实验10序列信号发生器 (18)实验11用状态机实现串行数据检测器 (19)实验12分频器 (20)实验13Moore状态机 (21)实验14Mealy状态机 (23)实验15三层电梯 (24)实验16性线反馈移位寄存器(LFSR)设计 (32)实验17正负脉宽数控调制信号发生器 (32)三、存储器设计 (34)实验1只读存储器(ROM) (34)实验2SRAM (34)实验3FIFO (35)四、扩展接口实验 (39)实验1流水灯 (39)实验2VGA彩色信号显示控制器设计 (40)实验3PS/2键盘接口实验 (48)实验4PS/2鼠标接口实验 (49)五、综合实验 (58)实验1函数发生器 (58)实验2自动售货机 (61)实验3移位相加4位硬件乘法器电路设计 (63)一、组合逻辑实验实验13X8译码器程序//Decoder:3-to8decoder with an enable contmodule decoder(y,en,a);output[7:0]y;input en;input[2:0]a;reg[7:0]y;always@(en or a)//EN和A是敏感信号if(!en)//如果使能信号为低,无效y=8'b1111_1111;elsecase(a)3'b000:y=8'b1111_1110;//最低位为低3'b001:y=8'b1111_1101;3'b010:y=8'b1111_1011;3'b011:y=8'b1111_0111;3'b100:y=8'b1110_1111;3'b101:y=8'b1101_1111;3'b110:y=8'b1011_1111;3'b111:y=8'b0111_1111;default:y=8'bx;//否则为不确定信号endcaseendmodule实验2二-十进制译码器//Decoder:binary-to decimal decoder with an enable controlmodule b2d(y,en,a);output[7:0]y;input en;input[3:0]a;reg[7:0]y;always@(en or a)//EN和A是敏感信号if(!en)//如果使能信号为低,无效y=8'b1111_1111;elsebeginif(a>9)y<=a+6;//这里完成了二进制到十进制的译码,elsey<=a;end//为了方便在平台上进行观察验证///这里把数据的个位和十位分别用4个LED进行显示,均为二进制Endmodule实验3BCD码—七段数码管显示译码器module decode4_7(decodeout,a);output[6:0]decodeout;input[3:0]a;reg[6:0]decodeout;always@(a)begincase(a)//用case语句进行译码abcdefg4'h0:decodeout=7'b1111110;4'h1:decodeout=7'b0110000;4'h2:decodeout=7'b1101101;4'h3:decodeout=7'b1111001;4'h4:decodeout=7'b0110011;4'h5:decodeout=7'b1011011;4'h6:decodeout=7'b1011111;4'h7:decodeout=7'b1110000;4'h8:decodeout=7'b1111111;4'h9:decodeout=7'b1111011;4'ha:decodeout=7'b1110111;4'hb:decodeout=7'b0011111;4'hc:decodeout=7'b1001110;4'hd:decodeout=7'b0111101;4'he:decodeout=7'b1001111;4'hf:decodeout=7'b1000111;default:decodeout=7'bx;endcaseendendmodule实验48-3编码器//a8-3codermodule coder(dout,din);output[2:0]dout;input[7:0]din;reg[2:0]dout;always@(din)case(din)8'b1111_1110:dout<=3'b000;8'b1111_1101:dout<=3'b001;8'b1111_1011:dout<=3'b010;8'b1111_0111:dout<=3'b011;8'b1110_1111:dout<=3'b100;8'b1101_1111:dout<=3'b101;8'b1011_1111:dout<=3'b110;8'b0111_1111:dout<=3'b111;default:dout<=3'bx;endcaseendmodule实验58-3优先编码器module encoder(d0,d1,d2,d3,d4,d5,d6,d7,x,y,v); output x,y,v;input d0,d1,d2,d3,d4,d5,d6,d7;reg x,y,v;always@(d0or d1or d2or d3or d4or d5or d6or d7) if(d7==0){x,y,v}=3'b111;else if(d6==0){x,y,v}=3'b110;else if(d5==0){x,y,v}=3'b101;else if(d4==0){x,y,v}=3'b100;else if(d3==0){x,y,v}=3'b011;else if(d2==0){x,y,v}=3'b010;else if(d1==0){x,y,v}=3'b001;else if(d0==0){x,y,v}=3'b000;else{x,y,v}=3'bxxx;endmodule实验6十—二进制编码器//decimal to binary encodermodule encoder(y,a);output[4:0]y;input[4:0]a;//input[4]为十位,[3:0]为个位?reg[4:0]y;always@(a)//A是敏感信号beginif(a>9)y<=a-6;//这里完成了十进制到二进制的编码,elsey<=a;end//为了方便在平台上进行观察验证///这里把数据的个位用4个2进制数据表示,十位用1bit进行显示;endmodule实验7三选一数据选择器module mux3to1(dout,a,b,c,sel);output[1:0]dout;input[1:0]a,b,c;input[1:0]sel;reg[1:0]dout;//RTL modelingalways@(a or b or c or sel)case(sel)2'b00:dout<=a;2'b01:dout<=b;2'b10:dout<=c;default:dout<=2'bx;endcaseendmodule//数据流方式描述的1位半加器module halfadder(sum,cout,a,b); input a,b;output sum,cout;assign sum=a^b;assign cout=a&b;//carry out; endmodule附录:各种不同的描述方式:1,调用门元件实现的1位半加器module half_add1(a,b,sum,cout); input a,b;output sum,cout;and(cout,a,b);xor(sum,a,b);endmodule2,采用行为描述的1位半加器module half_add3(a,b,sum,cout); input a,b;output sum,cout;reg sum,cout;always@(a or b)begincase({a,b})//真值表描述2'b00:begin sum=0;cout=0;end2'b01:begin sum=1;cout=0;end2'b10:begin sum=1;cout=0;end2'b11:begin sum=0;cout=1;end endcaseendendmodule3,采用行为描述的1位半加器module half_add4(a,b,sum,cout); input a,b;output sum,cout;reg sum,cout;always@(a or b)beginsum=a^b;cout=a&b;endendmodule//1bit full adder1位全加器module full_add(a,b,cin,sum,cout);input a,b,cin;output sum,cout;assign{cout,sum}=a+b+cin;endmodule附录:各种不同的描述方式实现的1位全加器1,调用门元件实现的1位全加器module full_add1(a,b,cin,sum,cout);input a,b,cin;output sum,cout;wire s1,m1,m2,m3;and(m1,a,b),(m2,b,cin),(m3,a,cin);xor(s1,a,b),(sum,s1,cin);or(cout,m1,m2,m3);endmodule2数据流描述的1位全加器module full_add2(a,b,cin,sum,cout);input a,b,cin;output sum,cout;assign sum=a^b^cin;assign cout=(a&b)|(b&cin)|(cin&a);endmodule3行为描述的1位全加器module full_add4(a,b,cin,sum,cout);input a,b,cin;output sum,cout;reg sum,cout;//在always块中被赋值的变量应定义为reg型reg m1,m2,m3;always@(a or b or cin)beginsum=(a^b)^cin;m1=a&b;m2=b&cin;m3=a&cin;cout=(m1|m2)|m3;endendmodule4混合描述的1位全加器module full_add5(a,b,cin,sum,cout);input a,b,cin;output sum,cout;reg cout,m1,m2,m3;//在always块中被赋值的变量应定义为reg型wire s1;xor x1(s1,a,b);//调用门元件always@(a or b or cin)//always块语句beginm1=a&b;m2=b&cin;m3=a&cin;cout=(m1|m2)|m3;endassign sum=s1^cin;//assign持续赋值语句endmodule实验10半减器module half_sub(diff,sub_out,x,y);output diff,sub_out;input x,y;reg diff,sub_out;//行为描述always@(x or y)case({x,y})2'b00:begin diff=0;sub_out=0;end2'b01:begin diff=1;sub_out=1;end2'b10:begin diff=1;sub_out=0;end2'b11:begin diff=0;sub_out=0;enddefault:begin diff=x;sub_out=x;endendcaseendmodule实验11全减器module full_sub(diff,sub_out,x,y,sub_in);output diff,sub_out;input x,y,sub_in;reg diff,sub_out;//行为描述always@(x or y or sub_in)case({x,y,sub_in})3'b000:begin diff=0;sub_out=0;end3'b001:begin diff=1;sub_out=1;end3'b010:begin diff=1;sub_out=1;end3'b011:begin diff=0;sub_out=1;end3'b100:begin diff=1;sub_out=0;end3'b101:begin diff=0;sub_out=0;end3'b110:begin diff=0;sub_out=0;end3'b111:begin diff=1;sub_out=1;enddefault:begin diff=x;sub_out=x;endendcaseendmodule实验12多位数值比较器module comp(ABB,AEB,ASB,A,B,I1,I2,I3);output ABB,AEB,ASB;//ABB表示A>B AEB表示A=B,ASB表示A<B;input[1:0]A,B;input I1,I2,I3;//I1表示上一级的A>B I2表示上一级的A=B,I3表示上一级的A<B; reg ABB,AEB,ASB;//行为描述always@(A or B or I1or I2or I3)if(A>B){ABB,AEB,ASB}=3'b100;else if(A<B){ABB,AEB,ASB}=3'b001;else//A=B,但是考虑到前一级的情况begin if(I1)//I1表示上一级的A>B{ABB,AEB,ASB}=3'b100;else if(I3){ABB,AEB,ASB}=3'b001;//I3表示上一级的A<B;else{ABB,AEB,ASB}=3'b010;endendmodule实验13奇偶校验//奇偶校验位产生器module parity(even_bit,odd_bit,input_bus);output even_bit,odd_bit;input[7:0]input_bus;assign odd_bit=^input_bus;//产生奇校验位assign even_bit=~odd_bit;//产生偶校验位endmodule实验14补码生成module compo(d_out,d_in);output[7:0]d_out;input[7:0]d_in;reg[7:0]d_out;always@(d_in)if(d_in[7]==1'b0)//正数,最高位为符号位,0说明是正数,正数补码是其本身d_out=d_in;else//负数d_out={d_in[7],~d_in[6:0]+1'b1};//最高位符号位不变,数据位加一构成其补码endmodule实验158位硬件加法器的设计//8位硬件加法器module add8b(cout,sum,a,b,cin);output[7:0]sum;output cout;input[7:0]a,b;input cin;assign{cout,sum}=a+b+cin;endmodule实验164位并行乘法器//4位并行乘法器module mult(outcome,a,b);parameter size=4;input[size:1]a,b;//两个操作数output[2*size:1]outcome;//结果assign outcome=a*b;//乘法运算符endmodule实验17七人表决器//for语句描述的七人投票表决器module voter7(pass,vote);output pass;//通过为高电平,否则为低电平input[6:0]vote;//7个投票输入#通过为高,否定为低reg[2:0]sum;integer i;reg pass;always@(vote)beginsum=0;for(i=0;i<=6;i=i+1)//for语句if(vote[i])sum=sum+1;if(sum[2])pass=1;//若超过4人赞成,则pass=1else pass=0;endendmodule实验18格雷码变换module BIN2GARY(EN,DATA_IN,DATA_OUT);input EN;input[3:0]DATA_IN;output[3:0]DATA_OUT;assign DATA_OUT[0]=(DATA_IN[0]^DATA_IN[1])&&EN; assign DATA_OUT[1]=(DATA_IN[1]^DATA_IN[2])&&EN; assign DATA_OUT[2]=(DATA_IN[2]^DATA_IN[3])&&EN; assign DATA_OUT[3]=DATA_IN[3]&&EN;endmodule二、时序逻辑实验实验1D触发器module myDFF(q,qn,d,clk,set,reset);input d,clk,set,reset;output q,qn;reg q,qn;always@(posedge clk)beginif(reset)beginq<=0;qn<=1;//同步清0,高电平有效endelse if(set)beginq<=1;qn<=0;//同步置1,高电平有效else beginq<=d;qn<=~d;endendendmodule实验2JK触发器//带异步清0、异步置1的JK触发器module JK_FF(CLK,J,K,Q,RS,SET);input CLK,J,K,SET,RS;output Q;reg Q;always@(posedge CLK or negedge RS or negedge SET) beginif(!RS)Q<=1'b0;else if(!SET)Q<=1'b1;else case({J,K})2'b00:Q<=Q;2'b01:Q<=1'b0;2'b10:Q<=1'b1;2'b11:Q<=~Q;default:Q<=1'bx;endcaseendendmodule实验3四位移位寄存器//4位移位寄存器module shifter(din,clk,clr,dout);input din,clk,clr;output[3:0]dout;reg[3:0]dout;always@(posedge clk)beginif(clr)dout<=4'b0;//同步清0,高电平有效elsebegindout<=dout<<1;//输出信号左移一位dout[0]<=din;//输入信号补充到输出信号的最低位endendmodule//分频器部分,获得便于试验观察的时钟信号module clk_div(clk_out,clk_in);input clk_in;output clk_out;reg clk_out;reg[25:0]counter;//50_000_000=1011_1110_1011_1100_0010_0000_00parameter cnt=50_000_000;///50MHz is the sys clk,50_000_000=2FAF080 always@(posedge clk_in)begincounter<=counter+1;if(counter==cnt/2-1)beginclk_out<=!clk_out;counter<=0;endendendmodule实验4异步计数器//行为描述方式实现的4位异步计数器module counter(clk,clr,q0,q1,q2,q3);input clk,clr;output q0,q1,q2,q3;reg q0,q1,q2,q3;//reg q0_t,q1_t,q2_t,q3_t;reg q0_r,q1_r,q2_r,q3_r;always@(posedge clk or negedge clr)if(!clr)q0_r<=0;elseq0_r<=!q0_r;always@(posedge q0_r or negedge clr)if(!clr)q1_r<=0;elseq1_r<=!q1_r;always@(posedge q1_r or negedge clr)if(!clr)q2_r<=0;elseq2_r<=!q2_r;always@(posedge q2_r or negedge clr)if(!clr)q3_r<=0;elseq3_r<=!q3_r;assign{q0,q1,q2,q3}={q0_r,q1_r,q2_r,q3_r};endmodule//分频器部分,获得便于试验观察的时钟信号module clk_div(clk_out,clk_in);input clk_in;output clk_out;reg clk_out;reg[25:0]counter;//50_000_000=1011_1110_1011_1100_0010_0000_00 parameter cnt=50_000_000;///50MHz is the sys clk,50_000_000=2FAF080 always@(posedge clk_in)begincounter<=counter+1;if(counter==cnt/2-1)beginclk_out<=!clk_out;counter<=0;endendendmodule实验5同步计数器Verilog HDL程序//带异步清0的同步计数器module counter(Q,CR,CLK);input CLK,CR;output[3:0]Q;reg[3:0]Q;always@(posedge CLK or negedge CR)beginif(!CR)Q<=4'b0000;elsebeginif(Q==15)Q<=0;else Q<=Q+1;endendendmodule//分频器部分,获得便于试验观察的时钟信号module clk_div(clk_out,clk_in);input clk_in;output clk_out;reg clk_out;reg[25:0]counter;//50_000_000=1011_1110_1011_1100_0010_0000_00 parameter cnt=50_000_000;///50MHz is the sys clk,50_000_000=2FAF080 always@(posedge clk_in)begincounter<=counter+1;if(counter==cnt/2-1)beginclk_out<=!clk_out;counter<=0;endendendmodule实验6可逆计数器//同步清零的可逆计数器module counter(Q,CLK,CR,UD);input CLK,CR,UD;output[3:0]Q;reg[3:0]cnt;initialbegincnt<=4'b0000;endassign Q=cnt;always@(posedge CLK)beginif(!CR)cnt<=4'b0000;//同步清0,低电平有效else beginif(UD)cnt=cnt+1;//加法计数else cnt=cnt-1;//减法计数endendendmodule//分频器部分,获得便于试验观察的时钟信号module clk_div(clk_out,clk_in);input clk_in;output clk_out;reg clk_out;reg[25:0]counter;//50_000_000=1011_1110_1011_1100_0010_0000_00parameter cnt=50_000_000;///50MHz is the sys clk,50_000_000=2FAF080 always@(posedge clk_in)begincounter<=counter+1;if(counter==cnt/2-1)beginclk_out<=!clk_out;counter<=0;endendendmodule实验7步长可变的加减计数器//同步清零的步长可变加减计数器module counter(Q,CLK,CR,UD,STEP);input CLK,CR,UD;input[1:0]STEP;output[3:0]Q;reg[3:0]cnt;initialbegincnt<=4'b0000;endassign Q=cnt;always@(posedge CLK)beginif(!CR)cnt<=4'b0000;//同步清0,低电平有效else beginif(UD)cnt=cnt+STEP;//加法计数else cnt=cnt-STEP;//减法计数endendendmodule//分频器部分,获得便于试验观察的时钟信号module clk_div(clk_out,clk_in);input clk_in;output clk_out;reg clk_out;reg[25:0]counter;//50_000_000=1011_1110_1011_1100_0010_0000_00 parameter cnt=50_000_000;///50MHz is the sys clk,50_000_000=2FAF080 always@(posedge clk_in)begincounter<=counter+1;if(counter==cnt/2-1)beginclk_out<=!clk_out;counter<=0;endendendmodule实验8含异步清0和同步时钟使能的4位加法计数器//实验八含异步清0和同步时钟使能的4位加法计数器module counter(clk,clear,en,qd);input clk,clear,en;output[3:0]qd;reg[3:0]cnt;always@(posedge clk or negedge clear)beginif(!clear)cnt<=4'h0;//异步清0,低电平有效else if(en)//同步使能cnt<=cnt+1;//加法计数endassign qd=cnt;endmodule//分频器部分,获得便于试验观察的时钟信号module clk_div(clk_out,clk_in);input clk_in;output clk_out;reg clk_out;reg[25:0]counter;//50_000_000=1011_1110_1011_1100_0010_0000_00parameter cnt=50_000_000;///50MHz is the sys clk,50_000_000=2FAF080 always@(posedge clk_in)begincounter<=counter+1;if(counter==cnt/2-1)beginclk_out<=!clk_out;counter<=0;endendendmodule实验9顺序脉冲发生器module pulsegen(q0,q1,q2,clk,rd);input clk,rd;output q0,q1,q2;reg q0,q1,q2;reg[2:0]x,y;always@(posedge clk)if(rd)beginy<=0;x<=3'b001;//give a initial valueendelsebeginy<=x;x<={x[1:0],x[2]};endassign{q0,q1,q2}=y;endmodule//分频器部分,获得便于试验观察的时钟信号module clk_div(clk_out,clk_in);input clk_in;output clk_out;reg clk_out;reg[25:0]counter;//50_000_000=1011_1110_1011_1100_0010_0000_00 parameter cnt=50_000_000;///50MHz is the sys clk,50_000_000=2FAF080 always@(posedge clk_in)begincounter<=counter+1;if(counter==cnt/2-1)beginclk_out<=!clk_out;counter<=0;endendendmodule实验10序列信号发生器module sequencer(y,clk,clr);input clk,clr;reg[7:0]yt;parameter s0=8'b1000_0000,//state0s1=8'b1100_0001,//state1s2=8'b1110_0000,//state2s3=8'b0001_0000,s4=8'b1111_1000,s5=8'b0000_0011,s6=8'b1111_0011,s7=8'b0000_0001;//state7always@(posedge clk)beginif(clr)yt<=s0;//clear to state0elsebegincase(yt)s0:yt<=s1;//change from state0to state1s1:yt<=s2;//s2:yt<=s3;//state2-->3s3:yt<=s4;s4:yt<=s5;s5:yt<=s6;s6:yt<=s7;s7:yt<=s0;//state7to state0default:yt<=s0;//default state7to s0endcaseendendassign y=yt;endmodule实验11用状态机实现串行数据检测器module detector(got,instr,clk);output got;input instr,clk;reg[2:0]cstate,nextstate;reg got;parameter s0=0,s1=1,s2=2,s3=3,s4=4,s5=5,s6=6,s7=7;//8statesalways@(posedge clk)//定义起始状态begincstate<=nextstate;endalways@(cstate or instr)//定义状态转换begincase(cstate)s0:begin got<=0;if(instr)nextstate<=s1;//detected the1st bit of1110010,i.e.,1,to s1else nextstate<=s0;//if not,stay hereends1:begin got<=0;if(instr)nextstate<=s2;//detected the2nd bit of1110010,i.e.,1,to s2else nextstate<=s0;//notends2:begin got<=0;if(instr)nextstate<=s3;//detected the3rd bit of1110010,i.e.,1else nextstate<=s0;//notends3:begin got<=0;if(!instr)nextstate<=s4;//detected the4th bit of1110010,i.e.,0else nextstate<=s2;//not,stayends4:begin got<=0;if(!instr)nextstate<=s5;//detected the5th bit of1110010,i.e.,0else nextstate<=s1;//notends5:begin got<=0;f(instr)nextstate<=s6;//detected the6th bit of1110010,i.e.,1else nextstate<=s0;//notends6:begin got<=0;if(!instr)nextstate<=s7;//detected the7th bit of1110010,i.e.,0else nextstate<=s2;//notends7:begin got<=1;//got the sequenceif(instr)nextstate<=s1;//detected the1st bit of1110010,i.e.,1,chagne to s1 else nextstate<=s0;//not,change to s0endendcaseendendmodule实验12分频器//分频器部分,获得便于试验观察的时钟信号,在实验台上进行观察module clk_div(clk_out,clk_in);input clk_in;output clk_out;reg clk_out;reg[25:0]counter;//50_000_000=1011_1110_1011_1100_0010_0000_00 parameter cnt=50_000_000;///50MHz is the sys clk,50_000_000=2FAF080 always@(posedge clk_in)begincounter<=counter+1;if(counter==cnt/2-1)beginclk_out<=!clk_out;counter<=0;endendendmodule//分频器部分用于设计仿真,10分频module clk_diver(clk_out,clk_in);input clk_in;output clk_out;reg clk_out;reg[4:0]counter;//parameter cnt=10;///10分频always@(posedge clk_in)begincounter<=counter+1;if(counter==cnt/2-1)beginclk_out<=!clk_out;counter<=0;endendendmodule实验13Moore状态机module moore(dataout,clk,datain,reset);output[3:0]dataout;input[1:0]datain;input clk,reset;parameter s0=2'b00,//采用格雷码编码s1=2'b01,s2=2'b11,s3=2'b10;reg[1:0]cstate,nstate;reg[3:0]dataout;always@(posedge clk or posedge reset)//时序逻辑进程if(reset)//异步复位cstate<=s0;else//--当检测到时钟上升沿时执行CASE语句begincstate<=nstate;endalways@(cstate or datain)begincase(cstate)s0:begin if(datain==0)nstate<=s1;else nstate<=s0;ends1:begin if(datain==1)nstate<=s2;else nstate<=s1;ends2:begin if(datain==2)nstate<=s3;else nstate<=s2;ends3:begin if(datain==3)nstate<=s0;else nstate<=s3;end//由信号state将当前状态值带出此进程,进入组合逻辑进程endcaseendalways@(cstate)//组合逻辑进程begincase(cstate)//--确定当前状态值s0:dataout<=4'b0001;//对应状态s0的数据输出为"0001"s1:dataout<=4'b0010;s2:dataout<=4'b0100;s3:dataout<=4'b1000;endcaseendendmodule//分频器部分,获得便于试验观察的时钟信号module clk_div(clk_out,clk_in);input clk_in;output clk_out;reg clk_out;reg[25:0]counter;//50_000_000=1011_1110_1011_1100_0010_0000_00parameter cnt=50_000_000;///50MHz is the sys clk,50_000_000=2FAF080 always@(posedge clk_in)begincounter<=counter+1;if(counter==cnt/2-1)beginclk_out<=!clk_out;counter<=0;endendendmodule实验14Mealy状态机module mealy(dataout,clk,datain,reset);output[3:0]dataout;input[1:0]datain;input clk,reset;parameter s0=2'b00,//采用格雷码编码s1=2'b01,s2=2'b11,s3=2'b10;reg[1:0]cstate,nstate;reg[3:0]dataout;always@(posedge clk or posedge reset)//时序逻辑进程if(reset)//异步复位cstate<=s0;else//--当检测到时钟上升沿时执行CASE语句begincstate<=nstate;endalways@(cstate or datain)begincase(cstate)s0:begin if(datain==0)nstate<=s1;else nstate<=s0;ends1:begin if(datain==1)nstate<=s2;else nstate<=s1;ends2:begin if(datain==2)nstate<=s3;else nstate<=s2;ends3:begin if(datain==3)nstate<=s0;else nstate<=s3;end//由信号state将当前状态值带出此进程,进入组合逻辑进程endcaseendalways@(cstate or datain)//组合逻辑进程begincase(cstate)//--确定当前状态值s0:begin if(datain==0)dataout<=4'b0001;else dataout<=4'b0000;end//对应状态s0,输入datain为0时,数据输出为"0001",即输出由当前状态和输入同时控制;s1:begin if(datain==1)dataout<=4'b0010;else dataout<=4'b0101;ends2:begin if(datain==2)dataout<=4'b0100;else dataout<=4'b0011;ends3:begin if(datain==3)dataout<=4'b1000;else dataout<=4'b0110;endendcaseendendmodule实验15三层电梯module lift_3(buttonclk,liftclk,reset,f1upbutton,f2upbutton,f2dnbutton, f3dnbutton,stop1button,stop2button,stop3button,position,doorlight,udsig,fdnlight,fuplight);input buttonclk;//input liftclk;//电梯运行时钟input reset;//resetinput f1upbutton;//from1st floor to upstairsinput f2upbutton;//from2nd floor to upstairsinput f2dnbutton;//from2nd floor to downstairsinput f3dnbutton;//from3rd floor to downstairsinput stop1button;//signal to stop the lift on floor1input stop2button;//stop on floor2input stop3button;//stop on floor3output[2:1]fuplight;reg[2:1]fuplight;//regoutput[3:2]fdnlight;reg[3:2]fdnlight;reg[3:1]stoplight;reg[1:0]position;output doorlight;//close or open开关指示灯reg doorlight;output udsig;//up or down signalreg udsig;parameter[3:0]stopon1=0;///state machineparameter[3:0]dooropen=1;parameter[3:0]doorclose=2;parameter[3:0]doorwait1=3;parameter[3:0]doorwait2=4;parameter[3:0]doorwait3=5;parameter[3:0]doorwait4=6;parameter[3:0]up=7;parameter[3:0]down=8;parameter[3:0]stop=9;reg[3:0]mylift;//reg clearup;reg cleardn;reg[1:0]pos;always@(posedge reset or posedge liftclk)beginif(reset==1'b1)///asyn resetbeginmylift=stopon1;//defalut positon:floor1clearup=1'b0;//clear upcleardn=1'b0;//clear downendelsebegincase(mylift)//FSMstopon1:///stop on floor1begindoorlight=1'b1;position=1;//the lift positon flagpos=1;//mylift=doorwait1;enddoorwait1:beginmylift=doorwait2;//2nd secondsenddoorwait2:beginclearup=1'b0;//cleardn=1'b0;mylift=doorwait3;//3rd sec.senddoorwait3:beginmylift=doorwait4;//4th secondenddoorwait4:beginmylift=doorclose;//enddoorclose://after4seconds,close the doorbegindoorlight=1'b0;if(udsig==1'b0)//going upbeginif(position==3)//on floor3beginif(stoplight==3'b000&fuplight==2'b00& fdnlight==2'b00)//no requestsbeginudsig=1'b1;///mylift=doorclose;endelsebeginudsig=1'b1;mylift=down;//if not,must be going downendendelse if(position==2)//on floor2beginif(stoplight==3'b000&fuplight==2'b00& fdnlight==2'b00)//no requestsbeginudsig=1'b0;//still going upmylift=doorclose;//closingendelse if((stoplight[3])==1'b1|((stoplight[3])==1'b0&(fdnlight[3])==1'b1))begin//inside req to stop onf.3,or req.to go down from f.3udsig=1'b0;//still going upmylift=up;endelsebegin//must be going down whatever happensudsig=1'b1;mylift=down;endendelse if(position==1)//on floor1beginif(stoplight==3'b000&fuplight==2'b00& fdnlight==2'b00)//no req.beginudsig=1'b0;mylift=doorclose;//waiting for the going up reqendelsebeginudsig=1'b0;//must be going upmylift=up;endendendelse if(udsig==1'b1)//if going downbeginif(position==1)//beginif(stoplight==3'b000&fuplight==2'b00& fdnlight==2'b00)beginudsig=1'b0;//no reqmylift=doorclose;//waiting for the req to go upendelsebeginudsig=1'b0;//going up at any casemylift=up;endendelse if(position==2)beginif(stoplight==3'b000&fuplight==2'b00& fdnlight==2'b00)beginudsig=1'b1;mylift=doorclose;endelse if((stoplight[1])==1'b1|((stoplight[1]) ==1'b0&(fuplight[1])==1'b1))beginudsig=1'b1;//downmylift=down;endelsebeginudsig=1'b0;//mylift=up;endendelse if(position==3)///beginif(stoplight==3'b000&fuplight==2'b00& fdnlight==2'b00)beginudsig=1'b1;mylift=doorclose;endelsebeginudsig=1'b1;mylift=down;endendendendup:///going up stairsbeginposition=position+1;//under the lift clockpos=pos+1;//if(pos<3&((stoplight[pos])==1'b1|(fuplight[pos]) ==1'b1))begin//destination isn't the top,to stop there or going up from theremylift=stop;//stop the liftendelse if(pos==3&((stoplight[pos])==1'b1| (fdnlight[pos])==1'b1))begin//has been on f.3,and stop here request or go dowm reqmylift=stop;//next state:stopendelsebeginmylift=doorclose;//endenddown://go downbeginposition=position-1;pos=pos-1;if(pos>1&((stoplight[pos])==1'b1|(fdnlight[pos]) ==1'b1))beginmylift=stop;//stop hereendelse if(pos==1&((stoplight[pos])==1'b1| (fuplight[pos])==1'b1))beginmylift=stop;endelsebeginmylift=doorclose;//no req to stop or go up,closedendendstop://beginmylift=dooropen;//next state to openenddooropen:begindoorlight=1'b1;if(udsig==1'b0)//going upbeginif(position<=2&((stoplight[position])==1'b1 |(fuplight[position])==1'b1))beginclearup=1'b1;endelsebeginclearup=1'b1;cleardn=1'b1;endendelse if(udsig==1'b1)beginif(position>=2&((stoplight[position])==1'b1 |(fdnlight[position])==1'b1))begincleardn=1'b1;endelsebeginclearup=1'b1;cleardn=1'b1;endendmylift=doorwait1;endendcaseendendalways@(posedge reset or posedge buttonclk)//控制按键信号灯beginif(reset==1'b1)//asyn resetbeginstoplight=3'b000;fuplight=2'b00;fdnlight=2'b00;endelse//posedge buttonclkbeginif(clearup==1'b1)//begin//内部停靠信号灯和外部上升请求信号灯灭stoplight[position]=1'b0;fuplight[position]=1'b0;endelse//beginif(f1upbutton==1'b1)beginfuplight[1]=1'b1;endelse if(f2upbutton==1'b1)beginfuplight[2]=1'b1;endendif(cleardn==1'b1)beginstoplight[position]=1'b0;fdnlight[position]=1'b0;endelsebeginif(f2dnbutton==1'b1)beginfdnlight[2]=1'b1;endelse if(f3dnbutton==1'b1)beginfdnlight[3]=1'b1;endendif(stop1button==1'b1)beginstoplight[1]=1'b1;endelse if(stop2button==1'b1)beginstoplight[2]=1'b1;endelse if(stop3button==1'b1)beginstoplight[3]=1'b1;endendendendmodule//分频器部分,获得电梯运行(慢)和扫描按键请求的时钟(快)module clk_div(clk_10hz,clk_1hz,clk_in);input clk_in;output clk_1hz,clk_10hz;reg clk_1hz,clk_10hz;reg[25:0]counter1;//50_000_000=1011_1110_1011_1100_0010_0000_00 reg[22:0]counter2;//5,000,000=1001_1000_1001_0110_1000_000parameter cnt1=50_000_000;///50MHz is the sys clk,50_000_000=2FAF080,1HZ parameter cnt2=5_000_000;//to10HZalways@(posedge clk_in)begincounter1<=counter1+1;if(counter1==cnt1/2-1)beginclk_1hz<=!clk_1hz;counter1<=0;endend///clk_10hz,10HZalways@(posedge clk_in)begincounter2<=counter2+1;if(counter2==cnt2/2-1)beginclk_10hz<=!clk_10hz;counter2<=0;endendendmodule。
verilog hdl语言100例详解
verilog hdl语言100例详解Verilog HDL语言是一种硬件描述语言,用于描述数字电路和系统的行为和结构。
它是硬件设计工程师在数字电路设计中的重要工具。
本文将介绍100个例子,详细解释Verilog HDL语言的应用。
1. 基本门电路:Verilog HDL可以用于描述基本门电路,如与门、或门、非门等。
例如,下面是一个描述与门电路的Verilog HDL代码:```verilogmodule and_gate(input a, input b, output y);assign y = a & b;endmodule```2. 多路选择器:Verilog HDL也可以用于描述多路选择器。
例如,下面是一个描述2:1多路选择器的Verilog HDL代码:```verilogmodule mux_2to1(input a, input b, input sel, output y);assign y = sel ? b : a;endmodule```3. 寄存器:Verilog HDL可以用于描述寄存器。
例如,下面是一个描述8位寄存器的Verilog HDL代码:```verilogmodule register_8bit(input [7:0] d, input clk, input reset, output reg [7:0] q);always @(posedge clk or posedge reset)if (reset)q <= 0;elseq <= d;endmodule```4. 计数器:Verilog HDL可以用于描述计数器。
例如,下面是一个描述8位计数器的Verilog HDL代码:```verilogmodule counter_8bit(input clk, input reset, output reg [7:0] count);always @(posedge clk or posedge reset)if (reset)count <= 0;elsecount <= count + 1;endmodule```5. 加法器:Verilog HDL可以用于描述加法器。
用verilog-a写的一些电路模块的例子
用verilog-a写的一些电路模块的例子以下是几个用Verilog-A 语言编写的电路模块的例子:1. 增益电路模块````include "disciplines.vams"module gain_circuit(va, vb, vout, g);input va, vb;output vout;parameter real g=10.0;analog beginvout = g * (va - vb);endendmodule```这个例子展示了一个简单的增益电路模块,其中输入是两个电压va、vb,输出是vout,增益系数为g。
在模块中使用了Verilog-A 的`analog begin` 语句来定义电路的行为。
2. RC 低通滤波器模块````include "disciplines.vams"module rc_lowpass_filter(vin, vout, r, c);input vin;output vout;parameter real r=1.0, c=1e-6;real v1;analog begini(vin, v1) <+ (vin - v1)/(r*c);vout <+ v1;endendmodule```这个例子展示了一个基于RC 电路的低通滤波器模块,其中输入为vin,输出为vout,RC 电路的参数由r 和c 决定。
在模块中使用了Verilog-A 的`i()` 语句来定义电路的行为。
3. 三角波发生器模块````include "disciplines.vams"module triangle_wave_generator(vout, freq, amp, dc);output vout;parameter real freq=1e3, amp=1.0, dc=0.0;real t;analog begint = $abstime;vout <+ amp * (2 * (t * freq - floor(t * freq + 0.5)) - 1) + dc;endendmodule```这个例子展示了一个简单的三角波发生器模块,其中输出为vout,频率由freq 决定,幅值由amp 决定,直流分量由dc 决定。
Verilog建模示例
奇数分频电路
• 错位异或法:对占空比为50%的N倍奇数分频 • 首先进行上升沿出发的模N奇数,到某选定值时输出翻转,然后经 (N-1)/2再次翻转,得到一奇数N分频时钟; • 其次进行下降沿出发的模N记数,到某选定值时输出翻转,然后经 (N-1)/2再次翻转,也得到一奇数N分频时钟; • 将两个信号进行或运算
e a b y
3-8译码器
module decode3to8(din,reset,dout); input [2:0] din; input reset_n; output [7:0] dout; reg [7:0] dout; always @(din or reset) begin if (!reset_n) dout = 8’b0000_0000; else case (din) 1’b000: dout = 8’b0000_0001; 1’b001: dout = 8’b0000_0010; 1’b010: dout = 8’b0000_0100; 1’b011: dout = 8’b0000_1000; 1’b100: dout = 8’b0001_0000; 1’b101: dout = 8’b0010_0000; 1’b110: dout = 8’b0100_0000; 1’b111: dout = 8’b1000_0000; endcase end endmodule
二always块状态机
A/Z=0/1 A/Z=0/0
S0
A/Z=1/0
S3
A/Z=1/1
A/Z=0/0
A/Z=1/1
A/Z=0/0
S1
A/Z=1/1
S2
二always块状态机
module mealy_fsm(z,a, clk, rst_n); parameter S0 = 0,S1 = 1,S2 = 2,S3 = 3; output z; input a,clk,rst_n; reg z; reg [1:0] state,new_state; always @(posedge clk or negedge rst_n) if (~rst_n) state <= S0; else state <= new_state; end always @(state or a) case (state) s0: if (a) begin z = 1; new_state = S2; end else z = 0;
verilog基本电路设计(包括:时钟域同步、无缝切换、异步fifo、去抖滤波))
Verilog基本电路设计(包括:时钟域同步、无缝切换、异步FIFO、去抖滤波))Verilog基本电路设计共包括四部分:单bit跨时钟域同步时钟无缝切换异步FIFO去抖滤波Verilog基本电路设计之一: 单bit跨时钟域同步(帖子链接:/thread-605419-1-1.html)看到坛子里不少朋友,对于基本数字电路存在这样那样的疑惑,本人决定开贴,介绍数字电路最常见的模块单元,希望给初学者带来帮助,也欢迎大佬们前来拍砖。
如果想要做数字设计,下面这些电路是一定会碰到的,也是所有大型IP,SOC设计必不可少的基础,主要包括异步信号的同步处理,同步FIFO,异步FIFO,时钟无缝切换,信号滤波debounce等等,后面会根据大家反馈情况再介绍新电路。
首先介绍异步信号的跨时钟域同步问题。
一般分为单bit的控制信号同步,以及多bit的数据信号同步。
多bit的信号同步会使用异步FIFO完成,而单bit的信号同步,又是时钟无缝切换电路以及异步FIFO电路的设计基础,这里先介绍单bit信号同步处理。
clka域下的信号signal_a,向异步的clkb域传递时,会产生亚稳态问题。
所有的亚稳态,归根结底就是setup/hold时间不满足导致。
在同一个时钟域下的信号,综合以及布线工具可以在data路径或者clock路径上插入buffer使得每一个DFF的setup/hold时间都满足;但是当signal_a在clkb域下使用时,由于clka与clkb异步,它们的相位关系不确定,那么在clkb的时钟沿到来时,无法确定signal_a此时是否处于稳定无变化状态,也即setup/hold时间无法确定,从而产生亚稳态。
这种异步信号在前后端流程里面是无法做时序分析的,也就是静态时序分析里常说的false_path。
消除亚稳态,就是采用多级DFF来采样来自另一个时钟域的信号,级数越多,同步过来的信号越稳定。
对于频率很高的设计,建议至少用三级DFF,而两级DFF同步则是所有异步信号处理的最基本要求。
verilog多模块编程实例
Verilog多模块编程实例1. 介绍Verilog是一种硬件描述语言,被广泛应用于数字电路设计。
Verilog具有模块化设计的特点,可以将一个大型的电路设计分解成多个小模块,然后逐个实现和调试。
本文将介绍Verilog多模块编程的实例,以帮助读者了解如何使用Verilog进行模块化设计。
2. 模块化设计的优势模块化设计是一种将大型系统分解成多个小模块的设计方法。
在Verilog中,模块化设计有以下几个优势:- 提高代码可读性:通过将大型系统分解成多个小模块,可以提高代码的可读性和可维护性。
- 便于调试:每个小模块相对独立,可以单独调试和测试,提高了系统的可靠性和稳定性。
- 提高复用性:将功能相似的代码封装成模块,可以提高代码的复用性,减少代码冗余。
3. 多模块编程实例接下来,我们将通过一个简单的数字电路设计来演示Verilog多模块编程的实例。
假设我们要设计一个4位全加器电路,首先我们需要实现一个单位全加器模块,然后将四个单元全加器模块连接成一个4位全加器模块。
3.1 单位全加器模块我们定义一个单位全加器模块,代码如下:```verilogmodule Adder_unit (input a, b, cin,output sum, cout);assign {cout, sum} = a + b + cin;endmodule```在单位全加器模块中,我们定义了三个输入信号a、b、cin和两个输出信号sum、cout。
其中,sum表示相加的结果,cout表示进位。
在模块内部,我们通过assign语句实现了全加器的功能。
3.2 4位全加器模块接下来,我们将四个单位全加器模块连接成一个4位全加器模块,代码如下:```verilogmodule Adder_4bit (input [3:0] a, b,input cin,output [3:0] sum,output cout);Adder_unit U0(.a(a[0]), .b(b[0]), .cin(cin), .sum(sum[0]), .cout(cout0));Adder_unit U1(.a(a[1]), .b(b[1]), .cin(cout0), .sum(sum[1]), .cout(cout1)); Adder_unit U2(.a(a[2]), .b(b[2]), .cin(cout1), .sum(sum[2]), .cout(cout2)); Adder_unit U3(.a(a[3]), .b(b[3]), .cin(cout2), .sum(sum[3]), .cout(cout));endmodule```在4位全加器模块中,我们首先定义了四个输入信号a、b和一个输入信号cin,以及四个输出信号sum和一个输出信号cout。
verilog优化逻辑的例子
verilog优化逻辑的例子Verilog是一种硬件描述语言,用于描述数字电路的行为和结构。
在设计数字电路时,优化逻辑是非常重要的,可以使电路具有更高的性能和更低的功耗。
下面列举了10个使用Verilog优化逻辑的例子。
1. 优化逻辑运算:在设计数字电路时,经常需要使用逻辑运算符,如与、或、非等。
通过合理地使用逻辑运算符,可以减少电路中门的数量,从而提高电路的性能和速度。
2. 优化布尔表达式:布尔表达式是用于描述逻辑电路的重要工具。
通过简化布尔表达式,可以减少电路中的逻辑门数量,从而提高电路的效率。
3. 优化时序逻辑:时序逻辑是一种特殊的逻辑电路,它的输出取决于输入信号的顺序和时序。
通过合理地设计时序逻辑,可以减少电路中的延迟,提高电路的速度和性能。
4. 优化组合逻辑:组合逻辑是一种不带时钟的逻辑电路,它的输出仅取决于当前的输入信号。
通过合理地设计组合逻辑,可以减少电路中的延迟和功耗,提高电路的性能。
5. 优化多输入逻辑:多输入逻辑是一种具有多个输入信号的逻辑电路。
通过优化多输入逻辑,可以减少电路中的逻辑门数量,提高电路的速度和功耗。
6. 优化状态机:状态机是一种用于描述电路行为的模型。
通过优化状态机的设计,可以减少电路中的逻辑门数量,提高电路的性能和速度。
7. 优化数据通路:数据通路是用于处理数据的路径,包括寄存器、加法器、乘法器等。
通过优化数据通路的设计,可以减少电路中的延迟和功耗,提高电路的性能。
8. 优化存储器设计:存储器是用于存储数据的电路,包括寄存器、RAM、ROM等。
通过优化存储器的设计,可以减少电路中的延迟和功耗,提高电路的性能。
9. 优化时钟频率:时钟频率是电路运行的速度,通过优化电路的设计,可以提高电路的时钟频率,从而提高电路的性能和速度。
10. 优化功耗:功耗是电路消耗的能量,通过优化电路的设计,可以减少电路中的功耗,提高电路的能效。
通过Verilog优化逻辑的设计,可以提高电路的性能和速度,减少电路的延迟和功耗,从而实现更高效的数字电路设计。
Verilog的135个经典设计实例
王金明《Verilog HDL程序设计教程》【例3.1】4位全加器module adder4(cout,sum,ina,inb,cin);output[3:0] sum;output cout;input[3:0] ina,inb;input cin;assign {cout,sum}=ina+inb+cin;endmodule【例3.2】4位计数器module count4(out,reset,clk);output[3:0] out;input reset,clk;reg[3:0] out;always @(posedge clk)beginif (reset) out<=0; //同步复位else out<=out+1; //计数endendmodule【例3.3】4位全加器的仿真程序`timescale 1ns/1ns`include "adder4.v"module adder_tp; //测试模块的名字reg[3:0] a,b; //测试输入信号定义为reg型reg cin;wire[3:0] sum; //测试输出信号定义为wire型wire cout;integer i,j;adder4 adder(sum,cout,a,b,cin); //调用测试对象always #5 cin=~cin; //设定cin的取值initialbegina=0;b=0;cin=0;for(i=1;i<16;i=i+1)#10 a=i; //设定a的取值end- 1 - 程序文本initialbeginfor(j=1;j<16;j=j+1)#10 b=j; //设定b的取值endinitial //定义结果显示格式begin$monitor($time,,,"%d + %d + %b={%b,%d}",a,b,cin,cout,sum); #160 $finish;endendmodule【例3.4】4位计数器的仿真程序`timescale 1ns/1ns`include "count4.v"module coun4_tp;reg clk,reset; //测试输入信号定义为reg型wire[3:0] out; //测试输出信号定义为wire型parameter DELY=100;count4 mycount(out,reset,clk); //调用测试对象always #(DELY/2) clk = ~clk; //产生时钟波形initialbegin //激励信号定义clk =0; reset=0;#DELY reset=1;#DELY reset=0;#(DELY*20) $finish;end//定义结果显示格式initial $monitor($time,,,"clk=%d reset=%d out=%d", clk, reset,out);endmodule【例3.5】“与-或-非”门电路module AOI(A,B,C,D,F); //模块名为AOI(端口列表A B C D F)input A,B,C,D; //模块的输入端口为A B C Doutput F; //模块的输出端口为F- 2 -王金明《Verilog HDL程序设计教程》wire A,B,C,D,F; //定义信号的数据类型 assign F= ~((A&B)|(C&D)); //逻辑功能描述endmodule【例5.1】用case语句描述的4选1数据选择器module mux4_1(out,in0,in1,in2,in3,sel);output out;input in0,in1,in2,in3;input[1:0] sel;reg out;always @(in0 or in1 or in2 or in3 or sel) //敏感信号列表 case(sel)2'b00: out=in0;2'b01: out=in1;2'b10: out=in2;2'b11: out=in3;default: out=2'bx;endcaseendmodule【例5.2】同步置数、同步清零的计数器module count(out,data,load,reset,clk);output[7:0] out;input[7:0] data;input load,clk,reset;reg[7:0] out;always @(posedge clk) //clk上升沿触发beginif (!reset) out = 8'h00; //同步清0低电平有效else if (load) out = data; //同步预置else out = out + 1; //计数endendmodule【例5.3】用always过程语句描述的简单算术逻辑单元`define add 3'd0`define minus 3'd1`define band 3'd2`define bor 3'd3`define bnot 3'd4- 3 - 程序文本module alu(out,opcode,a,b);output[7:0] out;reg[7:0] out;input[2:0] opcode; //操作码input[7:0] a,b; //操作数always@(opcode or a or b) //电平敏感的always块 begincase(opcode)`add: out = a+b; //加操作`minus: out = a-b; //减操作`band: out = a&b; //求与`bor: out = a|b; //求或`bnot: out=~a; //求反default: out=8'hx; //未收到指令时输出任意态 endcaseendendmodule【例5.4】用initial过程语句对测试变量A、B、C赋值 `timescale 1ns/1nsmodule test;reg A,B,C;initialbeginA = 0;B = 1;C = 0;#50 A = 1; B = 0;#50 A = 0; C = 1;#50 B = 1;#50 B = 0; C = 0;#50 $finish ;endendmodule【例5.5】用begin-end串行块产生信号波形 `timescale 10ns/1nsmodule wave1;reg wave;parameter cycle=10;initialbegin- 4 -王金明《Verilog HDL程序设计教程》wave=0;#(cycle/2) wave=1;#(cycle/2) wave=0;#(cycle/2) wave=1;#(cycle/2) wave=0;#(cycle/2) wave=1;#(cycle/2) $finish ;endinitial $monitor($time,,,"wave=%b",wave); endmodule【例5.6】用fork-join并行块产生信号波形`timescale 10ns/1nsmodule wave2;reg wave;parameter cycle=5;initialforkwave=0;#(cycle) wave=1;#(2*cycle) wave=0;#(3*cycle) wave=1;#(4*cycle) wave=0;#(5*cycle) wave=1;#(6*cycle) $finish;joininitial $monitor($time,,,"wave=%b",wave); endmodule【例5.7】持续赋值方式定义的2选1多路选择器module MUX21_1(out,a,b,sel);input a,b,sel;output out;assign out=(sel==0)?a:b;//持续赋值如果sel为0则out=a 否则out=b endmodule【例5.8】阻塞赋值方式定义的2选1多路选择器module MUX21_2(out,a,b,sel); input a,b,sel;- 5 - 程序文本output out;reg out;always@(a or b or sel)beginif(sel==0) out=a; //阻塞赋值 else out=b;endendmodule【例5.9】非阻塞赋值module non_block(c,b,a,clk);output c,b;input clk,a;reg c,b;always @(posedge clk)beginb<=a;c<=b;endendmodule【例5.10】阻塞赋值module block(c,b,a,clk);output c,b;input clk,a;reg c,b;always @(posedge clk)beginb=a;c=b;endendmodule【例5.11】模为60的BCD码加法计数器module count60(qout,cout,data,load,cin,reset,clk); output[7:0] qout;output cout;input[7:0] data;input load,cin,clk,reset;reg[7:0] qout;always @(posedge clk) //clk上升沿时刻计数- 6 -王金明《Verilog HDL程序设计教程》beginif (reset) qout<=0; //同步复位else if(load) qout<=data; //同步置数else if(cin)beginif(qout[3:0]==9) //低位是否为9是则beginqout[3:0]<=0; //回0并判断高位是否为5if (qout[7:4]==5) qout[7:4]<=0;elseqout[7:4]<=qout[7:4]+1; //高位不为5则加1endelse //低位不为9则加1qout[3:0]<=qout[3:0]+1;endendassign cout=((qout==8'h59)&cin)?1:0; //产生进位输出信号endmodule【例5.12】BCD码—七段数码管显示译码器module decode4_7(decodeout,indec);output[6:0] decodeout;input[3:0] indec;reg[6:0] decodeout;always @(indec)begincase(indec) //用case语句进行译码4'd0:decodeout=7'b1111110;4'd1:decodeout=7'b0110000;4'd2:decodeout=7'b1101101;4'd3:decodeout=7'b1111001;4'd4:decodeout=7'b0110011;4'd5:decodeout=7'b1011011;4'd6:decodeout=7'b1011111;4'd7:decodeout=7'b1110000;4'd8:decodeout=7'b1111111;4'd9:decodeout=7'b1111011;default: decodeout=7'bx;endcaseend- 7 - 程序文本endmodule【例5.13】用casez描述的数据选择器 module mux_casez(out,a,b,c,d,select); output out;input a,b,c,d;input[3:0] select;reg out;always @(select or a or b or c or d)begincasez(select)4'b???1: out = a;4'b??1?: out = b;4'b?1??: out = c;4'b1???: out = d;endcaseendendmodule【例5.14】隐含锁存器举例module buried_ff(c,b,a);output c;input b,a;reg c;always @(a or b)beginif((b==1)&&(a==1)) c=a&b;endendmodule【例5.15】用for语句描述的七人投票表决器module voter7(pass,vote);output pass;input[6:0] vote;reg[2:0] sum;integer i;reg pass;always @(vote)beginsum=0;- 8 -王金明《Verilog HDL程序设计教程》for(i=0;i<=6;i=i+1) //for语句if(vote[i]) sum=sum+1;if(sum[2]) pass=1; //若超过4人赞成则pass=1 else pass=0;endendmodule【例5.16】用for语句实现2个8位数相乘module mult_for(outcome,a,b);parameter size=8;input[size:1] a,b; //两个操作数output[2*size:1] outcome; //结果reg[2*size:1] outcome;integer i;always @(a or b)beginoutcome=0;for(i=1; i<=size; i=i+1) //for语句if(b[i]) outcome=outcome +(a << (i-1));endendmodule【例5.17】用repeat实现8位二进制数的乘法module mult_repeat(outcome,a,b);parameter size=8;input[size:1] a,b;output[2*size:1] outcome;reg[2*size:1] temp_a,outcome;reg[size:1] temp_b;always @(a or b)beginoutcome=0;temp_a=a;temp_b=b;repeat(size) //repeat语句size为循环次数beginif(temp_b[1]) //如果temp_b的最低位为1就执行下面的加法 outcome=outcome+temp_a;temp_a=temp_a<<1; //操作数a左移一位- 9 - 程序文本temp_b=temp_b>>1; //操作数b右移一位endendendmodule【例5.18】同一循环的不同实现方式 module loop1; //方式1integer i;initialfor(i=0;i<4;i=i+1) //for语句begin$display(“i=%h”,i);endendmodulemodule loop2; //方式2integer i;initial begini=0;while(i<4) //while语句begin$display ("i=%h",i);i=i+1;endendendmodulemodule loop3; //方式3integer i;initial begini=0;repeat(4) //repeat语句begin$display ("i=%h",i);i=i+1;endendendmodule【例5.19】使用了`include语句的16位加法器- 10 -王金明《Verilog HDL程序设计教程》`include "adder.v" module adder16(cout,sum,a,b,cin);output cout;parameter my_size=16;output[my_size-1:0] sum;input[my_size-1:0] a,b;input cin;adder my_adder(cout,sum,a,b,cin); //调用adder模块endmodule//下面是adder模块代码module adder(cout,sum,a,b,cin);parameter size=16;output cout;output[size-1:0] sum;input cin;input[size-1:0] a,b;assign {cout,sum}=a+b+cin;endmodule【例5.20】条件编译举例module compile(out,A,B);output out;input A,B;`ifdef add //宏名为addassign out=A+B;`elseassign out=A-B;`endifendmodule【例6.1】加法计数器中的进程module count(data,clk,reset,load,cout,qout);output cout;output[3:0] qout;reg[3:0] qout;input[3:0] data;input clk,reset,load;- 11 - 程序文本always @(posedge clk) //进程1always过程块beginif (!reset) qout= 4'h00; //同步清0低电平有效else if (load) qout= data; //同步预置else qout=qout + 1; //加法计数endassign cout=(qout==4'hf)?1:0; //进程2用持续赋值产生进位信号【例6.2】任务举例module alutask(code,a,b,c);input[1:0] code;input[3:0] a,b;output[4:0] c;reg[4:0] c;task my_and; //任务定义注意无端口列表input[3:0] a,b; //a,b,out名称的作用域范围为task任务内部output[4:0] out;integer i;beginfor(i=3;i>=0;i=i-1)out[i]=a[i]&b[i]; //按位与endendtaskalways@(code or a or b)begincase(code)2'b00: my_and(a,b,c);/* 用任务my_and需注意端口列表的顺序应与任务定义中的一致这里的a,b,c分别对应任务定义中的a,b,out */2'b01: c=a|b; //或2'b10: c=a-b; //相减2'b11: c=a+b; //相加endcaseend- 12 -王金明《Verilog HDL程序设计教程》【例6.3】测试程序`include "alutask.v"module alu_tp;reg[3:0] a,b;reg[1:0] code;wire[4:0] c;parameter DELY = 100;alutask ADD(code,a,b,c); //调用被测试模块initial begincode=4'd0; a= 4'b0000; b= 4'b1111;#DELY code=4'd0; a= 4'b0111; b= 4'b1101;#DELY code=4'd1; a= 4'b0001; b= 4'b0011;#DELY code=4'd2; a= 4'b1001; b= 4'b0011;#DELY code=4'd3; a= 4'b0011; b= 4'b0001;#DELY code=4'd3; a= 4'b0111; b= 4'b1001;#DELY $finish;endinitial $monitor($time,,,"code=%b a=%b b=%b c=%b", code,a,b,c); endmodule【例6.4】函数function[7:0] get0;input[7:0] x;reg[7:0] count;integer i;begincount=0;for (i=0;i<=7;i=i+1)if (x[i]=1'b0) count=count+1;get0=count;endendfunction【例6.5】用函数和case语句描述的编码器不含优先顺序module code_83(din,dout);input[7:0] din;output[2:0] dout;- 13 - 程序文本function[2:0] code; //函数定义input[7:0] din; //函数只有输入输出为函数名本身 casex (din)8'b1xxx_xxxx : code = 3'h7;8'b01xx_xxxx : code = 3'h6;8'b001x_xxxx : code = 3'h5;8'b0001_xxxx : code = 3'h4;8'b0000_1xxx : code = 3'h3;8'b0000_01xx : code = 3'h2;8'b0000_001x : code = 3'h1;8'b0000_000x : code = 3'h0;default: code = 3'hx;endcaseendfunctionassign dout = code(din) ; //函数调用endmodule【例6.6】阶乘运算函数module funct(clk,n,result,reset);output[31:0] result;input[3:0] n;input reset,clk;reg[31:0] result;always @(posedge clk) //在clk的上升沿时执行运算beginif(!reset) result<=0; //复位else beginresult <= 2 * factorial(n); //调用factorial函数endendfunction[31:0] factorial; //阶乘运算函数定义注意无端口列表input[3:0] opa; //函数只能定义输入端输出端口为函数名本身 reg[3:0] i;beginfactorial = opa ? 1 : 0;for(i= 2; i <= opa; i = i+1) //该句若要综合通过opa应赋具体的数值 factorial = i* factorial; //阶乘运算end- 14 -王金明《Verilog HDL程序设计教程》endfunctionendmodule【例6.7】测试程序`define clk_cycle 50`include "funct.v"module funct_tp;reg[3:0] n;reg reset,clk;wire[31:0] result;initial //定义激励向量beginn=0; reset=1; clk=0;for(n=0;n<=15;n=n+1)#100 n=n;endinitial $monitor($time,,,"n=%d result=%d",n,result);//定义输出显示格式always # `clk_cycle clk=~clk; //产生时钟信号funct funct_try(.clk(clk),.n(n),.result(result),.reset(reset)); //调用被测试模块endmodule【例6.8】顺序执行模块1module serial1(q,a,clk);output q,a;input clk;reg q,a;always @(posedge clk)beginq=~q;a=~q;endendmodule【例6.9】顺序执行模块2 module serial2(q,a,clk); output q,a;- 15 - 程序文本input clk;reg q,a;always @(posedge clk)begina=~q;q=~q;endendmodule【例6.10】并行执行模块1 module paral1(q,a,clk);output q,a;input clk;reg q,a;always @(posedge clk)beginq=~q;endalways @(posedge clk)begina=~q;endendmodule【例6.11】并行执行模块2module paral2(q,a,clk);output q,a;input clk;reg q,a;always @(posedge clk)begina=~q;endalways @(posedge clk)beginq=~q;endendmodule【例7.1】调用门元件实现的4选1 MUX- 16 -王金明《Verilog HDL程序设计教程》module mux4_1a(out,in1,in2,in3,in4,cntrl1,cntrl2); output out;input in1,in2,in3,in4,cntrl1,cntrl2;wire notcntrl1,notcntrl2,w,x,y,z;not notcntrl1,cntrl2),(notcntrl2,cntrl2);and (w,in1,notcntrl1,notcntrl2),(x,in2,notcntrl1,cntrl2),(y,in3,cntrl1,notcntrl2),(z,in4,cntrl1,cntrl2);or (out,w,x,y,z);endmodule【例7.2】用case语句描述的4选1 MUXmodule mux4_1b(out,in1,in2,in3,in4,cntrl1,cntrl2); output out;input in1,in2,in3,in4,cntrl1,cntrl2;reg out;always@(in1 or in2 or in3 or in4 or cntrl1 or cntrl2) case({cntrl1,cntrl2})2'b00:out=in1;2'b01:out=in2;2'b10:out=in3;2'b11:out=in4;default:out=2'bx;endcaseendmodule【例7.3】行为描述方式实现的4位计数器module count4(clk,clr,out);input clk,clr;output[3:0] out;reg[3:0] out;always @(posedge clk or posedge clr)beginif (clr) out<=0;else out<=out+1;endendmodule- 17 - 程序文本【例7.4】数据流方式描述的4选1 MUXmodule mux4_1c(out,in1,in2,in3,in4,cntrl1,cntrl2);output out;input in1,in2,in3,in4,cntrl1,cntrl2;assign out=(in1 & ~cntrl1 & ~cntrl2)|(in2 & ~cntrl1 & cntrl2)| (in3 & cntrl1 & ~cntrl2)|(in4 & cntrl1 & cntrl2);endmodule【例7.5】用条件运算符描述的4选1 MUXmodule mux4_1d(out,in1,in2,in3,in4,cntrl1,cntrl2);output out;input in1,in2,in3,in4,cntrl1,cntrl2;assign out=cntrl1 ? (cntrl2 ? in4:in3):(cntrl2 ? in2:in1);endmodule【例7.6】门级结构描述的2选1MUXmodule mux2_1a(out,a,b,sel);output out;input a,b,sel;not (sel_,sel);and a1,a,sel_),(a2,b,sel);or (out,a1,a2);endmodule【例7.7】行为描述的2选1MUXmodule mux2_1b(out,a,b,sel);output out;input a,b,sel;reg out;always @(a or b or sel)beginif(sel) out = b;else out = a;endendmodule【例7.8】数据流描述的2选1MUXmodule MUX2_1c(out,a,b,sel);output out;- 18 -王金明《Verilog HDL程序设计教程》input a,b,sel; assign out = sel ? b : a;endmodule【例7.9】调用门元件实现的1位半加器module half_add1(a,b,sum,cout);input a,b;output sum,cout;and cout,a,b);xor sum,a,b);endmodule【例7.10】数据流方式描述的1位半加器module half_add2(a,b,sum,cout);input a,b;output sum,cout;assign sum=a^b;assign cout=a&b;endmodule【例7.11】采用行为描述的1位半加器module half_add3(a,b,sum,cout);input a,b;output sum,cout;reg sum,cout;always @(a or b)begincase ({a,b}) //真值表描述 2'b00: begin sum=0; cout=0; end2'b01: begin sum=1; cout=0; end2'b10: begin sum=1; cout=0; end2'b11: begin sum=0; cout=1; endendcaseendendmodule【例7.12】采用行为描述的1位半加器module half_add4(a,b,sum,cout);input a,b;output sum,cout;- 19 - 程序文本reg sum,cout;always @(a or b)beginsum= a^b;cout=a&b;endendmodule【例7.13】调用门元件实现的1位全加器 module full_add1(a,b,cin,sum,cout);input a,b,cin;output sum,cout;wire s1,m1,m2,m3;and m1,a,b),(m2,b,cin),(m3,a,cin);xor s1,a,b),(sum,s1,cin);or (cout,m1,m2,m3);endmodule【例7.14】数据流描述的1位全加器module full_add2(a,b,cin,sum,cout);input a,b,cin;output sum,cout;assign sum = a ^ b ^ cin;assign cout = (a & b)|(b & cin)|(cin & a); endmodule【例7.15】1位全加器module full_add3(a,b,cin,sum,cout);input a,b,cin;output sum,cout;assign {cout,sum}=a+b+cin;endmodule【例7.16】行为描述的1位全加器module full_add4(a,b,cin,sum,cout);input a,b,cin;output sum,cout;- 20 -王金明《Verilog HDL程序设计教程》reg sum,cout; //在always块中被赋值的变量应定义为reg型reg m1,m2,m3;always @(a or b or cin)beginsum = (a ^ b) ^ cin;m1 = a & b;m2 = b & cin;m3 = a & cin;cout = (m1|m2)|m3;endendmodule【例7.17】混合描述的1位全加器module full_add5(a,b,cin,sum,cout);input a,b,cin;output sum,cout;reg cout,m1,m2,m3; //在always块中被赋值的变量应定义为reg型wire s1;xor x1(s1,a,b); //调用门元件always @(a or b or cin) //always块语句beginm1 = a & b;m2 = b & cin;m3 = a & cin;cout = (m1| m2) | m3;endassign sum = s1 ^ cin; //assign持续赋值语句endmodule【例7.18】结构描述的4位级连全加器`include "full_add1.v"module add4_1(sum,cout,a,b,cin);output[3:0] sum;output cout;input[3:0] a,b;input cin;full_add1 f0(a[0],b[0],cin,sum[0],cin1); //级连描述full_add1 f1(a[1],b[1],cin1,sum[1],cin2);full_add1 f2(a[2],b[2],cin2,sum[2],cin3);- 21 - 程序文本full_add1 f3(a[3],b[3],cin3,sum[3],cout);endmodule【例7.19】数据流描述的4位全加器module add4_2(cout,sum,a,b,cin);output[3:0] sum;output cout;input[3:0] a,b;input cin;assign {cout,sum}=a+b+cin;endmodule【例7.20】行为描述的4位全加器module add4_3(cout,sum,a,b,cin);output[3:0] sum;output cout;input[3:0] a,b;input cin;reg[3:0] sum;reg cout;always @(a or b or cin)begin{cout,sum}=a+b+cin;endendmodule【例8.1】$time与$realtime的区别`timescale 10ns/1nsmodule time_dif;reg ts;parameter delay=2.6;initialbegin#delay ts=1;#delay ts=0;#delay ts=1;#delay ts=0;endinitial $monitor($time,,,"ts=%b",ts); //使用函数$time- 22 -王金明《Verilog HDL程序设计教程》endmodule【例8.2】$random函数的使用`timescale 10ns/1nsmodule random_tp;integer data;integer i;parameter delay=10;initial $monitor($time,,,"data=%b",data);initial beginfor(i=0; i<=100; i=i+1)#delay data=$random; //每次产生一个随机数 endendmodule【例8.3】1位全加器进位输出UDP元件primitive carry_udp(cout,cin,a,b);input cin,a,b;output cout;table//cin a b : cout //真值表0 0 0 : 0;0 1 0 : 0;0 0 1 : 0;0 1 1 : 1;1 0 0 : 0;1 0 1 : 1;1 1 0 : 1;1 1 1 : 1;endtableendprimitive【例8.4】包含x态输入的1位全加器进位输出UDP元件primitive carry_udpx1(cout,cin,a,b);input cin,a,b;output cout;table// cin a b : cout //真值表0 0 0 : 0;- 23 - 程序文本0 1 0 : 0;0 0 1 : 0;0 1 1 : 1;1 0 0 : 0;1 0 1 : 1;1 1 0 : 1;1 1 1 : 1;0 0 x : 0; //只要有两个输入为0则进位输出肯定为0 0 x 0 : 0;x 0 0 : 0;1 1 x : 1; //只要有两个输入为1则进位输出肯定为1 1 x 1 : 1;x 1 1 : 1;endtableendprimitive【例8.5】用简缩符“”表述的1位全加器进位输出UDP元件 primitive carry_udpx2(cout,cin,a,b);input cin,a,b;output cout;table// cin a b : cout //真值表? 0 0 : 0; //只要有两个输入为0则进位输出肯定为0 0 ? 0 : 0;0 0 ? : 0;? 1 1 : 1; //只要有两个输入为1则进位输出肯定为1 1 ? 1 : 1;1 1 ? : 1;endtableendprimitive【例8.6】3选1多路选择器UDP元件primitive mux31(Y,in0,in1,in2,s2,s1);input in0,in1,in2,s2,s1;output Y;table//in0 in1 in2 s2 s1 : Y0 ? ? 0 0 : 0; //当s2s1=00时Y=in01 ? ? 0 0 : 1;? 0 ? 0 1 : 0; //当s2s1=01时Y=in1- 24 -王金明《Verilog HDL程序设计教程》? 1 ? 0 1 : 1;? ? 0 1 ? : 0; //当s2s1=1时Y=in2? ? 1 1 ? : 1;0 0 ? 0 ? : 0;1 1 ? 0 ? : 1;0 ? 0 ? 0 : 0;1 ? 1 ? 0 : 1;? 0 0 ? 1 : 0;? 1 1 ? 1 : 1;endtableendprimitive【例8.7】电平敏感的1位数据锁存器UDP元件primitive latch(Q,clk,reset,D);input clk,reset,D;output Q;reg Q;initial Q = 1'b1; //初始化table// clk reset D : state : Q? 1 ? : ? : 0 ; //reset=1则不管其他端口为什么值输出都为0 0 0 0 : ? : 0 ; //clk=0锁存器把D端的输入值输出0 0 1 : ? : 1 ;1 0 ? : ? : - ; //clk=1锁存器的输出保持原值用符号“-”表示 endtableendprimitive【例8.8】上升沿触发的D触发器UDP元件primitive DFF(Q,D,clk);output Q;input D,clk;reg Q;table//clk D : state : Q(01) 0 : ? : 0; //上升沿到来输出Q=D(01) 1 : ? : 1;(0x) 1 : 1 : 1;(0x) 0 : 0 : 0;(?0) ? : ? : -; //没有上升沿到来输出Q保持原值? (??) : ? : - ; //时钟不变输出也不变- 25 - 程序文本endtableendprimitive【例8.9】带异步置1和异步清零的上升沿触发的D触发器UDP元件 primitive DFF_UDP(Q,D,clk,clr,set);output Q;input D,clk,clr,set;reg Q;table// clk D clr et state : Q(01) 1 0 0 : ? : 0;(01) 1 0 x : ? : 0;? ? 0 x : 0 : 0;(01) 0 0 0 : ? : 1;(01) 0 x 0 : ? : 1;? ? x 0 : 1 : 1;(x1) 1 0 0 : 0 : 0;(x1) 0 0 0 : 1 : 1;(0x) 1 0 0 : 0 : 0;(0x) 0 0 0 : 1 : 1;? ? 1 ? : ? : 1; //异步复位? ? 0 1 : ? : 0; //异步置1n ? 0 0 : ? : -;? * ? ? : ? : -;? ? (?0) ? : ? : -;? ? ? (?0): ? : -;? ? ? ? : ? : x;endtableendprimitive【例8.12】延迟定义块举例module delay(out,a,b,c);output out;input a,b,c;and a1(n1,a,b);or o1(out,c,n1);specify(a=>out)=2;(b=>out)=3;(c=>out)=1;- 26 -王金明《Verilog HDL程序设计教程》 endspecifyendmodule【例8.13】激励波形的描述'timescale 1ns/1nsmodule test1;reg A,B,C;initialbegin //激励波形描述A = 0;B = 1;C = 0;#100 C = 1;#100 A = 1; B = 0;#100 A = 0;#100 C = 0;#100 $finish;endinitial $monitor($time,,,"A=%d B=%d C=%d",A,B,C); //显示endmodule【例8.15】用always过程块产生两个时钟信号module test2;reg clk1,clk2;parameter CYCLE = 100;alwaysbegin{clk1,clk2} = 2'b10;#(CYCLE/4) {clk1,clk2} = 2'b01;#(CYCLE/4) {clk1,clk2} = 2'b11;#(CYCLE/4) {clk1,clk2} = 2'b00;#(CYCLE/4) {clk1,clk2} = 2'b10;endinitial $monitor($time,,,"clk1=%b clk2=%b",clk1,clk2);endmodule【例8.17】存储器在仿真程序中的应用module ROM(addr,data,oe);output[7:0] data; //数据信号input[14:0] addr; //地址信号input oe; //读使能信号低电平有效- 27 - 程序文本reg[7:0] mem[0:255]; //存储器定义parameter DELAY = 100;assign #DELAY data=(oe==0) ? mem[addr] : 8'hzz;initial $readmemh("rom.hex",mem); //从文件中读入数据 endmodule【例8.18】8位乘法器的仿真程序`timescale 10ns/1nsmodule mult_tp; //测试模块的名字reg[7:0] a,b; //测试输入信号定义为reg型wire [15:0] out; //测试输出信号定义为wire型integer i,j;mult8 m1(out,a,b); //调用测试对象//激励波形设定initialbegina=0;b=0;for(i=1;i<255;i=i+1)#10 a=i;endinitialbeginfor(j=1;j<255;j=j+1)#10 b=j;endinitial //定义结果显示格式begin$monitor($time,,,"%d * %d= %d",a,b,out);#2560 $finish;endendmodulemodule mult8(out, a, b); //8位乘法器源代码parameter size=8;input[size:1] a,b; //两个操作数output[2*size:1] out; //结果assign out=a*b; //乘法运算符- 28 -王金明《Verilog HDL程序设计教程》endmodule 【例8.19】8位加法器的仿真程序`timescale 1ns/1nsmodule add8_tp; //仿真模块无端口列表reg[7:0] A,B; //输入激励信号定义为reg型reg cin;wire[7:0] SUM; //输出信号定义为wire型wire cout;parameter DELY = 100;add8 AD1(SUM,cout,A,B,cin); //调用测试对象initial begin //激励波形设定A= 8'd0; B= 8'd0; cin=1'b0;#DELY A= 8'd100; B= 8'd200; cin=1'b1;#DELY A= 8'd200; B= 8'd88;#DELY A= 8'd210; B= 8'd18; cin=1'b0;#DELY A= 8'd12; B= 8'd12;#DELY A= 8'd100; B= 8'd154;#DELY A= 8'd255; B= 8'd255; cin=1'b1;#DELY $finish;end//输出格式定义initial $monitor($time,,,"%d + %d + %b = {%b, %d}",A,B,cin,cout,SUM);endmodule module add8(SUM,cout,A,B,cin); //待测试的8位加法器模块output[7:0] SUM;output cout;input[7:0] A,B;input cin;assign {cout,SUM}=A+B+cin;endmodule【例8.20】2选1多路选择器的仿真`timescale 1ns/1nsmodule mux_tp;reg a,b,sel;wire out;- 29 - 程序文本MUX2_1 m1(out,a,b,sel); //调用待测试模块initialbegina=1'b0; b=1'b0; sel=1'b0;#5 sel=1'b1;#5 a=1'b1; el=1'b0;#5 sel=1'b1;#5 a=1'b0; b=1'b1; el=1'b0;#5 sel=1'b1;#5 a=1'b1; b=1'b1; sel=1'b0;#5 sel=1'b1;endinitial $monitor($time,,,"a=%b b=%b sel=%b out=%b",a,b,sel,out); endmodulemodule MUX2_1(out,a,b,sel); //待测试的2选1MUX模块input a,b,sel;output out;not #(0.4,0.3) (sel_,sel); //#(0.4,0.3)为门延时and #(0.7,0.6) (a1,a,sel_);and #(0.7,0.6) (a2,b,sel);or #(0.7,0.6) (out,a1,a2);endmodule【例8.21】8位计数器的仿真`timescale 10ns/1nsmodule count8_tp;reg clk,reset; //输入激励信号定义为reg型wire[7:0] qout; //输出信号定义为wire型parameter DELY=100;counter C1(qout,reset,clk); //调用测试对象always #(DELY/2) clk = ~clk; //产生时钟波形initialbegin //激励波形定义clk =0; reset=0;- 30 -王金明《Verilog HDL程序设计教程》#DELY reset=1;#DELY reset=0;#(DELY*300) $finish;end//结果显示initial $monitor($time,,,"clk=%d reset=%d qout=%d",clk,reset,qout);endmodule module counter(qout,reset,clk); //待测试的8位计数器模块output[7:0] qout;input clk,reset;reg[7:0] qout;always @(posedge clk)begin if (reset) qout<=0;else qout<=qout+1;endendmodule【例9.1】基本门电路的几种描述方法1门级结构描述module gate1(F,A,B,C,D);input A,B,C,D;output F;nand(F1,A,B); //调用门元件and(F2,B,C,D);or(F,F1,F2);endmodule2数据流描述module gate2(F,A,B,C,D);input A,B,C,D;output F;assign F=(A&B)|(B&C&D); //assign持续赋值endmodule3行为描述module gate3(F,A,B,C,D);input A,B,C,D;output F;- 31 - 程序文本reg F;always @(A or B or C or D) //过程赋值beginF=(A&B)|(B&C&D);endendmodule【例9.2】用bufif1关键字描述的三态门module tri_1(in,en,out);input in,en;output out;tri out;bufif1 b1(out,in,en); //注意三态门端口的排列顺序endmodule【例9.3】用assign语句描述的三态门module tri_2(out,in,en);output out;input in,en;assign out = en ? in : 'bz;//若en=1则out=in若en=0则out为高阻态 endmodule【例9.4】三态双向驱动器module bidir(tri_inout,out,in,en,b);inout tri_inout;output out;input in,en,b;assign tri_inout = en ? in : 'bz;assign out = tri_inout ^ b;endmodule【例9.5】三态双向驱动器module bidir2(bidir,en,clk);inout[7:0] bidir;input en,clk;reg[7:0] temp;assign bidir= en ? temp : 8'bz;always @(posedge clk)begin- 32 -王金明《Verilog HDL程序设计教程》if(en) temp=bidir;else temp=temp+1;endendmodule【例9.6】3-8译码器module decoder_38(out,in);output[7:0] out;input[2:0] in;reg[7:0] out;always @(in)begincase(in)3'd0: out=8'b11111110;3'd1: out=8'b11111101;3'd2: out=8'b11111011;3'd3: out=8'b11110111;3'd4: out=8'b11101111;3'd5: out=8'b11011111;3'd6: out=8'b10111111;3'd7: out=8'b01111111;endcaseendendmodule【例9.7】8-3优先编码器module encoder8_3(none_on,outcode,a,b,c,d,e,f,g,h); output none_on;output[2:0] outcode;input a,b,c,d,e,f,g,h;reg[3:0] outtemp;assign {none_on,outcode}=outtemp;always @(a or b or c or d or e or f or g or h)beginif(h) outtemp=4'b0111;else if(g) outtemp=4'b0110;else if(f) outtemp=4'b0101;else if(e) outtemp=4'b0100;else if(d) outtemp=4'b0011;else if(c) outtemp=4'b0010;- 33 - 程序文本else if(b) outtemp=4'b0001;else if(a) outtemp=4'b0000;else outtemp=4'b1000;endendmodule【例9.8】用函数定义的8-3优先编码器module code_83(din, dout);input[7:0] din;output[2:0] dout;function[2:0] code; //函数定义input[7:0] din; //函数只有输入端口输出为函数名本身 if (din[7]) code = 3'd7;else if (din[6]) code = 3'd6;else if (din[5]) code = 3'd5;else if (din[4]) code = 3'd4;else if (din[3]) code = 3'd3;else if (din[2]) code = 3'd2;else if (din[1]) code = 3'd1;else code = 3'd0;endfunctionassign dout = code(din); //函数调用endmodule【例9.9】七段数码管译码器module decode47(a,b,c,d,e,f,g,D3,D2,D1,D0);output a,b,c,d,e,f,g;input D3,D2,D1,D0; //输入的4位BCD码reg a,b,c,d,e,f,g;always @(D3 or D2 or D1 or D0)begincase({D3,D2,D1,D0}) //用case语句进行译码 4'd0: {a,b,c,d,e,f,g}=7'b1111110;4'd1: {a,b,c,d,e,f,g}=7'b0110000;4'd2: {a,b,c,d,e,f,g}=7'b1101101;4'd3: {a,b,c,d,e,f,g}=7'b1111001;4'd4: {a,b,c,d,e,f,g}=7'b0110011;4'd5: {a,b,c,d,e,f,g}=7'b1011011;- 34 -王金明《Verilog HDL程序设计教程》4'd6: {a,b,c,d,e,f,g}=7'b1011111;4'd7: {a,b,c,d,e,f,g}=7'b1110000;4'd8: {a,b,c,d,e,f,g}=7'b1111111;。
verilog状态机设计例题
verilog状态机设计例题Verilog状态机设计是数字电路设计中的重要内容,它通常用于控制系统和序列逻辑电路的设计。
在Verilog中,状态机通常使用行为级描述或者结构级描述来实现。
下面我将从例题的角度来介绍Verilog状态机设计。
假设我们要设计一个简单的2位计数器,它可以按顺序循环输出00、01、10、11、00……的计数序列。
我们可以使用Verilog来实现这个状态机。
首先,我们需要定义状态机的状态和状态转移。
在这个例子中,我们有4个状态:S0、S1、S2和S3,分别对应00、01、10、11四种计数状态。
状态转移规则如下:当当前状态为S0时,下一个状态为S1;当当前状态为S1时,下一个状态为S2;当当前状态为S2时,下一个状态为S3;当当前状态为S3时,下一个状态为S0。
接下来,我们可以使用Verilog的行为级描述来实现这个状态机。
下面是一个简单的Verilog代码示例:verilog.module counter (。
input clk, // 时钟输入。
input rst, // 复位输入。
output reg [1:0] count // 2位计数输出。
);// 定义状态。
typedef enum {S0, S1, S2, S3} state_type;reg [1:0] state, next_state;// 状态转移逻辑。
always @(posedge clk or posedge rst) begin.if (rst) begin.state <= S0; // 复位时初始状态为S0。
end.else begin.state <= next_state; // 根据下一个状态更新当前状态。
end.end.// 下一个状态逻辑。
case (state)。
S0: next_state = S1;S1: next_state = S2;S2: next_state = S3;S3: next_state = S0;default: next_state = S0;endcase.end.// 输出逻辑。
verilog优化逻辑的例子
verilog优化逻辑的例子以Verilog优化逻辑为例,我们将介绍10个优化技巧和实例,以帮助您更好地理解和运用Verilog语言。
1. 使用位运算代替乘法和除法在某些情况下,使用位运算可以替代乘法和除法操作,从而提高运算效率。
例如,将一个数乘以2可以使用左移操作来代替。
2. 使用位宽最小化在设计中,尽量使用最小的位宽来表示信号,以节省资源和提高性能。
例如,如果一个信号的最大值是15,那么可以使用4位来表示,而不是8位。
3. 使用优化的逻辑门在Verilog中,可以使用不同类型的逻辑门来实现相同的功能。
选择合适的逻辑门可以提高设计的性能和效率。
例如,使用与门和或门来实现逻辑与操作比使用与非门和与门的组合更有效率。
4. 使用分层次设计将复杂的逻辑模块划分为较小的子模块,可以提高设计的可读性和可维护性。
通过分层次设计,可以更容易地进行逻辑优化和调试。
5. 使用生成循环生成循环是一种强大的Verilog语言特性,可以用来生成重复的逻辑结构。
通过使用生成循环,可以减少冗余的代码,并提高设计的可维护性。
6. 使用选择语句代替多层if-else语句在某些情况下,使用选择语句(case语句)可以替代多层if-else 语句,从而提高代码的可读性和性能。
选择语句可以更清晰地表达逻辑关系,并且在硬件实现中更高效。
7. 使用寄存器代替连续赋值在Verilog中,连续赋值会导致逻辑的多次计算,从而降低性能。
为了提高性能,可以使用寄存器来保存中间结果,并在需要时进行赋值。
8. 使用常量和参数在设计中,使用常量和参数可以提高代码的可读性和可维护性。
通过将常量和参数定义在模块的顶部,可以方便地修改和调整设计参数。
9. 使用复位和使能信号在复杂的设计中,使用复位和使能信号可以控制模块的行为,从而提高设计的灵活性和可靠性。
通过使用复位信号,可以在系统启动时将模块重置到初始状态。
10. 使用状态机状态机是一种常用的设计模式,可以将复杂的逻辑结构分解为一系列简单的状态。
verilog经典三段式状态机设计实例
Moore型verilog源代码:FSM实现10010串的检测Moore状态转移图module moorefsm(clk,rst,a,z);input clk,rst;input a;output z;reg z;reg [3:0] currentstate,nextstate;parameter S0 = 4'b0000;parameter S1 = 4'b0001;parameter S2 = 4'b0010;parameter S3 = 4'b0011;parameter S4 = 4'b0100;parameter S5 = 4'b0101; always@(posedge clk or negedge rst) beginif(!rst)currentstate <= S0;elsecurrentstate <= nextstate;endalways@(currentstate or a or rst)beginif(!rst)nextstate = S0;elsecase(currentstate)S0: nextstate = (a==1)?S1:S0;S1: nextstate = (a==0)?S2:S1;S2: nextstate = (a==0)?S3:S1;S3: nextstate = (a==1)?S4:S0;S4: nextstate = (a==0)?S5:S1;S5: nextstate = (a==0)?S3:S1;default: nextstate = S0;endcaseendalways@(rst or currentstate)beginif(!rst)z = 0;elsecase(currentstate)S0: z = 0;S1: z = 0;S2: z = 0;S3: z = 0;S4: z = 0;S5: z = 1;default: z = 0;endcaseend endmodulemoorefsm测试模块testbenchmodule tb_fsm;reg clk,rst;reg a;wire z;moorefsmfsm(.clk(clk),.rst(rst),.a(a),.z(z)); initialbeginclk = 0;rst = 1;#5 rst = 0;#3 rst = 1;#20 a = 1;#100 a = 1;#100 a = 0;#100 a = 0;#100 a = 1;#100 a = 0;#100 a = 0;#100 a = 1;#100 a = 0;#100 a = 0;#100 a = 0;#100 a = 0;#100 a = 1;#100 a = 0;#100 a = 0;#100 a = 1;#100 a = 0;#100 a = 1;#100 a = 0;endalways #50 elk = ~clk; endmoduleMealy型verilog源代码:FSM实现10010串的检测module mealyfsm(clk,rst,a,z);Mealy状态转移图input clk;input rst;input a;output z;reg z;reg [3:0] temp_z;reg [3:0] currentstate,nextstate;parameter S0 = 4'b0000;parameter S1 = 4'b0001;parameter S2 = 4'b0010;parameter S3 = 4'b0011;parameter S4 = 4'b0100;always@(posedge clk or negedge rst) if(!rst) currentstate <= S0;elsecurrentstate <= nextstate;always@(currentstate or a or rst) if(!rst)nextstate = S0;elsecase(currentstate)S0: nextstate = (a == 1)? S1 : S0;S1: nextstate = (a == 0)? S2 : S1;S2: nextstate = (a == 0)? S3 : S1;S3: nextstate = (a == 1)? S4 : S0;S4: nextstate = (a == 0)? S2 : S0;default:nextstate = S0;endcasealways@(rst or currentstate or a) if(!rst)temp_z = 0;elsecase(currentstate)S0: temp_z = 0;S1: temp_z = 0;S2: temp_z = 0;S3: temp_z = 0;S4: temp_z = (a == 0)? 1 : 0;default:temp_z = 0;endcasealways@(posedge clk or negedge rst)if(!rst)z <= 0;elsebeginif((temp_z == 1)&&(nextstate == S2))z <= 1;elsez <= 0;endendmodulemealyfsm 测试模块testbenchmodule tb_fsm;reg clk,rst;reg a;wire z; mealyfsmfsm(.clk(clk),.rst(rst),.a(a),.z(z));initialbeginclk = 0;rst = 1;#5 rst = 0;#3 rst = 1;#20 a = 1;#100 a = 1;#100 a = 0;#100 a = 0;#100 a = 1;#100 a = 0;#100 a = 0;#100 a = 1;#100 a = 0;#100 a = 0;#100 a = 0;#100 a = 0;#100 a = 1;#100 a = 0;#100 a = 0;#100 a = 1;#100 a = 0;#100 a = 1;#100 a = 0;endalways #50 clk = ~clk; endmodule。
(EDA技术及应用)第6章VerilogHDL设计应用实例
第6章 Verilog HDL设计应用实例
6.1 8位加法器的设计
1.系统设计思路 加法器是数字系统中的基本逻辑器件,减法器和硬件乘法器 都可由加法器来构成。多位加法器的构成有两种方式:并行进位和 串行进位。并行进位加法器设有进位产生逻辑,运算速度较快;串 行进位方式是将全加器级联构成多位加法器。并行进位加法器通常 比串行级联加法器占用更多的资源。随着位数的增加,相同位数的 并行加法器与串行加法器的资源占用差距也越来越大。因此,在工 程中使用加法器时,要在速度和容量之间寻找平衡点。 实践证明, 4位二进制并行加法器和串行级联加法器占用几乎相 同的资源。这样,多位加法器由 4位二进制并行加法器级联构成是 较好的折中选择。本设计中的8位二进制并行加法器即是由两个4位 二进制并行加法器级联而成的,其电路原理图如图6.1所示。
在掌握了EDA技术的基础知识和基本操作后,学习 EDA技术最有效地方法就是进行EDA技术的综合应用设计 。本章阐述了12个非常实用的Verilog HDL综合应用设计实 例的系统设计思路,主要Verilog HDL源程序,部分时序仿 真和逻辑综合结果及分析,以及硬件的逻辑验证方法。这些 综合应用设计实例包括8位加法器、8位乘法器、8位除法器 等基本运算电路,数字频率计、数字秒表、交通灯信号控制 器、可调信号发生电路、闹钟系统等常用应用电路,PWM 信号发生器、高速PID控制器,FIR滤波器,CORDIC算法 的应用等电机控制、数字信号处理、模糊控制、神经网络中 经常用到的基本电路。
verilog门电路组合简单设计例化
Verilog门电路组合简单设计例化一、引言在数字电路设计中,Verilog语言被广泛应用于门电路组合的设计和仿真。
门电路组合的设计是数字电路领域中的基础知识之一,对于理解数字电路的原理和应用至关重要。
本文将围绕Verilog门电路组合的简单设计例化展开讨论,从基础概念开始,逐步深入,帮助读者全面、深刻地理解这一主题。
二、Verilog语言简介Verilog是一种硬件描述语言(HDL),主要用于描述数字逻辑电路。
它类似于一种程序设计语言,但其目的是用于描述电子系统,而不是软件程序。
Verilog具有丰富的语法结构,可以描述从简单的门电路到复杂的集成电路的各个层次。
三、门电路组合简介门电路是数字电路领域的基础组成部分,它由与门、或门、非门等基本逻辑门构成。
组合电路是一种数字电路,它的输出完全取决于当前输入状态,与电路的历史状态无关。
门电路组合设计就是通过组合这些基本的逻辑门,构建出完成特定逻辑功能的电路。
四、Verilog门电路组合的设计流程1. 确定功能需求:首先需要明确要设计的门电路要实现什么功能,比如加法器、减法器、比较器等。
2. 逻辑设计:根据功能需求,进行逻辑设计,确定需要用到的基本逻辑门,以及它们之间的连接关系。
3. Verilog编写:利用Verilog语言描述逻辑设计,包括模块的定义、端口的声明、逻辑功能的描述等。
4. 仿真验证:通过仿真工具对Verilog代码进行仿真验证,确保设计符合预期的功能需求。
5. 综合与布局:进行逻辑综合和布局布线,将逻辑设计映射到实际的物理电路中。
6. 下载与测试:将设计好的Verilog门电路下载到目标芯片中进行测试,验证设计的正确性和稳定性。
五、深入理解Verilog门电路组合设计在Verilog门电路组合的设计过程中,需要注意以下几个重要的方面。
1. 模块化设计:在实际设计时,应该将功能模块化,保持清晰的模块划分,利用模块化的设计思想,可以提高设计的可维护性和可重用性。
verilog优化逻辑的例子
verilog优化逻辑的例子Verilog是一种硬件描述语言,用于描述数字逻辑电路。
在设计和实现数字逻辑电路时,优化逻辑是至关重要的。
通过优化逻辑可以提高电路的性能、减少功耗、降低成本等。
下面列举了10个以Verilog优化逻辑的例子。
1. 使用位移操作代替乘法运算:在一些情况下,乘法运算需要大量的硬件资源,可以使用位移操作来代替乘法运算,从而减少硬件资源的使用。
2. 使用并行操作代替串行操作:在一些情况下,串行操作需要较长的延迟时间,可以使用并行操作来代替串行操作,从而减少延迟时间。
3. 优化状态机:对于复杂的状态机,可以通过精简状态转移图或者使用更高效的状态编码方式来优化状态机的逻辑。
4. 使用查找表代替复杂的逻辑判断:对于一些复杂的逻辑判断,可以使用查找表来代替,从而简化逻辑电路。
5. 使用流水线技术:对于一些需要处理大量数据的电路,可以使用流水线技术将处理过程划分为多个阶段,从而提高电路的吞吐量。
6. 使用FIFO缓冲区:在一些需要缓存数据的电路中,使用FIFO缓冲区可以有效地管理数据的输入和输出,提高电路的处理能力。
7. 使用复用器和选择器:在一些需要多路复用和选择的电路中,使用复用器和选择器可以减少硬件资源的使用,简化电路的逻辑。
8. 使用加法器代替减法器:在一些需要进行减法运算的电路中,可以通过转换运算表达式,使用加法器来代替减法器,从而减少硬件资源的使用。
9. 使用编码器和解码器:在一些需要进行编码和解码的电路中,使用编码器和解码器可以简化逻辑电路,降低硬件资源的使用。
10. 使用异步时序逻辑:在一些需要处理异步信号的电路中,使用异步时序逻辑可以提高电路的响应速度和稳定性。
通过以上的优化技术,可以有效地提高数字逻辑电路的性能和效率。
在实际应用中,根据具体的设计需求和资源限制,选择适合的优化技术进行逻辑优化,可以使电路更加高效、可靠和经济。
第六章 Verilog HDL高级程序设计举例
10/7/2013
Microelectronics School Xidian University
7
6.2典型电路设计
• 6.2.1加法器树乘法器
加法器树乘法器的设计思想是“移位后加”,并且加法运算采用加法器 树的形式。乘法运算的过程是,被乘数与乘数的每一位相乘并且乘以 相应的权值,最后将所得的结果相加,便得到了最终的乘法结果。 例:下图是一个4位的乘法器结构,用Verilog HDL设计一个加法器树 4位乘法器
module mult_addtree_tb; reg [3:0]mult_a; reg [3:0]mult_b; wire [7:0]mult_out; // module instance mul_addtree U1(.mul_a(mult_a),.mul_b(mult_b),.mul_out(mult_out)); initial //Stimuli signal begin mult_a=0; mult_b=0; repeat(9) begin #20 mult_a=mult_a+1; mult_b=mult_b+1; end end endmodule
10/7/2013
Xidian University
11
module mult_addtree_2_stag_tb; reg clk, clr; reg [3:0]mult_a, mult_b; wire [7:0]mult_out; mul_addtree_2_stage U1(.mul_a(mult_a),.mul_b(mult_b), .mul_out(mult_out),.clk(clk),.clr(clr)); initial begin clk=0; clr=0; mult_a=1; mult_b=1; #5 clr=1; end always #10 clk=~clk; initial begin repeat(5) begin #20 mult_a=mult_a+1; mult_b=mult_b+1; end end endmodule
100例VERILOG
【例3.1】4 位全加器【例3.2】4 位计数器【例3.3】4 位全加器的仿真程序【例3.4】4 位计数器的仿真程序【例3.5】“与-或-非”门电路【例5.1】用case 语句描述的4 选1 数据选择器【例5.2】同步置数、同步清零的计数器【例5.3】用always 过程语句描述的简单算术逻辑单元【例5.4】用initial 过程语句对测试变量A、B、C 赋值【例5.5】用begin-end 串行块产生信号波形【例5.6】用fork-join 并行块产生信号波形【例5.7】持续赋值方式定义的2 选1 多路选择器【例5.8】阻塞赋值方式定义的2 选1 多路选择器【例5.9】非阻塞赋值【例5.10】阻塞赋值【例5.11】模为60 的BCD 码加法计数器【例5.12】BCD 码—七段数码管显示译码器【例5.13】用casez 描述的数据选择器【例5.14】隐含锁存器举例【例5.15】用for 语句描述的七人投票表决器【例5.16】用for 语句实现2 个8 位数相乘【例5.17】用repeat 实现8 位二进制数的乘法【例5.18】同一循环的不同实现方式【例5.19】使用了`include 语句的16 位加法器【例5.20】条件编译举例【例6.1】加法计数器中的进程【例6.2】任务举例【例6.3】测试程序【例6.4】函数【例6.5】用函数和case 语句描述的编码器(不含优先顺序)【例6.6】阶乘运算函数【例6.7】测试程序【例6.8】顺序执行模块1【例6.9】顺序执行模块2【例6.10】并行执行模块1【例6.11】并行执行模块2【例7.1】调用门元件实现的4 选1 MUX【例7.2】用case 语句描述的4 选1 MUX【例7.3】行为描述方式实现的4 位计数器【例7.4】数据流方式描述的4 选1 MUX【例7.5】用条件运算符描述的4 选1 MUX【例7.6】门级结构描述的2 选1MUX【例7.7】行为描述的2 选1MUX【例7.8】数据流描述的2 选1MUX【例7.9】调用门元件实现的1 位半加器【例7.10】数据流方式描述的1 位半加器【例7.11】采用行为描述的1 位半加器【例7.12】采用行为描述的1 位半加器【例7.13】调用门元件实现的1 位全加器【例7.14】数据流描述的1 位全加器【例7.15】1 位全加器【例7.16】行为描述的1 位全加器【例6.2】任务举例【例6.3】测试程序【例6.4】函数【例6.5】用函数和case 语句描述的编码器(不含优先顺序)【例6.6】阶乘运算函数【例6.7】测试程序【例6.8】顺序执行模块1【例6.9】顺序执行模块2【例6.10】并行执行模块1【例6.11】并行执行模块2【例7.1】调用门元件实现的4 选1 MUX【例7.2】用case 语句描述的4 选1 MUX【例7.3】行为描述方式实现的4 位计数器【例7.4】数据流方式描述的4 选1 MUX【例7.5】用条件运算符描述的4 选1 MUX【例7.6】门级结构描述的2 选1MUX【例7.7】行为描述的2 选1MUX【例7.8】数据流描述的2 选1MUX【例7.9】调用门元件实现的1 位半加器【例7.10】数据流方式描述的1 位半加器【例7.11】采用行为描述的1 位半加器【例7.12】采用行为描述的1 位半加器【例7.13】调用门元件实现的1 位全加器【例7.14】数据流描述的1 位全加器【例7.15】1 位全加器【例7.16】行为描述的1 位全加器【例7.17】混合描述的1 位全加器【例7.18】结构描述的4 位级连全加器【例7.19】数据流描述的4 位全加器【例7.20】行为描述的4 位全加器【例8.1】$time 与$realtime 的区别【例8.2】$random 函数的使用【例8.3】1 位全加器进位输出UDP 元件【例8.4】包含x 态输入的1 位全加器进位输出UDP 元件【例8.5】用简缩符“?”表述的1 位全加器进位输出UDP 元件【例8.6】3 选1 多路选择器UDP 元件【例8.7】电平敏感的1 位数据锁存器UDP 元件【例8.8】上升沿触发的D 触发器UDP元件【例8.9】带异步置1 和异步清零的上升沿触发的D 触发器UDP 元件【例8.12】延迟定义块举例【例8.13】激励波形的描述【例8.15】用always 过程块产生两个时钟信号【例8.17】存储器在仿真程序中的应用【例8.18】8 位乘法器的仿真程序【例8.19】8 位加法器的仿真程序【例8.20】2 选1 多路选择器的仿真【例8.21】8 位计数器的仿真【例9.1】基本门电路的几种描述方法【例9.2】用bufif1 关键字描述的三态门【例9.3】用assign 语句描述的三态门【例9.4】三态双向驱动器【例9.5】三态双向驱动器【例9.6】3-8 译码器【例9.7】8-3 优先编码器【例9.8】用函数定义的8-3 优先编码器【例9.9】七段数码管译码器【例9.10】奇偶校验位产生器【例9.11】用if-else 语句描述的4 选1 MUX【例9.12】用case 语句描述的4 选1 MUX【例9.13】用组合电路实现的ROM【例9.14】基本D 触发器【例9.15】带异步清0、异步置1 的D 触发器【例9.16】带同步清0、同步置1 的D 触发器【例9.17】带异步清0、异步置1 的JK 触发器【例9.18】电平敏感的1 位数据锁存器【例9.19】带置位和复位端的1 位数据锁存器【例9.20】8 位数据锁存器【例9.21】8 位数据寄存器【例9.22】8 位移位寄存器【例9.23】可变模加法/减法计数器【例9.24】4 位Johnson 计数器(异步复位)【例9.25】256×8 RAM 模块【例9.26】256×16 RAM 块【例9.27】4 位串并转换器【例9.28】用函数实现简单的处理器【例9.29】微处理器的测试代码【例9.30】乘累加器(MAC)代码【例9.31】乘累加器的测试代码【例10.1】非流水线方式8 位全加器【例10.2】4 级流水方式的8 位全加器【例10.3】两个加法器和一个选择器的实现方式【例10.4】两个选择器和一个加法器的实现方式【例10.5】状态机设计的例子【例10.6】自动转换量程频率计控制器【例10.7】8 位全加器【例10.8】8 位寄存器【例10.9】累加器顶层连接文本描述【例10.10】用`include 描述的累加器【例10.11】阻塞赋值方式描述的移位寄存器1【例10.12】阻塞赋值方式描述的移位寄存器2【例10.13】阻塞赋值方式描述的移位寄存器3【例10.14】非阻塞赋值方式描述的移位寄存器【例10.15】长帧同步时钟的产生【例10.16】引入了D 触发器的长帧同步时钟的产生【例11.1】数字跑表【例11.2】4 位数字频率计控制模块【例11.3】4 位数字频率计计数子模块【例11.4】频率计锁存器模块【例11.5】交通灯控制器【例11.6】“梁祝”乐曲演奏电路【例11.7】自动售饮料机【例11.8】多功能数字钟【例11.9】电话计费器程序【例12.1】8 位级连加法器【例12.2】8 位并行加法器【例12.3】8 位超前进位加法器【例12.4】8 位并行乘法器【例12.5】4×4 查找表乘法器【例12.6】8 位加法树乘法器【例12.7】11 阶FIR 数字滤波器【例12.8】16 位高速数字相关器【例12.9】(7,4)线性分组码编码器【例12.10】(7,4)线性分组码译码器【例12.11】(7,4)循环码编码器【例12.12】(7,4)循环码纠错译码器【例12.13】CRC 编码。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
begin b=a; c=b; end endmodule
【例 5.11】模为 60 的 BCD 码加法计数器
module count60(qout,cout,data,load,cin,reset,clk);
【例 5.6】用 fork-join 并行块产生信号波形
`timescale 10ns/1ns module wave2; reg wave; parameter cycle=5; initial
fork wave=0;
#(cycle) wave=1; #(2*cycle) wave=0; #(3*cycle) wave=1; #(4*cycle) wave=0; #(5*cycle) wave=1; #(6*cycle) $finish; join initial $monitor($time,,,"wave=%b",wave); endmodule
else
out<=out+1;
end
endmodule
//同步复位 //计数
【例 3.3】4 位全加器的仿真程序
`timescale 1ns/1ns `include "adder4.v" module adder_tp; reg[3:0] a,b; reg cin; wire[3:0] sum; wire cout; integer i,j;
output[7:0] qout;
output cout;
input[7:0] data;
input load,cin,clk,reset;
reg[7:0] qout; always @(posedge clk)
//clk 上升沿时刻计数
-6-
王金明:《Verilog HDL 程序设计教程》
begin if (reset) else if(load)
//设定 a 的取值
end
-1-
程序文本
initial begin for(j=1;j<16;j=j+1) #10 b=j; end
//设定 b 的取值
initial
//定义结果显示格式
begin
$monitor($time,,,"%d + %d + %b={%b,%d}",a,b,cin,cout,sum);
//敏感信号列表
case(sel)
2'b00: out=in0;
2'b01: out=in1;
2'b10: out=in2;
2'b11: out=in3;
default: out=2'bx;
endcase
endmodule
【例 5.2】同步置数、同步清零的计数器
module count(out,data,load,reset,clk);
//高位不为 5,则加 1
end else
//低位不为 9,则加 1
qout[3:0]<=qout[3:0]+1;
end
end assign cout=((qout==8'h59)&cin)?1:0;
//产生进位输出信号
endmodule
【例 5.12】BCD 码—七段数码管显示译码器
module decode4_7(decodeout,indec);
end //定义结果显示格式
initial $monitor($time,,,"clk=%d reset=%d out=%d", clk, reset,out);
endmodule
【例 3.5】“与-或-非”门电路
module AOI(A,B,C,D,F); input A,B,C,D; output F; -2-
begin A = 0; B = 1; C = 0;
#50 A = 1; B = 0; #50 A = 0; C = 1; #50 B = 1; #50 B = 0; C = 0; #50 $finish ; end endmodule
【例 5.5】用 begin-end 串行块产生信号波形
`timescale 10ns/1ns module wave1; reg wave; parameter cycle=10; initபைடு நூலகம்al
王金明:《Verilog HDL 程序设计教程》
【例 3.2】4 位计数器
module count4(out,reset,clk);
output[3:0] out;
input reset,clk;
reg[3:0] out;
always @(posedge clk)
begin
if (reset) out<=0;
count4 mycount(out,reset,clk);
//调用测试对象
always #(DELY/2) clk = ~clk;
//产生时钟波形
initial begin
//激励信号定义
clk =0; reset=0;
#DELY reset=1;
#DELY reset=0;
#(DELY*20) $finish;
【例 5.7】持续赋值方式定义的 2 选 1 多路选择器
module MUX21_1(out,a,b,sel); input a,b,sel; output out; assign out=(sel==0)?a:b;
//持续赋值,如果 sel 为 0,则 out=a ;否则 out=b endmodule
4'd2:decodeout=7'b1101101;
4'd3:decodeout=7'b1111001;
4'd4:decodeout=7'b0110011;
4'd5:decodeout=7'b1011011;
4'd6:decodeout=7'b1011111;
4'd7:decodeout=7'b1110000;
output[7:0] out;
input[7:0] data;
input load,clk,reset;
reg[7:0] out;
always @(posedge clk)
begin
if (!reset)
out = 8'h00;
else if (load) out = data;
else
out = out + 1;
output[6:0] decodeout;
input[3:0] indec;
reg[6:0] decodeout;
always @(indec)
begin case(indec)
//用 case 语句进行译码
4'd0:decodeout=7'b1111110;
4'd1:decodeout=7'b0110000;
4'd8:decodeout=7'b1111111;
4'd9:decodeout=7'b1111011;
default: decodeout=7'bx;
endcase
end
-7-
程序文本 endmodule
【例 5.13】用 casez 描述的数据选择器
module mux_casez(out,a,b,c,d,select); output out; input a,b,c,d; input[3:0] select; reg out; always @(select or a or b or c or d)
-3-
程序文本 module alu(out,opcode,a,b); output[7:0] out; reg[7:0] out; input[2:0] opcode; input[7:0] a,b; always@(opcode or a or b) begin case(opcode) `add: out = a+b; `minus: out = a-b; `band: out = a&b; `bor: out = a|b; `bnot: out=~a; default: out=8'hx; endcase end endmodule
#160 $finish; end
endmodule
【例 3.4】4 位计数器的仿真程序
`timescale 1ns/1ns `include "count4.v" module coun4_tp; reg clk,reset; wire[3:0] out; parameter DELY=100;
//测试输入信号定义为 reg 型 //测试输出信号定义为 wire 型
out=b;
endmodule
【例 5.9】非阻塞赋值
module non_block(c,b,a,clk);
output c,b; input clk,a;
reg c,b;
always @(posedge clk)
begin
b<=a; c<=b; end
endmodule
//阻塞赋值
【例 5.10】阻塞赋值
begin -4-
王金明:《Verilog HDL 程序设计教程》 wave=0; #(cycle/2) wave=1; #(cycle/2) wave=0; #(cycle/2) wave=1; #(cycle/2) wave=0; #(cycle/2) wave=1; #(cycle/2) $finish ; end initial $monitor($time,,,"wave=%b",wave); endmodule