北航verilog实验报告全.docx
《北航verilog实验报告全.docx》由会员分享,可在线阅读,更多相关《北航verilog实验报告全.docx(65页珍藏版)》请在冰豆网上搜索。
![北航verilog实验报告全.docx](https://file1.bdocx.com/fileroot1/2023-2/2/6360e010-688e-4ae1-bd16-473e582dccba/6360e010-688e-4ae1-bd16-473e582dccba1.gif)
北航verilog实验报告全
实验一
实验目的:
熟悉硬件开发流程,掌握Modelsim设计与仿真环境,学会简单组合逻辑电路、简单时序逻辑电路设计,不要求掌握综合和综合后仿真。
实验内容:
必做实验:
练习一、简单的组合逻辑设计
练习二、简单分频时序逻辑电路的设计
选做实验:
选做一、练习一的练习题
选做二、7段数码管译码电路
练习一、简单的组合逻辑设计
描述一个可综合的数据比较器,比较数据a、b的大小,若相同,则给出结果1,否则给出结果0。
实验代码:
模块源代码:
modulecompare(equal,a,b);
inputa,b;
outputequal;
assignequal=(a==b)?
1:
0;
endmodule
测试模块源代码:
`timescale1ns/1ns
`include"./compare.v"
modulet;
rega,b;
wireequal;
initial
begin
a=0;
b=0;
#100a=0;b=1;
#100a=1;b=1;
#100a=1;b=0;
#100a=0;b=0;
#100$stop;
end
comparem(.equal(equal),.a(a),.b(b));
endmodule
实验波形
练习二、简单分频时序逻辑电路的设计
用always块和@(posedgeclk)或@(negedgeclk)的结构表述一个1/2分频器的可综合模型,观察时序仿真结果。
实验代码:
模块源代码:
modulehalfclk(reset,clkin,clkout);
inputclkin,reset;
outputclkout;
regclkout;
always@(posedgeclkin)
begin
if(!
reset)clkout=0;
elseclkout=~clkout;
end
endmodule
测试模块源代码:
`timescale1ns/100ps
`defineclkcycle50
modulett;
regclkin,reset;
wireclkout;
always#`clkcycleclkin=~clkin;
initial
begin
clkin=0;
reset=1;
#10reset=0;
#110reset=1;
#100000$stop;
end
halfclkm0(.reset(reset),.clkin(clkin),.clkout(clkout));
endmodule
实验波形:
练习题1:
设计一个字节(8位)的比较器。
要求:
比较两个字节的大小,并改写测试模型,使其能进行比较全面的测试。
观察RTL级仿真、综合后门级仿真和布线后仿真有什么不同,并说明不同的原因。
从文件系统中查阅自动生成的compare.vm,compare.vo文件和compare.v文件作比较,说出不同点和相同点。
实验代码:
模块源代码:
modulecompare1(equal,a,b);
input[7:
0]a,b;
outputequal;
assignequal=(a>b)?
1:
0;
endmodule
测试模块源代码:
`timescale1ns/1ns
`include"./compare1.v"
modulettt;
reg[7:
0]a,b;
wireequal;
initial
begin
a=8'b00000000;
b=8'b00000000;
#100a=8'b00001001;b=8'b00100010;
#100a=8'b00110001;b=8'b00100100;
#100a=8'b00010001;b=8'b00101000;
#100a=8'b10000001;b=8'b00110000;
#100$stop;
end
compare1m(.equal(equal),.a(a),.b(b));
endmodule
实验波形:
实验分析:
RTL,综合后门级仿真和布线后仿真的区别
1.RTL行为级仿真
这个阶段的仿真可以用来检查代码中的语法错误以及代码行为的正确性,其中不包括延时信息。
如果没有实例化一些与器件相关的特殊底层元件的话,这个阶段的仿真也可以做到与器件无关。
因此在设计的初期阶段不使用特殊底层元件即可以提高代码的可读性、可维护性,又可以提高仿真效率,且容易被重用。
2.综合后门级功能仿真(前仿真)
一般在设计流程中的第二个仿真是综合后门级功能仿真。
绝大多数的综合工具除了可以输出一个.VO标准网表文件以外,还可以输出Verilog或者VHDL网表,其中标准网表文件是用来在各个工具之间传递设计数据的,并不能用来做仿真使用,而输出的Verilog或者VHDL网表可以用来仿真,之所以叫门级仿真是因为综合工具给出的仿真网表已经是与生产厂家的器件的底层元件模型对应起来了,所以为了进行综合后仿真必须在仿真过程中加入厂家的器件库,对仿真器进行一些必要的配置,不然仿真器并不认识其中的底层元件,无法进行仿真。
Xilinx公司的集成开发环境ISE中并不支持综合后仿真,而是使用映射前门级仿真代替,对于Xilinx开发环境来说,这两个仿真之间差异很小。
3.时序仿真(后仿真)
在设计流程中的最后一个仿真是时序仿真。
在设计布局布线完成以后可以提供一个时序仿真模型,这种模型中也包括了器件的一些信息,同时还会提供一个SDF时序标注文件(StandardDelayformatTimingAnotation)。
SDF时序标注最初使用在Verilog语言的设计中,现在VHDL语言的设计中也引用了这个概念。
对于一般的设计者来说并不需知道SDF
对源程序.v的仿真称之为功能仿真,对.vo的仿真称之为网表仿真,这里使用的就是厂家实际用到的元件,是为了确认综合是不是实现了用户预想的功能。
和加入sdo之后的仿真是真正加入了线路延时的仿真。
选做2:
7段数码管译码电路
实验代码:
模块源代码:
modulesegment(a,b);
input[3:
0]a;
output[6:
0]b;
reg[6:
0]b;
always@(a)
begin
case(a)
4'd0:
b=7'b0000001;
4'd1:
b=7'b1001111;
4'd2:
b=7'b0010010;
4'd3:
b=7'b0000110;
4'd4:
b=7'b1001100;
4'd5:
b=7'b0100100;
4'd6:
b=7'b0100000;
4'd7:
b=7'b0001111;
4'd8:
b=7'b0000000;
4'd9:
b=7'b0000100;
default:
b=7'bx;
endcase
end
endmodule
测试模块源代码:
`timescale1ns/1ns
modulesegment_tb;
reg[3:
0]a;
wire[6:
0]b;
initial
begin
a=4'b0;
#10$stop;
end
always
begin
#1a=a+1'b1;
end
segmentm(.a(a),.b(b));
endmodule
实验波形:
实验二
实验目的:
掌握较为复杂电路设计方法。
实验内容:
必做实验:
练习三、利用条件语句实现计数分频时序电路
练习五、用always块实现较复杂组合逻辑电路
选做实验:
选做一、练习三的练习题
选做二、练习五的练习题
练习三:
利用条件语句实现计数分频时序电路
实验目的:
1.掌握条件语句在简单时序模块设计中的使用。
2.学习在Verilog模块中应用计数器。
3.学习测试模块的编写、综合和不同层次的仿真。
实验内容:
可总和风格的分频器,可将10MHZ的时钟分频为500khz的时钟。
实验代码:
模块源代码:
modulefdivision(RESET,F10M,F500K);
inputF10M,RESET;
outputF500K;
regF500K;
reg[7:
0]j;
always@(posedgeF10M)
if(!
RESET)//低电平复位
begin
F500K<=0;
j<=0;
end
else
begin
if(j==19)//对计数器进行判断,以确定F500K信号是否反转
begin
j<=0;
F500K<=~F500K;
end
else
j<=j+1;
end
endmodule
测试模块源代码:
`timescale1ns/100ps
`defineclk_cycle50
moduledivision_Top;
regF10M,RESET;
wireF500K_clk;
always#`clk_cycleF10M=~F10M;
initial
begin
RESET=1;
F10M=0;
#100RESET=0;
#100RESET=1;
#10000$stop;
end
fdivisionfdivision(.RESET(RESET),.F10M(F10M),.F500K(F500K_clk));
endmodule
实验波形:
实验五:
用always块实现较复杂的组合逻辑电路
实验目的:
1.掌握用always实现较大组合逻辑电路的方法
2.进一步了解assign与always两种组合电路实现方法的区别和注意点
3.学习测试模块中随机数的产生和应用
4.学习综合不同层次的仿真,并比较结果
实验内容:
设计一个简单的指令译码电路,通过对指令的判断,对输入数据执行相应的操作,包括加、减、与、或和求反,无论数据还是指令发生变化,都要做出及时的反应。
实验代码:
模块原代码:
`defineband3'd2
`definebor3'd3
`defineunegate3'd4
modulealu(out,opcode,a,b);
output[7:
0]out;
reg[7:
0]out;
input[2:
0]opcode;
input[7:
0]a,b;
always@(opcodeoraorb)
begin
case(opcode)
`plus:
out=a+b;//以下是加,减,与,或,非,反等等
`minus:
out=a-b;
`band:
out=a&b;
`bor:
out=a|b;
`unegate:
out=~a;
default:
out=8'hx;//没有收到指令就随意输出
endcase
end
endmodule
指令译码器的测试模块源代码:
`timescale1ns/1ns
`include"./alu.v"
modulealutest;
wire[7:
0]out;
reg[7:
0]a,b;
reg[2:
0]opcode;
parametertimes=5;
initial
begin
a={$random}%256;
b={$random}%256;
opcode=3'h0;
repeat(times)
begin
#100a={$random}%256;
b={$random}%256;
opcode=opcode+1;
end
#100$stop;
end
alualu(out,opcode,a,b);
endmodule
实验分析:
当alutest的opcode为不同值时,a和b执行不同的操作,输出不同的值。
加减与或反分别对应opcode的12345。
练习题3:
利用10mhz的时钟,设计一个单周期形状的周期波形。
实验代码:
模块源代码:
moduleoptional3(RESET,F10M,signal);
inputF10M,RESET;
outputsignal;
regsignal;
reg[8:
0]j;
always@(posedgeF10M)
if(!
RESET)
begin
signal<=0;
j<=0;
end
else
begin
case(j)
9'd199:
signal<=~signal;
9'd299:
signal<=~signal;
endcase
if(j!
=9'd499)
begin
j<=j+1;
end
else
begin
j<=0;
end
end
endmodule
测试模块源代码:
`timescale1ns/100ps
`defineclk_cycle50
moduleop3_tb;
regF10M,RESET;
wiresignal;
always#`clk_cycleF10M=~F10M;
initial
begin
RESET=1;
F10M=0;
#100RESET=0;
#100RESET=1;
end
optional3u(.RESET(RESET),.F10M(F10M),.signal(signal));
endmodule
实验波形:
练习题4:
设计一个8路数据选择器,每路输入数据与输出数据均为4位2进制数,当选择开关(至少3位)或输入数据发生变化时,输出数据也相应地变化。
实验代码:
模块源代码:
moduleoptional5(out,opcode,in0,in1,in2,in3,in4,in5,in6,in7);
output[3:
0]out;
reg[3:
0]out;
input[2:
0]opcode;
input[3:
0]in0,in1,in2,in3,in4,in5,in6,in7;
always@(opcodeorin0orin1orin2orin3orin4orin5orin6orin7)
begin
case(opcode)
3'd0:
out=in0;
3'd1:
out=in1;
3'd2:
out=in2;
3'd3:
out=in3;
3'd4:
out=in4;
3'd5:
out=in5;
3'd6:
out=in6;
3'd7:
out=in7;
endcase
end
endmodule
测试模块源代码:
`timescale1ns/1ns
moduleop5_tb;
wire[3:
0]out;
reg[3:
0]in0,in1,in2,in3,in4,in5,in6,in7;
reg[2:
0]opcode;
parametertimes=50;
initial
begin
in0={$random}%256;
in1={$random}%256;
in2={$random}%256;
in3={$random}%256;
in4={$random}%256;
in5={$random}%256;
in6={$random}%256;
in7={$random}%256;
opcode=3'd0;
repeat(times)
begin
#100in0={$random}%256;
in1={$random}%256;
in2={$random}%256;
in3={$random}%256;
in4={$random}%256;
in5={$random}%256;
in6={$random}%256;
in7={$random}%256;
#200opcode=opcode+1;
end
#5000$stop;
end
optional5u(.out(out),.opcode(opcode),.in0(in0),.in1(in1),.in2(in2),.in3(in3),.in4(in4),.in5(in5),.in6(in6),.in7(in7));
endmodule
实验波形:
实验三
实验目的:
掌握函数和任务的开发与使用。
实验内容:
必做实验:
练习六、在Verilog中使用函数
练习七、在Verilog中使用任务
选做实验:
选做一、练习六的练习题
选做二、练习七的练习题
练习六:
在VerilogHDL中使用函数
实验目的:
1.了解函数的定义和在模块设计中的使用
2.了解函数的可综合性问题
3.了解许多综合器不能综合复杂的算术运算
实验内容:
做一个函数调用的示例,采用同步时钟触发运算,每个clk时钟周期都会执行一次运算。
在测试模块中,通过调用系统任务$display及在时钟的下降沿显示每次计算的结果。
实验代码:
模块源代码:
moduletest6(clk,n,result,reset);
output[31:
0]result;
input[3:
0]n;
inputreset,clk;
reg[31:
0]result;
always@(posedgeclk)
begin
if(!
reset)
result<=0;
else
begin
result<=n*factorial(n)/((n*2)+1);
end
end
function[31:
0]factorial;
input[3:
0]operand;
reg[3:
0]index;
begin
factorial=operand?
1:
0;
for(index=2;index<=operand;index=index+1)
factorial=index*factorial;
end
endfunction
endmodule
测试模块源代码:
`include"test6.v"
`timescale1ns/100ps
`defineclk_cycle50
moduletryfuctTop;
reg[3:
0]n,i;
regreset,clk;
wire[31:
0]result;
initial
begin
clk=0;
n=0;
reset=1;
#100reset=0;
#100reset=1;
for(i=0;i<=15;i=i+1)
begin
#200n=i;
end
#100$stop;
end
always#`clk_cycleclk=~clk;
test6u(.clk(clk),.n(n),.result(result),.reset(reset));
endmodule
实验波形:
练习七:
在VerilogHDL中使用任务
实验目的:
1.掌握任务在Verilog模块设计中的应用
2.学会在电平敏感列表的always中使用拼接操作、任务和阻塞赋值等语句,并生成复杂组合逻辑的高级方法
实验内容:
利用电平敏感的always块和一个比较两变量大小排序的任务,设计4位并行输入数的高速排序组合逻辑。
实验代码:
模块源代码:
moduletest7(ra,rb,rc,rd,a,b,c,d);
output[3:
0]ra,rb,rc,rd;
input[3:
0]a,b,c,d;
reg[3:
0]ra,rb,rc,rd;
reg[3:
0]va,vb,vc,vd;
always@(aorborcord)
begin
{va,vb,vc,vd}={a,b,c,d};
sort2(va,vc);
sort2(vb,vd);
sort2(va,vb);
sort2(vc,vd);
sort2(vb,vc);
{ra,rb,rc,rd}={va,vb,vc,vd};
end
tasksort2;
inout[3:
0]x,y;
reg[3:
0]tmp;
if(x>y)
begin
tmp=x;
x=y;
y=tmp;
end
endtask
endmodule
测试模块源代码:
`timescale1ns/100ps
`include"test7.v"
moduletask_Top;
reg[3:
0]a,b,c,d;
wire[3:
0]ra,rb,rc,rd;
initial
begina=0;b=0;c=0;d=0;
repeat(50)
begin
#100a={$random}%15;
b={$random}%15;
c={$random}%15;
d={$random}%15;
end
#100$stop;
end
test7u(.a(a),.b(b),.c(c),.d(d),.ra(ra),.rb(rb),.rc(rc),.rd(rd));
endmodule
实验波形:
练习题5:
设计一个带控制端的逻辑运算电路,分别完成正整数的平方、立方和最大数为5的阶乘运算。
实验代码:
模块源代码:
moduleop6(clk,n,result,reset,control);
output[31:
0]result;
input[3:
0]n;
inputreset,clk;
input[1:
0]control;
reg[31:
0]result;
always@(posedgeclk)
begin
if(!
reset)
result<=0;
else
begin
case(control)
2'd0:
result<=n*n;
2'd1:
result<=n*n*n;
default:
//result<=n*factorial(n)/((n*2)+1);
result<=factorial(n);
endcase
end
end
function[31:
0]factorial;
input[3:
0]operand;
reg[3:
0]index;
begin
factorial=operand?
1:
0;
for(index=2;index<=operand;index=index+1)
factorial=index*factorial;
end
endfunction
endmodule
测试模块源代码: