URL
https://opencores.org/ocsvn/ethmac/ethmac/trunk
Subversion Repositories ethmac
[/] [ethmac/] [trunk/] [bench/] [verilog/] [wb_slave_behavioral.v] - Rev 346
Compare with Previous | Blame | View Log
////////////////////////////////////////////////////////////////////// //// //// //// File name: wb_slave_behavioral.v //// //// //// //// This file is part of the Ethernet IP core project //// //// http://www.opencores.org/project,ethmac //// //// //// //// Author(s): //// //// - Tadej Markovic, tadej@opencores.org //// //// //// //// All additional information is available in the README.txt //// //// file. //// //// //// //// //// ////////////////////////////////////////////////////////////////////// //// //// //// Copyright (C) 2002 Tadej Markovic, tadej@opencores.org //// //// //// //// 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 source file is free software; you can redistribute it //// //// and/or modify it under the terms of the GNU Lesser General //// //// Public License as published by the Free Software Foundation; //// //// either version 2.1 of the License, or (at your option) any //// //// later version. //// //// //// //// This source is distributed in the hope that it will be //// //// useful, but WITHOUT ANY WARRANTY; without even the implied //// //// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// //// PURPOSE. See the GNU Lesser General Public License for more //// //// details. //// //// //// //// You should have received a copy of the GNU Lesser General //// //// Public License along with this source; if not, download it //// //// from http://www.opencores.org/lgpl.shtml //// //// //// ////////////////////////////////////////////////////////////////////// // // CVS Revision History // // $Log: not supported by cvs2svn $ // Revision 1.2 2002/09/13 12:29:14 mohor // Headers changed. // // Revision 1.1 2002/09/13 11:57:21 mohor // New testbench. Thanks to Tadej M - "The Spammer". // // Revision 1.2 2002/03/06 09:10:56 mihad // Added missing include statements // // Revision 1.1 2002/02/01 13:39:43 mihad // Initial testbench import. Still under development // // `include "timescale.v" `include "wb_model_defines.v" module WB_SLAVE_BEHAVIORAL ( CLK_I, RST_I, ACK_O, ADR_I, CYC_I, DAT_O, DAT_I, ERR_O, RTY_O, SEL_I, STB_I, WE_I, CAB_I ); /*------------------------------------------------------------------------------------------------------ WISHBONE signals ------------------------------------------------------------------------------------------------------*/ input CLK_I; input RST_I; output ACK_O; input `WB_ADDR_TYPE ADR_I; input CYC_I; output `WB_DATA_TYPE DAT_O; input `WB_DATA_TYPE DAT_I; output ERR_O; output RTY_O; input `WB_SEL_TYPE SEL_I; input STB_I; input WE_I; input CAB_I; reg `WB_DATA_TYPE DAT_O; /*------------------------------------------------------------------------------------------------------ Asynchronous dual-port RAM signals for storing and fetching the data ------------------------------------------------------------------------------------------------------*/ //reg `WB_DATA_TYPE wb_memory [0:16777215]; // WB memory - 24 addresses connected - 2 LSB not used reg `WB_DATA_TYPE wb_memory [0:1048575]; // WB memory - 20 addresses connected - 2 LSB not used reg `WB_DATA_TYPE mem_wr_data_out; reg `WB_DATA_TYPE mem_rd_data_in; /*------------------------------------------------------------------------------------------------------ Maximum values for WAIT and RETRY counters and which response !!! ------------------------------------------------------------------------------------------------------*/ reg [2:0] a_e_r_resp; // tells with which cycle_termination_signal must wb_slave respond ! reg [3:0] wait_cyc; reg [7:0] max_retry; // assign registers to default state while in reset always@(RST_I) begin if (RST_I) begin a_e_r_resp <= 3'b000; // do not respond wait_cyc <= 4'b0; // no wait cycles max_retry <= 8'h0; // no retries end end //reset task cycle_response; input [2:0] ack_err_rty_resp; // acknowledge, error or retry response input flags input [3:0] wait_cycles; // if wait cycles before each data termination cycle (ack, err or rty) input [7:0] retry_cycles; // noumber of retry cycles before acknowledge cycle begin // assign values a_e_r_resp <= #1 ack_err_rty_resp; wait_cyc <= #1 wait_cycles; max_retry <= #1 retry_cycles; end endtask // cycle_response /*------------------------------------------------------------------------------------------------------ Tasks for writing and reading to and from memory !!! ------------------------------------------------------------------------------------------------------*/ reg `WB_ADDR_TYPE task_wr_adr_i; reg `WB_ADDR_TYPE task_rd_adr_i; reg `WB_DATA_TYPE task_dat_i; reg `WB_DATA_TYPE task_dat_o; reg `WB_SEL_TYPE task_sel_i; reg task_wr_data; reg task_data_written; reg `WB_DATA_TYPE task_mem_wr_data; // write to memory task wr_mem; input `WB_ADDR_TYPE adr_i; input `WB_DATA_TYPE dat_i; input `WB_SEL_TYPE sel_i; begin task_data_written = 0; task_wr_adr_i = adr_i; task_dat_i = dat_i; task_sel_i = sel_i; task_wr_data = 1; wait(task_data_written); task_wr_data = 0; end endtask // read from memory task rd_mem; input `WB_ADDR_TYPE adr_i; output `WB_DATA_TYPE dat_o; input `WB_SEL_TYPE sel_i; begin task_rd_adr_i = adr_i; task_sel_i = sel_i; #1; dat_o = task_dat_o; end endtask /*------------------------------------------------------------------------------------------------------ Internal signals and logic ------------------------------------------------------------------------------------------------------*/ reg calc_ack; reg calc_err; reg calc_rty; reg [7:0] retry_cnt; reg [7:0] retry_num; reg retry_expired; // Retry counter always@(posedge RST_I or posedge CLK_I) begin if (RST_I) retry_cnt <= #1 8'h00; else begin if (calc_ack || calc_err) retry_cnt <= #1 8'h00; else if (calc_rty) retry_cnt <= #1 retry_num; end end always@(retry_cnt or max_retry) begin if (retry_cnt < max_retry) begin retry_num = retry_cnt + 1'b1; retry_expired = 1'b0; end else begin retry_num = retry_cnt; retry_expired = 1'b1; end end reg [3:0] wait_cnt; reg [3:0] wait_num; reg wait_expired; // Wait counter always@(posedge RST_I or posedge CLK_I) begin if (RST_I) wait_cnt <= #1 4'h0; else begin if (wait_expired || ~STB_I) wait_cnt <= #1 4'h0; else wait_cnt <= #1 wait_num; end end always@(wait_cnt or wait_cyc or STB_I or a_e_r_resp or retry_expired) begin if ((wait_cyc > 0) && (STB_I)) begin if (wait_cnt < wait_cyc) // 4'h2) begin wait_num = wait_cnt + 1'b1; wait_expired = 1'b0; calc_ack = 1'b0; calc_err = 1'b0; calc_rty = 1'b0; end else begin wait_num = wait_cnt; wait_expired = 1'b1; if (a_e_r_resp == 3'b100) begin calc_ack = 1'b1; calc_err = 1'b0; calc_rty = 1'b0; end else if (a_e_r_resp == 3'b010) begin calc_ack = 1'b0; calc_err = 1'b1; calc_rty = 1'b0; end else if (a_e_r_resp == 3'b001) begin calc_err = 1'b0; if (retry_expired) begin calc_ack = 1'b1; calc_rty = 1'b0; end else begin calc_ack = 1'b0; calc_rty = 1'b1; end end else begin calc_ack = 1'b0; calc_err = 1'b0; calc_rty = 1'b0; end end end else if ((wait_cyc == 0) && (STB_I)) begin wait_num = 2'h0; wait_expired = 1'b1; if (a_e_r_resp == 3'b100) begin calc_ack = 1'b1; calc_err = 1'b0; calc_rty = 1'b0; end else if (a_e_r_resp == 3'b010) begin calc_ack = 1'b0; calc_err = 1'b1; calc_rty = 1'b0; end else if (a_e_r_resp == 3'b001) begin calc_err = 1'b0; if (retry_expired) begin calc_ack = 1'b1; calc_rty = 1'b0; end else begin calc_ack = 1'b0; calc_rty = 1'b1; end end else begin calc_ack = 1'b0; calc_err = 1'b0; calc_rty = 1'b0; end end else begin wait_num = 2'h0; wait_expired = 1'b0; calc_ack = 1'b0; calc_err = 1'b0; calc_rty = 1'b0; end end wire rd_sel = (CYC_I && STB_I && ~WE_I); wire wr_sel = (CYC_I && STB_I && WE_I); // Generate cycle termination signals assign ACK_O = calc_ack && STB_I; assign ERR_O = calc_err && STB_I; assign RTY_O = calc_rty && STB_I; // Assign address to asynchronous memory always@(RST_I or ADR_I) begin if (RST_I) // this is added because at start of test bench we need address change in order to get data! begin #1 mem_rd_data_in = `WB_DATA_WIDTH'hxxxx_xxxx; end else begin // #1 mem_rd_data_in = wb_memory[ADR_I[25:2]]; #1 mem_rd_data_in = wb_memory[ADR_I[21:2]]; end end // Data input/output interface always@(rd_sel or mem_rd_data_in or RST_I) begin if (RST_I) DAT_O <=#1 `WB_DATA_WIDTH'hxxxx_xxxx; // assign outputs to unknown state while in reset else if (rd_sel) DAT_O <=#1 mem_rd_data_in; else DAT_O <=#1 `WB_DATA_WIDTH'hxxxx_xxxx; end always@(RST_I or task_rd_adr_i) begin if (RST_I) task_dat_o = `WB_DATA_WIDTH'hxxxx_xxxx; else task_dat_o = wb_memory[task_rd_adr_i[21:2]]; end always@(CLK_I or wr_sel or task_wr_data or ADR_I or task_wr_adr_i or mem_wr_data_out or DAT_I or task_mem_wr_data or task_dat_i or SEL_I or task_sel_i) begin if (task_wr_data) begin task_mem_wr_data = wb_memory[task_wr_adr_i[21:2]]; if (task_sel_i[3]) task_mem_wr_data[31:24] = task_dat_i[31:24]; if (task_sel_i[2]) task_mem_wr_data[23:16] = task_dat_i[23:16]; if (task_sel_i[1]) task_mem_wr_data[15: 8] = task_dat_i[15: 8]; if (task_sel_i[0]) task_mem_wr_data[ 7: 0] = task_dat_i[ 7: 0]; wb_memory[task_wr_adr_i[21:2]] = task_mem_wr_data; // write data task_data_written = 1; end else if (wr_sel && ~CLK_I) begin // mem_wr_data_out = wb_memory[ADR_I[25:2]]; // if no SEL_I is active, old value will be written mem_wr_data_out = wb_memory[ADR_I[21:2]]; // if no SEL_I is active, old value will be written if (SEL_I[3]) mem_wr_data_out[31:24] = DAT_I[31:24]; if (SEL_I[2]) mem_wr_data_out[23:16] = DAT_I[23:16]; if (SEL_I[1]) mem_wr_data_out[15: 8] = DAT_I[15: 8]; if (SEL_I[0]) mem_wr_data_out[ 7: 0] = DAT_I[ 7: 0]; // wb_memory[ADR_I[25:2]] <= mem_wr_data_out; // write data wb_memory[ADR_I[21:2]] = mem_wr_data_out; // write data end end endmodule