Posts Tagged with "FPGA"

既に発行済みのブログであっても適宜修正・追加することがあります。
We may make changes and additions to blogs already published.
posted by sakurai on September 6, 2022 #502

BSVソース

完成したBSVのソースを貼り付けます。1つのソースで4種のFSMを合成し分けているため、やや複雑になっています。

SoundFSM.bsv:

import StmtFSM::*;

`define SOUND1_ON     1        // 自弾発射音_ON
`define SOUND2_ON     2        // 自機爆発音_ON
`define SOUND3_ON     3        // インベーダ爆発音_ON
`define SOUND4_ON     4        // インベーダ歩行音1_ON
`define SOUND5_ON     5        // インベーダ歩行音2_ON
`define SOUND6_ON     6        // インベーダ歩行音3_ON
`define SOUND7_ON     7        // インベーダ歩行音4_ON
`define SOUND8_ON     8        // UFO爆発音_ON
`define SOUND9_ON     9        // 自機増加音_ON
`define SOUND10_ON   10        // UFO飛行音_ON
`define SOUND10_OFF  11        // UFO飛行音_OFF
`define NULL         'h80
`define COND_FSM0 !emptyf && (code == `SOUND1_ON || code == `SOUND2_ON || code == `SOUND9_ON)
`define COND_FSM1 !emptyf && (code == `SOUND3_ON)
`define COND_FSM2 !emptyf && (code == `SOUND4_ON || code == `SOUND5_ON || code == `SOUND6_ON || code == `SOUND7_ON)
`define COND_FSM3 !emptyf && (code == `SOUND8_ON || code == `SOUND10_ON || code == `SOUND10_OFF)

typedef UInt#(15) Addr_t;
typedef UInt#(8) Data_t;
typedef Bit#(4) Code_t;

interface FSM_ifc;
   method Action sound(Code_t code);
   method Action rom_data(Data_t indata);
   method Action sync(Bool lrclk);
   method Action empty(Bool flag);
   method Addr_t rom_address();
   method Data_t sdout();
   method Bool soundon();
   method Bool fifo_ren();
endinterface

 (* synthesize,always_ready,always_enabled *)
`ifdef FSM0
module mkSoundFSM0(FSM_ifc);
`elsif FSM1
module mkSoundFSM1(FSM_ifc);
`elsif FSM2
module mkSoundFSM2(FSM_ifc);
`elsif FSM3
module mkSoundFSM3(FSM_ifc);
`endif

   Wire#(Code_t) code <- mkWire,
                   current <- mkRegU;
   Wire#(Bool) lrclk <- mkWire;
   Reg#(Data_t) romdata <- mkRegU,
                   data <- mkRegU,
                   dout <- mkReg(`NULL);
   Reg#(UInt#(32)) workd <- mkRegU;
   Reg#(UInt#(15)) dcount <- mkRegU;
   Reg#(Addr_t) worka <- mkRegU,
                   romaddr <- mkRegU,
                   addr <- mkRegU;
   Reg#(UInt#(8)) ii <- mkReg(0);
   Reg#(Bool) son <- mkReg(False),
                   sonEarly <- mkReg(False),
                   ren <- mkReg(False),
                   emptyf <- mkReg(True);
`ifdef FSM3
    Reg#(Bool) fUFO <- mkReg(False);
`endif

   // subfunctions
   //   READ MEM
   //     input:  worka
   //     output: romdata;
   function Stmt readmem;
      return (seq
         addr <= worka;
         noAction;
         data <= romdata;
      endseq);
   endfunction

   //   READ COUNT
   //     input:  romaddr
   //     output: (romaddr,...,romaddr+3) => dcount;
   //             romaddr + 4 => romaddr;
   function Stmt readcount;
      return (seq
         workd <= 0;
         for (ii <= 0; ii <= 3; ii <= ii + 1) seq
            worka <= romaddr + extend(3-ii);
            readmem;
            if (ii == 3) dcount <= truncate(workd<<8) | extend(romdata);
            else workd <= workd<<8 | extend(romdata);
         endseq
         romaddr <= romaddr + 4;
      endseq);
   endfunction

   Stmt main = seq
      while(True) seq
         action
            dout <= `NULL;
            sonEarly <= False;
            son <= False;
            ren <= False;
         endaction
`ifdef FSM0
         await(`COND_FSM0);
         action
            ren <= True;
            current <= code;
         endaction
`elsif FSM1
         await(`COND_FSM1);
         action
            ren <= True;
            current <= code;
         endaction
