Update FPGARAM authored by Toru Koizumi's avatar Toru Koizumi
......@@ -27,7 +27,7 @@ FPGA 上で RAM を構成する方法には、フリップフロップ、分散R
## 分散RAM
1 read / 1 write の 分散RAM の記述例です。
1 read + 1 write の 分散RAM の記述例です。
重要なのは、**書き込みのタイミングをクロックと同期する**ということです。
......@@ -49,27 +49,25 @@ FPGA 上で RAM を構成する方法には、フリップフロップ、分散R
## ブロックRAM
1 read / 1 write の ブロックRAM の記述例です。
1 read + 1 write の ブロックRAM の記述例です。
重要なのは、**書き込みのタイミングと読み出しアドレスをそれぞれクロックと同期する**ということです。
重要なのは、**書き込みのタイミングと読み出しのタイミングをそれぞれクロックと同期する**ということです。
```verilog
module ram(clk, we, r_addr, r_data, w_addr, w_data);
input clk, we;
input [4:0] r_addr, w_addr;
input [31:0] w_data;
output [31:0] r_data;
reg [4:0] addr_reg;
output reg [31:0] r_data;
reg [31:0] mem [0:31];
always @(posedge clk) begin
if(we) mem[w_addr] <= w_data; // 書き込みのタイミングを同期
addr_reg <= r_addr; //読み出しアドレスを同期
r_data <= mem[r_addr]; // 読み出しのタイミングを同期
end
assign r_data = mem[addr_reg];
endmodule
```
port 数の増やし方は、分散RAM の時と同様ですが、2つまでしか増やせません。
port 数の増やし方は、分散RAM の時と同様ですが、2つまでしか増やせません(上記例は 1 read + 1 write で2 port 使っているため、これ以上増やせません。2 read にすることや、read と write 兼用の port を二つ設けることは可能です)
## バイトマスク付きライト
......@@ -82,17 +80,15 @@ port 数の増やし方は、分散RAM の時と同様ですが、2つまでし
input [3:0] we; // 書き込むバイトは1, 書き込まないでそのままにするバイトは0を指定
input [4:0] r_addr, w_addr;
input [31:0] w_data;
output [31:0] r_data;
reg [4:0] addr_reg;
output reg [31:0] r_data;
reg [31:0] mem [0:31];
always @(posedge clk) begin
if(we[0]) mem[w_addr][ 7: 0] <= w_data[ 7: 0];
if(we[1]) mem[w_addr][15: 8] <= w_data[15: 8];
if(we[2]) mem[w_addr][23:16] <= w_data[23:16];
if(we[3]) mem[w_addr][31:24] <= w_data[31:24];
addr_reg <= r_addr;
r_data <= mem[r_addr];
end
assign r_data = mem[addr_reg];
endmodule
```
......@@ -146,18 +142,16 @@ RAM の初期化は、モジュール内に次の記述をすることで行う
## ROM の記述
ROM の場合も、write 線がないだけで RAM と同様です。すなわち、読み出しを同期すれば ブロックRAM で構成されます。
ROM の場合も、write 線がないだけで RAM と同様です。すなわち、読み出しタイミングを同期すれば ブロックRAM で構成されます。
```verilog
module rom(clk, r_addr, r_data);
input clk;
input [4:0] r_addr;
output [31:0] r_data;
reg [4:0] addr_reg;
output reg [31:0] r_data;
reg [31:0] mem [0:31]
always @(posedge clk) begin
addr_reg <= r_addr; //読み出しアドレスを同期
r_data <= mem[r_addr]; // 読み出しタイミングを同期
end
assign r_data = mem[addr_reg];
endmodule
```