Untitled
unknown
plain_text
9 months ago
17 kB
8
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