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 +++++++++++++++++---------- tests/interface_wrapper/operations.memv | 39 +++++ tests/interface_wrapper/test.v | 6 +- tests/wrapped_stack_machine_cond_jump/test.v | 6 +- 4 files changed, 189 insertions(+), 87 deletions(-) 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 diff --git a/tests/interface_wrapper/operations.memv b/tests/interface_wrapper/operations.memv index 2b581b5..97237f0 100644 --- a/tests/interface_wrapper/operations.memv +++ b/tests/interface_wrapper/operations.memv @@ -1,5 +1,7 @@ `include "macroasm.vh" // look into macroasm.vh for more info +//// First half of operations has (SEL_O == 4'b111 && ADR_O[0] == 0) + // First - a sequence of reads and writes like in self_32bit_word test `WRITE(000000, deadbeef) `WAIT @@ -49,3 +51,40 @@ `WRITE(012302, 0fca0000) `WRITE(012306, 0000baca) `READ (012304, baca0fca) + + +//// Second half with non-aligned accesses and weird SEL_O patterns starts here + +`WRITE (200013, afe8b317) +`READ (200013, afe8b317) + +`WRITES(140022, xxxxd0d3, 3) // Only select 2 bottom bytes +`READS (140022, xxxxd0d3, 3) + +`WRITES(140022, xx48e2xx, 6) // Only select 2 middle bytes +`READS (140022, xx48e2xx, 6) +`READS (140022, xx48e2d3, f) // Select 3 bottom bytes + +`WRITES(140025, xxxxxx72, 1) // Single byte write at odd address +`WRITES(140024, xxxx7248, 3) +`READS (140023, xx7248e2, 7) // Non-aligned read + +`DESELECT + +// Some other complicated stuff +`WRITES(2013e4, 1182bbxx, a) +`WAIT +`WRITES(2013e6, xx10xxa2, 5) +`WAIT +`WAIT +`WAIT +`READS (2013e5, 1011a2bb, f) +`READS (2013e7, 23232323, 0) + +`DESELECT +`WAIT +`WRITES(987135, 8dxxxx1e, 9) +`WRITES(987137, xxxxxx3f, 1) +`WRITES(987135, fedcba98, 0) // Should not do anything +`WRITES(987133, 44xxxxxx, 8) +`READS (987135, 8d3f441e, f) diff --git a/tests/interface_wrapper/test.v b/tests/interface_wrapper/test.v index 4031f35..d69970a 100644 --- a/tests/interface_wrapper/test.v +++ b/tests/interface_wrapper/test.v @@ -145,7 +145,7 @@ interface_wrapper wrapper CLK <= 0; RST <= 1; - for (i = 0; i < 600; i++) begin + for (i = 0; i < 2000; i++) begin #1; CLK <= ~CLK; @@ -155,9 +155,9 @@ interface_wrapper wrapper if (M_finished) $finish; - end + end // for (i = 0; i < 2000; i++) - $display("error: master hasn't finished its operations in 300 ticks"); + $display("error: master hasn't finished its operations in 1000 ticks"); $finish; end endmodule // interface_wrapper_test diff --git a/tests/wrapped_stack_machine_cond_jump/test.v b/tests/wrapped_stack_machine_cond_jump/test.v index 7845045..ae50d4d 100644 --- a/tests/wrapped_stack_machine_cond_jump/test.v +++ b/tests/wrapped_stack_machine_cond_jump/test.v @@ -161,7 +161,7 @@ module wrapped_stack_machine_test(); CLK <= 0; RST <= 1; - for (i = 0; i < 3500; i++) begin + for (i = 0; i < 5000; i++) begin #1; CLK <= ~CLK; @@ -185,9 +185,9 @@ module wrapped_stack_machine_test(); $finish; end // if (M_finished) - end // for (i = 0; i < 3500; i++) + end // for (i = 0; i < 5000; i++) - $display("error: cpu hasn't finished its operations in 1750 ticks"); + $display("error: cpu hasn't finished its operations in 2500 ticks"); $finish; end // initial begin endmodule // wrapped_stack_machine_test -- cgit v1.2.3