📄 ssramcon_sim.v
字号:
/*********************************************************/
// MODULE: SSRAM Controller simulation
//
// FILE NAME: ssramcon_sim.v
// VERSION: 1.0
// DATE: January 1, 1999
// AUTHOR: Bob Zeidman, Zeidman Consulting
//
// CODE TYPE: Simulation
//
// DESCRIPTION: This module provides stimuli for simulating
// an SSRAM memory controller. It uses an SSRAM model and
// performs a number of writes and reads to the model,
// including back-to-back reads and writes. It also checks
// the reset function.
//
/*********************************************************/
// DEFINES
`define DEL 1 // Clock-to-output delay. Zero
// time delays can be confusing
// and sometimes cause problems.
`define WAIT 2 // Number of wait cycles needed
// Flow-through SSRAMs require
// 1 wait cycles
// Pipelined SSRAMs require
// 2 wait cycle
`define DWIDTH 8 // Data bus width
`define ADEPTH 256 // Memory depth
`define AWIDTH 8 // Number of bits needed to
// address memory
`define CYCLE_TIME 100 // System clock cycle time
// TOP MODULE
module ssramcon_sim();
// INPUTS
// OUTPUTS
// INOUTS
// SIGNAL DECLARATIONS
reg clock;
reg reset;
reg as;
reg we;
reg oe;
reg ce;
reg cs;
wire ack;
reg [`DWIDTH-1:0] data_out; // Data written by processor
reg [`DWIDTH-1:0] data_exp; // Data expected to be read
// from memory
wire [`DWIDTH-1:0] data; // Data bus
reg [`AWIDTH-1:0] address; // Address bus
reg [`AWIDTH-1:0] addr_count; // Address counter
reg [`DWIDTH-1:0] data_patt; // Data pattern holder
reg [`WAIT-1:0] as_shift; // Shift register for as
reg [`WAIT-1:0] we_shift; // Shift register for we
integer fin_flag; // Tells the simulation
// when we're finished
// PARAMETERS
// ASSIGN STATEMENTS
// The data bus direction is determined by the address
// strobe and write enable signals from previous cycles.
assign data = (as_shift[`WAIT-1] & we_shift[`WAIT-1]) ?
data_out : 8'hzz;
// MAIN CODE
// Instantiate the controller
ssram_control Ssram_control(
.clock(clock),
.reset(reset),
.as(as),
.ack(ack));
// Instantiate an SSRAM
ssram Ssram(
.clock(clock),
.oe(oe),
.we(we),
.ce(ce),
.cs(cs),
.address(address),
.data(data));
// Generate the clock
always #(`CYCLE_TIME/2) clock = ~clock;
// Simulate
initial begin
// Initialize inputs
clock = 1;
reset = 0;
as_shift = 0;
we_shift = 0;
as = 0;
cs = 1;
oe = 1;
ce = 1;
// Test the reset signal
#`DEL;
// Assert the reset signal
reset = 1;
// Wait for the outputs to change asynchronously
#`DEL
#`DEL
// Test outputs
if (ack === 1'b0)
$display ("Reset is working");
else begin
$display("\nERROR at time %0t:", $time);
$display("Reset is not working");
$display(" ack = %b\n", ack);
// Use $stop for debugging
$stop;
end
// Deassert the reset signal
reset = 0;
// Initialize the address counter
addr_count = 0;
// Initialize the data pattern to be written
data_patt = `DWIDTH'h1;
// Write a series of values to memory
while (&addr_count === 1'b0) begin
// Write to memory
writemem(addr_count, data_patt);
// Increment the address counter
addr_count = addr_count + 1;
// Shift the data pattern
data_patt <= (data_patt << 1);
data_patt[0] <= data_patt[`DWIDTH-1];
// Wait for the data pattern to change
#`DEL;
end
// Write once more to memory
writemem(addr_count, data_patt);
// Wait for the access to complete
#`DEL;
// Initialize the address counter
addr_count = 0;
// Initialize the data pattern to be read
data_patt = `DWIDTH'h1;
// Verify the values that were written
while (&addr_count === 1'b0) begin
// Read from memory
readmem(addr_count, data_patt);
// Increment the address counter
addr_count = addr_count + 1;
// Shift the data pattern
data_patt <= (data_patt << 1);
data_patt[0] <= data_patt[`DWIDTH-1];
// Wait for the data pattern to change
#`DEL;
end
// Read once more from memory
readmem(addr_count, data_patt);
// Set the finish flag
fin_flag = `WAIT;
// Turn off chip select
@(posedge clock);
cs <= #`DEL 0;
end
// Shift the address strobe and write enable signals
// so that we can use them after the appropriate cycle
// delay
always @(posedge clock) begin
// Shift the address strobe signal into
// the address strobe shift register
as_shift <= #`DEL as_shift << 1;
as_shift[0] <= #`DEL as;
// Shift the write enable signal into
// the write enable shift register
we_shift <= #`DEL we_shift << 1;
we_shift[0] <= #`DEL we;
// Look for an acknowledge during the correct cycle
if (as_shift[`WAIT-1] & ~ack) begin
$display("\nERROR at time %0t:", $time);
$display("Did not receive the expected acknowledge\n");
// Use $stop for debugging
$stop;
end
else if (~as_shift[`WAIT-1] & ack) begin
$display("\nERROR at time %0t:", $time);
$display("Received an unexpected acknowledge\n");
// Use $stop for debugging
$stop;
end
end
// Perform any necessary signal checking
always @(data_exp) begin
// Did we find the expected data?
if (data !== data_exp) begin
$display("\nERROR at time %0t:", $time);
$display("Controller is not working");
$display(" data written = %h", data_exp);
$display(" data read = %h\n", data);
// Use $stop for debugging
$stop;
end
// Are we done checking all reads?
if (fin_flag === 0) begin
$display("\nSimulation complete - no errors\n");
$finish;
end
fin_flag = fin_flag - 1;
end
// TASKS
// Write data to memory
task writemem;
// INPUTS
input [`AWIDTH-1:0] write_addr; // Memory address
input [`DWIDTH-1:0] write_data; // Data to write to memory
// OUTPUTS
// INOUTS
// TASK CODE
begin
// Wait for the rising clock edge
@(posedge clock);
we <= #`DEL 1; // Set up a write access
as <= #`DEL 1; // Assert address strobe
address <= #`DEL write_addr; // Set up the address
// Set up the data to change
// at the correct cycle
data_out <= #(`CYCLE_TIME * `WAIT + `DEL) write_data;
end
endtask // writemem
// Read data from memory and check its value
task readmem;
// INPUTS
input [`AWIDTH-1:0] read_addr; // Memory address
input [`DWIDTH-1:0] read_data; // Expected read data
// OUTPUTS
// INOUTS
// TASK CODE
begin
// Wait for the rising clock edge
@(posedge clock);
we <= #`DEL 0; // Set up a read access
as <= #`DEL 1; // Assert address strobe
address <= #`DEL read_addr; // Set up the address
// Set up the expected data
data_exp <= #(`CYCLE_TIME * `WAIT + 2*`DEL) read_data;
end
endtask // readmem
endmodule // ssramcon_sim
// SUBMODULE
// SSRAM memory model
module ssram(
clock,
data,
address,
oe,
ce,
cs,
we);
// INPUTS
input clock; // Clock
input [`AWIDTH-1:0] address; // Memory address
input oe; // Output enable
input we; // Write enable
input ce; // Clock enable
input cs; // Chip select
// OUTPUTS
// INOUTS
inout [`DWIDTH-1:0] data; // Data lines
// SIGNAL DECLARATIONS
wire clock;
wire [`AWIDTH-1:0] address;
wire oe;
wire we;
wire ce;
wire cs;
wire [`DWIDTH-1:0] data;
reg [`DWIDTH-1:0] mem[`ADEPTH-1:0]; // Stored data
// Shift register for storing addresses
// for pipelined accesses
reg [`AWIDTH-1:0] addr_shift[`WAIT-1:0];
// Shift register for storing write enable
// for pipelined accesses
reg [`WAIT-1:0] we_shift;
// Shift register for storing chip selecte
// for pipelined accesses
reg [`WAIT-1:0] cs_shift;
reg i; // Temporary variable
// PARAMETERS
// ASSIGN STATEMENTS
// Output the data if the SSRAM is enabled, the clock is
// enabled, oe is asserted, and the current access is a read
assign data = ce & oe & cs_shift[`WAIT-1] &
~we_shift[`WAIT-1] ? mem[addr_shift[`WAIT-1]] : 8'hzz;
// MAIN CODE
// Initialize chip select shift register
initial begin
cs_shift = 0;
end
// Look at the rising edge of clock
always @(posedge clock) begin
// Don't do anything unless the clock is enabled
if (ce) begin
// Store the address and control signals
// in their respective shift registers and shift them
cs_shift <= #`DEL cs_shift << 1;
cs_shift[0] <= #`DEL cs;
we_shift <= #`DEL we_shift << 1;
we_shift[0] <= #`DEL we;
for (i = `WAIT-1; i > 0; i = i - 1) begin
addr_shift[i] <= #`DEL addr_shift[i-1];
end
addr_shift[0] <= #`DEL address;
// If there is a chip select and write enable,
// write the data
if (cs_shift[`WAIT-1] & we_shift[`WAIT-1]) begin
mem[addr_shift[`WAIT-1]] <= #`DEL data;
end
end
end
endmodule // sram
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -