Skip to content
Snippets Groups Projects
Commit 64a53484 authored by TANDEAU DE MARSAC Gautier's avatar TANDEAU DE MARSAC Gautier
Browse files

Replace operativeUnit.vhd

parent 3475c124
No related branches found
No related tags found
No related merge requests found
-------------------------------------------------------------------------------
-- Title : operativeUnit
-- Project :
-------------------------------------------------------------------------------
-- File : operativeUnit.vhd
-- Author : Jean-Noel BAZIN <jnbazin@pc-disi-026.enst-bretagne.fr>
-- Company :
-- Created : 2018-04-11
-- Last update: 2025-03-28
-- Platform :
-- Standard : VHDL'93/02
-------------------------------------------------------------------------------
-- Description: Operative unit of a sequential FIR filter. Including shift
-- register for samples, registers for coefficients, a MAC and a register to
-- store the result
-------------------------------------------------------------------------------
-- Copyright (c) 2018
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version A
-- 2025-04-09 1.2 marzel Renamed some signals and port names to match
-- the description of lab activity
-- Modified the sample width to 16 bits
-- Changed the filter coefficients to have abetter
-- low-pass filter
-- 2019-02-13 1.1 marzel Update to provide a 16-tap filter and improve
-- the user experience ;)
-- 2018-04-11 1.0 jnbazin Created
-- 2018-04-18 1.0 marzel Modification of SR_Y assignment to a round
-- instead of a trunc
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
......@@ -45,7 +17,7 @@ entity operativeUnit is
I_incrAddress : in std_logic; -- Control signal to increment register read address
I_initSum : in std_logic; -- Control signal to initialize the MAC register
I_loadSum : in std_logic; -- Control signal to load the MAC register;
I_loadOutput : in std_logic; -- Control signal to load Y register
I_loadOutput : in std_logic; -- Control signal to load Y register
O_processingDone : out std_logic; -- Indicate that processing is done
O_filteredSample : out std_logic_vector(15 downto 0) -- filtered sample
);
......@@ -53,7 +25,7 @@ entity operativeUnit is
end entity operativeUnit;
architecture arch_operativeUnit of operativeUnit is
type registerFile is array(0 to 15) of signed(15 downto 0);
type registerFile is array(0 to 31) of signed(15 downto 0);
signal SR_coefRegister : registerFile;
signal SR_shiftRegister : registerFile; -- shift register file used to store and shift input samples
......@@ -61,79 +33,124 @@ architecture arch_operativeUnit of operativeUnit is
signal SC_multOperand2 : signed(15 downto 0);
signal SC_MultResult : signed(31 downto 0); -- Result of the multiplication Xi*Hi
signal SC_addResult : signed(35 downto 0); -- result of the accumulation addition
signal SR_sum : signed(35 downto 0); -- Accumulation register
signal SR_sum : signed(35 downto 0); -- Accumulation re gister
signal SR_filteredSample: signed(15 downto 0); -- filtered sample storage register
signal SR_readAddress : integer range 0 to 15; -- register files read address
begin
SR_coefRegister <= (to_signed(317,16),
to_signed(476,16),
to_signed(925,16),
to_signed(1589,16),
to_signed(2354,16),
to_signed(3087,16),
to_signed(3661,16),
to_signed(3975,16),
to_signed(3975,16),
to_signed(3661,16),
to_signed(3087,16),
to_signed(2354,16),
to_signed(1589,16),
to_signed(925,16),
to_signed(476,16),
to_signed(317,16)
);
-- Low-pass filter provided with octave (or Matlab ;)) script :
-- pkg load signal
--
-- fs=44100
-- fn=fs/2
-- n=32
-- fc=1000
-- fHP=fir1(n-1,fc/fn,"high");
--
-- function quantized_signal = quantize(signal, q)
-- % Quantize the signal to q bits
-- max_val = 2^(q-1) - 1;
-- min_val = -2^(q-1);
-- quantized_signal = round(min(max(signal * 2^(q-1), min_val), max_val)) / 2^(q-1);
-- end
--
-- q=16
--
-- fHPq= quantize(fHP,q);
--
-- for i=1:n
-- printf("to_signed(%d,%d),\n", fHPq(i)*2^(q-1),q);
-- endfor
-- Table to store the filter coefficients obtained with the previous script
SR_coefRegister <= (to_signed(-40,16),
to_signed(-52,16),
to_signed(-78,16),
to_signed(-122,16),
to_signed(-185,16),
to_signed(-270,16),
to_signed(-376,16),
to_signed(-501,16),
to_signed(-640,16),
to_signed(-789,16),
to_signed(-940,16),
to_signed(-1086,16),
to_signed(-1219,16),
to_signed(-1331,16),
to_signed(-1416,16),
to_signed(-1470,16),
to_signed(31316,16),
to_signed(-1470,16),
to_signed(-1416,16),
to_signed(-1331,16),
to_signed(-1219,16),
to_signed(-1086,16),
to_signed(-940,16),
to_signed(-789,16),
to_signed(-640,16),
to_signed(-501,16),
to_signed(-376,16),
to_signed(-270,16),
to_signed(-185,16),
to_signed(-122,16),
to_signed(-78,16),
to_signed(-52,16)
);
-- Process to describe the shift register storing the input samples
shift : process (I_clock, I_reset) is
begin
if I_reset = '1' then
begin -- process shift
if I_reset = '1' then -- asynchronous reset (active high)
SR_shiftRegister <= (others => (others => '0'));
elsif rising_edge(I_clock) then
if I_loadShift = '1' then
SR_shiftRegister <= signed(I_inputSample) & SR_shiftRegister(0 to 14);
-- SR_shiftRegister <= signed (I_inputSample) & SR_shiftRegister(0 downto 14);
SR_shiftRegister(0) <= signed(I_inputSample);
SR_shiftRegister(1 to 15) <= SR_shiftRegister(0 to 14);
end if;
end if;
end process shift;
-- Process to describe the counter providing the selection adresses
-- Process to describe the counter providing the selection addresses
incr_address : process (I_clock, I_reset) is
begin
if I_reset = '1' then
if I_reset = '1' then -- asynchronous reset (active high)
SR_readAddress <= 0;
elsif rising_edge(I_clock) then
if I_initAddress = '1' then
SR_readAddress <= 0;
elsif I_incrAddress = '1' then
if SR_readAddress = 15 then
SR_readAddress <= 0;
else
if SR_readAddress < 15 then
SR_readAddress <= SR_readAddress + 1;
end if;
end if;
end if;
end process incr_address;
-- Signal detecting that the next cycle will be the one
-- providing the last product used to compute the convolution
O_processingDone <= '1' when SR_readAddress = 15 else '0';
-- Signals connected with multiplexers (SIMPLY inferred with table indices)
SC_multOperand1 <= SR_shiftRegister(SR_readAddress);
SC_multOperand2 <= SR_coefRegister(SR_readAddress);
SC_multOperand1 <= SR_shiftRegister(SR_readAddress); -- 16 bits
SC_multOperand2 <= SR_coefRegister(SR_readAddress); -- 16 bits
-- Multiplication of the operands
SC_MultResult <= SC_multOperand1 * SC_multOperand2;
SC_MultResult <= resize(SC_multOperand1, 16) * resize(SC_multOperand2, 16); -- 32 bits
-- Sum of the multiplication result and the accumulated value
SC_addResult <= resize(SC_MultResult, SC_addResult'length) + SR_sum;
-- Register to store the accumulated value if the loadSum is active
sum_acc : process (I_clock, I_reset) is
-- It also reduces the width of the sum to fit to the input and output
-- signal widths (be careful with truncating/rounding)
sum_acc : process (I_clock, I_reset) is
begin
if I_reset = '1' then
if I_reset = '1' then -- asynchronous reset (active high)
SR_sum <= (others => '0');
elsif rising_edge(I_clock) then
if I_initSum = '1' then
......@@ -145,18 +162,28 @@ begin
end process sum_acc;
-- Register to store the final result if the loadOutput is active
store_result : process (I_clock, I_reset) is
begin
if I_reset = '1' then
SR_filteredSample <= (others => '0');
elsif rising_edge(I_clock) then
if I_loadOutput = '1' then
SR_filteredSample <= SR_sum(30 downto 15);
store_result : process (I_clock, I_reset) is
variable rounded_value : signed(15 downto 0);
begin
if I_reset = '1' then
SR_filteredSample <= (others => '0');
elsif rising_edge(I_clock) then
if I_loadOutput = '1' then
-- Extraction de la base (30 downto 15)
rounded_value := SR_sum(30 downto 15);
-- Si le bit 14 (juste après) est à 1, on arrondit vers le haut
if SR_sum(14) = '1' then
rounded_value := rounded_value + to_signed(1, rounded_value'length);
end if;
-- On affecte le résultat arrondi
SR_filteredSample <= rounded_value;
end if;
end process store_result;
end if;
end process store_result;
O_filteredSample <= std_logic_vector(SR_filteredSample);
end architecture arch_operativeUnit;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment