Commit 6cf80089 authored by Jan Pospisil's avatar Jan Pospisil

added RF frequency sense

parent a7f7c929
-- TODO:
-- - frequency sense
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
......
......@@ -56,6 +56,12 @@ architecture syn of FfpgSlave is
signal ClkRf_k: std_logic;
signal TriggerRf: std_logic;
signal ClkRfStable: std_logic := '0';
constant c_ClkRfStableWidth: positive := 12; -- 32-10 ~ kHz, 32-20 ~ MHz
constant c_ClkRfStableCount: positive := 4;
type t_ClkStable is array (0 to c_ClkRfStableCount-1) of unsigned(c_ClkRfStableWidth-1 downto 0);
signal ClkRfFrequencyHistory: t_ClkStable := (others => (others => '0'));
signal Ch1SetMemAddress_b11: unsigned(10 downto 0);
signal Ch1SetMemData_b32: unsigned(31 downto 0);
......@@ -226,7 +232,7 @@ begin
LedSignal_b(3) <= TriggerRf;
-- CLK IN
LedSignal_b(4) <= '1'; -- works just as "ON" LED as presence of ClkRf_ik cannot be sensed
LedSignal_b(4) <= ClkRfStable;
cSlowToggle: entity work.SlowToggle(behavioral)
generic map (
......@@ -301,10 +307,45 @@ begin
ClkOut_ok <= Clk_ik;
----------------------------------
-- to be used
-- RF frequency sense
----------------------------------
cFrequencySense: entity work.FrequencySense(syn)
generic map (
g_ClkFrequency => g_ClkFrequency,
g_SenseFrequencyWidth => WbRegsInput.frequency_i'length
)
port map (
Clk_ik => Clk_ik,
SenseClk_ik => ClkRf_k,
SenseFrequency_ob => WbRegsInput.frequency_i
);
pFrequencyHistory: process (Clk_ik) is begin
if rising_edge(Clk_ik) then
ClkRfFrequencyHistory(0) <= WbRegsInput.frequency_i(WbRegsInput.frequency_i'length-1 downto WbRegsInput.frequency_i'length-c_ClkRfStableWidth);
for i in 1 to c_ClkRfStableCount-1 loop
ClkRfFrequencyHistory(i) <= ClkRfFrequencyHistory(i-1);
end loop;
end if;
end process;
pFrequencyStable: process (ClkRfFrequencyHistory) is
variable Result: std_logic;
begin
Result := '1';
for i in 1 to c_ClkRfStableCount-1 loop
if ClkRfFrequencyHistory(i) /= ClkRfFrequencyHistory(0) then
Result := '0';
end if;
end loop;
ClkRfStable <= Result;
end process;
----------------------------------
-- debug
----------------------------------
WbRegsInput.frequency_i <= (others => 'X');
WbRegsInput.debug_i(31 downto 6) <= (others => '0');
end architecture;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity FrequencySense is
generic (
g_ClkFrequency: positive; -- input clock frequency in Hz
g_SenseFrequencyWidth: positive -- to accomodate maximum frequency to sense
);
port (
Clk_ik: in std_logic;
SenseClk_ik: in std_logic;
SenseFrequency_ob: out unsigned(g_SenseFrequencyWidth-1 downto 0) := (others => '0')
);
end entity;
architecture syn of FrequencySense is
-- SD ~ SenseClk_ik Domain
signal Latch, LatchToggle: std_logic := '0';
signal LatchToggleSD, LatchSD: std_logic;
signal
FrequencyCounterValueSD_b, FrequencyCounterValueSD_bd,
FrequencyCounterValue_b, FrequencyCounterValue_bd:
std_logic_vector(g_SenseFrequencyWidth-1 downto 0);
signal Frequency_b: unsigned(g_SenseFrequencyWidth-1 downto 0);
begin
-- Clk_ik domain
c1HzGenerator: entity work.CounterLength(syn)
generic map (
g_Length => g_ClkFrequency
)
port map (
Clk_ik => Clk_ik,
Reset_ir => '0',
Enable_i => '1',
Overflow_o => Latch
);
pLatchToggle: process (Clk_ik) is begin
if rising_edge(Clk_ik) then
if Latch = '1' then
LatchToggle <= not LatchToggle;
end if;
end if;
end process;
cFrequencyCounterReg: entity work.Reg(syn)
port map (
Clk_ik => Clk_ik,
Reset_ir => '0',
Data_ib => FrequencyCounterValue_b,
Enable_i => Latch,
Data_ob => FrequencyCounterValue_bd
);
Frequency_b <= unsigned(FrequencyCounterValue_b) - unsigned(FrequencyCounterValue_bd);
pFrequencyReg: process (Clk_ik) is begin
if rising_edge(Clk_ik) then
if Latch = '1' then
SenseFrequency_ob <= Frequency_b;
end if;
end if;
end process;
-- CDC
cLatchSyncer: entity work.Delay(syn)
generic map (
g_Width => 1,
g_Delay => 3,
g_AsyncRegUsed => "TRUE"
)
port map (
Clk_ik => SenseClk_ik,
Data_ib(0) => LatchToggle,
Data_ob(0) => LatchToggleSD
);
cFrequencyCounterSyncer: entity work.Delay(syn)
generic map (
g_Width => g_SenseFrequencyWidth,
g_Delay => 3,
g_AsyncRegUsed => "TRUE"
)
port map (
Clk_ik => Clk_ik,
Data_ib => FrequencyCounterValueSD_bd,
Data_ob => FrequencyCounterValue_b
);
-- SenseClk_ik domain
cFrequencyCounterSD: entity work.Counter(syn)
generic map (
g_Width => g_SenseFrequencyWidth
)
port map (
Clk_ik => SenseClk_ik,
Reset_ir => '0',
Enable_i => '1',
Set_i => '0',
SetValue_ib => (others => '0'),
Overflow_o => open,
std_logic_vector(Value_ob) => FrequencyCounterValueSD_b
);
cLatchEdgeDetectorSD: entity work.EdgeDetector(both)
port map (
Clk_ik => SenseClk_ik,
Signal_i => LatchToggleSD,
Edge_o => LatchSD
);
cFrequencyCounterRegSD: entity work.Reg(syn)
port map (
Clk_ik => SenseClk_ik,
Reset_ir => '0',
Data_ib => FrequencyCounterValueSD_b,
Enable_i => LatchSD,
Data_ob => FrequencyCounterValueSD_bd
);
end architecture;
\ No newline at end of file
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity FrequencySense_tb is
end entity;
architecture testbench of FrequencySense_tb is
--! computes least possible width of the vector to store value X
-- http://stackoverflow.com/a/12751341/615627
function f_log2(x: natural) return natural is
variable i: natural;
begin
i := 0;
while (2**i < x) loop
i := i + 1;
end loop;
return i;
end function;
constant c_ClkFrequency: positive := 62_500;
constant c_ClkPeriod: time := (1 sec)/real(c_ClkFrequency);
constant c_SenseClkFrequency: positive := 5_000;
constant c_SenseClkPeriod: time := (1 sec)/real(c_SenseClkFrequency);
constant c_SenseFrequencyWidth: positive := f_log2(c_SenseClkFrequency);
signal Clk_ik, SenseClk_k, SenseClk_ik: std_logic := '0';
signal SenseClkEnable: std_logic := '1';
signal SenseFrequency_ob: unsigned(c_SenseFrequencyWidth-1 downto 0);
procedure f_Tick(ticks: in natural) is begin
wait for ticks * c_ClkPeriod;
end procedure;
begin
cDUT: entity work.FrequencySense(syn)
generic map (
g_ClkFrequency => c_ClkFrequency,
g_SenseFrequencyWidth => c_SenseFrequencyWidth
)
port map (
Clk_ik => Clk_ik,
SenseClk_ik => SenseClk_ik,
SenseFrequency_ob => SenseFrequency_ob
);
pClk: process is begin
Clk_ik <= '0';
wait for c_ClkPeriod/2;
Clk_ik <= '1';
wait for c_ClkPeriod/2;
end process;
pSenseClk: process is begin
SenseClk_k <= '0';
wait for c_SenseClkPeriod/2;
SenseClk_k <= '1';
wait for c_SenseClkPeriod/2;
end process;
SenseClk_ik <= SenseClk_k and SenseClkEnable;
pTest: process is begin
wait for 5 sec;
SenseClkEnable <= '0';
wait for 5.35 sec;
SenseClkEnable <= '1';
wait for 5 sec;
assert false report "NONE. End of simulation." severity failure;
wait;
end process;
end architecture;
\ No newline at end of file
......@@ -29,6 +29,7 @@ vcom -2008 -reportprogress 300 -work work ../../rtl/ChangeDetector.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/Reg.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/RegSyncer.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/SlowToggle.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/FrequencySense.vhd
vcom -2008 -reportprogress 300 -work work ../../../ip_cores/general-cores/modules/wishbone/wishbone_pkg.vhd
vcom -2008 -reportprogress 300 -work work ../../../ip_cores/general-cores/modules/wishbone/wb_slave_adapter/wb_slave_adapter.vhd
......
......@@ -290,12 +290,12 @@ peripheral {
reg {
name = "Clock frequency";
prefix = "frequency";
description = "Frequency of the input clock in kHz.";
description = "Frequency of the input clock in Hz.";
field {
name = "Clock frequency value";
type = UNSIGNED;
size = 16;
size = 32;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
......
......@@ -31,6 +31,7 @@ vcom -2008 -reportprogress 300 -work work ../../../ffpg/rtl/ChangeDetector.vhd
vcom -2008 -reportprogress 300 -work work ../../../ffpg/rtl/Reg.vhd
vcom -2008 -reportprogress 300 -work work ../../../ffpg/rtl/RegSyncer.vhd
vcom -2008 -reportprogress 300 -work work ../../../ffpg/rtl/SlowToggle.vhd
vcom -2008 -reportprogress 300 -work work ../../../ffpg/rtl/FrequencySense.vhd
vcom -2008 -reportprogress 300 -work work ../../../ip_cores/general-cores/modules/wishbone/wishbone_pkg.vhd
vcom -2008 -reportprogress 300 -work work ../../../ip_cores/general-cores/modules/wishbone/wb_slave_adapter/wb_slave_adapter.vhd
......
This diff is collapsed.
......@@ -22,7 +22,7 @@ class ConColors:
m = encoreio.Module.get_instance('fmc_fpg', 0)
WB_DEBUG = True
WB_DEBUG = False
WB_DEBUG_2_SV = False
WB_DEBUG_2_SV_FILE = 'wb_trace.svh'
......@@ -134,6 +134,9 @@ def WaitForNotBusy(register, bit, timeOut, tries, message = '', polarity = 1):
def Ad9512Sync():
WbSetBits('control', 0x200)
def PrintFrequency():
print(str(WbRead('frequency')/1e6)+' MHz')
# 0 - front panel clock
# 1 - FPGA loop clock
# 2 - oscillator
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment