写了个spi module,怎么测都不过,没办法,回头来做行为仿真。
学习写testbench使用的是下面的文档,来自某FPGA制造商文档:
/Files/pied/verilog_testbench_primer.pdf
区别与verilog HDL代码,主要留意以下内容:
1,语言本身支持的特征和可综合的代码是两回事,不是所有verilog语言都可以转化为硬件的。
2,testbench作为top module,不需要任何输入和输出。
3,在testbench module中将要测试的模块例化为dut(名字可以任起),input要是reg类型,output要是wire类型,inout是reg。
4,initial和always是同时执行的,只是initial只执行一次。
5,通过在initial里面添加语句,对 dut进行各种输入设置,以达到测试dut的目的。
6,必要时在测试的module,或者是testbench的代码中添加$display($time,"<value of BufferPort :%h>", BufferPort); 来查看变量值。
下面是给俺的SPI module写的testbench,参考上面的pdf写的:
module controller();
reg rst_l;
reg clk_100;
reg sdi;
reg sck;
reg cs;
reg TransFlag;
reg [
0:
7] trsData;
wire [
0:
7] rcvData;
wire TransEndFlag;
wire ReceiveFlag;
wire sdo;
reg [
4:
0] i;
reg [
4:
0] counter;
spi dut( .rst(rst_l),
.clk(clk_100),
.sdi(sdi),
.sdo(sdo),
.sck(sck),
.cs(cs),
.trsData(trsData),
.rcvData(rcvData),
.TransFlag(TransFlag),
.TransEndFlag(TransEndFlag),
.ReceiveFlag(ReceiveFlag)
);
//
test 'read'&'read' from reg 0x0000 of ad9865
always #
5 clk_100 = ~clk_100;
initial
begin
$display($
time,
"
It's my first test bench!
");
clk_100 =
1
'
b0;
counter =
3
'
b000;
$display($
time,
"
coming out of reset!
");
//
initiate spi input
sck =
1
'
b0;
cs =
1
'
b1;
sdi =
1
'
b0;
rst_l =
1
'
b0;
#
20 rst_l =
1
'
b1;
//
send parametes set
TransFlag =
1
'
b1;
trsData =
8
'
b0101_0101;
//
begin send test
cs =
1
'
b0;
wait (TransEndFlag ==
1
'
b1);
$display($
time,
"
send processing is finished!
");
TransFlag =
1
'
b0;
cs =
1
'
b1;
//
begin receive test
cs =
1
'
b0;
for (i =
8; i !=
0; i=i-
1) sdi =
1;
wait (ReceiveFlag ==
1
'
b1);
cs =
1;
$display($
time,
"
the data received :%h
", rcvData);
end
always @(
posedge clk_100)
begin
if(sdo ==
1)
$display($
time,
"
posedge_ of sdo comes :%h
", sdo);
if(counter ==
11)
begin
sck =~sck;
counter =
3
'
b000;
end
else
begin
counter = counter +
1
'
b1;
end
end
endmodule
再三检查SPI的逻辑,最后发现,我给的sck是clk的十分之一,而SPI module里面用的给端口采样的频率也是clk的十分之一,所以老是采样不成功;把sck改更小后问题解决。