mirror of
https://github.com/aolofsson/oh.git
synced 2025-02-07 06:44:09 +08:00
Adding testbench for stimulus
-New name, new methodology
This commit is contained in:
parent
f0d0750dae
commit
996d980059
@ -1,61 +1,64 @@
|
|||||||
// A stimulus file provides inputs signals to the design under test (DUT).
|
// A stimulus file provides inputs signals to the design under test (DUT).
|
||||||
// This stimulus module is designed to be compatible with verilog simulators,
|
// This stimulus module is designed to be compatible with verilog simulators,
|
||||||
// emulators, and FPGA prototyping. This is akin to a simple test vector generator
|
// emulators, and FPGA prototyping. This is akin to a simple test vector generator
|
||||||
// No looping supported!
|
|
||||||
//
|
|
||||||
// Memory format:
|
|
||||||
// b0 = valid,
|
|
||||||
// b1-7 = wait time
|
|
||||||
// b8-bxxx = packet
|
|
||||||
//
|
//
|
||||||
// Test Process:
|
// Test Process:
|
||||||
// 1. Zero out memory (or write program)
|
// 1. Zero out memory (or write program)
|
||||||
// 2. Set go signal
|
// 2. Set go signal
|
||||||
//
|
// 3. Drive out all valid packets sequentially
|
||||||
module stimulus #( parameter DW = 32, // Memory width=DW+
|
|
||||||
parameter MAW = 15, // Memory address width
|
module stimulus
|
||||||
parameter HEXFILE = "NONE" // Name of hex file
|
#(parameter DW = 64, // Stimulus packet width
|
||||||
|
parameter DEPTH = 1024, // Memory depth
|
||||||
|
parameter CW = 0, // bit[0]=valid, [CW-1:1]=timestamp
|
||||||
|
parameter MW = DW + CW, // Memory width (derived)
|
||||||
|
parameter FILENAME = "NONE" // Simulus hexfile for $readmemh
|
||||||
)
|
)
|
||||||
(
|
(
|
||||||
//Asynchronous Stimulus Reset
|
// External stimulus load port
|
||||||
input nreset,
|
input nreset, // async reset
|
||||||
input ext_start, // Start driving stimulus
|
input ext_start, // Start driving stimulus
|
||||||
input use_timestamps,//b1-7 used for timestamps
|
|
||||||
input ignore_valid,//b0 valid bit ignored
|
|
||||||
//External Load port
|
|
||||||
input ext_clk,// External clock for write path
|
input ext_clk,// External clock for write path
|
||||||
input ext_access, // Valid packet for memory
|
input ext_access, // Valid packet for memory
|
||||||
input [DW-1:0] ext_packet, // Packet for memory
|
input [MW-1:0] ext_packet, // Packet for memory
|
||||||
//DUT Drive port
|
// DUT drive port
|
||||||
input dut_clk, // DUT side clock
|
input dut_clk, // DUT side clock
|
||||||
input dut_wait, // DUT stall signal
|
input dut_ready, // DUT ready signal
|
||||||
output stim_access, // Access signal
|
output stim_valid, // Packet valid
|
||||||
output [DW-1:0] stim_packet, // Packet
|
output [DW-1:0] stim_packet, // Packet data
|
||||||
output stim_done // Stimulus program done
|
output stim_done // Signals that stimulus is done
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam MD = 1<<MAW; // Memory depth
|
// memory parameters
|
||||||
|
parameter MAW = $clog2(DEPTH); // Memory address width
|
||||||
|
|
||||||
//Registers
|
// state machine parameters
|
||||||
reg [DW-1:0] ram[0:MD-1];
|
localparam STIM_IDLE = 2'b00;
|
||||||
|
localparam STIM_ACTIVE = 2'b01;
|
||||||
|
localparam STIM_PAUSE = 2'b10;
|
||||||
|
localparam STIM_DONE = 2'b11;
|
||||||
|
|
||||||
|
// Local values
|
||||||
|
reg [MW-1:0] ram[0:DEPTH-1];
|
||||||
reg [1:0] rd_state;
|
reg [1:0] rd_state;
|
||||||
reg [MAW-1:0] wr_addr;
|
reg [MAW-1:0] wr_addr;
|
||||||
reg [MAW-1:0] rd_addr;
|
reg [MAW-1:0] rd_addr;
|
||||||
reg [255:0] memhfile;
|
|
||||||
reg [1:0] sync_pipe;
|
reg [1:0] sync_pipe;
|
||||||
reg [6:0] rd_delay;
|
reg mem_read;
|
||||||
reg [DW-1:0] stim_packet;
|
reg [MW-1:0] mem_data;
|
||||||
reg stim_read;
|
reg [CW:0] rd_delay;
|
||||||
|
wire dut_start;
|
||||||
|
wire valid_packet;
|
||||||
|
|
||||||
//#################################
|
//#################################
|
||||||
// Init memory if configured
|
// Init memory if configured
|
||||||
//#################################
|
//#################################
|
||||||
generate
|
generate
|
||||||
if(!(HEXFILE=="NONE"))
|
if(!(FILENAME=="NONE"))
|
||||||
initial
|
initial
|
||||||
begin
|
begin
|
||||||
$display("Initializing STIMULUS from %s", HEXFILE);
|
$display("Driving stimulus from %s", FILENAME);
|
||||||
$readmemh(HEXFILE, ram);
|
$readmemh(FILENAME, ram);
|
||||||
end
|
end
|
||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
@ -72,52 +75,48 @@ module stimulus #( parameter DW = 32, // Memory width=DW+
|
|||||||
//Synchronize ext_start to dut_clk domain
|
//Synchronize ext_start to dut_clk domain
|
||||||
always @ (posedge dut_clk or negedge nreset)
|
always @ (posedge dut_clk or negedge nreset)
|
||||||
if(!nreset)
|
if(!nreset)
|
||||||
sync_pipe[1:0] <= 1'b0;
|
sync_pipe[1:0] <= 'b0;
|
||||||
else
|
else
|
||||||
sync_pipe[1:0] <= {sync_pipe[0],ext_start};
|
sync_pipe[1:0] <= {sync_pipe[0],ext_start};
|
||||||
|
|
||||||
assign dut_start = sync_pipe[1];
|
assign dut_start = sync_pipe[1];
|
||||||
|
|
||||||
//#################################
|
//#################################
|
||||||
// Read port state machine
|
// Read port state machine
|
||||||
//#################################
|
//#################################
|
||||||
//1. Start on dut_start
|
//1. Start on dut_start
|
||||||
//2. After thar update rd state machine on all not stall and not wait
|
//2. Drive stimulus while dut is ready
|
||||||
//3. Set end state on special end packet
|
//3. Set end state on special end packet (bit 0)
|
||||||
|
|
||||||
`define STIM_IDLE 2'b00
|
|
||||||
`define STIM_ACTIVE 2'b01
|
|
||||||
`define STIM_PAUSE 2'b10
|
|
||||||
`define STIM_DONE 2'b11
|
|
||||||
|
|
||||||
always @ (posedge dut_clk or negedge nreset)
|
always @ (posedge dut_clk or negedge nreset)
|
||||||
if(!nreset)
|
if(!nreset)
|
||||||
begin
|
begin
|
||||||
rd_state[1:0] <= `STIM_IDLE;
|
rd_state[1:0] <= STIM_IDLE;
|
||||||
rd_addr[MAW-1:0] <= 'b0;
|
rd_addr[MAW-1:0] <= 'b0;
|
||||||
rd_delay[6:0] <= 'b0;
|
rd_delay <= 'b0;
|
||||||
end
|
end
|
||||||
else if(~dut_wait)
|
else if(dut_ready)
|
||||||
case (rd_state[1:0])
|
case (rd_state[1:0])
|
||||||
`STIM_IDLE :
|
STIM_IDLE :
|
||||||
rd_state[1:0] <= dut_start ? `STIM_ACTIVE : `STIM_IDLE;
|
rd_state[1:0] <= dut_start ? STIM_ACTIVE : STIM_IDLE;
|
||||||
`STIM_ACTIVE :
|
STIM_ACTIVE :
|
||||||
begin
|
begin
|
||||||
rd_state[1:0] <= (|rd_delay[6:0]) ? `STIM_PAUSE :
|
rd_state[1:0] <= (|rd_delay) ? STIM_PAUSE :
|
||||||
~stim_valid ? `STIM_DONE :
|
~stim_valid ? STIM_DONE :
|
||||||
`STIM_ACTIVE;
|
STIM_ACTIVE;
|
||||||
rd_addr[MAW-1:0] <= rd_addr[MAW-1:0] + 1'b1;
|
rd_addr[MAW-1:0] <= rd_addr[MAW-1:0] + 1'b1;
|
||||||
rd_delay[6:0] <= {(7){use_timestamps}} & stim_packet[7:1];
|
rd_delay <= (CW > 1) ? mem_data[CW:1] : 'b0;
|
||||||
end
|
end
|
||||||
`STIM_PAUSE :
|
STIM_PAUSE :
|
||||||
begin
|
begin
|
||||||
rd_state[1:0] <= (|rd_delay[6:0]) ? `STIM_PAUSE : `STIM_ACTIVE;
|
rd_state[1:0] <= (|rd_delay) ? STIM_PAUSE : STIM_ACTIVE;
|
||||||
rd_delay[6:0] <= rd_delay[6:0] - 1'b1;
|
rd_delay <= rd_delay - 1'b1;
|
||||||
end
|
end
|
||||||
endcase // case (rd_state[1:0])
|
endcase // case (rd_state[1:0])
|
||||||
|
|
||||||
//Output Driver
|
//Output Driver
|
||||||
assign stim_done = (rd_state[1:0] == `STIM_DONE);
|
assign stim_done = (rd_state[1:0] == STIM_DONE);
|
||||||
assign stim_valid = ignore_valid | stim_packet[0];
|
assign valid_packet = (CW==0) | mem_data[0];
|
||||||
|
|
||||||
//#################################
|
//#################################
|
||||||
// RAM
|
// RAM
|
||||||
@ -126,18 +125,17 @@ module stimulus #( parameter DW = 32, // Memory width=DW+
|
|||||||
//write port
|
//write port
|
||||||
always @(posedge ext_clk)
|
always @(posedge ext_clk)
|
||||||
if(ext_access)
|
if(ext_access)
|
||||||
ram[wr_addr[MAW-1:0]] <= ext_packet[DW-1:0];
|
ram[wr_addr[MAW-1:0]] <= ext_packet[MW-1:0];
|
||||||
|
|
||||||
//read port
|
//read port
|
||||||
always @ (posedge dut_clk)
|
always @ (posedge dut_clk)
|
||||||
begin
|
begin
|
||||||
stim_packet[DW-1:0] <= ram[rd_addr[MAW-1:0]];
|
mem_data[MW-1:0] <= ram[rd_addr[MAW-1:0]];
|
||||||
stim_read <= (rd_state==`STIM_ACTIVE); //mem-cycle adjust
|
mem_read <= (rd_state==STIM_ACTIVE); //mem-cycle adjust
|
||||||
end
|
end
|
||||||
|
|
||||||
//Shut off access immediately, but pipeline delay by one cycle
|
//Shut off access immediately, but pipeline delay by one cycle
|
||||||
assign stim_access = stim_valid & stim_read & ~stim_done;
|
assign stim_valid = valid_packet & mem_read & ~stim_done;
|
||||||
|
assign stim_packet[DW-1:0] = mem_data[MW-1:CW];
|
||||||
|
|
||||||
endmodule // stimulus
|
endmodule // stimulus
|
||||||
|
|
||||||
|
|
||||||
|
52
src/stdlib/dv/tb_oh_stimulus.v
Normal file
52
src/stdlib/dv/tb_oh_stimulus.v
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
module testbench();
|
||||||
|
|
||||||
|
localparam DW = 144;
|
||||||
|
localparam CW = 8;
|
||||||
|
localparam FILENAME = "test.mem"; //
|
||||||
|
|
||||||
|
/*AUTOINPUT*/
|
||||||
|
/*AUTOWIRE*/
|
||||||
|
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
||||||
|
wire nreset; // From oh_simctrl of oh_simctrl.v
|
||||||
|
wire start; // From oh_simctrl of oh_simctrl.v
|
||||||
|
wire stim_done; // From oh_stimulus of oh_stimulus.v
|
||||||
|
wire [DW-1:0] stim_packet; // From oh_stimulus of oh_stimulus.v
|
||||||
|
wire stim_valid; // From oh_stimulus of oh_stimulus.v
|
||||||
|
wire vdd; // From oh_simctrl of oh_simctrl.v
|
||||||
|
wire vss; // From oh_simctrl of oh_simctrl.v
|
||||||
|
// End of automatics
|
||||||
|
|
||||||
|
oh_stimulus #(.DW(DW),
|
||||||
|
.CW(CW),
|
||||||
|
.FILENAME(FILENAME))
|
||||||
|
oh_stimulus(.dut_ready (1'b1),
|
||||||
|
.dut_clk (dut_clk),
|
||||||
|
.ext_valid (1'b0),
|
||||||
|
.ext_packet ({(DW + CW){1'b0}}),
|
||||||
|
.ext_clk (ext_clk),
|
||||||
|
.ext_start (start),
|
||||||
|
/*AUTOINST*/
|
||||||
|
// Outputs
|
||||||
|
.stim_valid (stim_valid),
|
||||||
|
.stim_packet (stim_packet[DW-1:0]),
|
||||||
|
.stim_done (stim_done),
|
||||||
|
// Inputs
|
||||||
|
.nreset (nreset));
|
||||||
|
|
||||||
|
oh_simctrl oh_simctrl(.stim_done (1'b0),
|
||||||
|
.test_done (1'b1),
|
||||||
|
.test_diff (1'b0),
|
||||||
|
.dut_active (1'b1),
|
||||||
|
.clk1 (ext_clk),
|
||||||
|
.clk2 (dut_clk),
|
||||||
|
/*AUTOINST*/
|
||||||
|
// Outputs
|
||||||
|
.nreset (nreset),
|
||||||
|
.start (start),
|
||||||
|
.vdd (vdd),
|
||||||
|
.vss (vss));
|
||||||
|
|
||||||
|
endmodule // tb
|
||||||
|
// Local Variables:
|
||||||
|
// verilog-library-directories:("." "../hdl")
|
||||||
|
// End:
|
Loading…
x
Reference in New Issue
Block a user