146 lines
No EOL
3.1 KiB
Verilog
146 lines
No EOL
3.1 KiB
Verilog
`timescale 1ns / 1ps
|
|
|
|
module spi_core_tb();
|
|
|
|
localparam period = 10;
|
|
parameter WORDSIZE = 16;
|
|
reg clk, rst;
|
|
|
|
reg sck, sdi, ncs;
|
|
wire sdo;
|
|
|
|
wire cs_rising, cs_falling;
|
|
|
|
wire [WORDSIZE-1:0] data_out;
|
|
wire data_out_valid;
|
|
|
|
reg [WORDSIZE-1:0] data_in;
|
|
reg data_in_valid;
|
|
|
|
initial begin
|
|
clk = 0;
|
|
/* rst set below */
|
|
sck = 0;
|
|
sdi = 0;
|
|
ncs = 1;
|
|
data_in = 0;
|
|
data_in_valid = 0;
|
|
forever #period clk = ~clk;
|
|
end
|
|
|
|
integer i;
|
|
integer j;
|
|
integer k;
|
|
integer testcase;
|
|
reg [WORDSIZE-1:0] sim_rxdata [1:4];
|
|
reg [WORDSIZE-1:0] sim_txdata [1:4];
|
|
reg [WORDSIZE-1:0] sim_txbuf;
|
|
initial begin
|
|
sim_rxdata[1] = 16'h523a;
|
|
sim_rxdata[2] = 16'hbeef;
|
|
sim_rxdata[3] = 16'h7721;
|
|
sim_rxdata[4] = 16'h0108;
|
|
|
|
sim_txdata[1] = 16'h1234;
|
|
sim_txdata[2] = 16'h5678;
|
|
sim_txdata[3] = 16'h9abc;
|
|
sim_txdata[4] = 16'hdef9;
|
|
|
|
for (j=1; j<=4; j=j+1) begin
|
|
$display("TC-SIMPLE-%d: rx/tx %d word", j, j);
|
|
testcase = j;
|
|
|
|
rst = 1;
|
|
repeat(2) @(posedge clk);
|
|
rst = 0;
|
|
@(posedge clk);
|
|
|
|
data_in = sim_txdata[1];
|
|
data_in_valid = 1;
|
|
@(posedge clk);
|
|
|
|
data_in_valid = 0;
|
|
ncs = 0;
|
|
@(posedge clk);
|
|
if (cs_rising || !cs_falling || data_out_valid) $finish;
|
|
|
|
for (k=0; k<j; k=k+1) begin
|
|
sim_txbuf = 0;
|
|
data_in = 16'h0000;
|
|
data_in_valid = 0;
|
|
|
|
for (i=0; i<WORDSIZE; i=i+1) begin
|
|
sdi = sim_rxdata[k+1][WORDSIZE-1-i];
|
|
sck = 0;
|
|
|
|
@(posedge clk);
|
|
if (cs_rising || cs_falling || (i < WORDSIZE-1 && data_out_valid)) $finish;
|
|
@(posedge clk);
|
|
if (cs_rising || cs_falling || data_out_valid) $finish;
|
|
|
|
sck = 1;
|
|
sim_txbuf[WORDSIZE-1-i] = sdo;
|
|
|
|
if (i == WORDSIZE-1) begin
|
|
data_in = sim_txdata[k+2];
|
|
data_in_valid = 1;
|
|
end
|
|
|
|
@(posedge clk);
|
|
data_in_valid = 0;
|
|
if (cs_rising || cs_falling || (i < WORDSIZE-1 && data_out_valid)) $finish;
|
|
@(posedge clk);
|
|
if (cs_rising || cs_falling || (i < WORDSIZE-1 && data_out_valid)) $finish;
|
|
end
|
|
|
|
if (!data_out_valid) $finish;
|
|
if (data_out != sim_rxdata[k+1]) $finish;
|
|
if (!sim_txbuf == sim_txdata[k+1]) $finish;
|
|
end
|
|
|
|
sck = 0;
|
|
@(posedge clk);
|
|
ncs = 1;
|
|
@(posedge clk);
|
|
if (!cs_rising || cs_falling || data_out_valid) $finish;
|
|
|
|
repeat(10) @(posedge clk);
|
|
end
|
|
|
|
$finish;
|
|
end
|
|
|
|
reg cs_rising_last, cs_falling_last;
|
|
always @(posedge clk) begin
|
|
/* Only one signal can be active at the same time */
|
|
if (cs_rising && cs_falling) $finish;
|
|
/* Both signals must be one-cycle pulses */
|
|
if (cs_rising == 1 && cs_rising_last == 1) $finish;
|
|
if (cs_falling == 1 && cs_falling_last == 1) $finish;
|
|
cs_rising_last <= cs_rising;
|
|
cs_falling_last <= cs_falling;
|
|
end
|
|
|
|
reg sck_last, sdo_last;
|
|
always @(posedge clk) begin
|
|
//if (sck_last == sck && sdo_last != sdo) $finish; /* SDO can only change on SCK edges */
|
|
sck_last <= sck;
|
|
sdo_last <= sdo;
|
|
end
|
|
|
|
|
|
spi_core #(.WORDSIZE(WORDSIZE)) spi_core_dut (
|
|
.clk(clk), .rst(rst),
|
|
|
|
.sck(sck), .sdi(sdi), .sdo(sdo), .ncs(ncs),
|
|
|
|
.cs_rising(cs_rising),
|
|
.cs_falling(cs_falling),
|
|
|
|
.data_out(data_out),
|
|
.data_out_valid(data_out_valid),
|
|
.data_in(data_in),
|
|
.data_in_valid(data_in_valid)
|
|
);
|
|
|
|
endmodule |