diff --git a/axis_width_converter_test_behav.wcfg b/axis_width_converter_test_behav.wcfg
index fab0bee..df855ce 100644
--- a/axis_width_converter_test_behav.wcfg
+++ b/axis_width_converter_test_behav.wcfg
@@ -11,15 +11,15 @@
-
-
-
+
+
+
-
-
+
+
-
+
test
label
@@ -32,23 +32,11 @@
clk
clk
-
- downsizer_readout_mode[1:0]
- downsizer_readout_mode[1:0]
-
-
- upsizer_readout_mode[1:0]
- upsizer_readout_mode[1:0]
-
-
- rec_count[31:0]
- rec_count[31:0]
- SIGNEDDECRADIX
-
downsizer_in
label
+
data[255:0]
data[255:0]
@@ -74,8 +62,8 @@
downsizer_out
label
- data[127:0]
- data[127:0]
+ data[63:0]
+ data[63:0]
ready
@@ -106,8 +94,8 @@
reset
- data_reg[1:0][127:0]
- data_reg[1:0][127:0]
+ data_reg[3:0][63:0]
+ data_reg[3:0][63:0]
valid_reg
@@ -118,8 +106,8 @@
last_reg
- counter[0:0]
- counter[0:0]
+ counter[1:0]
+ counter[1:0]
read_final
@@ -133,6 +121,7 @@
upsizer_in
label
+
data[15:0]
data[15:0]
@@ -157,6 +146,7 @@
upsizer_out
label
+
data[127:0]
data[127:0]
@@ -199,4 +189,212 @@
counter[2:0]
+
+ sent_word[63:0]
+ sent_word[63:0]
+
+
+ received_word[63:0]
+ received_word[63:0]
+
+
+ data[1:0][2:0][255:0]
+ data[1:0][2:0][255:0]
+
+ [1][2:0][255:0]
+ [1][2:0][255:0]
+
+
+
+ [0][2:0][255:0]
+ [0][2:0][255:0]
+
+
+
+
+ DWIDTH[31:0]
+ DWIDTH[31:0]
+ UNSIGNEDDECRADIX
+
+
+ comb_in
+ label
+
+ data[191:0]
+ data[191:0]
+
+
+ ready
+ ready
+
+
+ valid
+ valid
+
+
+ last
+ last
+
+
+ ok
+ ok
+
+
+
+ comb_out
+ label
+
+ data[255:0]
+ data[255:0]
+
+
+ ready
+ ready
+
+
+ valid
+ valid
+
+
+ last
+ last
+
+
+ ok
+ ok
+
+
+
+ comb_dut
+ label
+
+
+ clk
+ clk
+
+
+ reset
+ reset
+
+
+ DWIDTH_IN[31:0]
+ DWIDTH_IN[31:0]
+
+
+ UP[31:0]
+ UP[31:0]
+
+
+ DOWN[31:0]
+ DOWN[31:0]
+
+
+ comb_dut_up
+ label
+
+ clk
+ clk
+
+
+ reset
+ reset
+
+
+ data_reg[3:0][191:0]
+ data_reg[3:0][191:0]
+
+
+ counter[1:0]
+ counter[1:0]
+
+
+ DWIDTH[31:0]
+ DWIDTH[31:0]
+
+
+ UP[31:0]
+ UP[31:0]
+
+
+ DWIDTH_OUT[31:0]
+ DWIDTH_OUT[31:0]
+
+
+
+ comb_dut_down
+ label
+
+ clk
+ clk
+
+
+ reset
+ reset
+
+
+ data_reg[2:0][63:0]
+ data_reg[2:0][63:0]
+
+
+ valid_reg
+ valid_reg
+
+
+ last_reg
+ last_reg
+
+
+ counter[1:0]
+ counter[1:0]
+
+
+ read_final
+ read_final
+
+
+ rollover
+ rollover
+
+
+ DWIDTH[31:0]
+ DWIDTH[31:0]
+
+
+ DOWN[31:0]
+ DOWN[31:0]
+
+
+ DWIDTH_OUT[31:0]
+ DWIDTH_OUT[31:0]
+
+
+
+ comb_dut_up_out
+ label
+
+ data[767:0]
+ data[767:0]
+
+
+ ready
+ ready
+
+
+ valid
+ valid
+
+
+ last
+ last
+
+
+ ok
+ ok
+
+
+ DWIDTH[31:0]
+ DWIDTH[31:0]
+
+
+
diff --git a/dds_test.srcs/sim_1/new/axis_width_converter_test.sv b/dds_test.srcs/sim_1/new/axis_width_converter_test.sv
index b98e1d6..1a32484 100644
--- a/dds_test.srcs/sim_1/new/axis_width_converter_test.sv
+++ b/dds_test.srcs/sim_1/new/axis_width_converter_test.sv
@@ -10,14 +10,14 @@ int error_count;
localparam int DWIDTH_DOWN_IN = 256;
localparam int DWIDTH_UP_IN = 16;
-localparam int DWIDTH_COMB_IN = 192;
+localparam int DWIDTH_COMB_IN = 24;
localparam int DOWN = 4;
localparam int UP = 8;
localparam int COMB_UP = 4;
localparam int COMB_DOWN = 3;
-let max(a,b) = (a > b) ? a : b;
-localparam int DWIDTH = max(max(max(DWIDTH_DOWN_IN, DWIDTH_UP_IN*UP), (DWIDTH_COMB_IN*COMB_UP)/COMB_DOWN), DWIDTH_COMB_IN);
+`define MAX(A,B) (A > B) ? A : B
+localparam int DWIDTH = `MAX(`MAX(`MAX(DWIDTH_DOWN_IN, DWIDTH_UP_IN*UP), (DWIDTH_COMB_IN*COMB_UP)/COMB_DOWN), DWIDTH_COMB_IN);
Axis_If #(.DWIDTH(DWIDTH_DOWN_IN)) downsizer_in ();
Axis_If #(.DWIDTH(DWIDTH_DOWN_IN/DOWN)) downsizer_out ();
@@ -83,29 +83,37 @@ assign downsizer_out.ready = out_ready[0];
assign upsizer_out.ready = out_ready[1];
assign comb_out.ready = out_ready[2];
+logic [2:0] in_valid;
+assign downsizer_in.valid = in_valid[0];
+assign upsizer_in.valid = in_valid[1];
+assign comb_in.valid = in_valid[2];
+
logic [1:0][2:0] last;
-assign last[0][0] = downsizer_in.last;
-assign last[0][1] = upsizer_in.last;
-assign last[0][2] = comb_in.last;
+assign downsizer_in.last = last[0][0];
+assign upsizer_in.last = last[0][1];
+assign comb_in.last = last[0][2];
assign last[1][0] = downsizer_out.last;
assign last[1][1] = upsizer_out.last;
assign last[1][2] = comb_out.last;
localparam [1:0][2:0][31:0] NUM_WORDS = '{
- '{DOWN, 1, COMB_DOWN},
- '{1, UP, COMB_UP}
+ '{COMB_UP, UP, 1}, // output words
+ '{COMB_DOWN, 1, DOWN} // input words
};
localparam [2:0][31:0] WORD_SIZE = '{
- DWIDTH_DOWN_IN/DOWN, // downsizer
+ DWIDTH_COMB_IN/COMB_DOWN, // both
DWIDTH_UP_IN, // upsizer
- DWIDTH_COMB_IN/COMB_DOWN // both
+ DWIDTH_DOWN_IN/DOWN // downsizer
};
+localparam MAX_WORD_SIZE = `MAX(`MAX(WORD_SIZE[0],WORD_SIZE[1]),WORD_SIZE[2]);
+logic [MAX_WORD_SIZE-1:0] sent_word, received_word;
+
// update data and track sent/received samples
always_ff @(posedge clk) begin
if (reset) begin
- data_in <= '0;
+ data[1] <= '0;
end else begin
for (int i = 0; i < 3; i++) begin
// inputs
@@ -115,7 +123,10 @@ always_ff @(posedge clk) begin
end
// save data that was sent, split up into individual "words"
for (int j = 0; j < NUM_WORDS[0][i]; j++) begin
- sent[i].push_front(data[0][i][j*WORD_SIZE[i]+:WORD_SIZE[i]]);
+ for (int k = 0; k < WORD_SIZE[i]; k++) begin
+ sent_word[k] = data[0][i][j*WORD_SIZE[i]+k];
+ end
+ sent[i].push_front(sent_word);
end
if (last[0][i]) begin
last_sent[i].push_front(sent[i].size());
@@ -125,7 +136,10 @@ always_ff @(posedge clk) begin
if (ok[1][i]) begin
// save data that was received, split up into individual "words"
for (int j = 0; j < NUM_WORDS[1][i]; j++) begin
- received[i].push_front(data[1][i][j*WORD_SIZE[i]+:WORD_SIZE[i]]);
+ for (int k = 0; k < WORD_SIZE[i]; k++) begin
+ received_word[k] = data[1][i][j*WORD_SIZE[i]+k];
+ end
+ received[i].push_front(received_word);
end
if (last[1][i]) begin
last_received[i].push_front(received[i].size());
@@ -183,7 +197,7 @@ task check_dut(input int dut_select);
while (sent[dut_select].size() > 0 && received[dut_select].size() > 0) begin
if (sent[dut_select][$] != received[dut_select][$]) begin
error_count = error_count + 1;
- $warning("data mismatch error (received %x, sent %x)", received[dut_select][$], sent[dut_select][$]);
+ $warning("data mismatch error (received %x, sent %x)", received[dut_select][$] & ((1 << WORD_SIZE[dut_select]) - 1), sent[dut_select][$] & ((1 << WORD_SIZE[dut_select]) - 1));
end
sent[dut_select].pop_back();
received[dut_select].pop_back();
@@ -193,17 +207,21 @@ endtask
// actually do the test
initial begin
reset <= 1'b1;
-
- downsizer_in.valid <= '0;
- upsizer_in.valid <= '0;
- comb_in.valid <= '0;
+ // reset input valid
+ in_valid <= '0;
+ // reset input last
last[0] <= '0;
+ // set readout mode to off for all DUTs(readout disabled)
readout_mode <= '0;
+ // reset input data
+ data[0] <= '0;
repeat (50) @(posedge clk);
reset <= 1'b0;
repeat (50) @(posedge clk);
+
+ // do test
for (int i = 0; i < 3; i++) begin
$display("#################################################");
unique case (i)
@@ -213,56 +231,45 @@ initial begin
endcase
$display("#################################################");
for (int j = 1; j <= 2; j++) begin
+ // cycle between continuously-high and randomly toggling ready signal on output interface
readout_mode[i] <= j;
unique case (i)
0: begin
- downsizer_in.send_samples(clk, 5, 1'b1, 1'b0);
- downsizer_in.send_samples(clk, 8, 1'b0, 1'b0);
- downsizer_in.send_samples(clk, 7, 1'b1, 1'b0);
+ // send 5 samples with random arrivals
+ downsizer_in.send_samples(clk, 5, 1'b1, 1'b1);
+ // send 8 samples all at once
+ downsizer_in.send_samples(clk, 8, 1'b0, 1'b1);
+ // send 10 samples with random arrivals
+ downsizer_in.send_samples(clk, 10, 1'b1, 1'b1);
end
1: begin
- upsizer_in.send_samples(clk, 5, 1'b1, 1'b0);
- upsizer_in.send_samples(clk, 8, 1'b0, 1'b0);
- upsizer_in.send_samples(clk, 7, 1'b1, 1'b0);
+ upsizer_in.send_samples(clk, 5, 1'b1, 1'b1);
+ upsizer_in.send_samples(clk, 8, 1'b0, 1'b1);
+ upsizer_in.send_samples(clk, 10, 1'b1, 1'b1);
end
2: begin
- comb_in.send_samples(clk, 5, 1'b1, 1'b0);
- comb_in.send_samples(clk, 8, 1'b0, 1'b0);
- comb_in.send_samples(clk, 7, 1'b1, 1'b0);
+ comb_in.send_samples(clk, 5, 1'b1, 1'b1);
+ comb_in.send_samples(clk, 8, 1'b0, 1'b1);
+ comb_in.send_samples(clk, 10, 1'b1, 1'b1);
end
+ endcase
last[0][i] <= 1'b1;
- downsizer_in.valid <= 1'b1;
- do begin @(posedge clk); end while (!downsizer_in.ok);
- last[0][0] <= 1'b0;
- downsizer_in.valid <= 1'b0;
- // check downsizer
- do begin @(posedge clk); end while (!(downsizer_out.last && downsizer_out.ok));
- check_downsizer();
+ in_valid[i] <= 1'b1;
+ // wait until last is actually registered by the DUT before deasserting it
+ do begin @(posedge clk); end while (!ok[0][i]);
+ last[0][i] <= 1'b0;
+ in_valid[i] <= 1'b0;
+
+ // read out everything, waiting until last signal on DUT output
+ do begin @(posedge clk); end while (!(last[1][i] && ok[1][i]));
+ // check the output data matches the input
+ check_dut(i);
repeat (100) @(posedge clk);
end
+ // disable readout of DUT when finished
readout_mode[i] <= '0;
end
- repeat (10) @(posedge clk);
- $display("#################################################");
- $display("# finished testing downsizer, testing upsizer #");
- $display("#################################################");
- // check upsizer
- for (int i = 1; i <= 2; i++) begin
- upsizer_readout_mode <= i;
- upsizer_in.send_samples(clk, 27, 1'b1, 1'b0);
- upsizer_in.send_samples(clk, 19, 1'b0, 1'b0);
- upsizer_in.send_samples(clk, 17, 1'b1, 1'b0);
- upsizer_in.last <= 1'b1;
- upsizer_in.valid <= 1'b1;
- do begin @(posedge clk); end while (!upsizer_in.ok);
- upsizer_in.last <= 1'b0;
- upsizer_in.valid <= 1'b0;
- // check upsizer
- do begin @(posedge clk); end while (!(upsizer_out.last && upsizer_out.ok));
- check_upsizer();
- repeat (100) @(posedge clk);
- end
- upsizer_readout_mode <= 2'b00;
+
$display("#################################################");
if (error_count == 0) begin
$display("# finished with zero errors");
diff --git a/dds_test.srcs/sources_1/new/axis.sv b/dds_test.srcs/sources_1/new/axis.sv
index 5fb1d4e..ab8267e 100644
--- a/dds_test.srcs/sources_1/new/axis.sv
+++ b/dds_test.srcs/sources_1/new/axis.sv
@@ -98,13 +98,13 @@ task automatic send_samples(
samples_sent = 0;
valid <= 1'b1;
while (samples_sent < n_samples) begin
+ @(posedge clk);
if (ok) begin
samples_sent = samples_sent + 1'b1;
end
if (rand_arrivals) begin
valid <= $urandom() & 1'b1;
end // else do nothing; intf.valid is already 1'b1
- @(posedge clk);
end
if (reset_valid) begin
valid <= '0;
diff --git a/dds_test.srcs/sources_1/new/axis_width_converter.sv b/dds_test.srcs/sources_1/new/axis_width_converter.sv
index ff92b7b..54eca37 100644
--- a/dds_test.srcs/sources_1/new/axis_width_converter.sv
+++ b/dds_test.srcs/sources_1/new/axis_width_converter.sv
@@ -1,5 +1,9 @@
// width converter
-// constructs multiple DOWN -> UP resizers in parallel to operate at high throughput
+// constructs a single UP -> DOWN resizer
+// The UP resizer always accepts samples, so it can run at full rate.
+// Therefore, the rate of the input is limited by the output rate.
+// If DOWN > UP, then the input must stall occasionally, which is to be
+// expected.
module axis_width_converter #(
parameter int DWIDTH_IN = 192,
parameter int UP = 4,
@@ -23,13 +27,13 @@ axis_upsizer #(
);
axis_downsizer #(
- .DWIDTH(DWIDTH_IN),
+ .DWIDTH(DWIDTH_IN*UP),
.DOWN(DOWN)
-) up_i (
+) down_i (
.clk,
.reset,
.data_in(data),
- .data_out,
+ .data_out
);
endmodule