Add ability to poll interrupt / DMA status for multiple slaves attached to the FSI master

parent 4020a96e
......@@ -18,10 +18,11 @@ module fsi_master_interface(
output wire [2:0] cycle_error,
input wire [1:0] enhanced_error_recovery, // Bit 1 == EER for IPOLL, Bit 0 == EER for all other transmissions
input wire [7:0] internal_cmd_issue_delay,
input wire [3:0] ipoll_enable_slave_id, // Bitwise field, enable for I_POLL to slaves 3 - 0
input wire enable_ipoll,
output wire ipoll_error,
output wire [1:0] interrupt_field,
output wire [2:0] dma_control_field,
output wire [7:0] interrupt_field,
output wire [11:0] dma_control_field,
output wire fsi_data_out, // Must have I/O output register enabled in top level SB_IO or equivalent, output data driven at rising edge of clock
input wire fsi_data_in,
......@@ -158,11 +159,14 @@ module fsi_master_interface(
reg [1:0] slave_error_recovery_state = 0;
reg [1:0] master_error_recovery_state = 0;
reg [7:0] ipoll_start_timer = 0;
reg enable_ipoll_reg = 0;
reg [3:0] ipoll_enable_slave_id_reg = 0;
reg [1:0] ipoll_slave_id = 0;
reg ipoll_in_process = 0;
reg busy_response_in_process = 0;
reg [1:0] commands_since_last_ipoll = 0;
reg [1:0] interrupt_field_internal = 0;
reg [2:0] dma_control_field_internal = 0;
reg [7:0] interrupt_field_internal = 0;
reg [11:0] dma_control_field_internal = 0;
assign debug_port = control_state;
......@@ -226,13 +230,13 @@ module fsi_master_interface(
end
FSI_TRANSFER_STATE_IDLE: begin
if (busy_response_in_process
&& ((enable_ipoll && (commands_since_last_ipoll < FSI_IPOLL_MAX_SEQ_STD_COMMANDS)) || !enable_ipoll)) begin
&& ((enable_ipoll_reg && (commands_since_last_ipoll < FSI_IPOLL_MAX_SEQ_STD_COMMANDS)) || !enable_ipoll_reg)) begin
commands_since_last_ipoll <= commands_since_last_ipoll + 1;
ipoll_in_process <= 0;
crc_data <= 0;
control_state <= FSI_TRANSFER_STATE_TX01;
end else if (start_cycle
&& ((enable_ipoll && (commands_since_last_ipoll < FSI_IPOLL_MAX_SEQ_STD_COMMANDS)) || !enable_ipoll)) begin
&& ((enable_ipoll_reg && (commands_since_last_ipoll < FSI_IPOLL_MAX_SEQ_STD_COMMANDS)) || !enable_ipoll_reg)) begin
data_direction_reg <= data_direction;
data_length_reg <= data_length;
slave_id_reg <= slave_id;
......@@ -256,7 +260,7 @@ module fsi_master_interface(
fsi_master_timeout_counting <= 0;
commands_since_last_ipoll <= commands_since_last_ipoll + 1;
control_state <= FSI_TRANSFER_STATE_TX01;
end else if (enable_ipoll && ((ipoll_start_timer > FSI_IPOLL_IDLE_START_CYCLES)
end else if (enable_ipoll_reg && ((ipoll_start_timer > FSI_IPOLL_IDLE_START_CYCLES)
|| (commands_since_last_ipoll >= FSI_IPOLL_MAX_SEQ_STD_COMMANDS))) begin
// Send I_POLL
//
......@@ -264,7 +268,22 @@ module fsi_master_interface(
// if no IPOLL has been issued for the past FSI_IPOLL_MAX_SEQ_STD_COMMANDS
// number of command requests. This is to ensure that interrupts are not
// lost under heavy I/O load.
if (enable_ipoll) begin
//
// We cycle through all enabled slaves, with the slave changing on each I_POLL call.
// The specification is unfortunately silent as to whether this is the intended
// mechanism to gather data from all slaves on a bus, but it seems to be a
// reasonable way to handle the interrupt polling requirements for all slaves...
if (enable_ipoll_reg && ipoll_enable_slave_id_reg) begin
ipoll_slave_id = ipoll_slave_id + 1;
if (!ipoll_enable_slave_id_reg[ipoll_slave_id]) begin
ipoll_slave_id = ipoll_slave_id + 1;
end
if (!ipoll_enable_slave_id_reg[ipoll_slave_id]) begin
ipoll_slave_id = ipoll_slave_id + 1;
end
if (!ipoll_enable_slave_id_reg[ipoll_slave_id]) begin
ipoll_slave_id = ipoll_slave_id + 1;
end
fsi_command_code <= FSI_CODEWORD_TX_MSG_I_POLL_DAT;
fsi_command_code_length <= FSI_CODEWORD_TX_MSG_I_POLL_LEN;
cycle_counter <= FSI_CODEWORD_TX_MSG_I_POLL_LEN;
......@@ -279,9 +298,11 @@ module fsi_master_interface(
ipoll_in_process <= 0;
ipoll_start_timer <= ipoll_start_timer + 1;
end
if (!enable_ipoll) begin
if (!enable_ipoll_reg) begin
ipoll_error_reg <= 0;
end
enable_ipoll_reg <= enable_ipoll;
ipoll_enable_slave_id_reg <= ipoll_enable_slave_id;
internal_cmd_issue_delay_reg <= internal_cmd_issue_delay;
cycle_complete_reg <= 0;
end
......@@ -296,14 +317,22 @@ module fsi_master_interface(
// Send slave ID bit 1
fsi_data_direction_reg <= 1;
crc_protected_bits_transmitting = 1;
fsi_data_reg_internal = slave_id_reg[1];
if (ipoll_in_process) begin
fsi_data_reg_internal = ipoll_slave_id[1];
end else begin
fsi_data_reg_internal = slave_id_reg[1];
end
control_state <= FSI_TRANSFER_STATE_TX03;
end
FSI_TRANSFER_STATE_TX03: begin
// Send slave ID bit 2
fsi_data_direction_reg <= 1;
crc_protected_bits_transmitting = 1;
fsi_data_reg_internal = slave_id_reg[0];
if (ipoll_in_process) begin
fsi_data_reg_internal = ipoll_slave_id[0];
end else begin
fsi_data_reg_internal = slave_id_reg[0];
end
if (!fsi_command_code_set) begin
if (enable_relative_address_reg) begin
if (last_address_valid && (last_address[20:2] == address_reg[20:2])) begin
......@@ -826,31 +855,31 @@ module fsi_master_interface(
FSI_TRANSFER_STATE_IR01: begin
// Receive interrupt field, bit 1
crc_protected_bits_receiving = 1;
interrupt_field_internal[1] <= fsi_data_in_internal;
interrupt_field_internal[(ipoll_slave_id*2)+1] <= fsi_data_in_internal;
control_state <= FSI_TRANSFER_STATE_IR02;
end
FSI_TRANSFER_STATE_IR02: begin
// Receive interrupt field, bit 2
crc_protected_bits_receiving = 1;
interrupt_field_internal[0] <= fsi_data_in_internal;
interrupt_field_internal[(ipoll_slave_id*2)+0] <= fsi_data_in_internal;
control_state <= FSI_TRANSFER_STATE_IR03;
end
FSI_TRANSFER_STATE_IR03: begin
// Receive DMA control field, bit 1
crc_protected_bits_receiving = 1;
dma_control_field_internal[2] <= fsi_data_in_internal;
dma_control_field_internal[(ipoll_slave_id*3)+2] <= fsi_data_in_internal;
control_state <= FSI_TRANSFER_STATE_IR04;
end
FSI_TRANSFER_STATE_IR04: begin
// Receive DMA control field, bit 2
crc_protected_bits_receiving = 1;
dma_control_field_internal[1] <= fsi_data_in_internal;
dma_control_field_internal[(ipoll_slave_id*3)+1] <= fsi_data_in_internal;
control_state <= FSI_TRANSFER_STATE_IR05;
end
FSI_TRANSFER_STATE_IR05: begin
// Receive DMA control field, bit 3
crc_protected_bits_receiving = 1;
dma_control_field_internal[0] <= fsi_data_in_internal;
dma_control_field_internal[(ipoll_slave_id*3)+0] <= fsi_data_in_internal;
cycle_counter <= 4;
control_state <= FSI_TRANSFER_STATE_RX06;
end
......
......@@ -49,7 +49,8 @@ module fsi_test();
.cycle_complete(cycle_complete),
.cycle_error(cycle_error),
.enhanced_error_recovery(enhanced_error_recovery),
.internal_cmd_issue_delay(0),
.internal_cmd_issue_delay(8'h00),
.ipoll_enable_slave_id(4'b0001),
.enable_ipoll(enable_ipoll),
.ipoll_error(ipoll_error),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment