📄 pci_wb_master.v
字号:
end
// FF for seting and reseting burst_transfer signal
always@(posedge wb_clock_in or posedge reset_in)
begin
if (reset_in)
begin
burst_chopped <= #`FF_DELAY 1'b0;
burst_chopped_delayed <= #`FF_DELAY 1'b0;
first_data_is_burst_reg <= #`FF_DELAY 1'b0 ;
end
else
begin
if (pciw_fifo_transaction_ready_in)
begin
if (pciw_fifo_control_in[`DATA_ERROR_CTRL_BIT])
burst_chopped <= #`FF_DELAY 1'b1;
else if (wb_ack_i || wb_err_i || wb_rty_i)
burst_chopped <= #`FF_DELAY 1'b0;
end
else
burst_chopped <= #`FF_DELAY 1'b0;
burst_chopped_delayed <= #`FF_DELAY burst_chopped;
if (last_data_transferred || first_data_is_burst)
first_data_is_burst_reg <= #`FF_DELAY ~last_data_transferred ;
end
end
assign burst_transfer = first_data_is_burst || first_data_is_burst_reg ;
reg [(`WB_FSM_BITS - 1):0] c_state ; //current state register
reg [(`WB_FSM_BITS - 1):0] n_state ; //next state input to current state register
//##################################
// WISHBONE B3 master state machine
//##################################
// state machine register control and registered outputs (without wb_adr_o counter)
always@(posedge wb_clock_in or posedge reset_in)
begin
if (reset_in) // reset state machine to S_IDLE state
begin
c_state <= #`FF_DELAY S_IDLE;
wb_cyc_o <= #`FF_DELAY 1'b0;
wb_stb_o <= #`FF_DELAY 1'b0;
wb_we_o <= #`FF_DELAY 1'b0;
wb_cti_o <= #`FF_DELAY 3'h2;
wb_bte_o <= #`FF_DELAY 2'h0;
wb_sel_o <= #`FF_DELAY 4'h0;
wb_dat_o <= #`FF_DELAY 32'h0;
pcir_fifo_data_out <= #`FF_DELAY 32'h0;
pcir_fifo_control_out <= #`FF_DELAY 4'h0;
pcir_fifo_wenable_out <= #`FF_DELAY 1'b0;
end
else
begin
c_state <= #`FF_DELAY n_state;
wb_bte_o <= #`FF_DELAY 2'h0;
case (n_state) // synthesis parallel_case full_case
S_WRITE:
begin
wb_cyc_o <= #`FF_DELAY ~addr_into_cnt;
wb_stb_o <= #`FF_DELAY ~addr_into_cnt;
wb_we_o <= #`FF_DELAY ~addr_into_cnt;
// if '1' then next burst BE is not equat to current one => burst is chopped into singles
// OR if last data is going to be transfered
if ((wb_stb_o && wb_ack_i) || addr_into_cnt_reg || (~wb_cyc_o && (retried || burst_chopped_delayed)))
begin
if (burst_transfer && ~pciw_fifo_control_in[`DATA_ERROR_CTRL_BIT] &&
~(pciw_fifo_renable_out && (pciw_fifo_control_in[`LAST_CTRL_BIT] || pciw_fifo_almost_empty_in)))
wb_cti_o <= #`FF_DELAY 3'h2;
else
wb_cti_o <= #`FF_DELAY 3'h7;
end
if ((pciw_fifo_renable_out && ~addr_into_cnt) || addr_into_cnt_reg)
begin
wb_sel_o <= #`FF_DELAY ~pciw_fifo_cbe_in;
wb_dat_o <= #`FF_DELAY pciw_fifo_addr_data_in;
end
end
S_WRITE_ERR_RTY:
begin
wb_cyc_o <= #`FF_DELAY 1'b0;
wb_stb_o <= #`FF_DELAY 1'b0;
wb_we_o <= #`FF_DELAY 1'b0;
wb_cti_o <= #`FF_DELAY 3'h2;
// stay the same as previous
//wb_sel_o <= #`FF_DELAY 4'h0;
//wb_dat_o <= #`FF_DELAY 32'h0;
end
S_READ:
begin
wb_cyc_o <= #`FF_DELAY ~addr_into_cnt;
wb_stb_o <= #`FF_DELAY ~addr_into_cnt;
wb_we_o <= #`FF_DELAY 1'b0;
if ((wb_stb_o && wb_ack_i) || addr_into_cnt_reg || (~wb_cyc_o && retried))
begin
if (burst_transfer && ~read_bound_comb)
wb_cti_o <= #`FF_DELAY 3'h2;
else
wb_cti_o <= #`FF_DELAY 3'h7;
end
if (burst_transfer)
wb_sel_o <= #`FF_DELAY 4'hF;
else
wb_sel_o <= #`FF_DELAY ~pci_tar_be;
// no need to change att all
//wb_dat_o <= #`FF_DELAY 32'h0;
end
S_READ_RTY:
begin
wb_cyc_o <= #`FF_DELAY 1'b0;
wb_stb_o <= #`FF_DELAY 1'b0;
wb_we_o <= #`FF_DELAY 1'b0;
wb_cti_o <= #`FF_DELAY 3'h2;
// no need to change att all
//wb_sel_o <= #`FF_DELAY 4'h0;
//wb_dat_o <= #`FF_DELAY 32'h0;
end
S_TURN_ARROUND:
begin
wb_cyc_o <= #`FF_DELAY 1'b0;
wb_stb_o <= #`FF_DELAY 1'b0;
wb_we_o <= #`FF_DELAY 1'b0;
wb_cti_o <= #`FF_DELAY 3'h2;
// no need to change att all
//wb_sel_o <= #`FF_DELAY 4'h0;
//wb_dat_o <= #`FF_DELAY 32'h0;
end
default: // S_IDLE:
begin
wb_cyc_o <= #`FF_DELAY 1'b0;
wb_stb_o <= #`FF_DELAY 1'b0;
wb_we_o <= #`FF_DELAY 1'b0;
wb_cti_o <= #`FF_DELAY 3'h2;
// no need to change att all
//wb_sel_o <= #`FF_DELAY 4'h0;
//wb_dat_o <= #`FF_DELAY 32'h0;
end
endcase
pcir_fifo_data_out <= #`FF_DELAY wb_dat_i;
pcir_fifo_control_out <= #`FF_DELAY pcir_fifo_control ;
pcir_fifo_wenable_out <= #`FF_DELAY pcir_fifo_wenable ;
end
end
assign wb_adr_o = addr_cnt_out ;
// state machine logic
always@(c_state or
wb_ack_i or
wb_rty_i or
wb_err_i or
w_attempt or
r_attempt or
retried or
burst_chopped or
burst_chopped_delayed or
rty_i_delayed or
pci_tar_read_request or
rty_counter_almost_max_value or
set_retry or
last_data_to_pcir_fifo or
first_wb_data_access or
pciw_fifo_control_in or
pciw_fifo_empty_in or
burst_transfer or
last_data_from_pciw_fifo_reg
)
begin
case (c_state)
S_IDLE:
begin
// Default values for signals not used in this state
pcir_fifo_wenable = 1'b0 ;
pcir_fifo_control = 4'h0 ;
addr_count = 1'b0 ;
read_count_enable = 1'b0 ;
pci_error_sig_out = 1'b0 ;
error_source_out = 1'b0 ;
retried_d = 1'b0 ;
last_data_transferred = 1'b0 ;
wb_read_done = 1'b0 ;
wait_for_wb_response = 1'b0 ;
write_rty_cnt_exp_out = 1'b0 ;
pci_error_sig_out = 1'b0 ;
read_rty_cnt_exp_out = 1'b0 ;
case ({w_attempt, r_attempt, retried})
3'b101 : // Write request for PCIW_FIFO to WB bus transaction
begin // If there was retry, the same transaction must be initiated
pciw_fifo_renable = 1'b0 ; // the same data
addr_into_cnt = 1'b0 ; // the same address
read_count_load = 1'b0 ; // no need for cache line when there is write
n_state = S_WRITE ;
end
3'b100 : // Write request for PCIW_FIFO to WB bus transaction
begin // If there is new transaction
if (burst_chopped_delayed)
begin
addr_into_cnt = 1'b0 ; // address must not be latched into address counter
pciw_fifo_renable = 1'b1 ; // first location is address (in FIFO), next will be data
end
else
begin
if (pciw_fifo_control_in[`ADDR_CTRL_BIT])
addr_into_cnt = 1'b1 ; // address must be latched into address counter
else
addr_into_cnt = 1'b0 ;
pciw_fifo_renable = 1'b1 ; // first location is address (in FIFO), next will be data
end
read_count_load = 1'b0 ; // no need for cache line when there is write
n_state = S_WRITE ;
end
3'b011 : // Read request from PCI Target for WB bus to PCIR_FIFO transaction
begin // If there was retry, the same transaction must be initiated
addr_into_cnt = 1'b0 ; // the same address
read_count_load = 1'b0 ; // cache line counter must not be changed for retried read
pciw_fifo_renable = 1'b0 ; // don't read from FIFO, when read transaction from WB to FIFO
n_state = S_READ ;
end
3'b010 : // Read request from PCI Target for WB bus to PCIR_FIFO transaction
begin // If there is new transaction
addr_into_cnt = 1'b1 ; // address must be latched into counter from separate request bus
read_count_load = 1'b1 ; // cache line size must be latched into its counter
pciw_fifo_renable = 1'b0 ; // don't read from FIFO, when read transaction from WB to FIFO
n_state = S_READ ;
end
default : // stay in IDLE state
begin
pciw_fifo_renable = 1'b0 ;
addr_into_cnt = 1'b0 ;
read_count_load = 1'b0 ;
n_state = S_IDLE ;
end
endcase
end
S_WRITE: // WRITE from PCIW_FIFO to WB bus
begin
// Default values for signals not used in this state
pcir_fifo_wenable = 1'b0 ;
pcir_fifo_control = 4'h0 ;
addr_into_cnt = 1'b0 ;
read_count_load = 1'b0 ;
read_count_enable = 1'b0 ;
wb_read_done = 1'b0 ;
read_rty_cnt_exp_out = 1'b0 ;
case ({wb_ack_i, wb_err_i, wb_rty_i})
3'b100 : // If writting of one data is acknowledged
begin
addr_count = 1'b1 ; // prepare next address if there will be burst
retried_d = 1'b0 ; // there was no retry
pci_error_sig_out = 1'b0 ; // there was no error
error_source_out = 1'b0 ;
write_rty_cnt_exp_out = 1'b0 ; // there was no retry
wait_for_wb_response = 1'b0 ;
// if last data was transfered !
if (last_data_from_pciw_fifo_reg)
begin
n_state = S_TURN_ARROUND;
if (~pciw_fifo_empty_in)
pciw_fifo_renable = 1'b0 ; // prepare next value (address when new trans., data when burst tran.)
else
pciw_fifo_renable = 1'b0 ;
last_data_transferred = 1'b1 ; // signal for last data transfered
end
// next burst data has different byte enables !
else if (burst_transfer && burst_chopped)
begin
n_state = S_IDLE ;
pciw_fifo_renable = 1'b0 ; // next value (address when new trans., data when burst tran.)
last_data_transferred = 1'b0 ;
end
else
begin
n_state = S_WRITE ;
pciw_fifo_renable = 1'b1 ; // prepare next value (address when new trans., data when burst tran.)
last_data_transferred = 1'b0 ;
end
end
3'b010 : // If writting of one data is terminated with ERROR
begin
if (~pciw_fifo_empty_in)
pciw_fifo_renable = 1'b1 ; // prepare next value (address when new trans., data when cleaning FIFO)
else
pciw_fifo_renable = 1'b0 ;
addr_count = 1'b0 ; // no need for new address
retried_d = 1'b0 ; // there was no retry
last_data_transferred = 1'b1 ; // signal for last data transfered
pci_error_sig_out = 1'b1 ; // segnal for error reporting
error_source_out = 1'b0 ; // error source from other side of WB bus
write_rty_cnt_exp_out = 1'b0 ; // there was no retry
wait_for_wb_response = 1'b0 ;
if (last_data_from_pciw_fifo_reg) // if last data was transfered
n_state = S_TURN_ARROUND ; // go to S_TURN_ARROUND for new transfere
else // if there wasn't last data of transfere
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -