Untitled
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