pci_tar.tf
来自「VHDLVERILOG语言实现的CARDBUS的IP源码,已经实现现场应用」· TF 代码 · 共 745 行 · 第 1/2 页
TF
745 行
if (c_be_n[3:0] == 4'b1101)
lower_addr[31:0] <= pci_ad[31:0];
else
lower_addr[31:0] <= lower_addr[31:0];
end
//match goes high when ad[] is in our address space
assign match = in_addr_phase && (pci_ad[31:0] >= BASE_ADDRESS) && (pci_ad[31:0] < (BASE_ADDRESS + MEM_SIZE))
|| matchcfg || matchio || matchia;
assign match64 = frame && ({pci_ad[31:0],lower_addr} >= BASE_ADDRESS)
&& ({pci_ad[31:0],lower_addr} < (BASE_ADDRESS + MEM_SIZE));
assign matchcfg = in_addr_phase && idsel && (pci_ad[1:0] == 2'b00) && (c_be_n[3:1] == 3'b101);
assign matchio = in_addr_phase && (pci_ad[31:0] >= BASE_ADDRESS_IO)
&& (pci_ad[31:0] < (BASE_ADDRESS_IO + IO_SIZE)) && (c_be_n[3:1] == 3'b001);
assign matchia = in_addr_phase && (c_be_n[3:0] == 4'b0000) && IA_ENABLE;
//adress latch for memory read/write
wire [63:0] increment;
assign increment = (BUS_SIZE/8);
always @(posedge clk or posedge rst)
begin
if (rst)
mem_addr <= 64'h0;
else if (match && (target == idle)) begin
if (~matchcfg) mem_addr[63:0] <= {32'h0, pci_ad[31:2], 2'b00};
else mem_addr[63:0] <= {56'h0, pci_ad[7:2], 2'b00};
end
else if (match64 && (target == dualaddress_cycle))
mem_addr[63:0] <= {pci_ad[31:0],lower_addr[31:2],2'b00};
else if (trdy_reg & irdy)
begin
mem_addr[63:0] <= (mem_addr[63:0] + (req64_transaction ? (increment[63:0]) : (64'h0000000000000004)));
end
else
mem_addr[63:0] <= mem_addr[63:0];
end
// readback data from memory
assign dataout_reg[63:0] = ia_access ? {32'h0,INTERRUPT_VECTOR} : (
cfg_access ?
{32'h0,MyCfg[mem_addr+3],MyCfg[mem_addr+2],MyCfg[mem_addr+1],MyCfg[mem_addr]} : (
io_access ?
{32'h0,MyIO[mem_addr-BASE_ADDRESS_IO+3],MyIO[mem_addr-BASE_ADDRESS_IO+2],
MyIO[mem_addr-BASE_ADDRESS_IO+1],MyIO[mem_addr-BASE_ADDRESS_IO]} :
{MyMemory[mem_addr-BASE_ADDRESS+7],MyMemory[mem_addr-BASE_ADDRESS+6],MyMemory[mem_addr-BASE_ADDRESS+5],
MyMemory[mem_addr-BASE_ADDRESS+4], MyMemory[mem_addr-BASE_ADDRESS+3],MyMemory[mem_addr-BASE_ADDRESS+2],
MyMemory[mem_addr-BASE_ADDRESS+1],MyMemory[mem_addr-BASE_ADDRESS]}
));
//Drive The ad[] bus when adoe is high!
assign pci_ad[63:56] = (((BUS_SIZE == 64) & ack64) & adoe) ? (!c_be_n[7] ? dataout_reg[63:56] : 8'ha5) : 8'bz;
assign pci_ad[55:48] = (((BUS_SIZE == 64) & ack64) & adoe) ? (!c_be_n[6] ? dataout_reg[55:48] : 8'ha5) : 8'bz;
assign pci_ad[47:40] = (((BUS_SIZE == 64) & ack64) & adoe) ? (!c_be_n[5] ? dataout_reg[47:40] : 8'ha5) : 8'bz;
assign pci_ad[39:32] = (((BUS_SIZE == 64) & ack64) & adoe) ? (!c_be_n[4] ? dataout_reg[39:32] : 8'ha5) : 8'bz;
assign pci_ad[31:24] = (adoe ? (!c_be_n[3] ? dataout_reg[31:24] : 8'ha5) :8'bz);
assign pci_ad[23:16] = (adoe ? (!c_be_n[2] ? dataout_reg[23:16] : 8'ha5) :8'bz);
assign pci_ad[15: 8] = (adoe ? (!c_be_n[1] ? dataout_reg[15: 8] : 8'ha5) :8'bz);
assign pci_ad[ 7: 0] = (adoe ? (!c_be_n[0] ? dataout_reg[ 7: 0] : 8'ha5) :8'bz);
wire new_devsel;
wire old_devsel;
assign adoe = (target == s_data);
assign old_devsel = (adoe | write_trdy_en) ? 1'b1 : 1'b0;
assign devsel_n = new_devsel;
//assign devsel_n old_devsel;
assign write_trdy_en = (target == w_data);
assign target_selected = (target != idle);
integer devsel_delay;
always @(posedge match or posedge match64)
begin
@(posedge clk);
for (devsel_delay=0; devsel_delay < DEVICE_SPEED; devsel_delay = devsel_delay + 1) begin
@(posedge clk);
end
if (TARGET_ABORT) begin //Create a target abort
devsel_ok <= 1'b1;
devsel_activate <= 1'b1;
if (target == read_turnaround) @(posedge clk); //Additional cycle if it's a read
@(posedge clk);
// @(posedge clk);
//Deassert devsel
devsel_activate <= 1'b0;
devsel_ok <= 1'b0;
//Assert stop
Assert_Target_Abort <= 1'b1;
@(posedge clk);
while (frame == 1'b1) @(posedge clk);
Assert_Target_Abort <= 1'b0;
end
else begin //Normal Transaction
devsel_ok <= 1'b1;
devsel_activate <= 1'b1;
if (target == read_turnaround) @(posedge clk); //Additional cycle if it's a read
@(posedge clk);
devsel_activate <= 1'b0;
@(posedge clk);
while (old_devsel) @(posedge clk);
devsel_ok <= 1'b0;
end
end
assign new_devsel = ((old_devsel | devsel_activate) & devsel_ok & target_selected) ? 1'b0 : 1'bz;
reg [15:0] WaitStates;
reg [15:0] StopWaits;
reg [15:0] XferCount;
reg stoplatch;
reg trdylatch;
assign trdy_n = (trdyoe ? (!trdy_reg) : 1'bz);
assign trdy_reg = stoplatch ? trdylatch : ((adoe | write_trdy_en) && !(target == read_turnaround) && ((WaitStates == 0) || !WAITSTATES_ENABLE) && (devsel_ok) && (!TARGET_ABORT));
assign trdyoe = adoe | write_trdy_en;
always @(posedge clk or posedge rst)
begin
if (rst) begin
trdylatch <= 1'b0;
stoplatch <= 1'b0;
end else begin
if ((~stop_n) & (~trdy_n) & (~irdy_n)) begin
trdylatch <= 1'b0;
stoplatch <= 1'b1;
end else begin
stoplatch <= stop;
trdylatch <= trdy_reg;
end
end
end
always @(posedge clk or posedge rst)
begin
if (rst)
begin
WaitStates <= 0;
StopWaits <= 0;
XferCount <= 1;
end
else
if ((match64 && (target == dualaddress_cycle)) || (match && (target == idle)))
begin
WaitStates <= (VARIABLE_WAITS) ? (($random % (MAX_WAITS-MIN_WAITS+1)) + MIN_WAITS) : INITIAL_WAITS;
StopWaits <= STOP_WAITS;
end
else if ((WaitStates == 0) && !(target == idle) && irdy)
begin
if ((XferCount == 1)) begin
WaitStates <= (VARIABLE_WAITS) ? (($random % (MAX_WAITS-MIN_WAITS+1)) + MIN_WAITS) : SUBSEQUENT_WAITS;
XferCount <= (XFER_COUNT > 1) ? XFER_COUNT : 1;
end
else XferCount <= (XferCount > 0) ? (XferCount - 1) : 0;
StopWaits <= STOP_WAITS;
end
else if (!(target == idle))
begin
WaitStates <= (WaitStates > 0) ? (WaitStates - 1) : 0;
StopWaits <= (StopWaits > 0) ? (StopWaits - 1) : 0;
end
else
begin
WaitStates <= 0;
StopWaits <= 0;
XferCount <= 1;
end
end
//Write Data Into The Memory:
integer init;
always @(posedge clk or posedge rst)
begin
if (rst)
begin
//Initialize Memory
// Neal, this should only be done once, not on every clock edge
for (init = 0; init < MEM_SIZE; init = init + 1)
MyMemory[init] <= 8'b0;
for (init = 0; init < IO_SIZE; init = init + 1)
MyIO[init] <= 8'b0;
for (init = 0; init < CFG_SIZE; init = init + 1)
MyCfg[init] <= 8'b0;
sc_reg[31:0] <= 32'h00000000;
end
else begin
if (irdy & trdy_reg & write_trdy_en & ~cfg_access & ~io_access & ~ia_access)
begin
if (!c_be_n[0])
MyMemory[mem_addr-BASE_ADDRESS] <= pci_ad[7:0];
if (!c_be_n[1])
MyMemory[mem_addr-BASE_ADDRESS+1] <= pci_ad[15:8];
if (!c_be_n[2])
MyMemory[mem_addr-BASE_ADDRESS+2] <= pci_ad[23:16];
if (!c_be_n[3])
MyMemory[mem_addr-BASE_ADDRESS+3] <= pci_ad[31:24];
if ((BUS_SIZE == 64) && ack64)
begin
if (!c_be_n[4])
MyMemory[mem_addr-BASE_ADDRESS+4] <= pci_ad[39:32];
if (!c_be_n[5])
MyMemory[mem_addr-BASE_ADDRESS+5] <= pci_ad[47:40];
if (!c_be_n[6])
MyMemory[mem_addr-BASE_ADDRESS+6] <= pci_ad[55:48];
if (!c_be_n[7])
MyMemory[mem_addr-BASE_ADDRESS+7] <= pci_ad[63:56];
end
end
if (irdy & trdy_reg & write_trdy_en & cfg_access)
begin
if (!c_be_n[0])
MyCfg[mem_addr[7:0]] <= pci_ad[7:0];
if (!c_be_n[1])
MyCfg[mem_addr+1] <= pci_ad[15:8];
if (!c_be_n[2])
MyCfg[mem_addr+2] <= pci_ad[23:16];
if (!c_be_n[3])
MyCfg[mem_addr+3] <= pci_ad[31:24];
end
if (irdy & trdy_reg & write_trdy_en & io_access)
begin
if (!c_be_n[0])
MyIO[mem_addr-BASE_ADDRESS_IO] <= pci_ad[7:0];
if (!c_be_n[1])
MyIO[mem_addr-BASE_ADDRESS_IO+1] <= pci_ad[15:8];
if (!c_be_n[2])
MyIO[mem_addr-BASE_ADDRESS_IO+2] <= pci_ad[23:16];
if (!c_be_n[3])
MyIO[mem_addr-BASE_ADDRESS_IO+3] <= pci_ad[31:24];
end
if (irdy & sc_access)
begin
if (!c_be_n[0])
MyMemory[0] <= pci_ad[7:0];
if (!c_be_n[1])
MyMemory[1] <= pci_ad[15:8];
if (!c_be_n[2])
MyMemory[2] <= pci_ad[23:16];
if (!c_be_n[3])
MyMemory[3] <= pci_ad[31:24];
end
end
end
//Drive data_count (counts data phases)
always @(posedge clk or posedge rst)
begin
if (rst)
data_count <= 0;
else
if (irdy & trdy_reg)
data_count <= data_count + 1;
else if (target == idle)
data_count <= 0;
end
//Drive The Stop Signal
assign stop_n = (stop_en ? ~stop_reg : 1'bz);
assign stop_en = (adoe || write_trdy_en) || Assert_Target_Abort;
reg stophold;
always @(posedge clk or posedge rst)
begin
if(rst)
begin
stophold <= 1'b0;
end
else
begin
stophold <= stop_reg;
end
end
// Once stop is asserted, it is held until the last data phase completes
assign stop_reg = ( (STOP_ENABLE && (STOP_COUNT <= data_count) && (StopWaits <= 1) && (stop_en) && devsel ) ||
(STOP_ENABLE && (trdy_reg) && (STOP_COUNT == (data_count + 1)) && (STOP_WAITS == 0)) ||
(stophold && devsel) ||
(Assert_Target_Abort) ); // added devsel to first term (BDS, QL)
//count # times stop is asserted
reg count_stop;
always @(posedge clk or posedge rst)
begin
if(rst)
begin
count_stop <= 1;
end
else
begin
if (stop_reg && count_stop)
begin
if (RETRY_COUNT == 0)
begin
count_stop<=0;
end
else
begin
RETRY_COUNT <= RETRY_COUNT - 1;
count_stop <= 0;
end
end
else if (!stop_reg)
begin
count_stop <= 1;
if ((RETRY_COUNT == 0) && (ENABLE_RETRY_COUNT))
begin
STOP_ENABLE <= 0;
end
end
end
end
reg [63:0] pci_ad_d;
// parity check
pci_parity_check my_pci_parity_check(
.ad_p(pci_ad_d),
.c_be_n_p(c_be_n_d),
.parity32(parity32_out),
.parity64(parity64_out)
);
reg parity32_out_d;
reg parity64_out_d;
always @(posedge clk or posedge rst) begin
if(rst) begin
c_be_n_d[7:0] <= 8'h0;
pci_ad_d[63:0] <= 64'h0;
parity_en <= 1'b0;
parity32_out_d <= 1'b0;
parity64_out_d <= 1'b0;
end else begin
c_be_n_d[7:0] <= c_be_n[7:0];
pci_ad_d[63:0] <= pci_ad[63:0];
parity_en <= adoe;
parity32_out_d <= parity32_out;
parity64_out_d <= parity64_out;
end
end
assign par = (parity_en ? parity32_out ^ WRONG_PAR : 1'bz);
assign par64 = (parity_en ? parity64_out ^ WRONG_PAR64 : 1'bz);
//drive PERR signal (doesn't detect parity errors- drives perr if PERR_ASSERT is on)
reg perr_en;
reg perr_out;
always @(posedge clk or posedge rst) begin
if (rst) begin
perr_out <= 1'b0;
perr_en <= 1'b0;
end else begin
if (irdy & trdy_reg & write_trdy_en) begin
@(posedge clk);
perr_en <= 1'b1;
perr_out <= 1'b1;
@(posedge clk);
perr_en <= 1'b0;
perr_out <= 1'b0;
end
end
end
assign perr_n = ((perr_en && PERR_ASSERT) ? (~perr_out) : 1'bz);
endmodule
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?