数字系统设计verilog HDL 第 版 王金明

合集下载

数字系统设计与veriloghdl课后答案

数字系统设计与veriloghdl课后答案

数字系统设计与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。

EDA技术与Verilog设计王金明版第6章

EDA技术与Verilog设计王金明版第6章

6.2 块语句
并行块fork-join fork-join块中的所有语句是并发执行的。
ቤተ መጻሕፍቲ ባይዱ
比如: fork regb=rega; regc=regb; join 由于fork-join块内的语句同时执行,在上面的块语句执行完 后,regb更新为rega的值,而regc的值更新为没有改变前 regb的值,故执行完成后,regb与regc的值是不同的。
如果加上时序控制,则这个always语句将变为一条 非常有用的描述语句。见下例:
[例]:always #half_period areg = ~areg; 这 个 例 子 生 成 了 一 个 周 期 为 :period(=2*half_period) 的无限延续的信号波形, 常用这种方法来描述时钟信号,作为激励信号来测 试所设计的电路。 Verilog提供三种时序控制方法:基于延迟的时 序控制、基于事件的时序控制和电平敏感的时序控 制。
������ initial 过程块的使用主要是面向功能模拟的,通常用 来描述测试模块的初始化、监视、波形生成等功能; ������ always过程块的使用主要是对硬件功能模拟的行为进 行描述,也可以在测试模块用来对时钟进行描述。利用 always过程块可以实现触发器、锁存器和组合电路。 一个模块中可有多个initial和always语句,代表多个过程 块的存在,它们之间相互独立,并行运行
Verilog HDL行为语句
类别 initial 过程语句 块语句 always 串行块begin-end 并行块fork-join √ √ 语句 可综合性
赋值语句
持续赋值assign
过程赋值=、<= if-else

√ √ √ √

第7章王金明verilog HDL 程序设计教程

第7章王金明verilog HDL 程序设计教程

语句描述的4选 【例7.2】 用case语句描述的 选1 MUX 】 语句描述的 module 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=i9;b11:out=in4; default:out=2'bx; endcase endmodule
【例7.4】 数据流描述的 选1 MUX 】 数据流描述的4选 module 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
门元件的调用 对于buf和not两种元件的调用,需注意 和 两种元件的调用, 对于 两种元件的调用 的是:它们允许有多个输出, 的是:它们允许有多个输出,但只能 有一个输入。比如: 有一个输入。比如:
not N1(out1,out2,in); //1个输入 ,2个输出 个输入in, 个输出 个输出out1,out2 个输入 buf B1(out1,out2,out3,in); //1个输入 ,3个输出 个输入in, 个输出 个输入 out1,out2,out3
用基本门实现的4选 用基本门实现的 选1 MUX原理图 原理图
7.3 行为描述

第9章数字系统设计verilog HDL(第6版)王金明

第9章数字系统设计verilog HDL(第6版)王金明

第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实验与设计。

verilogHDL(王金明版源码)

verilogHDL(王金明版源码)

王金明:《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 HDL(第6版)王金明

第5章数字系统设计verilog HDL(第6版)王金明

第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设计王金明版第12章Verilog语言的发展

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 HDL(第6版)王金明

第7章数字系统设计verilog HDL(第6版)王金明

第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模块的数据宽度和深度。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

第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位全加器,并进行综合和仿真,查看综合结果和仿真结果。

相关文档
最新文档