⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sramcon_sim.v

📁 各种基本单元的verilog模块.对初学者很有帮助的.
💻 V
字号:
/*********************************************************/
// MODULE:		SRAM/ROM Controller simulation
//
// FILE NAME:	sramcon_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 SRAM/ROM memory controller. It uses an SRAM 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 WR_COUNT 1		// Number of write cycles needed
`define RD_COUNT 4		// Number of read cycles needed
`define CLK_HPERIOD 50	// Clock half period
						// Clock period
`define CLK_PERIOD CLK_HPERIOD*2
`define WR_PERIOD 70	// Write access time of memory
						// Should be between
						// (WR_COUNT-1)*CLK_PERIOD and
						// WR_COUNT*CLK_PERIOD
`define RD_PERIOD 350	// Read access time of memory
						// (RD_COUNT-1)*CLK_PERIOD and
						// RD_COUNT*CLK_PERIOD
`define DWIDTH 8		// Data bus width
`define ADEPTH 256		// Memory depth
`define AWIDTH 8		// Number of bits needed to
						// address memory 

// TOP MODULE
module sramcon_sim();

// INPUTS

// OUTPUTS

// INOUTS

// SIGNAL DECLARATIONS
reg					clock;
reg					reset;
reg					as;
reg					rw;			
wire				out_en;
wire				write_en;
wire				ack;

