[RTLLM-p036] Miscellaneous/RISC-V/RAM
雙埠同步 RAM
請設計一個名為 RAM 的雙埠同步記憶體模組。此模組具有獨立的讀取埠與寫入埠,因此可以在同一個時脈週期進行讀取與寫入操作。
RAM 的資料寬度為 6 位元,深度為 8,共有 8 個記憶體位置。當 Reset 有效時,所有記憶體位置皆初始化為:
000000
當 write_en 為 1 時,在 clk 的上升沿將 write_data 寫入 write_addr 指定的位置。
當 read_en 為 1 時,在 clk 的上升沿讀取 read_addr 指定位置的資料,並更新至 read_data。
當 read_en 為 0 時,在 clk 的上升沿將 read_data 清除為 0。
模組名稱
RAM
參數
| 參數 | 預設值 | 說明 |
|---|---|---|
WIDTH |
6 | 每個記憶體位置的資料寬度 |
DEPTH |
8 | RAM 的記憶體深度 |
輸入埠
| 埠名稱 | 位元寬度 | 說明 |
|---|---|---|
clk |
1 | 時脈訊號 |
rst_n |
1 | 低電位有效的非同步 Reset |
write_en |
1 | 寫入使能訊號 |
write_addr |
8 | 寫入位址,有效位址為 0 至 7 |
write_data |
6 | 欲寫入 RAM 的資料 |
read_en |
1 | 讀取使能訊號 |
read_addr |
8 | 讀取位址,有效位址為 0 至 7 |
輸出埠
| 埠名稱 | 位元寬度 | 說明 |
|---|---|---|
read_data |
6 | RAM 的同步讀取輸出 |
功能說明
Reset
當 rst_n 為 0 時,所有記憶體位置與 read_data 都必須清除為 0:
RAM[0] = 000000
RAM[1] = 000000
RAM[2] = 000000
RAM[3] = 000000
RAM[4] = 000000
RAM[5] = 000000
RAM[6] = 000000
RAM[7] = 000000
read_data = 000000
Reset 為非同步操作,因此不需要等待時脈上升沿。
寫入操作
當 rst_n = 1 且 write_en = 1 時,在 clk 上升沿執行:
RAM[write_addr] <= write_data;
當 write_en = 0 時,RAM 內容保持不變。
讀取操作
當 rst_n = 1 且 read_en = 1 時,在 clk 上升沿執行:
read_data <= RAM[read_addr];
當 read_en = 0 時,在 clk 上升沿執行:
read_data <= 6'b000000;
同時讀寫
讀取與寫入分別由兩個時序區塊控制,因此可以在同一個時脈上升沿同時進行。
若讀取位址與寫入位址不同,兩個操作互不影響。
若同一個時脈週期讀取與寫入相同位址,由於使用 nonblocking assignment,read_data 會取得該位址寫入前的舊資料。
設計要求
- 模組名稱必須為
RAM。 - 資料寬度預設為 6 位元。
- 記憶體深度預設為 8。
- 有效位址範圍為 0 至 7。
- Reset 必須為低電位有效的非同步 Reset。
- Reset 時必須清除全部 RAM 內容。
- Reset 時必須將
read_data清除為 0。 write_en = 1時執行同步寫入。read_en = 1時執行同步讀取。read_en = 0時,read_data必須清除為 0。- 讀取與寫入可以同時進行。
- 時序邏輯必須使用 nonblocking assignment。
程式模板
module RAM #(
parameter WIDTH = 6,
parameter DEPTH = 8
) (
input clk,
input rst_n,
input write_en,
input [7:0] write_addr,
input [WIDTH-1:0] write_data,
input read_en,
input [7:0] read_addr,
output reg [WIDTH-1:0] read_data
);
reg [WIDTH-1:0] RAM [0:DEPTH-1];
// Write your code here
endmodule
評論