?? pci_mast.tf
字號:
data_array[0] = data[31:0];
data_array[1] = data[63:32];
be_array[0] = be[3:0];
be_array[1] = be[7:4];
if (force_32) m64_local = 1'b0;
else m64_local = m64bit;
got_devsel = 1'b1;
array_position = 0;
dwords_transmitted = 0;
while (got_devsel & (dwords_transmitted == 0)) begin
dwords_transmitted = 0;
target_access_one_frame(address, data, command, be, addr_parity,
data_parity, dword_count, initial_data_delay,
next_data_delay, m64_local & (address[2:0]==0) & (dword_count[0]==0), array_position,
pass_fail, 1'b1, temp, 1'b0);
//$display("Transmitted %d dwords before %0t",dwords_transmitted, $time);
array_position = array_position + dwords_transmitted;
address = address + dwords_transmitted*4;
dword_count = dword_count - dwords_transmitted;
//$display("%d dwords left to go before %0t",dword_count, $time);
end
end
endtask
/*
task target_access(address, data, command, be, addr_parity,
data_parity, dword_count, initial_data_delay,
next_data_delay, m64bit);
*/
task target_access;
input [63:0] address;
input [63:0] data;
input [3:0] command;
input [7:0] be;
input addr_parity;
input data_parity;
input [31:0] dword_count;
input [3:0] initial_data_delay;
input [3:0] next_data_delay;
input m64bit;
reg [RW_BUFF_SIZE_ADDR_BITS:0] array_position;
reg pass_fail;
reg m64_local;
reg [63:0] temp;
begin
pass_fail = 1'b1; // we pass unless something doesn't compare and sets this to 0
if ( dword_count < 1 ) begin
$display("Error: time=%d, target_access requested with a transfer count of 0",$time);
repeat (10) @(posedge pci_clk);
$finish;
end
if (dword_count <= 2) begin
data_array[0] = data[31:0];
data_array[1] = data[63:32];
be_array[0] = be[3:0];
be_array[1] = be[7:4];
end
if (force_32) m64_local = 1'b0;
else m64_local = m64bit;
got_devsel = 1'b1;
array_position = 0;
while (got_devsel & (dword_count>0) ) begin
dwords_transmitted = 0;
target_access_one_frame(address, data, command, be, addr_parity,
data_parity, dword_count, initial_data_delay,
next_data_delay, m64_local & (address[2:0]==0) & (dword_count[0]==0), array_position,
pass_fail, 1'b1, temp, 1'b0);
//$display("Transmitted %d dwords before %0t",dwords_transmitted, $time);
array_position = array_position + dwords_transmitted;
address = address + dwords_transmitted*4;
dword_count = dword_count - dwords_transmitted;
//$display("%d dwords left to go before %0t",dword_count, $time);
end
end
endtask
wire bus_idle_ready_to_start;
assign bus_idle_ready_to_start =
((~irdy) & (~frame))
| (irdy & (trdy | stop) & (~frame) & irdy_oe);
reg [63:0] data_read;
/*
task target_access_one_frame(address, data, command, be, addr_parity,
data_parity, burst_count, initial_data_delay,
next_data_delay, m64bit, initial_array_position,
pass_fail, quiet, last_data, hold_req);
*/
task target_access_one_frame;
input [63:0] address;
input [63:0] data;
input [3:0] command;
input [7:0] be;
input addr_parity;
input data_parity;
input [31:0] burst_count;
input [3:0] initial_data_delay;
input [3:0] next_data_delay;
input m64bit;
input [RW_BUFF_SIZE_ADDR_BITS:0] initial_array_position;
inout pass_fail;
input quiet;
output [63:0] last_data;
input hold_req;
integer index;
begin
if ( burst_count < 1 ) begin
$display("Error: time=%d, target_access requested with a transfer count of 0",$time);
repeat (10) @(posedge pci_clk);
$finish;
end
req_reg <= 1'b1;
//Get the grant before commencing
if ( (~(req_reg & gnt)) | ~bus_idle_ready_to_start ) begin //request the grant if we aren't already, even if we already have it!
req_reg <= 1'b1;
@(posedge pci_clk); //Wait a clock to avoid arbiter confusion.
while ( (~gnt) | (~bus_idle_ready_to_start)) begin
@(posedge pci_clk);
end
end
irdy_reg <= 0;
//Initialize the delay and counter variables
timeleft = initial_data_delay + 1;
countleft = burst_count;
timeout = 16'h0;
got_devsel = 1'b0;
quit = 1'b0;
//From now on, everything will be treated as a burst!
burst = 1;
//assert frame
frame_oe <= 1'b1;
frame_reg <= 1'b1;
//assert idsel (???)
idsel_oe <= 1'b1;
if(command == `COMMAND_CONFIG_READ || command == `COMMAND_CONFIG_WRITE)
idsel_reg <= 1'b1;
else
idsel_reg <= 1'b0;
//Enable the address and command busses
pci_ad_oe <= 1'b1; // PCI ad bus output enable
pci_cbe_oe <= 1'b1; // cbe output enable
//Set the 64 bit request line if we are a 64bit master
req64_oe <= m64bit;
//Split address and add a clock cycle if we have a 64 bit address
if((!(address[63:32] == 32'b0)) || fake_a_DAC) // dual address access
begin
pci_ad_reg[63:0] <= address[63:0];
pci_cbe_reg[7:0] <= {command[3:0], `COMMAND_DUAL_ADDR};
@(posedge pci_clk);
pci_ad_reg[63:0] <= {address[63:32], address[63:32]};
pci_cbe_reg[7:0] <= {command[3:0], command[3:0]};
end
//Otherwise, set the address and command values
else
begin
// set the upper address and command to random for non-64bit
// addresses
pci_ad_reg[63:32] <= ($random << 3) ^ ($random >> 3);
pci_ad_reg[31:0] <= address[31:0];
pci_cbe_reg[7:4] <= ($random >> 5);
pci_cbe_reg[3:0] <= command[3:0];
end
/* insert parity check here*/
//assert irdy
irdy_oe <= 1'b1;
while(!quit) begin
@(posedge pci_clk);
//#1;
//Stop requesting if we see stop asserted
if (stop) req_reg <= 1'b0;
//Remember if we saw devsel
if (devsel) got_devsel = 1'b1;
//Set the current index into the data_array
index = initial_array_position+burst_count-countleft;
//Update timeout (counts up to 15, devsel must be seen before 10)
timeout = (timeout > 15 ? timeout : timeout + 1);
//Update time left (creates wait states: counts from next_data_delay down to 0)
timeleft = (timeleft == 0) ? 0 : timeleft - 1;
//A read cycle, don't drive ad
if(~command[0]) pci_ad_oe <= 1'b0;
//Deal with a timed out transaction (No devsel)
if ( (timeout > 10) && (~devsel) ) begin
//$display("Error time=%d,didn't receive devsel in time,trying to quit gracefully!",$time);
if ( frame_reg )
frame_reg <= 1'b0;
else begin
frame_oe <= 1'b0;
irdy_reg <= 1'b0;
irdy_oe <= 1'b0;
quit = 1'b1;
pci_ad_oe <= 1'b0; // PCI ad bus output disable
pci_cbe_oe <= 1'b0; // cbe output disable
idsel_oe <= 1'b0; // idsel is now invalid, this line should be removed...
irdy_oe <= 1'b0;
req64_oe <= 1'b0;
req_reg <= 1'b0; //stop requesting grant
quit = 1'b1;
@(posedge pci_clk);
@(posedge pci_clk);
end
end
//A data phase is occurring
if(irdy_reg && (trdy /*|| stop*/)) begin //Don't advance count if stop and not trdy is seen!
//Count Data Transferred (read or written)
if (!ack64_l) begin
countleft = countleft - 2;
if (trdy) dwords_transmitted = dwords_transmitted+2;
end
else begin
countleft = countleft - 1;
if (trdy) dwords_transmitted = dwords_transmitted+1;
end
//Set irdy timeout (To create irdy wait states!!)
timeleft = next_data_delay;
//Deassert irdy for next clock edge
irdy_reg <= 1'b0;
end
//Compare Data
if(~command[0]) begin // its a read: check data that's on the bus
// Store data just read
data_read = pci_ad;
// start comparing after first data phase
//if ( trdy && ((burst_count - countleft) >= (ack64_l ? 1:2)) & (dwords_transmitted!=0)) begin
if ( irdy & trdy ) begin
if (!ack64_l) begin
//$display ("Just about to call compare64 at time %0t. actual = %0h, bes=%0h, data_array[index]=%0h, index=%0d",
// $time, pci_ad, be, data_array[index], index);
compare64(address + ((dwords_transmitted-2)*4), {data_array[index+1],data_array[index]},
pci_ad, {be_array[index+1], be_array[index]}, pass_fail, quiet, last_data);
end
else begin
//$display("Call compare,time %0t. actual = %0h, bes=%0h, data_array[index]=%0h, index=%0d",
// $time, pci_ad, (address[2] ? be[7:4]:be[3:0]), data_array[index], index);
compare(address + ((dwords_transmitted-1)*4), data_array[index], pci_ad[31:0],
be_array[index], pass_fail, quiet, last_data);
end
end
end
if ( irdy & trdy )
index = index + (ack64_l ? 1 : 2);
//Ready to send/receive
if(timeleft < 1)
begin
if(command[0]) begin // its a write: put data on the bus
//$display ("data_array[0]=%0h, data_array[1]=%0h, time %0t", data_array[0], data_array[1], $time);
if(m64bit) begin
pci_ad_reg[63:0] <= {data_array[index + 1],data_array[index]};
pci_cbe_reg[7:0] <= ~{be_array[index + 1],be_array[index]};
end
else begin
//Put "random" on upper 32 bits of data bus
//with byte enables "random" also
pci_ad_reg[31:0] <= data_array[index];
pci_cbe_reg[3:0] <= ~be_array[index];
pci_ad_reg[63:32] <= ($random << 3) ^ ($random >> 3);
pci_cbe_reg[7:4] <= ($random >> 5);
end
end
//Assert irdy as long as we have data and we haven't been halted
//(and devsel has been asserted by someone)
if((!stop || frame_reg) && (countleft > 0) ) begin
//If We Are Just Starting, check the 64/32 bit stuff
if ( (!got_devsel) & devsel ) begin
got_devsel <= 1'b1;
if (ack64_l && m64bit) begin //We are a 64 bit master, target is only 32 bits
burst = 1;
countleft = 2;
m64bit = 0;
end
end
//Assert irdy
irdy_reg <= 1'b1;
//Deassert frame when a stop is signaled or no more that 1 data phase left
if(((countleft == (m64bit ? 2 : 1)) || stop)) begin
frame_reg <= 1'b0; // data to transfer for one clock.
frame_oe <= 1'b0; // tristate frame
end
end
end // if (trdy | stop)
//This is the end of the last data phase! Disable outputs.
if (!frame && irdy && (trdy || stop)) begin
//Disable the address and command busses
pci_ad_oe <= 1'b0; // PCI ad bus output disable
pci_cbe_oe <= 1'b0; // cbe output disable
idsel_oe <= 1'b0; // idsel is now invalid, this line should be removed...
irdy_oe <= 1'b0;
req64_oe <= 1'b0;
if (!hold_req) req_reg <= 1'b0; //stop requesting grant
quit = 1'b1;
end
//Invert the command bus to get the correct byte selects
if (m64bit) begin
pci_cbe_reg[7:0] <= ~{be_array[index+1],be_array[index]};
end else begin
//Set byte enable turned off on upper 32 bits
pci_cbe_reg[3:0] <= ~be_array[index];
pci_cbe_reg[7:4] <= ($random >> 5);
end
end // while !quit
// force the turn-around cycle
if ( stop & (~trdy) )
@(posedge pci_clk);
`ifdef GATE_SIM
@(posedge pci_clk); // don't allow fast back-back transactions in gate simulation... bus conflicts
`endif
// $display("DONE WITH TRANSACTION");
// if(!got_devsel)
// begin
// $display("ERROR time=%d, PCI access did not get devsel",$time);
// $display(" address: %x", address);
// $display(" command: %x", command);
// $display(" be: %x", be);
// end
end
endtask
endmodule // tf_pci_master
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -