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

📄 pci_master32_sm_if.v

📁 用verilog编写的pci——rtl级。
💻 V
📖 第 1 页 / 共 3 页
字号:

// three requests are possible - posted write, delayed write and delayed read
reg del_write_req ;
reg posted_write_req ;
reg del_read_req ;

// assign request output
assign req_out = del_write_req || posted_write_req || del_read_req ;

// posted write is not present, when WB Write Fifo is empty and posted write transaction is not beeing requested at present time
assign posted_write_not_present_out = !posted_write_req && wbw_fifo_empty_in ;

// write requests are staged, so data is read from source into current data register and next data register
reg write_req_int ;
always@(posedge reset_in or posedge clk_in)
begin
    if ( reset_in )
        write_req_int <= #`FF_DELAY 1'b0 ;
    else
        write_req_int <= #`FF_DELAY posted_write_req || del_write_req ;

end

// ready output is generated one clock after request for reads and two after for writes
always@(posedge reset_in or posedge clk_in)
begin
    if (reset_in)
        rdy_out <= #`FF_DELAY 1'b0 ;
    else
        rdy_out <= #`FF_DELAY del_read_req || ( (posted_write_req || del_write_req) && write_req_int) ;
end

// wires with logic used as inputs to request FFs
wire do_posted_write = ( wbw_fifo_transaction_ready_in && ~wbw_fifo_empty_in && ~err_lock ) ;
wire do_del          = ( del_req_in && ~err_lock && wbw_fifo_empty_in ) ;
wire do_del_write    = do_del &&  del_we_in ;
wire do_del_read     = do_del && ~del_we_in ;

// register for indicating current operation's data source
parameter DELAYED_WRITE = 1'b1 ;
parameter POSTED_WRITE  = 1'b0 ;

// new data source - depending on which transaction will be processed next - delayed read is here because source of byte enables must
// be specified for delayed reads also - data source is not relevant for delayed reads, so value is don't care anyway
wire new_data_source = (do_del_write || do_del_read) ? DELAYED_WRITE : POSTED_WRITE ; // input to data source register
wire data_source_change = ~req_out ;    // change (enable) for data source register - when no requests are in progress

reg data_source ;           // data source value
always@(posedge reset_in or posedge clk_in)
begin
    if (reset_in)
        // default value is posted write source - wbw_fifo
        data_source <= #`FF_DELAY POSTED_WRITE ;
    else
    if (data_source_change)
        // change data source on rising clock edge
        data_source <= #`FF_DELAY new_data_source ;
end

// multiplexer for data output to PCI MASTER state machine
reg [31:0] source_data ;
reg [3:0]  source_be ;
always@(data_source or wbw_fifo_addr_data_in or wbw_fifo_cbe_in or del_wdata_in or del_be_in or del_burst_in)
begin
    case (data_source)
        POSTED_WRITE:   begin
                            source_data = wbw_fifo_addr_data_in ;
                            source_be   = wbw_fifo_cbe_in ;
                        end
        DELAYED_WRITE:  begin
                            source_data = del_wdata_in ;
                            // read all bytes during delayed burst read!
                            source_be   = ~( del_be_in | {4{del_burst_in}} ) ;
                        end
    endcase
end

