(原创)Altera 1-port ram 的wishbone slave接口写法和wishbone master BFM验证

Altera 1-port ram wishbone slave接口写法和wishbone master BFM验证

目标aemb软硬件系统

在学习wishbone总线

现在的想法是:先做一个wishbone+altera ramtestbench

ToolsàMegaWizard Plug-In Manageràcreat a new custom megafunction variation

Mem Init中选择No,leave it blank

生成altera_ram.v文件

// megafunction wizard: %RAM: 1-PORT%

// GENERATION: STANDARD

// VERSION: WM1.0

// MODULE: altsyncram

 

// ============================================================

// File Name: altera_ram.v

// Megafunction Name(s):

//                     altsyncram

//

// Simulation Library Files(s):

//                     altera_mf

// ============================================================

// ************************************************************

// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!

//

// 9.0 Build 132 02/25/2009 SJ Full Version

// ************************************************************

 

 

//Copyright (C) 1991-2009 Altera Corporation

//Your use of Altera Corporation's design tools, logic functions

//and other software and tools, and its AMPP partner logic

//functions, and any output files from any of the foregoing

//(including device programming or simulation files), and any

//associated documentation or information are expressly subject

//to the terms and conditions of the Altera Program License

//Subscription Agreement, Altera MegaCore Function License

//Agreement, or other applicable license agreement, including,

//without limitation, that your use is for the sole purpose of

//programming logic devices manufactured by Altera and sold by

//Altera or its authorized distributors.  Please refer to the

//applicable agreement for further details.

 

 

// synopsys translate_off

`timescale 1 ps / 1 ps

// synopsys translate_on

module altera_ram (

       aclr,

       address,

       byteena,

       clock,

       data,

       wren,

       q);

 

       input     aclr;

       input   [12:0]  address;

       input   [3:0]  byteena;

       input     clock;

       input   [31:0]  data;

       input     wren;

       output  [31:0]  q;

 

       wire [31:0] sub_wire0;

       wire [31:0] q = sub_wire0[31:0];

 

       altsyncram      altsyncram_component (

                               .wren_a (wren),

                               .aclr0 (aclr),

                               .clock0 (clock),

                               .byteena_a (byteena),

                               .address_a (address),

                               .data_a (data),

                               .q_a (sub_wire0),

                               .aclr1 (1'b0),

                               .address_b (1'b1),

                               .addressstall_a (1'b0),

                               .addressstall_b (1'b0),

                               .byteena_b (1'b1),

                               .clock1 (1'b1),

                               .clocken0 (1'b1),

                               .clocken1 (1'b1),

                               .clocken2 (1'b1),

                               .clocken3 (1'b1),

                               .data_b (1'b1),

                               .eccstatus (),

                               .q_b (),

                               .rden_a (1'b1),

                               .rden_b (1'b1),

                               .wren_b (1'b0));

       defparam

               altsyncram_component.byte_size = 8,

               altsyncram_component.clock_enable_input_a = "BYPASS",

               altsyncram_component.clock_enable_output_a = "BYPASS",

               altsyncram_component.intended_device_family = "Cyclone II",

               altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO",

               altsyncram_component.lpm_type = "altsyncram",

               altsyncram_component.numwords_a = 8192,

               altsyncram_component.operation_mode = "SINGLE_PORT",

               altsyncram_component.outdata_aclr_a = "CLEAR0",

               altsyncram_component.outdata_reg_a = "CLOCK0",

               altsyncram_component.power_up_uninitialized = "FALSE",

               altsyncram_component.widthad_a = 13,

               altsyncram_component.width_a = 32,

               altsyncram_component.width_byteena_a = 4;

 

 

endmodule

 

// ============================================================

// CNX file retrieval info

// ============================================================

// Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0"

// Retrieval info: PRIVATE: AclrAddr NUMERIC "0"

// Retrieval info: PRIVATE: AclrByte NUMERIC "0"

// Retrieval info: PRIVATE: AclrData NUMERIC "0"

// Retrieval info: PRIVATE: AclrOutput NUMERIC "1"

// Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "1"

// Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8"

// Retrieval info: PRIVATE: BlankMemory NUMERIC "1"

// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0"

// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0"

// Retrieval info: PRIVATE: Clken NUMERIC "0"

// Retrieval info: PRIVATE: DataBusSeparated NUMERIC "1"

// Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0"

// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A"

// Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0"

// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II"

// Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0"

// Retrieval info: PRIVATE: JTAG_ID STRING "NONE"

// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"

// Retrieval info: PRIVATE: MIFfilename STRING ""

// Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "8192"

// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"

// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3"

// Retrieval info: PRIVATE: RegAddr NUMERIC "1"

// Retrieval info: PRIVATE: RegData NUMERIC "1"

// Retrieval info: PRIVATE: RegOutput NUMERIC "1"

// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"

// Retrieval info: PRIVATE: SingleClock NUMERIC "1"

// Retrieval info: PRIVATE: UseDQRAM NUMERIC "1"

// Retrieval info: PRIVATE: WRCONTROL_ACLR_A NUMERIC "0"

// Retrieval info: PRIVATE: WidthAddr NUMERIC "13"

// Retrieval info: PRIVATE: WidthData NUMERIC "32"

// Retrieval info: PRIVATE: rden NUMERIC "0"

// Retrieval info: CONSTANT: BYTE_SIZE NUMERIC "8"

// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS"

// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS"

// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II"

// Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO"

// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"

// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "8192"

// Retrieval info: CONSTANT: OPERATION_MODE STRING "SINGLE_PORT"

// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "CLEAR0"

// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0"

// Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE"

// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "13"

// Retrieval info: CONSTANT: WIDTH_A NUMERIC "32"

// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "4"

// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT NODEFVAL aclr

// Retrieval info: USED_PORT: address 0 0 13 0 INPUT NODEFVAL address[12..0]

// Retrieval info: USED_PORT: byteena 0 0 4 0 INPUT NODEFVAL byteena[3..0]

// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL clock

// Retrieval info: USED_PORT: data 0 0 32 0 INPUT NODEFVAL data[31..0]

// Retrieval info: USED_PORT: q 0 0 32 0 OUTPUT NODEFVAL q[31..0]

// Retrieval info: USED_PORT: wren 0 0 0 0 INPUT NODEFVAL wren

// Retrieval info: CONNECT: @address_a 0 0 13 0 address 0 0 13 0

// Retrieval info: CONNECT: q 0 0 32 0 @q_a 0 0 32 0

// Retrieval info: CONNECT: @byteena_a 0 0 4 0 byteena 0 0 4 0

// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0

// Retrieval info: CONNECT: @aclr0 0 0 0 0 aclr 0 0 0 0

// Retrieval info: CONNECT: @data_a 0 0 32 0 data 0 0 32 0

// Retrieval info: CONNECT: @wren_a 0 0 0 0 wren 0 0 0 0

// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all

// Retrieval info: GEN_FILE: TYPE_NORMAL altera_ram.v TRUE

// Retrieval info: GEN_FILE: TYPE_NORMAL altera_ram.inc FALSE

// Retrieval info: GEN_FILE: TYPE_NORMAL altera_ram.cmp FALSE

// Retrieval info: GEN_FILE: TYPE_NORMAL altera_ram.bsf FALSE

// Retrieval info: GEN_FILE: TYPE_NORMAL altera_ram_inst.v FALSE

// Retrieval info: GEN_FILE: TYPE_NORMAL altera_ram_bb.v FALSE

// Retrieval info: GEN_FILE: TYPE_NORMAL altera_ram_waveforms.html FALSE

// Retrieval info: GEN_FILE: TYPE_NORMAL altera_ram_wave*.jpg FALSE

// Retrieval info: LIB_FILE: altera_mf

编写altera_ramslave接口文件,此处是根据orpXL工程中的接口写的,只不过在orpXL中是VHDL文件的。ram0_top.v文件

module ram0_top(

               input clk_i,

              input rst_i,

              

               input wb_stb_i,

               input wb_cyc_i,

               output reg wb_ack_o,

               input [31:0] wb_addr_i,

               input [3:0] wb_sel_i,

               input wb_we_i,

               input [31:0] wb_data_i,

               output [31:0] wb_data_o

       );

 

       // request signal

       wire request;

      

       // inputs to ram

       wire [12:0] ram_address;

       wire [31:0] ram_data;

       wire [3:0] ram_byteena;

       wire ram_wren;

      

       // request signal's rising edge

       reg request_delay;

       wire request_rising_edge;

 

       // ack signal

       reg ram_ack;

      

       // get request signal

       assign request = wb_stb_i & wb_cyc_i;

      

       // select data to on-chip ram only when request = '1'

       // otherwise wren will be '0', so that no data will be

       // written into onchip ram by mistake.

 

       assign ram_address = (request == 1'b1)? wb_addr_i[14:2]:13'b0;

       assign ram_data    = (request == 1'b1)? wb_data_i:32'b0;

       assign ram_byteena = (request == 1'b1)? wb_sel_i:4'b0;

       assign ram_wren    = (request == 1'b1)? wb_we_i:1'b0;

      

       // [14:2] of 32-bit address input is connected to ram0,

       // for the reason of 4 byte alignment of OR1200 processor.

       // 8-bit char or 16-bit short int accesses are accomplished

       // with the help of wb_sel_i (byteena) signal.

 

altera_ram ram0(

       .aclr(rst_i),

       .address(ram_address),

       .byteena(ram_byteena),

       .clock(clk_i),

       .data(ram_data),

       .wren(ram_wren),

      

       .q(wb_data_o)

       );

      

       // get the rising edge of request signal

       always @ (posedge clk_i)

       begin

               if(rst_i == 1)

                       request_delay <= 0;

               else

                       request_delay <= request;

       end

      

       assign request_rising_edge = (request_delay ^ request) & request;

 

       // generate a 1 cycle acknowledgement for each request rising edge

       always @ (posedge clk_i)

       begin

               if (rst_i == 1)

                       ram_ack <= 0;

               else if (request_rising_edge == 1)

                       ram_ack <= 1;

               else

                       ram_ack <= 0;

       end

 

       // register wb_ack output, because onchip ram0 uses registered output

       always @ (posedge clk_i)

       begin

               if (rst_i == 1)

                       wb_ack_o <= 0;

               //else if(request == 1'b1)

               //      wb_ack_o <= 1;

               else

                 wb_ack_o <= ram_ack;

       end

endmodule

 

后记:其中这句

assign request_rising_edge = (request_delay ^ request) & request;

一开始把&错写成|了,浪费了时间。

wishbone masterBFM文件 wb_master_model.v文件

/////////////////////////////////////////////////////////////////////

////                                                             ////

////  WISHBONE Master Model                                      ////

////                                                             ////

////                                                             ////

////  Author: Rudolf Usselmann                                   ////

////          rudi@asics.ws                                      ////

////                                                             ////

/////////////////////////////////////////////////////////////////////

////                                                             ////

//// Copyright (C) 2001 Rudolf Usselmann                         ////

////                    rudi@asics.ws                            ////

////                                                             ////

//// This source file may be used and distributed without        ////

//// restriction provided that this copyright statement is not   ////

//// removed from the file and that any derivative work contains ////

//// the original copyright notice and the associated disclaimer.////

////                                                             ////

////     THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     ////

//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   ////

//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   ////

//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      ////

//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         ////

//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    ////

//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   ////

//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        ////

//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  ////

//// LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  ////

//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  ////

//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         ////

//// POSSIBILITY OF SUCH DAMAGE.                                 ////

////                                                             ////

/////////////////////////////////////////////////////////////////////

 

//  CVS Log

//

//  $Id: wb_mast_model.v,v 1.1.1.1 2001/07/26 08:22:36 rudi Exp $

//

//  $Date: 2001/07/26 08:22:36 $

//  $Revision: 1.1.1.1 $

//  $Author: rudi $

//  $Locker:  $

//  $State: Exp $

//

// Change History:

//               $Log: wb_mast_model.v,v $

//               Revision 1.1.1.1  2001/07/26 08:22:36  rudi

//               WISHBONE Simulation Models

//

//

//

//

//

//                       

 

/*

 

task mem_fill;

 

- Fills local burst read (rd_buf[]) and write(wr_buf[]) buffers with random values.

 

 

task wb_wr1( 32 bit address, 4 bit byte select, 32 bit write data);

 

- Performs a single WISHBONE write

 

 

task wb_wr4( 32 bit address, 4 bit byte select, integer delay,

       32 bit data 1, 32 bit data 2, 32 bit data 3, 32 bit data 4);

 

- Performs 4 consecutive WISHBONE writes

- Strobe is deasserted between writes for 'delay' number of cycles

  (This simulates wait state insertion ...)

 

 

task wb_wr_mult( 32 bit address, 4 bit byte select, integer delay,

       integer count);

 

- Simular to wb_wr4, except it pwrforms "count" number of write cycles.

  The data is taken from the internal wr_bub[] memory.

- Strobe is deasserted between writes for 'delay' number of cycles

  (This simulates wait state insertion ...)

 

 

task wb_rmw( 32 bit address, 4 bit byte select, integer delay,

       integer rcount, integer wcount);

 

- This task performs "rcount" read cycles, followed by wcount write cycles.

- read data is placed in to the internal rd_buf[] memory, write data is

  taken from the internal wr_buf[] memory.

- Strobe is deasserted between writes for 'delay' number of cycles

  (This simulates wait state insertion ...)

 

task wb_wmr( 32 bit address, 4 bit byte select, integer delay,

       integer rcount, integer wcount);

 

- This task performs "wcount" write cycles, followed by "rcount" read cycles.

- read data is placed in to the internal rd_buf[] memory, write data is

  taken from the internal wr_buf[] memory.

- Strobe is deasserted between writes for 'delay' number of cycles

  (This simulates wait state insertion ...)

 

task wb_rd1( 32 bit address, 4 bit byte select, 32 bit read data);

 

- Performs a single WISHBONE write

 

 

task wb_rd4( 32 bit address, 4 bit byte select, integer delay,

       32 bit data 1, 32 bit data 2, 32 bit data 3, 32 bit data 4);

 

- Performs 4 consecutive WISHBONE reads

- Strobe is deasserted between reads for 'delay' number of cycles

  (This simulates wait state insertion ...)

 

 

task wb_rd_mult( 32 bit address, 4 bit byte select, integer delay,

       integer count);

 

- Simular to wb_rd4, except it pwrforms "count" number of read cycles.

  The data is read in to the internal rd_buf[] memory.

- Strobe is deasserted between reads for 'delay' number of cycles

  (This simulates wait state insertion ...)

 

*/

 

 

//`include "wb_model_defines.v"

