Verilog Single-Port RAM Ontwerp: Uitgebreide Gids
Ontwerp
module single_port_sync_ram #(
parameter ADDR_WIDTH = 4,
parameter DATA_WIDTH = 32,
parameter DEPTH = 16
) (
input clk,
input [ADDR_WIDTH-1:0] addr,
inout [DATA_WIDTH-1:0] data,
input cs,
input we,
input oe
);
reg [DATA_WIDTH-1:0] tmp_data;
reg [DATA_WIDTH-1:0] mem [DEPTH];
always @ (posedge clk) begin
if (cs & we) mem[addr] <= data;
end
always @ (posedge clk) begin
if (cs & !we) tmp_data <= mem[addr];
end
assign data = cs & oe & !we ? tmp_data : 'hz;
endmodule
Single Port RAM met synchrone read/write diagram
Testbench
module tb;
parameter ADDR_WIDTH = 4;
parameter DATA_WIDTH = 16;
parameter DEPTH = 16;
reg clk, cs, we, oe;
reg [ADDR_WIDTH-1:0] addr;
wire [DATA_WIDTH-1:0] data;
reg [DATA_WIDTH-1:0] tb_data;
single_port_sync_ram #(.DATA_WIDTH(DATA_WIDTH)) u0 (
.clk(clk), .addr(addr), .data(data), .cs(cs), .we(we), .oe(oe)
);
always #10 clk = ~clk;
assign data = !oe ? tb_data : 'hz;
initial begin
{clk, cs, we, addr, tb_data, oe} <= 0;
repeat (2) @ (posedge clk);
for (integer i = 0; i < 2**ADDR_WIDTH; i = i+1) begin
repeat (1) @(posedge clk)
addr <= i; we <= 1; cs <= 1; oe <= 0; tb_data <= $random;
end
for (integer i = 0; i < 2**ADDR_WIDTH; i = i+1) begin
repeat (1) @(posedge clk)
addr <= i; we <= 0; cs <= 1; oe <= 1;
end
#20 $finish;
end
endmodule
Verilog
- Verilog beheersen: Complete tutorial voor digitale schakelingontwerp
- Verilog concatenatie beheersen: Een praktische gids
- Verilog-toewijzingen begrijpen: types, syntax en best practices
- Verilog Blocking vs. Non-Blocking: belangrijkste verschillen uitgelegd
- Verilog-functies beheersen voor efficiënt RTL-ontwerp
- Verilog Tasks begrijpen: Functions vs Tasks, Syntax en Gebruik
- Verilog Clock Generator: Ontwerp & Implementatie Gids
- Verilog Math Functions beheersen voor efficiënt Hardware-ontwerp
- Verilog $timeformat beheersen: Precisie en Weergave-controle
- Verilog Timescales begrijpen en printen in elke Scope
- Verilog File I/O onder de knie: Openen, Lezen, Schrijven en Sluiten