library IEEE;
use IEEE.std_LOGIC_1164.ALL;
-- the next two packages are necessary in order to use arithmetic expressions with std_logic_vectors
use ieee.std_logic_arith.all;
-- interpret the std_logic_vectors as unsigned
use ieee.std_logic_unsigned.all;
entity top_core is
Generic(ClkMHz : integer := 100);
Port (
CLK : in std_logic;
Reset : in std_logic;
-- put here the signals to the SUxxx modules
-- Slot 0 is empty
-- SU704 on slot 1
SU1_INTTL : in std_logic_vector( 5 downto 1);
SU1_OUTP : out std_logic_vector( 5 downto 1);
SU1_INECL : in std_logic_vector( 5 downto 1);
SU1_OE_n : out std_logic_vector( 5 downto 1);
SU1_LED_n : out std_logic_vector( 5 downto 1);
SU1_TERM : out std_logic_vector( 5 downto 1);
-- Slot 2 is empty
-- Slot 3 is empty
-- Slot 4 is empty
-- Slot 5 is empty
-- Slot 6 is empty
-- Slot 7 is empty
-- end of the SUxxx section
Tick1ms : in std_logic;
Tick20ms : in std_logic;
-- DMA config & handshaking
DMA_ena : in std_logic; -- DMA enabled
DMA_ack : in std_logic; -- DMA acknoledge
DMA_req : out std_logic; -- request, activate only when DMA_ena=1, deactivate after ack
DMA_Nwords : out std_logic_vector(15 downto 0); -- Number of words
DMA_Addr : out std_logic_vector(31 downto 0); -- start address
DMA_dsize : out std_logic_vector( 1 downto 0); -- 0..3 for 1..4 bytes
DMA_Ainc : out std_logic; -- auto increment of the address
-- IF
CAddr : in std_logic_vector(31 downto 0);
CWR : in std_logic;
CRD : in std_logic;
CDIn : in std_logic_vector(31 downto 0);
CDOut : out std_logic_vector(31 downto 0);
CRdy : out std_logic);
end top_core;
architecture unsere of top_core is
constant max_timer : Integer := ClkMHz*1000000-1;
signal timer : Integer range 0 to max_timer;
signal copy_rst : std_logic;
signal inp_edge : std_logic_vector(1 downto 0);
signal cnt_ena : std_logic;
signal counter, counter_cp : std_logic_vector(31 downto 0);
signal generator : std_logic_vector(6 downto 0);
begin
-- output 1 is the output of the generator, all others are unused
SU1_OUTP <= (5 => generator(generator'high), others => '0');
-- output enabled only in channel 5
SU1_OE_n <= (5 => '0', others => '1');
-- termination only in channel 1 (the input)
SU1_TERM <= (1 => '1', others => '0');
-- the ready for the Cbus, if not wired will be 0 and the USB controller waits for ever!
CRDy <= '1';
-- detect a positive edge at the input, sample twice in a shift register
process(clk)
begin
if rising_edge(clk) then
-- shift register with two bits
inp_edge <= inp_edge(0) & SU1_INTTL(1);
-- new is 1 and the old is 0
cnt_ena <= inp_edge(0) and not inp_edge(1);
-- binary counter, used to generate some output
generator <= generator + 1;
end if;
end process;
-- counter for the detected edges
process(clk)
begin
if rising_edge(clk) then
-- if copy & reset - latch the counter to the register and clear the counter
-- for the next counting period.
if copy_rst='1' then
-- take into account a possible edge detected right now
counter <= (0 => cnt_ena, others => '0');
counter_cp <= counter;
elsif cnt_ena='1' then
-- count up
counter <= counter + 1;
end if;
end if;
end process;
-- read mux, either the latched counts or the running counter
CDout <= counter_cp when CAddr(0)='0' else counter;
-- output register to control the LEDs
process(clk)
begin
if rising_edge(clk) then
if Reset='1' then
-- all LEDs are on after reset
SU1_LED_n <= (others => '0');
elsif CWR='1' then
-- invert when writing, so writing 1 will turn the LED on
SU1_LED_n <= not CDIn(SU1_LED_n'length-1 downto 0);
end if;
end if;
end process;
-- timer, produce once in a second a pulse one period long
process(clk)
begin
if rising_edge(clk) then
if timer > 0 then
-- count down
timer <= timer - 1;
-- deactivate copy & reset
copy_rst <= '0';
else
-- load with the max value
timer <= max_timer;
-- activate copy & reset
copy_rst <= '1';
end if;
end if;
end process;
end;