寫了個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
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改更小后問題解決。
