Untitled
unknown
plain_text
8 months ago
9.8 kB
9
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;
-- Registered outputs
signal dataReady_reg : std_logic := '0';
signal seqDone_reg : std_logic := '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)
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;
----------------------------------------------------------------------------
-- 3) Combinational FSM: next-state logic & default outputs
----------------------------------------------------------------------------
process(curState, start, counter, nWords, edgeDetect)
begin
-- default each cycle
dataReady_reg <= '0';
seqDone_reg <= '0';
nextState <= curState;
case curState is
--------------------------------------------------------------------
when IDLE =>
if start = '1' then
nextState <= SETUP;
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;
end if;
--------------------------------------------------------------------
when LATCH_DATA =>
-- do your data latch
if (counter + 1) < nWords then
nextState <= REQUEST_BYTE; -- if more words avail go back
else
nextState <= DATA_READY_PULSE; -- if not go to find peak
end if;
when DATA_READY_PULSE =>
dataReady_reg <= '1';
nextState <= REQUEST_BYTE; -- go request next byte
--------------------------------------------------------------------
--------------------------------------------------------------------
when DONE =>
seqDone_reg <= '1';
if start='0' then
nextState <= IDLE;
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
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 REQUEST_BYTE =>
-- toggle ctrlOut each time we request
ctrlOut_reg <= not ctrlOut_reg;
when WAIT_CTRL =>
-- no direct data updates
null;
when LATCH_DATA =>
-- read the data
new_sample := signed(data);
-- shift the rolling buffer
prev_samples(2) <= prev_samples(1);
prev_samples(1) <= prev_samples(0);
prev_samples(0) <= new_sample;
-- Peak detection
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(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;
elsif post_count > 0 then
-- store next few samples
dataResults(post_count-1) <= data;
post_count <= post_count - 1;
end if;
counter <= counter + 1;
byte <= std_logic_vector(peak_value);
when DONE =>
-- convert peak_index to BCD
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;
----------------------------------------------------------------------------
-- 5) Output assignments
----------------------------------------------------------------------------
ctrlOut <= ctrlOut_reg;
dataReady <= dataReady_reg;
seqDone <= seqDone_reg;
end architecture Behavioral;
Editor is loading...
Leave a Comment