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