Skip to content

Commit

Permalink
biquad.vhd: multiply/sum and resize in different cycles
Browse files Browse the repository at this point in the history
The combinatorial logic to implement 'resize' chained with DPS48s may make
timing closure difficult. So, break these operations into two different cycles.
  • Loading branch information
guilhermerc committed Mar 28, 2024
1 parent 4e6bc2d commit 278f902
Showing 1 changed file with 85 additions and 29 deletions.
114 changes: 85 additions & 29 deletions modules/common/biquad/biquad.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,27 @@ ARCHITECTURE behave OF biquad IS
-(g_COEFF_FRAC_WIDTH + g_X_FRAC_WIDTH + g_EXTRA_BITS)) :=
(OTHERS => '0');

SIGNAL state : NATURAL RANGE 0 TO 3 := 0;
-- Signals to hold full precision operations' results
SIGNAL b0_times_w_tmp, a1_times_w_d1_tmp, a2_times_w_d2_tmp,
b1_times_w_d1_tmp, b2_times_w_d2_tmp :
SFIXED((g_COEFF_INT_WIDTH + w'LEFT + 1)-1 DOWNTO
-g_COEFF_FRAC_WIDTH + w'RIGHT) := (OTHERS => '0');
SIGNAL w_tmp :
SFIXED(MAXIMUM(g_X_INT_WIDTH-1, aux_a'LEFT)+1 DOWNTO
MINIMUM(-g_X_FRAC_WIDTH, aux_a'RIGHT)) := (OTHERS => '0');
SIGNAL aux_a_tmp :
SFIXED(MAXIMUM(a1_times_w_d1'LEFT+1, a2_times_w_d2'LEFT)+1 DOWNTO
MINIMUM(a1_times_w_d1'RIGHT, a2_times_w_d2'RIGHT)) :=
(OTHERS => '0');
SIGNAL aux_b_tmp :
SFIXED(MAXIMUM(b1_times_w_d1'LEFT, b2_times_w_d2'LEFT)+1 DOWNTO
MINIMUM(b1_times_w_d1'RIGHT, b2_times_w_d2'RIGHT)) :=
(OTHERS => '0');
SIGNAL y_tmp :
SFIXED(MAXIMUM(b0_times_w'LEFT, aux_b'LEFT)+1 DOWNTO
MINIMUM(b0_times_w'RIGHT, aux_b'RIGHT)) := (OTHERS => '0');

SIGNAL state : NATURAL RANGE 0 TO 6 := 0;
BEGIN
PROCESS(clk_i) IS
BEGIN
Expand All @@ -101,54 +121,87 @@ BEGIN
b2_times_w_d2 <= (OTHERS => '0');
aux_a <= (OTHERS => '0');
aux_b <= (OTHERS => '0');
w_tmp <= (OTHERS => '0');
b0_times_w_tmp <= (OTHERS => '0');
a1_times_w_d1_tmp <= (OTHERS => '0');
a2_times_w_d2_tmp <= (OTHERS => '0');
b1_times_w_d1_tmp <= (OTHERS => '0');
b2_times_w_d2_tmp <= (OTHERS => '0');
aux_a_tmp <= (OTHERS => '0');
aux_b_tmp <= (OTHERS => '0');
state <= 0;
y_valid_o <= '0';
ELSE
y_valid_o <= '0';

CASE state IS
-- Computes: w[n] = x[n] - a1*w[n - 1] - a2*w[n - 2]
-- Computes: w[n] = x[n] - a1*w[n - 1] - a2*w[n - 2] (full precision)
WHEN 0 =>
IF x_valid_i THEN
w <= resize(x_i + aux_a, w'LEFT, w'RIGHT);
w_tmp <= x_i + aux_a;
state <= 1;
END IF;

-- Computes: b0*w[n]
-- w[n - 1] (for the next iteration)
-- w[n - 2] (for the next iteration)
-- Computes: w[n] (resized)
WHEN 1 =>
b0_times_w <= resize(coeffs_i.b0*w, b0_times_w'LEFT,
b0_times_w'RIGHT);
w_d1 <= w;
w_d2 <= w_d1;
w <= resize(w_tmp, w'LEFT, w'RIGHT);
state <= 2;

-- Computes: y[n] = w[n] + b1*w[n - 1] + b2*w[n - 2]
-- a1*w[n - 1] (for the next iteration)
-- a2*w[n - 2] (for the next iteration)
-- b1*w[n - 1] (for the next iteration)
-- b2*w[n - 2] (for the next iteration)
-- Computes: b0*w[n] (full precision)
-- w[n - 1] for the next iteration
-- w[n - 2] for the next iteration
WHEN 2 =>
y_o <= resize(b0_times_w + aux_b, y_o'LEFT, y_o'RIGHT);
y_valid_o <= '1';
a1_times_w_d1 <= resize(coeffs_i.a1*w_d1, a1_times_w_d1'LEFT,
b0_times_w_tmp <= coeffs_i.b0*w;
w_d1 <= w;
w_d2 <= w_d1;
state <= 3;

-- Computes: b0*w[n] (resized)
-- a1*w[n - 1] for the next iteration (full precision)
-- a2*w[n - 2] for the next iteration (full precision)
-- b1*w[n - 1] for the next iteration (full precision)
-- b2*w[n - 2] for the next iteration (full precision)
WHEN 3 =>
b0_times_w <= resize(b0_times_w_tmp, b0_times_w'LEFT,
b0_times_w'RIGHT);
a1_times_w_d1_tmp <= coeffs_i.a1*w_d1;
a2_times_w_d2_tmp <= coeffs_i.a2*w_d2;
b1_times_w_d1_tmp <= coeffs_i.b1*w_d1;
b2_times_w_d2_tmp <= coeffs_i.b2*w_d2;
state <= 4;

-- Computes: a1*w[n - 1] for the next iteration (resized)
-- a2*w[n - 2] for the next iteration (resized)
-- b1*w[n - 1] for the next iteration (resized)
-- b2*w[n - 2] for the next iteration (resized)
-- y[n] = w[n] + b1*w[n - 1] + b2*w[n - 2] (full precision)
WHEN 4 =>
a1_times_w_d1 <= resize(a1_times_w_d1_tmp, a1_times_w_d1'LEFT,
a1_times_w_d1'RIGHT);
a2_times_w_d2 <= resize(coeffs_i.a2*w_d2, a2_times_w_d2'LEFT,
a2_times_w_d2 <= resize(a2_times_w_d2_tmp, a2_times_w_d2'LEFT,
a2_times_w_d2'RIGHT);
b1_times_w_d1 <= resize(coeffs_i.b1*w_d1, b1_times_w_d1'LEFT,
b1_times_w_d1 <= resize(b1_times_w_d1_tmp, b1_times_w_d1'LEFT,
b1_times_w_d1'RIGHT);
b2_times_w_d2 <= resize(coeffs_i.b2*w_d2, b2_times_w_d2'LEFT,
b2_times_w_d2 <= resize(b2_times_w_d2_tmp, b2_times_w_d2'LEFT,
b2_times_w_d2'RIGHT);
state <= 3;
y_tmp <= b0_times_w + aux_b;
state <= 5;

-- Computes: -a1*w[n - 1] - a2*w[n - 2] for the next iteration (full precision)
-- b1*w[n - 1] + b2*w[n - 2] for the next iteration (full precision)
-- y[n] (resized)
WHEN 5 =>
aux_a_tmp <= -a1_times_w_d1 - a2_times_w_d2;
aux_b_tmp <= b1_times_w_d1 + b2_times_w_d2;
y_o <= resize(y_tmp, y_o'LEFT, y_o'RIGHT);
y_valid_o <= '1';
state <= 6;

-- Computes: -a1*w[n - 1] - a2*w[n - 2] (for the next iteration)
-- b1*w[n - 1] + b2*w[n - 2] (for the next iteration)
WHEN 3 =>
aux_a <= resize(-a1_times_w_d1 - a2_times_w_d2, aux_a'LEFT,
aux_a'RIGHT);
aux_b <= resize(b1_times_w_d1 + b2_times_w_d2, aux_b'LEFT,
aux_b'RIGHT);
-- Computes: -a1*w[n - 1] - a2*w[n - 2] for the next iteration (resized)
-- b1*w[n - 1] + b2*w[n - 2] for the next iteration (resized)
WHEN 6 =>
aux_a <= resize(aux_a_tmp, aux_a'LEFT, aux_a'RIGHT);
aux_b <= resize(aux_b_tmp, aux_b'LEFT, aux_b'RIGHT);
state <= 0;
END CASE;
END IF;
Expand All @@ -158,5 +211,8 @@ BEGIN
busy_o <= '1' WHEN (state = 0 AND x_valid_i = '1') ELSE
'1' WHEN state = 1 ELSE
'1' WHEN state = 2 ELSE
'1' WHEN state = 3 ELSE
'1' WHEN state = 4 ELSE
'1' WHEN state = 5 ELSE
'0';
END ARCHITECTURE behave;

0 comments on commit 278f902

Please sign in to comment.