Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PandaBrick quDIS Interface - Initial commit #214

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 139 additions & 0 deletions modules/qudis/hdl/hssl_axis_decoder.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
----------------------------------------------------------------------------------
--
-- Single Axis quDIS HSSL Decoder.
--
-- G.Francis, August 2024.
--
--
-- quDIS Settings:
--
-- Timings below are for 32 bits (for PandABrick)
--
-- quDIS absolute maximum update rate is about 25kHz...
--
-- Example quDIS Daisy Settings (frequencies approximate):
--
-- 25kHz : Clock: 1uS, Gap: 8, Average 80nS.
--
-- 10kHz : Clock: 2uS, Gap: 18, Average 160nS.
--
-- Slowest mode is Clock 2.48uS, Gap 63, which gives 4.24kHz.
--
--
----------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;


entity hssl_axis_decoder is
generic (
DATA_LEN : natural := 32
);
Port (

clk_i : in std_logic; -- 125MHz Clock

clk_bit_i : in std_logic; -- HSSL Interface
data_bit_i : in std_logic;

hssl_val_o : out std_logic_vector(DATA_LEN-1 downto 0); -- Position Output
health_bit_o : out std_logic

);
end hssl_axis_decoder;


architecture arch_hssl of hssl_axis_decoder is


signal clk_bit : std_logic := '0';
signal clk_bit_b : std_logic := '0';
signal clk_prev : std_logic := '0';

signal rx_shift_reg : std_logic_vector(DATA_LEN-1 downto 0);

signal health_bit : std_logic := '0';

signal clk_timer : unsigned(15 downto 0);
signal bit_count : unsigned(5 downto 0);
signal threshold : unsigned(15 downto 0);



begin


-- Synchronize the hssl clock input
process (clk_i) is
begin
if rising_edge(clk_i) then
clk_bit <= clk_bit_b;
clk_bit_b <= clk_bit_i;
end if;
end process;



-- Decoder State Machine
process (clk_i) is

variable timeout : natural := 0;

begin
if rising_edge(clk_i) then

if clk_bit /= clk_prev then -- Clock bit has changed...

if clk_bit = '1' then -- rising edge...

if clk_timer > threshold then -- If finished,

if bit_count = DATA_LEN then
hssl_val_o <= rx_shift_reg; -- output value,
health_bit <= '1'; -- and flag good data.
else
health_bit <= '0'; -- or flag bad data if the bit count is wrong.
end if;

bit_count <= (others => '0'); -- reset bit counter

end if;

else -- falling edge...

rx_shift_reg <= rx_shift_reg(rx_shift_reg'high-1 downto 0) & data_bit_i; -- sample bit,
bit_count <= bit_count + 1; -- increment bit counter
threshold <= clk_timer + clk_timer/2; -- Set threshold to 1.5 * (measured clock-low width)
clk_timer <= (others => '0'); -- and reset clk-low width counter.

end if;

timeout := 0;

else

if clk_bit = '0' then
clk_timer <= clk_timer + 1; -- Clock bit has not changed (and is low), so increment timer.
end if;

end if;

clk_prev <= clk_bit; -- (store new clock level)


if timeout > 1250000 then -- 10mS timeout on clock bit input.
health_bit_o <= '0';
else
health_bit_o <= health_bit;
timeout := timeout + 1;
end if;

end if;

end process;



end arch_hssl;
114 changes: 114 additions & 0 deletions modules/qudis/hdl/qudis.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
----------------------------------------------------------------------------------
--
-- 3-Axis quDIS Interferometer decoder
--
-- G.Francis, August 2024.
--
----------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library work;
use work.top_defines.all;
use work.addr_defines.all;


entity qudis is
Port (

clk_i : in std_logic;
reset_i : in std_logic;
bit_bus_i : in bit_bus_t;
pos_bus_i : in pos_bus_t;

-- HSSL Hardware Interface
hssl_clk_pins : in std_logic_vector(3 downto 1);
hssl_data_pins : in std_logic_vector(3 downto 1);

-- Output Positions
pos_1_o : out std_logic_vector(31 downto 0);
pos_2_o : out std_logic_vector(31 downto 0);
pos_3_o : out std_logic_vector(31 downto 0);

-- Internal read interface
read_strobe_i : in std_logic;
read_address_i : in std_logic_vector(BLK_AW-1 downto 0);
read_data_o : out std_logic_vector(31 downto 0);
read_ack_o : out std_logic;

-- Internal write interface
write_strobe_i : in std_logic;
write_address_i : in std_logic_vector(BLK_AW-1 downto 0);
write_data_i : in std_logic_vector(31 downto 0);
write_ack_o : out std_logic

);
end qudis;


architecture arch_qudis of qudis is

signal hssl_positions : std32_array(3 downto 1);
signal health_bits : std_logic_vector(3 downto 1);
signal health : std_logic_vector(31 downto 0);

begin


-- Generate the Decoders...
GEN_DECODERS:
for axis_num in 1 to 3 generate

hssl_axis_decoder_inst : entity work.hssl_axis_decoder
port map (
clk_i => clk_i,
clk_bit_i => hssl_clk_pins(axis_num),
data_bit_i => hssl_data_pins(axis_num),
hssl_val_o => hssl_positions(axis_num),
health_bit_o => health_bits(axis_num)
);

end generate GEN_DECODERS;


-- Output positions...
pos_1_o <= hssl_positions(1);
pos_2_o <= hssl_positions(2);
pos_3_o <= hssl_positions(3);


-- Health word (bits are 1 for good)...
health(0) <= not health_bits(1);
health(1) <= not health_bits(2);
health(2) <= not health_bits(3);
health(31 downto 3) <= ( others => '0' );



qudis_ctrl_inst : entity work.qudis_ctrl
port map (
-- Clock and Reset
clk_i => clk_i,
reset_i => reset_i,
bit_bus_i => bit_bus_i,
pos_bus_i => pos_bus_i,

-- Block Parameters
HEALTH => health,

-- Memory Bus Interface
read_strobe_i => read_strobe_i,
read_address_i => read_address_i,
read_data_o => read_data_o,
read_ack_o => read_ack_o,

write_strobe_i => write_strobe_i,
write_address_i => write_address_i,
write_data_i => write_data_i,
write_ack_o => write_ack_o
);


end arch_qudis;
Loading
Loading