Untitled

 avatar
unknown
plain_text
25 days ago
11 kB
2
Indexable
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
use work.common_pack.all;
 
entity dataConsume is
    port (
        clk         : in  std_logic;
        reset       : in  std_logic;
        start       : in  std_logic;
        numWords_bcd: in  BCD_ARRAY_TYPE(2 downto 0);
        ctrlIn      : in  std_logic;
        ctrlOut     : out std_logic;
        data        : in  std_logic_vector(7 downto 0);
        dataReady   : out std_logic;
        byte        : out std_logic_vector(7 downto 0);
        seqDone     : out std_logic;
        maxIndex    : out BCD_ARRAY_TYPE(2 downto 0);
        dataResults : out CHAR_ARRAY_TYPE(0 to RESULT_BYTE_NUM-1)
    );
end dataConsume;
 
architecture Behavioral of dataConsume is
 
    -- Additional or revised states, preserving your original ones.
    type fsm_state is (
        IDLE,
        SETUP,
        REQUEST_BYTE,
        WAIT_CTRL,
        LATCH_DATA,
        DATA_READY_PULSE,
        OUTPUT_BYTE,
        DONE
    );
 
    signal curState, nextState : fsm_state := IDLE;
 
    -- bcd to int conversion
    signal nWords      : integer range 0 to 999 := 0;
    signal counter     : integer range 0 to 999 := 0;
 
    -- ctrlOut handshake
    signal ctrlOut_reg : std_logic := '0';
    -- ctrlIn rising/falling detection
    signal ctrlIn_prev : std_logic := '0';
    signal edgeDetect  : std_logic := '0';
 
    -- Peak detection
    signal peak_value  : signed(7 downto 0) := (others => '0');
    signal peak_index  : integer range 0 to 999 := 0;
 
    -- Rolling buffer for last 3 samples
    type rolling_array is array (0 to 2) of signed(7 downto 0);
    signal prev_samples : rolling_array := (others => (others => '0'));
    signal post_count   : integer range 0 to 3 := 0;
 
    -- registers
    signal dataReady_reg : std_logic := '0';
    signal seqDone_reg   : std_logic := '0';
    signal byte_reg      : std_logic_vector(7 downto 0) := (others => '0');
    signal maxIndex_reg  : BCD_ARRAY_TYPE(2 downto 0) := (others => (others => '0'));
    signal results_reg   : CHAR_ARRAY_TYPE(0 to RESULT_BYTE_NUM - 1)
                          := (others => (others => '0'));
 
    signal updateCounter : boolean := false;
    signal byte_out : boolean := false;
    signal detectPeak : boolean := false;
 
    -- BCD convert function
    function bcd_to_int(bcd3: BCD_ARRAY_TYPE(2 downto 0)) return integer is
        variable tmp : integer := 0;
    begin
        tmp := to_integer(unsigned(bcd3(2))) * 100 +
               to_integer(unsigned(bcd3(1))) * 10 +
               to_integer(unsigned(bcd3(0)));
        return tmp;
    end function;

    function decimal_to_bcd(input_decimal : integer) return BCD_ARRAY_TYPE is
        variable bcd : BCD_ARRAY_TYPE(2 downto 0);
    begin
        bcd(2) := std_logic_vector(to_unsigned(input_decimal / 100, 4));
        bcd(1) := std_logic_vector(to_unsigned((input_decimal mod 100) / 10, 4));
        bcd(0) := std_logic_vector(to_unsigned(input_decimal mod 10, 4));
        return bcd;
    end function;
 
