⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pci_mast.tf

📁 VHDLVERILOG语言实现的CARDBUS的IP源码,已经实现现场应用
💻 TF
📖 第 1 页 / 共 3 页
字号:

    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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -