|
1 |
メモリをBSVで書く |
教科書版の手書きVerilogは、トップの配線、メモリ、クロック生成の3つでした。このうちメモリは、BSVの標準ライブラリBRAMCoreがそのまま当てはまる部分で、手書きのVerilogを残す理由がありません。パターンROM、VRAM、サウンドROMの3つをBSVのモジュールにしました。どれも初期値は今までどおりmemの$readmemhで読み、Vivadoの運用は変わりません。合成はYosysのsynth_xilinx、動作確認はVerilatorとiverilogで、前回までと同じ条件です。
置き場所を決める物差しは、機能が別なら別モジュール、というものです。FSMはROMを読む機能、ROMは内容を持つ機能で、2つは別のモジュールにします。そのうえで、ROMを読むのがそのFSMだけなら、ROMのモジュールはそのFSMの中に置き、FSMがメソッドで呼びます。パターンROMはブリッタの中に、サウンドROMはサウンドFSMの中に置きました。VRAMは2つのクロック域から共有されるので、独立のモジュールとしてトップに置いたままです。
1点目 パターンROMをブリッタの中に置く

図1132.1 パターンROM書き換え前後
パターンROMを読むのはブリッタだけです。それなのにROMはmaster.vにあり、ブリッタはアドレスをレジスタp_addrに置いて外に出し、読み出しデータをワイヤromdataで受けていました。ブリッタのMemPortにはprom_addrとpdinの2ポートがあり、mkGameFSMにも同じ名前のポートが素通しで並んでいました。
書き換え前
// MemPort: 画面メモリ側の面
interface MemPort;
(* always_ready *) method PAddr_t prom_addr;
(* always_ready *) method VAddr_t vaddr;
(* always_ready *) method Bool vwe;
(* always_ready *) method Pattern_t vdout;
(* always_enabled *) method Action pdin(Pattern_t d);
(* always_enabled *) method Action vdin(Pattern_t d);
endinterface
Reg#(PAddr_t) p_addr <- mkRegU;
Reg#(VAddr_t) v_addr <- mkRegU;
Reg#(Bool) fvwe <- mkReg(False);
Reg#(Bool) fobj <- mkReg(False),
fbase <- mkReg(False);
Reg#(Pattern_t) vd <- mkRegU;
Wire#(Pattern_t) vdata <- mkWire,
romdata <- mkWire;
action
p_addr <= {pack(ys)[7:0], pack(xs)[6:0]};
UInt#(8) y_addr = truncate(yd);
UInt#(8) x_addr = truncate(xd);
v_addr <= {pack(y_addr), pack(x_addr)};
endaction
noAction; // リード待ち(1サイクル)
action
case (b.op)
BLIT_COPY: vd <= romdata;
BLIT_OR: vd <= vdata | romdata;
BLIT_ANDN: vd <= vdata & ~romdata;
BLIT_ERASE: vd <= 0;
endcase
xs <= xs + 1;
xd <= xd + 1;
endaction
interface MemPort mem;
method PAddr_t prom_addr = p_addr;
method VAddr_t vaddr = v_addr;
method Bool vwe = fvwe;
method Pattern_t vdout = vd;
method Action pdin(Pattern_t d); romdata <= d; endmethod
method Action vdin(Pattern_t d); vdata <= d; endmethod
endinterface
master.vにはROMのインスタンスと、そこへ渡す2本の配線がありました。
wire [14:0] prom_addr;
wire [3:0] prom_dout;
mkGameFSM u_game (
.CLK (clk),
.RST_N (rst_n),
.COUNT (COUNT),
.START_BUTTON (start_db),
.LEFT_BUTTON (left_db),
.RIGHT_BUTTON (right_db),
.FIRE_BUTTON (fire_db),
.tick (tick),
.empty (fifo_empty),
.fifo_wen (fifo_wen),
.SCODE (scode),
.prom_addr (prom_addr),
.pdin (prom_dout),
.vaddr (vaddr),
.vdout (vdout),
.vwe (vwe),
.vdin (vdin),
.Gun_Exp (gun_exp)
);
rom #(.WIDTH(4), .AWIDTH(15), .DEPTH(25728), .FILE("prom.mem")) u_prom (
.clk (clk),
.addr (prom_addr),
.q (prom_dout)
);
Leave a Comment