Skip to content

Commit

Permalink
Merge pull request #216 from PandABlocks/pandabrick-encoders
Browse files Browse the repository at this point in the history
Pandabrick encoders
  • Loading branch information
tomtrafford authored Oct 18, 2024
2 parents 4b7a35b + 2fc97a5 commit 5b15630
Show file tree
Hide file tree
Showing 19 changed files with 1,275 additions and 519 deletions.
2 changes: 1 addition & 1 deletion apps/PandABrick.app.ini
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description:
- built-in FMC encoder card
- PandA synchroniser on SFP on-board FMC
target: PandABrick
includes: common_soft_blocks.include.ini
includes: pandabrick_soft_blocks.include.ini

[SFP_SYNC]
module: sfp_panda_sync
Expand Down
228 changes: 228 additions & 0 deletions common/hdl/encoders/absenc.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library work;
use work.support.all;

entity absenc is
port(
clk_i : in std_logic;
reset_i : in std_logic;

clk_out_ext_i : in std_logic;

ABSENC_PROTOCOL_i : in std_logic_vector(2 downto 0);
ABSENC_ENCODING_i : in std_logic_vector(1 downto 0);
CLK_SRC_i : in std_logic;
CLK_PERIOD_i : in std_logic_vector(31 downto 0);
FRAME_PERIOD_i : in std_logic_vector(31 downto 0);
ABSENC_BITS_i : in std_logic_vector(7 downto 0);
ABSENC_LSB_DISCARD_i : in std_logic_vector(4 downto 0);
ABSENC_MSB_DISCARD_i : in std_logic_vector(4 downto 0);
ABSENC_STATUS_o : out std_logic_vector(31 downto 0);
ABSENC_HEALTH_o : out std_logic_vector(31 downto 0);
ABSENC_HOMED_o : out std_logic_vector(31 downto 0);
ABSENC_ENABLED_i : in std_logic_vector(31 downto 0);

abs_posn_o : out std_logic_vector(31 downto 0);

PROTOCOL_FOR_ABSENC_i : in std_logic_vector(2 downto 0);
PASSTHROUGH_i : in std_logic;
DATA_IN_i : in std_logic;
CLK_IN_i : in std_logic;
CLK_OUT_o : out std_logic;
clk_out_encoder_biss_o : out std_logic
);
end entity;


architecture rtl of absenc is

signal bits_not_used : unsigned(4 downto 0);
signal posn_ssi : std_logic_vector(31 downto 0);
signal posn_biss : std_logic_vector(31 downto 0);
signal posn_ssi_sniffer : std_logic_vector(31 downto 0);
signal posn_biss_sniffer : std_logic_vector(31 downto 0);
signal posn : std_logic_vector(31 downto 0);

signal ABSENC_PROTOCOL : std_logic_vector(2 downto 0) := "000";
signal linkup_ssi : std_logic;
signal linkup_biss_sniffer : std_logic;
signal health_biss_sniffer : std_logic_vector(31 downto 0);
signal linkup_biss_master : std_logic;
signal health_biss_master : std_logic_vector(31 downto 0);
signal clk_out_encoder_ssi : std_logic;

signal ssi_frame : std_logic;
signal ssi_frame_master : std_logic;
signal ssi_frame_sniffer : std_logic;

begin

abs_ps_select: process(clk_i)
begin
if rising_edge(clk_i) then
if (ABSENC_ENABLED_i = TO_SVECTOR(1,32)) then
-- BITS not begin used
bits_not_used <= 31 - (unsigned(ABSENC_BITS_i(4 downto 0))-1);
lp_test: for i in 31 downto 0 loop
-- Discard bits not being used and MSB and LSB and extend the sign.
-- Note that we need the loop to manipulate the vector. Slicing with \
-- variable indices is not synthesisable.
if (i > 31 - bits_not_used - unsigned(ABSENC_MSB_DISCARD_i) - unsigned(ABSENC_LSB_DISCARD_i)) then
if ((ABSENC_ENCODING_i=c_UNSIGNED_BINARY_ENCODING) or (ABSENC_ENCODING_i=c_UNSIGNED_GRAY_ENCODING)) then
abs_posn_o(i) <= '0';
else
-- sign extension
abs_posn_o(i) <= posn(31 - to_integer(bits_not_used + unsigned(ABSENC_MSB_DISCARD_i)));
end if;
-- Add the LSB_DISCARD on to posn index count and start there
else
abs_posn_o(i) <= posn(i + to_integer(unsigned(ABSENC_LSB_DISCARD_i)));
end if;
end loop lp_test;
else
abs_posn_o <= (others => '0');
end if;
end if;
end process abs_ps_select;

--------------------------------------------------------------------------
-- Position Data and STATUS readback multiplexer
--
-- Link status information is valid only for loopback configuration
--------------------------------------------------------------------------

