diff --git a/project_ecg/project_ecg.srcs/sources_1/new/controlUnit.vhd b/project_ecg/project_ecg.srcs/sources_1/new/controlUnit.vhd new file mode 100644 index 0000000000000000000000000000000000000000..31d981f878121e55378838f8998ab36b28809b31 --- /dev/null +++ b/project_ecg/project_ecg.srcs/sources_1/new/controlUnit.vhd @@ -0,0 +1,145 @@ +------------------------------------------------------------------------------- +-- Title : controlUnit +-- Project : +------------------------------------------------------------------------------- +-- File : controlUnit.vhd +-- Author : Elodie Bottin et Théophile Deconche +-- Company : +-- Created : 2025-03-19 +-- Last update: 2025-03-19 +-- Platform : +-- Standard : VHDL'93/02 +------------------------------------------------------------------------------- +-- Description: Control unit of an ecg. +------------------------------------------------------------------------------- +-- Copyright (c) 2025 +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2025-03-19 1.0 e23botti 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_processingDoneFIR1 : in std_logic; + I_processingDoneFIR2 : in std_logic; + I_processingDoneIIR1 : in std_logic; + I_processingDoneIIR2 : in std_logic; + 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_loadY : out std_logic; -- Control signal to load Y register + O_FilteredSampleValid : out std_logic; -- Data valid signal for filtered sample + + O_samples : out std_logic_vector(1 downto 0); -- 2 bit input sample + O_coeff : out std_logic_vector(1 downto 0); -- 2 bit input sample + O_loadShiftX : out std_logic; + O_loadShiftY : out std_logic; + O_loadShiftZ : out std_logic + + ); + +end entity controlUnit; +architecture archi_operativeUnit of controlUnit is + + + type T_state is (WAIT_SAMPLE, STORE, PROCESSING_LOOP_FIR1, STORE_IIR1, PROCESSING_LOOP_IIR1, INIT_IIR2, PROCESSING_LOOP_IIR2, STORE_FIR2, PROCESSING_LOOP_FIR2, 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 (SR_presentState, I_inputSampleValid, I_processingDone) is + begin + case SR_presentState is + + when WAIT_SAMPLE => + if I_inputSampleValid = '1' then + SR_futurState <= STORE; + end if; + + when STORE => + SR_futurState <= PROCESSING_LOOP; + + when PROCESSING_LOOP_FIR1 => + if I_processingDoneFIR1 = '1' then + SR_futurState <= STORE_IIR1; + end if; + + when STORE_IIR1 => + SR_futurState <= PROCESSING_LOOP_IIR1; + + when PROCESSING_LOOP_IIR1 => + if I_processingDoneIIR1 = '1' then + SR_futurState <= INIT_IIR2; + end if; + + when INIT_IIR2 => + SR_futurState <= PROCESSING_LOOP_IIR2; + + when PROCESSING_LOOP_IIR2 => + if I_processingDoneIIR2 = '1' then + SR_futurState <= STORE_FIR2; + end if; + + when STORE_FIR2 => + SR_futurState <= PROCESSING_LOOP_FIR2; + + when PROCESSING_LOOP_FIR2 => + if I_processingDoneFIR2 = '1' then + SR_futurState <= OUTPUT; + end if; + + when OUTPUT => + SR_futurState <= WAIT_END_SAMPLE; + + when WAIT_END_SAMPLE => + if I_inputSampleValid = '0' then + SR_futurState <= WAIT_SAMPLE; + end if; + + when others => null; + end case; + end process; + + + O_initAddress <= '1' when ((SR_presentState = STORE or SR_presentState = STORE_IIR1) or (SR_presentState = INIT_IIR2 or SR_presentState = STORE_FIR2)) else '0'; + O_incrAddress <= '1' when ((SR_presentState = PROCESSING_LOOP_FIR1 or SR_presentState = PROCESSING_LOOP_IIR1) or (SR_presentState = PROCESSING_LOOP_IIR2 or SR_presentState = PROCESSING_LOOP_FIR2)) else '0'; + O_initSum <= '1' when ((SR_presentState = STORE or SR_presentState = STORE_IIR1) or (SR_presentState = INIT_IIR2 or SR_presentState = STORE_FIR2)) else '0'; + O_loadSum <= '1' when ((SR_presentState = PROCESSING_LOOP_FIR1 or SR_presentState = PROCESSING_LOOP_IIR1) or (SR_presentState = PROCESSING_LOOP_IIR2 or SR_presentState = PROCESSING_LOOP_FIR2)) else '0'; + O_loadY <= '1' when SR_presentState = OUTPUT else '0'; + O_FilteredSampleValid <= '1' when (SR_presentState = OUTPUT or SR_presentState = WAIT_END_SAMPLE) else '0'; + O_samples <= "00" when (SR_presentState = PROCESSING_LOOP_FIR1 or SR_presentState = STORE) else + "01" when (SR_presentState = PROCESSING_LOOP_IIR1 or SR_presentState = STORE_IIR1) else "10"; + +O_coeff <= "00" when (SR_presentState = PROCESSING_LOOP_FIR1 or SR_presentState = STORE) else + "01" when (SR_presentState = PROCESSING_LOOP_IIR1 or SR_presentState = STORE_IIR1) else + "10" when (SR_presentState = PROCESSING_LOOP_IIR2 or SR_presentState = INIT_IIR2) else "11"; + + O_loadShiftX <= '1' when SR_presentState = STORE else '0'; + O_loadShiftY <= '1' when SR_presentState = STORE_IIR1 else '0'; + O_loadShiftZ <= '1' when SR_presentState = PROCESSING_LOOP_IIR1 else '0'; + + + + + +end architecture archi_operativeUnit; diff --git a/project_ecg/project_ecg.srcs/sources_1/new/operativUnit.vhd b/project_ecg/project_ecg.srcs/sources_1/new/operativUnit.vhd new file mode 100644 index 0000000000000000000000000000000000000000..d718fdac525e324386ea01aecc73b44b4db08712 --- /dev/null +++ b/project_ecg/project_ecg.srcs/sources_1/new/operativUnit.vhd @@ -0,0 +1,270 @@ +------------------------------------------------------------------------------- +-- Title : operativUnit +-- Project : +------------------------------------------------------------------------------- +-- File : operativUnit.vhd +-- Author : Elodie Bottin et Théophile Deconche +-- Company : +-- Created : 2025-03-19 +-- Last update: 2025-03-19 +-- Platform : +-- Standard : VHDL'93/02 +------------------------------------------------------------------------------- +-- Description: Operativ unit of an ecg. +------------------------------------------------------------------------------- +-- Copyright (c) 2025 +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2025-03-19 1.0 e23botti Created +------------------------------------------------------------------------------- + +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; -- 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_loadY : in std_logic; -- Control signal to load Y register + O_processingDoneFIR1 : out std_logic; -- Indicate that processing is done + O_processingDoneFIR2 : out std_logic; + O_processingDoneIIR1 : out std_logic; + O_processingDoneIIR2 : out std_logic; + O_Y : out std_logic_vector(7 downto 0); -- filtered sample + + I_samples : in std_logic_vector(1 downto 0); -- 2 bit input sample + I_coeff : in std_logic_vector(1 downto 0); -- 2 bit input sample + I_loadShiftX : in std_logic; + I_loadShiftY : in std_logic; + I_loadShiftZ : in std_logic + + + + ); + +end entity operativeUnit; + +architecture arch_operativeUnit of operativeUnit is + type registerFileFIR1 is array(0 to 88) of signed(7 downto 0); + type registerFileFIR2 is array(0 to 11) of signed(7 downto 0); + type registerFileIIR1 is array(0 to 2) of signed(7 downto 0); + type registerFileIIR2 is array(0 to 2) of signed(7 downto 0); + + signal SR_coefFIR1 : registerFileFIR1; + signal SR_coefFIR2 : registerFileFIR2; + signal SR_coefIIR1 : registerFileIIR1; + signal SR_coefIIR2 : registerFileIIR2; + + + signal SR_shiftX : __BLANK__; + signal SR_shiftY : __BLANK__; + signal SR_shiftZ : __BLANK__; + signal SC_multOperand1 : signed(7 downto 0); + signal SC_multOperand2 : signed(7 downto 0); + signal SC_MultResult : signed(15 downto 0); -- Result of the multiplication Xi*Hi + signal SC_addResult : signed(19 downto 0); -- result of the accumulation addition + signal SR_sum : signed(19 downto 0); -- Accumulation register + signal SR_Y : signed(7 downto 0); -- filtered sample storage register + signal SR_readAddress : integer range 0 to 15; -- 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_coefFIR1 <= (to_signed(-1, 8), -- ROM register used file to store FIR coefficients + to_signed(-1, 8), + to_signed(-1, 8), + to_signed(-1, 8), + to_signed(-1, 8), + to_signed(-1, 8), + to_signed(-1, 8), + to_signed(-2, 8), + to_signed(-2, 8), + to_signed(-2, 8), + to_signed(-2, 8), + to_signed(-2, 8), + to_signed(-3, 8), + to_signed(-3, 8), + to_signed(-3, 8), + to_signed(-3, 8), + to_signed(-4, 8), + to_signed(-4, 8), + to_signed(-4, 8), + to_signed(-5, 8), + to_signed(-5, 8), + to_signed(-5, 8), + to_signed(-5, 8), + to_signed(-6, 8), + to_signed(-6, 8), + to_signed(-6, 8), + to_signed(-7, 8), + to_signed(-7, 8), + to_signed(-7, 8), + to_signed(-7, 8), + to_signed(-8, 8), + to_signed(-8, 8), + to_signed(-8, 8), + to_signed(-8, 8), + to_signed(-9, 8), + to_signed(-9, 8), + to_signed(-9, 8), + to_signed(-9, 8), + to_signed(-9, 8), + to_signed(-9, 8), + to_signed(-10, 8), + to_signed(-10, 8), + to_signed(-10, 8), + to_signed(-10, 8), + to_signed(502, 8), + to_signed(-10, 8), + to_signed(-10, 8), + to_signed(-10, 8), + to_signed(-10, 8), + to_signed(-9, 8), + to_signed(-9, 8), + to_signed(-9, 8), + to_signed(-9, 8), + to_signed(-9, 8), + to_signed(-9, 8), + to_signed(-8, 8), + to_signed(-8, 8), + to_signed(-8, 8), + to_signed(-8, 8), + to_signed(-7, 8), + to_signed(-7, 8), + to_signed(-7, 8), + to_signed(-7, 8), + to_signed(-6, 8), + to_signed(-6, 8), + to_signed(-6, 8), + to_signed(-5, 8), + to_signed(-5, 8), + to_signed(-5, 8), + to_signed(-5, 8), + to_signed(-4, 8), + to_signed(-4, 8), + to_signed(-4, 8), + to_signed(-3, 8), + to_signed(-3, 8), + to_signed(-3, 8), + to_signed(-3, 8), + to_signed(-2, 8), + to_signed(-2, 8), + to_signed(-2, 8), + to_signed(-2, 8), + to_signed(-2, 8), + to_signed(-1, 8), + to_signed(-1, 8), + to_signed(-1, 8), + to_signed(-1, 8), + to_signed(-1, 8), + to_signed(-1, 8), + to_signed(-1, 8) + ); + + SR_coefFIR2 <= (to_signed(-59, 8), + to_signed(61, 8), + to_signed(74, 8), + to_signed(96, 8), + to_signed(113, 8), + to_signed(120, 8), + to_signed(113, 8), + to_signed(96, 8), + to_signed(74, 8), + to_signed(61, 8), + to_signed(-59, 8)); + + SR_coefIIR1 <= (to_signed(480, 8), + to_signed(-777, 8), + to_signed(480, 8)); + + --à vérifier + SR_coefIIR2 <= (to_signed(512, 8), + to_signed(-777, 8), + to_signed(449, 8)); + + shift : process (I_reset, I_clock) is + begin -- process shift samples + if I_reset = '1' then -- asynchronous reset (active high) + SR_shiftX <= (others => (others => '0')); + SR_shiftY <= (others => (others => '0')); + SR_shiftZ <= (others => (others => '0')); + elsif rising_edge(I_clock) then + if I_loadShiftX = '1' then + SR_shiftX(1 to 15) <= SR_shiftX(0 to 14); + SR_shiftX(0) <= signed(I_inputSample); + elsif I_loadShiftY = '1' then + SR_shiftY(1 to 15) <= SR_shiftY(0 to 14); + SR_shiftY(0) <= signed(SC_addResult); + elsif I_loadShiftZ = '1' then + SR_shiftZ(1 to 15) <= SR_shiftZ(0 to 14); + SR_shiftZ(0) <= signed(SC_addResult); + + end if; + end if; + end process shift; + + 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 <= 14) then + SR_readAddress <= SR_readAddress + 1; + end if; + + end if; + end process incr_address; + + O_processingDone <= '1' when SR_readAddress >= 14 else '0' ; + + SC_multOperand1 <= SR_shiftFIR1(SR_readAddress); -- 8 bits + SC_multOperand2 <= SR_coefFIR1(SR_readAddress); -- 8 bits + SC_MultResult <= SC_multOperand1 * SC_multOperand2; -- 16 bits + 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_reset, I_clock) is + begin + if I_reset = '1' then -- asynchronous reset (active high) + SR_Y <= (others => '0'); + elsif rising_edge(I_clock) then + if I_loadY = '1' then + if SC_addResult(6) = '1' then + SR_Y <= SC_addResult(14 downto 7)+1; + else + SR_Y <= SC_addResult(14 downto 7); + end if; + end if; + end if; + + end process store_result; + + O_Y <= std_logic_vector(SR_Y); + +end architecture arch_operativeUnit;