`elsif FSM2
         await(`COND_FSM2);
         action
            ren <= True;
            current <= code;
         endaction
`elsif FSM3
         await(`COND_FSM3 || fUFO);
         if (`COND_FSM3) action
            fUFO <= (code == `SOUND10_ON);
            ren <= True;
            current <= code;
         endaction else if (fUFO) action
            current <= `SOUND10_ON;
        endaction
`endif
         await(emptyf);
         ren <= False;
`ifdef FSM3
         if (code == `SOUND10_OFF) continue;
`endif
         await(lrclk);
         await(!lrclk);
         delay(4);

         action    
            case (current)
`ifdef FSM0
               `SOUND1_ON:  romaddr <=     0 + 16;
               `SOUND2_ON:  romaddr <=  3422 + 16;
               `SOUND9_ON:  romaddr <= 16150 + 16;
`elsif FSM1
               `SOUND3_ON:  romaddr <=     0 + 16;
`elsif FSM2
               `SOUND4_ON:  romaddr <=     0 + 16;
               `SOUND5_ON:  romaddr <=  1266 + 16;
               `SOUND6_ON:  romaddr <=  2836 + 16;
               `SOUND7_ON:  romaddr <=  4406 + 16;
`elsif FSM3
               `SOUND8_ON:  romaddr <=     0 + 16;
               `SOUND10_ON: romaddr <= 25968 + 16;
`endif
            endcase
         endaction
         readcount;
         romaddr <= romaddr + extend(dcount) + 4;

         readcount;
         romaddr <= romaddr - 1;

         while (!((dcount == 0) || 
`ifdef FSM0
            (`COND_FSM0 && current !=`SOUND9_ON))) seq
`elsif FSM1
            (`COND_FSM1)))seq
`elsif FSM2
            (`COND_FSM2))) seq
`elsif FSM3
            (`COND_FSM3))) seq
`endif
            if (sonEarly == False) seq
               readmem;
               action
                  sonEarly <= True;
                  son <= False;
                  dout <= `NULL;
               endaction
            endseq else seq
               readmem;
               action
                  son <= True;
                  dout <= romdata;
               endaction
            endseq

            delay(11);
            action
               romaddr <= romaddr + 1;
               worka <= romaddr + 1;
               dcount <= dcount - 1;
            endaction
         endseq
`ifdef FSM3
         if ((code == `SOUND8_ON || code == `SOUND10_OFF) && !emptyf) fUFO <= False;
`endif
      endseq
   endseq;

   mkAutoFSM(main);

   method Action sound(Code_t incode);
      code <= incode;
   endmethod
   method Action rom_data(Data_t indata);
      romdata <= indata;
   endmethod
   method Addr_t rom_address();
      return addr;
   endmethod
   method Data_t sdout();
      return dout;
   endmethod
   method Bool soundon();
      return son;
   endmethod
   method Action sync(Bool inlrclk);
      lrclk <= inlrclk;
   endmethod
   method Bool fifo_ren();
      return ren;
   endmethod
   method Action empty(Bool flag);
      emptyf <= flag;
   endmethod

`ifdef FSM0
endmodule: mkSoundFSM0
`elsif FSM1
endmodule: mkSoundFSM1
`elsif FSM2
endmodule: mkSoundFSM2
`elsif FSM3
endmodule: mkSoundFSM3
`endif

これをverilogに合成するには、FSM0であれば、

bsc -verilog -D FSM0 SoundFSM.bsv

のようにマクロ定義により行います。


左矢前のブログ 次のブログ右矢


ページ: