URL
https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk
Subversion Repositories open8_urisc
[/] [open8_urisc/] [trunk/] [VHDL/] [mavg_8ch_16b_64d.vhd] - Rev 332
Go to most recent revision | Compare with Previous | Blame | View Log
-- Copyright (c)2023 Jeremy Seth Henry -- All rights reserved. -- -- Redistribution and use in source and binary forms, with or without -- modification, are permitted provided that the following conditions are met: -- * Redistributions of source code must retain the above copyright -- notice, this list of conditions and the following disclaimer. -- * Redistributions in binary form must reproduce the above copyright -- notice, this list of conditions and the following disclaimer in the -- documentation and/or other materials provided with the distribution, -- where applicable (as part of a user interface, debugging port, etc.) -- -- THIS SOFTWARE IS PROVIDED BY JEREMY SETH HENRY ``AS IS'' AND ANY -- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -- DISCLAIMED. IN NO EVENT SHALL JEREMY SETH HENRY BE LIABLE FOR ANY -- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -- THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- -- VHDL units : mavg_8ch_16b_64d -- Description: 8-channel moving average calculation for 16-bit unsigned data -- Accumulator depth is 64 elements, using 1 block RAM. -- -- Revision History -- Author Date Change ------------------ -------- --------------------------------------------------- -- Seth Henry 05/18/23 Initial Upload library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; use ieee.std_logic_misc.all; entity mavg_8ch_16b_64d is generic( Reset_Level : std_logic := '1' ); port( Clock : in std_logic; Reset : in std_logic; -- RAW_Channel : in std_logic_vector(2 downto 0); RAW_Data : in std_logic_vector(15 downto 0); RAW_Valid : in std_logic; -- Busy_Out : out std_logic; -- AVG_Channel : out std_logic_vector(2 downto 0); AVG_Out : out std_logic_vector(15 downto 0); AVG_Valid : out std_logic; -- Busy_In : in std_logic ); end entity; architecture behave of mavg_8ch_16b_64d is type AVG_CTL_STATES is (INIT, CLR_BUFF, IDLE, BUSY_WAIT, RD_LAST, ADV_PTR, CALC_NEXT, WR_NEW); signal AVG_Ctl : AVG_CTL_STATES := INIT; signal CH_Select : std_logic_vector(2 downto 0); signal Data_New : std_logic_vector(15 downto 0) := (others => '0'); signal RAM_Wr_Addr : std_logic_vector(8 downto 0) := (others => '0'); alias RAM_Wr_Chan is RAM_Wr_Addr(8 downto 6); alias RAM_Wr_Ptr is RAM_Wr_Addr(5 downto 0); signal RAM_Wr_Data : std_logic_vector(15 downto 0) := (others => '0'); signal RAM_Wr_En : std_logic := '0'; signal RAM_Rd_Addr : std_logic_vector(8 downto 0) := (others => '0'); alias RAM_Rd_Chan is RAM_Rd_Addr(8 downto 6); alias RAM_Rd_Ptr is RAM_Rd_Addr(5 downto 0); signal RAM_Rd_Data : std_logic_vector(15 downto 0) := (others => '0'); alias Data_Old is RAM_Rd_Data; type PTR_ARRAY is array (0 to 7) of std_logic_vector(5 downto 0); signal SP0_Pointers : PTR_ARRAY; signal SPN_Pointers : PTR_ARRAY; -- Accumulator width is bus_size (16) + log depth (6) type ACCUM_ARRAY is array (0 to 7) of unsigned(21 downto 0); signal Accumulators : ACCUM_ARRAY; begin MAVG_Control_proc: process( Clock, Reset ) variable i : integer := 0; begin if( Reset = Reset_Level )then AVG_Ctl <= INIT; CH_Select <= (others => '0'); Data_New <= (others => '0'); Busy_Out <= '0'; for i in 0 to 7 loop SP0_Pointers(i) <= (others => '1'); SPN_Pointers(i) <= (others => '0'); Accumulators(i) <= (others => '0'); end loop; RAM_Wr_Addr <= (others => '0'); RAM_Wr_Data <= (others => '0'); RAM_Wr_En <= '0'; RAM_Rd_Addr <= (others => '0'); AVG_Channel <= (others => '0'); AVG_Out <= (others => '0'); AVG_Valid <= '0'; elsif( rising_edge(Clock) )then RAM_Wr_En <= '0'; Busy_Out <= '1'; AVG_Valid <= '0'; i := conv_integer(unsigned(CH_Select)); case( AVG_Ctl )is when INIT => RAM_Wr_Addr <= (others => '0'); RAM_Wr_Data <= (others => '0'); AVG_Ctl <= CLR_BUFF; when CLR_BUFF => RAM_Wr_Addr <= RAM_Wr_Addr + 1; RAM_Wr_En <= '1'; if( and_reduce(RAM_Wr_Addr) = '1' )then AVG_Ctl <= IDLE; end if; when IDLE => Busy_Out <= '0'; if( RAW_Valid = '1' )then Data_New <= RAW_Data; CH_Select <= RAW_Channel; AVG_Ctl <= BUSY_WAIT; end if; when BUSY_WAIT => if( Busy_In = '0' )then AVG_Ctl <= RD_LAST; end if; when RD_LAST => RAM_Rd_Chan <= CH_Select; RAM_Rd_Ptr <= SPN_Pointers(i); AVG_Ctl <= ADV_PTR; when ADV_PTR => SP0_Pointers(i) <= SP0_Pointers(i) + 1; AVG_Ctl <= CALC_NEXT; when CALC_NEXT => Accumulators(i) <= Accumulators(i) + unsigned( Data_New ) - unsigned( Data_Old ); AVG_Ctl <= WR_NEW; when WR_NEW => RAM_Wr_Chan <= CH_Select; RAM_Wr_Ptr <= SP0_Pointers(i); RAM_Wr_Data <= Data_New; RAM_Wr_En <= '1'; SPN_Pointers(i) <= SP0_Pointers(i) + 1; AVG_Channel <= CH_Select; AVG_Out <= std_logic_vector(Accumulators(i)(21 downto 6)); AVG_Valid <= '1'; AVG_Ctl <= IDLE; when others => null; end case; end if; end process; U_BUFF : entity work.mavg_buffer_16b port map( clock => Clock, data => RAM_Wr_Data, rdaddress => RAM_Rd_Addr, wraddress => RAM_Wr_Addr, wren => RAM_Wr_En, q => RAM_Rd_Data ); end architecture;
Go to most recent revision | Compare with Previous | Blame | View Log