1
0
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:
aolofsson 2022-06-17 23:03:32 -04:00
parent f0d0750dae
commit 996d980059
2 changed files with 135 additions and 85 deletions

View File

@ -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

View 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: