西工大硬件描述语言实验报告文档格式.docx
《西工大硬件描述语言实验报告文档格式.docx》由会员分享,可在线阅读,更多相关《西工大硬件描述语言实验报告文档格式.docx(56页珍藏版)》请在冰豆网上搜索。
#100$stop;
end
comparem(.equal(equal),.a(a),.b(b));
五、综合仿真
RTL图及仿真后波形图:
六、思考题
1.课本练习一的测试方法二中,第二个initial块有什么用?
它与第一个initial块有什么关系?
测试方法二中的第二个initial用来暂停仿真以便观察仿真波形,它与第一个initial是并行关系
2.如果在第二个initial块中,没有写出#10000或者$stop,仿真会如何进行?
如果没有写#10000,仿真会直接停止,没有$stop,仿真不会结束。
3.比较两种测试方法,哪一种更全面?
第二种测试方法更全面,测试了更多种的变换的情况。
实验二简单分频时序逻辑电路的设计
1.掌握条件语句在简单时序模块设计中的使用;
2.掌握verilog语句在简单时序模块设计中的使用;
3.学习在Verilog模块中应用计数器;
4.学习测试模块的编写、综合和不同层次的仿真。
1.使用always块和@(posedgeclk)或@(negedgeclk)的结构来表述时序逻辑,设计1/2分频的可综合模型。
得到如下波形图:
2.对模块进行RTL级仿真、综合后门级仿真,布局布线仿真;
1.建立工程文件,编写模块源码和测试模块,要求测试模块能对源文件进行比较全面的测试。
2.编译源码和测试模块,用测试模块对源文件进行测试,并综合仿真。
得到波形图。
4.记录数据并完成实验报告。
1.模块代码
modulehalf_clk(reset,clk_in,clk_out);
inputclk_in,reset;
outputclk_out;
regclk_out;
always@(posedgeclk_in)
if(!
reset)
clk_out=0;
else
clk_out=~clk_out;
`timescale1ns/100ps
`defineclk_cycle50
moduletop;
regclk,reset;
wireclk_out;
always#`clk_cycleclk=~clk;
initial
begin
clk=0;
reset=1;
#10reset=0;
#110reset=1;
#100000$stop;
half_clkm0(.reset(reset),.clk_in(clk),.clk_out(clk_out));
RTL图以及仿真后波形图
1.如果没有reset信号,能否控制2分频clk_out信号的相位?
如果没有reset信号,则无法控制2分频clk_out信号的相位。
2.只用clk时钟沿的触发(即不用2分频产生的时钟沿)如何直接产生4分频、
8分频、或者16分频的时钟?
借助一个整型变量j做计数操作。
3.如何只用clk时钟沿的触发直接产生占空比不同的分频时钟?
借助一个整型变量j做计数操作,从而用clk时钟沿的触发直接产生4分频、8分频或者16分频的时钟,及产生占空比不同的分频时钟。
实验三利用条件语句实现计数分频时序电路
2.掌握最基本时序电路的实现方法;
1.复习课本,熟悉条件语句的使用方式;
2.建立工程并编写源代码;
3.综合并布局布线仿真并分析always语句在时序逻辑中的作用;
4.学习测试模块的编写、综合和仿真。
1.建立工程文件,编写模块源码和测试模块,要求测试模块能对源文件进行比较全面的测试;
2.编译源码和测试模块,用测试模块对源文件进行测试,并综合仿真;
3.观察综合后生成的文件和源文件的不同点和相同点;
4.综合时采用不同的FPGA器件,如Altera公司的CycloneII系列和StratixIII系列,观察综合后的结果有什么不同。
modulefdivision(RESET,F10M,F500K);
inputF10M,RESET;
outputF500K;
regF500K;
reg[7:
0]j;
always@(posedgeF10M)
RESET)//低电平复位。
F500K<
=0;
j<
else
if(j==19)//对计数器进行判断,以确定F500K信号是否反转。
=~F500K;
=j+1;
moduledivision_top;
regF10M,RESET;
wireF500K_clk;
always#`clk_cycleF10M=~F10M;
RESET=1;
F10M=0;
#100RESET=0;
#100RESET=1;
#10000$stop;
fdivisionfdivision(.RESET(RESET),.F10M(F10M),.F500K(F500K_clk));
RTL图以及仿真后波形图:
1.考虑如何实现任意数值分频。
任意分频代码:
moduledivn(clk,rst_n,o_clk);
inputclk,rst_n;
outputo_clk;
parameterWIDTH=3;
parameterN=5;
reg[WIDTH-1:
0]cnt_p,cnt_n;
//count_pose,count_nege
regclk_p,clk_n;
assigno_clk=(N==1)?
clk:
(N[0])?
(clk_p&
clk_n):
clk_p;
//如果N=1,o_clk=clk;
如果N为偶数,o_clk=clk_p;
如果N为奇数,o_clk=clk_p&
clk_n,
//之所以是相与运算,是因为clk_p和clk_n两者高电平比低电平多一个clk,而两者相//差半个clk,相与结果使o_clk占空比为50%
always@(posedgeclkornegedgerst_n)
rst_n)
cnt_p<
=0;
elseif(cnt_p==(N-1))
=cnt_p+1;
begin
clk_p<
elseif(cnt_p<
(N>
>
1))
=1;
always@(negedgeclkornegedgerst_n)
cnt_n<
elseif(cnt_n==(N-1))
=cnt_n+1;
clk_n<
elseif(cnt_n<
1))
end
3.如果综合时采用不同的FPGA器件,如Altera公司的CycloneII系列和StratixIII系列,想想综合后的结果有什么不同?
时钟分频的实现方法如果是采用行波时钟的方式(异步设计),容易造成时钟偏差,很难控制芯片内部的逻辑基本单元中的触发器的建立/保持时间,同时不同芯片的内部参数也有所不同,同一代码的时序分析结果分析得不同也很正常。
如果分频后的时钟作为后级设计的工作时钟,那么整个设计不只使用一个主时钟,而是用多个时钟来实现的话(异步设计),存在信号的跨时钟域转换问题,跨时钟域的信号如果设计不当,会采到亚稳态。
3.课后自己试着利用10MB的时钟,设计一个单周期形状的周期波形。
模块代码:
modulezhouqiwave(reset,F10M,a);
inputreset,F10M;
outputa;
rega;
reg[15:
0]b;
always@(resetorposedgeF10M)
reset)
a<
b<
if(b==199)
=~a;
=b+1;
if(b==299)
if(b==499)
测试代码:
`timescale10ns/10ns
modulezhouqiwave_tb;
regF10M,reset;
wirea;
always#5F10M=~F10M;
reset=0;
#5reset=1;
#6000$stop;
end
zhouqiwavem(.reset(reset),.F10M(F10M),.a(a));
endmodule
实验四阻塞赋值与非阻塞赋值的区别
1.通过实验,掌握阻塞赋值与非阻塞赋值的概念与区别;
2.深入理解顺序执行和并发执行的概念。
3.了解非阻塞和阻塞赋值的不同使用场合;
4.学习测试模块的编写,综合和不同层次的仿真。
1.本次实验参照课本上的练习三,采用VerilogHDL语言描述两个模块,分别包含有阻塞和非阻塞赋值语句;
2.编写测试模块,在相同输入信号的条件下,比较阻塞与非阻塞语句的输出结果;
3.对模块进行RTL级仿真、综合后门级仿真,布局布线仿真;
4.分析阻塞赋值与非阻塞赋值的区别。
1.仔细阅读课本,建立工程文件,编写模块源码和测试模块,要求测试模块能对源文件进行比较全面的测试;
3.观察综合后生成的两个电路结构图并观察仿真波形图,分析阻塞与非阻塞赋值的异同
a)采用阻塞赋值
moduleblocking(clk,a,b,c);
output[3:
0]b,c;
input[3:
0]a;
inputclk;
reg[3:
always@(posedgeclk)
b=a;
c=b;
$display("
Blocking:
a=%d,b=%d,c=%d."
a,b,c);
b)采用非阻塞赋值
modulenon_blocking(clk,a,b,c);
b<
=a;
c<
=b;
Non_Blocking:
`include"
./blocking.v"
./non_blocking.v"
modulecompareTop;
wire[3:
0]b1,c1,b2,c2;
regclk;
forever#50clk=~clk;
a=4'
h3;
____________"
);
#100a=4'
h7;
hf;
ha;
h2;
#100$display("
$stop;
End
non_blockingnon_blocking(clk,a,b2,c2);
blockingblocking(clk,a,b1,c1);
1.解释说明测试模块中forever语句后若有其他语句,是否能够执行?
为什么?
不能。
forever循环语句常用于产生周期性的波形,用来作为仿真测试信号。
它与always不同之处在于它不能独立写在程序中,而必须写在initial块中。
2.在blocking模块中按如下两种方法,仿真与综合的结果会有什么样的变化?
作出仿真波形,分析综合结果。
a)
always@(posedgeclk)
c=b;
b=a;
可以实现与上面非阻塞赋值相同的赋值结果。
b)
always@(posedgeclk)b=a;
always@(posedgeclk)c=b;
有可能出现竞争现象。
实验五用always块实现较复杂的组合逻辑电路
1.掌握用always实现较大组合逻辑电路的方法;
2.进一步了解assign与always两种组合电路实现方法的区别和注意点;
3.学习测试模块中随机数的产生和应用;
4.学习综合不同层次的仿真,并比较结果。
1.运用always语句块设计一个8位数据选择器。
要求:
每路输入数据与输出数据均为4位2进制数,当选择开关(至少3位)或输入数据发生变化时,输出数据也相应地变化;
2.写出测试模块,对模块的功能进行测试;
3.对模块进行RTL级仿真、综合后门级仿真,布局布线仿真。
3.观察综合后生成的两个电路结构图并观察仿真波形图,分析assign与always两种组合电路实现方法的区别和注意点;
1.模块代码:
`defineplus
3'
d0
`defineminus
3'
d1
`defineband
d2
`definebor
d3
`defineunegate3'
d4
//通过对指令的判断,对输入数据执行相应的操作,包括加、减、与、或和求反
//无论是指令作用的数据还是指令本身发生变化,结果都要作出及时的反应。
module
alu(out,opcode,a,b);
output[7:
0]out;
reg[7:
0]
out;
input[2:
0]opcode;
input[7:
0]a,b;
//操作数。
always@(opcodeoraorb)
//电平敏感的always块
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
endmodule
2.测试代码:
`include
"
./alu.v"
alutest;
wire[7:
a,b;
reg[2:
opcode;
parameter
times=5;
a={$random}%256;
//Givearadomnumberblongsto[0,255]
b={$random}%256;
opcode=3'
h0;
repeat(times)
#100
a={$random}%256;
//Givearadomnumber.
b={$random}%256;
opcode=opcode+1;
end
#100
end
alu
alu1(out,opcode,a,b);
1.分析用assign语句和always语句进行组合逻辑设计时有什么异同点?
verilog语言中的赋值语句有两种,一种是持续赋值语句(assign语句),另一种是过程赋值语句(always语句)。
持续赋值语句(assign语句)主要用于对wire型变量的赋值,因为wire的值不能存住,需要一直给值,所以需要用持续赋值。
过程赋值语句(always语句)主要用于reg型变量的赋值,因为always语句被执行是需要满足触发条件的,所以always过程块里面的内容不是每时每刻都被执行,因此需要将被赋值的对象定义成寄存器类型,以便这个值能被保持住。
过程赋值又分为阻塞赋值“=”和非阻塞赋值“<
=”两种。
2.使用always块设计一个八功能的算术运算单元,其输入信号a和b均为4位,还有功能选择select为3位,输出信号为out(5位)。
算术运算单元所执行的操作与select信号有关,具体关系如下表所列(忽略输出结果中的上溢和下溢位):
Select信号
函数的输出
3’b000
a
3’b001
a+b
3’b010
a-b
3’b011
a/b
3’b100
a%b(余数)
3’b101
<
1
3’b110
a>
3’b111
(a>
b)(大小副值比较)
`defineoriginal3'
`defineplus3'
`defineminus3'
`definedivision3'
`defineremainder3'
`defineleftmov3'
d5
`definerightmov3'
d6
`definecompare3'
d7
modulemathunit(out,select,a,b);
output[4:
0]out;
reg[4:
input[2:
0]select;
always@(selectoraorb)
case(select)
`original:
out=a;
out=a+b;
`division:
out=a/b;
`remainder:
out=a%b;
`leftmov:
out=a<
1;
`rightmov:
out=a>
`compare:
b?
a:
out=4’bx;
实验六在Verilog中使用函数
1.了解函数的定义和在模块设计中的使用;
2.了解函数的可综合性问题;
3.了解许多综合器不能综合复杂的算术运算;
1.本次实验是VerilogHDL语言函数调用的一个简单示范;
2.本实验采用同步时钟触发运算的执行,每个clk时钟周期都会执行一次运算;
3.在测试模块中,通过调用系统任务$display及在时钟的下降沿显示计算的结果。
1.建立工程文件;
2.参照资料编写源文件tryfun