Untitled
unknown
plain_text
7 months ago
12 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 ctrlOut_reg : std_logic := '0';
signal ctrlIn_prev : std_logic := '0'; -- For single rising-edge detection
signal edgeDetect : std_logic := '0';
------------------------------------------------------------------------
-- 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 post_count : integer range 0 to 3 := 0;
-- Single-cycle pulses
signal dataReady_reg : std_logic := '0';
signal seqDone_reg : std_logic := '0';
signal dataResults_internal : CHAR_ARRAY_TYPE(0 to RESULT_BYTE_NUM - 1);
------------------------------------------------------------------------
-- 3) Convert 3-digit BCD to integer
------------------------------------------------------------------------
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
----------------------------------------------------------------------------
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 detection of a single rising edge 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;
----------------------------------------------------------------------------
-- C) Combinational next-state logic, plus single-cycle pulses
----------------------------------------------------------------------------
process(curState, start, counter, nWords, edgeDetect)
begin
------------------------------------------------------------------------
-- By default, dataReady_reg and seqDone_reg are '0' 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 =>
nextState <= REQUEST_BYTE;
when REQUEST_BYTE =>
-- We'll toggle ctrlOut in the sequential block
nextState <= WAIT_CTRL;
when WAIT_CTRL =>
-- Wait for single rising edge on ctrlIn
if edgeDetect = '1' then
nextState <= LATCH_DATA;
end if;
when LATCH_DATA =>
-- If not finished, request another. If done, do a dataReady pulse.
if counter >= nWords-1 then
nextState <= PEAK_1;
else
nextState <= REQUEST_BYTE;
end if;
when PEAK_1 =>
nextState <= PEAK_2;
when PEAK_2 =>
nextState <= PEAK_3;
when PEAK_3 =>
nextState <= DATA_READY_PULSE;
when DATA_READY_PULSE =>
-- single-cycle dataReady='1'
dataReady_reg <= '1';
nextState <= DONE;
when DONE =>
-- single-cycle seqDone='1'; once start=0 => IDLE
seqDone_reg <= '1';
if start = '0' then
nextState <= IDLE;
end if;
when others =>
nextState <= IDLE;
end case;
end process;
----------------------------------------------------------------------------
-- D) Synchronous data-path: counters, handshake toggling, storing peak window
----------------------------------------------------------------------------
process(clk)
variable new_sample : signed(7 downto 0);
variable reg_peak : integer := -128;
begin
if rising_edge(clk) then
if reset = '1' then
-- Reset everything
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 =>
null; -- do nothing
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 <= (others => (others => '0'));
when REQUEST_BYTE =>
-- Toggle ctrlOut to request next byte
ctrlOut_reg <= not ctrlOut_reg;
when WAIT_CTRL =>
null; -- just waiting for the rising edge
when LATCH_DATA =>
-- read the new 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 & 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;
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;
-- increment global sample counter
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 extra data updates. The comb process sets dataReady=1 for this cycle
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;
----------------------------------------------------------------------------
-- E) Drive final outputs from internal registers
----------------------------------------------------------------------------
ctrlOut <= ctrlOut_reg;
dataReady <= dataReady_reg; -- pulses high for one clock in DATA_READY_PULSE
seqDone <= seqDone_reg; -- pulses high for one clock in DONE
dataResults <= dataResults_internal;
byte <= data;
end architecture Behavioral;Editor is loading...
Leave a Comment