Project

General

Profile

1157 markw
--------------------------------------------------------------------------
1154 markw
-- (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;

1155 markw
syncreset : in std_logic;
start_addr : IN std_logic_vector(15 downto 0);
1172 markw
len : IN std_logic_vector(15 downto 0);
1154 markw
period : IN std_logic_vector(11 downto 0);

1155 markw
twocycles : in std_logic;

addr : OUT STD_LOGIC_VECTOR(16 downto 0);
irq : OUT STD_LOGIC;
req : OUT STD_LOGIC
1154 markw
);
END sample_channel;

ARCHITECTURE vhdl OF sample_channel IS
1155 markw
signal pointer_reg : unsigned(16 downto 0);
signal pointer_next : unsigned(16 downto 0);
1172 markw
signal remaining_reg : unsigned(15 downto 0);
signal remaining_next : unsigned(15 downto 0);
1154 markw
signal periodpos_reg : unsigned(11 downto 0);
signal periodpos_next : unsigned(11 downto 0);
1157 markw
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;
1155 markw
1154 markw
BEGIN
-- register
process(clk,reset_n)
begin
if (reset_n='0') then
pointer_reg <= (others=>'0');
remaining_reg <= (others=>'0');
periodpos_reg <= (others=>'0');
1157 markw
req_reg <= '0';
irq_reg <= '0';
resetpending_reg <= '0';
1154 markw
elsif (clk'event and clk='1') then
pointer_reg <= pointer_next;
remaining_reg <= remaining_next;
periodpos_reg <= periodpos_next;
1157 markw
req_reg <= req_next;
irq_reg <= irq_next;
resetpending_reg <= resetpending_next;
1154 markw
end if;
end process;

process(start_addr, len, period,
1157 markw
pointer_reg, remaining_reg, periodpos_reg, resetpending_reg,
1155 markw
enable,
1163 markw
syncreset,
twocycles
1154 markw
)
1155 markw
variable change : unsigned(16 downto 0);
1157 markw
variable endperiod : std_logic;
variable endsample : std_logic;
variable nextsample : std_logic;
1154 markw
begin
pointer_next <= pointer_reg;
remaining_next <= remaining_reg;
periodpos_next <= periodpos_reg;
1157 markw
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))));
1154 markw
if (enable='1') then
periodpos_next <= periodpos_reg-1;
1157 markw
resetpending_next <='0';

if (endperiod='1') then
1155 markw
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);
1157 markw
req_next <= '1';

nextsample := endsample;
1154 markw
end if;
1157 markw
if (resetpending_reg='1') then
nextsample := '1';
end if;

if (nextsample='1') then
1234 markw
irq_next <= '1';
1157 markw
pointer_next <= unsigned(start_addr)&'0';
remaining_next <= unsigned(len);
periodpos_next <= unsigned(period);
req_next <= '1';
end if;
1154 markw
end if;
end process;

1160 markw
addr <= std_logic_vector(pointer_next);
1157 markw
req <= req_reg;
irq <= irq_reg;
1154 markw
end vhdl;