aboutsummaryrefslogtreecommitdiffstats
path: root/tests/xilinx
diff options
context:
space:
mode:
Diffstat (limited to 'tests/xilinx')
-rw-r--r--tests/xilinx/.gitignore1
-rw-r--r--tests/xilinx/dsp_simd.ys25
-rw-r--r--tests/xilinx/macc.sh3
-rw-r--r--tests/xilinx/macc.v84
-rw-r--r--tests/xilinx/macc.ys31
-rw-r--r--tests/xilinx/macc_tb.v96
-rw-r--r--tests/xilinx/mul_unsigned.v30
-rw-r--r--tests/xilinx/mul_unsigned.ys10
8 files changed, 280 insertions, 0 deletions
diff --git a/tests/xilinx/.gitignore b/tests/xilinx/.gitignore
index b48f808a1..54733fb71 100644
--- a/tests/xilinx/.gitignore
+++ b/tests/xilinx/.gitignore
@@ -1,3 +1,4 @@
/*.log
/*.out
/run-test.mk
+/*_uut.v
diff --git a/tests/xilinx/dsp_simd.ys b/tests/xilinx/dsp_simd.ys
new file mode 100644
index 000000000..956952327
--- /dev/null
+++ b/tests/xilinx/dsp_simd.ys
@@ -0,0 +1,25 @@
+read_verilog <<EOT
+module simd(input [12*4-1:0] a, input [12*4-1:0] b, (* use_dsp="simd" *) output [7*12-1:0] o12, (* use_dsp="simd" *) output [2*24-1:0] o24);
+generate
+ genvar i;
+ // 4 x 12-bit adder
+ for (i = 0; i < 4; i++)
+ assign o12[i*12+:12] = a[i*12+:12] + b[i*12+:12];
+ // 2 x 24-bit subtract
+ for (i = 0; i < 2; i++)
+ assign o24[i*24+:24] = a[i*24+:24] - b[i*24+:24];
+endgenerate
+reg [3*12-1:0] ro;
+always @* begin
+ ro[0*12+:12] = a[0*10+:10] + b[0*10+:10];
+ ro[1*12+:12] = a[1*10+:10] + b[1*10+:10];
+ ro[2*12+:12] = a[2*8+:8] + b[2*8+:8];
+end
+assign o12[4*12+:3*12] = ro;
+endmodule
+EOT
+
+proc
+equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx
+design -load postopt
+select -assert-count 3 t:DSP48E1
diff --git a/tests/xilinx/macc.sh b/tests/xilinx/macc.sh
new file mode 100644
index 000000000..86e4c2bb6
--- /dev/null
+++ b/tests/xilinx/macc.sh
@@ -0,0 +1,3 @@
+../../yosys -qp "synth_xilinx -top macc2; rename -top macc2_uut" macc.v -o macc_uut.v
+iverilog -o test_macc macc_tb.v macc_uut.v macc.v ../../techlibs/xilinx/cells_sim.v
+vvp -N ./test_macc
diff --git a/tests/xilinx/macc.v b/tests/xilinx/macc.v
new file mode 100644
index 000000000..e36b2bab1
--- /dev/null
+++ b/tests/xilinx/macc.v
@@ -0,0 +1,84 @@
+// Signed 40-bit streaming accumulator with 16-bit inputs
+// File: HDL_Coding_Techniques/multipliers/multipliers4.v
+//
+// Source:
+// https://www.xilinx.com/support/documentation/sw_manuals/xilinx2014_2/ug901-vivado-synthesis.pdf p.90
+//
+module macc # (parameter SIZEIN = 16, SIZEOUT = 40) (
+ input clk, ce, sload,
+ input signed [SIZEIN-1:0] a, b,
+ output signed [SIZEOUT-1:0] accum_out
+);
+// Declare registers for intermediate values
+reg signed [SIZEIN-1:0] a_reg, b_reg;
+reg sload_reg;
+reg signed [2*SIZEIN-1:0] mult_reg;
+reg signed [SIZEOUT-1:0] adder_out, old_result;
+always @* /*(adder_out or sload_reg)*/ begin // Modification necessary to fix sim/synth mismatch
+ if (sload_reg)
+ old_result <= 0;
+ else
+ // 'sload' is now active (=low) and opens the accumulation loop.
+ // The accumulator takes the next multiplier output in
+ // the same cycle.
+ old_result <= adder_out;
+end
+
+always @(posedge clk)
+ if (ce)
+ begin
+ a_reg <= a;
+ b_reg <= b;
+ mult_reg <= a_reg * b_reg;
+ sload_reg <= sload;
+ // Store accumulation result into a register
+ adder_out <= old_result + mult_reg;
+ end
+
+// Output accumulation result
+assign accum_out = adder_out;
+
+endmodule
+
+// Adapted variant of above
+module macc2 # (parameter SIZEIN = 16, SIZEOUT = 40) (
+ input clk,
+ input ce,
+ input rst,
+ input signed [SIZEIN-1:0] a, b,
+ output signed [SIZEOUT-1:0] accum_out,
+ output overflow
+);
+// Declare registers for intermediate values
+reg signed [SIZEIN-1:0] a_reg, b_reg, a_reg2, b_reg2;
+reg signed [2*SIZEIN-1:0] mult_reg = 0;
+reg signed [SIZEOUT:0] adder_out = 0;
+reg overflow_reg;
+always @(posedge clk) begin
+ //if (ce)
+ begin
+ a_reg <= a;
+ b_reg <= b;
+ a_reg2 <= a_reg;
+ b_reg2 <= b_reg;
+ mult_reg <= a_reg2 * b_reg2;
+ // Store accumulation result into a register
+ adder_out <= adder_out + mult_reg;
+ overflow_reg <= overflow;
+ end
+ if (rst) begin
+ a_reg <= 0;
+ a_reg2 <= 0;
+ b_reg <= 0;
+ b_reg2 <= 0;
+ mult_reg <= 0;
+ adder_out <= 0;
+ overflow_reg <= 1'b0;
+ end
+end
+assign overflow = (adder_out >= 2**(SIZEOUT-1)) | overflow_reg;
+
+// Output accumulation result
+assign accum_out = overflow ? 2**(SIZEOUT-1)-1 : adder_out;
+
+endmodule
diff --git a/tests/xilinx/macc.ys b/tests/xilinx/macc.ys
new file mode 100644
index 000000000..417a3b21b
--- /dev/null
+++ b/tests/xilinx/macc.ys
@@ -0,0 +1,31 @@
+read_verilog macc.v
+design -save read
+
+proc
+hierarchy -top macc
+#equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx ### TODO
+equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx
+miter -equiv -flatten -make_assert -make_outputs gold gate miter
+sat -verify -prove-asserts -seq 10 -show-inputs -show-outputs miter
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd macc # Constrain all select calls below inside the top module
+select -assert-count 1 t:BUFG
+select -assert-count 1 t:FDRE
+select -assert-count 1 t:DSP48E1
+select -assert-none t:BUFG t:FDRE t:DSP48E1 %% t:* %D
+
+design -load read
+proc
+hierarchy -top macc2
+#equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx ### TODO
+equiv_opt -run :prove -map +/xilinx/cells_sim.v synth_xilinx
+miter -equiv -flatten -make_assert -make_outputs gold gate miter
+sat -verify -prove-asserts -seq 10 -show-inputs -show-outputs miter
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd macc2 # Constrain all select calls below inside the top module
+select -assert-count 1 t:BUFG
+select -assert-count 1 t:DSP48E1
+select -assert-count 1 t:FDRE
+select -assert-count 1 t:LUT2
+select -assert-count 41 t:LUT3
+select -assert-none t:BUFG t:DSP48E1 t:FDRE t:LUT2 t:LUT3 %% t:* %D
diff --git a/tests/xilinx/macc_tb.v b/tests/xilinx/macc_tb.v
new file mode 100644
index 000000000..64aed05c4
--- /dev/null
+++ b/tests/xilinx/macc_tb.v
@@ -0,0 +1,96 @@
+`timescale 1ns / 1ps
+
+module testbench;
+
+ parameter SIZEIN = 16, SIZEOUT = 40;
+ reg clk, ce, rst;
+ reg signed [SIZEIN-1:0] a, b;
+ output signed [SIZEOUT-1:0] REF_accum_out, accum_out;
+ output REF_overflow, overflow;
+
+ integer errcount = 0;
+
+ reg ERROR_FLAG = 0;
+
+ task clkcycle;
+ begin
+ #5;
+ clk = ~clk;
+ #10;
+ clk = ~clk;
+ #2;
+ ERROR_FLAG = 0;
+ if (REF_accum_out !== accum_out) begin
+ $display("ERROR at %1t: REF_accum_out=%b UUT_accum_out=%b DIFF=%b", $time, REF_accum_out, accum_out, REF_accum_out ^ accum_out);
+ errcount = errcount + 1;
+ ERROR_FLAG = 1;
+ end
+ if (REF_overflow !== overflow) begin
+ $display("ERROR at %1t: REF_overflow=%b UUT_overflow=%b DIFF=%b", $time, REF_overflow, overflow, REF_overflow ^ overflow);
+ errcount = errcount + 1;
+ ERROR_FLAG = 1;
+ end
+ #3;
+ end
+ endtask
+
+ initial begin
+ //$dumpfile("test_macc.vcd");
+ //$dumpvars(0, testbench);
+
+ #2;
+ clk = 1'b0;
+ ce = 1'b0;
+ a = 0;
+ b = 0;
+
+ rst = 1'b1;
+ repeat (10) begin
+ #10;
+ clk = 1'b1;
+ #10;
+ clk = 1'b0;
+ #10;
+ clk = 1'b1;
+ #10;
+ clk = 1'b0;
+ end
+ rst = 1'b0;
+
+ repeat (10000) begin
+ clkcycle;
+ ce = 1; //$urandom & $urandom;
+ //rst = $urandom & $urandom & $urandom & $urandom & $urandom & $urandom;
+ a = $urandom & ~(1 << (SIZEIN-1));
+ b = $urandom & ~(1 << (SIZEIN-1));
+ end
+
+ if (errcount == 0) begin
+ $display("All tests passed.");
+ $finish;
+ end else begin
+ $display("Caught %1d errors.", errcount);
+ $stop;
+ end
+ end
+
+ macc2 ref (
+ .clk(clk),
+ .ce(ce),
+ .rst(rst),
+ .a(a),
+ .b(b),
+ .accum_out(REF_accum_out),
+ .overflow(REF_overflow)
+ );
+
+ macc2_uut uut (
+ .clk(clk),
+ .ce(ce),
+ .rst(rst),
+ .a(a),
+ .b(b),
+ .accum_out(accum_out),
+ .overflow(overflow)
+ );
+endmodule
diff --git a/tests/xilinx/mul_unsigned.v b/tests/xilinx/mul_unsigned.v
new file mode 100644
index 000000000..e3713a642
--- /dev/null
+++ b/tests/xilinx/mul_unsigned.v
@@ -0,0 +1,30 @@
+/*
+Example from: https://www.xilinx.com/support/documentation/sw_manuals/xilinx2019_1/ug901-vivado-synthesis.pdf [p. 89].
+*/
+
+// Unsigned 16x24-bit Multiplier
+// 1 latency stage on operands
+// 3 latency stage after the multiplication
+// File: multipliers2.v
+//
+module mul_unsigned (clk, A, B, RES);
+parameter WIDTHA = /*16*/ 6;
+parameter WIDTHB = /*24*/ 9;
+input clk;
+input [WIDTHA-1:0] A;
+input [WIDTHB-1:0] B;
+output [WIDTHA+WIDTHB-1:0] RES;
+reg [WIDTHA-1:0] rA;
+reg [WIDTHB-1:0] rB;
+reg [WIDTHA+WIDTHB-1:0] M [3:0];
+integer i;
+always @(posedge clk)
+ begin
+ rA <= A;
+ rB <= B;
+ M[0] <= rA * rB;
+ for (i = 0; i < 3; i = i+1)
+ M[i+1] <= M[i];
+ end
+assign RES = M[3];
+endmodule
diff --git a/tests/xilinx/mul_unsigned.ys b/tests/xilinx/mul_unsigned.ys
new file mode 100644
index 000000000..77990bd68
--- /dev/null
+++ b/tests/xilinx/mul_unsigned.ys
@@ -0,0 +1,10 @@
+read_verilog mul_unsigned.v
+proc
+hierarchy -top mul_unsigned
+equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd mul_unsigned # Constrain all select calls below inside the top module
+select -assert-count 1 t:BUFG
+select -assert-count 1 t:DSP48E1
+select -assert-count 30 t:FDRE
+select -assert-none t:DSP48E1 t:FDRE t:BUFG %% t:* %D