簡単に作るVerilogテストベンチの続きです。Opencores で公開されているEthmacに、WishboneのBFMを接続してみました。標準でついてくるWishboneのBFMがVHDLだったので、必要な機能だけVerilogで書き直しました。
- Wishbone BFMはここから。http://opencores.org/opencores,wishbone
- Ethmacの入手先はここです。http://opencores.org/project,ethmac
- シミュレータはVeritakを使用しています。
Verilogport
Wishbone付属のBFMをVerilogに移植した物をgithubにあげてあります。
https://github.com/natsutan/wishbone_BFM_verilog_port
サポートしているAPIは、以下の6つです。
- clock_wait 指定したクロック分だけwaitする。
- wb_init wishboneバスの初期化を行う。
- wb_rst 指定したクロック分、wishbone busをリセット状態にする。
- rd_32 32bitシングルリード
- wr_32 32bitシングルライト
- rmw_32 32bitリードモディファイライト
レジスタR/W
簡単に作るVerilogテストベンチの同じレジスタをR/Wしました。
wishboneのアドレス線をずらしてつなぐことで、tb_eth_defines.v で定義されているレジスタ名を、BFMのAPIにそのまま使用しています。これで、対象のレジスタに対して、リードライトできました。
initial begin #1 CLK_stop = 0; reset_int = 0; wb_init(); wb_rst(2); clock_wait(2); // Wait 20 ns for global reset to finish wr_32(`ETH_MAC_ADDR0,32'h12345678); clock_wait(1); rd_32(`ETH_MAC_ADDR0, read_data); $display("RD 0 %08X", read_data); clock_wait(10); # 100 CLK_stop = 1; # 100 $finish(); end
topレベル
// OpenCoresで公開されているEthermac用のテストベンチ // // Eathermacプロジェクト // http://opencores.org/project,ethmac // timescaleの設定 //`timescale 1ns/1ps //`include "wb_model_defines.v" `include "ethmac_defines.v" `include "timescale.v" module ethermac_tb (); //DUTの入力に接続する信号 wire wb_clk_i; // WISHBONE clock wire wb_rst_i; // WISHBONE reset wire [31:0] wb_dat_i; // WISHBONE data input wire [31:0] wb_dat_o; // WISHBONE data output wire wb_err_o; // WISHBONE error output // WISHBONE slave wire [31:0] wb_adr_i; // WISHBONE address reg wire [3:0] wb_sel_i; // WISHBONE byte select input wire wb_we_i; // WISHBONE write enable input wire wb_cyc_i; // WISHBONE cycle input wire wb_stb_i; // WISHBONE strobe input wire wb_ack_o; // WISHBONE acknowledge output // WISHBONE master wire [31:0] m_wb_adr_o; wire [3:0] m_wb_sel_o; wire m_wb_we_o; reg [31:0] m_wb_dat_i; wire [31:0] m_wb_dat_o; wire m_wb_cyc_o; wire m_wb_stb_o; reg m_wb_ack_i; reg m_wb_err_i; wire [2:0] m_wb_cti_o; // Cycle Type Identifier wire [1:0] m_wb_bte_o; // Burst Type Extension // Tx reg mtx_clk_pad_i; // Transmit clock (from PHY) wire [3:0] mtxd_pad_o; // Transmit nibble (to PHY) wire mtxen_pad_o; // Transmit enable (to PHY) wire mtxerr_pad_o; // Transmit error (to PHY) // Rx reg mrx_clk_pad_i; // Receive clock (from PHY) reg [3:0] mrxd_pad_i; // Receive nibble (from PHY) reg mrxdv_pad_i; // Receive data valid (from PHY) reg mrxerr_pad_i; // Receive data error (from PHY) // Common Tx and Rx reg mcoll_pad_i; // Collision (from PHY) reg mcrs_pad_i; // Carrier sense (from PHY) // MII Management interface reg md_pad_i; // MII data input (from I/O cell) wire mdc_pad_o; // MII Management data clock (to PHY) wire md_pad_o; // MII data output (to I/O cell) wire md_padoe_o; // MII data output enable (to I/O cell) wire int_o; // Interrupt output wire [4:0] wbm_tag; assign wbm_tag = 0; // CLKの周期 parameter WB_PERIOD = 10.0; parameter TX_PERIOD = 8.0; parameter RX_PERIOD = 8.0; //DUT ethmac u0 ( .wb_clk_i(wb_clk_i), .wb_rst_i(wb_rst_i), .wb_dat_i(wb_dat_i), .wb_dat_o(wb_dat_o), .wb_adr_i(wb_adr_i[11:2]), .wb_sel_i(wb_sel_i), .wb_we_i(wb_we_i), .wb_cyc_i(wb_cyc_i), .wb_stb_i(wb_stb_i), .wb_ack_o(wb_ack_o), .wb_err_o(wb_err_o), .m_wb_adr_o(m_wb_adr_o), .m_wb_sel_o(m_wb_sel_o), .m_wb_we_o(m_wb_we_o), .m_wb_dat_o(m_wb_dat_o), .m_wb_dat_i(m_wb_dat_i), .m_wb_cyc_o(m_wb_cyc_o), .m_wb_stb_o(m_wb_stb_o), .m_wb_ack_i(m_wb_ack_i), .m_wb_err_i(m_wb_err_i), .m_wb_cti_o(m_wb_cti_o), .m_wb_bte_o(m_wb_bte_o), .mtx_clk_pad_i(mtx_clk_pad_i), .mtxd_pad_o(mtxd_pad_o), .mtxen_pad_o(mtxen_pad_o), .mtxerr_pad_o(mtxerr_pad_o), .mrx_clk_pad_i(mrx_clk_pad_i), .mrxd_pad_i(mrxd_pad_i), .mrxdv_pad_i(mrxdv_pad_i), .mrxerr_pad_i(mrxerr_pad_i), .mcoll_pad_i(mcoll_pad_i), .mcrs_pad_i(mcrs_pad_i), .mdc_pad_o(mdc_pad_o), .md_pad_i(md_pad_i), .md_pad_o(md_pad_o), .md_padoe_o(md_padoe_o), .int_o(int_o) ); syscon #(.clk_period(WB_PERIOD)) sc ( .RST_sys(RST_sys), .CLK_stop(CLK_stop), .RST_o(wb_rst_i), .CLK_o(wb_clk_i) ); mb_master_bfm0 #(.clk_period(WB_PERIOD)) master ( .RST_sys(RST_sys), .CLK_stop(CLK_stop), .RST_I(wb_rst_i), .CLK_I(wb_clk_i), .ADR_O(wb_adr_i), .DAT_I(wb_dat_o), .DAT_O(wb_dat_i), .WE_O(wb_we_i), .STB_O(wb_stb_i), .CYC_O(wb_cyc_i), .ACK_I(wb_stb_o), .ERR_I(wb_err_o), .RTY_I(), .LOCK_O(), .SEL_O(wb_sel_i), .CYCLE_IS() ); // clkの生成 always # (TX_PERIOD/2) mtx_clk_pad_i = ~mtx_clk_pad_i; always # (RX_PERIOD/2) mrx_clk_pad_i = ~mrx_clk_pad_i; initial begin #1 mtx_clk_pad_i = 1; mrx_clk_pad_i = 0; end endmodule // ethermac_tb