diff --git a/src/hdl/operativeUnit.vhd b/src/hdl/operativeUnit.vhd index 68ac0a1c7824194002029b791f9e4fa2faf27998..a277fdfa7a77717a847ae5d206ec9db2d2ae2e1c 100644 --- a/src/hdl/operativeUnit.vhd +++ b/src/hdl/operativeUnit.vhd @@ -1,219 +1,353 @@ -------------------------------------------------------------------------------- --- 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 ( - initAddress : in std_logic; - I_incrAddress : in std_logic; - I_x : in std_logic; - I_y : in std_logic; - I_z1 : in std_logic; - I_z2 : in std_logic; - I_initSum : in std_logic; - I_loadSum : in std_logic; - I_inputSample : in std_logic_vector(10 downto 0); - I_loadShift_x : in std_logic; - I_loadShift_y : in std_logic; - I_loadShift_z : in std_logic; - I_loadY : in std_logic; - I_loadRun : in std_logic; - - O_processingDone: in std_logic; - O_Y : in std_logic_vector(10 downto 0) - ); - -end entity operativeUnit; - -architecture arch_operativeUnit of operativeUnit is - type registerFile_h is array(0 to 128) of signed(10 downto 0); - type registerFile_b is array(0 to 2) of signed(10 downto 0); - type registerFile_a is array(0 to 1) of signed(10 downto 0); - type registerFile_g is array(0 to 10) of signed(10 downto 0); - - signal SR_read_add_x : unsigned(128 downto 0); - signal SR_read_add_y : unsigned(2 downto 0); - signal SR_read_add_z1 : unsigned(1 downto 0); - signal SR_read_add_z2 : unsigned(10 downto 0); - - signal SR_Sample_Sel : unsigned(2 downto 0); - signal SR_Coeff_Sel : unsigned(3 downto 0); - - signal SC_sample_x : signed(10 downto 0); - signal SC_sample_y : signed(10 downto 0); - signal SC_sample_z : signed(10 downto 0); - - signal SC_coeff_h : signed(10 downto 0); - signal SC_coeff_b : signed(10 downto 0); - signal SC_coeff_a : signed(10 downto 0); - signal SC_coeff_g : signed(10 downto 0); - - signal SC_multOperand1 : signed(10 downto 0); - signal SC_multOperand2 : signed(10 downto 0); - - signal SC_add : unsigned(28 downto 0); - - signal SC_multResult : unsigned(21 downto 0); - signal SC_addResult : unsigned(28 downto 0); - - signal SC_output : signed(10 downto 0); - - signal SC_coeff_h : registerFile_h; - signal SC_coeff_b : registerFile_b; - signal SC_coeff_a : registerFile_a; - signal SC_coeff_g : registerFile_g; - - signal SC_sample_x : registerFile_h; - signal SC_sample_y : registerFile_b; - signal SC_sample_z : registerFile_g; - -begin - --- Low-pass filter provided with octave (or Matlab ;)) command ---fir1(15, .001)/sqrt(sum(fir1(15, .001).^2))*2^6 - SR_coefRegister <= (to_signed(2, 8), -- ROM register used file to store FIR coefficients - to_signed(3, 8), - to_signed(6, 8), - to_signed(10, 8), - to_signed(15, 8), - to_signed(20, 8), - to_signed(24, 8), - to_signed(26, 8), - to_signed(26, 8), - to_signed(24, 8), - to_signed(20, 8), - to_signed(15, 8), - to_signed(10, 8), - to_signed(6, 8), - to_signed(3, 8), - to_signed(2, 8) - ); - - shift : process (I_clock, I_reset) is - begin -- process shift - if I_reset = '1' then - SC_sample_x <= (others => '0'); - SC_sample_y <= (others => '0'); - SC_sample_z <= (others => '0'); - elsif rising_edge(I_clock) then - if I_loadShift_x = '1' then - SC_sample_x <= SC_sample_x(1 to 128); - SC_sample_x(0) <= signed(I_inputSample); - elsif I_loadShift_y = '1' then - SC_sample_y <= SR_read_add_y(1 to 2); - SC_sample_y(0) <= signed(SC_addResult(10 to 20)); -- a checker - elsif I_loadShift_z = '1' then - SC_sample_z <= SR_read_add_z2(1 to 10); - SC_sample_z(0) <= signed(SC_addResult(9 to 19)); -- a checker - end if; - end if; - end process shift; - - incr_address : process (I_clock, I_reset) is - begin - if I_reset = '1' then - SR_read_add_x <= (others => '0'); - SR_read_add_y <= (others => '0'); - SR_read_add_z1 <= (others => '0'); - SR_read_add_z2 <= (others => '0'); - elsif rising_edge(I_clock) then - if I_initAddress = '1' then - SR_read_add_x <= 0; - SR_read_add_y <= 0; - SR_read_add_z1 <= 0; - SR_read_add_z2 <= 0; - elsif I_incrAddress = '1' then - if SR_read_add_x < 129 then - SR_read_add_x <= SR_read_add_x + 1; - end if; - if SR_read_add_y < 3 then - SR_read_add_y <= SR_read_add_y + 1; - end if; - if SR_read_add_z1 < 2 then - SR_read_add_z1 <= SR_read_add_z1 + 1; - end if; - if SR_read_add_z2 < 11 then - SR_read_add_z2 <= SR_read_add_z2 + 1; - end if; - end if; - end if; - end process incr_address; - - O_processingDone <= '1' when SR_read_add_x > 128 or - SR_read_add_y > 3 or - SR_read_add_z1 > 2 or - SR_read_add_z2 > 11 - else '0'; - - SC_multOperand1 <= SR_Sample_Sel(SC_sample_x) when I_x = '1' else - SR_Sample_Sel(SC_sample_y) when I_y = '1' else - SR_Sample_Sel(SC_sample_z) when I_z1 = '1' else - SR_Sample_Sel(SC_sample_z) when I_z2 = '1' else - (others => '0'); - SC_multOperand2 <= SR_Coeff_Select(SC_coeff_h) when I_x = '1' else - SR_Coeff_Select(SC_coeff_b) when I_y = '1' else - SR_Coeff_Select(SC_coeff_a) when I_z1 = '1' else - SR_Coeff_Select(SC_coeff_g) when I_z2 = '1' else - (others => '0'); - SC_multResult <= SC_multOperand1*SC_multOperand2; - SC_addResult <= SC_multResult + SC_add; - - sum_acc : process(I_clock, I_reset) is - begin - if I_reset = '1' then - SC_add <= (others => '0'); - elsif rising_edge(I_clock) then - if I_loadSum = '1' then - SC_add <= SC_addResult; - elsif I_initSum = '1' then - SC_add <= (others => '0'); - end if; - end if; - end process sum_acc; - - store_result : process (I_clock, I_reset) is - begin - if I_reset = '1' then - SC_output <= (others => '0'); - elsif rising_edge(I_clock) then - if I_loadRun = '1' then - if SC_addResult(9) = '1' then - SC_output <= SC_addResult(20 downto 10) + 1; - else - SC_output <= SC_addResult(20 downto 10); - end if; - end if; - end if; - end process store_result; - - O_Y <= std_logic_vector(SC_output); - -end architecture arch_operativeUnit; +------------------------------------------------------------------------------- +-- 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 ( + initAddress : in std_logic; + I_incrAddress : in std_logic; + I_x : in std_logic; + I_y : in std_logic; + I_z1 : in std_logic; + I_z2 : in std_logic; + I_initSum : in std_logic; + I_loadSum : in std_logic; + I_inputSample : in std_logic_vector(10 downto 0); + I_loadShift_x : in std_logic; + I_loadShift_y : in std_logic; + I_loadShift_z : in std_logic; + I_loadY : in std_logic; + I_loadRun : in std_logic; + + O_processingDone: in std_logic; + O_Y : in std_logic_vector(10 downto 0) + ); + +end entity operativeUnit; + +architecture arch_operativeUnit of operativeUnit is + type registerFile_h is array(0 to 128) of signed(10 downto 0); + type registerFile_b is array(0 to 2) of signed(10 downto 0); + type registerFile_a is array(0 to 1) of signed(10 downto 0); + type registerFile_g is array(0 to 10) of signed(10 downto 0); + + signal SR_read_add_x : unsigned(128 downto 0); + signal SR_read_add_y : unsigned(2 downto 0); + signal SR_read_add_z1 : unsigned(1 downto 0); + signal SR_read_add_z2 : unsigned(10 downto 0); + + signal SR_Sample_Sel : unsigned(2 downto 0); + signal SR_Coeff_Sel : unsigned(3 downto 0); + + signal SC_sample_x : signed(10 downto 0); + signal SC_sample_y : signed(10 downto 0); + signal SC_sample_z : signed(10 downto 0); + + signal SC_coeff_h : signed(10 downto 0); + signal SC_coeff_b : signed(10 downto 0); + signal SC_coeff_a : signed(10 downto 0); + signal SC_coeff_g : signed(10 downto 0); + + signal SC_multOperand1 : signed(10 downto 0); + signal SC_multOperand2 : signed(10 downto 0); + + signal SC_add : unsigned(28 downto 0); + + signal SC_multResult : unsigned(21 downto 0); + signal SC_addResult : unsigned(28 downto 0); + + signal SC_output : signed(10 downto 0); + + signal SC_coeff_h : registerFile_h; + signal SC_coeff_b : registerFile_b; + signal SC_coeff_a : registerFile_a; + signal SC_coeff_g : registerFile_g; + + signal SC_sample_x : registerFile_h; + signal SC_sample_y : registerFile_b; + signal SC_sample_z : registerFile_g; + +begin + +-- Low-pass filter provided with octave (or Matlab ;)) command +--fir1(15, .001)/sqrt(sum(fir1(15, .001).^2))*2^6 + SC_coeff_h <= (to_signed(0,11), + to_signed(0,11), + to_signed(0,11), + to_signed(0,11), + to_signed(0,11), + to_signed(0,11), + to_signed(0,11), + to_signed(0,11), + to_signed(0,11), + to_signed(0,11), + to_signed(0,11), + to_signed(0,11), + to_signed(0,11), + to_signed(0,11), + to_signed(0,11), + to_signed(0,11), + to_signed(0,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), + 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), + to_signed(0,11), + to_signed(0,11), + to_signed(0,11), + to_signed(0,11), + to_signed(0,11), + to_signed(0,11), + to_signed(0,11), + to_signed(0,11), + to_signed(0,11), + to_signed(0,11), + to_signed(0,11), + to_signed(0,11), + to_signed(0,11), + to_signed(0,11), + to_signed(0,11), + to_signed(0,11), + to_signed(0,11) + ); + + SC_coeff_b <= (to_signed(480, 11), -- ROM register used file to store FIR coefficients + to_signed(-777, 11), + to_signed(480, 11) + ); + SC_coeff_a <= (to_signed(-777, 11), -- ROM register used file to store FIR coefficients + to_signed(449, 11) + ); + + SC_coeff_g <= (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 + SC_sample_x <= (others => '0'); + SC_sample_y <= (others => '0'); + SC_sample_z <= (others => '0'); + elsif rising_edge(I_clock) then + if I_loadShift_x = '1' then + SC_sample_x <= SC_sample_x(1 to 128); + SC_sample_x(0) <= signed(I_inputSample); + elsif I_loadShift_y = '1' then + SC_sample_y <= SR_read_add_y(1 to 2); + SC_sample_y(0) <= signed(SC_addResult(10 to 20)); -- a checker + elsif I_loadShift_z = '1' then + SC_sample_z <= SR_read_add_z2(1 to 10); + SC_sample_z(0) <= signed(SC_addResult(9 to 19)); -- a checker + end if; + end if; + end process shift; + + incr_address : process (I_clock, I_reset) is + begin + if I_reset = '1' then + SR_read_add_x <= (others => '0'); + SR_read_add_y <= (others => '0'); + SR_read_add_z1 <= (others => '0'); + SR_read_add_z2 <= (others => '0'); + elsif rising_edge(I_clock) then + if I_initAddress = '1' then + SR_read_add_x <= 0; + SR_read_add_y <= 0; + SR_read_add_z1 <= 0; + SR_read_add_z2 <= 0; + elsif I_incrAddress = '1' then + if SR_read_add_x < 129 then + SR_read_add_x <= SR_read_add_x + 1; + end if; + if SR_read_add_y < 3 then + SR_read_add_y <= SR_read_add_y + 1; + end if; + if SR_read_add_z1 < 2 then + SR_read_add_z1 <= SR_read_add_z1 + 1; + end if; + if SR_read_add_z2 < 11 then + SR_read_add_z2 <= SR_read_add_z2 + 1; + end if; + end if; + end if; + end process incr_address; + + O_processingDone <= '1' when SR_read_add_x > 128 or + SR_read_add_y > 3 or + SR_read_add_z1 > 2 or + SR_read_add_z2 > 11 + else '0'; + + SC_multOperand1 <= SR_Sample_Sel(SC_sample_x) when I_x = '1' else + SR_Sample_Sel(SC_sample_y) when I_y = '1' else + SR_Sample_Sel(SC_sample_z) when I_z1 = '1' else + SR_Sample_Sel(SC_sample_z) when I_z2 = '1' else + (others => '0'); + SC_multOperand2 <= SR_Coeff_Select(SC_coeff_h) when I_x = '1' else + SR_Coeff_Select(SC_coeff_b) when I_y = '1' else + SR_Coeff_Select(SC_coeff_a) when I_z1 = '1' else + SR_Coeff_Select(SC_coeff_g) when I_z2 = '1' else + (others => '0'); + SC_multResult <= SC_multOperand1*SC_multOperand2; + SC_addResult <= SC_multResult + SC_add; + + sum_acc : process(I_clock, I_reset) is + begin + if I_reset = '1' then + SC_add <= (others => '0'); + elsif rising_edge(I_clock) then + if I_loadSum = '1' then + SC_add <= SC_addResult; + elsif I_initSum = '1' then + SC_add <= (others => '0'); + end if; + end if; + end process sum_acc; + + store_result : process (I_clock, I_reset) is + begin + if I_reset = '1' then + SC_output <= (others => '0'); + elsif rising_edge(I_clock) then + if I_loadRun = '1' then + if SC_addResult(9) = '1' then + SC_output <= SC_addResult(20 downto 10) + 1; + else + SC_output <= SC_addResult(20 downto 10); + end if; + end if; + end if; + end process store_result; + + O_Y <= std_logic_vector(SC_output); + +end architecture arch_operativeUnit;