begin
    ----------------------------------------------------------------------------
    -- 1) fsm transitions
    ----------------------------------------------------------------------------
    process(clk, reset)
    begin
        if rising_edge(clk) then
            if reset = '1' then
                curState <= IDLE;
            else
                curState <= nextState;
            end if;
        end if;
    end process;
 
      ----------------------------------------------------------------------------
    -- 3) Combinational FSM: next-state logic
    ----------------------------------------------------------------------------
    process(curState, start, counter, nWords, edgeDetect)
    begin
        case curState is
            --------------------------------------------------------------------
            when IDLE =>
                if start = '1' then
                    nextState <= SETUP;
                else
                    nextState <= IDLE;
                end if;
 
            --------------------------------------------------------------------
            when SETUP =>
                -- Once BCD->int is done in sequential path, we request first byte
                nextState <= REQUEST_BYTE;
 
            --------------------------------------------------------------------
            when REQUEST_BYTE =>
                -- We'll do the toggling of ctrlOut in the sequential process
                nextState <= WAIT_CTRL;  -- wait for ctrlIn to go high
 
            --------------------------------------------------------------------
            when WAIT_CTRL =>
                -- We want a rising edge: edgeDetect='1' AND ctrlIn='1'
                if edgeDetect = '1' then
                    nextState <= LATCH_DATA;
                else
                    nextState <= WAIT_CTRL;
                end if;
 
            --------------------------------------------------------------------
            when LATCH_DATA =>
            -- do your data lat
                if counter < nWords then
                    nextState <= DATA_READY_PULSE; -- if more words avail go back  
                else
                    nextState <= DONE;    
                end if;

            when DATA_READY_PULSE =>
                nextState <= REQUEST_BYTE;
       
            when DONE =>
               nextState <= IDLE;
 
            when others =>
                nextState <= IDLE;
 
        end case;
    end process;
 
    ----------------------------------------------------------------------------
    -- 4) Synchronous data-path updates
    ----------------------------------------------------------------------------
    process(clk)
    begin
        if rising_edge(clk) then
            if reset = '1' then
                nWords        <= 0;
                updateCounter <= false;
                peak_value    <= (others => '0');
                peak_index    <= 0;
                prev_samples  <= (others => (others => '0'));
                post_count    <= 0;
                seqDone  <= '0';
                dataReady <= '0';
                maxIndex_reg  <= (others => (others => '0'));
                results_reg   <= (others => (others => '0'));  --?
            else
                peak_value <= (others => '0');
                peak_index <= 0;
                prev_samples <= (others => (others => '0'));
                post_count   <= 0;
                results_reg  <= (others => (others => '0'));
                maxIndex_reg <= (others => (others => '0'));
                seqDone <= '0';
                dataReady <= '0';
                case curState is
 
                    when IDLE =>
                        -- do nothing
 
                    when SETUP =>
                        -- convert BCD->int
                        nWords <= bcd_to_int(numWords_bcd);
                   
                    when REQUEST_BYTE =>
                    --nothing
 
                    when WAIT_CTRL =>
                    --nothing
 
                    when LATCH_DATA =>
                        -- read the data
                        detectPeak <= true;
                        updateCounter <= true;

                    when OUTPUT_BYTE =>
                        byte_out <= true;

                    when DATA_READY_PULSE =>
                        dataReady <= '1';
 
                    when DONE =>
                        if (counter >= nWords) then
                            seqDone <= '1';
                        end if;

                    when others =>
                        null;
                end case;
            end if;
        end if;
    end process;
 
 
----helper functions:
    process(clk)
    begin
        if rising_edge(clk) then
            if (reset = '1') then
                byte <= (others => '0');
            elsif byte_out then
                byte <= data;
            end if;
        end if;
    end process;
 
    process(clk)
    begin
        if rising_edge(clk) then
            if reset = '1' then
                counter <= 0;
            elsif updateCounter then
                counter <= counter + 1;
            end if;
        end if;
    end process;
               


    process(clk)
    begin
        if rising_edge(clk) then
            if reset = '1' then 
                peak_index   <= 0;
                peak_value   <= (others => '0');
                prev_samples <= (others => (others => '0'));
                post_count   <= 0;
                results_reg  <= (others => (others => '0'));

            elsif detectPeak then 
                if post_count > 0 then
                    results_reg(post_count-1) <= data;
                    post_count <= post_count - 1;
                end if;

                if (counter = 0) or (signed(data) > peak_value) then
                    peak_value <= signed(data);
                    peak_index <= counter;

                    results_reg(6) <= std_logic_vector(prev_samples(2));
                    results_reg(5) <= std_logic_vector(prev_samples(1));
                    results_reg(4) <= std_logic_vector(prev_samples(0));
                    results_reg(3) <= data;

                    results_reg(2) <= (others => '0');
                    results_reg(1) <= (others => '0');
                    results_reg(0) <= (others => '0');

                    post_count <= 3;
                end if;

                prev_samples(2) <= prev_samples(1);
                prev_samples(1) <= prev_samples(0);
                prev_samples(0) <= signed(data);
            end if;
        end if;
    end process;

    ----------------------------------------------------------------------------
        -- detection of ctrlIn edges
    ----------------------------------------------------------------------------
    process(clk, ctrlIn, ctrlIn_prev)
    begin
        if rising_edge(clk) then
            ctrlIn_prev <= ctrlIn;
        end if;
            edgeDetect <= ctrlIn xor ctrlIn_prev;
    end process;
 
    process(clk, reset)
    begin
        if rising_edge(clk) then
            if reset = '1' then
                ctrlOut_reg <= '0';
            elsif curState = REQUEST_BYTE then
                    ctrlOut_reg <= not ctrlOut_reg;
            end if;        
        end if;
        ctrlOut <= ctrlOut_reg;
    end process;
 
    dataResults <= results_reg;
    maxIndex <= decimal_to_bcd(peak_index);
 
end architecture Behavioral;
Editor is loading...
Leave a Comment