Untitled
unknown
plain_text
22 days ago
9.6 kB
4
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); data: in std_logic_vector(7 downto 0); ctrlIn: in std_logic; ctrlOut: out std_logic; dataReady: out std_logic; seqDone: out std_logic; byte: out std_logic_vector(7 downto 0); maxIndex: out BCD_ARRAY_TYPE(2 downto 0); dataResults: out CHAR_ARRAY_TYPE(0 to 6) ); end dataConsume; --------------------------------------------------------- SIGNAL DECLARATION --------------------------------------------------------- architecture Behavioral of dataConsume is -- define custom types for use within architecture type state_type is (IDLE, PROCESS_DATA, WAIT_CMDP, CHECK_COMPLETE); type signed_array is array (integer range <>) of signed(7 downto 0); -- signals for managing state transitions signal curr_state, next_state: state_type; -- signals for two phase protocol logic signal prev_ctrlIn, ctrlOut_state: std_logic := '0'; signal edge_detected_ctrlIn: std_logic := '0'; -- signals for counter and numWords as integer signal numWords_int: integer := 0; signal counter: integer := 0; -- signals for the peak detection algorithm signal peak_value: signed(7 downto 0) := (others => '0'); signal lastThreeBytes: signed_array(0 to 2) := (others => (others => '0')); signal update_next_values: integer := 0; -- enable signals and counter reset signal en_updateCounter: boolean := FALSE; signal en_bcdToInt: boolean := FALSE; signal en_peakDetection: boolean := FALSE; signal en_byteOutput: boolean := FALSE; signal en_reset: boolean := TRUE; begin --------------------------------------------------------- STATE MACHINE --------------------------------------------------------- -------------------------------- -- State Machine Transitions -------------------------------- StateMachine: process(clk, reset) begin if rising_edge(clk) then if reset = '1' then curr_state <= IDLE; else curr_state <= next_state; end if; end if; end process; -------------------------------------- -- Next State Logic -------------------------------------- combi_next: process(curr_state, start, edge_detected_ctrlIn, counter, numWords_int) begin case curr_state is when IDLE => -- Remain idle until start signal goes high, synchronising us with command processor if start = '1' then next_state <= PROCESS_DATA; else next_state <= IDLE; end if; when PROCESS_DATA => -- Processing incoming bytes, finding peak and storing values in DataResults if edge_detected_ctrlIn = '1' then next_state <= WAIT_CMDP; else next_state <= PROCESS_DATA; end if; when WAIT_CMDP => -- Waiting for start from command processor or first run through if start = '1' or counter = 1 then next_state <= CHECK_COMPLETE; else next_state <= WAIT_CMDP; end if; when CHECK_COMPLETE => -- If we haven't reached the number of words we need to process, keep processing if counter < numWords_int then next_state <= PROCESS_DATA; else next_state <= IDLE; end if; when others => next_state <= IDLE; end case; end process; -------------------------------------- -- Combinatorial logic for state machine outputs -------------------------------------- combi_out: process(curr_state, start, edge_detected_ctrlIn, counter, numWords_int) begin -- Reset signals to avoid latches en_reset <= FALSE; en_bcdToInt <= FALSE; en_updateCounter <= FALSE; en_peakDetection <= FALSE; en_byteOutput <= FALSE; dataReady <= '0'; seqDone <= '0'; case curr_state is when IDLE => en_reset <= TRUE; -- reset signals, fixing bug for board reset button if start = '1' then en_bcdToInt <= TRUE; -- BCDtoINT process end if; when PROCESS_DATA => if edge_detected_ctrlIn = '1' then en_updateCounter <= TRUE; -- UpdateCounter Process en_peakDetection <= TRUE; -- PeakDetection process end if; when WAIT_CMDP => en_byteOutput <= TRUE; -- ByteOutput process when CHECK_COMPLETE => dataReady <= '1'; if counter >= numWords_int then seqDone <= '1'; end if; when others => null; end case; end process; --------------------------------------------------------- TWO PHASE PROTOCOL --------------------------------------------------------- --------------------------- -- detect ctrlIn edge toggle by using XOR gate to spot a binary difference between current and previous ctrlIn --------------------------- CtrlInEdgeDetect: process(clk, ctrlIn, prev_ctrlIn) begin if rising_edge(clk) then prev_ctrlIn <= ctrlIn; end if; edge_detected_ctrlIn <= ctrlIn XOR prev_ctrlIn; end process; --------------------------- -- ctrlOut is toggled when the program starts and when we have processed a byte and the next byte is expected --------------------------- CtrlOutToggle: process(clk, reset, ctrlOut_state) begin if rising_edge(clk) then if reset = '1' then ctrlOut_state <= '0'; elsif (curr_state = IDLE and start = '1') or (curr_state = CHECK_COMPLETE and counter < numWords_int) then ctrlOut_state <= not ctrlOut_state; end if; end if; ctrlOut <= ctrlOut_state; end process; --------------------------------------------------------- BASIC PROCESSES --------------------------------------------------------- -------------------------------------- -- Update counter to keep track of current index of byte being processed -------------------------------------- UpdateCounter: process(clk) begin if rising_edge(clk) then if en_reset then counter <= 0; elsif en_updateCounter then counter <= counter + 1; end if; end if; end process; ---------------------------- -- converts numWords_bcd input signal from BCD to integer for comparison against counter ---------------------------- BCDtoINT: process(clk) begin if rising_edge(clk) then if reset = '1' then numWords_int <= 0; elsif en_bcdToInt then numWords_int <= to_integer(unsigned(numWords_bcd(2))) * 100 + to_integer(unsigned(numWords_bcd(1))) * 10 + to_integer(unsigned(numWords_bcd(0))); end if; end if; end process; ---------------------------- -- keep sending the bytes we read to the command processor ---------------------------- ByteOutput: process(clk) begin if rising_edge(clk) then if reset = '1' then byte <= "00000000"; elsif en_byteOutput THEN byte <= data; end if; end if; end process; --------------------------------------------------------- PEAK DETECTION ALGORITHM --------------------------------------------------------- PeakDetection: process(clk) begin if rising_edge(clk) then if reset = '1' or en_reset then peak_value <= (others => '0'); update_next_values <= 0; lastThreeBytes <= (others => (others => '0')); maxIndex <= (others => (others => '0')); dataResults <= (others => (others => '0')); elsif en_peakDetection then -- 1. Update dataResults with next three values if the peak was recently found. -- update_next_values tracks how many values we still need to store after the peak if update_next_values > 0 then dataResults(update_next_values - 1) <= std_logic_vector(signed(data)); -- Update next dataResults value update_next_values <= update_next_values - 1; end if; -- 2. Peak detection. -- If it's the first byte or the current byte is greater than past peak value if counter = 0 or signed(data) > peak_value then peak_value <= signed(data); -- update peak value for future comparison maxIndex(0) <= std_logic_vector(to_unsigned(counter mod 10, 4)); -- Update max index using counter maxIndex(1) <= std_logic_vector(to_unsigned((counter / 10) mod 10, 4)); maxIndex(2) <= std_logic_vector(to_unsigned((counter / 100) mod 10, 4)); dataResults(6) <= std_logic_vector(lastThreeBytes(2));-- Update the three values before the peak dataResults(5) <= std_logic_vector(lastThreeBytes(1)); dataResults(4) <= std_logic_vector(lastThreeBytes(0)); dataResults(3) <= std_logic_vector(signed(data)); -- Update the peak value dataResults(2) <= (others => '0'); -- Reset the three values after the peak dataResults(1) <= (others => '0'); dataResults(0) <= (others => '0'); update_next_values <= 3; -- indicating that we need to store the next three values end if; -- 3. Always keep track of the last three bytes, so we can update dataResults(6 downto 4) when peak found lastThreeBytes(2) <= lastThreeBytes(1); lastThreeBytes(1) <= lastThreeBytes(0); lastThreeBytes(0) <= signed(data); end if; end if; end process; end Behavioral;
Editor is loading...
Leave a Comment