0% found this document useful (0 votes)
6 views8 pages

SRAM Controller and Testbench Code

The document describes a Verilog implementation of a memory controller system, including a synchronous RAM controller, SRAM bank, and a test bench for validating operations. The memory controller manages read and write operations to multiple SRAM banks based on input signals, while the test bench verifies functionality through various test cases. The design includes state management for operations and a detailed simulation environment for testing memory interactions.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views8 pages

SRAM Controller and Testbench Code

The document describes a Verilog implementation of a memory controller system, including a synchronous RAM controller, SRAM bank, and a test bench for validating operations. The memory controller manages read and write operations to multiple SRAM banks based on input signals, while the test bench verifies functionality through various test cases. The design includes state management for operations and a detailed simulation environment for testing memory interactions.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

`timescale 1ns / 1ps

//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 21.10.2025 12:14:25
// Design Name:
// Module Name: memory
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////

module s_ram_controller(input clk,


input rst,
input start, // chip select
input write_enable,
input [1:0] bank_select,
input [7:0] address,
input [31:0] write_data,
output reg done,
output reg [31:0] read_data,

// Interface to SRAM bank


output reg in_CS,
output reg in_write_en,
output reg [1:0] in_bank_select,
output reg [7:0] in_bram_add,
//output reg [7:0] in_sram_col,
output reg [31:0] in_sram_write_data,
input [31:0] out_sram_read_data
);

localparam IDLE = 3'b000,


WRITE = 3'b001,
READ = 3'b010,
WAIT = 3'b011,
DONE = 3'b100;

reg [2:0] current_state, next_state;

always @(posedge clk or posedge rst) begin


if (rst)
current_state <= IDLE;
else
current_state <= next_state;
end

always @(*) begin


case (current_state)
IDLE: begin
if (start) begin
if (write_enable)
next_state = WRITE;
else
next_state = READ;
end else
next_state = IDLE;
end
WRITE: next_state = WAIT;
READ: next_state = WAIT;
WAIT: next_state = DONE;
DONE: next_state = IDLE;
default: next_state = IDLE;
endcase
end

// Output Control
always @(posedge clk or posedge rst) begin
if (rst) begin
in_CS <= 1'b1;
in_write_en <= 1'b0;
in_bank_select <= 2'b00;
in_bram_add <= 14'b0;
// in_sram_col <= 9'b0;
in_sram_write_data <= 32'b0;
read_data <= 32'b0;
done <= 1'b0;
end else begin
case (current_state)
IDLE: begin
in_CS <= 1'b1;
done <= 1'b0;
end
WRITE: begin
in_CS <= 1'b0;
in_write_en <= 1'b1;
in_bank_select <= bank_select;
in_bram_add <= address;
// in_sram_col <= col_address;
in_sram_write_data <= write_data;
end
READ: begin
in_CS <= 1'b0;
in_write_en <= 1'b0;
in_bank_select <= bank_select;
in_bram_add <= address;
//in_sram_col <= col_address;
end
WAIT: begin
in_CS <= 1'b1; // deactivate chip select
if (!write_enable)
read_data <= out_sram_read_data;
end
DONE: begin
done <= 1'b1;
end
endcase
end
end

endmodule

module s_ram_bank(
// SRAM MODEL INTERFACE
input in_CLK,
input in_CS, // CHIP SELECT
input in_write_en, // Write Enable
input [1:0] in_bank_select, // Bank Selection
input [7:0] in_sram_row, // Row Address
input [31:0] in_sram_write_data,

output reg [31:0] out_sram_read_data // Read Data Output


);

reg [3:0] we;


always @(*) begin
we = 4'b0000; // Initialize all write enables to 0
if (in_bank_select == 2'b00) begin
we[0] = 1;
end
else if (in_bank_select == 2'b01) begin
we[1] = 1;
end
else if (in_bank_select == 2'b10) begin
we[2] = 1;
end
else if (in_bank_select == 2'b11) begin
we[3] = 1;
end
end

wire [31:0] bank_read_data [0:3];

genvar i;
generate
for (i = 0; i < 4; i = i + 1) begin : bank_gen
b_ram bank_inst (
.in_CLK(in_CLK),
.in_CS(in_CS & we[i]), // Combine chip select with bank write enable
.in_write_en(in_write_en),
.in_bram_add(in_sram_row), // Using row address as BRAM address
.in_sram_write_data(in_sram_write_data),
.out_sram_read_data(bank_read_data[i])
);
end
endgenerate

// Output multiplexer based on bank selection


always @(*) begin
case (in_bank_select)
2'b00: out_sram_read_data = bank_read_data[0];
2'b01: out_sram_read_data = bank_read_data[1];
2'b10: out_sram_read_data = bank_read_data[2];
2'b11: out_sram_read_data = bank_read_data[3];
default: out_sram_read_data = 32'b0;
endcase
end

endmodule

module b_ram(
// SRAM MODEL INTERFACE
input in_CLK,
input in_CS, // CHIP SELECT
input in_write_en, // Write Enable
input [7:0] in_bram_add, // Row Address
input [31:0] in_sram_write_data,
output reg [31:0] out_sram_read_data // Read Data Output
);

parameter DATA = 32;


parameter addr = 8;

(* ram_style = "block" *) reg [DATA-1:0] mem [(2**addr)-1:0];

always @(posedge in_CLK) begin


if (!in_CS) begin
if (in_write_en) begin
mem[in_bram_add] <= in_sram_write_data;
end
end else begin
out_sram_read_data <= mem[in_bram_add];
end
end

endmodule

`timescale 1ns / 1ps

module top_memory(
input clk,
input rst,
input start, // chip select
input write_enable,
input [1:0] bank_select,
input [7:0] address,
input [31:0] write_data,
output done,
output [31:0] read_data
);

