Commit 5c3dc526 authored by Florian Huemer's avatar Florian Huemer

init

parent a234a429
*.bak
*.flock
*.rpt
*.done
*.summary
*.smsg
*.qmsg
*.pof
*.sof
*.rbf
*.jdi
*.cdb
*.hdb
*.rdb
*.ddb
*.log
*~
db/**
incremental_db/**
greybox_tmp/**
-- Title : approx_agreement.vhd
-- Created : 19.11.2015
-- Author : Attila Kinali <attila@kinali.ch>
--
-- Description: Approximate Agreement on Pulsed system
-- The input values are processed at every 0->1 change of piValid
-- XXX
--
-- Input Singals:
-- XXX: XXX
--
-- Output Signals:
-- XXX: XXX
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.fixed_float_types.all;
use ieee.fixed_pkg.all;
use work.dac_interface_types.all;
use work.clocksync_types.all;
entity approx_agreement is
generic (
gTDCIntegerBits : natural; -- number of coarse counter bits in the TDC
gTDCFractionBits : natural; -- Number of bits in the fractional part
gCoarseCorrectionBits : positive; -- Number of bits in the coarse correction signal
gMeasurementWindowLength : positive; -- delay sApplyCorrection for at least the measurement window size, to ensure we do not jump back in
gDivider : positive -- how many clock cycles per SCLK cycle of the DAC (<=30MHz)
);
port (
piValues : in t2DArray(0 to 1, gTDCIntegerBits+gTDCFractionBits-1 downto 0); -- The two values that define the upper and lower bound of the n-2f range.
piValid : in std_logic; -- the input values are valid
piReference : in sfixed(gTDCIntegerBits-1 downto -gTDCFractionBits);
piDACReset : in std_logic; -- reset the DAC to nonimal value, must not be set earlier than 26*gDivider cycles after poApplyCorrection has been pulsed
poCoarseCorrection : out sfixed(gCoarseCorrectionBits-1 downto 0);
poApplyCorrection : out std_logic; -- high for signle cylce when coarse correction is valid and should be applied
piCntrlP : in sfixed(gTDCIntegerBits-1 downto -gTDCFractionBits);
piCntrlType : in std_logic;
-- DAC interface pins
poSync_n : out std_logic; -- /SYNC pin
poSCLK : out std_logic; -- SCLK pin
poDIN : out std_logic; -- DIN pin
clk : in std_logic;
reset : in std_logic
);
end entity approx_agreement;
architecture structural of approx_agreement is
component dac_interface is
generic (
gDivider : positive -- how many clock cycles per SCLK cycle (<=30MHz)
);
port (
piData : in std_logic_vector(num_bits-1 downto 0); -- input data
piDataReady : in std_logic; -- high = data input ready, start cycle
poBusy : out std_logic; -- high = unit is busy
poSync_n : out std_logic; -- /SYNC pin
poSCLK : out std_logic; -- SCLK pin
poDIN : out std_logic; -- DIN pin
clk : in std_logic;
reset : in std_logic
);
end component;
constant cTDCBitwidth : positive := gTDCIntegerBits+gTDCFractionBits;
-- signals are one bit larger than inputs to account for the addition
signal sValA : std_logic_vector(gTDCIntegerBits+gTDCFractionBits-1 downto 0);
signal sValB : std_logic_vector(gTDCIntegerBits+gTDCFractionBits-1 downto 0);
signal sNumA : sfixed(gTDCIntegerBits downto -gTDCFractionBits);
signal sNumB : sfixed(gTDCIntegerBits downto -gTDCFractionBits);
signal sSum : sfixed(gTDCIntegerBits+1 downto -gTDCFractionBits); -- temp signal to keep sum
signal sReference : sfixed(gTDCIntegerBits+1 downto -gTDCFractionBits);
signal sError : sfixed(gTDCIntegerBits+2 downto -gTDCFractionBits); -- error signal
signal sValidDelay : std_logic_vector(gMeasurementWindowLength downto 0); -- signal to delay piValid by one cylce
signal sApplyCorrection : std_logic; -- signal to delay piValid by one cylce
signal sDACdata : std_logic_vector(num_bits-1 downto 0); --16 bits
signal sDACDataReady : std_logic;
signal sDACBusy : std_logic;
signal sCntrlP : sfixed(gTDCIntegerBits-1 downto -gTDCFractionBits);
signal sCntrlP_D1 : sfixed(gTDCIntegerBits-1 downto -gTDCFractionBits);
signal sError_D1 : sfixed(gTDCIntegerBits+2 downto -gTDCFractionBits); -- error signal
signal sCntrlP_D2 : sfixed(gTDCIntegerBits-1 downto -gTDCFractionBits);
signal sError_D2 : sfixed(gTDCIntegerBits+2 downto -gTDCFractionBits); -- error signal
signal sCntrlP_D3 : sfixed(gTDCIntegerBits-1 downto -gTDCFractionBits);
signal sError_D3 : sfixed(gTDCIntegerBits+2 downto -gTDCFractionBits); -- error signal
signal sErrorTimesP : sfixed(0 downto -(num_bits-1)); -- values between -1 and +1
begin
ConnectInput: for i in sValA'range generate
begin
sValA(i) <= piValues(0,i);
sValB(i) <= piValues(1,i);
end generate;
sNumA <= to_sfixed("0" & sValA, sNumA);
sNumB <= to_sfixed("0" & sValB, sNumB);
sReference <= resize(piReference,sReference);
CalcCorrection: process(clk)
begin
if rising_edge(clk)
then
if reset = '1'
then
sSum <= to_sfixed(0, sSum'high, sSum'low);
sError <= to_sfixed(0, sError'high, sError'low);
sValidDelay <= (others => '0');
sApplyCorrection <= '1';
sCntrlP <= (others=>'0');
else
sSum <= (sNumA + sNumB) sra 1;
sError <= sSum - sReference;
sValidDelay(sValidDelay'high) <= piValid;
sValidDelay(sValidDelay'high-1 downto sValidDelay'low) <= sValidDelay(sValidDelay'high downto sValidDelay'low+1);
sCntrlP <= piCntrlP;
sCntrlP_D1 <= sCntrlP; --use additional registers and hope that quartus register retiming will do the job :)
sError_D1 <= sError;
sCntrlP_D2 <= sCntrlP_D1;
sError_D2 <= sError_D1;
sCntrlP_D3 <= sCntrlP_D2;
sError_D3 <= sError_D2;
sErrorTimesP <= resize( arg => (sError_D3 * sCntrlP_D3),
size_res => sErrorTimesP,
overflow_style => fixed_saturate,
round_style => fixed_truncate
);
-- generate a single pulse of sApplyCorrection
if sValidDelay(1) = '1' and sValidDelay(0) = '0'
then
sApplyCorrection <= '1';
else
sApplyCorrection <= '0';
end if;
end if;
end if;
end process;
ResizeCorrection: process(clk)
begin
if rising_edge(clk)
then
poCoarseCorrection <= resize(
arg => sError,
left_index => gCoarseCorrectionBits-1,
right_index => 0,
overflow_style => fixed_saturate,
round_style => fixed_round
);
--poApplyCorrection <= sApplyCorrection;
poApplyCorrection <= '0';
end if;
end process;
SetDAC: process(clk)
begin
if rising_edge(clk)
then
if reset = '1'
then
sDACdata <= (others => '0');
sDACDataReady <= '0';
else
if sApplyCorrection = '1' and sDACBusy = '0'
then
-- we decide on the direction and amplitude to correction
-- simply on the sign of the error. Yes this not exact
-- and will cause errors in the correction if abs(sError) >=0.5
-- but in that case we are off by more than one clock cylce (7.7ns @ 130MHz)
-- and the wrong correction applied here is 3 orders of magnitude smaller.
-- FIXME: fix this if the round length approaches 7.7ns/10ppm/2=385us
--if sError < to_sfixed(0, sError) then-- slow down
-- sDACdata <= (others => '0');
--elsif sError = to_sfixed(0, sError) then-- right frequency
-- sDACdata <= (num_bits-1 => '1', others => '0');
--else
-- sDACdata <= (others => '1'); -- go full speed!
--end if;
if (piCntrlType = '0') then -- simple controller
if sError < -0.5 then-- slow down
sDACdata <= (others => '0');
elsif sError > 0.5 then
sDACdata <= (others => '1'); -- go full speed!
else -- right frequency
sDACdata <= (num_bits-1 => '1', others => '0');
end if;
else -- P controller
sDACdata <= to_std_logic_vector(sErrorTimesP);
sDACdata(num_bits-1) <= not sErrorTimesP(0);
end if;
sDACDataReady <= '1';
elsif piDACReset = '1'
then
sDACdata <= (num_bits-1 => '1', others => '0');
sDACDataReady <= '1';
else
sDACDataReady <= '0';
end if;
end if;
end if;
end process;
DAC: dac_interface
generic map (
gDivider => gDivider
)
port map (
piData => sDACdata,
piDataReady => sDACDataReady,
poBusy => sDACBusy,
poSync_n => poSync_n,
poSCLK => poSCLK,
poDIN => poDIN,
clk => clk,
reset => reset
);
end architecture structural;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.clocksync_types.all;
entity clocksync_top is
port (
piPulseIn : in std_logic_vector(num_nodes-2 downto 0);
poPulseOut : out std_logic_vector(num_nodes-1 +2 downto 0); -- for each node, the nodes own pulse and two auxillary pluse outputs
piReferencePulse : in std_logic;
piButton1 : in std_logic;
piButton2 : in std_logic;
-- DAC control pins
poSync_n : out std_logic; -- /SYNC pin
poSCLK : out std_logic; -- SCLK pin
poDIN : out std_logic; -- DIN pin
-- LEDs on the DE0 nano board
poLED : out std_logic_vector(7 downto 0);
poDebugSig : out std_logic_vector( (num_nodes-1)*2-1 downto 0);
poClkHalf : out std_logic;
poClkHalf2 : out std_logic;
poClk : out std_logic;
piClkLoop : in std_logic;
poClkLoop : out std_logic;
piclk : in std_logic
);
end entity clocksync_top;
architecture behavioral of clocksync_top is
component ctrl_algo is
generic (gNum_nodes : positive; -- Total number of nodes
-- sum of gTDCIntegerBits and gTDCFractionBits should be 31 for now (uart_ctrl limitation)
gCycleLength : positive; -- number of clock cylces for an algo loop. must be at least 1.5us+2u+3cycles
gPulseWidth : positive; -- number of clock cycles for the pulse width
gClockFrequency : positive -- clock frequency in MHz
);
port (piPulseIn : in std_logic_vector(num_nodes-2 downto 0);
piReferencePulse : in std_logic;
poPulse : out std_logic; -- Protocol pulse
piStopClock : in std_logic; -- if high, the clock is kept at at the point where the pulse would be generated, to start from there when it goes low
-- DAC interface pins
poSync_n : out std_logic; -- /SYNC pin
poSCLK : out std_logic; -- SCLK pin
poDIN : out std_logic; -- DIN pin
poDebugSig : out std_logic_vector( (num_nodes-1)*2-1 downto 0);
clk : in std_logic;
reset : in std_logic
);
end component;
component debounce IS
GENERIC(
counter_size : INTEGER := 19); --counter size (19 bits gives 10.5ms with 50MHz clock)
PORT(
clk : IN STD_LOGIC; --input clock
button : IN STD_LOGIC; --input signal to be debounced
result : OUT STD_LOGIC); --debounced signal
END component;
component ip_altpll is
PORT
(
areset : IN STD_LOGIC := '0';
inclk0 : IN STD_LOGIC := '0';
c0 : OUT STD_LOGIC
);
end component;
-- main constants
constant cClockFrequency : positive := 130; -- clock frequency in MHz
signal sStopClock : std_logic;
signal sPulseOut : std_logic;
signal sPulseInVec : std_logic_vector(num_nodes-2 downto 0);
-- state machines
type clk_state_type is (start, wait_for_button_press, wait_for_button_release, wait_for_pulse, running);
signal clk_state : clk_state_type;
-- button synchronizers and de-bouncer (100us debounce)
signal sButtonState1 : std_logic; -- current state
signal sButtonState2 : std_logic; -- current state
signal clk : std_logic; -- the global clock
signal reset : std_logic; -- the global reset, unused
signal sClkHalf : std_logic;
signal sWCFValid : std_logic;
signal sWCFAFirst : std_logic;
begin
clkhalfer: process(piclk)
begin
if rising_edge(piclk)
then
sClkHalf <= not sClkHalf;
end if;
end process;
poClkHalf <= sClkHalf;
poClkHalf2 <= sClkHalf;
poClk <= piClk;
poClkLoop <= piClkLoop;
reset <= not sButtonState1; -- connect reset to SW1
reset_debounce: debounce
GENERIC map(
counter_size => 19
)
PORT map(
clk => clk,
button => piButton1,
result => sButtonState1
);
button_debounce: debounce
GENERIC map(
counter_size => 19
)
PORT map(
clk => clk,
button => piButton2,
result => sButtonState2
);
main_FSM: process(clk,piButton1, piButton2)
begin
if rising_edge(clk)
then
if reset = '1'
then
clk_state <= start;
sStopClock <= '1';
poLED <= (others => '0');
else
case clk_state is
when start =>
clk_state <= wait_for_button_press;
sStopClock <= '1';
poLED(0) <= '1';
poLED(7 downto 1) <= (others => '0'); -- clear leds incase we came from an unitialized state
when wait_for_button_press =>
if sButtonState2 = '0'
then
clk_state <= wait_for_button_release;
sStopClock <= '1';
--elsif piPulseIn(0) = '1' or piPulseIn(1) = '1' or piPulseIn(2) = '1'
elsif sPulseInVec(0) = '1' or sPulseInVec(1) = '1' or sPulseInVec(2) = '1'
then
clk_state <= running;
sStopClock <= '0';
end if;
poLED(2) <= '1';
when wait_for_button_release =>
if sButtonState2 = '1'
then
clk_state <= running;
sStopClock <= '1';
end if;
poLED(3) <= '1';
when running =>
sStopClock <= '0';
poLED(5) <= '1';
when others =>
clk_state <= start;
end case;
end if;
end if;
-- assign unused LEDs
poLED(6) <= piButton1;
poLED(7) <= piButton2;
end process;
poPulseOut(4 downto 0) <= (others => not sPulseOut);
poPulseOut(5) <= sPulseInVec(1);
sPulseInVec <= not piPulseIn; --(others => piPulseIn(0));
CTRL: ctrl_algo
generic map (
gNum_nodes => num_nodes,
gCycleLength => cClockFrequency*50,
gPulseWidth => 7,
gClockFrequency => cClockFrequency
)
port map (
piPulseIn => sPulseInVec,
piReferencePulse => not piReferencePulse,
poPulse => sPulseOut,
piStopClock => sStopClock,
poSync_n => poSync_n,
poSCLK => poSCLK,
poDIN => poDin,
poDebugSig => poDebugSig,
clk => clk,
reset => reset
);
ALTERA_PLL: ip_altpll
port map
(
inclk0 => piclk,
c0 => clk
);
end architecture behavioral;
\ No newline at end of file
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package clocksync_types is
constant num_nodes : positive := 4; -- total number of nodes
type t2DArray is array(natural range <>, natural range <>) of std_logic;
type uart_ctrl_sig_type is (idle, send_header, send_data);
function log2ceil (n : integer) return integer;
function log2floor (n : integer) return integer;
end package clocksync_types;
package body clocksync_types is
-- purpose: computes ceil(log2(n))
function log2ceil (n : integer) return integer is
variable m, p : integer;
begin
m := 0;
p := 1;
for i in 0 to n loop
if p < n then
m := m + 1;
p := p * 2;
end if;
end loop;
return m;
end log2ceil;
-- purpose: computes floor(log2(n))
function log2floor (n : integer) return integer is
variable m, p : integer;
begin
m := -1;
p := 1;
for i in 0 to n loop
if p <= n then
m := m + 1;
p := p * 2;
end if;
end loop;
return m;
end log2floor;
end;
-- Title : compare_exchange
-- Created : 17.11.2015
-- Author : Attila Kinali <attila@kinali.ch>
--
-- Description: compare two std_logic_vector vectors interpreted as unsigned and output them sorted
-- Has an additional data valid bit to enable pipelining
-- XXX
--
-- Input Singals:
-- XXX: XXX
--
-- Output Signals:
-- XXX: XXX