ABSENC_PROTOCOL <= ABSENC_PROTOCOL_i when (PASSTHROUGH_i = '1')
else PROTOCOL_FOR_ABSENC_i;


process(clk_i)
begin
if rising_edge(clk_i) then
case (ABSENC_PROTOCOL) is
when "000" => -- SSI
if PASSTHROUGH_i = '1' then
posn <= posn_ssi_sniffer;
else -- DCARD_CONTROL
posn <= posn_ssi;
end if;
ABSENC_STATUS_o(0) <= linkup_ssi;
if (linkup_ssi = '0') then
ABSENC_HEALTH_o <= TO_SVECTOR(2,32);
else
ABSENC_HEALTH_o <= (others=>'0');
end if;
ABSENC_HOMED_o <= TO_SVECTOR(1,32);


when "001" => -- BISS & Loopback
-- if (DCARD_MODE_i(3 downto 1) = DCARD_MONITOR) then
if PASSTHROUGH_i = '1' then
posn <= posn_biss_sniffer;
ABSENC_STATUS_o(0) <= linkup_biss_sniffer;
ABSENC_HEALTH_o <= health_biss_sniffer;
else -- DCARD_CONTROL
posn <= posn_biss;
ABSENC_STATUS_o(0) <= linkup_biss_master;
ABSENC_HEALTH_o<=health_biss_master;
end if;
ABSENC_HOMED_o <= TO_SVECTOR(1,32);

when others =>
ABSENC_HEALTH_o <= TO_SVECTOR(5,32);
posn <= (others => '0');
ABSENC_STATUS_o <= (others => '0');
ABSENC_HOMED_o <= TO_SVECTOR(1,32);
end case;
end if;
end process;

--------------------------------------------------------------------------
-- SSI Instantiations
--------------------------------------------------------------------------

-- SSI Master
ssi_master_inst : entity work.ssi_master
port map (
clk_i => clk_i,
reset_i => reset_i,
ENCODING => ABSENC_ENCODING_i,
BITS => ABSENC_BITS_i,
CLK_PERIOD => CLK_PERIOD_i,
FRAME_PERIOD => FRAME_PERIOD_i,
ssi_sck_o => clk_out_encoder_ssi,
ssi_dat_i => DATA_IN_i,
posn_o => posn_ssi,
posn_valid_o => open,
ssi_frame_o => ssi_frame_master
);

-- SSI Sniffer
ssi_sniffer_inst : entity work.ssi_sniffer
port map (
clk_i => clk_i,
reset_i => reset_i,
ENCODING => ABSENC_ENCODING_i,
BITS => ABSENC_BITS_i,
error_o => open,
ssi_sck_i => CLK_IN_i,
ssi_dat_i => DATA_IN_i,
posn_o => posn_ssi_sniffer,
ssi_frame_o => ssi_frame_sniffer
);

ssi_frame <= ssi_frame_sniffer when PASSTHROUGH_i = '1'
else ssi_frame_master;

-- Frame checker for SSI
ssi_err_det_inst: entity work.ssi_error_detect
port map (
clk_i => clk_i,
serial_dat_i => DATA_IN_i,
ssi_frame_i => ssi_frame,
link_up_o => linkup_ssi
);

-- Loopbacks
CLK_OUT_o <= clk_out_ext_i when (CLK_SRC_i = '1') else
clk_out_encoder_biss_o when (CLK_SRC_i = '0' and ABSENC_PROTOCOL_i = "101") else
clk_out_encoder_ssi;

--------------------------------------------------------------------------
-- BiSS Instantiations
--------------------------------------------------------------------------
-- BiSS Master
biss_master_inst : entity work.biss_master
port map (
clk_i => clk_i,
reset_i => reset_i,
ENCODING => ABSENC_ENCODING_i,
BITS => ABSENC_BITS_i,
link_up_o => linkup_biss_master,
health_o => health_biss_master,
CLK_PERIOD => CLK_PERIOD_i,
FRAME_PERIOD => FRAME_PERIOD_i,
biss_sck_o => clk_out_encoder_biss_o,
biss_dat_i => DATA_IN_i,
posn_o => posn_biss,
posn_valid_o => open
);

-- BiSS Sniffer
biss_sniffer_inst : entity work.biss_sniffer
port map (
clk_i => clk_i,
reset_i => reset_i,
ENCODING => ABSENC_ENCODING_i,
BITS => ABSENC_BITS_i,
link_up_o => linkup_biss_sniffer,
health_o => health_biss_sniffer,
error_o => open,
ssi_sck_i => CLK_IN_i,
ssi_dat_i => DATA_IN_i,
posn_o => posn_biss_sniffer
);

end rtl;
148 changes: 148 additions & 0 deletions common/hdl/encoders/incenc.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library work;

