またしてもこの本でVerilogだ。
FPGA ボードで学ぶ組込みシステム開発入門 ?Altera編?
- 作者: 小林優
- 出版社/メーカー: 技術評論社
- 発売日: 2011/09/22
- メディア: 大型本
- 購入: 3人 クリック: 31回
- この商品を含むブログ (19件) を見る
まずはMega WizardでRAMを作る、主な設定は以下の通り。
- RAM 2 port
- 1 port read / 1 port write
- 8bits/word x 16words、memory block typeはautoで選択
- sigle clock, read enableはなし
- read portのregisterは外す(出力はクロック非同期)
後はすべてデフォルトで作成する。
出来上がったRAMの宣言はこんな感じになる。
module eram ( clock, data, rdaddress, wraddress, wren, q); input clock; input [7:0] data; input [3:0] rdaddress; input [3:0] wraddress; input wren; output [7:0] q;
テストしてみよう。
以下のようなRAMの書き込み、読み出しをするモジュールを作る。
- 10バイト目(アドレス0x00から0x09)までそのアドレス値を書く
- それを10バイト目(アドレス0x00から0x09)まで読み出す
module eram_wr_test( input wire in_clk, input wire in_reset, output reg [2:0] state_machine, output wire f_counter_write_expired, output wire f_counter_read_expired, output reg [3:0] _4bit_counter_write, output reg [3:0] _4bit_counter_read, output wire [7:0] read_buffer, output wire [7:0] sram_read_out); // // state machine // parameter INIT = 3'b000; parameter WRITE = 3'b001; parameter HOLD = 3'b010; parameter READ = 3'b011; parameter STOP = 3'b100; // always @(posedge in_clk, posedge in_reset) begin if (in_reset) state_machine <= INIT; else case (state_machine) INIT: state_machine <= WRITE; WRITE: if (f_counter_write_expired) state_machine <= HOLD; else state_machine <= WRITE; HOLD: state_machine <= READ; READ: if (f_counter_read_expired) state_machine <= STOP; else state_machine <= READ; STOP: state_machine <= STOP; endcase end // // write counter // assign f_counter_write_expired = (_4bit_counter_write == 4'd9)? 1'b1: 1'b0; // always @(negedge in_clk, posedge in_reset) begin if (in_reset) _4bit_counter_write <= 4'd0; else if (state_machine == WRITE) begin if (f_counter_write_expired) begin _4bit_counter_write <= 4'd0; end else begin _4bit_counter_write <= _4bit_counter_write +4'd1; end end end // // memory writer // reg [7:0] _8bit_16word_ram [0:15]; // integer counter_ram_clear; always @(posedge in_clk, posedge in_reset) begin if (in_reset) begin for (counter_ram_clear = 0; counter_ram_clear < 16; counter_ram_clear = counter_ram_clear + 1) begin _8bit_16word_ram[counter_ram_clear] <= 8'h0; end end else if (state_machine == WRITE) _8bit_16word_ram[_4bit_counter_write] = {4'b0000, _4bit_counter_write}; end // // read counter // assign f_counter_read_expired = (_4bit_counter_read == 4'd9)? 1'b1: 1'b0; assign read_buffer = (state_machine == READ)? _8bit_16word_ram[_4bit_counter_read]: 8'h00; // always @(negedge in_clk, posedge in_reset) begin if (in_reset) _4bit_counter_read <= 4'd0; else if (state_machine == READ) begin if (f_counter_read_expired) _4bit_counter_read <= 4'd0; else _4bit_counter_read <= _4bit_counter_read + 4'd1; end end // // ERAM module // // wire write_enable; assign write_enable = (state_machine == WRITE)? 1'b1: 1'b0; // eram ERAM( .clock(in_clk), .data({4'b0000, _4bit_counter_write}), .rdaddress(_4bit_counter_read), .wraddress(_4bit_counter_write), .wren(write_enable), .q(sram_read_out)); endmodule
比較として、同じような8bit幅16wordのレジスタを作り、同時に読み書きする。
こちらがRTLシミュレーションの結果。
一番下2つのうち、上がレジスタの読み出し結果、下が組み込みRAMの読み出し結果だ。
レジスタはアドレスが変われば、読み出し値が変わる、ただのラッチなので当たり前か。
一方組み込みRAMの方はアドレスがセットされて次のクロック立ち上がりでデータが読み出される。