//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//// ////
|
//// ////
|
//// File name "pci_behavioral_iack_target" ////
|
//// File name "pci_behavioral_iack_target" ////
|
//// ////
|
//// ////
|
//// 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): ////
|
//// - Miha Dolenc (mihad@opencores.org) ////
|
//// - Miha Dolenc (mihad@opencores.org) ////
|
//// ////
|
//// ////
|
//// ////
|
//// ////
|
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//// ////
|
//// ////
|
//// Copyright (C) 2000 Miha Dolenc, mihad@opencores.org ////
|
//// Copyright (C) 2000 Miha Dolenc, mihad@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.2 2002/03/06 09:10:56 mihad
|
// Revision 1.2 2002/03/06 09:10:56 mihad
|
// Added missing include statements
|
// Added missing include statements
|
//
|
//
|
// Revision 1.1 2002/02/01 15:07:51 mihad
|
// Revision 1.1 2002/02/01 15:07:51 mihad
|
// *** empty log message ***
|
// *** empty log message ***
|
//
|
//
|
|
|
`include "pci_constants.v"
|
`include "pci_constants.v"
|
`include "timescale.v"
|
`include "timescale.v"
|
`include "bus_commands.v"
|
`include "bus_commands.v"
|
|
|
// module is provided just as target for responding to interrupt acknowledge commands, because
|
// module is provided just as target for responding to interrupt acknowledge commands, because
|
// other models don't support this command
|
// other models don't support this command
|
module pci_behavioral_pci2pci_bridge
|
module pci_behavioral_pci2pci_bridge
|
(
|
(
|
CLK,
|
CLK,
|
AD,
|
AD,
|
CBE,
|
CBE,
|
RST,
|
RST,
|
FRAME,
|
FRAME,
|
IRDY,
|
IRDY,
|
DEVSEL,
|
DEVSEL,
|
TRDY,
|
TRDY,
|
STOP,
|
STOP,
|
PAR,
|
PAR,
|
response,
|
response,
|
data_in,
|
data_in,
|
data_out,
|
data_out,
|
devsel_speed,
|
devsel_speed,
|
wait_states,
|
wait_states,
|
bus_number
|
bus_number
|
);
|
);
|
`include "pci_blue_constants.vh"
|
`include "pci_blue_constants.vh"
|
|
|
input CLK ;
|
input CLK ;
|
|
|
inout [31:0] AD ;
|
inout [31:0] AD ;
|
reg [31:0] AD_out ;
|
reg [31:0] AD_out ;
|
reg AD_en ;
|
reg AD_en ;
|
|
|
input [3:0] CBE ;
|
input [3:0] CBE ;
|
input RST ;
|
input RST ;
|
input FRAME ;
|
input FRAME ;
|
input IRDY ;
|
input IRDY ;
|
|
|
output DEVSEL ;
|
output DEVSEL ;
|
reg DEVSEL ;
|
reg DEVSEL ;
|
|
|
output TRDY ;
|
output TRDY ;
|
reg TRDY ;
|
reg TRDY ;
|
|
|
output STOP ;
|
output STOP ;
|
reg STOP ;
|
reg STOP ;
|
|
|
inout PAR ;
|
inout PAR ;
|
reg PAR_out ;
|
reg PAR_out ;
|
reg PAR_en ;
|
reg PAR_en ;
|
|
|
// posible responses:
|
// posible responses:
|
//2'b00 - Normal
|
//2'b00 - Normal
|
//2'b01 - Disconnect With Data
|
//2'b01 - Disconnect With Data
|
//2'b10 - Retry
|
//2'b10 - Retry
|
//2'b11 - Abort
|
//2'b11 - Abort
|
input [1:0] response ;
|
input [1:0] response ;
|
|
|
input [31:0] data_out ;
|
input [31:0] data_out ;
|
output [31:0] data_in ;
|
output [31:0] data_in ;
|
reg [31:0] data_in ;
|
reg [31:0] data_in ;
|
input [1:0] devsel_speed ;
|
input [1:0] devsel_speed ;
|
input [3:0] wait_states ;
|
input [3:0] wait_states ;
|
input [7:0] bus_number ;
|
input [7:0] bus_number ;
|
|
|
reg frame_prev ;
|
reg frame_prev ;
|
reg read0_write1 ;
|
reg read0_write1 ;
|
|
|
reg generate_par ;
|
reg generate_par ;
|
reg busy ;
|
reg busy ;
|
|
|
assign PAR = PAR_en ? PAR_out : 1'bz ;
|
assign PAR = PAR_en ? PAR_out : 1'bz ;
|
assign AD = AD_en ? AD_out : 32'hzzzz_zzzz ;
|
assign AD = AD_en ? AD_out : 32'hzzzz_zzzz ;
|
|
|
always@(posedge CLK or negedge RST)
|
always@(posedge CLK or negedge RST)
|
begin
|
begin
|
if ( !RST )
|
if ( !RST )
|
begin
|
begin
|
frame_prev <= #1 1'b1 ;
|
frame_prev <= #1 1'b1 ;
|
AD_out <= #1 32'hDEAD_BEAF ;
|
AD_out <= #1 32'hDEAD_BEAF ;
|
AD_en <= #1 1'b0 ;
|
AD_en <= #1 1'b0 ;
|
DEVSEL <= #1 1'bz ;
|
DEVSEL <= #1 1'bz ;
|
TRDY <= #1 1'bz ;
|
TRDY <= #1 1'bz ;
|
STOP <= #1 1'bz ;
|
STOP <= #1 1'bz ;
|
PAR_out <= #1 1'b0 ;
|
PAR_out <= #1 1'b0 ;
|
PAR_en <= #1 1'b0 ;
|
PAR_en <= #1 1'b0 ;
|
busy = 1'b0 ;
|
busy = 1'b0 ;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
frame_prev <= #`FF_DELAY FRAME ;
|
frame_prev <= #`FF_DELAY FRAME ;
|
end
|
end
|
end
|
end
|
|
|
always@(posedge CLK)
|
always@(posedge CLK)
|
begin
|
begin
|
if ( RST )
|
if ( RST )
|
begin
|
begin
|
if ( (frame_prev === 1) && (FRAME === 0) && (CBE[3:1] === `BC_CONF_RW) && (AD[1:0] === 2'b01) && (AD[23:16] === bus_number) )
|
if ( (frame_prev === 1) && (FRAME === 0) && (CBE[3:1] === `BC_CONF_RW) && (AD[1:0] === 2'b01) && (AD[23:16] === bus_number) )
|
begin
|
begin
|
read0_write1 = CBE[0] ;
|
read0_write1 = CBE[0] ;
|
busy = 1'b1 ;
|
busy = 1'b1 ;
|
do_reference ;
|
do_reference ;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
if (!busy)
|
if (!busy)
|
begin
|
begin
|
TRDY <= #1 1'bz ;
|
TRDY <= #1 1'bz ;
|
STOP <= #1 1'bz ;
|
STOP <= #1 1'bz ;
|
DEVSEL <= #1 1'bz ;
|
DEVSEL <= #1 1'bz ;
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
task do_reference ;
|
task do_reference ;
|
begin
|
begin
|
assert_devsel ;
|
assert_devsel ;
|
insert_waits_drive_ad_on_read ;
|
insert_waits_drive_ad_on_read ;
|
terminate ;
|
terminate ;
|
busy <= #1 1'b0 ;
|
busy <= #1 1'b0 ;
|
end
|
end
|
endtask // do reference
|
endtask // do reference
|
|
|
task assert_devsel ;
|
task assert_devsel ;
|
reg [1:0] num_of_cyc;
|
reg [1:0] num_of_cyc;
|
begin:main
|
begin:main
|
if (devsel_speed == `Test_Devsel_Fast)
|
if (devsel_speed == `Test_Devsel_Fast)
|
begin
|
begin
|
num_of_cyc = 0 ;
|
num_of_cyc = 0 ;
|
end
|
end
|
|
|
if (devsel_speed == `Test_Devsel_Medium)
|
if (devsel_speed == `Test_Devsel_Medium)
|
begin
|
begin
|
num_of_cyc = 1 ;
|
num_of_cyc = 1 ;
|
end
|
end
|
|
|
if (devsel_speed == `Test_Devsel_Slow)
|
if (devsel_speed == `Test_Devsel_Slow)
|
begin
|
begin
|
num_of_cyc = 2 ;
|
num_of_cyc = 2 ;
|
end
|
end
|
|
|
if (devsel_speed == `Test_Devsel_Subtractive)
|
if (devsel_speed == `Test_Devsel_Subtractive)
|
begin
|
begin
|
num_of_cyc = 3 ;
|
num_of_cyc = 3 ;
|
end
|
end
|
|
|
repeat(num_of_cyc)
|
repeat(num_of_cyc)
|
@(posedge CLK) ;
|
@(posedge CLK) ;
|
|
|
DEVSEL <= #1 1'b0 ;
|
DEVSEL <= #1 1'b0 ;
|
end
|
end
|
endtask // assert_devsel
|
endtask // assert_devsel
|
|
|
task insert_waits_drive_ad_on_read ;
|
task insert_waits_drive_ad_on_read ;
|
reg [3:0] waits_left ;
|
reg [3:0] waits_left ;
|
begin
|
begin
|
if (((devsel_speed == `Test_Devsel_Fast) && (!read0_write1)) || (response == 2'b11))
|
if (((devsel_speed == `Test_Devsel_Fast) && (!read0_write1)) || (response == 2'b11))
|
begin
|
begin
|
TRDY <= #1 1'b1 ;
|
TRDY <= #1 1'b1 ;
|
STOP <= #1 1'b1 ;
|
STOP <= #1 1'b1 ;
|
@(posedge CLK) ;
|
@(posedge CLK) ;
|
if (wait_states > 0)
|
if (wait_states > 0)
|
waits_left = wait_states - 1;
|
waits_left = wait_states - 1;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
waits_left = wait_states ;
|
waits_left = wait_states ;
|
end
|
end
|
|
|
if (!read0_write1)
|
if (!read0_write1)
|
AD_en <= #1 1'b1 ;
|
AD_en <= #1 1'b1 ;
|
|
|
while (waits_left > 0)
|
while (waits_left > 0)
|
begin
|
begin
|
TRDY <= #1 1'b1 ;
|
TRDY <= #1 1'b1 ;
|
STOP <= #1 1'b1 ;
|
STOP <= #1 1'b1 ;
|
@(posedge CLK) ;
|
@(posedge CLK) ;
|
waits_left = waits_left - 1 ;
|
waits_left = waits_left - 1 ;
|
end
|
end
|
end
|
end
|
endtask // insert_waits_drive_ad_on_read
|
endtask // insert_waits_drive_ad_on_read
|
|
|
task terminate ;
|
task terminate ;
|
begin
|
begin
|
|
|
if (response)
|
if (response)
|
begin
|
begin
|
STOP <= #1 1'b0 ;
|
STOP <= #1 1'b0 ;
|
end
|
end
|
|
|
if (response == 2'b11)
|
if (response == 2'b11)
|
DEVSEL <= #1 1'b1 ;
|
DEVSEL <= #1 1'b1 ;
|
|
|
if (!response[1])
|
if (!response[1])
|
begin
|
begin
|
TRDY <= #1 1'b0 ;
|
TRDY <= #1 1'b0 ;
|
if (!read0_write1)
|
if (!read0_write1)
|
begin
|
begin
|
if (!CBE[3])
|
if (!CBE[3])
|
AD_out[31:24] <= #1 data_out[31:24] ;
|
AD_out[31:24] <= #1 data_out[31:24] ;
|
|
|
if (!CBE[2])
|
if (!CBE[2])
|
AD_out[23:16] <= #1 data_out[23:16] ;
|
AD_out[23:16] <= #1 data_out[23:16] ;
|
|
|
if (!CBE[1])
|
if (!CBE[1])
|
AD_out[15:8] <= #1 data_out[15:8] ;
|
AD_out[15:8] <= #1 data_out[15:8] ;
|
|
|
if (!CBE[0])
|
if (!CBE[0])
|
AD_out[7:0] <= #1 data_out[7:0] ;
|
AD_out[7:0] <= #1 data_out[7:0] ;
|
end
|
end
|
end
|
end
|
|
|
@(posedge CLK) ;
|
@(posedge CLK) ;
|
while (IRDY !== 0)
|
while (IRDY !== 0)
|
@(posedge CLK) ;
|
@(posedge CLK) ;
|
|
|
if (read0_write1)
|
if (read0_write1)
|
begin
|
begin
|
if (!CBE[3])
|
if (!CBE[3])
|
data_in[31:24] = AD[31:24] ;
|
data_in[31:24] = AD[31:24] ;
|
else
|
else
|
data_in[31:24] = 8'hDE ;
|
data_in[31:24] = 8'hDE ;
|
|
|
if (!CBE[2])
|
if (!CBE[2])
|
data_in[23:16] = AD[23:16] ;
|
data_in[23:16] = AD[23:16] ;
|
else
|
else
|
data_in[23:16] = 8'hAD ;
|
data_in[23:16] = 8'hAD ;
|
|
|
if (!CBE[1])
|
if (!CBE[1])
|
data_in[15:8] = AD[15:8] ;
|
data_in[15:8] = AD[15:8] ;
|
else
|
else
|
data_in[15:8] = 8'hBE ;
|
data_in[15:8] = 8'hBE ;
|
|
|
if (!CBE[0])
|
if (!CBE[0])
|
data_in[7:0] = AD[7:0] ;
|
data_in[7:0] = AD[7:0] ;
|
else
|
else
|
data_in[7:0] = 8'hAF ;
|
data_in[7:0] = 8'hAF ;
|
end
|
end
|
|
|
TRDY <= #1 1'b1 ;
|
TRDY <= #1 1'b1 ;
|
|
|
while (FRAME !== 1)
|
while (FRAME !== 1)
|
begin
|
begin
|
STOP <= #1 1'b0 ;
|
STOP <= #1 1'b0 ;
|
@(posedge CLK) ;
|
@(posedge CLK) ;
|
end
|
end
|
|
|
DEVSEL <= #1 1'b1 ;
|
DEVSEL <= #1 1'b1 ;
|
STOP <= #1 1'b1 ;
|
STOP <= #1 1'b1 ;
|
AD_en <= #1 1'b0 ;
|
AD_en <= #1 1'b0 ;
|
AD_out <= #1 32'hDEAD_BEAF ;
|
AD_out <= #1 32'hDEAD_BEAF ;
|
end
|
end
|
endtask // terminate ;
|
endtask // terminate ;
|
|
|
always@(posedge CLK)
|
always@(posedge CLK)
|
begin
|
begin
|
if (RST)
|
if (RST)
|
begin
|
begin
|
PAR_en <= #1 AD_en ;
|
PAR_en <= #1 AD_en ;
|
PAR_out <= #1 (^AD) ^ (^CBE) ;
|
PAR_out <= #1 (^AD) ^ (^CBE) ;
|
end
|
end
|
end
|
end
|
|
|
endmodule
|
endmodule
|
|
|