entity incenc is
port(
clk_i : in std_logic;
reset_i : in std_logic;

posn_i : in std_logic_vector(31 downto 0);
enable_i : in std_logic;

QPERIOD_i : in std_logic_vector(31 downto 0);
QPERIOD_WSTB_i : in std_logic;
QSTATE_o : out std_logic_vector(31 downto 0);

INCENC_BITS_i : in std_logic_vector(7 downto 0);
LSB_DISCARD_i : in std_logic_vector(4 downto 0);
MSB_DISCARD_i : in std_logic_vector(4 downto 0);
INCENC_PROTOCOL_i : in std_logic_vector(2 downto 0);
SETP_i : in std_logic_vector(31 downto 0);
SETP_WSTB_i : in std_logic;
RST_ON_Z_i : in std_logic_vector(31 downto 0);
STATUS_o : out std_logic_vector(31 downto 0);
INCENC_HEALTH_o : out std_logic_vector(31 downto 0);
HOMED_o : out std_logic_vector(31 downto 0);

A_IN_i : in std_logic;
B_IN_i : in std_logic;
Z_IN_i : in std_logic;
quad_a_o : out std_logic;
quad_b_o : out std_logic;

inc_posn_o : out std_logic_vector(31 downto 0)
);
end entity;


architecture rtl of incenc is

signal A_IN : std_logic;
signal B_IN : std_logic;
signal Z_IN : std_logic;

signal inc_bits_not_used : unsigned(4 downto 0);
signal posn_incr : std_logic_vector(31 downto 0);
signal posn_inc : std_logic_vector(31 downto 0);
signal linkup_incr : std_logic;
signal linkup_incr_std32 : std_logic_vector(31 downto 0);
signal step : std_logic;
signal dir : std_logic;
signal homed_qdec : std_logic_vector(31 downto 0);


begin

ps_select: process(clk_i)
begin
if rising_edge(clk_i) then
-- BITS not begin used
inc_bits_not_used <= 31 - (unsigned(INCENC_BITS_i(4 downto 0))-1);
inc_lp_test: for i in 31 downto 0 loop
-- Discard bits not being used and MSB and LSB and extend the sign.
-- Note that we need the loop to manipulate the vector. Slicing with \
-- variable indices is not synthesisable.
if (i > 31 - inc_bits_not_used - unsigned(MSB_DISCARD_i) - unsigned(LSB_DISCARD_i)) then
inc_posn_o(i) <= '0';
else
inc_posn_o(i) <= posn_inc(i + to_integer(unsigned(LSB_DISCARD_i)));
end if;
end loop inc_lp_test;
end if;
end process ps_select;

--------------------------------------------------------------------------
-- Position Data and STATUS readback multiplexer
--
-- Link status information is valid only for loopback configuration
--------------------------------------------------------------------------
process(clk_i)
begin
if rising_edge(clk_i) then
case (INCENC_PROTOCOL_i) is
when "000" => -- Quadrature
posn_inc <= posn_incr;
STATUS_o(0) <= linkup_incr;
INCENC_HEALTH_o(0) <= not(linkup_incr);
INCENC_HEALTH_o(31 downto 1)<= (others=>'0');
HOMED_o <= homed_qdec;

when "001" => -- Step/Direction
posn_inc <= posn_incr;
STATUS_o(0) <= linkup_incr;
INCENC_HEALTH_o(0) <= not(linkup_incr);
INCENC_HEALTH_o(31 downto 1)<= (others=>'0');
HOMED_o <= homed_qdec;

when others =>
posn_inc <= posn_incr;
STATUS_o(0) <= linkup_incr;
INCENC_HEALTH_o(0) <= not(linkup_incr);
INCENC_HEALTH_o(31 downto 1)<= (others=>'0');
HOMED_o <= homed_qdec;
end case;
end if;
end process;
--------------------------------------------------------------------------
-- Incremental Encoder Instantiation :
--------------------------------------------------------------------------
qdec : entity work.qdec
port map (
clk_i => clk_i,
-- reset_i => reset_i,
LINKUP_INCR => linkup_incr_std32,
a_i => A_IN,
b_i => B_IN,
z_i => Z_IN,
SETP => SETP_i,
SETP_WSTB => SETP_WSTB_i,
RST_ON_Z => RST_ON_Z_i,
HOMED => homed_qdec,
out_o => posn_incr
);

linkup_incr <= '1';
linkup_incr_std32 <= x"0000000"&"000"&linkup_incr;

--
-- INCREMENTAL OUT
--
qenc_inst : entity work.qenc
port map (
clk_i => clk_i,
reset_i => reset_i,
QPERIOD => QPERIOD_i,
QPERIOD_WSTB => QPERIOD_WSTB_i,
QSTATE => QSTATE_o,
enable_i => enable_i,
posn_i => posn_i,
a_o => quad_a_o,
b_o => quad_b_o,
step_o => step,
dir_o => dir
);

end rtl;
Loading

0 comments on commit 5b15630

Please sign in to comment.