📄 pci_master32_sm_if.v
字号:
// 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 + -