DE0でFPGAのチップ内蔵RAMにアクセスする

RAMがほしい。
regを使ってRAMを作れないことはないんだけど、それだとロジックセルのフリップフロップを使ったRAMになって、せっかくチップに64KB近いRAMが載っているのがもったいない。
8MバイトのSDRAMもあるのだけど、これは扱うのはちょっとめんどくさそうなのであとまわし。


ということで、チップ内蔵RAMを使ってみる。
ToolメニューのMega Wizardというところからメモリモジュールが作成できるらしい。
いろいろな種類のRAMが選べるのだけど、今回はとりあえずRAM:1-PORTを選ぶ。


容量


インタフェース
「q output port」は、レジスタ経由の受け渡しになって1相遅れるらしいので、ここではチェックをはずしておく


メモリ書き込み時の出力を選ぶ。書き込んだ値か古い値かなどが選べるけど、ここでは書き込んだ値にしておく。


メモリの初期化。値を設定しておくこともできるけど、今回は使わない。


シミュレーション用ファイル。今回は不要。


最後に、生成ファイルの選択。ここで、_instを選ぶとメモリアクセスのサンプルが出力されるので、使い方がわからないうちは選んでおくといい。


そしたら、コードを書く。
今回は、左4つのスイッチをアドレス直結しつつ一番左の7セグに直結、右4つのスイッチをメモリへのデータ入力と一番右の7セグに直結、あとはメモリ出力を右から2番目の7セグに直結して、左端のボタンを押すと書き込み信号が出るような、あまり賢くない回路を組んでみた。
なので、左4つのスイッチで指定したアドレスの値が常に右から2番目の7セグに表示される。ボタンを押すと指定したアドレスに右4つのスイッチで指定した値が書き込まれる(同時に読み込まれるので右から2番目の7セグにも反映される)。という動きをする。


いままで組んだ回路は状態を覚えてくれていなかったのだけど、これでいろんな状態を管理できるようになった。
楽しい。
見てる側には、表示が7セグとLEDしかないと、何も変わり映えしないので、楽しさは伝わりにくいだろうけど。


コードはこんな感じ。hexsegは7セグ表示のモジュールを適当に。

module sram(
    input clk, 
    input [9:0] sw, 
    input [2:0] btn, 
    output [9:0] led, 
    output [7:0] hled0, 
    output [7:0] hled1, 
    output [7:0] hled2, 
    output [7:0] hled3
);
assign led=10'h0;
assign hled2=8'hff;

// chattering
reg [15:0] cnt;
reg ubtn;
always @(posedge clk) begin
    cnt=cnt+1;
end
always @(posedge cnt[15]) begin
    ubtn=btn[2];
end

// button
reg obtn;// old button
reg wsig;// write signal
always @(posedge clk)begin
    if(ubtn) begin
        if(!obtn) begin
            obtn <= 1'b1;
            wsig <= 1'b1;
        end else begin
            wsig <= 1'b0;
        end
    end else begin
        obtn <= 1'b0;
    end
end

// ram access
wire [7:0] rdata;
ram ram_inst (
    .address ( {1'b0, sw[9:6]} ),
    .clock ( clk ),
    .data ( {4'd0, sw[3:0]} ),
    .wren ( wsig ),
    .q ( rdata )
    );

// display
hexseg h1(clk, sw[3:0], hled0);
hexseg h2(clk, rdata[3:0], hled1);
hexseg h3(clk, sw[9:6], hled3);

endmodule