问题:使用ModelSim仿真整个VORC(Video Oriented Reconfigurable Coprocessor)时,其结果出错。从仿真波形可以看出三点怪异之处。第一:数据ain和bin相加的结果表明两者是错位相加(即:0+0,1+1而不是0+1,1+2),对照电路图可以找到原因:ain数据存在一个乘法器的延迟时间,这造成ain数据会晚一个节拍参与计算。第二:当数据ain和bin均为0时,乘法器的输出不为0,而是1,查看测试文件中所加的激励以及定义电路功能的操作码,可知:初始化时,将操作码定义为0时,造成mult1的两个输入数据均为1,因此乘法器的输出为1。第三:当数据ain和bin增加到16时,加法出错,如图一黄色竖线所在位置。分析仿真波形可以找出一个原因:MULT1(乘法器1)的结果不正确,也就是说MULT1不能正常工作。导致乘法器不能正确工作的原因推测是乘法器存在延迟。由于初始的代码使用的是纯组合逻辑,因此可能造成时序的混乱。(接下来需要进行验证)
测试文件的写法是否正确?也就是说,测试文件能不能达到测试的效果?(测试文件确实有问题,最好将输入数据的变化节拍大于时钟周期)
图一 VORC加法仿真波形(出现错误)
1、VRC_MULT(乘法器使用纯组合电路实现)
用Verilog中的乘号来编写时,使用ModelSim仿真时有延时,这会导致仿真整个VRC结构时,结果出错。
代码:
'timescale 1ns/1ns
module mult_8x4 (a, b, y);
input [7:0] a;
input [3:0] b;
output [11:0] y;
reg [11:0] y;
reg [7:0] areg;
reg [3:0] breg;
always @ (a or b)
begin
areg <= a;
breg <= b;
y <= areg * breg;
end
endmodule
测试文件
'timescale 1ns/1ns
module mult_8x4_tb ;
reg [7:0] a;
reg [3:0] b;
wire [11:0] y;
mult_8x4 dut (a, b, y);
initial
begin
a=0; b=0;
end
always #10 a = a + 1;
always #20 b = b + 1;
endmodule
仿真波形:(此结果表明:乘积相对于输入数据延迟一拍。)
图二 纯组合电路组成的乘法器仿真波形
2、VRC_MULT(乘法器使用时序电路实现)
采用时序逻辑来设计乘法器可以解决上述因延迟造成的结果差错问题。
代码:
'timescale 1ns/1ns
module mult_8x4 (clk, start,a, b, y, done);
input clk;
input start;
input [7:0] a;
input [3:0] b;
output [11:0] y;
output done;
reg [11:0] y;
reg done;
reg [7:0] areg;
reg [3:0] breg;
always @ (posedge clk or start or a or b) //posedge clk or start or
begin
if (start)
begin
areg <= a;
breg <= b;
y <= areg * breg;
done <=1;
end
else
begin
y <= 12'h000;
done <= 0;
end
end
endmodule
测试代码1:(输入数据ain变化节拍为一个时钟周期,bin为两个时钟周期)
'timescale 1ns/1ns
module mult_8x4_tb ;
reg clk;
reg start;
reg [7:0] a;
reg [3:0] b;
wire [11:0] y;
wire done;
mult_8x4 dut (clk, start,a, b, y, done);
initial clk = 0;
always #10 clk = ~clk;
initial
begin
a=0;
b=0;
start = 1;
end
always #20 a = a + 1;
always #40 b = b + 1;
endmodule
仿真波形:(从波形可以看出,在时钟的上升沿采集到乘积结果是正确,红线表示乘积延迟1/2周期。)
图三 使用时序逻辑组成的乘法器仿真波形
测试代码2:(输入数据ain变化节拍为二分之一时钟周期,bin为一个时钟周期)
'timescale 1ns/1ns
module mult_8x4_tb ; //()clk, start,done
reg clk;
reg start;
reg [7:0] a;
reg [3:0] b;
wire [11:0] y;
wire done;
mult_8x4 dut (clk, start,a, b, y, done);
initial clk = 0;
always #10 clk = ~clk;
initial
begin
a = 0;
b = 0;
// y = 0; //线网不能赋初值
start = 1;
end
always #10 a = a + 1;
always #20 b = b + 1;
endmodule
仿真波形:(从波形看,乘积结果存在1/2时钟周期的延迟,而实际情况是:乘法器是一个存组合电路,敏感信号包括ain和bin,如果两者的变化比时钟周期小,那么就会出现延迟,如下图所示。)
图四 使用时序逻辑设计乘法器并修改测试文件后的仿真波形
3、结论
从上面的波形图中,可以看到乘积结果y在起始阶段都存在一个节拍的红线,这表明乘法器本身存在延迟。
乘法器是众多数字系统中的基本模块。从原理上讲,它属于组合逻辑;但从工程设计上来说,它应该利用时序逻辑设计的方法来实现。
用Verilog HDL中的运算表达式描述乘法器是很容易的。
借助综合工具,可将上述带"*"运算表达式的Verilog代码自动综合成典型的电路结构。综合器有许多选择可供选择,通过设置相应的选项和约束文件,可以在面积和速度之间寻求折中。高性能的综合器会根据设计者提供的选项和约束文件,自动选择一种电路结构;有时,为了满足对运算速度的要求,综合器会自动插入流水线结构,以提供运算的性能。
随着综合工具的不断发展,综合器的资源库中的基本电路结构越来越多,通过编译系统的分析,可以为设计者自动选择满足约束的电路结构。
4、疑问
为了提高乘法器的运算性能,需要自己动手设计高速乘法器,那么如何设计?其设计的关键是什么?
5、经验
使用时序乘法器并修改测试文件(使测试文件的输入数据的变化节拍等于或者大于时钟周期)
仿真波形:(当ain=32,bin=16时,相加得到的结果为31,出现错误的原因是:乘法器2存在一个节拍的延迟,导致加法器的输入数据错误(本应该输入1但实际是输入的延迟信号0.))
图五 乘法器延迟造成的另一问题
6、解决办法:使用移位相加来实现乘法器:(使用这种方法设计的乘法器用ModelSim仿真没有延迟)
代码:
// mult_for (use shifting and addition) combinational logic
module mult_for (prod, mcnd, mpy);
parameter size = 8; //The parameter is useful for IP reuse.
input [size : 1] mcnd;
input [size : 1] mpy;
output [2*size :1] prod;
reg [2*size :1] prod;
integer i;
always @ (mcnd or mpy)
begin
prod = 0;
for (i = 1; i<=size; i = i+1)
if(mpy[i])
prod = prod + (mcnd <<(i-1));
end
endmodule
测试代码:
module mult_for_tb;// (prod, mcnd, mpy);
reg [8:1] mcnd;
reg [8:1] mpy;
wire [16:1] prod;
mult_for dut (prod, mcnd, mpy);
initial
begin
mcnd = 0;
mpy = 0;
end
always #20 mcnd = mcnd + 1;
always #20 mpy = mpy + 1;
endmodule
波形仿真:
图六使用移位相加的方式实现的乘法器仿真波形无延迟
7、在VORC中使用移位相加乘法器(无延迟),可以解决上面仿真出现的问题。
代码:
'timescale 1ns/1ns
module mult_8x4 (clk, start, a, b, y);
input clk;
input start;
input [7:0] a;
input [3:0] b;
output [11:0] y;
reg [11:0] y;
reg [7:0] areg;
reg [3:0] breg;
integer i;
always @ (posedge clk or start or a or b)
begin
y = 0;
if (start)
begin
areg = a;
breg = b;
for (i = 0; i<=3; i = i+1)
if(breg[i])
y = y + (areg << i);
end
else
begin
y = 12'h000;
end
end
endmodule
VORC实现加法运算时的仿真波形:
图七 VORC_PE加法运算仿真波形(成功)
8、总结
使用Verilog HDL中的算术运算符"*"编写代码,在ModelSim进行仿真时,乘积结果会出现延迟,这是导致VORC时序出错,仿真结果不正确的关键。解决办法:使用移位相加的方法编写乘法器,去除延迟,在仿真VORC的加法操作时,可以得到正确的仿真结果。