// Internal wires between controller and SRAM bank


wire in_CS;
wire in_write_en;
wire [1:0] in_bank_select;
wire [7:0] in_bram_add;
wire [31:0] in_sram_write_data;
wire [31:0] out_sram_read_data;

// Instantiate SRAM Controller


s_ram_controller controller_inst (
.clk(clk),
.rst(rst),
.start(start),
.write_enable(write_enable),
.bank_select(bank_select),
.address(address),
.write_data(write_data),
.done(done),
.read_data(read_data),

// Interface to SRAM bank


.in_CS(in_CS),
.in_write_en(in_write_en),
.in_bank_select(in_bank_select),
.in_bram_add(in_bram_add),
.in_sram_write_data(in_sram_write_data),
.out_sram_read_data(out_sram_read_data)
);

// Instantiate SRAM Bank


s_ram_bank sram_bank_inst (
.in_CLK(clk),
.in_CS(in_CS),
.in_write_en(in_write_en),
.in_bank_select(in_bank_select),
.in_sram_row(in_bram_add), // Connect row address
.in_sram_write_data(in_sram_write_data),
.out_sram_read_data(out_sram_read_data)
);

endmodule

TEST BENCH
timescale 1ns / 1ps

module tb_top_memory();
reg clk;
reg rst;
reg start;
reg write_enable;
reg [1:0] bank_select;
reg [7:0] address;
reg [31:0] write_data;
wire done;
wire [31:0] read_data;

// Instantiate the top module


top_memory uut (
.clk(clk),
.rst(rst),
.start(start),
.write_enable(write_enable),
.bank_select(bank_select),
.address(address),
.write_data(write_data),
.done(done),
.read_data(read_data)
);

// Clock generation
always #5 clk = ~clk;

// Test data patterns


reg [31:0] test_data [0:15];
integer i;

initial begin
// Initialize test data
for (i = 0; i < 16; i = i + 1) begin
test_data[i] = 32'h12345678 + i * 32'h11111111;
end

// Initialize signals
clk = 0;
rst = 1;
start = 0;
write_enable = 0;
bank_select = 2'b00;
address = 8'h00;
write_data = 32'h00000000;

// Apply reset
#20;
rst = 0;
#20;

$display("=== Starting Memory System Testbench ===");


$display("Time\tOperation\tBank\tAddress\tData");
$display("------------------------------------------------");

// Test 1: Write to all banks


$display("\n=== Test 1: Writing to all banks ===");
for (i = 0; i < 4; i = i + 1) begin
write_to_memory(i, i * 16, test_data[i]);
#50;
end

// Test 2: Read from all banks


$display("\n=== Test 2: Reading from all banks ===");
for (i = 0; i < 4; i = i + 1) begin
read_from_memory(i, i * 16);
#50;
end

// Test 3: Write multiple addresses in same bank


$display("\n=== Test 3: Multiple writes to Bank 0 ===");
for (i = 0; i < 4; i = i + 1) begin
write_to_memory(2'b00, i, test_data[i + 4]);
#50;
end

// Test 4: Read multiple addresses from same bank


$display("\n=== Test 4: Multiple reads from Bank 0 ===");
for (i = 0; i < 4; i = i + 1) begin
read_from_memory(2'b00, i);
#50;
end

// Test 5: Write to high addresses


$display("\n=== Test 5: Writing to high addresses ===");
write_to_memory(2'b11, 8'hFF, 32'hDEADBEEF);
#50;
read_from_memory(2'b11, 8'hFF);
#50;

// Test 6: Back-to-back operations


$display("\n=== Test 6: Back-to-back operations ===");
write_to_memory(2'b01, 8'h10, 32'hCAFEBABE);
wait_for_done();
read_from_memory(2'b01, 8'h10);
wait_for_done();
write_to_memory(2'b10, 8'h20, 32'hFACEB00C);
wait_for_done();

// Test 7: Verify data integrity across banks


$display("\n=== Test 7: Data integrity check ===");
for (i = 0; i < 4; i = i + 1) begin
read_from_memory(i, i * 16);
#50;
if (read_data === test_data[i]) begin
$display("✓ Bank %0d data verified correctly", i);
end else begin
$display("✗ Bank %0d data mismatch! Expected: %h, Got: %h",
i, test_data[i], read_data);
end
end

#100;
$display("\n=== Testbench Complete ===");
$finish;
end

// Task for write operation


task write_to_memory;
input [1:0] bank;
input [7:0] addr;
input [31:0] data;
begin
@(posedge clk);
write_enable = 1;
bank_select = bank;
address = addr;
write_data = data;
start = 1;

@(posedge clk);
start = 0;

wait_for_done();

$display("%0t\tWRITE\t\t%0d\t%h\t%h", $time, bank, addr, data);


end
endtask

// Task for read operation


task read_from_memory;
input [1:0] bank;
input [7:0] addr;
begin
@(posedge clk);
write_enable = 0;
bank_select = bank;
address = addr;
start = 1;

@(posedge clk);
start = 0;

wait_for_done();

$display("%0t\tREAD\t\t%0d\t%h\t%h", $time, bank, addr, read_data);


end
endtask

// Task to wait for done signal


task wait_for_done;
begin
wait(done == 1);
@(posedge clk);
#1; // Small delay for signal stabilization
end
endtask

// Monitor to track all operations


always @(posedge clk) begin
if (done) begin
if (write_enable) begin
$display("%0t\tWRITE DONE\t%0d\t%h\t%h",
$time, bank_select, address, write_data);
end else begin
$display("%0t\tREAD DONE\t%0d\t%h\t%h",
$time, bank_select, address, read_data);
end
end
end

endmodule

You might also like