systemVerilogサンプル・その2

interface接続例を載せよう。。合成可能RTLだ~~~
→Quartus2-9.1sp1に限るぜ。。

信号の接続にもっと賢そうな技はないの??と思うかもしれないけど合成する部分は確実性が大事だ。
net+sdfでシミュレーションしたら動かないなんてよくある。。

回路は先日載せたtimer_coreを2つインスタンスしwb_busも2つインスタンスする。
それをassignで接続。。

昨年の夏頃はinterfaceを複数個インスタンスするとエラーになっていたが。。いつの間にかOKに!!
 →これが出来ないとinterfaceの威力半減だろ。。

合成するtopモジュールはinterface記述出来ない。
 →下記をtopモジュールにして合成するとエラーに。。
module timer_core(interface wb_bus) ;


テストベンチ部分は気が向いたら載せよう。。


`include "timescale.svh"
interface wb_bus() ;
   
   wire                     clk_i ;   // clock 
   wire                     nrst_i ;  // reset 
   wire [3:0]               adr_i ;   // address
   wire [31:0]              dat_i ;   // data input
   wire [31:0]              dat_o ;   // clk_rst_manager
   wire                     we_i  ;   // write enable
   wire [3:0]               sel_i ;   // byte enable
   wire                     stb_i ;   // strobe
   wire                     ack_o ;   // acknowledge accept
   wire                     cyc_i ;   // cycle assrted
   wire                     intr_o ;  // interrput
   
   modport master_mp(
                     output  clk_i, nrst_i, adr_i, dat_i, we_i, sel_i, cyc_i, stb_i,
                     input  dat_o, ack_o, intr_o
                     ) ;
   
   modport slave_mp(
                    input  clk_i, nrst_i, adr_i, dat_i, we_i, sel_i, stb_i, cyc_i,
                    output dat_o, ack_o, intr_o) ;
endinterface : wb_bus

module timer_module
(
 input        clk_i,
 input        nrst_i,
 input [3:0]  adr_i,
 input [31:0] dat_i,
 input        cyc_i,
 input        stb_i,
 input [3:0]  sel_i,
 input        we_i,
 output [31:0] dat_o,
 output       ack_o,
 output       intr_o
 ) ;
   
   wb_bus
     wb_t0(),
     wb_t1() ;
   
   timer_core
     t0(.wb_bus(wb_t0.slave_mp)),
     t1(.wb_bus(wb_t1.slave_mp)) ;
   
   logic [31:0] rdat ;

   wire         t0_stb  = stb_i == 1'b1 && (adr_i[3] == 1'b0) ;
   wire         t1_stb  = stb_i == 1'b1 && (adr_i[3] == 1'b1) ;
   
   assign  wb_t0.clk_i  = clk_i ;
   assign  wb_t0.nrst_i = nrst_i ;
   assign  wb_t0.adr_i  = adr_i ;
   assign  wb_t0.dat_i  = dat_i ;
   assign  wb_t0.stb_i  = t0_stb ;
   assign  wb_t0.cyc_i  = cyc_i ;
   assign  wb_t0.sel_i  = sel_i ;
   assign  wb_t0.we_i   = we_i ;

   assign  wb_t1.clk_i  = clk_i ;
   assign  wb_t1.nrst_i = nrst_i ;
   assign  wb_t1.adr_i  = adr_i ;
   assign  wb_t1.dat_i  = dat_i ;
   assign  wb_t1.stb_i  = t1_stb ;
   assign  wb_t1.cyc_i  = cyc_i ;
   assign  wb_t1.sel_i  = sel_i ;
   assign  wb_t1.we_i   = we_i ;

   assign  intr_o = wb_t0.intr_o |
                    wb_t1.intr_o ;

   assign  ack_o = wb_t0.ack_o |
                   wb_t1.ack_o ;

   assign  dat_o = rdat ;
   
   always_comb begin
      case ({t0_stb, t1_stb})
        2'b10  : rdat = wb_t0.dat_o ;
        2'b01  : rdat = wb_t1.dat_o ;
        default : rdat = 0 ;
      endcase // case ({t0_stb, t1_stb})
   end
endmodule