Untitled

 avatar
unknown
plain_text
22 days ago
17 kB
5
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);  -- BCD-coded #words
        ctrlIn      : in  std_logic;   -- handshake from prior stage
        ctrlOut     : out std_logic;   -- handshake toggled to request next byte
        data        : in  std_logic_vector(7 downto 0);
        dataReady   : out std_logic;   -- single-cycle "data is done" pulse
        byte        : out std_logic_vector(7 downto 0);
        seqDone     : out std_logic;   -- single-cycle "all done" pulse
        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

    ------------------------------------------------------------------------
    -- 1) State definitions
    ------------------------------------------------------------------------
    type fsm_state is (
        IDLE,
        SETUP,
        REQUEST_BYTE,
        WAIT_CTRL,
        LATCH_DATA,
        PEAK_1,
        PEAK_2,
        PEAK_3,
        DATA_READY_PULSE,
        DONE
    );
    signal curState, nextState : fsm_state := IDLE;

    ------------------------------------------------------------------------
    -- 2) Internal registers and handshake detection
    ------------------------------------------------------------------------
    signal nWords       : integer range 0 to 999 := 0;
    signal counter      : integer range 0 to 999 := 0;
    signal numWords_bcd_reg : BCD_ARRAY_TYPE(2 downto 0);
    signal counter_inc  : std_logic;
    signal ctrlIn_reg : std_logic;
    signal data_reg   : std_logic_vector(7 downto 0);
    signal postCount_dec : std_logic;
    signal dataReady_reg : std_logic;
    signal ctrlOut_reg  : std_logic := '0';
    signal ctrlIn_prev  : std_logic := '0';  -- For single rising-edge detection
    signal edgeDetect   : std_logic := '0';
    signal new_sample   : signed(7 downto 0);
    signal postCount_reset : std_logic;
    signal MyBCD : BCD_ARRAY_TYPE(2 downto 0) := (others => (others => '0'));

    ------------------------------------------------------------------------
    -- 3) Peak-detection signals
    ------------------------------------------------------------------------
    signal peak_value   : signed(7 downto 0) := (others => '0');
    signal peak_index   : integer range 0 to 999 := 0;

    -- Rolling buffer (3 previous samples)
    type rolling_array is array(0 to 2) of signed(7 downto 0);
    signal prev_samples : rolling_array := (others => (others => '0'));

    -- Once we detect a new peak, we want the next 3 samples stored in dataResults_internal(2..0).
    signal postCount   : integer range 0 to 3 := 0;

    -- Internal data result storage
    signal dataResults_internal : CHAR_ARRAY_TYPE(0 to RESULT_BYTE_NUM - 1) := (OTHERS => (OTHERS => '0'));

    -- (Note: dataReady_reg and seqDone_reg are removed.)

    ------------------------------------------------------------------------
    -- 4) Conversion functions: BCD-to-int and int-to-BCD
    ------------------------------------------------------------------------
    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 := (others => (others => '0'));
        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 100, 4));
        return bcd;
    end function;

