计算机原理与结构 实验1 《计算机硬件描述语言》
一、实验目的
1、了解:System Verilog如何构建计算机硬件;
2、了解:Quartus II中如何设置Modelsim工具的使用及联合仿真;
3、 掌握:Quartus II 的设计方案输入;
4、掌握:Modelsim对信号的仿真调试。
二、实验内容
某乘法器用 System Verilog 实现如下:
module basic_base2_mul(x_in, y_in, p_out);
parameter N = 8,
M = 4;
input logic [N-1:0] x_in;
input logic [M-1:0] y_in;
output logic [N+M-1:0] p_out;
integer i;
reg [M:0] wires[N:0];
initial
begin
for (i=0;i<=N;i=i+1) begin
wires[i]=0;
end
end
always @(x_in or y_in)begin
for(i=0; i<=N-1; i=i+1)begin
wires[i+1] = mult_by_1(x_in[i], wires[i][M:1], y_in);
p_out[i] = wires[i+1][0];
end
p_out[N+M-1:N] = wires[N][M:1];
end
function [M:0] mult_by_1;
input xi;
input [M-1:0] A, B;
if(xi) mult_by_1 = A + B;
else mult_by_1 = A;
endfunction
endmodule
试用 QuartusII/Modelsim 进行仿真,给出仿真结果,并说明程序每条语句的作用。
三、实验方法
利用ModelSim SE 10.1开发工具、Quartus II 13开发工具进行System Verilog语言实现二进制乘法及其仿真测试,先使用ModelSim再接着使用Quartus II进行仿真。
四、实验步骤
1、打开ModelSim 10.1a工具,新建一个项目(Project),在项目中新建仿真代码文件basic_base2_mul.sv
,编入给出的乘法器System Verilog代码并保存、编译,此时可见文件的状态从问号变成了一个绿色的勾;
2、再新建一个测试文件test_basic_base2_mul.sv
,编入相应的测试代码,和上一步的步骤相同,进行保存、编译,结果如下;
3、点击菜单下的 Simulation->Start Simulation 选项,选中test文件开始仿真;(这里注意下面有个Enable optimization的选项不要勾选,否则没有信号)
4、将Object窗口中的三个相关信号x_in
、y_in
、p_out
加入Wave波形窗口;
5、使用10ns为单位进行仿真,点击上方的“Run”代表的按钮开始仿真;
6、ModelSim进行简单仿真结束后,打开Quartus II进行联合仿真。新建一个Quartus项目,选择合适的配置,比如主板类型、引脚数等等,并引入在ModelSim中编写好的basic_base2_mul.sv
文件,形成一个新项目;
7、点击上方按钮工具栏中的Start Compilation执行编译,编译成功;
此时可以查看编译出的硬件电路图;
8、通过右击文件->settings->Simulation增加test benches的方式引入测试文件test_basic_base2_mul.sv并再次执行编译;
9、点击菜单栏下的Tools->Run Simulation Tool->Gate Level Simulation开始仿真,可以发现仿真结果不对,原因是运算有时延但是变化是瞬间的;
10、重新修改test文件,将时延改为20ns,重新编译后再进行仿真得到正确的仿真结果;
五、实验结果
最后的实验结果已经包含于上述步骤当中。
程序语句解释:
// N比特乘M比特的二进制乘法器
// 声明模块,模块名(定义输入输出)
module basic_base2_mul(x_in, y_in, p_out);
parameter N = 8, M = 4; // 定义常量数据,此模块中表示位数
input logic [N-1:0] x_in; // 定义N bit的输入x_in
input logic [M-1:0] y_in; // 定义M bit的输入y_in
output logic [N+M-1:0] p_out; // 定义M+N bit的输出p_out
integer i; // 定义一个整数控制循环
reg [M:0] wires[N:0];
// 线路全部初始化为0,wires是结构化元件间物理连线
initial begin
for (i=0;i<=N;i=i+1) begin
wires[i]=0;
end
end
// 乘法运算
always @(x_in or y_in) begin
for(i=0; i<=N-1; i=i+1) begin
// 逐位进行乘法运算
wires[i+1] = mult_by_1(x_in[i], wires[i][M:1], y_in);
p_out[i] = wires[i+1][0];
end
p_out[N+M-1:N] = wires[N][M:1];
end
// 一位乘法函数
function [M:0] mult_by_1;
input xi;
input [M-1:0] A, B;
if(xi) mult_by_1 = A + B;
else mult_by_1 = A;
endfunction // 函数结束
endmodule // 模块结束
六、实验结论
本次实验通过使用ModelSim开发工具成功对二进制乘法器进行仿真测试,可直观的查看System Verilog语言的成果,实验测试符合预期。
七、实验小结
主要是学会了如何单独使用ModelSim工具进行简单的仿真以及如何使用Quartus II工具结合ModelSim进行仿真操作,还进一步熟悉了System Verilog语言的语法。实验过程中出现了比较多的问题,但是都一一解决了,主要还是求助于同学和网上的博客。比如,一开始在ModelSim中新建文件,选择的文件类型应该是System Verilog类型而不是Verilog类型,二者的语法还是不太相同的,初次因为这个耗时较长,因为选择的Verilog类型,编译的时候一直报语法错(主要是从定义那里开始一直往下都报错)。简单仿真的时候,要注意有个Optimization选项卡下的Enable Optimization选项不要选,否则会因为作了代码优化导致信号出不来。还有就是通过Quartus II打开ModelSim的时候必须保证跳转到ModelSim之前没有打开ModelSim,否则会出现证书错误(一个证书只支持一个窗口,麻了)。
还有一些关于System Verilog和Verilog的一些知识:
在传统的Verilog中,变量主要分为线网型(wire)和寄存器型(reg)两大类型。只有寄存器型变量才能够在过程代码块中被赋值,而线网型变量只能在过程代码块之外被连续赋值。寄存器型变量的过程赋值和线网型变量的连续赋值使用了完全不同的语句结构。在Verilog中,二者的区分比较微妙,以至于有些专业的工程师也在设计中混淆二者。由于always过程代码块不仅可以描述时序逻辑电路,还可以通过将所有寄存器型的输入变量添加到敏感列表来实现纯组合逻辑电路,因此“寄存器型”这个带有时序逻辑意义的术语本身也令人误会。
程赋值和线网型变量的连续赋值使用了完全不同的语句结构。在Verilog中,二者的区分比较微妙,以至于有些专业的工程师也在设计中混淆二者。由于always过程代码块不仅可以描述时序逻辑电路,还可以通过将所有寄存器型的输入变量添加到敏感列表来实现纯组合逻辑电路,因此“寄存器型”这个带有时序逻辑意义的术语本身也令人误会。
System Verilog增强了寄存器型变量的功能,它可以像Verilog中线网型变量一样由线网(如逻辑门等模块的输出)驱动(这样的线网驱动寄存器的方式在Verilog中是不允许的)。这种增强的变量类型被命名为“逻辑型”,从而避免“寄存器型”在字面上给人带来的误会。在大多数情况中,System Verilog中的logic可以替代Verilog中的reg和wire,但是如果某个某个变量具有多个驱动源,那么就不能使用logic,而要使用严格的wire来定义它。