`timescale 1ns/100ps

 

module wb_mast(clk, rst, adr, din, dout, cyc, stb, sel, we, ack, err, rty);

 

input          clk, rst;

output [31:0]  adr;

input  [31:0]  din;

output [31:0]  dout;

output         cyc, stb;

output [3:0]   sel;

output         we;

input          ack, err, rty;

 

////////////////////////////////////////////////////////////////////

//

// Local Wires

//

 

parameter mem_size = 4096;

 

reg    [31:0]  adr;

reg    [31:0]  dout;

reg            cyc, stb;

reg    [3:0]   sel;

reg            we;

 

reg    [31:0]  rd_mem[mem_size:0];

reg    [31:0]  wr_mem[mem_size:0];

integer                rd_cnt;

integer                wr_cnt;

 

////////////////////////////////////////////////////////////////////

//

// Memory Logic

//

 

initial

   begin

       adr = 32'hxxxx_xxxx;

       dout = 32'hxxxx_xxxx;

       cyc = 0;

       stb = 0;

       sel = 4'hx;

       we = 1'hx;

       rd_cnt = 0;

       wr_cnt = 0;

       #1;

       $display("\nINFO: WISHBONE MASTER MODEL INSTANTIATED (%m)\n");

   end

 

 

task mem_fill;

 

integer n;

begin

rd_cnt = 0;

wr_cnt = 0;

for(n=0;n<mem_size;n=n+1)

   begin

       rd_mem[n] = $random;

       wr_mem[n] = $random;

   end

end

endtask

 

////////////////////////////////////////////////////////////////////

//

// Write 1 Word Task

//

 

task wb_wr1;

input  [31:0]  a;

input  [3:0]   s;

input  [31:0]  d;

 

begin

 

@(posedge clk);

#1;

adr = a;

dout = d;

cyc = 1;

stb = 1;

we=1;

sel = s;

 

@(posedge clk);

while(~ack & ~err)     @(posedge clk);

#1;

cyc=0;

stb=0;

adr = 32'hxxxx_xxxx;

dout = 32'hxxxx_xxxx;

we = 1'hx;

sel = 4'hx;

 

end

endtask

 

////////////////////////////////////////////////////////////////////

//

// Write 4 Words Task

//

 

task wb_wr4;

input  [31:0]  a;

input  [3:0]   s;

input          delay;

input  [31:0]  d1;

input  [31:0]  d2;

input  [31:0]  d3;

input  [31:0]  d4;

 

integer                delay;

 

begin

 

@(posedge clk);

#1;

cyc = 1;

sel = s;

 

repeat(delay)

   begin

       @(posedge clk);

       #1;

   end

adr = a;

dout = d1;

stb = 1;

we=1;

while(~ack & ~err)     @(posedge clk);

#2;

stb=0;

we=1'bx;

dout = 32'hxxxx_xxxx;

adr = 32'hxxxx_xxxx;

 

repeat(delay)

   begin

       @(posedge clk);

       #1;

   end

stb=1;

adr = a+4;

dout = d2;

we=1;

@(posedge clk);

while(~ack & ~err)     @(posedge clk);

#2;

stb=0;

we=1'bx;

dout = 32'hxxxx_xxxx;

adr = 32'hxxxx_xxxx;

 

repeat(delay)

   begin

       @(posedge clk);

       #1;

   end

stb=1;

adr = a+8;

dout = d3;

we=1;

@(posedge clk);

while(~ack & ~err)     @(posedge clk);

#2;

stb=0;

we=1'bx;

dout = 32'hxxxx_xxxx;

adr = 32'hxxxx_xxxx;

 

repeat(delay)

   begin

       @(posedge clk);

       #1;

   end

stb=1;

adr = a+12;

dout = d4;

we=1;

@(posedge clk);

while(~ack & ~err)     @(posedge clk);

#1;

stb=0;

cyc=0;

 

adr = 32'hxxxx_xxxx;

dout = 32'hxxxx_xxxx;

we = 1'hx;

sel = 4'hx;

 

end

endtask

 

 

task wb_wr_mult;

input  [31:0]  a;

input  [3:0]   s;

input          delay;

input          count;

 

integer                delay;

integer                count;

integer                n;

 

begin

 

@(posedge clk);

#1;

cyc = 1;

 

for(n=0;n<count;n=n+1)

   begin

       repeat(delay)

          begin

               @(posedge clk);

               #1;

          end

       adr = a + (n*4);

       dout = wr_mem[n + wr_cnt];

       stb = 1;

       we=1;

       sel = s;

       if(n!=0)        @(posedge clk);

       while(~ack & ~err)      @(posedge clk);

       #2;

       stb=0;

       we=1'bx;

       sel = 4'hx;

       dout = 32'hxxxx_xxxx;

       adr = 32'hxxxx_xxxx;

   end

 

cyc=0;

adr = 32'hxxxx_xxxx;

 

wr_cnt = wr_cnt + count;

end

endtask

 

 

task wb_rmw;

input  [31:0]  a;

input  [3:0]   s;

input          delay;

input          rcount;

input          wcount;

 

integer                delay;

integer                rcount;

integer                wcount;

integer                n;

 

begin

 

@(posedge clk);

#1;

cyc = 1;

we = 1'bx;

sel = 4'hx;

adr = 32'hxxxx_xxxx;

repeat(delay)  @(posedge clk);

#1;

we = 0;

sel = s;

 

for(n=0;n<rcount-1;n=n+1)

   begin

       adr = a + (n*4);

       stb = 1;

       while(~ack & ~err)      @(posedge clk);

       rd_mem[n + rd_cnt] = din;

       //$display("Rd Mem[%0d]: %h", (n + rd_cnt), rd_mem[n + rd_cnt] );

       #2;

       stb=0;

       we = 1'hx;

       sel = 4'hx;

       adr = 32'hxxxx_xxxx;

       repeat(delay)

          begin

               @(posedge clk);

               #1;

          end

       we = 0;

       sel = s;

   end

 

adr = a+(n*4);

stb = 1;

@(posedge clk);

while(~ack & ~err)     @(posedge clk);

rd_mem[n + rd_cnt] = din;

//$display("Rd Mem[%0d]: %h", (n + rd_cnt), rd_mem[n + rd_cnt] );

#1;

stb=0;

we = 1'hx;

sel = 4'hx;

adr = 32'hxxxx_xxxx;

 

rd_cnt = rd_cnt + rcount;

 

for(n=0;n<wcount;n=n+1)

   begin

       repeat(delay)

          begin

               @(posedge clk);

               #1;

          end

       adr = a + (n*4);

       dout = wr_mem[n + wr_cnt];

       stb = 1;

       we=1;

       sel = s;

       @(posedge clk);

       while(~ack & ~err)      @(posedge clk);

       #2;

       stb=0;

       we=1'bx;

       sel = 4'hx;

       dout = 32'hxxxx_xxxx;

       adr = 32'hxxxx_xxxx;

   end

 

cyc=0;

stb=0;

we=1'bx;

sel = 4'hx;

dout = 32'hxxxx_xxxx;

adr = 32'hxxxx_xxxx;

 

wr_cnt = wr_cnt + wcount;

end

endtask

 

 

 

task wb_wmr;

input  [31:0]  a;

input  [3:0]   s;

input          delay;

input          rcount;

input          wcount;

 

integer                delay;

integer                rcount;

integer                wcount;

integer                n;

 

begin

 

@(posedge clk);

#1;

cyc = 1;

we = 1'bx;

sel = 4'hx;

sel = s;

 

for(n=0;n<wcount;n=n+1)

   begin

       repeat(delay)

          begin

               @(posedge clk);

               #1;

          end

       adr = a + (n*4);

       dout = wr_mem[n + wr_cnt];

       stb = 1;

       we=1;

       sel = s;

       @(posedge clk);

       while(~ack & ~err)      @(posedge clk);

       #2;

       stb=0;

       we=1'bx;

       sel = 4'hx;

       dout = 32'hxxxx_xxxx;

       adr = 32'hxxxx_xxxx;

   end

 

wr_cnt = wr_cnt + wcount;

stb=0;

repeat(delay)  @(posedge clk);

#1;

 

sel = s;

we = 0;

for(n=0;n<rcount-1;n=n+1)

   begin

       adr = a + (n*4);

       stb = 1;

       while(~ack & ~err)      @(posedge clk);

       rd_mem[n + rd_cnt] = din;

       //$display("Rd Mem[%0d]: %h", (n + rd_cnt), rd_mem[n + rd_cnt] );

       #2;

       stb=0;

       we = 1'hx;

       sel = 4'hx;

       adr = 32'hxxxx_xxxx;

       repeat(delay)

          begin

               @(posedge clk);

               #1;

          end

       we = 0;

       sel = s;

   end

 

adr = a+(n*4);

stb = 1;

@(posedge clk);

while(~ack & ~err)     @(posedge clk);

rd_mem[n + rd_cnt] = din;

rd_cnt = rd_cnt + rcount;

//$display("Rd Mem[%0d]: %h", (n + rd_cnt), rd_mem[n + rd_cnt] );

#1;

 

cyc = 0;

stb = 0;

we  = 1'hx;

sel = 4'hx;

adr = 32'hxxxx_xxxx;

 

end

endtask

 

 

////////////////////////////////////////////////////////////////////

//

// Read 1 Word Task

//

 

task wb_rd1;

input  [31:0]  a;

input  [3:0]   s;

output [31:0]  d;

 

begin

 

@(posedge clk);

#1;

adr = a;

cyc = 1;

stb = 1;

we  = 0;

sel = s;

 

while(~ack & ~err)     @(posedge clk);

d = din;

#1;

cyc=0;

stb=0;

adr = 32'hxxxx_xxxx;

dout = 32'hxxxx_xxxx;

we = 1'hx;

sel = 4'hx;

 

end

endtask

 

 

////////////////////////////////////////////////////////////////////

//

// Read 4 Words Task

//

 

 

task wb_rd4;

input  [31:0]  a;

input  [3:0]   s;

input          delay;

output [31:0]  d1;

output [31:0]  d2;

output [31:0]  d3;

output [31:0]  d4;

 

integer                delay;

begin

 

@(posedge clk);

#1;

cyc = 1;

we = 0;

sel = s;

repeat(delay)  @(posedge clk);

 

adr = a;

stb = 1;

while(~ack & ~err)     @(posedge clk);

d1 = din;

#2;

stb=0;

we = 1'hx;

sel = 4'hx;

adr = 32'hxxxx_xxxx;

repeat(delay)

   begin

       @(posedge clk);

       #1;

   end

we = 0;

sel = s;

 

adr = a+4;

stb = 1;

@(posedge clk);

while(~ack & ~err)     @(posedge clk);

d2 = din;

#2;

stb=0;

we = 1'hx;

sel = 4'hx;

adr = 32'hxxxx_xxxx;

repeat(delay)

   begin

       @(posedge clk);

       #1;

   end

we = 0;

sel = s;

 

 

adr = a+8;

stb = 1;

@(posedge clk);

while(~ack & ~err)     @(posedge clk);

d3 = din;

#2;

stb=0;

we = 1'hx;

sel = 4'hx;

adr = 32'hxxxx_xxxx;

repeat(delay)

   begin

       @(posedge clk);

       #1;

   end

we = 0;

sel = s;

 

adr = a+12;

stb = 1;

@(posedge clk);

while(~ack & ~err)     @(posedge clk);

d4 = din;

#1;

stb=0;

cyc=0;

we = 1'hx;

sel = 4'hx;

adr = 32'hxxxx_xxxx;

end

endtask

 

 

task wb_rd_mult;

input  [31:0]  a;

input  [3:0]   s;

input          delay;

input          count;

 

integer                delay;

integer                count;

integer                n;

 

begin

 

@(posedge clk);

#1;

cyc = 1;

we = 0;

sel = s;

repeat(delay)  @(posedge clk);

 

for(n=0;n<count-1;n=n+1)

   begin

       adr = a + (n*4);

       stb = 1;

       while(~ack & ~err)      @(posedge clk);

       rd_mem[n + rd_cnt] = din;

       #2;

       stb=0;

       we = 1'hx;

       sel = 4'hx;

       adr = 32'hxxxx_xxxx;

       repeat(delay)

          begin

               @(posedge clk);

               #1;

          end

       we = 0;

       sel = s;

   end

 

adr = a+(n*4);

stb = 1;

@(posedge clk);

while(~ack & ~err)     @(posedge clk);

rd_mem[n + rd_cnt] = din;

#1;

stb=0;

cyc=0;

we = 1'hx;

sel = 4'hx;

adr = 32'hxxxx_xxxx;

 

rd_cnt = rd_cnt + count;

end

endtask

 

endmodule

 

写顶层模块wb_tb,直接从张老师给的例子中拷贝出来的,改了一下wb_tb.v文件

`timescale 1ns/100ps