reg  [`DWIDTH-1:0]	data_out;	// Data out of processor
wire [`DWIDTH-1:0]	data;		// Data bus
reg  [`AWIDTH-1:0]	address;	// Address bus

integer				cyc_count;	// Count cycles to determine
								// if the access has taken
								// too long
reg	 [`AWIDTH:0]	addr_count; // Address counter
reg  [`DWIDTH-1:0]	data_patt;	// Data pattern holder

// PARAMETERS

// ASSIGN STATEMENTS
assign data = (as & rw) ? 8'hzz : data_out;

// MAIN CODE

// Instantiate the controller
sram_control Sram_control(
		.clock(clock),
		.reset_n(~reset),
		.as_n(~as),
		.rw(rw),
		.out_en(out_en),
		.write_en(write_en),
		.ack(ack));

// Instantiate an SRAM
sram Sram(
		.rd(out_en),
		.wr(write_en),
		.address(address),
		.data(data));

// Generate the clock
always #`CLK_HPERIOD clock = ~clock;

// Simulate
initial begin
	// Initialize inputs
	clock = 1;
	reset = 0;
	as = 0;

	// Test the reset signal
	#`DEL;
	// Assert the reset signal
	reset = 1;

	// Wait for the outputs to change asynchronously
	#`DEL
	#`DEL
	// Test outputs
	if ((out_en === 1'b0) && (write_en === 1'b0) &&
		(ack === 1'b0))
		$display ("Reset is working");
	else begin
		$display("\nERROR at time %0t:", $time);
		$display("Reset is not working");
		$display("    out_en   = %b", out_en);
		$display("    write_en = %b", write_en);
		$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[`AWIDTH] === 0) begin
		// Write to memory
		writemem(addr_count[`AWIDTH-1:0], 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

	// 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[`AWIDTH] === 0) begin 
		// Read from memory
		readmem(addr_count[`AWIDTH-1:0], 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

	$display("\nSimulation complete - no errors\n");
	$finish;
end

// Check the number of cycles for each access
always @(posedge clock) begin
	// Check whether an access is taking too long
	if (cyc_count > (`RD_COUNT + `WR_COUNT)) begin
		$display("\nERROR at time %0t:", $time);
		if (rw)
			$display("Read access took to long\n");
		else
			$display("Write access took to long\n");

		// Use $stop for debugging
		$stop;
	end
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
	cyc_count = 0;		// Initialize the cycle count

	// Wait for the rising clock edge
	@(posedge clock);
	rw <= 0;				// Set up a write access
	as <= 1;				// Assert address strobe
	address <= write_addr;	// Set up the address
	data_out <= write_data;	// Set up the data

	// Wait for the acknowledge
	@(posedge clock);
	while (~ack) begin
		// Increment the cycle count
		cyc_count = cyc_count + 1;

		@(posedge clock);
	end

	as <= 0;			// Deassert address strobe
	@(posedge clock);	// Wait one clock cycle

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]	expected;		// Expected read data

// OUTPUTS

// INOUTS

// TASK CODE
begin
	cyc_count = 0;		// Initialize the cycle count

	// Wait for the rising clock edge
	@(posedge clock);
	rw <= 1;				// Set up a read access
	as <= 1;				// Assert address strobe
	address <= read_addr;	// Set up the address

	// Wait for the acknowledge
	@(posedge clock);
	while (~ack) begin
		// Increment the cycle count
		cyc_count = cyc_count + 1;

		@(posedge clock);
	end

	// Did we find the expected data?
	if (data !== expected) begin
		$display("\nERROR at time %0t:", $time);
		$display("Controller is not working");
		$display("    data written = %h", expected);
		$display("    data read    = %h\n", data);

		// Use $stop for debugging
		$stop;
	end

	as <= 0;			// Deassert address strobe
	@(posedge clock);	// Wait one clock cycle

end
endtask		// readmem

endmodule			// sramcon_sim

// SUBMODULE
// SRAM memory model
module sram(
		data,
		address,
		rd,
		wr);

// INPUTS
input [`AWIDTH-1:0]	address;	// Memory address
input				rd;		  	// Read input
input	   			wr;		  	// Write input

// OUTPUTS

// INOUTS
inout [`DWIDTH-1:0]	data;	  	// Data lines

// SIGNAL DECLARATIONS
wire [`AWIDTH-1:0]	address;
wire				rd;
wire				wr;
wire [`DWIDTH-1:0]	data;
reg  [`DWIDTH-1:0]	mem[`ADEPTH-1:0];  	// Stored data

time		rd_time;	// Time of the most recent change
						// of the rd inputwire [63:0]	rd_dtime;  	// rd_time delayed by `RD_PERIOD
					   	// time units

time		wr_time;	// Time of the most recent change
						// of the wr inputwire [63:0]	wr_dtime;  	// wr_time delayed by `WD_PERIOD
					   	// time units

reg			oe;		  	// Output enable - this signal is
						// asserted after the minimum rd
						// pulse time
reg			we;		  	// Write enable - this signal is
						// asserted after the minimum wr
						// pulse time

// PARAMETERS

// ASSIGN STATEMENTS
assign #`RD_PERIOD rd_dtime = rd_time;
assign #`WR_PERIOD wr_dtime = wr_time;

// Output the data if the rd signal is asserted
// and the oe is asserted, which means that
// we met the minimum rd pulse time
assign data = (oe & rd) ? mem[address] : 8'hzz;

// MAIN CODE
initial begin
   oe = 0;
   we = 0;
   wr_time = 0;
   rd_time = 0;
end

// Look for the beginning of the write access
always @(posedge wr) begin
	wr_time = $time;  		// Save the time of the most
						  	// recent rising edge of wr
	we = 0;
end

always @(wr_dtime) begin
	if (wr_time === wr_dtime) begin
		// If this is true, the last rising edge of wr
		// was exactly `WR_PERIOD time units ago, so
		// assert the write enable
		we = 1;
	end
end

// Look for the end of the write access
always @(negedge wr) begin
	if (we) begin
		// Write the data if the write enable is asserted
		// which means we met the minimum wr pulse time
		mem[address] <= data;
	end
	we = 0;			// Turn off the write enable
end

// Look for the beginning of the read access
always @(posedge rd) begin
	rd_time = $time;  		// Save the time of the most
						  	// recent rising edge of rd
	oe = 0;
end

always @(rd_dtime) begin
	if (rd_time === rd_dtime) begin
		// If this is true, the last rising edge of rd
		// was exactly `RD_PERIOD time units ago, so
		// assert the output enable
		oe = 1;
	end
end

// Look for the end of the read access
always @(negedge rd) begin
	oe = 0;			// Turn off the output enable
end
endmodule		// sram

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -