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

📄 pci_wb_master.v

📁 用verilog编写的pci——rtl级。
💻 V
📖 第 1 页 / 共 4 页
字号:
// wire for read attempt - 1 when PCI Target is attempting a read and PCIR_FIFO is not full !
// because of transaction ordering, PCI Master must not start read untill all writes are done -> at that
//   moment PCIW_FIFO is empty !!! (when read is pending PCI Target will block new reads and writes)
wire r_attempt = ( pci_tar_read_request && !w_attempt && pciw_fifo_empty_in ) ; 

// Signal is used for reads on WB, when there is retry!
reg             first_wb_data_access ;

reg             last_data_from_pciw_fifo ;  // signal tells when there is last data in pciw_fifo
reg             last_data_from_pciw_fifo_reg ;
reg             last_data_to_pcir_fifo ;    // signal tells when there will be last data for pcir_fifo

// Logic used in State Machine logic implemented out of State Machine because of less delay!
always@(posedge wb_clock_in or posedge reset_in)
begin
    if (reset_in)
        last_data_from_pciw_fifo <= #`FF_DELAY 1'b0 ;
    else
    begin
        if ((pciw_fifo_renable_out) && 
            (pciw_fifo_control_in[`LAST_CTRL_BIT] || pciw_fifo_almost_empty_in)) // if last data is going to be transfered
            last_data_from_pciw_fifo <= #`FF_DELAY 1'b1 ; // signal for last data from PCIW_FIFO
        else
            last_data_from_pciw_fifo <= #`FF_DELAY 1'b0 ;
    end
end

    reg read_count_load;
    reg read_count_enable;
    
    reg [(`PCIR_ADDR_LENGTH - 1):0] max_read_count ;
    always@(pci_cache_line_size or cache_lsize_not_zero or pci_tar_cmd)
    begin 
        if (cache_lsize_not_zero) 
            if ( (pci_cache_line_size >= `PCIR_DEPTH) || (~pci_tar_cmd[1] && ~pci_tar_cmd[0]) )
                // If cache line size is larger than FIFO or BC_MEM_READ_MUL command is performed!
                max_read_count = `PCIR_DEPTH - 1'b1;
            else
                max_read_count = pci_cache_line_size ;
        else
            max_read_count = 1'b1;
    end

    reg [(`PCIR_ADDR_LENGTH - 1):0] read_count ;

    // cache line bound indicator - it signals when data for one complete cacheline was read
    wire read_bound_comb = ~|( { read_count[(`PCIR_ADDR_LENGTH - 1):2], read_count[0] } ) ;

    reg  read_bound ;
    always@(posedge wb_clock_in or posedge reset_in)
    begin
        if ( reset_in )
            read_bound <= #`FF_DELAY 1'b0 ;
        else if (read_count_load)
            read_bound <= #`FF_DELAY 1'b0 ;
        else if ( read_count_enable )
            read_bound <= #`FF_DELAY read_bound_comb ;
    end

    // down counter with load
    always@(posedge reset_in or posedge wb_clock_in)
    begin
        if (reset_in)
            read_count <= #`FF_DELAY 0 ;
        else
        if (read_count_load)
            read_count <= #`FF_DELAY max_read_count ;
        else
        if (read_count_enable)
            read_count <= #`FF_DELAY read_count - 1'b1 ;
    end

// Logic used in State Machine logic implemented out of State Machine because of less delay!
//   definition of signal telling, when there is last data written into FIFO
always@(pci_tar_cmd or pci_tar_burst_ok or read_bound)
begin
    // burst is OK for reads when there is ((MEM_READ_LN or MEM_READ_MUL) and AD[1:0]==2'b00) OR
    //   (MEM_READ and Prefetchable_IMAGE and AD[1:0]==2'b00) -> pci_tar_burst_ok
    case ({pci_tar_cmd, pci_tar_burst_ok})
    {`BC_MEM_READ, 1'b1},
    {`BC_MEM_READ_LN, 1'b1} :
    begin   // when burst cycle
        if (read_bound)
            last_data_to_pcir_fifo = 1'b1 ;
        else
            last_data_to_pcir_fifo = 1'b0 ;
    end
    {`BC_MEM_READ_MUL, 1'b1} :
    begin   // when burst cycle
        if (read_bound)
            last_data_to_pcir_fifo = 1'b1 ;
        else
            last_data_to_pcir_fifo = 1'b0 ;
    end
    default :
    // {`BC_IO_READ, 1'b0},
    // {`BC_IO_READ, 1'b1},
    // {`BC_MEM_READ, 1'b0},
    // {`BC_MEM_READ_LN, 1'b0},
    // {`BC_MEM_READ_MUL, 1'b0}:
    begin   // when single cycle
        last_data_to_pcir_fifo = 1'b1 ;
    end
    endcase
end

reg             wait_for_wb_response ;

`ifdef PCI_WBM_NO_RESPONSE_CNT_DISABLE
wire set_retry = 1'b0 ;

`else
reg     [3:0]   wb_no_response_cnt ;
reg     [3:0]   wb_response_value ;
reg             set_retry ; // 

// internal WB no response retry generator counter!
always@(posedge reset_in or posedge wb_clock_in)
begin
    if (reset_in)
        wb_no_response_cnt <= #`FF_DELAY 4'h0 ; 
    else
        wb_no_response_cnt <= #`FF_DELAY wb_response_value ;
end
// internal WB no response retry generator logic
always@(wait_for_wb_response or wb_no_response_cnt)
begin
    if (wb_no_response_cnt == 4'h8) // when there isn't response for 8 clocks, set internal retry
    begin
        wb_response_value = 4'h0 ;
        set_retry = 1'b1 ;
    end
    else
    begin
        if (wait_for_wb_response)
            wb_response_value = wb_no_response_cnt + 1'h1 ; // count clocks when no response
        else
            wb_response_value = 4'h0 ;
        set_retry = 1'b0 ;
    end
end
`endif

wire    retry = wb_rty_i || set_retry ; // retry signal - logic OR function between wb_rty_i and internal WB no response retry!
reg     [7:0]   rty_counter ; // output from retry counter
reg     [7:0]   rty_counter_in ; // input value - output value + 1 OR output value
reg             rty_counter_almost_max_value ; // signal tells when retry counter riches maximum value - 1!
reg             reset_rty_cnt ; // signal for asynchronous reset of retry counter after each complete transfere

// sinchronous signal after each transfere and asynchronous signal 'reset_rty_cnt' after reset  
//   for reseting the retry counter
always@(posedge reset_in or posedge wb_clock_in)
begin
    if (reset_in)
        reset_rty_cnt <= #`FF_DELAY 1'b1 ; // asynchronous set when reset signal is active
    else
        reset_rty_cnt <= #`FF_DELAY wb_ack_i || wb_err_i || last_data_transferred ; // synchronous set after completed transfere
end

// Retry counter register control
always@(posedge reset_in or posedge wb_clock_in)
begin
    if (reset_in)
        rty_counter <= #`FF_DELAY 8'h00 ;
    else
    begin
        if (reset_rty_cnt)
            rty_counter <= #`FF_DELAY 8'h00 ;
        else if (retry)
            rty_counter <= #`FF_DELAY rty_counter_in ;
    end
end
// Retry counter logic
always@(rty_counter)
begin
    if(rty_counter == `WB_RTY_CNT_MAX - 1'b1) // stop counting
    begin
        rty_counter_in = rty_counter ;
        rty_counter_almost_max_value = 1'b1 ;
    end
    else
    begin
        rty_counter_in = rty_counter + 1'b1 ; // count up
        rty_counter_almost_max_value = 1'b0 ;
    end
end     

reg     [31:0]  addr_cnt_out ;  // output value from address counter to WB ADDRESS output
reg     [31:0]  addr_cnt_in ;   // input address value to address counter
reg             addr_into_cnt ; // control signal for loading starting address into counter
reg             addr_into_cnt_reg ; 
reg             addr_count ; // control signal for count enable
reg     [3:0]   bc_register ; // used when error occures during writes!

// wb address counter register control
always@(posedge wb_clock_in or posedge reset_in)
begin
    if (reset_in) // reset counter
    begin
        addr_cnt_out <= #`FF_DELAY 32'h0000_0000 ;
        bc_register  <= #`FF_DELAY 4'h0 ;
        addr_into_cnt_reg <= #`FF_DELAY 1'b0;
    end
    else
    begin
        addr_cnt_out <= #`FF_DELAY addr_cnt_in ; // count up or hold value depending on cache line counter logic
        addr_into_cnt_reg <= #`FF_DELAY addr_into_cnt;
        if (addr_into_cnt)
            bc_register  <= #`FF_DELAY pciw_fifo_cbe_in ;
    end
end

// when '1', the bus command is IO command - not supported commands are checked in pci_decoder modules
wire    io_memory_bus_command = !pci_tar_cmd[3] && !pci_tar_cmd[2] ;

// wb address counter logic
always@(addr_into_cnt or r_attempt or addr_count or pciw_fifo_addr_data_in or pci_tar_address or addr_cnt_out or
        io_memory_bus_command)
begin
    if (addr_into_cnt) // load starting address into counter
    begin
        if (r_attempt)
        begin // if read request, then load read addresss from PCI Target
            addr_cnt_in = {pci_tar_address[31:2], pci_tar_address[1] && io_memory_bus_command, 
                                                  pci_tar_address[0] && io_memory_bus_command} ; 
        end
        else
        begin // if not read request, then load write address from PCIW_FIFO
            addr_cnt_in = pciw_fifo_addr_data_in[31:0] ; 
        end
    end
    else
    if (addr_count)
    begin
        addr_cnt_in = addr_cnt_out + 3'h4 ; // count up for 32-bit alligned address 
    end
    else
    begin
        addr_cnt_in = addr_cnt_out ;
    end
end

reg retried ; // Signal is output value from FF and is set for one clock period after retried_d is set
reg retried_d ; // Signal is set whenever cycle is retried and is input to FF for delaying -> used in S_IDLE state
reg retried_write;
reg rty_i_delayed; // Dignal used for determinig the source of retry!

reg     first_data_is_burst ; // Signal is set in S_WRITE or S_READ states, when data transfere is burst!
reg     first_data_is_burst_reg ;
wire    burst_transfer ; // This signal is set when data transfere is burst and is reset with RESET or last data transfered
reg     burst_chopped; // This signal is set when WB_SEL_O is changed during burst write transaction
reg     burst_chopped_delayed;

// FFs output signals tell, when there is first data out from FIFO (for BURST checking)
//   and for delaying retried signal
always@(posedge wb_clock_in or posedge reset_in)
begin
    if (reset_in) // reset signals
    begin
        retried <= #`FF_DELAY 1'b0 ;
        retried_write <= #`FF_DELAY 1'b0 ;
        rty_i_delayed <= #`FF_DELAY 1'B0 ;
    end
    else
    begin
        retried <= #`FF_DELAY retried_d ; // delaying retried signal  
        retried_write <= #`FF_DELAY retried ;
        rty_i_delayed <= #`FF_DELAY wb_rty_i ;
    end
end

// Determinig if first data is a part of BURST or just a single transfere!
always@(addr_into_cnt or r_attempt or pci_tar_burst_ok or max_read_count or 
        pciw_fifo_control_in or pciw_fifo_empty_in)
begin
    if (addr_into_cnt)
    begin
        if (r_attempt)
        begin
                // burst is OK for reads when there is ((MEM_READ_LN or MEM_READ_MUL) and AD[1:0]==2'b00) OR
                //   (MEM_READ and Prefetchable_IMAGE and AD[1:0]==2'b00) -> pci_tar_burst_ok
            if  (pci_tar_burst_ok && (max_read_count != 8'h1))
                first_data_is_burst = 1'b1 ; 
            else
                first_data_is_burst = 1'b0 ;
        end
        else
        begin
            first_data_is_burst = 1'b0 ;
        end
    end
    else
        first_data_is_burst = pciw_fifo_control_in[`BURST_BIT] && ~pciw_fifo_empty_in && 
                              ~pciw_fifo_control_in[`LAST_CTRL_BIT] /*&& ~pciw_fifo_control_in[`DATA_ERROR_CTRL_BIT]*/;

⌨️ 快捷键说明

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