数字系统设计verilog HDL 第 版 王金明
- 格式:pdf
- 大小:3.61 MB
- 文档页数:41
数字系统设计与veriloghdl课后答案【篇一:数字逻辑与数字系统设计习题参考答案】>第1章习题解答1.3 (1)86(2)219(3)106.25(4)0.6875 (4)0.1011.4 (1)101111(2)1001000(3)100001l.111.5 (1)(117)10=(165)8=(1110101)2=(75)16(2)(3452)10=(6574)8=(110101111100)2=(d7c)16(3)(23768.6875)10=(56330.54)8=(101110011011000.1011)2=(5cd 8.b)16 (4)(0.625)10=(0.5)8=(0.101)2=(0.a)16 1.6(1)(117)8=(1001111)2=(79)10(2)(7456)8=(111100101110)2=(3886)10(3)(23765.64)8=(10 0111 1111 0101.1101)2=(10229.8125)10(4)(0.746)8=(0.11111)2=(0.96875)10 1.7 (1)(9a)16=(10011010)2=(154)10(2) (3cf6)16=(11110011110110)2=(15606)10(3) (7ffe.6)16=(111111*********.011)2=(32766.375)10 (4)(0.c4)16=(0.110001)2=(0.765625)10 1-8(1)(125)10=(000100100101)8421bcd(2)(7342)10=(0111001101000010)8421bcd(3)(2018.49)10=(0010000000011000.01001001)8421bcd(4)(0.785)10=(0.011110000101)8421bcd1.9(1)(106)10=(1101010)2 原码=反码=补码=01101010 (2)(-98)10=(-1100010)2原码=11100010反码=10011101 补码=11100011(3)(-123)10=(-1111011)2 原码=11111011反码=10000101 补码=11111011(4)(-0.8125)10=(-0.1101)2 原码=1.1101000反码=1.0010111 补码=1.00110001.10(1)(104)10=(1101000)2 [1101000]补=01101000(-97)10=(-1100001)2 [-1100001]补=1001111101101000 + 10011111 0000011110000011 + 01001111 11010010[104-97]补=01101000+10011111=00000111, 104-97=(00000111)2=7 (2) (-125)10=(-1111101)2(79)10=(01001111)2[-1111101]补=10000011 [01001111]补=0100111101111000 [-125+79]补=10000011+01001111=11010010,-125+79=(-0101110)2=-46 (3) (120)10=(1111000)2[01111000]补=01111000(-67)10=(-1000011)2[-1000011]补=10111101[120-67]补=10000011+01001111=00110101,-125+79=(00110101)2=53 (4) (-87)10=(-1010111)2[-1010111]补=10101001(12)10=(1100)2[1100]补=00001100[-87+12]补=10101001+00001100=10110101,-125+79=(-1001011)2=-75+ 10111101 0011010110101001+ 00001100 10110101第2章习题解答2.3 解:根据逻辑图可直接写出逻辑表达式:(a) f=ab?bc;(b)f=abbcac解:设3个输入变量分别为a、b、c,输出为f,按题意,其中有奇数个为1,则输出f=1,因此可写出其逻辑表达式为f=abc?abc?abc?abc。
第9章 Verilog设计进阶9.1 加法器设计(1)级连加法器8位级连加法器module add_jl(sum,cout,a,b,cin);input[7:0] a,b;input cin;output[7:0] sum;output cout;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); full_add1 f3(a[3],b[3],cin3,sum[3],cin4); full_add1 f4(a[4],b[4],cin4,sum[4],cin5); full_add1 f5(a[5],b[5],cin5,sum[5],cin6); full_add1 f6(a[6],b[6],cin6,sum[6],cin7); full_add1 f7(a[7],b[7],cin7,sum[7],cout); endmodule(2)数据流描述的加法器module add_bx(cout,sum,a,b,cin); parameter WIDTH=8; input cin; output cout; input[WIDTH-1:0] a,b; output[WIDTH-1:0] sum; assign {cout,sum}=a+b+cin;endmodule(3) 8位超前进位加法器moduleadd_ahead(sum,cout,a,b,cin); input[7:0] a,b;input cin;output[7:0] sum;output cout;wire[7:0] G,P;wire[7:0] C,sum;assign G[0]=a[0]&b[0]; assign P[0]=a[0]|b[0]; assign C[0]=cin;assign sum[0]=G[0]^P[0]^C[0]; assign G[1]=a[1]&b[1]; assign P[1]=a[1]|b[1]; assign C[1]=G[0]|(P[0]&cin); assign sum[1]=G[1]^P[1]^C[1]; assign G[2]=a[2]&b[2]; assign P[2]=a[2]|b[2]; assign C[2]=G[1]|(P[1]&C[1]); assign sum[2]=G[2]^P[2]^C[2]; assign G[3]=a[3]&b[3]; assign P[3]=a[3]|b[3]; assign C[3]=G[2]|(P[2]&C[2]); assign sum[3]=G[3]^P[3]^C[3];assign G[4]=a[4]&b[4]; assign P[4]=a[4]|b[4]; assign C[4]=G[3]|(P[3]&C[3]); assign sum[4]=G[2]^P[2]^C[2]; assign G[5]=a[5]&b[5]; assign P[5]=a[5]|b[5]; assign C[5]=G[4]|(P[4]&C[4]); assign sum[5]=G[5]^P[5]^C[5]; assign G[6]=a[6]&b[6]; assign P[6]=a[6]|b[6]; assign C[6]=G[5]|(P[5]&C[5]); assign sum[6]=G[6]^P[6]^C[6]; assign G[7]=a[7]&b[7]; assign P[7]=a[7]|b[7]; assign C[7]=G[6]|(P[6]&C[6]); assign sum[7]=G[7]^P[7]^C[7]; assign cout=G[7]|(P[7]&C[7]); endmodule(4)流水线加法器module adder8(cout,sum,a,b,cin,enable); input[7:0] a,b; input cin,enable; output[7:0] sum; reg[7:0] sum;output cout;reg cout;reg[3:0] tempa,tempb,firsts; reg firstc; always @(posedge enable)begin{firstc,firsts}=a[3:0]+b[3:0]+cin; tempa=a[7:4]; tempb=b[7:4];endalways @(posedge enable)begin{cout,sum[7:4]}=tempa+tempb+firstc; sum[3:0]=firsts;endendmodule9.2 乘法器)并行乘法器(1module mult(outcome,a,b); parameter size=8;input[size:1] a,b;output[2*size:1] outcome; assign outcome=a*b;endmodule8×8并行乘法器的门级综合原理图(2)移位相加乘法器4×4移位相加乘法操作示意图8位移位相加乘法器顶层设计8位移位相加乘法器时序仿真波形(3)布斯乘法器(4)查找表乘法器9.3 奇数分频与小数分频(1)奇数分频module count7(reset,clk,cout);input clk,reset; output wire cout;reg[2:0] m,n; reg cout1,cout2;assign cout=cout1|cout2;//两个计数器的输出相或always @(posedge clk)beginif(!reset) begin cout1<=0; m<=0; endelse begin if(m==6) m<=0; else m<=m+1;if(m<3) cout1<=1;else cout1<=0; end endalways @(negedge clk)beginif(!reset) begin cout2<=0; n<=0; endelse begin if(n==6) n<=0; else n<=n+1;if(n<3) cout2<=1; else cout2<=0; end endendmodule模7奇数分频器功能仿真波形图(Quartus Ⅱ)module count_num(reset,clk,cout);parameter NUM=13;input clk,reset; output wire cout;reg[4:0] m,n; reg cout1,cout2;assign cout=cout1|cout2;always @(posedge clk)begin if(!reset) begin cout1<=0; m<=0; endelsebegin if(m==NUM-1) m<=0; else m<=m+1;if(m<(NUM-1)/2) cout1<=1; else cout1<=0;endendalways @(negedge clk)begin if(!reset) begin cout2<=0; n<=0; endelse beginif(n==NUM-1) n<=0; else n<=n+1;if(n<(NUM-1)/2) cout2<=1; else cout2<=0; end endendmodule模13奇数分频器功能仿真波形图(Quartus Ⅱ)module fdiv5_5(clkin,clr,clkout);input clkin,clr; output reg clkout;reg clk1; wire clk2; integer count;xor xor1(clk2,clkin,clk1); //异或门always@(posedge clkout or negedge clr) //2分频器begin if(~clr) begin clk1<=1'b0; endelse clk1<=~clk1;endalways@(posedge clk2 or negedge clr) //模5分频器begin if(~clr)begin count<=0; clkout<=1'b0; endelse if(count==5) //要改变分频器的模,只需改变count的值begin count<=0; clkout<=1'b1; endelse begin count<=count+1; clkout<=1'b0; end endendmodule功能仿真波形5.5倍半整数分频器功能仿真波形图(Quartus Ⅱ)小数分频module fdiv8_1(clk_in,rst,clk_out);input clk_in,rst; output reg clk_out;reg[3:0] cnt1,cnt2;//cnt1计分频的次数always@(posedge clk_in or posedge rst)begin if(rst) begin cnt1<=0; cnt2<=0; clk_out<=0; endelse if(cnt1<9)//9次8分频begin if(cnt2<7) begin cnt2<=cnt2+1; clk_out<=0; end else begin cnt2<=0; cnt1<=cnt1+1; clk_out<=1; end end else begin //1次9分频if(cnt2<8) begin cnt2<=cnt2+1; clk_out<=0; end else begin cnt2<=0; cnt1<=0; clk_out<=1; endend endendmodule8.1小数分频功能仿真波形(Quartus Ⅱ)9.4 VGA图像显示控制器设计VGA 行扫描时序VGA 场扫描时序标准VGA显示模式行、场扫描的时序行扫描时序要求(单位:像素,输出一个Pixel的时间间隔)行同步头行图像行周期对应位置H_Tf H_Ta H_Tb H_Tc H_Td H_Te H_Tg时间/Pixels8964086408800场扫描时序要求(单位:行,输出一行Line的时间间隔)场同步头场图像场周期对应位置V_Tf V_Ta V_Tb V_Tc V_Td V_Te V_Tg时间/Lines222584808525VGA图像显示控制器设计VGA图像显示控制器结构框图R,G,B三基色信号分别采用5 bit,6 bit,5 bit表示的LENA图像9.5 点阵式液晶显示控制GDM12864的结构及指令“写数据”时序图液晶控制9.6 乐曲演奏电路乐曲演奏的原理乐曲演奏电路原理框图习题 9习题 9习题 9实验与设计。
王金明:《Verilog HDL 程序设计教程》- 1 -【例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 的取值Endinitialbeginfor(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; //模块的输出端口为Fwire 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'd4module 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`timescale 1ns/1ns`include "alu.v"module alu_tb;wire [7:0] out;reg [7:0] a,b;reg [2:0] opcode;initialbegina = 8'h12;b = 8'h34;opcode = `add;#10 opcode = `minus;#10 opcode = `band;#10 opcode = `bor;#10 opcode = `bnot;endalu alu(.out(out),.a(a),.b(b),.opcode(opcode)); endmodule【例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;initialbeginwave=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;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`timescale 1ns/1ns`include "block.v"module block_tb;wire c,b;reg clk,a;initialbeginclk = 0;a = 0;#30 a = 1;#30 a = 0;#30 a = 1;#30 $stop;endalways #10 clk = ~clk;block block(.c(c),.b(b),.clk(clk),.a(a));endmodule【例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 上升沿时刻计数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`timescale 1ns/1ns`include "count60.v"module count60_tb;wire [7:0] qout;wire cout;reg [7:0] data;reg load,cin,clk,reset;always #5 clk = ~clk;count60cnt(.qout(qout),.cout(cout),.data(data),.load(load),.cin(cin),.cl k(clk),.reset(reset));initialbeginclk = 0;reset = 1;load = 1; cin = 0; data = 8'h25;#20 reset = 0;#20 load = 0;#30 cin = 1;#100 load = 1;#30 load = 0;#300 cin = 0;#50 cin = 1;#500 $stop;endendmodule【例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;endcaseendendmodule【例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'b1: 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;- 9 -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【例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 左移一位程序文本- 10 -temp_b=temp_b>>1; //操作数b 右移一位endendendmodule`include "mult_repeat.v"module mult_repeat_tb;parameter size = 8;reg [size:1] a,b;wire [2*size:1] outcome;initialbegina = 8'h25;b = 8'h16;#10 a = 8'ha4; b = 8'h20;endmult_repeat mult(.a(a),.b(b),.outcome(outcome)); endmodule【例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 位加法器- 11 -`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;程序文本- 12 -always @(posedge clk) //进程1,always 过程块beginif (!reset) qout= 4'h00; //同步清0,低电平有效else if (load) qout= data; //同步预置else qout=qout + 1; //加法计数endassign cout=(qout==4'hf)?1:0; //进程2,用持续赋值产生进位信号endmodule【例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; //相加endcaseendendmodule- 13 -【例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;程序文本- 14 -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- 15 -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 #1 `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】顺序执行模块2module serial2(q,a,clk);output q,a;程序文本- 16 -input clk;reg q,a;always @(posedge clk)begina=~q;q=~q;endendmodule【例6.10】并行执行模块1module 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- 17 -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程序文本- 18 -【例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 选1MUX module MUX2_1c(out,a,b,sel); output out;- 19 -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; end endcaseendendmodule【例7.12】采用行为描述的1 位半加器module half_add4(a,b,sum,cout); input a,b;output sum,cout;程序文本- 20 -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;- 21 -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);程序文本- 22 -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- 23 -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;程序文本- 24 -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,则进位输出肯定为00 x 0 : 0;x 0 0 : 0;1 1 x : 1; //只要有两个输入为1,则进位输出肯定为11 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;// cin a b : cout //真值表0 0 : 0; //只要有两个输入为0,则进位输出肯定为00 ? 0 : 0;0 0 ? : 0;1 1 : 1; //只要有两个输入为1,则进位输出肯定为11 ? 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- 25 -1 0 1 : 1;0 1 : 0; //当s2s1=1?时,Y=in21 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;initial Q = 1'b1; //初始化table// clk reset D : state : Q1 : : 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 保持原值() : : - ; //时钟不变,输出也不变程序文本- 26 -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 set : 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;- 27 -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; //读使能信号,低电平有效程序文本- 28 -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 mult8_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; //乘法运算符- 29 -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); endmodulemodule 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;程序文本- 30 -MUX2_1 m1(out,a,b,sel); //调用待测试模块initialbegina=1'b0; b=1'b0; sel=1'b0;#5 sel=1'b1;#5 a=1'b1; sel=1'b0;#5 sel=1'b1;#5 a=1'b0; b=1'b1; sel=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 counter8_tp;reg clk,reset; //输入激励信号定义为reg 型wire[7:0] qout; //输出信号定义为wire 型parameter DELY=100;counter8 C1(qout,reset,clk); //调用测试对象always #(DELY/2) clk = ~clk; //产生时钟波形initialbegin //激励波形定义clk =0; reset=0;- 31 -#DELY reset=1;#DELY reset=0;#(DELY*300) $finish;end//结果显示initial $monitor($time,,,"clk=%d reset=%d qout=%d",clk,reset,qout); endmodulemodule counter8(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);endmodule(2)数据流描述module gate2(F,A,B,C,D);input A,B,C,D;output F;assign F=(A&B)|(B&C&D); //assign 持续赋值endmodule(3)行为描述module gate3(F,A,B,C,D);input A,B,C,D;output F;程序文本- 32 -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- 33 -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;。
第5章 Verilog语法与要素5.1 Verilog语言要素空白符和注释标识符(Identifiers)=count=COUNT //COUNT与count是不同的=_A1_d2 //以下划线开头=R56_68=FIVE关键字(Keywords)5.2 常量实数(Real)字符串(Strings)5.3 数据类型数据类型5.3.1 net型5.3.2 Variable型5.4 参数(parameter)【例5.2】采用参数定义的数据比较器module compare_w(a,b,larger,equal,less); parameter SIZE=6; //参数定义input[SIZE-1:0] a,b;output larger,equal,less;wire larger,equal,less;assign larger=(a>b);assign equal=(a==b);assign less=(a<b);endmodule【例5.3】采用参数定义的加法器module add_w(a,b,sum); parameter MSB=15; //参数定义input[MSB:0] a,b;output[MSB+1:0] sum;assign sum=a+b; endmodule【例5.4】采用参数定义的二进制计数器module count_w(en,clk,reset,out); input clk,reset,en;parameter WIDTH=8; //参数定义output[WIDTH-1:0] out;reg[WIDTH-1:0] out;always @(posedge clk or negedge reset) if(!reset) out=0;else if(en) out=out+1; endmodule5.5 向量n1.标量与向量宽度为1位的变量称为标量,如果在变量声明中没有指定位宽,则默认为标量(1位)。
EDA技术与Verilog设计王金明版第12章Verilog语言的发展EDA技术与Verilog设计是现代数字电路设计中非常重要的两个方面。
EDA技术(Electronic Design Automation)是指利用计算机辅助设计工具来帮助进行电子系统的设计和验证。
Verilog是一种硬件描述语言(HDL),用于设计和描述数字电路。
本文将重点介绍Verilog语言的发展。
Verilog语言最初由Gateway Design Automation公司的Phil Moorby和Prabhu Goel于1983年开始开发,用于辅助数字电路设计。
当时的数字电路设计主要使用原理图和编程方式,导致设计效率低下和错误的增多。
为了解决这些问题,硬件描述语言应运而生。
最早的Verilog语言是在原始C语言的基础上进行扩展,引入了许多与硬件相关的特性。
这使得Verilog的语法相对于C语言更加接近硬件描述。
Verilog语言可以描述电路的功能和结构,包括时序逻辑、组合逻辑、寄存器和存储器等。
随着硬件设计需求的不断增加,Verilog语言不断发展。
VerilogHDL 1364标准于1995年发布,引入了许多新的功能和特性。
其中最重要的是系统任务和函数,用于模拟系统级行为。
SystemVerilog语言于2002年推出,是Verilog HDL的扩展,引入了更多的高层次设计特性和验证特性。
Verilog语言的发展主要有以下几个方面的影响:1. 高层次综合(High-Level Synthesis,HLS)技术的发展对Verilog语言产生了深远的影响。
HLS技术允许设计者以高层次的抽象描述电路功能,然后将其自动转化为硬件电路。
这大大提高了设计的效率和可移植性。
Verilog语言的发展也使得其更加适合进行高层次综合。
2. 验证技术的发展也推动了Verilog语言的演进。
在设计过程中,验证是非常重要的一环。
随着电路规模的不断增加,传统的模拟仿真已经无法满足验证的需求。
第7章 Verilog设计的层次与风格7.1 Verilog设计的层次Verilog设计的描述风格7.2 结构(Structural)描述内置门元件【例7.1】调用门元件实现的4选1 MUXmodule mux4_1a(out,in1,in2,in3,in4,s0,s1); input in1,in2,in3,in4,s0,s1; output out; wire s0_n,s1_n,w,x,y,z;not (sel0_n,s0),(s1_n,s1);and (w,in1,s0_n,s1_n),(x,in2,s0_n,s1), (y,in3,s0,s1_n),(z,in4,s0,s1);or (out,w,x,y,z);endmodule用基本门实现的4选1 MUX7.3 行为描述【例7.2】用case语句描述的4选1 MUXmodule mux4_1b(out,in1,in2,in3,in4,s0,s1); input in1,in2,in3,in4,s0,s1;output reg out;always@(*) //使用通配符 case({s0,s1})2'b00:out=in1;2'b01:out=in2;2'b10:out=in3;2'b11:out=in4;default:out=2'bx;endcaseendmodule采用行为描述方式时需注意7.4 数据流描述【例7.4】数据流描述的4选1 MUXmodule mux4_1c(out,in1,in2,in3,in4,s0,s1); input in1,in2,in3,in4,s0,s1;output out;assign out=(in1 & ~s0 & ~s1)|(in2 & ~s0 & s1)| (in3& s0 & ~s1)|(in4 & s0 & s1); endmodule数据流描述7.5 不同描述风格的设计【例7.12】调用门元件实现的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数据流描述的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行为描述的1位全加器【例7.14】行为描述的1位全加器module full_add3(a,b,cin,sum,cout); input a,b,cin;output reg sum,cout;always @*//或写为always @(a or b or cin) begin{cout,sum}=a+b+cin;endendmodule采用层次化方式设计1位全加器两个半加器构成一个全加器【例7.15】用模块例化方式设计的1位全加器顶层设计module full_add(ain,bin,cin,sum,cout); input ain,bin,cin;output sum,cout;wire d,e,f; //用于内部连接的节点信号half_add u1(ain,bin,e,d);//半加器模块调用,采用位置关联方式half_add u2(e,cin,sum,f);or u3(cout,d,f); //或门调用endmodule【例7.16】半加器定义module half_add(a,b,so,co); input a,b;output so,co;assign co=a&b; assign so=a^b; endmodule4位加法器设计结构描述的4位级连全加器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); full_add1 f3(a[3],b[3],cin3,sum[3],cout); endmodule【例7.18】数据流描述的4位加法器module add4_2(cout,sum,a,b,cin); input cin; input[3:0] a,b; output[3:0] sum;output cout;assign {cout,sum}=a+b+cin; endmodule7.6 多层次结构电路的设计1.图形与文本混合设计8位全加器module add8(sum,cout,b,a,cin); output[7:0] sum;output cout;input[7:0] a,b;input cin;assign {cout,sum}=a+b+cin; endmodule 8位寄存器module reg8(qout,in,clk,clear); output[7:0] qout;input[7:0] in;input clk,clear;reg[7:0] qout;always @(posedge clk or posedge clear)beginif(clear) qout<=0; //异步清0 else qout<=in;endendmodule2.文本设计module acc(accout,cout,accin,cin,clk,clear); output[7:0] accout;output cout;input[7:0] accin;input cin,clk,clear;wire[7:0] sum;add8 accadd8(sum,cout,accout,accin,cin);//调用add8子模块reg8 accreg8(accout,sum,clk,clear);//调用reg8子模块endmodule累加器顶层文本描述模块调用7.7 基本组合电路设计门级结构描述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);endmodule数据流描述module gate2(F,A,B,C,D);input A,B,C,D;output F;assign F=(A&B)|(B&C&D);endmodule【例7.24】 74138的Verilog描述module ttl74138(a,y,g1,g2a,g2b);input[2:0] a; input g1,g2a,g2b; output reg[7:0] y; always @(*)begin if(g1 & ~g2a & ~g2b)//只有当g1、g2a、g2b为100时,译码器使能begin case(a)3'b000:y=8'b11111110; //译码输出3'b001:y=8'b11111101;3'b010:y=8'b11111011;3'b011:y=8'b11110111;3'b100:y=8'b11101111;3'b101:y=8'b11011111;3'b110:y=8'b10111111;3'b111:y=8'b01111111;default:y=8'b11111111;endcase endelse y=8'b11111111;endendmodule【例7.25】 8线—3线优先编码器74148的Verilog描述module ttl74148(din,ei,gs,eo,dout);input[7:0] din; input ei; output reg gs,eo; output reg[2:0] dout;always @(ei,din)begin if(ei) begin dout<=3'b111;gs<=1'b1;eo<=1'b1; end else if(din==8'b111111111) begindout<=3'b111;gs<=1'b1;eo<=1'b0;endelse if(!din[7]) begin dout<=3'b000;gs<=1'b0;eo<=1'b1;end else if(!din[6]) begin dout<=3'b001;gs<=1'b0;eo<=1'b1;end else if(!din[5]) begin dout<=3'b010;gs<=1'b0;eo<=1'b1;end else if(!din[4]) begin dout<=3'b011;gs<=1'b0;eo<=1'b1;end else if(!din[3]) begin dout<=3'b100;gs<=1'b0;eo<=1'b1;end else if(!din[2]) begin dout<=3'b101;gs<=1'b0;eo<=1'b1;end else if(!din[1]) begin dout<=3'b110;gs<=1'b0;eo<=1'b1;end else begin dout<=3'b111;gs<=1'b0;eo<=1'b1;endendendmodule【例7.27】奇偶校验位产生器module parity(even_bit,odd_bit,a); input[7:0] a;output even_bit,odd_bit;assign even_bit=^a;//生成偶校验位assign odd_bit=~even_bit;//生成奇校验位endmodule7.8 基本时序电路设计【例7.29】带异步清0/异步置1的JK触发器module jkff_rs(clk,j,k,q,rs,set);input clk,j,k,set,rs; output reg q;always @(posedge clk, negedge rs, negedge set) begin if(!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【例7.30】电平敏感的1位数据锁存器module latch1(q,d,le);input d,le; output q;assign q=le?d:q;//le为高电平时,将输入端数据锁存endmodule【例7.31】带置位/复位端的1位数据锁存器module latch2(q,d,le,set,reset); input d,le,set,reset;output q;assign q=reset?0:(set? 1:(le?d:q)); endmodule【例7.32】 8位数据锁存器(74LS373)module ttl373(le,oe,q,d);input le,oe; input[7:0] d; output reg[7:0] q;a l w a y s@*//或写为always @(le,oe,d)begin if(~oe & le) q<=d;//或写为if((!oe) && (le))else q<=8'bz;endendmodule【例7.33】数据寄存器module reg_w(dout,din,clk,clr); parameter WIDTH=7;input clk,clr; input[WIDTH:0] din; output reg[WIDTH:0] dout; always @(posedge clk, posedge clr) beginif(clr) dout<=0;else dout<=din; endendmodule【例7.35】可变模加法/减法计数器module updown_count(d,clk,clear,load,up_down,qd); input clk,clear,load,up_down;input[7:0] d; output[7:0] qd; reg[7:0] cnt; assign qd=cnt;always @(posedge clk)begin if(!clear) cnt<=8'h00;//同步清0,低电平有效else if(load) cnt<=d;//同步预置else if(up_down) cnt<=cnt+1;//加法计数else cnt<=cnt-1;//减法计数endendmodule7.9 三态逻辑设计【例7.39】行为描述的三态门module tristate1(in,en,out);input in,en; output reg out;always @(in or en)begin if(en) out<=in;else out<=1'bz; endendmodule【例7.40】调用门元件bufif1描述的三态门module tristate2(in,en,out);input in,en; output out; tri out;bufif1 b1(out,in,en);//注意三态门端口的排列顺序endmodule【例7.41】数据流描述的三态门module tristate3(out,in,en);input in,en; output out;assign out=en?in:1‘bz; //若en=1,out=in;//若en=0,out为高阻态endmodule【例7.42】三态双向驱动器module bidir(y,a,en,b); input a,en; output b; inout y;assign y=en?a:'bz; assign b=y; endmodule【例7.44】三态双向总线缓冲器module ttl245(a,b,oe,dir);input oe,dir; //使能信号和方向控制inout[7:0] a,b; //双向数据线assign a=({oe,dir}==2'b00)?b:8'bz; assign b=({oe,dir}==2'b01)?a:8'bz; endmodule习题 7习题 7实验与设计module vote5(vote,pass);input [5:1] vote;output reg pass;always @(vote)begin case(vote)5'b00111: pass=1;5'b01011: pass=1;5'b01101: pass=1; 5'b01110: pass=1;5'b01111: pass=1;5'b10011: pass=1; 5'b10101: pass=1;5'b10110: pass=1;5'b10111: pass=1; 5'b11001: pass=1;5'b11010: pass=1;5'b11011: pass=1; 5'b11100: pass=1;5'b11101: pass=1;5'b11110: pass=1; 5'b11111: pass=1; default: pass=1'b0;endcase endendmodulemodule vote5f(pass,vote);input[5:1] vote;output pass; reg[2:0] sum; integer i; reg pass;always@(vote)begin sum=0;for(i=1;i<=5;i=i+1)if (vote[i]) sum=sum+1;if (sum>=3) pass=1; else pass=0; end endmodulemodule vote7(pass,vote);input[7:1] vote;output pass; reg[2:0] sum;integer i; reg pass;always@(vote)begin sum=0;for(i=1;i<=7;i=i+1)if(vote[i]) sum=sum+1;if(sum>=4) pass=1; else pass=0; end endmoduleSave IP Variation 对话框实验与设计定制FIFO模块的数据宽度和深度。
第10章 Verilog设计的优化10.1 设计的可综合性综合过程10.2 流水线设计技术流水线操作的概念流水线操作的示意图非流水线方式8位全加器module adder8(cout,sum,ina,inb,cin,clk); input[7:0] ina,inb; input cin,clk; output[7:0] sum; output cout;reg[7:0] tempa,tempb,sum; reg cout,tempc; always @(posedge clk)begin tempa=ina;tempb=inb;tempc=cin; end //输入数据锁存always @(posedge clk)begin {cout,sum}=tempa+tempb+tempc; end endmodule两级流水实现的8位加法器module adder_pipe2(cout,sum,ina,inb,cin,clk); input[7:0] ina,inb; input cin,clk;output reg[7:0] sum;output reg cout;reg[3:0] tempa,tempb,firsts;reg firstc;always @(posedge clk)begin {firstc,firsts}=ina[3:0]+inb[3:0]+cin; tempa=ina[7:4]; tempb=inb[7:4];endalways @(posedge clk)begin {cout,sum[7:4]}=tempa+tempb+firstc; sum[3:0]=firsts;endendmodule四级流水线实现的8位加法器module pipeline(cout,sum,ina,inb,cin,clk);output[7:0] sum;output cout;input[7:0] ina,inb;input cin,clk; reg[7:0] tempa,tempb,sum;reg tempci,firstco,secondco,thirdco, cout;reg[1:0] firsts, thirda,thirdb;reg[3:0] seconda, secondb, seconds; reg[5:0] firsta, firstb, thirds; always @(posedge clk)begin tempa=ina; tempb=inb; tempci=cin; end //输入数据缓存always @(posedge clk)begin {firstco,firsts}=tempa[1:0]+tempb[1:0]+tempci; //第一级加(低2位)firsta=tempa[7:2]; firstb=tempb[7:2]; //未参加计算的数据缓存endalways @(posedge clk)begin {secondco,seconds}={firsta[1:0]+firstb[1:0]+firstco,firsts}; seconda=firsta[5:2]; secondb=firstb[5:2]; //数据缓存endalways @(posedge clk)begin {thirdco,thirds}={seconda[1:0]+secondb[1:0]+secondco,seconds}; thirda=seconda[3:2];thirdb=secondb[3:2];//数据缓存endalways @(posedge clk)begin{cout,sum}={thirda[1:0]+thirdb[1:0]+thirdco,thirds}; //第四级加end endmodule设计综合到不同器件的最高工作频率器件非流水线设计/MHz 2级流水线设计/MHz4级流水线设计/MHzEP1K10TC100-3(FPGA)138.89158.73166.67 EPM3064ALC44-4(CPLD)105.26149.25158.732个加法器和1个选择器的实现方式module resource1(sum,a,b,c,d,sel);parameter SIZE=4; input sel; input[SIZE-1:0] a,b,c,d;output reg[SIZE:0] sum;always @(*) //使用通配符begin if(sel) sum=a+b;else sum=c+d;end endmodule 10.3 资源共享(Resource Sharing )资源共享可用来减少系统所耗用的器件资源,尤其是将一些耗用资源较多的模块进行共享,能有效降低整个系统耗用的资源。
第8章 Verilog有限状态机设计8.1 有限状态机摩尔型(Moore)状态机米里型(Mealy)状态机用状态机设计模5计数器module fsm(clk,clr,z,qout);input clk,clr; output reg z; output reg[2:0] qout; always @(posedge clk or posedge clr) //此过程定义状态转换begin if(clr) qout<=0; //异步复位else case(qout)3'b000: qout<=3'b001;3'b001: qout<=3'b010;3'b010: qout<=3'b011;3'b011: qout<=3'b100;3'b100: qout<=3'b000;default: qout<=3'b000;/*default语句*/endcaseendalways @(qout) /*此过程产生输出逻辑*/ begin case(qout)3'b100: z=1'b1;default:z=1'b0;endcaseendendmodule8.2 有限状态机的几种描述方式“101”序列检测器的Verilog 描述(三个过程)module fsm1_seq101(clk,clr,x,z);input clk,clr,x; output reg z; reg[1:0] state,next_state;parameter S0=2'b00,S1=2'b01,S2=2'b11,S3=2'b10; /*状态编码,采用格雷(Gray )编码方式*/always @(posedge clk or posedge clr) /*该过程定义当前状态*/begin if(clr) state<=S0; //异步复位,s0为起始状态else state<=next_state;end always @(state or x) /*该过程定义次态*/begin case (state)S0:begin if(x) next_state<=S1;else next_state<=S0; end S1:begin if(x) next_state<=S1;else next_state<=S2; endS2:beginif(x) next_state<=S3; else next_state<=S0; end S3:b e g i ni f(x)next_state<=S1;else next_state<=S2; enddefault:next_state<=S0;/*default语句*/ endcaseend always @(state)/*该过程产生输出逻辑*/ begin case(state)S3: z=1'b1;default:z=1'b0; endcaseendendmodule“101”序列检测器的Verilog描述(三个过程)“101”序列检测器(单过程描述)module fsm4_seq101(clk,clr,x,z);input clk,clr,x; output reg z; reg[1:0] state; parameter S0=2'b00,S1=2'b01,S2=2'b11,S3=2'b10;/*状态编码,采用格雷(Gray)编码方式*/always @(posedge clk or posedge clr)Begin if(clr) state<=S0; //异步复位,s0为起始状态else case(state)S0:begin if(x) begin state<=S1; z=1'b0;endelse begin state<=S0; z=1'b0;endendS1:begin if(x) begin state<=S1; z=1'b0;endelse begin state<=S2; z=1'b0;endendS2:begin if(x) begin state<=S3; z=1'b0;endelse begin state<=S0; z=1'b0;endendS3:begin if(x) begin state<=S1; z=1'b1;endelse begin state<=S2; z=1'b1;endenddefault:begin state<=S0; z=1'b0;end /*default语句*/ endcase endendmodule8.3 状态编码常用的编码方式一位热码编码选择对话框(Quartus Ⅱ)在Verilog语言中,有两种方式可用于定义状态编码,分别用parameter和'define语句实现,比如要为state0、state1、state2、state3四个状态定义码字为:00、01、11、10,可采用下面两种方式。
数字系统设计与verilog_HDL_王金明_第四版__EDA期末知识点复习(宁波工程学院电科版)1、采用硬件描述语言(HDL)进行电路设计的优势。
1)更适合用于描述规模大、功能复杂的数字系统2)语言标准化、便于设计的复用、交流、保存和修改3)设计与工艺的无关性,宽范围的描述能力,便于组织大规模、模块化的设计2、Verilog模块的结构模块声明:包括模块名字、模块输入、输出端口列表,结束关键字为endmodule端口定义:格式为:input: 端口名1,端口名2…端口名n;output: 端口名1,端口名2…端口名n;inout: 端口名1,端口名2…端口名n;3、标识符是用户在编程时给verilog对象起的名字,模块、端口和实例的名字都是标识符。
标识符可以是任意一组字母、数字以及符号“$”和“_”的组合,但标识符的第一个字符必须是字母(a-z,A-Z)或者是下划线“_”,标识符最长可包含1023个字符,此外,标识符区分大小写。
4、整数写法:+/-’1、在较长的数之间可用下划线分开2、当数字不说明位宽时,默认值为32位3、 X或(z)在二进制中代表1位x(或z),在八进制中代表3位,在16进制中代表4位4、如果没有定义一个整数的位宽,其宽度为相应值中定义的位数。
5、如果定义的位宽比实际的位数长,通常在左边填0补位,但如果最左边一位为x或z,就相应的用x或z左边补位。
6、“?”是高阻态z的另一种表示符号,在数字的表示中,字符“?”和z 是完全等价的,可相互代替。
7、整数可以带符号,并且正负号应写在最左边,负数通常表示为二进制补码的形式。
8、当位宽与进制缺省时表示的是10进制数9、在位宽和‘之间,以及进制和数值之间允许出现空格,但’和进制之间以及数值之间是不能出现空格的。
要求掌握整数正确的书写方式。
5、向量:宽度大于1位的变量;标量:宽度为1位的变量。
定义2个8位reg型矢量:reg [7:0] ra, rb;6、运算符(1)注意:逻辑运算符,例如逻辑与&&、逻辑或||、逻辑非!,运算结果是1位的。
《数字系统设计与Verilog HDL》教学大纲课程中文名称: 数字系统设计与Verilog HDL 课程英文名称: Digital system design with Verilog HDL课程代码: 学时/实践或实验/学分:40/8/2.5课程类别: 课程性质: 选修课适用专业:执笔人: 审定人:审批人:一、教学目标教学目标是使学生了解掌握EDA技术的基础知识、可编程逻辑器件的基本结构、硬件描述语言的语法、编程方法以及相关开发软件的使用方法。
重点掌握:PLD器件的结构和开发流程、开发软件的使用方法、Verilog HDL语言的基本语法和利用Verilog HDL语言建模、仿真和综合的设计复杂数字逻辑电路与系统设计的方法和技术。
目标1:了解EDA技术的发展概况,掌握EDA技术的基本概念及相关的基础知识,掌握数字系统设计的设计方法和流程。
了解可编程逻辑器件的分类,掌握可编程逻辑器件的基本结构掌握,掌握CPLD及FPGA器件的基本结构掌握。
目标2:掌握Verilog HDL的语言要素、各种语句以及设计方法等基础知识;掌握Verilog HDL 模块和测试模块的基本结构,能够利用Verilog HDL语言对数字电路进行建模。
目标3:掌握Verilog HDL的三种描述方式;掌握层次设计的方法以及一些设计技巧;并掌握利用有限状态机对数字电路进行建模的方式。
目标4:掌握开发软件及仿真软件的使用流程及方法,能够对设计文件进行仿真验证。
二、课程教学目标与毕业要求关系矩阵注:用☆☆☆、☆☆、☆分别表示教学目标对毕业要求的贡献度为强、中、弱。
三、教学内容和学时分配(32学时)《数字系统设计与Verilog HDL》在理论教学方面侧重于PLD基本原理、Verilog HDL语法要素和行为语句、Verilog HDL阻塞与非阻塞赋值、Verilog HDL有限状态机设计和数字电路设计。
实验教学方面侧重于利用现代 EDA设计流程、软件仿真应用、仿真测试程序设计、层次设计。
EDA课程设计多功能数字钟设计程序清单数字系统设计与verilog HDL(第四版)王金明/*引脚锁定基于DE2一70,芯片为EP2C70F896,信号定义如下: Clk50m: 50MHz 时钟输,mode:模式选择0:计时模式1:设置闹钟模式mcheck:手动调整时间turn:手动调整时间,在时、分之间选择change:对选中的数据调整led hourl,led_hour0,led_minul,led_minu0,led_secl,led sec0;alert: 闹钟输出ld_alert: 是否设置了闹钟ld_hour,id_min,ld_sec:在调整时,指示选中了时,分还是秒*/moduleclock(clk50m,mode,turn,change,mreset,led_hour1,led_hour0,led_minu1,led_minu0, led_sec1,led_sec0, alert,ld_alert,ld_check,ld_hour,ld_min,ld_sec);input clk50m;input mode; // key0键input turn; //keyl键input change; // key2 键input mreset; //switch0复位,低电平有效output alert; //gpioO->IOAOoutput ld_alert; //ledgO-led19output ld_check; //ledgl-led22output ld_hour; //ledr3-led13output ld_min; //ledr9-led9output ld_sec; //ledr7-led7output[6:0] led_hour1;output[6:0] led_hour0;output[6:0] led_minu1;output[6:0] led_minu0;output[6:0]led_sec1;output[6:0]led_sec0;reg [1:0] modestate;//00: 计时模式10:闹钟模式; 01:手动调整模式;11:非法模式wire nowmode;//记录当前模式,0:计时模式;1: 设置闹钟模式wire ischecking; //是否在手动调整时间assign {nowmode, ischecking}=modestate;always@(negedge mode)//两个按钮都是低电平有效begincase (modestate)2'b00 : modestate<=2'b10; //设置闹钟模式优先2'b10: modestate<=2'b01; //手动调整模式2'b01: modestate<=2'b00;default :modestate<=2'b00;endcaseendwire reset, clk_1hz;switch #(8) rmjitter(clk50m,mresetr,reset);clk50mtol genlhz (clk50m, clk_1hz) ; //生成1Hz的时钟wire [2 : 0] selcode; //对turn信号在不同模式bitsel seldecoder (nowmode, ischecking, turn, selcode, reset);wire [3:0] clocktime0,clocktimel,clocktime2,clocktime3,clocktime4,clockthre5;//计时输出的时钟数值wire clockalarmon; //整点报时的闹钟输出wire [2 : 0] counterselcode;assign counterselcode=(modestate==2'b01)?selcode:3'b000;counter_time clock_time (clk_1hz,counterselcode,~change,clocktime5,clocktime4,clocktime3,clocktime2,clock time1,clocktime0,clockalarmon,reset);wire[3:0] alarmtime0,alarmtime1,alarmtime2,alarmtime3;wire alarmon;alarm_time alarm_time ( clk_1hz , nowmode , selcode [ 2 : 1] , change ,{clocktime5, clocktime4, clocktime3, clocktime2, clocktime1},{alarmtime3, alarmtime2, alarmtime1, alarmtime0} , alarmon, reset) ;wire voiceout ;alarm alarmvoice (clk50m,{clockalarmon, alarmon} ,voiceout, raset) ;//显示输出部分assign {ld_hour,ld_min,ld_sec}=(ischecking||nowmode)?selcode:3'b000; assign alert=voiceout;reg[3:0] showout2,showout3,showout4,showout5;led led5 (showout5,led_hour1) ; //led译码显示led led4 (showout4,led_hour0) ;led led3 (showout3,led_minu1) ;led led2 (showout2,led_minu0) ;led led1 (clocktime1,led_sec1) ;led led0 (clocktime0,led_sec0) ;alwaysbegin if ( nowmode)begin showout5=alarmtime3 ; showout4=alarmtime2 ;showout3=alarmtime1; showout2=alarmtime0 ; end else beginshowout5=clocktime5; showout4=clocktime4 ;showout3=clocktime3 ; showout2=clocktime2 ; end endassign ld_alert=nowmode; assign ld_check=ischecking;endmodule/*alarm.V:闹铃模块Clk50m: 50MHz输入时钟alarmon:闹铃是否打开,2'b00:不打开:2'b01:闹钟;2'b10:整点报时ala rmoUt:闹铃声音输出*/module alarm(clk50m,alarmon,alarmout,reset);input[1:0] alarmon;input clk50m,reset;output reg alarmout;reg[15:0] counter_1k;wire clk_1k;assign clk_1k=counter_1k[4];always@(posedge clk50m)begin if (counter_1k==20) counter_1k<=0;else counter_1k<=counter_1k+1'b1; endwire ddd_du_out,ddd_out;sound_ddd_du ddd_du (clk_1k,alarmon[1] ,ddd_du_out) ;sound_ddd ddd(clk_1k,alarmon[0],ddd_out);alwaysbegin if (!reset)begin if (alarmon [0]==1'b1) //ddd,闹钟的响铃优先级更高alarmout=ddd_out ;else if (alarmon==2'b10) alarmout=ddd_du_out;else alarmout=0 ;end else alarmout=0 ;endendmodule/*alarm_time.V:闹钟时间设定模块enable:使能信号Sel:在时、分之间切换选择10:时;01:分inc:对选中的信号自增basetime:基准时钟*/module alarm_time (clk_1hz , enable, sel, inc, basetime, alarmouttime, alarm_on, reset) ;input clk_1hz,enable, inc,reset;input[1:0] sel;input[4*5-1:0] basetime;output reg alarm_on;output [4*4-1: 0] alarmouttime;reg [ 3 : 0] hour1, hour0 , minu1, minu0 ; //存储的设定时间always@ (posedge inc or posedge reset)begin if (reset) //reset=1时复位begin { hour1, hour0,minu1, minu0 } <=16'h0 ; endelse beginif (enable) beginif (sel==2'b10) //设置时begin if({hour1,hour0}==8'h23) {hour1,hour0}<=8'h00;else if (hour0==9)begin hour0<=0;hour1<=hour1+1'b1; endelse hour0<=hour0+1'b1;endelse if(sel===2'b01)//设置分begin if({minu1,minu0}==8'h59) {minu1,minu0}<=8'h00;else if (minu0==4'h9)begin minu0<=4'h0;minu1<=minu1+4'h1;endelse minu0<=minu0+4'h1; endelse {hour1,hour0,minu1,minu0}<=16'h0;end endendalways //闹钟开始条件beginif(({hour1,hour0,minu1,minu0}==basetime[ (4*5-1) :4]) && (basetime[3:0]<2)) alarm_on=1'b1;else alarm_on=1'b0; endassign alarmouttime={ hour1,hour0,minu1,minu0};endmodule/*counter time,v:计时模块,并留有调整接;check:调整信号,3位,分别调整时、分、秒,调整方法:将计数输出给加法器,把调整信息转换成异步置数信息,将加法器的输出作为置数值;hour1,hour0,minul, minu0, sec1,sec0:输出的计时时钟;alarmout:整点报时输出*/modulecounter_time(clk_1hz,check,inc,hour1,hour0,minu1,minu0,sec1,sec0,alarmout,reset); input clk_1hz,inc,reset;input[2:0] check;output[3:0] hour1,hour0,minu1,minu0,sec1,sec0;output reg alarmout;reg clk_1hz_md;wire [6: 0] carryclk;reg[5:0] incplus;//自增脉冲wire [5 : 0] carry; //进位时钟wire [3 : 0] adderout0,adderout1,adderout2,adderout3,adderout4,adderout5;wire [3 : 0] timerout0,timerout1,timerout2,timerout3,timerout4,timerout5; hexcounter counter_sec0(carryclk[0],reset,4'd9,4'b0,timerout0,carry[0]); hexcounter counter_sec1(carryclk[1],reset,4'd5,4'b0,timerout1,carry[1]); hexcounter counter_minu0(carryclk[2],reset,4'd9,4'b0,timerout2,carry[2]); hexcounter counter_minu1(carryclk[3],reset,4'd5,4'b0,timerout3,carry[3]);wire [3:0] hour0max;assign hour0max=(timerout5==4'h2)?(4'h3) : (4'h9);hexcounter counter_hour0(carryclk[4],reset,hour0max,4'b0,timerout4,carry[4]); hexcounter counter_hour1(carryclk[5],reset,4'd2,4'b0,timerout5,carry[5]);//每个计时器的时钟,由前级进位和自堦脉冲相加得到assign carryclk[0]=(check==4'h0) ? clk_1hz_md:incplus[0];assign carryclk[1]=carry[0]|incplus[1];assign carryclk[2]=(check==4'h0) ? carry[1]:incplus[2];assign carryclk[3]=carry[2]|incplus[3];assign carryclk[4]=(check==4'h0) ? carry[3]:incplus[4];assign carryclk[5]=carry[4]|incplus[5];always //对异步置位信号进行解码begin case (check)3 'b001: begin clk_1hz_md=0;incplus={5 'b00000, inc} ;end3 'b010 : begin clk_1hz_md=0;incplus={3'b000,inc,2'b00};end3 'b100 : begin //在正常的调节状态中clk_1hz_md=0;incplus={1'b0, inc, 4'b000};enddefault:begin incplus=6'b000000;clk_1hz_md=clk_1hz ;endendcaseendalways begin if (((reset|check)==0)&&(timerout3==0) && (timerout2==0) && (timerout1<2)) alarmout=1;//时间小于20秒的时间内else alarmout=0;endassign hour1=timerout5;assign hour0=timerout4;assign minu1=timerout3;assign minu0=timerout2;assign sec1=timerout1;assign sec0=timerout0;endmodule/*Clk50mtol.v: 50mhz 时钟分频到lhz */module clk50mtol(clk50m,clk1hz);input clk50m;output clk1hz;reg [25:0]counter_1hz;//从50mhz 分频到lhz 的计数器assign clk1hz=counter_1hz[14];//assign clk1hz=counter_1hz[25];always@ (posedge clk50m)beginif(counter_1hz==20000) counter_1hz<=0;else counter_1hz<=counter_1hz+1'b1;endendmodule/*led.v:7段数码管(led)译码显示模块datain:4位,10进制数输入ledout:7位,数码管的7段*/module led(datain,ledout);parameter INWIDTH=4;parameter OUTWIDTH=7;input[INWIDTH-1: 0] datain;output [OUTWIDTH-1:0] ledout;reg[OUTWIDTH-1:0] dataout;assign ledout=dataout;always begincase (datain)0 : dataout<=7'b1000000;1 : dataout<=7'b1111001;2 : dataout<=7'b0100100;3 : dataout<=7'b0110000;4 : dataout<=7'b0011001;5 : dataout<=7'b0010010;6 : dataout<=7'b0000010;7 : dataout<=7'b1111000;8 : dataout<=7'b0000000;9 : dataout<=7'b0010000;default : dataout<=7'b1000000;endcaseendendmodule/*switch-v:对按键开关的消抖电路,采用一个频率较低的时钟,对输入进行采样,消除抖动*/module switch(clk,keyin,keyout);parameter COUNTWIDTH=8;input clk, keyin;output reg keyout;reg [COUNTWIDTH-1: 0] counter;wire clk_use; //频率较低的时钟assign clk_use=counter [COUNTWIDTH-1];always@ (posedge clk)counter<=counter+1'b1;always@ (posedge clk_use)keyout<=keyin;endmodule/*bitsel-v:将输出解码成对时、分、秒的选择(并且分闹钟设置模式还是计时模式)Alarmmode:是否是在设置闹钟模式checkmode:是否是在调整时间模式*/module bitsel(alarmmode, checkmode, sel, selcode, reset) ;input alarmmode, checkmode, sel, reset;output reg [2:0] selcode;reg [2:0] check_code ;reg [1:0] alarm_code ;always@ (negedge sel or posedge reset)begin if (reset) check_code<=3'b000; //reset=1 复位else begincase (check_code)3 'b000: check_code<=3 'b001;3 'b001: check_code<=3 'b010;3 'b010: check_code<=3 'b100;3 'b100: check_code<=3 'b001;default: check_code<=3 'b000;endcaseendendalways@ (negedge sel or posedge reset)begin if (reset) alarm_code<=2 'b00; //低电平复位else begincase (alarm_code)2'b00 : alarm_code<=2'b01;2 'b01 : alarm_code<=2 'b10 ;2 'b10 : alarm_code<=2 'b01;default : alarm_code<=2 'b00;endcaseendendalwaysbegin if (alarmmode^checkmode) //两个当中只有1个为1 begin if (checkmode) selcode=check_code;else selcode={alarm_code,1'b0}; endelse selcode=3 'b000 ;endendmodule/*adder.v:加法器*/module adder(in1, in2, out);parameter in1width=8;parameter in2width=8;parameter outwidth=8;input [in1width-1: 0] in1;input [in2width-1: 0] in2;output[outwidth-1: 0] out;assign out=in1+in2;endmodule/*excounter-v:16进制计数的一个计数器*/module hexcounter (clk, set, max, setdata, dataout, carryout) ; input clk,set;input[3:0] max,setdata;output carryout;output[3:0] dataout;reg[3:0] counter;reg carrybit;assign carryout=carrybit;assign dataout=counter;always@ (posedge clk or posedge set)begin if (set) //set是高电平有效begin counter<=setdata;carrybit<=0 ;endelse begin if( (counter==max)||(counter>max) )begin counter<=0 ;carrybit<=1;endelse begin counter<=counter+1'b1;carrybit<=0 ;endendendendmodule/*sound_ddd.V:发出嘀嘀嘀闹铃声模块*/module sound_ddd(clk_1k, on, out);parameter soundspace=30;parameter shotstopspace=20; //20ms,两个嘀声的时间距离parameter longstopspace=50;//50ms,连续三个嘀后的时间距离input clk_1k,on;output reg out;reg sound;always@ (posedge clk_1k)begin sound<=~sound; endreg[10:0] mscount;always@ (posedge clk_1k)begin if (mscount== (soundspace*3+shotstopspace*2+longstopspace-1) )mscount<=0;else mscount<=mscount+1'b1;endalways@ (negedge clk_1k)begin if (on)begin if ( (mscount>=0) && (mscount<soundspace) ) out<=sound;else if ( (mscount>=soundspace) && (mscount< (soundspace+shotstopspace) ) )out<=0;else if ( (mscount>= (soundspace+shotstopspace) ) && (mscount< (soundspace+shotstopspace) +soundspace) )out<=sound;else if ( (mscount>= (soundspace+shotstopspace) +soundspace) && (mscount< (soundspace+shotstopspace) *2) )out<=0;else if ( (mscount>= (soundspace+shotstopspace) *2)&&(mscount< ((soundspace+shotstopspace) *2+soundspace) ) )out<=sound;else out<=0;endelse out<=0 ;endendmodule/* sound ddd du,v:发出声音嘀嘀嘀一嘟声音模块*/module sound_ddd_du (clk_1k, on, out) ;parameter SOUNDSPACE=30;parameter shotstopspace=20;//20ms,两个嘀声的时间距离parameter longsoundspace=60; //嘟的长度input clk_1k, on;output reg out;reg sound_di, sound_du;always@ (posedge clk_1k) sound_di<=~sound_di;always@ (posedge sound_di) sound_du<=~sound_du;reg [ 11 : 0 ] mscount ;always@ (posedge clk_1k)begin if (on)begin if (mscount< (SOUNDSPACE+shotstopspace) *3+longsoundspace+10)mscount<=mscount+1'b1;endelse mscount<=0 ;endalways@ (negedge clk_1k)begin if (on)begin if ( (mscount>=0) && (mscount<SOUNDSPACE) ) out<=sound_di;else if ( (mscount>=SOUNDSPACE) && (mscount< (SOUNDSPACE+shotstopspace) ) )out<=0 ;else if ( (mscount>= (SOUNDSPACE+shotstopspace) ) && (mscount< (SOUNDSPACE+shotstopspace) +SOUNDSPACE) )out<=sound_di ;else if ( (mscount>= (SOUNDSPACE+shotstopspace) +SOUNDSPACE) && (mscount< (SOUNDSPACE+shotstopspace) *2) )out<=0;else if ( (mscount>= (SOUNDSPACE+shotstopspace) *2) && (mscount< ( (SOUNDSPACE+shotstopspace) *2+SOUNDSPACE) ) )out<=sound_di;else if ( (mscount>= (SOUNDSPACE+shotstopspace) *2+SOUNDSPACE) && (mscount< (SOUNDSPACE+shotstopspace) *3) )out<=0;else if ( (mscount>= (SOUNDSPACE+shotstopspace) *3) && (mscount< ( (SOUNDSPACE+shotstopspace) *3+longsoundspace) ) )out<=sound_du;else out<=0;endendendmodule。
第3章 Quartus Prime使用指南
3.1 Quartus Prime原理图设计n3.1.1 半加器原理图设计输入
Quartus Prime的主界面
Quartus Prime的主界面
3.1.1 半加器原理图设计输入
输入元件
Quartus Prime的主界面
3.1.1 半加器原理图设计输入
半加器电路图
Quartus Prime的主界面
3.1.1 半加器原理图设计输入
使用New Project Wizard创建工程
Quartus Prime的主界面
3.1.1 半加器原理图设计输入
设置Directory,Name,Top-Level Entity对话框
Quartus Prime的主界面
3.1.1 半加器原理图设计输入
将设计文件加入当前工程中
Quartus Prime的主界面
3.1.1 半加器原理图设计输入
选择目标器件
Quartus Prime的主界面
3.1.1 半加器原理图设计输入
选择综合器、仿真器
Quartus Prime的主界面
3.1.1 半加器原理图设计输入
工程信息汇总显示
Quartus Prime的主界面
3.1.2 1位全加器设计输入
Quartus Prime的主界面创建元件符号对话框
3.1.2 1位全加器设计输入
Quartus Prime的主界面1位全加器原理图
3.1.3 1位全加器的编译
n选择菜单Processing→Start Compilation,或者单击按钮,即启动了完全编译,完全编译包括如下5个过程:
n分析与综合(Analysis & Synthesis);
n适配(Fitter);
n装配(Assembler);
n定时分析(TimeQuest Timing Analysis);
n网表文件提取(EDA Netlist Writer)。
Quartus Prime的主界面
3.1.3 1位全加器的编译
Quartus Prime的主界面
编译信息汇总
3.1.4 1位全加器的仿真
Quartus Prime的主界面
建立Quartus Prime和Modelsim的链接
3.1.4 1位全加器的仿真
Quartus Prime的主界面设置仿真文件的格式和目录
3.1.4 1位全加器的仿真
Quartus Prime的主界面
自动生成的Test Bench模板文件
3.1.4 1位全加器的仿真
Quartus Prime的主界面对Test Bench进一步设置
3.1.4 1位全加器的仿真
1位全加器时序仿真波形图
Quartus Prime的主界面
3.1.5 1位全加器的下载
n本例针对的下载板为DE2-115,故目标器件应为:EP4CE115F29C7。
n选择菜单Assignments→Pin Planner,在Pin Planner对话框中,进行引脚的锁定。
n A →PIN_AB28 SW0(拨动开关)
n B →PIN_AC28 SW1(拨动开关)
n CIN →PIN_AC27 SW2(拨动开关)
n SUM →PIN_E21 LEDG0(LED灯)
n COUT→PIN_AB28 LEDG1(LED灯)
3.1.5 1位全加器的下载
编程下载窗口
Quartus Prime的主界面
第3章 Quartus Prime使用指南
3.2 基于IP 核的设计
Quartus Prime 的主界面LPM_COUNTER 模块命名
n 3.2.1 用LPM_COUNTER 设计模24
方向可控计数器
3.2.1 用LPM_COUNTER设计模24方向可控计数器
Quartus Prime的主界面
启动MegaWizard Plug-In Manager,对LPM_COUNTER模块进行参数设置
3.2.1 用LPM_COUNTER 设计模24方向可控计数器
Quartus Prime 的主界面
模24
方向可控计数器原理图
3.2.1 用LPM_COUNTER 设计模24方向可控计数器
Quartus Prime 的主界面
模24
方向可控计数器门级仿真波形图
3.2.2 用LPM_ROM模块实现4×4无符号数乘法器
Save IP Variation对话框
Quartus Prime的主界面
3.2.2 用LPM_ROM模块实现4×4无符号数乘法器
基于lpm_rom实现的4×4无符号数乘法器原理图
Quartus Prime的主界面
3.2.2 用LPM_ROM模块实现4×4无符号数乘法器
ROM存储器的内容存储在*.mif文件中
Quartus Prime的主界面
3.2.2 用LPM_ROM 模块实现4×4无符号数乘法器
Quartus Prime 的主界面
4×4
无符号数乘法器波形仿真结果
第3章 Quartus Prime使用指南
3.3 SignalTap II的使用方法
n Quartus Prime的嵌入式逻辑分析仪SignalTap II为设计者提供了一种方便高效的硬件测试手段,它可以随设计文件一起下载到目标芯片中,捕捉目标芯片内信号节点或总线上的数据,将这些数据暂存于目标芯片的嵌入式RAM中,然后通过器件的JTAG 端口将采到的信息和数据送到计算机进行显示,供用户分析。
Quartus Prime 的主界面
调入待测信号3.3 SignalTap II 的使用方法
Quartus Prime 的主界面 SignalTap II 参数设置窗口
3.3 SignalTap II
的使用方法
Quartus Prime 的主界面
SignalTap II 数据窗口显示的实时采样的信号波形3.3 SignalTap II
的使用方法
第3章 Quartus Prime使用指南
Quartus Prime 的主界面
编译器设置3.4 Quartus Prime
的优化设置与时序分析
Quartus Prime 的主界面
查看Design Assistant
报告3.4 Quartus Prime 的优化设置与时序分析
Quartus Prime 的主界面资源优化指导(Resource Optimization Advisor )3.4 Quartus Prime
的优化设置与时序分析
3.1 基于Quartus Prime软件,用D触发器设计一个2分频电路,并做波形仿真,在此基础上,设计一个4分频和8分频电路,做波形仿真。
1.4 数字系统的实现方式有哪些?各有什么优缺点?
3.2 基于Quartus Prime软件,用74161设计一个模10计数器,并进行编译和仿真。
3.3 基于Quartus Prime软件,用74161设计一个模99的计数器,个位和十位都采用8421BCD码的编码方式设计,分别用置0和置1两种方法实现,完成原理图设计输入、编译、仿真和下载整个过程。
3.5 基于Quartus Prime软件,用74283(4位二进制全加器)设计实现一个8位全加器,并进行综合和仿真,查看综合结果和仿真结果。