`define HALF_PERIOD 10

 

module wb_tb;

reg wb_clk;

reg wb_rst;

wire wb_stb;

wire wb_cyc;

wire wb_ack;

wire [3:0] wb_sel;

wire [31:0] wb_dat_to_ram;

wire [31:0] wb_dat_from_ram;

wire [31:0] wb_adr;

wire wb_we;

 

ram0_top ram0_inst(

       .clk_i(wb_clk),

       .rst_i(wb_rst),

       .wb_stb_i(wb_stb),

       .wb_cyc_i(wb_cyc),

       .wb_data_i(wb_dat_to_ram),

       .wb_data_o(wb_dat_from_ram),

       .wb_addr_i(wb_adr),

       .wb_we_i(wb_we),

       .wb_ack_o(wb_ack),

       .wb_sel_i(wb_sel)

);

 

/*

module wb_mast(clk, rst, adr, din, dout, cyc, stb, sel, we, ack, err, rty);

*/

wb_mast wb_mast_inst(

       .clk(wb_clk),

       .rst(wb_rst),

       .adr(wb_adr),

       .din(wb_dat_from_ram),

       .dout(wb_dat_to_ram),

       .cyc(wb_cyc),

       .stb(wb_stb),

       .sel(wb_sel),

       .we(wb_we),

       .ack(wb_ack),

       .err(1'b0),

       .rty(1'b0)

);

 

initial begin

       wb_clk<=0;

end

always@(wb_clk)

begin

       #`HALF_PERIOD wb_clk <= ~wb_clk;

end

 

 

reg [31:0] tmp_dat;

reg [31:0] d0,d1,d2,d3;

initial begin

 

       wb_rst<=1;

       #50 wb_rst<=0;

//write your test here!

       @(posedge wb_clk);

wb_mast_inst.wb_wr1(32'h00,4'b1111,32'haa88);

wb_mast_inst.wb_rd1(32'h00,4'b1111,tmp_dat);

$display($time,,"readfrom %x, value = %x\n",32'h00,tmp_dat);

 

//adr,adr+4,adr+8,adr+12

wb_mast_inst.wb_wr4(32'h00,4'b1111,1,32'h01,32'h02,32'h03,32'h04);

wb_mast_inst.wb_rd4(32'h00,4'b1111,3,d0,d1,d2,d3);

$display($time,,"read4from %x, value = %x , %x , %x , %x\n",32'h05,d0,d1,d2,d3);

 

#100 $stop;

end

 

 

endmodule

 

仿真脚本文件 altera_ram_slave.do文件

vlib work

vmap work work

vlog *.v

vsim -L C:/altera/90/modelsim_ae/altera/verilog/220model -L C:/altera/90/modelsim_ae/altera/verilog/altera_mf work.wb_tb

add wave /wb_clk

add wave /wb_rst

add wave /wb_stb

add wave /wb_cyc

add wave /wb_ack

add wave /wb_sel

add wave -radix hex /wb_dat_to_ram

add wave -radix hex /wb_dat_from_ram

add wave -radix hex /wb_adr

add wave /wb_we

 

add wave -radix hex /wb_tb/ram0_inst/*

 

run -all

dos窗口下切换到工作目录,运行

D:\aemb\or1200_wb_altram\wb_ram>vsim -do altera_ram_slave.do

或者在Modelsim 命令行窗口下换到工作目录,运行

VSIM(paused)>do altera_ram_slave.do

仿真结果

 


 

posted @ 2010-04-23 11:08  任怀鲁  阅读(3136)  评论(1编辑  收藏  举报