/* * This module transforms a Wishbone pipelined MASTER interface with 32-bit * data port and 8-bit granularity into one with 16-bit data port and 16-bit * granularity. It's just a wrapper, it is not considered a Wishbone SLAVE nor * MASTER by itself (although it could be presented that way). See Wishbone * datasheets of data interfaces in stack_machine.v and wrapped_stack_machine.v. */ `default_nettype none module interface_wrapper ( input wire CLK_I, input wire RST_I, output wire RAW_ACK_I, output wire RAW_ERR_I, /* We'll start using it soon */ input wire [20:0] RAW_ADR_O, output wire [31:0] RAW_DAT_I, input wire [31:0] RAW_DAT_O, input wire [3:0] RAW_SEL_O, input wire RAW_STB_O, input wire RAW_CYC_O, input wire RAW_WE_O, output wire RAW_STALL_I, input wire WRAPPED_ACK_I, output wire [19:0] WRAPPED_ADR_O, input wire [15:0] WRAPPED_DAT_I, output wire [15:0] WRAPPED_DAT_O, output wire WRAPPED_STB_O, output wire WRAPPED_CYC_O, output wire WRAPPED_WE_O, input wire WRAPPED_STALL_I ); wire raw_request_wanted; wire raw_request_completes; wire wrapped_request_sent; wire wrapped_request_completes; assign raw_request_wanted = RAW_CYC_O && RAW_STB_O; assign raw_request_completes = RAW_CYC_O && RAW_ACK_I; assign wrapped_request_sent = WRAPPED_CYC_O && WRAPPED_STB_O && !WRAPPED_STALL_I; assign wrapped_request_completes = WRAPPED_CYC_O && WRAPPED_ACK_I; /* "Parsing" raw command */ wire nothing_selected; wire [1:0] highest_selected_byte; wire [1:0] transfers_needed; wire start_with_read; assign nothing_selected = RAW_SEL_O == 4'b0; assign highest_selected_byte = RAW_SEL_O[3] ? 3 : RAW_SEL_O[2] ? 2 : RAW_SEL_O[1] ? 1 : 0; assign transfers_needed = nothing_selected ? 1 : (RAW_ADR_O[0] + highest_selected_byte + 2) / 2; assign start_with_read = !RAW_WE_O || RAW_ADR_O[0] || RAW_SEL_O[0] != RAW_SEL_O[1] || RAW_SEL_O[2] != RAW_SEL_O[3] || nothing_selected; /* Sending commands */ reg [1:0] left_to_send; reg [19:0] ADR; reg WE; reg STB; reg [47:0] write_data; /* Receiving responses */ reg [31:0] received_data_part; reg [1:0] acks_waited_for; reg [20:0] saved_ADR; reg [1:0] writes_back_needed; reg [4:0] write_mask; wire [47:0] received_data; wire command_sequence_finishes; wire can_accept_raw_command; assign received_data = {received_data_part, WRAPPED_DAT_I}; assign command_sequence_finishes = acks_waited_for == 1 && WRAPPED_ACK_I; assign can_accept_raw_command = acks_waited_for == 0 || (writes_back_needed == 0 && command_sequence_finishes); assign RAW_ACK_I = writes_back_needed == 0 && command_sequence_finishes; assign RAW_DAT_I = saved_ADR[0] ? received_data >> 8 : received_data; assign RAW_STALL_I = !can_accept_raw_command; assign WRAPPED_CYC_O = RAW_CYC_O; assign WRAPPED_ADR_O = ADR; assign WRAPPED_WE_O = WE; assign WRAPPED_STB_O = STB; assign WRAPPED_DAT_O = write_data[15:0]; always @ (posedge CLK_I) begin if (wrapped_request_sent) begin /* Variable assignments here are overridden further down */ left_to_send <= left_to_send - 1; if (WE) ADR <= ADR + 1; else ADR <= ADR - 1; if (left_to_send == 1) STB <= 0; if (WE) write_data <= {16'bx, write_data[47:16]}; end // if (wrapped_request_sent) if (wrapped_request_completes) begin received_data_part <= {received_data_part[15:0], WRAPPED_DAT_I}; acks_waited_for <= acks_waited_for - 1; /* might get overridden */ end if (writes_back_needed != 0 && command_sequence_finishes) begin /* Write data back */ left_to_send <= writes_back_needed; ADR <= saved_ADR[20:1]; WE <= 1; STB <= 1; write_data[47:40] <= received_data[47:40]; if (!write_mask[4]) write_data[39:32] <= received_data[39:32]; if (!write_mask[3]) write_data[31:24] <= received_data[31:24]; if (!write_mask[2]) write_data[23:16] <= received_data[23:16]; if (!write_mask[1]) write_data[15:8] <= received_data[15:8]; if (!write_mask[0]) write_data[7:0] <= received_data[7:0]; acks_waited_for <= writes_back_needed; writes_back_needed <= 0; end // if (writes_back_needed != 0 && command_sequence_finishes) if (raw_request_wanted && can_accept_raw_command) begin /* Setting up for sending commands */ left_to_send <= transfers_needed; if (start_with_read) ADR <= RAW_ADR_O[20:1] + transfers_needed - 1; else ADR <= RAW_ADR_O[20:1]; WE <= !start_with_read; STB <= 1; if (RAW_ADR_O[0]) write_data <= {8'bx, RAW_DAT_O, 8'bx}; else write_data <= {16'bx, RAW_DAT_O}; /* Setting up for receiving responses */ acks_waited_for <= transfers_needed; saved_ADR <= RAW_ADR_O; if (RAW_WE_O && start_with_read && !nothing_selected) writes_back_needed <= transfers_needed; else writes_back_needed <= 0; if (RAW_ADR_O[0]) write_mask <= {RAW_SEL_O, 1'b0}; else write_mask <= {1'b0, RAW_SEL_O}; end // if (raw_request_wanted && can_accept_raw_command) /* Override what's needed */ if (RST_I) begin left_to_send <= 0; STB <= 0; acks_waited_for <= 0; writes_back_needed <= 0; end end // always @ (posedge CLK_I) `ifdef SIMULATION /* Avoid undefined values */ initial begin left_to_send <= 0; STB <= 0; acks_waited_for <= 0; writes_back_needed <= 0; end `endif endmodule // interface_wrapper