aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWojciech Kosior <kwojtus@protonmail.com>2020-09-09 22:25:27 +0200
committerWojciech Kosior <kwojtus@protonmail.com>2020-09-09 22:25:27 +0200
commitbd26f7f0adba2963f6d4a4657fe2795c696126c8 (patch)
tree09d3fbbe91815d57d7cf3d89cb84c40ed49853b7
parent334f86ccc899b92e44f71f1ad85dcc3c31ef1a2c (diff)
downloadAGH-engineering-thesis-bd26f7f0adba2963f6d4a4657fe2795c696126c8.tar.gz
AGH-engineering-thesis-bd26f7f0adba2963f6d4a4657fe2795c696126c8.zip
enable byte-grained reads and writes through interface_wrapper
-rw-r--r--design/interface_wrapper.v225
-rw-r--r--tests/interface_wrapper/operations.memv39
-rw-r--r--tests/interface_wrapper/test.v6
-rw-r--r--tests/wrapped_stack_machine_cond_jump/test.v6
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