From bd26f7f0adba2963f6d4a4657fe2795c696126c8 Mon Sep 17 00:00:00 2001 From: Wojciech Kosior Date: Wed, 9 Sep 2020 22:25:27 +0200 Subject: enable byte-grained reads and writes through interface_wrapper --- design/interface_wrapper.v | 225 +++++++++++++++++++++++++++++---------------- 1 file changed, 144 insertions(+), 81 deletions(-) (limited to 'design') diff --git a/design/interface_wrapper.v b/design/interface_wrapper.v index 30d2e49..ada4a3f 100644 --- a/design/interface_wrapper.v +++ b/design/interface_wrapper.v @@ -14,7 +14,7 @@ module interface_wrapper 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, /* We'll start using it soon */ + input wire [3:0] RAW_SEL_O, input wire RAW_STB_O, input wire RAW_CYC_O, input wire RAW_WE_O, @@ -30,96 +30,159 @@ module interface_wrapper input wire WRAPPED_STALL_I ); - /* RAW -> WRAPPED */ - wire wrapped_request_happens; - assign wrapped_request_happens = WRAPPED_STB_O && !WRAPPED_STALL_I; - wire raw_request_wanted; - assign raw_request_wanted = RAW_STB_O && RAW_CYC_O; - - reg [19:0] ADR_O_waiting; - reg [31:0] DAT_O_waiting; - reg WE_O_waiting; - reg [1:0] request_out_waiting; - - wire can_accept_request; - assign can_accept_request = !request_out_waiting[0] || - (!request_out_waiting[1] && - wrapped_request_happens); - - assign WRAPPED_ADR_O = request_out_waiting[0] ? - ADR_O_waiting : RAW_ADR_O >> 1; - assign WRAPPED_DAT_O = request_out_waiting[0] ? - DAT_O_waiting[15:0] : RAW_DAT_O[15:0]; - assign WRAPPED_WE_O = request_out_waiting[0] ? - WE_O_waiting : RAW_WE_O; - assign WRAPPED_STB_O = request_out_waiting[0] || raw_request_wanted; - - assign WRAPPED_CYC_O = RAW_CYC_O; - - always @ (posedge CLK_I) begin - if (RST_I) begin - ADR_O_waiting <= 20'bx; - DAT_O_waiting <= 32'bx; - WE_O_waiting <= 1'bx; - request_out_waiting <= 2'b0; - end else begin - if (wrapped_request_happens) begin - if (request_out_waiting[1]) begin - ADR_O_waiting <= ADR_O_waiting + 1; - DAT_O_waiting <= {16'bx, DAT_O_waiting[31:16]}; - request_out_waiting <= {1'b0, request_out_waiting[1]}; - end else begin - ADR_O_waiting <= RAW_ADR_O >> 1; - WE_O_waiting <= RAW_WE_O; - request_out_waiting[0] <= raw_request_wanted; - - if (request_out_waiting[0]) begin - ADR_O_waiting <= RAW_ADR_O >> 1; - DAT_O_waiting <= RAW_DAT_O; - request_out_waiting[1] <= raw_request_wanted; - end else begin - ADR_O_waiting <= (RAW_ADR_O >> 1) + 1; - DAT_O_waiting <= {16'bx, RAW_DAT_O[31:16]}; - request_out_waiting[1] <= 0; - end - end // else: !if(request_out_waiting[1]) - end else if (!request_out_waiting[0]) begin // if (wr_request_happens) - ADR_O_waiting <= RAW_ADR_O >> 1; - WE_O_waiting <= RAW_WE_O; - DAT_O_waiting <= RAW_DAT_O; - request_out_waiting <= {2{raw_request_wanted}}; - end - end // else: !if(RST_I) - end // always @ (posedge CLK_I) - - /* WRAPPED -> RAW */ + 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; - reg [15:0] DAT_I_waiting; - reg DAT_I_received; + /* "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 RAW_ACK_I = WRAPPED_ACK_I && DAT_I_received; - assign RAW_ERR_I = 0; /* We'll start using it soon */ - assign RAW_DAT_I = {WRAPPED_DAT_I, DAT_I_waiting}; - assign RAW_STALL_I = !can_accept_request; + 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_ACK_I) - DAT_I_waiting <= WRAPPED_DAT_I; - - if (RST_I) - DAT_I_received <= 0; - else if (wrapped_request_completes) - DAT_I_received <= !DAT_I_received; - end + 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 */ + /* Avoid undefined values */ initial begin - request_out_waiting <= 0; - DAT_I_waiting <= 0; + left_to_send <= 0; + STB <= 0; + acks_waited_for <= 0; + writes_back_needed <= 0; end `endif endmodule // interface_wrapper -- cgit v1.2.3