//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//// ////
|
//// ////
|
//// File name: wb_slave_behavioral.v ////
|
//// File name: wb_slave_behavioral.v ////
|
//// ////
|
//// ////
|
//// This file is part of the "PCI bridge" project ////
|
//// This file is part of the "PCI bridge" project ////
|
//// http://www.opencores.org/cores/pci/ ////
|
//// http://www.opencores.org/cores/pci/ ////
|
//// ////
|
//// ////
|
//// Author(s): ////
|
//// Author(s): ////
|
//// - Tadej Markovic, tadej@opencores.org ////
|
//// - Tadej Markovic, tadej@opencores.org ////
|
//// ////
|
//// ////
|
//// All additional information is avaliable in the README.txt ////
|
//// All additional information is avaliable in the README.txt ////
|
//// file. ////
|
//// file. ////
|
//// ////
|
//// ////
|
//// ////
|
//// ////
|
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//// ////
|
//// ////
|
//// Copyright (C) 2000 Tadej Markovic, tadej@opencores.org ////
|
//// Copyright (C) 2000 Tadej Markovic, tadej@opencores.org ////
|
//// ////
|
//// ////
|
//// This source file may be used and distributed without ////
|
//// This source file may be used and distributed without ////
|
//// restriction provided that this copyright statement is not ////
|
//// restriction provided that this copyright statement is not ////
|
//// removed from the file and that any derivative work contains ////
|
//// removed from the file and that any derivative work contains ////
|
//// the original copyright notice and the associated disclaimer. ////
|
//// the original copyright notice and the associated disclaimer. ////
|
//// ////
|
//// ////
|
//// This source file is free software; you can redistribute it ////
|
//// This source file is free software; you can redistribute it ////
|
//// and/or modify it under the terms of the GNU Lesser General ////
|
//// and/or modify it under the terms of the GNU Lesser General ////
|
//// Public License as published by the Free Software Foundation; ////
|
//// Public License as published by the Free Software Foundation; ////
|
//// either version 2.1 of the License, or (at your option) any ////
|
//// either version 2.1 of the License, or (at your option) any ////
|
//// later version. ////
|
//// later version. ////
|
//// ////
|
//// ////
|
//// This source is distributed in the hope that it will be ////
|
//// This source is distributed in the hope that it will be ////
|
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
//// details. ////
|
//// details. ////
|
//// ////
|
//// ////
|
//// You should have received a copy of the GNU Lesser General ////
|
//// You should have received a copy of the GNU Lesser General ////
|
//// Public License along with this source; if not, download it ////
|
//// Public License along with this source; if not, download it ////
|
//// from http://www.opencores.org/lgpl.shtml ////
|
//// from http://www.opencores.org/lgpl.shtml ////
|
//// ////
|
//// ////
|
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//
|
//
|
// CVS Revision History
|
// CVS Revision History
|
//
|
//
|
// $Log: not supported by cvs2svn $
|
// $Log: not supported by cvs2svn $
|
|
// Revision 1.1 2002/02/01 13:39:43 mihad
|
|
// Initial testbench import. Still under development
|
|
//
|
//
|
//
|
|
|
`include "pci_testbench_defines.v"
|
`include "pci_testbench_defines.v"
|
`include "timescale.v"
|
`include "timescale.v"
|
|
`include "pci_constants.v"
|
module WB_SLAVE_BEHAVIORAL
|
module WB_SLAVE_BEHAVIORAL
|
(
|
(
|
CLK_I,
|
CLK_I,
|
RST_I,
|
RST_I,
|
ACK_O,
|
ACK_O,
|
ADR_I,
|
ADR_I,
|
CYC_I,
|
CYC_I,
|
DAT_O,
|
DAT_O,
|
DAT_I,
|
DAT_I,
|
ERR_O,
|
ERR_O,
|
RTY_O,
|
RTY_O,
|
SEL_I,
|
SEL_I,
|
STB_I,
|
STB_I,
|
WE_I,
|
WE_I,
|
CAB_I
|
CAB_I
|
);
|
);
|
|
|
/*----------------------------------------------------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------------------------------------------------
|
WISHBONE signals
|
WISHBONE signals
|
----------------------------------------------------------------------------------------------------------------------*/
|
----------------------------------------------------------------------------------------------------------------------*/
|
input CLK_I ;
|
input CLK_I ;
|
input RST_I ;
|
input RST_I ;
|
output ACK_O ;
|
output ACK_O ;
|
input `WB_ADDR_TYPE ADR_I ;
|
input `WB_ADDR_TYPE ADR_I ;
|
input CYC_I ;
|
input CYC_I ;
|
output `WB_DATA_TYPE DAT_O ;
|
output `WB_DATA_TYPE DAT_O ;
|
input `WB_DATA_TYPE DAT_I ;
|
input `WB_DATA_TYPE DAT_I ;
|
output ERR_O ;
|
output ERR_O ;
|
output RTY_O ;
|
output RTY_O ;
|
input `WB_SEL_TYPE SEL_I ;
|
input `WB_SEL_TYPE SEL_I ;
|
input STB_I ;
|
input STB_I ;
|
input WE_I ;
|
input WE_I ;
|
input CAB_I ;
|
input CAB_I ;
|
|
|
//reg ACK_O ;
|
//reg ACK_O ;
|
//reg ERR_O ;
|
//reg ERR_O ;
|
//reg RTY_O ;
|
//reg RTY_O ;
|
reg [31:0] DAT_O ;
|
reg [31:0] DAT_O ;
|
|
|
/*----------------------------------------------------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------------------------------------------------
|
Asynchronous dual-port RAM signals for storing and fetching the data
|
Asynchronous dual-port RAM signals for storing and fetching the data
|
----------------------------------------------------------------------------------------------------------------------*/
|
----------------------------------------------------------------------------------------------------------------------*/
|
reg [31:0] wb_memory [0:1023] ; // data for WB memory - 16 LSB addresses are connected
|
reg [31:0] wb_memory [0:1023] ; // data for WB memory - 16 LSB addresses are connected
|
reg [31:0] mem_wr_data_out ;
|
reg [31:0] mem_wr_data_out ;
|
reg [31:0] mem_rd_data_in ;
|
reg [31:0] mem_rd_data_in ;
|
|
|
/*----------------------------------------------------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------------------------------------------------
|
Maximum values for WAIT and RETRY counters and which response !!!
|
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 [2:0] a_e_r_resp ; // tells with which cycle_termination_signal must wb_slave respond !
|
reg wait_cyc ;
|
reg wait_cyc ;
|
reg [7:0] max_retry ;
|
reg [7:0] max_retry ;
|
|
|
// assign registers to default state while in reset
|
// assign registers to default state while in reset
|
always@(RST_I)
|
always@(RST_I)
|
begin
|
begin
|
if (RST_I)
|
if (RST_I)
|
begin
|
begin
|
a_e_r_resp <= 3'b000 ; // do not respond
|
a_e_r_resp <= 3'b000 ; // do not respond
|
wait_cyc <= 1'b0 ; // no wait cycles
|
wait_cyc <= 1'b0 ; // no wait cycles
|
max_retry <= 8'h0 ; // no retries
|
max_retry <= 8'h0 ; // no retries
|
end
|
end
|
end //reset
|
end //reset
|
|
|
task cycle_response ;
|
task cycle_response ;
|
input [2:0] ack_err_rty_resp ; // acknowledge, error or retry response input flags
|
input [2:0] ack_err_rty_resp ; // acknowledge, error or retry response input flags
|
input wait_cycles ; // if wait cycles before each data termination cycle (ack, err or rty)
|
input 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
|
input [7:0] retry_cycles ; // noumber of retry cycles before acknowledge cycle
|
begin
|
begin
|
// assign values
|
// assign values
|
a_e_r_resp <= #1 ack_err_rty_resp ;
|
a_e_r_resp <= #1 ack_err_rty_resp ;
|
wait_cyc <= #1 wait_cycles ;
|
wait_cyc <= #1 wait_cycles ;
|
max_retry <= #1 retry_cycles ;
|
max_retry <= #1 retry_cycles ;
|
end
|
end
|
endtask // cycle_response
|
endtask // cycle_response
|
|
|
/*----------------------------------------------------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------------------------------------------------
|
Internal signals and logic
|
Internal signals and logic
|
----------------------------------------------------------------------------------------------------------------------*/
|
----------------------------------------------------------------------------------------------------------------------*/
|
reg calc_ack ;
|
reg calc_ack ;
|
reg calc_err ;
|
reg calc_err ;
|
reg calc_rty ;
|
reg calc_rty ;
|
|
|
reg [7:0] retry_cnt ;
|
reg [7:0] retry_cnt ;
|
reg [7:0] retry_num ;
|
reg [7:0] retry_num ;
|
reg retry_expired ;
|
reg retry_expired ;
|
reg retry_rst ;
|
reg retry_rst ;
|
|
|
// RESET retry counter
|
// RESET retry counter
|
always@(posedge RST_I or posedge CLK_I)
|
always@(posedge RST_I or posedge CLK_I)
|
begin
|
begin
|
if (RST_I)
|
if (RST_I)
|
retry_rst <= 1'b1 ;
|
retry_rst <= 1'b1 ;
|
else
|
else
|
retry_rst <= calc_ack || calc_err ;
|
retry_rst <= calc_ack || calc_err ;
|
end
|
end
|
|
|
// Retry counter
|
// Retry counter
|
always@(posedge retry_rst or negedge calc_rty)
|
always@(posedge retry_rst or negedge calc_rty)
|
begin
|
begin
|
if (retry_rst)
|
if (retry_rst)
|
retry_cnt <= #`FF_DELAY 8'h00 ;
|
retry_cnt <= #`FF_DELAY 8'h00 ;
|
else
|
else
|
retry_cnt <= #`FF_DELAY retry_num ;
|
retry_cnt <= #`FF_DELAY retry_num ;
|
end
|
end
|
always@(retry_cnt or max_retry)
|
always@(retry_cnt or max_retry)
|
begin
|
begin
|
if (retry_cnt < max_retry)
|
if (retry_cnt < max_retry)
|
begin
|
begin
|
retry_num = retry_cnt + 1'b1 ;
|
retry_num = retry_cnt + 1'b1 ;
|
retry_expired = #10 1'b0 ;
|
retry_expired = #10 1'b0 ;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
retry_num = retry_cnt ;
|
retry_num = retry_cnt ;
|
retry_expired = #10 1'b1 ;
|
retry_expired = #10 1'b1 ;
|
end
|
end
|
end
|
end
|
|
|
reg [1:0] wait_cnt ;
|
reg [1:0] wait_cnt ;
|
reg [1:0] wait_num ;
|
reg [1:0] wait_num ;
|
reg wait_expired ;
|
reg wait_expired ;
|
reg reset_wait ;
|
reg reset_wait ;
|
|
|
always@(posedge RST_I or posedge CLK_I)
|
always@(posedge RST_I or posedge CLK_I)
|
begin
|
begin
|
if (RST_I)
|
if (RST_I)
|
reset_wait <= #`FF_DELAY 1'b1 ;
|
reset_wait <= #`FF_DELAY 1'b1 ;
|
else
|
else
|
reset_wait <= #`FF_DELAY (wait_expired || ~STB_I) ;
|
reset_wait <= #`FF_DELAY (wait_expired || ~STB_I) ;
|
end
|
end
|
|
|
// Wait counter
|
// Wait counter
|
always@(posedge reset_wait or posedge CLK_I)
|
always@(posedge reset_wait or posedge CLK_I)
|
begin
|
begin
|
if (reset_wait)
|
if (reset_wait)
|
wait_cnt <= #`FF_DELAY 4'h0 ;
|
wait_cnt <= #`FF_DELAY 4'h0 ;
|
else
|
else
|
wait_cnt <= #`FF_DELAY wait_num ;
|
wait_cnt <= #`FF_DELAY wait_num ;
|
end
|
end
|
always@(wait_cnt or wait_cyc or STB_I or a_e_r_resp or retry_expired)
|
always@(wait_cnt or wait_cyc or STB_I or a_e_r_resp or retry_expired)
|
begin
|
begin
|
if ((wait_cyc) && (STB_I))
|
if ((wait_cyc) && (STB_I))
|
begin
|
begin
|
if (wait_cnt < 2'h2)
|
if (wait_cnt < 2'h2)
|
begin
|
begin
|
wait_num = wait_cnt + 1'b1 ;
|
wait_num = wait_cnt + 1'b1 ;
|
wait_expired = 1'b0 ;
|
wait_expired = 1'b0 ;
|
calc_ack = 1'b0 ;
|
calc_ack = 1'b0 ;
|
calc_err = 1'b0 ;
|
calc_err = 1'b0 ;
|
calc_rty = 1'b0 ;
|
calc_rty = 1'b0 ;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
wait_num = wait_cnt ;
|
wait_num = wait_cnt ;
|
wait_expired = 1'b1 ;
|
wait_expired = 1'b1 ;
|
if (a_e_r_resp == 3'b100)
|
if (a_e_r_resp == 3'b100)
|
begin
|
begin
|
calc_ack = 1'b1 ;
|
calc_ack = 1'b1 ;
|
calc_err = 1'b0 ;
|
calc_err = 1'b0 ;
|
calc_rty = 1'b0 ;
|
calc_rty = 1'b0 ;
|
end
|
end
|
else
|
else
|
if (a_e_r_resp == 3'b010)
|
if (a_e_r_resp == 3'b010)
|
begin
|
begin
|
calc_ack = 1'b0 ;
|
calc_ack = 1'b0 ;
|
calc_err = 1'b1 ;
|
calc_err = 1'b1 ;
|
calc_rty = 1'b0 ;
|
calc_rty = 1'b0 ;
|
end
|
end
|
else
|
else
|
if (a_e_r_resp == 3'b001)
|
if (a_e_r_resp == 3'b001)
|
begin
|
begin
|
calc_err = 1'b0 ;
|
calc_err = 1'b0 ;
|
if (retry_expired)
|
if (retry_expired)
|
begin
|
begin
|
calc_ack = 1'b1 ;
|
calc_ack = 1'b1 ;
|
calc_rty = 1'b0 ;
|
calc_rty = 1'b0 ;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
calc_ack = 1'b0 ;
|
calc_ack = 1'b0 ;
|
calc_rty = 1'b1 ;
|
calc_rty = 1'b1 ;
|
end
|
end
|
end
|
end
|
else
|
else
|
begin
|
begin
|
calc_ack = 1'b0 ;
|
calc_ack = 1'b0 ;
|
calc_err = 1'b0 ;
|
calc_err = 1'b0 ;
|
calc_rty = 1'b0 ;
|
calc_rty = 1'b0 ;
|
end
|
end
|
end
|
end
|
end
|
end
|
else
|
else
|
if ((~wait_cyc) && (STB_I))
|
if ((~wait_cyc) && (STB_I))
|
begin
|
begin
|
wait_num = 2'h0 ;
|
wait_num = 2'h0 ;
|
wait_expired = 1'b1 ;
|
wait_expired = 1'b1 ;
|
if (a_e_r_resp == 3'b100)
|
if (a_e_r_resp == 3'b100)
|
begin
|
begin
|
calc_ack = 1'b1 ;
|
calc_ack = 1'b1 ;
|
calc_err = 1'b0 ;
|
calc_err = 1'b0 ;
|
calc_rty = 1'b0 ;
|
calc_rty = 1'b0 ;
|
end
|
end
|
else
|
else
|
if (a_e_r_resp == 3'b010)
|
if (a_e_r_resp == 3'b010)
|
begin
|
begin
|
calc_ack = 1'b0 ;
|
calc_ack = 1'b0 ;
|
calc_err = 1'b1 ;
|
calc_err = 1'b1 ;
|
calc_rty = 1'b0 ;
|
calc_rty = 1'b0 ;
|
end
|
end
|
else
|
else
|
if (a_e_r_resp == 3'b001)
|
if (a_e_r_resp == 3'b001)
|
begin
|
begin
|
calc_err = 1'b0 ;
|
calc_err = 1'b0 ;
|
if (retry_expired)
|
if (retry_expired)
|
begin
|
begin
|
calc_ack = 1'b1 ;
|
calc_ack = 1'b1 ;
|
calc_rty = 1'b0 ;
|
calc_rty = 1'b0 ;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
calc_ack = 1'b0 ;
|
calc_ack = 1'b0 ;
|
calc_rty = 1'b1 ;
|
calc_rty = 1'b1 ;
|
end
|
end
|
end
|
end
|
else
|
else
|
begin
|
begin
|
calc_ack = 1'b0 ;
|
calc_ack = 1'b0 ;
|
calc_err = 1'b0 ;
|
calc_err = 1'b0 ;
|
calc_rty = 1'b0 ;
|
calc_rty = 1'b0 ;
|
end
|
end
|
end
|
end
|
else
|
else
|
begin
|
begin
|
wait_num = 2'h0 ;
|
wait_num = 2'h0 ;
|
wait_expired = 1'b0 ;
|
wait_expired = 1'b0 ;
|
calc_ack = 1'b0 ;
|
calc_ack = 1'b0 ;
|
calc_err = 1'b0 ;
|
calc_err = 1'b0 ;
|
calc_rty = 1'b0 ;
|
calc_rty = 1'b0 ;
|
end
|
end
|
end
|
end
|
|
|
wire rd_sel = (CYC_I && STB_I && ~WE_I) ;
|
wire rd_sel = (CYC_I && STB_I && ~WE_I) ;
|
wire wr_sel = (CYC_I && STB_I && WE_I) ;
|
wire wr_sel = (CYC_I && STB_I && WE_I) ;
|
|
|
// Generate cycle termination signals
|
// Generate cycle termination signals
|
assign ACK_O = calc_ack && STB_I ;
|
assign ACK_O = calc_ack && STB_I ;
|
assign ERR_O = calc_err && STB_I ;
|
assign ERR_O = calc_err && STB_I ;
|
assign RTY_O = calc_rty && STB_I ;
|
assign RTY_O = calc_rty && STB_I ;
|
|
|
// Assign address to asynchronous memory
|
// Assign address to asynchronous memory
|
always@(ADR_I or RST_I)
|
always@(ADR_I or RST_I)
|
begin
|
begin
|
if (RST_I) // this is added because at start of test bench we need address change in order to get data!
|
if (RST_I) // this is added because at start of test bench we need address change in order to get data!
|
mem_rd_data_in = 32'hxxxx_xxxx ;
|
mem_rd_data_in = 32'hxxxx_xxxx ;
|
else
|
else
|
mem_rd_data_in = wb_memory[ADR_I[11:2]] ;
|
mem_rd_data_in = wb_memory[ADR_I[11:2]] ;
|
end
|
end
|
|
|
// assign outputs to unknown state while in reset
|
// assign outputs to unknown state while in reset
|
always@(RST_I)
|
always@(RST_I)
|
begin
|
begin
|
if (RST_I)
|
if (RST_I)
|
begin
|
begin
|
DAT_O <= 32'hxxxx_xxxx ;
|
DAT_O <= 32'hxxxx_xxxx ;
|
end
|
end
|
end //reset
|
end //reset
|
|
|
// Data input/output interface
|
// Data input/output interface
|
always@(rd_sel or wr_sel or mem_rd_data_in or DAT_I or SEL_I or mem_wr_data_out)
|
always@(rd_sel or wr_sel or mem_rd_data_in or DAT_I or SEL_I or mem_wr_data_out)
|
begin
|
begin
|
if (rd_sel)
|
if (rd_sel)
|
begin
|
begin
|
DAT_O = mem_rd_data_in ;
|
DAT_O = mem_rd_data_in ;
|
end
|
end
|
end
|
end
|
always@(posedge CLK_I)
|
always@(posedge CLK_I)
|
begin
|
begin
|
if (wr_sel)
|
if (wr_sel)
|
begin
|
begin
|
mem_wr_data_out = wb_memory[ADR_I[11:2]] ;
|
mem_wr_data_out = wb_memory[ADR_I[11:2]] ;
|
|
|
if ( SEL_I[3] )
|
if ( SEL_I[3] )
|
mem_wr_data_out[31:24] = DAT_I[31:24] ;
|
mem_wr_data_out[31:24] = DAT_I[31:24] ;
|
|
|
if ( SEL_I[2] )
|
if ( SEL_I[2] )
|
mem_wr_data_out[23:16] = DAT_I[23:16] ;
|
mem_wr_data_out[23:16] = DAT_I[23:16] ;
|
|
|
if ( SEL_I[1] )
|
if ( SEL_I[1] )
|
mem_wr_data_out[15: 8] = DAT_I[15: 8] ;
|
mem_wr_data_out[15: 8] = DAT_I[15: 8] ;
|
|
|
if ( SEL_I[0] )
|
if ( SEL_I[0] )
|
mem_wr_data_out[ 7: 0] = DAT_I[ 7: 0] ;
|
mem_wr_data_out[ 7: 0] = DAT_I[ 7: 0] ;
|
|
|
wb_memory[ADR_I[11:2]] <= mem_wr_data_out ;
|
wb_memory[ADR_I[11:2]] <= mem_wr_data_out ;
|
end
|
end
|
end
|
end
|
|
|
endmodule
|
endmodule
|
|
|