|
--------------------------------------------------------------------------
|
|
-- (c) 2020 mark watson
|
|
-- I am happy for anyone to use this for non-commercial use.
|
|
-- If my vhdl files are used commercially or otherwise sold,
|
|
-- please contact me for explicit permission at scrameta (gmail).
|
|
-- This applies for source and binary form and derived works.
|
|
---------------------------------------------------------------------------
|
|
LIBRARY ieee;
|
|
USE ieee.std_logic_1164.all;
|
|
use ieee.numeric_std.all;
|
|
use IEEE.STD_LOGIC_MISC.all;
|
|
|
|
ENTITY sample_channel IS
|
|
PORT
|
|
(
|
|
CLK : IN STD_LOGIC;
|
|
RESET_N : IN STD_LOGIC;
|
|
ENABLE : IN STD_LOGIC;
|
|
|
|
syncreset : in std_logic;
|
|
start_addr : IN std_logic_vector(15 downto 0);
|
|
len : IN std_logic_vector(15 downto 0);
|
|
period : IN std_logic_vector(11 downto 0);
|
|
|
|
twocycles : in std_logic;
|
|
|
|
addr : OUT STD_LOGIC_VECTOR(16 downto 0);
|
|
irq : OUT STD_LOGIC;
|
|
req : OUT STD_LOGIC
|
|
);
|
|
END sample_channel;
|
|
|
|
ARCHITECTURE vhdl OF sample_channel IS
|
|
signal pointer_reg : unsigned(16 downto 0);
|
|
signal pointer_next : unsigned(16 downto 0);
|
|
signal remaining_reg : unsigned(15 downto 0);
|
|
signal remaining_next : unsigned(15 downto 0);
|
|
signal periodpos_reg : unsigned(11 downto 0);
|
|
signal periodpos_next : unsigned(11 downto 0);
|
|
signal req_reg : std_logic;
|
|
signal req_next : std_logic;
|
|
signal irq_reg : std_logic;
|
|
signal irq_next : std_logic;
|
|
signal resetpending_reg : std_logic;
|
|
signal resetpending_next : std_logic;
|
|
|
|
BEGIN
|
|
-- register
|
|
process(clk,reset_n)
|
|
begin
|
|
if (reset_n='0') then
|
|
pointer_reg <= (others=>'0');
|
|
remaining_reg <= (others=>'0');
|
|
periodpos_reg <= (others=>'0');
|
|
req_reg <= '0';
|
|
irq_reg <= '0';
|
|
resetpending_reg <= '0';
|
|
elsif (clk'event and clk='1') then
|
|
pointer_reg <= pointer_next;
|
|
remaining_reg <= remaining_next;
|
|
periodpos_reg <= periodpos_next;
|
|
req_reg <= req_next;
|
|
irq_reg <= irq_next;
|
|
resetpending_reg <= resetpending_next;
|
|
end if;
|
|
end process;
|
|
|
|
process(start_addr, len, period,
|
|
pointer_reg, remaining_reg, periodpos_reg, resetpending_reg,
|
|
enable,
|
|
syncreset,
|
|
twocycles
|
|
)
|
|
variable change : unsigned(16 downto 0);
|
|
variable endperiod : std_logic;
|
|
variable endsample : std_logic;
|
|
variable nextsample : std_logic;
|
|
begin
|
|
pointer_next <= pointer_reg;
|
|
remaining_next <= remaining_reg;
|
|
periodpos_next <= periodpos_reg;
|
|
resetpending_next <= resetpending_reg or syncreset;
|
|
irq_next <= '0';
|
|
req_next <= '0';
|
|
|
|
nextsample := '0';
|
|
|
|
endperiod := not(or_reduce(std_logic_vector(periodpos_reg(periodpos_reg'left downto 1))));
|
|
endsample := not(or_reduce(std_logic_vector(remaining_reg(remaining_reg'left downto 1))));
|
|
|
|
if (enable='1') then
|
|
periodpos_next <= periodpos_reg-1;
|
|
resetpending_next <='0';
|
|
|
|
if (endperiod='1') then
|
|
if (twocycles='1') then
|
|
change:=to_unsigned(1,17);
|
|
else
|
|
change:=to_unsigned(2,17);
|
|
end if;
|
|
pointer_next <= pointer_reg+change;
|
|
remaining_next <= remaining_reg-1;
|
|
periodpos_next <= unsigned(period);
|
|
req_next <= '1';
|
|
|
|
nextsample := endsample;
|
|
end if;
|
|
|
|
if (resetpending_reg='1') then
|
|
nextsample := '1';
|
|
end if;
|
|
|
|
if (nextsample='1') then
|
|
irq_next <= '1';
|
|
pointer_next <= unsigned(start_addr)&'0';
|
|
remaining_next <= unsigned(len);
|
|
periodpos_next <= unsigned(period);
|
|
req_next <= '1';
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
addr <= std_logic_vector(pointer_next);
|
|
|
|
req <= req_reg;
|
|
irq <= irq_reg;
|
|
|
|
end vhdl;
|
|
|