| Copyright | (C) 2015-2016, University of Twente |
|---|---|
| License | BSD2 (see the file LICENSE) |
| Maintainer | Christiaan Baaij <christiaan.baaij@gmail.com> |
| Safe Haskell | Safe |
| Language | Haskell2010 |
| Extensions | DeriveDataTypeable |
CLaSH.Annotations.TopEntity
Description
The TopEntity annotations described in this module make it easier to put your
design on an FPGA.
We can exert some control how the top level function is created by the CλaSH
compiler by annotating the topEntity function with a TopEntity annotation.
You apply these annotations using the ANN pragma like so:
{-# ANN topEntity (TopEntity {t_name = ..., ... }) #-}
topEntity x = ...
For example, given the following specification:
topEntity :: Signal Bit -> Signal (BitVector 8)
topEntity key1 = leds
where
key1R = isRising 1 key1
leds = mealy blinkerT (1,False,0) key1R
blinkerT (leds,mode,cntr) key1R = ((leds',mode',cntr'),leds)
where
-- clock frequency = 50e6 (50 MHz)
-- led update rate = 333e-3 (every 333ms)
cnt_max = 16650000 -- 50e6 * 333e-3
cntr' | cntr == cnt_max = 0
| otherwise = cntr + 1
mode' | key1R = not mode
| otherwise = mode
leds' | cntr == 0 = if mode then complement leds
else rotateL leds 1
| otherwise = leds
The CλaSH compiler will normally generate the following topEntity.vhdl file:
-- Automatically generated VHDL
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.MATH_REAL.ALL;
use work.all;
use work.types.all;
entity topEntity is
port(input_0 : in std_logic_vector(0 downto 0);
-- clock
system1000 : in std_logic;
-- asynchronous reset: active low
system1000_rstn : in std_logic;
output_0 : out std_logic_vector(7 downto 0));
end;
architecture structural of topEntity is
begin
topEntity_0_inst : entity topEntity_0
port map
(key1_i1 => input_0
,system1000 => system1000
,system1000_rstn => system1000_rstn
,topLet_o => output_0);
end;
However, if we add the following TopEntity annotation in the file:
{-# ANN topEntity
(defTop
{ t_name = "blinker"
, t_inputs = ["KEY1"]
, t_outputs = ["LED"]
, t_extraIn = [ ("CLOCK_50", 1)
, ("KEY0" , 1)
]
, t_clocks = [ altpll "altpll50" "CLOCK_50(0)" "not KEY0(0)" ]
}) #-}
The CλaSH compiler will generate the following blinker.vhdl file instead:
-- Automatically generated VHDL
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.MATH_REAL.ALL;
use work.all;
use work.types.all;
entity blinker is
port(KEY1 : in std_logic_vector(0 downto 0);
CLOCK_50 : in std_logic_vector(0 downto 0);
KEY0 : in std_logic_vector(0 downto 0);
LED : out std_logic_vector(7 downto 0));
end;
architecture structural of blinker is
signal system1000 : std_logic;
signal system1000_rstn : std_logic;
signal altpll50_locked : std_logic;
begin
altpll50_inst : entity altpll50
port map
(inclk0 => CLOCK_50(0)
,c0 => system1000
,areset => not KEY0(0)
,locked => altpll50_locked);
-- reset system1000_rstn is asynchronously asserted, but synchronously de-asserted
resetSync_n_0 : block
signal n_1 : std_logic;
signal n_2 : std_logic;
begin
process(system1000,altpll50_locked)
begin
if altpll50_locked = '0' then
n_1 <= '0';
n_2 <= '0';
elsif rising_edge(system1000) then
n_1 <= '1';
n_2 <= n_1;
end if;
end process;
system1000_rstn <= n_2;
end block;
topEntity_0_inst : entity topEntity_0
port map
(key1_i1 => KEY1
,system1000 => system1000
,system1000_rstn => system1000_rstn
,topLet_o => LED);
end;
Where we now have:
- A top-level component that is called
blinker. - Inputs and outputs that have a user-chosen name:
KEY1,LED, etc. - An instantiated PLL
component providing a stable clock signal from the free-running clock pin
CLOCK_50. - A reset that is asynchronously asserted by the
locksignal originating from the PLL, meaning that your design is kept in reset until the PLL is providing a stable clock. The reset is additionally synchronously de-asserted to prevent metastability of your design due to unlucky timing of the de-assertion of the reset.
See the documentation of TopEntity for the meaning of all its fields.
- data TopEntity = TopEntity {}
- data ClockSource = ClockSource {}
- defTop :: TopEntity
- altpll :: String -> String -> String -> ClockSource
- alteraPll :: String -> String -> String -> ClockSource
- clockWizard :: String -> String -> String -> ClockSource
- clockWizardDifferential :: String -> String -> String -> String -> ClockSource
Data types
TopEntity annotation
Constructors
| TopEntity | |
Fields
| |
data ClockSource Source
A clock source
Constructors
| ClockSource | |
Fields
| |
Instances
Convenience functions
Default TopEntity which has no clocks, and no specified names for the
input and output ports. Also has no clock sources:
>>>defTopTopEntity {t_name = "topentity", t_inputs = [], t_outputs = [], t_extraIn = [], t_extraOut = [], t_clocks = []}
Altera clock sources
Arguments
| :: String | Name of the component. |
| -> String | Clock Pin/Expression of the free running clock. |
| -> String | Reset Pin/Expression controlling the reset of the PLL. |
| -> ClockSource |
A clock source that corresponds to the Altera/Quartus "ALTPLL" component
with default settings to provide a stable systemClock.
>>>altpll "altpll50" "CLOCK(0)" "not KEY(0)"ClockSource {c_name = "altpll50", c_inp = [("inclk0","CLOCK(0)")], c_outp = [("c0","system1000")], c_reset = Just ("areset","not KEY(0)"), c_lock = "locked", c_sync = False}
Will generate the following VHDL:
altpll50_inst : entity altpll50
port map
(inclk0 => CLOCK_50(0)
,c0 => system1000
,areset => not KEY0(0)
,locked => altpll50_locked);If you are however generating (System)Verilog you should write:
>>>altpll "altpll50" "CLOCK[0]" "~ KEY[0]"ClockSource {c_name = "altpll50", c_inp = [("inclk0","CLOCK[0]")], c_outp = [("c0","system1000")], c_reset = Just ("areset","~ KEY[0]"), c_lock = "locked", c_sync = False}
so that the following (System)Verilog is created:
altpll50 altpll50_inst (.inclk0 (CLOCK_50[0]) ,.c0 (system1000) ,.areset (~ KEY0[0]) ,.locked (altpll50_locked));
Arguments
| :: String | Name of the component. |
| -> String | Clock Pin/Expression of the free running clock. |
| -> String | Reset Pin/Expression controlling the reset of the PLL. |
| -> ClockSource |
A clock source that corresponds to the Altera "Altera PLL" component
with default settings to provide a stable systemClock.
>>>alteraPll "alteraPll50" "CLOCK(0)" "not KEY(0)"ClockSource {c_name = "alteraPll50", c_inp = [("refclk","CLOCK(0)")], c_outp = [("outclk_0","system1000")], c_reset = Just ("rst","not KEY(0)"), c_lock = "locked", c_sync = False}
Will generate the following VHDL:
alteraPll50_inst : entity alteraPll
port map
(refclk => CLOCK_50(0)
,outclk_0 => system1000
,rst => not KEY0(0)
,locked => alteraPll50_locked);If you are however generating (System)Verilog you should write:
>>>alteraPll "alteraPll50" "CLOCK[0]" "~ KEY[0]"ClockSource {c_name = "alteraPll50", c_inp = [("refclk","CLOCK[0]")], c_outp = [("outclk_0","system1000")], c_reset = Just ("rst","~ KEY[0]"), c_lock = "locked", c_sync = False}
so that the following (System)Verilog is created:
alteraPll50 alteraPll50_inst (.refclk (CLOCK_50[0]) ,.outclk_0 (system1000) ,.rst (~ KEY0[0]) ,.locked (alteraPll50_locked));
Xilinx clock sources
Arguments
| :: String | Name of the component. |
| -> String | Clock Pin/Expression of the free running clock. |
| -> String | Reset Pin/Expression controlling the reset of the PLL. |
| -> ClockSource |
A clock source that corresponds to the Xilinx PLL/MMCM component created
with the "Clock Wizard", with settings to provide a stable systemClock.
>>>clockWizard "clkwiz50" "CLOCK(0)" "not KEY(0)"ClockSource {c_name = "clkwiz50", c_inp = [("CLK_IN1","CLOCK(0)")], c_outp = [("CLK_OUT1","system1000")], c_reset = Just ("RESET","not KEY(0)"), c_lock = "LOCKED", c_sync = False}
Will generate the following VHDL:
clkwiz50_inst : entity clkwiz50
port map
(CLK_IN1 => CLOCK(0)
,CLK_OUT1 => system1000
,RESET => not KEY(0)
,LOCKED => clkwiz50_locked);If you are however generating (System)Verilog you should write:
>>>clockWizard "clkwiz50" "CLOCK[0]" "~ KEY[0]"ClockSource {c_name = "clkwiz50", c_inp = [("CLK_IN1","CLOCK[0]")], c_outp = [("CLK_OUT1","system1000")], c_reset = Just ("RESET","~ KEY[0]"), c_lock = "LOCKED", c_sync = False}
so that the following (System)Verilog is created:
clkwiz50 clkwiz50_inst (.CLK_IN1 (CLOCK[0]) ,.CLK_OUT1 (system1000) ,.RESET (~ KEY[0]) ,.LOCKED (clkwiz50_locked));
clockWizardDifferential Source
Arguments
| :: String | Name of the component. |
| -> String | Clock Pin/Expression of the differential free running clock, negative phase. |
| -> String | Clock Pin/Expression of the differential free running clock, positive phase. |
| -> String | Reset Pin/Expression controlling the reset of the PLL. |
| -> ClockSource |
A clock source that corresponds to the Xilinx PLL/MMCM component created
with the "Clock Wizard", with settings to provide a stable systemClock
from differential free-running inputs.
>>>clockWizardDifferential "clkwiz50" "CLOCK(0)" "CLOCK(1)" "not KEY(0)"ClockSource {c_name = "clkwiz50", c_inp = [("CLK_IN1_D_clk_n","CLOCK(0)"),("CLK_IN1_D_clk_p","CLOCK(1)")], c_outp = [("CLK_OUT1","system1000")], c_reset = Just ("RESET","not KEY(0)"), c_lock = "LOCKED", c_sync = False}
Will generate the following VHDL:
clkwiz50_inst : entity clkwiz50
port map
(CLK_IN1_D_clk_n => CLOCK(0)
,CLK_IN1_D_clk_p => CLOCK(1)
,CLK_OUT1 => system1000
,RESET => not KEY(0)
,LOCKED => clkwiz50_locked);If you are however generating (System)Verilog you should write:
>>>clockWizardDifferential "clkwiz50" "CLOCK[0]" "CLOCK[1]" "~ KEY[0]"ClockSource {c_name = "clkwiz50", c_inp = [("CLK_IN1_D_clk_n","CLOCK[0]"),("CLK_IN1_D_clk_p","CLOCK[1]")], c_outp = [("CLK_OUT1","system1000")], c_reset = Just ("RESET","~ KEY[0]"), c_lock = "LOCKED", c_sync = False}
so that the following (System)Verilog is created:
clkwiz50 clkwiz50_inst (.CLK_IN1_D_clk_n (CLOCK[0]) ,.CLK_IN1_D_clk_p (CLOCK[1]) ,.CLK_OUT1 (system1000) ,.RESET (~ KEY[0]) ,.LOCKED (clkwiz50_locked));