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 + -
显示快捷键?