Implementing a 256x8 RAM module with synchronous write and asynchronous read. Understanding memory design patterns in hardware.
The Memory DSL provides a declarative way to define RAM modules. Include RHDL::DSL::Memory to access memory, sync_write, and async_read.
class RAM256x8 < RHDL::Sim::Component
include RHDL::DSL::Memory
input :clk, :we # clock and write enable
input :addr, width: 8 # 8-bit address = 256 locations
input :din, width: 8 # 8-bit data input
output :dout, width: 8 # 8-bit data output
# Declare memory array: 256 entries x 8 bits
memory :mem, depth: 256, width: 8
# Write on rising clock edge when we=1
sync_write :mem,
clock: :clk, enable: :we,
addr: :addr, data: :din
# Read is combinational (no clock needed)
async_read :dout,
from: :mem, addr: :addr
end
module RAM256x8 (
input clk,
input we,
input [7:0] addr,
input [7:0] din,
output [7:0] dout
);
reg [7:0] mem [0:255];
assign dout = mem[addr];
always @(posedge clk) begin
if (we)
mem[addr] <= din;
end
endmodule
| Operation | Timing | Behavior |
|---|---|---|
| Async Read | Combinational | Output reflects mem[addr] immediately when addr changes |
| Sync Write | Posedge clk | When we=1, din is written to mem[addr] on rising edge |
| Read-During-Write | Same cycle | Read returns the old value (write-after-read semantics) |
Connect memory to a CPU by wiring address, data, and control signals with address decoding.
class MemorySystem < RHDL::Sim::Component
include RHDL::DSL::Memory
input :clk, :rst
input :cpu_addr, width: 16
input :cpu_data, width: 8
input :cpu_rw
output :data_out, width: 8
component :main_ram, RAM256x8
component :rom, ROM,
depth: 16384, width: 8
behavior do
is_rom = cpu_addr[15] & cpu_addr[14]
data_out <= mux(is_rom,
rom.dout, main_ram.dout)
end
end