设计 Verilog 单端口 RAM:全面指南
设计
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 & !wr ? tmp_data : 'hz; endmodule

测试平台
module tb; parameter ADDR_WIDTH = 4; parameter DATA_WIDTH = 16; parameter DEPTH = 16; reg clk; reg cs; reg we; reg 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 入门:数字电路设计完整教程
- 掌握 Verilog 拼接操作:实用指南
- 深入理解 Verilog 赋值语句:类型、语法与最佳实践
- Verilog阻塞与非阻塞赋值:关键区别详解
- 掌握Verilog函数:高效RTL设计的复用利器
- 理解Verilog任务:函数vs任务、语法与用法全解析
- Verilog 时钟发生器设计与实现指南
- 掌握 Verilog 数学函数:高效硬件设计的利器
- 掌握 Verilog $timeformat:精度控制与显示格式化
- 理解与打印 Verilog 任意作用域下的 Timescale
- 掌握 Verilog 文件 I/O:打开、读取、写入和关闭
- Verilog 入门指南:Hello World 示例