Add Vivado project files and testbench configurations for volume multiplier and volume saturator
- Created `tb_volume_multiplier_behav.wcfg` for waveform configuration of the volume multiplier testbench. - Added `volume_multiplier.xpr` project file for the volume multiplier design. - Created `volume_saturator.xpr` project file for the volume saturator design. - Added `volume_saturator_tb_behav.wcfg` for waveform configuration of the volume saturator testbench.
This commit is contained in:
@@ -38,15 +38,12 @@ ARCHITECTURE Behavioral OF LFO IS
|
||||
CONSTANT LFO_COUNTER_BASE_PERIOD_US : INTEGER := 1000; -- 1ms
|
||||
CONSTANT ADJUSTMENT_FACTOR : INTEGER := 90;
|
||||
CONSTANT JSTK_CENTER_VALUE : INTEGER := 2 ** (JOYSTICK_LENGHT - 1);
|
||||
constant LFO_COUNTER_BASE_CLK_CYCLES : INTEGER := LFO_COUNTER_BASE_PERIOD_US * 1000 / CLK_PERIOD_NS;
|
||||
|
||||
CONSTANT LFO_COUNTER_BASE_CLK_CYCLES : INTEGER := LFO_COUNTER_BASE_PERIOD_US * 1000 / CLK_PERIOD_NS;
|
||||
|
||||
SIGNAL step_clk_cycles : INTEGER := LFO_COUNTER_BASE_CLK_CYCLES;
|
||||
SIGNAL step_counter : INTEGER := 1;
|
||||
SIGNAL step_counter : INTEGER RANGE 0 TO 2 ** TRIANGULAR_COUNTER_LENGHT - 1 := 0;
|
||||
SIGNAL tri_counter : signed(TRIANGULAR_COUNTER_LENGHT - 1 DOWNTO 0) := (OTHERS => '0');
|
||||
SIGNAL direction_up : STD_LOGIC := '1';
|
||||
SIGNAL lfo_product : STD_LOGIC_VECTOR(CHANNEL_LENGHT + TRIANGULAR_COUNTER_LENGHT - 1 DOWNTO 0) := (OTHERS => '0');
|
||||
|
||||
SIGNAL trigger : STD_LOGIC := '0';
|
||||
|
||||
SIGNAL s_axis_tready_int : STD_LOGIC := '0';
|
||||
SIGNAL m_axis_tvalid_int : STD_LOGIC := '0';
|
||||
@@ -57,14 +54,6 @@ BEGIN
|
||||
s_axis_tready <= s_axis_tready_int;
|
||||
m_axis_tvalid <= m_axis_tvalid_int;
|
||||
|
||||
-- LFO period adjustment process
|
||||
PROCESS (aclk)
|
||||
BEGIN
|
||||
IF rising_edge(aclk) THEN
|
||||
step_clk_cycles <= LFO_COUNTER_BASE_CLK_CYCLES - ADJUSTMENT_FACTOR * to_integer(JSTK_CENTER_VALUE - unsigned(lfo_period));
|
||||
END IF;
|
||||
END PROCESS;
|
||||
|
||||
-- Optimized single process for LFO step and triangular waveform generation
|
||||
PROCESS (aclk)
|
||||
BEGIN
|
||||
@@ -76,34 +65,37 @@ BEGIN
|
||||
direction_up <= '1';
|
||||
|
||||
ELSE
|
||||
-- Clamp step_clk_cycles to a minimum of 1 to avoid negative or zero values
|
||||
IF (LFO_COUNTER_BASE_CLK_CYCLES - ADJUSTMENT_FACTOR * to_integer(JSTK_CENTER_VALUE - unsigned(lfo_period))) < 1 THEN
|
||||
step_clk_cycles <= 1;
|
||||
ELSE
|
||||
step_clk_cycles <= LFO_COUNTER_BASE_CLK_CYCLES - ADJUSTMENT_FACTOR * to_integer(JSTK_CENTER_VALUE - unsigned(lfo_period));
|
||||
END IF;
|
||||
|
||||
IF lfo_enable = '1' THEN
|
||||
|
||||
IF step_counter < step_clk_cycles THEN
|
||||
step_counter <= step_counter + 1;
|
||||
|
||||
ELSE
|
||||
IF step_counter >= step_clk_cycles THEN
|
||||
step_counter <= 0;
|
||||
|
||||
IF direction_up = '1' THEN
|
||||
IF tri_counter = 2 ** TRIANGULAR_COUNTER_LENGHT - 2 THEN
|
||||
direction_up <= '0';
|
||||
|
||||
IF tri_counter = 2 ** TRIANGULAR_COUNTER_LENGHT - 1 THEN
|
||||
direction_up <= '0';
|
||||
tri_counter <= tri_counter - 1;
|
||||
ELSE
|
||||
tri_counter <= tri_counter + 1;
|
||||
END IF;
|
||||
|
||||
ELSE
|
||||
IF tri_counter = 0 THEN
|
||||
direction_up <= '1';
|
||||
tri_counter <= tri_counter + 1;
|
||||
ELSE
|
||||
tri_counter <= tri_counter - 1;
|
||||
END IF;
|
||||
ELSIF tri_counter = 1 THEN
|
||||
direction_up <= '1';
|
||||
|
||||
END IF;
|
||||
|
||||
IF direction_up = '1' THEN
|
||||
tri_counter <= tri_counter + 1;
|
||||
|
||||
ELSE
|
||||
tri_counter <= tri_counter - 1;
|
||||
|
||||
END IF;
|
||||
|
||||
ELSE
|
||||
step_counter <= step_counter + 1;
|
||||
|
||||
END IF;
|
||||
|
||||
END IF;
|
||||
@@ -126,33 +118,31 @@ BEGIN
|
||||
m_axis_tlast <= '0';
|
||||
|
||||
ELSE
|
||||
-- Set the ready signal for the slave interface
|
||||
s_axis_tready_int <= m_axis_tready OR NOT m_axis_tvalid_int;
|
||||
|
||||
-- Clear valid flag when master interface is ready
|
||||
IF m_axis_tready = '1' THEN
|
||||
m_axis_tvalid_int <= '0';
|
||||
END IF;
|
||||
|
||||
IF trigger = '1' AND (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN
|
||||
IF s_axis_tvalid = '1' AND (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN
|
||||
IF lfo_enable = '1' THEN
|
||||
m_axis_tdata <= STD_LOGIC_VECTOR(
|
||||
resize(
|
||||
signed(s_axis_tdata) * tri_counter,
|
||||
m_axis_tdata'LENGTH
|
||||
)
|
||||
);
|
||||
|
||||
ELSE
|
||||
m_axis_tdata <= s_axis_tdata;
|
||||
|
||||
END IF;
|
||||
s_axis_tready_int <= '1';
|
||||
m_axis_tvalid_int <= '1';
|
||||
m_axis_tlast <= s_axis_tlast;
|
||||
m_axis_tdata <= lfo_product(CHANNEL_LENGHT + TRIANGULAR_COUNTER_LENGHT - 1 DOWNTO TRIANGULAR_COUNTER_LENGHT);
|
||||
|
||||
trigger <= '0';
|
||||
END IF;
|
||||
ELSE
|
||||
s_axis_tready_int <= '0';
|
||||
|
||||
-- Handle input data
|
||||
IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN
|
||||
IF lfo_enable = '1' THEN
|
||||
lfo_product <= STD_LOGIC_VECTOR(
|
||||
signed(s_axis_tdata) * tri_counter
|
||||
);
|
||||
ELSE
|
||||
lfo_product <= s_axis_tdata & (TRIANGULAR_COUNTER_LENGHT - 1 downto 0 => '0');
|
||||
END IF;
|
||||
|
||||
trigger <= '1';
|
||||
END IF;
|
||||
|
||||
END IF;
|
||||
|
||||
@@ -28,21 +28,18 @@ END volume_multiplier;
|
||||
|
||||
ARCHITECTURE Behavioral OF volume_multiplier IS
|
||||
|
||||
CONSTANT VOLUME_STEPS : INTEGER := (2 ** VOLUME_WIDTH) / (2 ** (VOLUME_STEP_2 + 1));
|
||||
CONSTANT VOLUME_STEPS : INTEGER := (2 ** VOLUME_WIDTH) / (2 ** VOLUME_STEP_2);
|
||||
CONSTANT CENTER_VOLUME_STEP : INTEGER := (2 ** (VOLUME_WIDTH - 1) - 1) / (2 ** VOLUME_STEP_2) + 1;
|
||||
|
||||
SIGNAL volume_exp_mult : INTEGER RANGE -VOLUME_STEPS TO VOLUME_STEPS := 0;
|
||||
signal volume_centered : SIGNED(VOLUME_WIDTH - 1 DOWNTO 0);
|
||||
|
||||
SIGNAL s_axis_tready_int : STD_LOGIC;
|
||||
|
||||
SIGNAL m_axis_tvalid_int : STD_LOGIC;
|
||||
|
||||
BEGIN
|
||||
-- Assigning the output signals
|
||||
s_axis_tready <= s_axis_tready_int;
|
||||
m_axis_tvalid <= m_axis_tvalid_int;
|
||||
|
||||
-- Volume to signed and centered
|
||||
volume_centered <= signed(unsigned(volume) - to_unsigned(511, VOLUME_WIDTH));
|
||||
s_axis_tready <= m_axis_tready AND aresetn;
|
||||
|
||||
-- Volume to exp
|
||||
PROCESS (aclk)
|
||||
@@ -54,7 +51,10 @@ BEGIN
|
||||
volume_exp_mult <= 0;
|
||||
|
||||
ELSE
|
||||
volume_exp_mult <= to_integer(volume_centered(VOLUME_WIDTH - 1 DOWNTO VOLUME_STEP_2));
|
||||
-- Volume to signed and centered and convert to power of 2 exponent
|
||||
volume_exp_mult <= to_integer(
|
||||
shift_right(signed('0' & volume), VOLUME_STEP_2) - CENTER_VOLUME_STEP
|
||||
);
|
||||
|
||||
END IF;
|
||||
|
||||
@@ -69,9 +69,9 @@ BEGIN
|
||||
IF rising_edge(aclk) THEN
|
||||
|
||||
IF aresetn = '0' THEN
|
||||
s_axis_tready_int <= '0';
|
||||
m_axis_tvalid_int <= '0';
|
||||
m_axis_tlast <= '0';
|
||||
m_axis_tdata <= (OTHERS => '0');
|
||||
|
||||
ELSE
|
||||
-- Clear valid flag when master interface is ready
|
||||
@@ -79,7 +79,9 @@ BEGIN
|
||||
m_axis_tvalid_int <= '0';
|
||||
END IF;
|
||||
|
||||
IF s_axis_tvalid = '1' AND (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN
|
||||
-- Handle the data flow
|
||||
IF s_axis_tvalid = '1' AND m_axis_tready = '1' THEN
|
||||
-- Multiply the input data with the volume and assign to output
|
||||
IF volume_exp_mult >= 0 THEN
|
||||
m_axis_tdata <= STD_LOGIC_VECTOR(
|
||||
shift_left(
|
||||
@@ -90,6 +92,7 @@ BEGIN
|
||||
volume_exp_mult
|
||||
)
|
||||
);
|
||||
|
||||
ELSE
|
||||
m_axis_tdata <= STD_LOGIC_VECTOR(
|
||||
shift_right(
|
||||
@@ -97,16 +100,15 @@ BEGIN
|
||||
signed(s_axis_tdata),
|
||||
m_axis_tdata'LENGTH
|
||||
),
|
||||
-volume_exp_mult
|
||||
- volume_exp_mult
|
||||
)
|
||||
);
|
||||
|
||||
END IF;
|
||||
s_axis_tready_int <= '1';
|
||||
|
||||
m_axis_tvalid_int <= '1';
|
||||
m_axis_tlast <= s_axis_tlast;
|
||||
|
||||
ELSE
|
||||
s_axis_tready_int <= '0';
|
||||
END IF;
|
||||
|
||||
END IF;
|
||||
|
||||
@@ -28,13 +28,12 @@ END volume_saturator;
|
||||
|
||||
ARCHITECTURE Behavioral OF volume_saturator IS
|
||||
|
||||
SIGNAL s_axis_tready_int : STD_LOGIC;
|
||||
SIGNAL m_axis_tvalid_int : STD_LOGIC;
|
||||
|
||||
BEGIN
|
||||
-- Output assignments
|
||||
s_axis_tready <= s_axis_tready_int;
|
||||
m_axis_tvalid <= m_axis_tvalid_int;
|
||||
s_axis_tready <= m_axis_tready AND aresetn;
|
||||
|
||||
PROCESS (aclk)
|
||||
BEGIN
|
||||
@@ -42,7 +41,6 @@ BEGIN
|
||||
IF rising_edge(aclk) THEN
|
||||
|
||||
IF aresetn = '0' THEN
|
||||
s_axis_tready_int <= '0';
|
||||
m_axis_tvalid_int <= '0';
|
||||
m_axis_tlast <= '0';
|
||||
m_axis_tdata <= (OTHERS => '0');
|
||||
@@ -53,23 +51,23 @@ BEGIN
|
||||
m_axis_tvalid_int <= '0';
|
||||
END IF;
|
||||
|
||||
IF s_axis_tvalid = '1' AND (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN
|
||||
-- Handle the data flow
|
||||
IF s_axis_tvalid = '1' AND m_axis_tready = '1' THEN
|
||||
-- Check if the input data is within the bounds else saturate
|
||||
IF signed(s_axis_tdata) > to_signed(HIGHER_BOUND, s_axis_tdata'length) THEN
|
||||
m_axis_tdata <= STD_LOGIC_VECTOR(to_signed(HIGHER_BOUND, TDATA_WIDTH));
|
||||
|
||||
ELSIF signed(s_axis_tdata) < to_signed(LOWER_BOUND, s_axis_tdata'length) THEN
|
||||
m_axis_tdata <= STD_LOGIC_VECTOR(to_signed(LOWER_BOUND, TDATA_WIDTH));
|
||||
|
||||
ELSE
|
||||
m_axis_tdata <= STD_LOGIC_VECTOR(resize(signed(s_axis_tdata), TDATA_WIDTH));
|
||||
|
||||
END IF;
|
||||
|
||||
s_axis_tready_int <= '1';
|
||||
m_axis_tvalid_int <= '1';
|
||||
m_axis_tlast <= s_axis_tlast;
|
||||
|
||||
ELSE
|
||||
s_axis_tready_int <= '0';
|
||||
|
||||
END IF;
|
||||
|
||||
END IF;
|
||||
|
||||
Reference in New Issue
Block a user