From 9f4bb046b876d2e373e491356d01a1310f44b420 Mon Sep 17 00:00:00 2001 From: KAMMOUN Yanis <yanis.kammoun@imt-atlantique.net> Date: Wed, 26 Mar 2025 11:20:28 +0000 Subject: [PATCH] Upload New File --- VHDL/operativeUnit.vhd | 255 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 255 insertions(+) create mode 100644 VHDL/operativeUnit.vhd diff --git a/VHDL/operativeUnit.vhd b/VHDL/operativeUnit.vhd new file mode 100644 index 0000000..2fba240 --- /dev/null +++ b/VHDL/operativeUnit.vhd @@ -0,0 +1,255 @@ +------------------------------------------------------------------------------- +-- Title : operativeUnit +-- Project : +------------------------------------------------------------------------------- +-- File : operativeUnit.vhd +-- Author : Jean-Noel BAZIN <jnbazin@pc-disi-026.enst-bretagne.fr> +-- Company : +-- Created : 2018-04-11 +-- Last update: 2019-02-13 +-- 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 Author Description +-- 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; +use ieee.numeric_std.all; + +entity operativeUnit is + + port ( + I_clock : in std_logic; -- global clock + I_reset : in std_logic; -- asynchronous global reset + I_inputSample : in std_logic_vector(10 downto 0); -- 8 bit input sample + I_loadShiftX : in std_logic; -- filtered sample + I_loadShiftY : in std_logic; -- filtered sample + I_loadShiftz : in std_logic; -- filtered sample + I_initAddress : in std_logic; -- Control signal to initialize register read address + 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_loadY : in std_logic; -- Control signal to load Y register + I_samples : in std_logic_vector(1 to 0); -- Data signal to select X or Y samples (and B or A coefficients) + I_coeffs : in std_logic_vector(1 to 0); -- Data signal to select coefficients + O_GprocessingDone : out std_logic; + O_BprocessingDone : out std_logic; + O_AprocessingDone : out std_logic; + O_HprocessingDone : out std_logic; + O_Y : out std_logic_vector(10 downto 0) -- filtered sample + ); + +end entity operativeUnit; + +architecture arch_operativeUnit of operativeUnit is + type registerFileG is array(0 to 95) of signed(10 downto 0) ; + type registerFileB is array(0 to 2) of signed(10 downto 0); + type registerFileA is array(0 to 1) of signed(10 downto 0); + type registerFileH is array(0 to 10) of signed(10 downto 0) ; + signal SR_GcoefRegister : registerFileG; + signal SR_BcoefRegister : registerFileB; + signal SR_AcoefRegister : registerFileA; + signal SR_HcoefRegister : registerFileH; + + + + signal SR_XshiftRegister : registerFileG := (others => (others => '0')); -- shift register file used to store and shift input samples + signal SR_YshiftRegister : registerFileB := (others => (others => '0')); -- Initialisation à 0; -- shift register file used to store and shift output samples + signal SR_ZshiftRegister : registerFileH := (others => (others => '0')); -- Initialisation à 0; -- shift register file used to store and shift output samples + signal SC_multOperand1 : signed(10 downto 0); + signal SC_multOperand2 : signed(10 downto 0); + signal SC_MultResult : signed(20 downto 0); -- Result of the multiplication Xi*Hi + signal SC_addResult : signed(25 downto 0); -- result of the accumulation addition + signal SR_sum : signed(25 downto 0); -- Accumulation register + signal SR_Y : signed(10 downto 0); -- filtered sample storage register + signal SR_readAddress : integer range 0 to 95; -- register files read address + + + +begin + +-- Low-pass filter provided with octave (or Matlab ;)) command +--fir1(15, .001)/sqrt(sum(fir1(15, .001).^2))*2^6 + SR_GcoefRegister <= (to_signed(-1, 11), to_signed(-1, 11), to_signed(-1, 11), to_signed(-1, 11), + to_signed(-1, 11), to_signed(-1, 11), to_signed(-2, 11), to_signed(-2, 11), + to_signed(-2, 11), to_signed(-3, 11), to_signed(-3, 11), to_signed(-3, 11), + to_signed(-4, 11), to_signed(-4, 11), to_signed(-5, 11), to_signed(-5, 11), + to_signed(-6, 11), to_signed(-6, 11), to_signed(-7, 11), to_signed(-7, 11), + to_signed(-8, 11), to_signed(-8, 11), to_signed(-9, 11), to_signed(-10, 11), + to_signed(-10, 11), to_signed(-11, 11), to_signed(-11, 11), to_signed(-12, 11), + to_signed(-13, 11), to_signed(-13, 11), to_signed(-14, 11), to_signed(-14, 11), + to_signed(-15, 11), to_signed(-15, 11), to_signed(-16, 11), to_signed(-16, 11), + to_signed(-17, 11), to_signed(-17, 11), to_signed(-18, 11), to_signed(-18, 11), + to_signed(-18, 11), to_signed(-19, 11), to_signed(-19, 11), to_signed(-19, 11), + to_signed(-19, 11), to_signed(-19, 11), to_signed(-19, 11), to_signed(1004, 11), + to_signed(-19, 11), to_signed(-19, 11), to_signed(-19, 11), to_signed(-19, 11), + to_signed(-19, 11), to_signed(-19, 11), to_signed(-18, 11), to_signed(-18, 11), + to_signed(-18, 11), to_signed(-17, 11), to_signed(-17, 11), to_signed(-16, 11), + to_signed(-16, 11), to_signed(-15, 11), to_signed(-15, 11), to_signed(-14, 11), + to_signed(-14, 11), to_signed(-13, 11), to_signed(-13, 11), to_signed(-12, 11), + to_signed(-11, 11), to_signed(-11, 11), to_signed(-10, 11), to_signed(-10, 11), + to_signed(-9, 11), to_signed(-8, 11), to_signed(-8, 11), to_signed(-7, 11), + to_signed(-7, 11), to_signed(-6, 11), to_signed(-6, 11), to_signed(-5, 11), + to_signed(-5, 11), to_signed(-4, 11), to_signed(-4, 11), to_signed(-3, 11), + to_signed(-3, 11), to_signed(-3, 11), to_signed(-2, 11), to_signed(-2, 11), + to_signed(-2, 11), to_signed(-1, 11), to_signed(-1, 11), to_signed(-1, 11), + to_signed(-1, 11), to_signed(-1, 11), to_signed(-1, 11) + ); + + SR_BcoefRegister <= (to_signed(480, 11), + to_signed(-777, 11), + to_signed(480, 11) + ); + + SR_AcoefRegister <= (to_signed(512, 11), + to_signed(-777, 11), + to_signed(449, 11) + ); + + SR_HcoefRegister <= (to_signed(-119, 11), + to_signed(122, 11), + to_signed(149, 11), + to_signed(191, 11), + to_signed(226, 11), + to_signed(239, 11), + to_signed(226, 11), + to_signed(191, 11), + to_signed(149, 11), + to_signed(122, 11), + to_signed(-119, 11) + ); + + + shiftX : process (I_reset, I_clock) is + begin -- process shift + if I_reset = '1' then -- asynchronous reset (active high) + SR_XshiftRegister <= (others => (others => '0')); + elsif Rising_edge(I_clock) then + if I_loadShiftX = '1' then + SR_XshiftRegister(0) <= signed(I_inputSample); + SR_XshiftRegister(1 to 95) <= SR_XshiftRegister(0 to 94); + end if; + end if; + end process shiftX ; + + shiftY : process (I_reset, I_clock) is + begin -- process shift + if I_reset = '1' then -- asynchronous reset (active high) + SR_YshiftRegister <= (others => (others => '0')); + elsif Rising_edge(I_clock) then + if I_loadShiftY = '1' then + if SC_addResult(9) = '1' then --cas ou on arrondi à l'entier supérieur + SR_Y <= SC_addResult(20 downto 10) + 1; + SR_YshiftRegister(0) <= signed(SC_addResult(20 downto 10) + 1); + else -- cas ou on arrondi à l'entier inférieur + SR_Y <= SC_addResult(20 downto 10); + SR_YshiftRegister(0) <= signed(SC_addResult(20 downto 10)); + end if; + SR_YshiftRegister(1 to 2) <= SR_YshiftRegister(0 to 1); + end if; + end if; + end process shiftY ; + + shiftZ : process (I_reset, I_clock) is + begin -- process shift + if I_reset = '1' then -- asynchronous reset (active high) + SR_ZshiftRegister <= (others => (others => '0')); + elsif Rising_edge(I_clock) then + if I_loadShiftZ = '1' then + if SC_addResult(8) = '1' then --cas ou on arrondi à l'entier supérieur + SR_Y <= SC_addResult(19 downto 9) + 1; + SR_ZshiftRegister(0) <= signed(SC_addResult(19 downto 9) + 1); + else -- cas ou on arrondi à l'entier inférieur + SR_Y <= SC_addResult(20 downto 10); + SR_ZshiftRegister(0) <= signed(SC_addResult(19 downto 9)); + end if; + SR_ZshiftRegister(1 to 10) <= SR_ZshiftRegister(0 to 9); + end if; + end if; + end process shiftZ ; + + + + incr_address : process (I_reset, I_clock) is + begin + 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' and SR_readAddress <= 93 then + SR_readAddress <= SR_readAddress + 1; +-- elsif I_coeffs = "00" then +-- if I_incrAddress = '1' and SR_readAddress <= 93 then +-- SR_readAddress <= SR_readAddress + 1; +-- end if; +-- elsif I_coeffs = "01" then +-- if I_incrAddress = '1' and SR_readAddress <= 2 then +-- SR_readAddress <= SR_readAddress + 1; +-- end if; + end if; + end if; + end process incr_address; + + O_GprocessingDone <= '1' when SR_readAddress = 94 else '0'; + O_BprocessingDone <= '1' when SR_readAddress = 1 else '0'; + O_AprocessingDone <= '1' when SR_readAddress = 0 else '0'; + O_HprocessingDone <= '1' when SR_readAddress = 9 else '0'; + + + SC_multOperand1 <= SR_XshiftRegister(SR_readAddress) when I_samples = "00" else + SR_YshiftRegister(SR_readAddress) when I_samples = "01" else + SR_ZshiftRegister(SR_readAddress) when I_samples = "10" or I_samples = "11"; + + SC_multOperand2 <= SR_GcoefRegister(SR_readAddress) when I_coeffs = "00" else + SR_BcoefRegister(SR_readAddress) when I_coeffs ="01" else + SR_AcoefRegister(SR_readAddress) when I_coeffs ="10" else + SR_HcoefRegister(SR_readAddress) when I_coeffs ="11"; + + + SC_MultResult <= SC_multOperand1 * SC_multOperand2; + SC_addResult <= resize(SC_MultResult, SC_addResult'length) + SR_sum; + + sum_acc : process (I_reset, I_clock) is + begin + if I_reset = '1' then -- asynchronous reset (active high) + SR_sum <= (others => '0'); + elsif Rising_edge(I_clock) then + if I_initSum = '1' then + SR_sum <= (others => '0'); + elsif I_loadSum = '1' then + SR_sum <= SC_addResult; + end if; + end if; + end process sum_acc; + + store_result : process (I_clock) is + begin + if Rising_edge(I_clock) then + if I_loadY = '1' then + if SC_addResult(9) = '1' then + SR_Y <= SC_addResult(20 downto 10) + 1; + else + SR_Y <= SC_addResult(20 downto 10); + end if; + end if; + end if; + + end process store_result; + + O_Y <= std_logic_vector(SR_Y); + +end architecture arch_operativeUnit; -- GitLab