Commit 2460adc3 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

serial bridge: initial working version

parent 6f359655
files = [ "vme64x_core.vhd",
"xvme64x_core_master.vhd",
"xvme64x_core_slave.vhd",
"vme64x_pkg.vhd",
"vme_bus.vhd",
"vme_bus_bridge.vhd",
"vme_cr_csr_space.vhd",
"vme_funct_match.vhd",
"vme_irq_controller.vhd",
"vme_user_csr.vhd",
"bridge_master.vhd",
"bridge_slave.vhd"
# "xvme64x_core.vhd"
]
files = ["serial_bridge_master.vhd",
"serial_bridge_slave.vhd",
"vme64x_core.vhd",
"vme64x_pkg.vhd",
"vme_bus_bridge.vhd",
"vme_bus.vhd",
"vme_cr_csr_space.vhd",
"vme_funct_match.vhd",
"vme_irq_controller.vhd",
"vme_user_csr.vhd",
"xvme64x_bridge_serdes.vhd",
"xvme64x_core_master.vhd",
"xvme64x_core_slave.vhd",
"xvme64x_core.vhd"];
......@@ -8,7 +8,7 @@ use work.vme64x_pkg.all;
library unisim;
use unisim.vcomponents.all;
entity bridge_master is
entity serial_bridge_master is
generic(
g_clock_period : integer
);
......@@ -17,9 +17,9 @@ entity bridge_master is
afpga_rst_n_i : in std_logic;
afpga_clk_i : in std_logic;
afpga_d_i : in std_logic_vector(7 downto 0);
afpga_d_i : in std_logic_vector(15 downto 0);
afpga_frame_i : in std_logic;
afpga_d_o : out std_logic_vector(7 downto 0);
afpga_d_o : out std_logic_vector(15 downto 0);
afpga_frame_o : out std_logic;
vme_berr_n_i : in std_logic;
......@@ -63,9 +63,9 @@ entity bridge_master is
irq_ack_i : in std_logic
);
end bridge_master;
end serial_bridge_master;
architecture rtl of bridge_master is
architecture rtl of serial_bridge_master is
constant c_tag_csr_req : std_logic_vector(3 downto 0) := x"0";
constant c_tag_csr_rsp : std_logic_vector(3 downto 0) := x"1";
......@@ -82,7 +82,6 @@ architecture rtl of bridge_master is
signal afpga_din : std_logic_vector(15 downto 0);
signal afpga_frame_out : std_logic;
signal afpga_frame_in : std_logic;
signal afpga_clk_n : std_logic;
signal mem_ack_int : std_logic;
......@@ -123,66 +122,13 @@ architecture rtl of bridge_master is
begin
mem_ack_o <= mem_ack_int;
afpga_clk_n <= not afpga_clk_i;
gen_ddr_ios : for i in 0 to 7 generate
U_ODDR_Data : ODDR2
generic map (
DDR_ALIGNMENT => "C0")
port map (
Q => afpga_d_o(i),
C0 => afpga_clk_i,
C1 => afpga_clk_n,
CE => '1',
D0 => afpga_dout(2*i),
D1 => afpga_dout(2*i+1),
R => '0',
S => '0');
U_IDDR_Data : IDDR2
generic map (
DDR_ALIGNMENT => "C0")
port map (
Q0 => afpga_din(2*i+1),
Q1 => afpga_din(2*i),
C0 => afpga_clk_i,
C1 => afpga_clk_n,
CE => '1',
D => afpga_d_i(i),
R => '0',
S => '0');
end generate gen_ddr_ios;
U_IDDR_Frame : IDDR2
generic map (
DDR_ALIGNMENT => "C0")
port map (
Q0 => afpga_frame_in,
Q1 => open,
C0 => afpga_clk_i,
C1 => afpga_clk_n,
CE => '1',
D => afpga_frame_i,
R => '0',
S => '0');
U_ODDR_Frame : ODDR2
generic map (
DDR_ALIGNMENT => "C0")
port map (
Q => afpga_frame_o,
C0 => afpga_clk_i,
C1 => afpga_clk_n,
CE => '1',
D0 => afpga_frame_out,
D1 => afpga_frame_out,
R => '0',
S => '0');
afpga_d_o <= afpga_dout;
afpga_frame_o <= afpga_frame_out;
afpga_frame_in <= afpga_frame_i;
afpga_din <= afpga_d_i;
p_in_fsm : process(afpga_clk_i)
begin
if rising_edge(afpga_clk_i) then
......
......@@ -34,7 +34,7 @@ use work.wishbone_pkg.all;
library unisim;
use unisim.vcomponents.all;
entity bridge_slave is
entity serial_bridge_slave is
generic (
g_CLOCK_PERIOD : integer
);
......@@ -43,9 +43,9 @@ entity bridge_slave is
sfpga_rst_n_i : in std_logic;
sfpga_clk_i : in std_logic;
sfpga_d_i : in std_logic_vector(7 downto 0);
sfpga_d_i : in std_logic_vector(15 downto 0);
sfpga_frame_i : in std_logic;
sfpga_d_o : out std_logic_vector(7 downto 0);
sfpga_d_o : out std_logic_vector(15 downto 0);
sfpga_frame_o : out std_logic;
vme_aux_valid_o : out std_logic;
......@@ -93,9 +93,9 @@ entity bridge_slave is
irq_pending_i : in std_logic;
irq_ack_o : out std_logic
);
end bridge_slave;
end serial_bridge_slave;
architecture rtl of bridge_slave is
architecture rtl of serial_bridge_slave is
constant c_tag_csr_req : std_logic_vector(3 downto 0) := x"0";
constant c_tag_csr_rsp : std_logic_vector(3 downto 0) := x"1";
......@@ -116,6 +116,8 @@ architecture rtl of bridge_slave is
signal cr_csr_write : std_logic;
signal addr_decoder_reg : std_logic_vector(31 downto 1);
type t_rx_state is
(
IDLE,
......@@ -148,87 +150,13 @@ architecture rtl of bridge_slave is
begin
sfpga_clk_n <= not sfpga_clk_i;
gen_ddr_ios : for i in 0 to 7 generate
U_ODDR_Data : ODDR2
generic map (
DDR_ALIGNMENT => "C0")
port map (
Q => sfpga_d_o(i),
C0 => sfpga_clk_i,
C1 => sfpga_clk_n,
CE => '1',
D0 => sfpga_dout(2*i),
D1 => sfpga_dout(2*i+1),
R => '0',
S => '0');
U_IDDR_Data : IDDR2
generic map (
DDR_ALIGNMENT => "C0")
port map (
Q0 => sfpga_din(2*i+1),
Q1 => sfpga_din(2*i),
C0 => sfpga_clk_i,
C1 => sfpga_clk_n,
CE => '1',
D => sfpga_d_i(i),
R => '0',
S => '0');
end generate gen_ddr_ios;
U_IDDR_Frame : IDDR2
generic map (
DDR_ALIGNMENT => "C0")
port map (
Q0 => sfpga_frame_in,
Q1 => open,
C0 => sfpga_clk_i,
C1 => sfpga_clk_n,
CE => '1',
D => sfpga_frame_i,
R => '0',
S => '0');
U_ODDR_Frame : ODDR2
generic map (
DDR_ALIGNMENT => "C0")
port map (
Q => sfpga_frame_o,
C0 => sfpga_clk_i,
C1 => sfpga_clk_n,
CE => '1',
D0 => sfpga_frame_out,
D1 => sfpga_frame_out,
R => '0',
S => '0');
sfpga_frame_in <= sfpga_frame_i;
sfpga_din <= sfpga_d_i;
-- if decode_start_i = '1' then
-- afpga_frame_out <= '1';
-- afpga_dout <= c_tag_decode_req & am_i & "000000";
-- tx_state <= TX_DECODE_REQ0;
-- end if;
-- when TX_CSR_REQ =>
-- afpga_frame_out <= '0';
-- afpga_dout <= cr_csr_addr_i(4 downto 0) & "000" & cr_csr_data_i;
-- tx_state <= RX_CSR_ACK;
-- when RX_CSR_ACK =>
-- if afpga_frame_in = '1' and afpga_din(15 downto 12) = c_tag_csr_rsp then
-- cr_csr_done_o <= '1';
-- cr_csr_data_o <= afpga_din(7 downto 0);
-- tx_state <= IDLE;
-- end if;
sfpga_frame_o <= sfpga_frame_out;
sfpga_d_o <= sfpga_dout;
p_in_fsm : process(sfpga_clk_i)
variable send_cfg : boolean := false;
begin
......@@ -241,6 +169,9 @@ begin
cr_csr_req_o <= '0';
cr_csr_we_o <= '0';
mem_req_o <= '0';
sfpga_dout <= (others => '0');
sfpga_frame_out <= '0';
else
......@@ -409,16 +340,17 @@ begin
sfpga_dout(15 downto 12) <= c_tag_decode_rsp;
sfpga_dout(11) <= decode_sel_i;
rx_state <= TX_DECODE_RSP1;
addr_decoder_reg <= addr_decoder_i;
end if;
when TX_DECODE_RSP1 =>
sfpga_frame_out <= '0';
sfpga_dout <= addr_decoder_i(31 downto 16);
sfpga_dout <= addr_decoder_reg(31 downto 16);
rx_state <= TX_DECODE_RSP2;
when TX_DECODE_RSP2 =>
sfpga_frame_out <= '0';
sfpga_dout(15 downto 1) <= addr_decoder_i(15 downto 1);
sfpga_dout(15 downto 1) <= addr_decoder_reg(15 downto 1);
rx_state <= IDLE;
......
......@@ -43,6 +43,8 @@ package vme64x_pkg is
-- Constants
------------------------------------------------------------------------------
type t_BRIDGE_SERDES_MODE is ( MASTER, SLAVE );
-- Manufactuer IDs.
constant c_CERN_ID : std_logic_vector(23 downto 0) := x"080030";
......
This diff is collapsed.
......@@ -8,8 +8,8 @@
--
-- description:
--
-- This block acts as interface between the VMEbus and the CR/CSR space or
-- WB bus.
-- Slighthtly hacked version of the vme_bus module for the purpose of testing
-- the inter-fpga VME serial bridge.
--
--------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE
......
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.vme64x_pkg.all;
library unisim;
use unisim.vcomponents.all;
entity xvme64x_bridge_serdes is
generic (
g_mode : t_bridge_serdes_mode := MASTER;
g_platform : string := "spartan6";
g_SERDES_RX_DELAY_TAPS : integer:= 0;
g_CLOCK_PERIOD : integer := 16
);
port (
clk_125m_i : in std_logic := '0';
rst_n_i : in std_logic := '0';
bridge_d_i : in std_logic_vector(15 downto 0);
bridge_frame_i : in std_logic;
bridge_d_o : out std_logic_vector(15 downto 0);
bridge_frame_o : out std_logic;
bridge_clk_o : out std_logic;
bridge_rst_n_o : out std_logic;
ser_clk_p_i : in std_logic := '0';
ser_clk_n_i : in std_logic := '0';
ser_clk_p_o : out std_logic;
ser_clk_n_o : out std_logic;
ser_tx_o : out std_logic_vector(4 downto 0);
ser_rx_i : in std_logic_vector(4 downto 0)
);
end xvme64x_bridge_serdes;
architecture rtl of xvme64x_bridge_serdes is
signal ser_clk_buf : std_logic;
signal clk_125m_0 : std_logic;
signal clk_500m_0 : std_logic;
signal pllout_clk_fb : std_logic;
signal pllout_clk_125m_0 : std_logic;
signal clk_500m_serdes : std_logic;
signal serdes_strobe : std_logic;
signal pll_locked : std_logic;
type t_serdes_par_data is array(0 to 4) of std_logic_vector(3 downto 0);
signal ser_rx_predelay, ser_rx_postdelay : std_logic_vector(4 downto 0);
signal ser_tx_predelay, ser_tx_postdelay : std_logic_vector(4 downto 0);
signal par_rx, par_tx : t_serdes_par_data;
signal io_reset : std_logic;
signal ser_clk_out_prebuf : std_logic;
signal serdes_rx_bitslip : std_logic;
signal BITSLIP_cnt : unsigned(3 downto 0);
begin
io_reset <= not rst_n_i;
gen1 : if g_mode = MASTER generate
U_clk_buf : IBUFGDS
generic map (
DIFF_TERM => TRUE
)
port map (
O => ser_clk_buf,
I => ser_clk_p_i,
IB => ser_clk_n_i
);
bridge_clk_o <= ser_clk_buf;
bridge_rst_n_o <= rst_n_i;
end generate gen1;
gen2 : if g_mode /= MASTER generate
ser_clk_buf <= clk_125m_i;
end generate gen2;
-- PLL for producing 125 MHz App clock
U_App_clk_pll : PLL_BASE
generic map (
BANDWIDTH => "OPTIMIZED",
CLK_FEEDBACK => "CLKFBOUT",
COMPENSATION => "INTERNAL",
DIVCLK_DIVIDE => 1,
CLKFBOUT_MULT => 8,
CLKFBOUT_PHASE => 0.000,
CLKOUT0_DIVIDE => 2, -- 500 MHz (IOSERDES)
CLKOUT0_PHASE => 0.000,
CLKOUT0_DUTY_CYCLE => 0.500,
CLKOUT1_DIVIDE => 8, -- 125 MHz
CLKOUT1_PHASE => 0.000,
CLKOUT1_DUTY_CYCLE => 0.500,
CLKOUT2_DIVIDE => 8,
CLKOUT2_PHASE => 180.000, -- 125 MHz (180 deg)
CLKOUT2_DUTY_CYCLE => 0.500,
CLKIN_PERIOD => 8.0,
REF_JITTER => 0.016)
port map (
CLKFBOUT => pllout_clk_fb,
CLKOUT0 => clk_500m_0,
CLKOUT1 => pllout_clk_125m_0,
CLKOUT2 => open, --pllout_clk_sys,
CLKOUT3 => open,
CLKOUT4 => open,
CLKOUT5 => open,
LOCKED => pll_locked,
RST => '0',
CLKFBIN => pllout_clk_fb,
CLKIN => ser_clk_buf);
U_clk_0_buf : BUFG
port map (
O => clk_125m_0,
I => pllout_clk_125m_0);
U_BufPLL : BUFPLL
generic map (
DIVIDE => 4
)
port map (
PLLIN => clk_500m_0,
LOCKED => pll_locked,
GCLK => clk_125m_0,
SERDESSTROBE => serdes_strobe,
IOCLK => clk_500m_serdes,
LOCK => open
);
gen_serdeses : for i in 0 to 4 generate
cmp_ibuf : IBUF
generic map (
IOSTANDARD => "LVCMOS33")
port map (
I => ser_rx_i(i),
O => ser_rx_predelay(i));
cmp_obuf : OBUF
generic map (
IOSTANDARD => "LVCMOS33")
port map (
O => ser_tx_o(i),
I => ser_tx_postdelay(i));
-- Instantiate the delay primitive
-----------------------------------
cmp_iodelay : IODELAY2
generic map (
DATA_RATE => "SDR",
IDELAY_VALUE => g_SERDES_RX_DELAY_TAPS,
IDELAY_TYPE => "FIXED",
COUNTER_WRAPAROUND => "STAY_AT_LIMIT",
DELAY_SRC => "IDATAIN",
SERDES_MODE => "NONE",
SIM_TAPDELAY_VALUE => 75)
port map (
-- required datapath
IDATAIN => ser_rx_predelay(i),
DATAOUT => ser_rx_postdelay(i),
T => '1',
-- inactive data connections
DATAOUT2 => open,
DOUT => open,
ODATAIN => '0',
TOUT => open,
-- connect up the clocks
IOCLK0 => '0', -- No calibration needed
IOCLK1 => '0', -- No calibration needed
-- Tie of the variable delay programming
CLK => '0',
CAL => '0',
INC => '0',
CE => '0',
BUSY => open,
RST => '0');
cmp_iserdes : ISERDES2
generic map (
DATA_RATE => "SDR",
DATA_WIDTH => 4,
INTERFACE_TYPE => "RETIMED",
SERDES_MODE => "NONE",
BITSLIP_ENABLE => true)
port map (
Q1 => par_rx(i)(3),
Q2 => par_rx(i)(2),
Q3 => par_rx(i)(1),
Q4 => par_rx(i)(0),
SHIFTOUT => open,
INCDEC => open,
VALID => open,
BITSLIP => serdes_rx_bitslip,
CE0 => '1',
CLK0 => clk_500m_serdes,
CLK1 => '0',
CLKDIV => clk_125m_0,
D => ser_rx_postdelay(i),
IOCE => serdes_strobe,
RST => io_reset,
SHIFTIN => '0' );
cmp_oserdes : OSERDES2
generic map (
DATA_RATE_OQ => "SDR",
DATA_RATE_OT => "SDR",
TRAIN_PATTERN => 0,
DATA_WIDTH => 4,
SERDES_MODE => "NONE",
OUTPUT_MODE => "SINGLE_ENDED")
port map (
D1 => par_tx(i)(3),
D2 => par_tx(i)(2),
D3 => par_tx(i)(1),
D4 => par_tx(i)(0),
T1 => '0',
T2 => '0',
T3 => '0',
T4 => '0',
SHIFTIN1 => '1',
SHIFTIN2 => '1',
SHIFTIN3 => '1',
SHIFTIN4 => '1',
SHIFTOUT1 => open,
SHIFTOUT2 => open,
SHIFTOUT3 => open,
SHIFTOUT4 => open,
TRAIN => '0',
OCE => '1',
CLK0 => clk_500m_serdes,
CLK1 => '0',
CLKDIV => clk_125m_0,
OQ => ser_tx_postdelay(i),
TQ => open,
IOCE => serdes_strobe,
TCE => '1',
RST => IO_RESET);
end generate gen_serdeses;
gen3: if g_mode = SLAVE generate
cmp_oserdes_clk : OSERDES2
generic map (
DATA_RATE_OQ => "SDR",
DATA_RATE_OT => "SDR",
TRAIN_PATTERN => 0,
DATA_WIDTH => 4,
SERDES_MODE => "NONE",
OUTPUT_MODE => "SINGLE_ENDED")
port map (
D1 => '0',
D2 => '0',
D3 => '1',
D4 => '1',
T1 => '0',
T2 => '0',
T3 => '0',
T4 => '0',
SHIFTIN1 => '1',
SHIFTIN2 => '1',
SHIFTIN3 => '1',
SHIFTIN4 => '1',
SHIFTOUT1 => open,
SHIFTOUT2 => open,
SHIFTOUT3 => open,
SHIFTOUT4 => open,
TRAIN => '0',
OCE => '1',
CLK0 => clk_500m_serdes,
CLK1 => '0',
CLKDIV => clk_125m_0,
OQ => ser_clk_out_prebuf,
TQ => open,
IOCE => serdes_strobe,
TCE => '1',
RST => IO_RESET);
OBUFDS_clk: OBUFDS
generic map (
IOSTANDARD => "DEFAULT",
SLEW => "FAST")
port map (
O => ser_clk_p_o,
OB => ser_clk_n_o,
I => ser_clk_out_prebuf);
end generate gen3;
gen_serdes_data : for i in 0 to 3 generate
par_tx(i)(0) <= bridge_d_i(i*4+0);
par_tx(i)(1) <= bridge_d_i(i*4+1);
par_tx(i)(2) <= bridge_d_i(i*4+2);
par_tx(i)(3) <= bridge_d_i(i*4+3);
bridge_d_o(i*4+0) <= par_rx(i)(0);
bridge_d_o(i*4+1) <= par_rx(i)(1);
bridge_d_o(i*4+2) <= par_rx(i)(2);
bridge_d_o(i*4+3) <= par_rx(i)(3);
bridge_frame_o <= par_rx(4)(0);
par_tx(4)(0) <= bridge_frame_i;
par_tx(4)(1) <= '0';
par_tx(4)(2) <= '0';
par_tx(4)(3) <= '0';
end generate gen_serdes_data;
p_serdes_bitslip : process(clk_125m_0, rst_n_i)
begin
if rst_n_i = '0' then
BITSLIP_cnt <= (others => '0');
serdes_rx_bitslip <= '0';
elsif rising_edge(clk_125m_0) then
if BITSLIP_cnt = 0 then
if par_rx(4) /= "0000" and par_rx(4) /= "0001" then
serdes_rx_bitslip <= '1';
BITSLIP_cnt <= to_unsigned(10, 4);
end if;
else
serdes_rx_bitslip <= '0';
BITSLIP_cnt <= BITSLIP_cnt - 1;
end if;
end if;
end process;
end rtl;
......@@ -53,9 +53,9 @@ entity xvme64x_core_master is
afpga_clk_i : in std_logic;
afpga_rst_n_i : in std_logic;
afpga_d_i : in std_logic_vector(7 downto 0);
afpga_d_i : in std_logic_vector(15 downto 0);
afpga_frame_i : in std_logic;
afpga_d_o : out std_logic_vector(7 downto 0);
afpga_d_o : out std_logic_vector(15 downto 0);
afpga_frame_o : out std_logic
);
......@@ -263,7 +263,7 @@ begin
s_ga <= not vme_i.ga(4 downto 0) when s_ga_parity = '1' else '1' & x"e";
bridge_master_1: entity work.bridge_master
inst_serial_bridge: entity work.serial_bridge_master
generic map (
g_clock_period => g_clock_period)
port map (
......
......@@ -44,10 +44,6 @@ entity xvme64x_core_slave is
-- Clock period (ns). Used for DS synchronization. A value is required.
g_CLOCK_PERIOD : natural;
-- Enables 'bridged' mode - with reduced pin count interface (bridge_xxx ports)
-- and an external system FPGA acting as a VME I/O expander.
g_BRIDGED_MODE : boolean := false;
-- Consider AM field of ADER to decode addresses. This is what the VME64x
-- standard says. However, for compatibility with previous implementations
-- (or to reduce resources), it is possible for a decoder to allow all AM
......@@ -115,14 +111,11 @@ entity xvme64x_core_slave is
wb_i : in t_wishbone_master_in;
wb_o : out t_wishbone_master_out;
-- Bridge I/F
bridge_clk_o : out std_logic;
bridge_rst_n_o : out std_logic;
-- Bridge I/F to the SerDes
bridge_frame_o : out std_logic;
bridge_d_o : out std_logic_vector(7 downto 0);
bridge_d_o : out std_logic_vector(15 downto 0);
bridge_frame_i : in std_logic := '0';
bridge_d_i : in std_logic_vector(7 downto 0) := x"00";
bridge_d_i : in std_logic_vector(15 downto 0) := x"0000";
-- Interrupt input from the master side.
-- Previously it was part of the wishbone interface, but is now separate
......@@ -274,18 +267,17 @@ begin
severity failure;
end generate;
bridge_clk_o <= clk_i;
bridge_rst_n_o <= rst_n_i;
s_reset_n <= rst_n_i;
bridge_slave_1: entity work.bridge_slave
inst_serial_bridge : entity work.serial_bridge_slave
generic map (
g_CLOCK_PERIOD => g_CLOCK_PERIOD)
port map (
sfpga_rst_n_i => rst_n_i,
sfpga_clk_i => clk_i,
sfpga_d_i => bridge_d_i,
sfpga_frame_i => bridge_frame_i,
sfpga_d_o => bridge_d_o,
......
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