Untitled
unknown
plain_text
7 months ago
9.0 kB
6
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,
DONE
);
signal curState, nextState : fsm_state := IDLE;
-- Internal signals
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;
-- 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;
begin
----------------------------------------------------------------------------
-- 1) Synchronous FSM: state register
----------------------------------------------------------------------------
process(clk, reset)
begin
if rising_edge(clk) then
if reset = '1' then
curState <= IDLE;
else
curState <= nextState;
end if;
end if;
end process;
----------------------------------------------------------------------------
-- 2) Synchronous 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, ctrlOut_reg)
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;
----------------------------------------------------------------------------
-- 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 latch
if counter < nWords then
nextState <= REQUEST_BYTE; -- if more words avail go back
else
nextState <= DONE;
end if;
when others =>
nextState <= IDLE;
end case;
end process;
----------------------------------------------------------------------------
-- 4) Synchronous data-path updates
----------------------------------------------------------------------------
process(clk)
variable new_sample : signed(7 downto 0);
begin
if rising_edge(clk) then
dataReady <= '0';
seqDone <= '0';
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 <= (others => (others => '0'));
maxIndex <= (others => (others => '0'));
else
case curState is
when IDLE =>
-- do nothing
when SETUP =>
-- convert BCD->int
nWords <= bcd_to_int(numWords_bcd);
counter <= 0;
peak_value <= (others => '0');
peak_index <= 0;
prev_samples <= (others => (others => '0'));
post_count <= 0;
dataResults <= (others => (others => '0'));
when LATCH_DATA =>
-- read the data
new_sample := signed(data);
if post_count > 0 then
-- store next few samples
dataResults(post_count-1) <= data;
post_count <= post_count - 1;
end if;
-- Peak detection
if (counter=0) or (new_sample>peak_value) then
peak_value <= new_sample;
peak_index <= counter;
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));
-- store the 3 samples before the new peak
dataResults(6) <= std_logic_vector(prev_samples(2));
dataResults(5) <= std_logic_vector(prev_samples(1));
dataResults(4) <= std_logic_vector(prev_samples(0));
dataResults(3) <= data; -- new peak
dataResults(2) <= (others => '0');
dataResults(1) <= (others => '0');
dataResults(0) <= (others => '0');
post_count <= 3;
counter <= counter + 1;
byte <= std_logic_vector(peak_value);
end if;
prev_samples(2) <= prev_samples(1);
prev_samples(1) <= prev_samples(0);
prev_samples(0) <= new_sample;
when DONE =>
dataReady <= '1';
if (counter >= nWords) then
seqDone <= '1';
end if;
when others =>
null;
end case;
end if;
end if;
end process;
end architecture Behavioral;Editor is loading...
Leave a Comment