wire            waddr =  wbw_fifo_control_in[`ADDR_CTRL_BIT] ;

// address change indicator - address is allowed to be loaded only when no transaction is in progress!
wire            address_change = ~req_out ; // address change - whenever there is no request in progress

// new address - input to register storing address of current request - if posted write request will be next,
// load address and bus command from wbw_fifo, else load data from delayed transaction logic
wire     [31:0] new_address = ( ~req_out && do_posted_write ) ? wbw_fifo_addr_data_in[31:0] : del_addr_in[31:0] ;
wire     [3:0]  new_bc      = ( ~req_out && do_posted_write ) ? wbw_fifo_cbe_in : del_bc_in ;

// address counter enable - only for posted writes when data is actually transfered
wire addr_count_en = !wait_in && posted_write_req && rtransfer_in ;

always@(posedge reset_in or posedge clk_in)
begin
    if (reset_in)
        bc_out <= #`FF_DELAY `BC_RESERVED0 ;
    else
    if (address_change)
        bc_out <= #`FF_DELAY new_bc ;
end

reg [29:0] current_dword_address ;

// DWORD address counter with load
always@(posedge reset_in or posedge clk_in)
begin
    if (reset_in)
        current_dword_address <= #`FF_DELAY 30'h0000_0000 ;
    else
    if (address_change)
        current_dword_address <= #`FF_DELAY new_address[31:2] ;
    else
    if (addr_count_en)
        current_dword_address <= #`FF_DELAY current_dword_address + 1'b1 ;
end

reg [1:0] current_byte_address ;
always@(posedge reset_in or posedge clk_in)
begin
    if (reset_in)
        current_byte_address <= #`FF_DELAY 2'b00 ;
    else
    if (address_change)
        current_byte_address <= #`FF_DELAY new_address[1:0] ;
end

// byte address generation logic
reg [ 1: 0] generated_byte_adr ;
reg [ 1: 0] pci_byte_adr       ;

always@(be_out)
begin
    casex(be_out)
    4'bxxx0:generated_byte_adr = 2'b00 ;
    4'bxx01:generated_byte_adr = 2'b01 ;
    4'bx011:generated_byte_adr = 2'b10 ;
    4'b0111:generated_byte_adr = 2'b11 ;
    4'b1111:generated_byte_adr = 2'b00 ;
    endcase
end

always@(generated_byte_adr or bc_out or current_byte_address)
begin
    // for memory access commands, set lower 2 address bits to 0
    if ((bc_out == `BC_MEM_READ) | (bc_out == `BC_MEM_WRITE) | 
        (bc_out == `BC_MEM_READ_MUL) | (bc_out == `BC_MEM_READ_LN) | 
        (bc_out == `BC_MEM_WRITE_INVAL))
    begin
        pci_byte_adr = 2'b00 ;
    end
    else if ((bc_out == `BC_IO_WRITE) | (bc_out == `BC_IO_READ))
    begin
        pci_byte_adr = generated_byte_adr ;
    end
    else
    begin
        pci_byte_adr = current_byte_address ;
    end
end

// address output to PCI master state machine assignment
assign address_out  = { current_dword_address, pci_byte_adr } ;

// the same for erroneous address assignement
assign err_addr_out = { current_dword_address, pci_byte_adr } ;

// cacheline size counter - for read transaction length control
// cache line count is enabled during burst reads when data is actually transfered
wire read_count_enable = ~wait_in && del_read_req && del_burst_in && wtransfer_in  ;

// cache line counter is loaded when del read request is not in progress
wire read_count_load   = ~del_read_req ;

reg [(`WBR_ADDR_LENGTH - 1):0] max_read_count ;
always@(cache_line_size_in or del_bc_in)
begin
    if ( (cache_line_size_in >= `WBR_DEPTH) || (~del_bc_in[1] && ~del_bc_in[0]) )
        max_read_count = `WBR_DEPTH - 1'b1;
    else
        max_read_count = cache_line_size_in ;
end

reg [(`WBR_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[(`WBR_ADDR_LENGTH - 1):2]) ;
reg  read_bound ;
always@(posedge clk_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

wire read_count_change_val = read_count_load | read_count_enable ;

wire [(`WBR_ADDR_LENGTH - 1):0] read_count_next = read_count_load ? max_read_count : (read_count - 1'b1) ;

// down counter with load
always@(posedge reset_in or posedge clk_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 ;
*/  if (read_count_change_val)
        read_count <= #`FF_DELAY read_count_next ;
end

// flip flop indicating error recovery is in progress
reg err_recovery_in ;
always@(posedge reset_in or posedge clk_in)
begin
    if (reset_in)
        err_recovery <= #`FF_DELAY 1'b0 ;
    else
        err_recovery <= #`FF_DELAY err_recovery_in ;
end

/*// retry counter implementation
reg [7:0] retry_count ;

wire retry_expired = ~|(retry_count[7:1]) ;

// loading of retry counter - whenever no request is present or other termination than retry or wait is signalled
wire retry_load = ~req_out || (~wait_in && rtransfer_in) ;

// retry DOWN counter with load
always@(posedge reset_in or posedge clk_in)
begin
    if (reset_in)
        retry_count <= #`FF_DELAY 8'hFF ;
    else
    if ( retry_load )
        retry_count <= #`FF_DELAY `PCI_RTY_CNT_MAX ;
    else
    if (retry_in)
        retry_count <= #`FF_DELAY retry_count - 1'b1 ;
end*/

/*==================================================================================================================
Delayed write requests are always single transfers!
Delayed write request starts, when no request is currently beeing processed and it is signaled from other side
of the bridge.
==================================================================================================================*/
// delayed write request FF input control
reg del_write_req_input ;

always@(
    do_del_write or
    del_write_req or
    posted_write_req or
    del_read_req or
    wait_in or
    //retry_in or
    //retry_expired or
    rtransfer_in or
    rerror_in or
    mabort_in
)
begin
    if (~del_write_req)
    begin
        // delayed write is not in progress and is requested
        // delayed write can be requested when no other request is in progress
        del_write_req_input = ~posted_write_req && ~del_read_req && do_del_write ;
    end
    else
    begin
        // delayed write request is in progress - assign input
        del_write_req_input = wait_in ||
                              ( /*~( retry_in && retry_expired) &&*/
                                ~rtransfer_in && ~rerror_in && ~mabort_in
                              );
    end
end

// delayed write request FLIP-FLOP

⌨️ 快捷键说明

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