begin

    ----------------------------------------------------------------------------
    -- A) State register: synchronous update of current state
    ----------------------------------------------------------------------------
    process(clk, reset)
    begin
        if rising_edge(clk) then
            if reset = '1' then
                curState <= IDLE;
            else
                curState <= nextState;
            end if;
        end if;
    end process;

    ----------------------------------------------------------------------------
    -- B) Synchronous rising-edge detection on ctrlIn
    ----------------------------------------------------------------------------
    process(clk)
    begin
        if rising_edge(clk) then
            ctrlIn_prev <= ctrlIn;
            if ctrlIn = '1' and ctrlIn_prev = '0' then
                edgeDetect <= '1';
            else
                edgeDetect <= '0';
            end if;
        end if;
    end process;

    process(clk)
    begin
        if rising_edge(clk) then
            if reset = '1' then
                numWords_bcd_reg <= (OTHERS => (OTHERS => '0'));
            elsif start = '1' then
                numWords_bcd_reg <= numWords_bcd;
            end if;
        end if;
    end process;

    process(clk)
    begin
        if rising_edge(clk) then
            if reset = '1' then
                counter <= 0;
            elsif counter_inc = '1' then
                counter <= counter + 1;
            end if;
        end if;
    end process;

    process(clk)
    begin
        if rising_edge(clk) then
            if curState = LATCH_DATA then
                ctrlIn_reg <= '0';
            elsif ctrlIn = '1' then
                data_reg <= data;
                new_sample <= signed(data);
                ctrlIn_reg  <= ctrlIn;
            end if;
        end if;
    end process;

    process(clk)
    begin
        if rising_edge(clk) then
            if reset = '1' then
                postCount <= 3;
            elsif postCount_reset = '1' then
                postCount <= 3;
            elsif postCount_dec = '1' then
                postCount <= postCount - 1;
            end if;
        end if;
    end process;
    
    process(clk)
    begin
        if rising_edge(clk) then
            if start = '1' and counter > 0 then
                dataReady <= '1';
                if counter = nWords then
                seqDone <= '1';
                end if;
            else
                dataReady <= '0';
                seqDone <= '0';
            end if;
        end if;
    end process;
    ----------------------------------------------------------------------------
    -- C) Combinational next-state logic (handshake pulses removed)
    ----------------------------------------------------------------------------
    process(ctrlIn_reg, curState, counter, start, numWords_bcd, data)
    begin

        ctrlOut <= '0';
        postCount_reset <= '0';
        postCount_dec <= '0';
        counter_inc <= '0';

        case curState is

            when IDLE =>
                if start = '1' then
                    nextState <= SETUP;
                else
                    nextState <= IDLE;
                end if;

            when SETUP =>
                nWords <= bcd_to_int(numWords_bcd_reg);
                nextState <= REQUEST_BYTE;

            when REQUEST_BYTE =>
                ctrlOut <= '1';
                nextState <= WAIT_CTRL;

            when WAIT_CTRL =>
                if ctrlIn_reg = '1' then
                    
                    nextState <= LATCH_DATA;
                else
                    nextState <= WAIT_CTRL;
                end if;

            when LATCH_DATA =>

                -- Peak detection & storing
                if (counter = 0) or (new_sample > peak_value) then
                    peak_value <= new_sample;
                    peak_index <= counter;
                    -- Store the 3 samples before the new peak
                    dataResults_internal(0) <= std_logic_vector(prev_samples(0));
                    dataResults_internal(1) <= std_logic_vector(prev_samples(1));
                    dataResults_internal(2) <= std_logic_vector(prev_samples(2));
                    
                    dataResults_internal(3) <= data_reg;  -- the new peak
                    -- Clear out the next 3 positions
                    dataResults_internal(4) <= (others => '0');
                    dataResults_internal(5) <= (others => '0');
                    dataResults_internal(6) <= (others => '0');
                    prev_samples(0) <= prev_samples(1);
                    prev_samples(1) <= prev_samples(2);
                    prev_samples(2) <= new_sample;
                    postCount_reset <= '1';
                    counter_inc <= '1';
                    nextState <= DONE;
                elsif postCount > 0 then
                    dataResults_internal(7 - postCount) <= data_reg;
                    postCount_dec <= '1';
                    counter_inc <= '1';
                    nextState <= DONE;
                end if;

            when DONE =>
                MyBCD(0) <= std_logic_vector(to_unsigned(peak_index mod 10, 4));
                MyBCD(1) <= std_logic_vector(to_unsigned((peak_index / 10) mod 10, 4));
                MyBCD(2) <= std_logic_vector(to_unsigned((peak_index / 100) mod 10, 4));
                
                if start = '0' then
                    nextState <= IDLE;
                else
                    nextState <= DONE;
                end if;

            when others =>
                nextState <= IDLE;
        end case;
    end process;

    -- ----------------------------------------------------------------------------
    -- -- D) Synchronous data-path: counters, ctrlOut toggling, and peak detection
    -- ----------------------------------------------------------------------------
    -- process(clk)
    --     variable new_sample : signed(7 downto 0);
    --     variable reg_peak   : integer := -128;
    -- begin
    --     if rising_edge(clk) then
    --         if reset = '1' then
    --             nWords      <= 0;
    --             counter     <= 0;
    --             ctrlOut_reg <= '0';
    --             peak_value  <= (others => '0');
    --             peak_index  <= 0;
    --             prev_samples <= (others => (others => '0'));
    --             post_count   <= 0;
    --             dataResults_internal <= (others => (others => '0'));
    --             maxIndex    <= (others => (others => '0'));
    --         else
    --             case curState is
    --                 when IDLE =>
    --                     null;
    --                 when SETUP =>
    --                     nWords <= bcd_to_int(numWords_bcd);
    --                     counter <= 0;
    --                     peak_value <= (others => '0');
    --                     peak_index <= 0;
    --                     prev_samples <= (others => (others => '0'));
    --                     post_count   <= 0;
    --                     dataResults_internal <= (others => (others => '0'));
    --                 when REQUEST_BYTE =>
    --                     -- Toggle ctrlOut to request next byte
    --                     ctrlOut_reg <= not ctrlOut_reg;
    --                 when WAIT_CTRL =>
    --                     null;  -- waiting for rising-edge detection
    --                 when LATCH_DATA =>
    --                     new_sample := signed(data);
    --                     -- Shift the rolling buffer
                       
    --                     -- Peak detection & storing
    --                     if (counter = 0) or (new_sample > peak_value) then
    --                         peak_value <= new_sample;
    --                         peak_index <= counter;
    --                         -- Store the 3 samples before the new peak
    --                         dataResults_internal(6) <= std_logic_vector(prev_samples(2));
    --                         dataResults_internal(5) <= std_logic_vector(prev_samples(1));
    --                         dataResults_internal(4) <= std_logic_vector(prev_samples(0));
    --                         dataResults_internal(3) <= data;  -- the new peak
    --                         -- Clear out the next 3 positions
    --                         dataResults_internal(2) <= (others => '0');
    --                         dataResults_internal(1) <= (others => '0');
    --                         dataResults_internal(0) <= (others => '0');
    --                         post_count <= 3;
    --                         prev_samples(2) <= prev_samples(1);
    --                         prev_samples(1) <= prev_samples(0);
    --                         prev_samples(0) <= new_sample;
    --                     elsif post_count > 0 then
    --                         dataResults_internal(post_count - 1) <= data;
    --                         post_count <= post_count - 1;
    --                         if counter >= nWords-1 then
    --                             reg_peak := to_integer(peak_value);
    --                         end if;
    --                     end if;
    --                     counter <= counter + 1;
    --                     if counter >= nWords-1 then
    --                         reg_peak := to_integer(peak_value);
    --                     end if;
    --                 when PEAK_1 =>
    --                     if signed(dataResults_internal(2)) > reg_peak then
    --                         dataResults_internal(1 to 6) <= dataResults_internal(0 to 5);
    --                         maxIndex <= decimal_to_bcd(counter - 3);
    --                     end if;
    --                 when PEAK_2 =>
    --                     if signed(dataResults_internal(1)) > reg_peak then
    --                         dataResults_internal(2 to 6) <= dataResults_internal(0 to 4);
    --                         maxIndex <= decimal_to_bcd(counter - 2);
    --                     end if;
    --                 when PEAK_3 =>
    --                     if signed(dataResults_internal(0)) > reg_peak then
    --                         dataResults_internal(3 to 6) <= dataResults_internal(0 to 3);
    --                         maxIndex <= decimal_to_bcd(counter - 1);
    --                     end if;
    --                 when DATA_READY_PULSE =>
    --                     -- No data-path updates here; the output pulse is generated in the synchronous output process.
    --                     null;
    --                 when DONE =>
    --                     -- Convert peak_index to BCD for maxIndex output
    --                     maxIndex(0) <= std_logic_vector(to_unsigned(peak_index mod 10, 4));
    --                     maxIndex(1) <= std_logic_vector(to_unsigned((peak_index / 10) mod 10, 4));
    --                     maxIndex(2) <= std_logic_vector(to_unsigned((peak_index / 100) mod 10, 4));
    --                 when others =>
    --                     null;
    --             end case;
    --         end if;
    --     end if;
    -- end process;

    -- ----------------------------------------------------------------------------
    -- -- E) Synchronous output assignment for handshake signals (no extra registers)
    -- ----------------------------------------------------------------------------
    -- process(clk)
    -- begin
    --     if rising_edge(clk) then
    --         case curState is
    --             when DATA_READY_PULSE =>
    --                 dataReady <= '1';
    --                 seqDone   <= '0';
    --             when DONE =>
    --                 dataReady <= '0';
    --                 seqDone   <= '1';
    --             when others =>
    --                 dataReady <= '0';
    --                 seqDone   <= '0';
    --         end case;
    --     end if;
    -- end process;

    ----------------------------------------------------------------------------
    -- F) Drive remaining outputs
    ----------------------------------------------------------------------------
    ctrlOut   <= ctrlOut_reg;
    dataResults <= dataResults_internal;
    byte <= data_reg;
    maxIndex <= MyBCD;

end Behavioral;
Editor is loading...
Leave a Comment