diff --git a/src-ref/controlUnit.vhd b/src-ref/controlUnit.vhd new file mode 100644 index 0000000000000000000000000000000000000000..a0964690fb001ab8b59eaa199660ea38b8cd6aa6 --- /dev/null +++ b/src-ref/controlUnit.vhd @@ -0,0 +1,142 @@ +------------------------------------------------------------------------------- +-- Title : controlUnit +-- 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: Control unit of a sequential FIR filter. +------------------------------------------------------------------------------- +-- Copyright (c) 2018 +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2018-04-11 1.0 jnbazin Created +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity controlUnit is + + port ( + I_clock : in std_logic; -- global clock + I_reset : in std_logic; -- asynchronous global reset + I_inputSampleValid : in std_logic; -- Control signal to load the input sample in the sample shift register and shift the register + I_processingDone1 : in std_logic; + I_processingDone2_1 : in std_logic; + I_processingDone2_2 : in std_logic; + I_processingDone3 : in std_logic; + O_loadShift : out std_logic_vector(1 downto 0); -- filtered sample + O_initAddress : out std_logic; -- Control signal to initialize register read address + O_incrAddress : out std_logic; -- Control signal to increment register read address + O_initSum : out std_logic; -- Control signal to initialize the MAC register + O_loadSum : out std_logic; -- Control signal to load the MAC register; + O_loadOutput : out std_logic; -- Control signal to load Y register + O_Selector : out std_logic_vector(1 downto 0) + --O_FilteredSampleValid : out std_logic -- Data valid signal for filtered sample + ); + +end entity controlUnit; + +architecture archi_operativeUnit of controlUnit is + + + type T_state is (WAIT_SAMPLE, STORE1, STORE2, STORE3, PROCESSING_LOOP1,PROCESSING_LOOP2_1,PROCESSING_LOOP2_2,PROCESSING_LOOP3, OUTPUT, WAIT_END_SAMPLE); -- state list + signal SR_presentState : T_state; + signal SR_futurState : T_state; + +begin + + process (I_clock, I_reset) is + begin + if I_reset = '1' then -- asynchronous reset (active high) + SR_presentState <= WAIT_SAMPLE; + elsif rising_edge(I_clock) then -- rising clock edge + SR_presentState <= SR_futurState; + end if; + end process; + + process (I_inputSampleValid, I_processingDone1, I_processingDone2_1, I_processingDone2_2, I_processingDone3, SR_presentState) is + begin + case SR_presentState is + + when WAIT_SAMPLE => + if I_inputSampleValid = '1' then + SR_futurState <= STORE1; + else + SR_futurState <= WAIT_SAMPLE; + end if; + + when STORE1 => + SR_futurState <= PROCESSING_LOOP1; + + when PROCESSING_LOOP1 => + if I_processingDone1 = '1' then + SR_futurState <= STORE2; + else + SR_futurState <= PROCESSING_LOOP1; + end if; + + when STORE2 => + SR_futurState <= PROCESSING_LOOP2_1; + + when PROCESSING_LOOP2_1 => + if I_processingDone2_1 = '1' then + SR_futurState <= PROCESSING_LOOP2_2; + else + SR_futurState <= PROCESSING_LOOP2_1; + end if; + + when PROCESSING_LOOP2_2 => + if I_processingDone2_2 = '1' then + SR_futurState <= STORE3; + else + SR_futurState <= PROCESSING_LOOP2_2; + end if; + + when STORE3 => + SR_futurState <= PROCESSING_LOOP3; + + when PROCESSING_LOOP3 => + if I_processingDone3 = '1' then + SR_futurState <= OUTPUT; + else + SR_futurState <= PROCESSING_LOOP3; + end if; + + when OUTPUT => + SR_futurState <= WAIT_END_SAMPLE; + + when others => ---WAIT_END_SAMPLE + if I_inputSampleValid = '1' then + SR_futurState <= WAIT_SAMPLE; + else + SR_futurState <= WAIT_END_SAMPLE; + end if; + + end case; + end process; + + O_loadShift <= "01" when SR_presentState = STORE1 else + "10" when SR_presentState = STORE2 else + "11" when SR_presentState = STORE3 else + "00"; + O_initAddress <= '1' when SR_presentState = STORE1 or SR_presentState = STORE2 or SR_presentState = STORE3 else '0'; + O_incrAddress <= '1' when SR_presentState = PROCESSING_LOOP1 or SR_presentState = PROCESSING_LOOP2_1 or SR_presentState = PROCESSING_LOOP2_2 or SR_presentState = PROCESSING_LOOP3 else '0'; + O_initSum <= '1' when SR_presentState = STORE1 or SR_presentState = STORE2 or SR_presentState = STORE3 else '0'; + O_loadSum <= '1' when SR_presentState = PROCESSING_LOOP1 or SR_presentState = PROCESSING_LOOP2_1 or SR_presentState = PROCESSING_LOOP2_2 or SR_presentState = PROCESSING_LOOP3 else '0'; + O_loadOutput <= '1' when SR_presentState = OUTPUT else '0' ; + O_Selector <= "01" when SR_presentState = STORE2 or SR_presentState = PROCESSING_LOOP2_1 else + "10" when SR_presentState = PROCESSING_LOOP2_2 else + "11" when SR_presentState = STORE3 or SR_presentState = PROCESSING_LOOP3 else + "00"; + --O_FilteredSampleValid <= '1' when SR_presentState = WAIT_END_SAMPLE else '0' ; + +end architecture archi_operativeUnit; diff --git a/src-ref/operativeUnit.vhd b/src-ref/operativeUnit.vhd new file mode 100644 index 0000000000000000000000000000000000000000..b85a2f52ae4feb7d218953891b1126d04b6aef3e --- /dev/null +++ b/src-ref/operativeUnit.vhd @@ -0,0 +1,336 @@ +------------------------------------------------------------------------------- +-- 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(7 downto 0); -- 8 bit input sample + I_loadShift : in std_logic_vector(1 downto 0); -- Control signal to load the input sample in the sample shift register and shift the register + 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_loadOutput : in std_logic; -- Control signal to load Y register + I_Selector : in std_logic_vector(1 downto 0); + O_processingDone1 : out std_logic; -- Indicate that processing is done + O_processingDone2_1 : out std_logic; -- Indicate that processing is done + O_processingDone2_2 : out std_logic; -- Indicate that processing is done + O_processingDone3 : out std_logic; -- Indicate that processing is done + O_Y : out std_logic_vector(7 downto 0) -- filtered sample + ); + +end entity operativeUnit; + +architecture arch_operativeUnit of operativeUnit is + type registerFile is array(0 to 15) of signed(7 downto 0); + signal SR_coefRegisterH : registerFile; + signal SR_coefRegisterB : registerFile; + signal SR_coefRegisterA : registerFile; + signal SR_coefRegisterG : registerFile; + + + signal SR_shiftRegisterX : registerFile; -- shift register file used to store and shift input samples + signal SR_shiftRegisterY : registerFile; -- shift register file used to store and shift input samples + signal SR_shiftRegisterZ : registerFile; -- shift register file used to store and shift input samples + + + signal SC_multOperandX : signed(10 downto 0); + signal SC_multOperandY : signed(10 downto 0); + signal SC_multOperandZ : signed(10 downto 0); + signal SC_multOperandH : signed(10 downto 0); + signal SC_multOperandB : signed(10 downto 0); + signal SC_multOperandA : signed(10 downto 0); + signal SC_multOperandG : signed(10 downto 0); + signal SC_multOperandCoef : signed(10 downto 0); + signal SC_multOperandShift : signed(10 downto 0); + + signal SC_MultResult : signed(21 downto 0); -- Result of the multiplication Xi*Hi + signal SC_addResult : signed(28 downto 0); -- result of the accumulation addition + signal SR_sum : signed(28 downto 0); -- Accumulation register + signal SR_Y : signed(7 downto 0); -- filtered sample storage register + signal SR_readAddress : integer range 0 to 128; -- register files read address + + +-- Coefficients des filtres + +begin + +-- Low-pass filter provided with octave (or Matlab ;)) command +--fir1(15, .001)/sqrt(sum(fir1(15, .001).^2))*2^6 + + +-- BaseLine filter provided with octave (or Matlab ;)) command +-- fir1(128, 1/100, 'high')*2^10 + SR_coefRegisterH <= (to_signed(-1, 11), -- ROM register used file to store FIR coefficients + 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) + ); + +-- Pei Tseng Notch filter provided by octave +-- [b, a] = pei_tseng_notch(1/5, 1/25)*2^9 +SR_coefRegisterB <= ( + to_signed(480, 11), + to_signed(-777, 11), + to_signed(480, 11) + ); + +SR_coefRegisterA <= ( + to_signed(512, 11), + to_signed(-777, 11), + to_signed(449, 11) + ); + +-- Parks McClellan filter provided by octave +-- fLP = remez(10, [0 50 60 250]/250, [1 1 0 0])*2^10 +SR_coefRegisterG <= ( + 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) + ); + + + shift : process (I_clock, I_reset) is + begin -- process shift + if I_reset = '1' then -- asynchronous reset (active high) + SR_shiftRegisterX <= (others => (others => '0')); + SR_shiftRegisterY <= (others => (others => '0')); + SR_shiftRegisterZ <= (others => (others => '0')); + elsif rising_edge(I_clock) then + if I_loadShift = "01" then + for i in 128 downto 1 loop + SR_shiftRegisterX(i) <= SR_shiftRegisterX(i-1); + end loop; + SR_shiftRegisterX(0) <= signed(I_inputSample); + end if; + + if I_loadShift = "10" then + for i in 2 downto 1 loop + SR_shiftRegisterY(i) <= SR_shiftRegisterY(i-1); + end loop; + SR_shiftRegisterY(0) <= signed(SC_addResult); + end if; + + if I_loadShift = "11" then + for i in 10 downto 1 loop + SR_shiftRegisterZ(i) <= SR_shiftRegisterZ(i-1); + end loop; + SR_shiftRegisterZ(0) <= signed(SC_addResult); + end if; + + end if; + + end process shift; + +-- Definition AdressGenerator + + incr_address : process (I_clock, I_reset) 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') then + if SR_readAddress < 128 then + SR_readAddress <= SR_readAddress + 1; + else + SR_readAddress <= 0; + end if; + end if; + end if; + end process incr_address; + +-- Definition des ProcessingDone + + O_processingDone1 <= '1' when SR_readAddress = 128 else '0'; + O_processingDone2_1 <= '1' when SR_readAddress >= 2 else '0'; + O_processingDone2_2 <= '1' when SR_readAddress >= 2 else '0'; --penser à commencer la 3eme boucle a 1 + O_processingDone3 <= '1' when SR_readAddress >= 11 else '0'; + +-- Definition des multiplexeurs + + SC_multOperandX <= SR_shiftRegisterX(SR_readAddress); -- 11 bits + SC_multOperandY <= SR_shiftRegisterY(SR_readAddress) when (SR_readAddress <= 2) else (others => '0'); + SC_multOperandZ <= SR_shiftRegisterZ(SR_readAddress) when (SR_readAddress <= 10) else (others => '0'); + + SC_multOperandH <= SR_coefRegisterH(SR_readAddress) ; -- 11 bits + SC_multOperandB <= SR_coefRegisterB(SR_readAddress) when (SR_readAddress >= 1 and SR_readAddress <= 2) else (others => '0'); + SC_multOperandA <= SR_coefRegisterA(SR_readAddress) when (SR_readAddress <= 2) else (others => '0'); + SC_multOperandG <= SR_coefRegisterG(SR_readAddress) when (SR_readAddress <= 10) else (others => '0'); + + SC_multOperandCoef <= SC_multOperandX when I_Selector = "00" else + SC_multOperandY when I_Selector = "01" else + SC_multOperandZ; + + SC_multOperandShift <= SC_multOperandH when I_Selector = "00" else + SC_multOperandB when I_Selector = "01" else + SC_multOperandA when I_Selector = "10" else + SC_multOperandG; + + SC_MultResult <= SC_multOperandCoef * SC_multOperandShift ; -- 22 bits + SC_addResult <= resize(SC_MultResult, SC_addResult'length) + SR_sum; -- 28 bits + +-- Definition du registre sommateur + + sum_acc : process (I_clock, I_reset) 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; + +-- Definition du registre de sortie + + store_result : process (I_clock) is + begin + if rising_edge(I_clock) then + if (I_loadOutput = '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;