Commit 0f5490f0 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

bridge

parent 1204aeca
......@@ -5,4 +5,5 @@ files = [ "vme64x_core.vhd",
"vme_funct_match.vhd",
"vme_irq_controller.vhd",
"vme_user_csr.vhd",
"vme_sfpga_bridge.vhd",
"xvme64x_core.vhd"]
......@@ -134,6 +134,20 @@ package vme64x_pkg is
iackin_n : std_logic;
end record;
constant c_default_vme64x_in : t_vme64x_in := (
as_n => '0',
rst_n => '0',
write_n => '0',
am => "000000",
ds_n => "00",
ga => "000000",
lword_n => '0',
data => x"00000000",
Addr => "0000000000000000000000000000000",
iack_n => '0',
iackin_n => '0'
);
type t_vme64x_out is record
iackout_n : std_logic;
dtack_n : std_logic;
......
This diff is collapsed.
......@@ -116,6 +116,7 @@ entity vme_cr_csr_space is
g_END_USER_CSR : std_logic_vector(23 downto 0);
g_BEG_SN : std_logic_vector(23 downto 0);
g_END_SN : std_logic_vector(23 downto 0);
g_BRIDGED_MODE : boolean;
g_DECODER : t_vme64x_decoder_arr);
port (
clk_i : in std_logic;
......@@ -140,7 +141,13 @@ entity vme_cr_csr_space is
user_cr_addr_o : out std_logic_vector(18 downto 2);
user_cr_data_i : in std_logic_vector( 7 downto 0);
ader_o : out t_ader_array);
ader_o : out t_ader_array;
bridge_aux_valid_i : in std_logic;
bridge_aux_ga_i : in std_logic_vector(4 downto 0)
);
end vme_cr_csr_space;
architecture rtl of vme_cr_csr_space is
......@@ -332,6 +339,10 @@ begin
s_reg_usr_bit_reg <= x"00";
s_reg_ader <= (others => x"00000000");
else
if g_BRIDGED_MODE and bridge_aux_valid_i = '1' then
s_reg_bar <= bridge_aux_ga_i & "000";
end if;
if we_i = '1' and s_csr_access = '1' then
-- FIXME: the SVEC linux driver assume that this bit is just a
-- pulse, and doesn't clear it. Follow this legacy (and incorrect)
......
library ieee;
use ieee.STD_LOGIC_1164.all;
use ieee.NUMERIC_STD.all;
use work.gencores_pkg.all;
use work.vme64x_pkg.all;
library unisim;
use unisim.vcomponents.all;
entity vme_sfpga_bridge is
generic(
g_clock_period : integer
);
port (
afpga_rst_n_i : in std_logic;
afpga_clk_i : in std_logic;
afpga_d_i : in std_logic_vector(7 downto 0);
afpga_frame_i : in std_logic;
afpga_d_o : out std_logic_vector(7 downto 0);
afpga_frame_o : out std_logic;
-- address channel
addr_req_o : out std_logic;
addr_o : out std_logic_vector(31 downto 1);
addr_am_o : out std_logic_vector(5 downto 0);
addr_lword_n_o : out std_logic;
-- data channel (write)
write_req_o : out std_logic;
write_ack_i : in std_logic;
write_ds_n_o : out std_logic_vector(1 downto 0);
write_data_o : out std_logic_vector(63 downto 0);
write_dtack_n_i : in std_logic;
write_berr_i : in std_logic;
write_write_n_o : out std_logic;
-- data channel (read)
read_req_o : out std_logic := '0';
read_ack_i : in std_logic;
read_ds_n_o : out std_logic_vector(1 downto 0);
read_write_n_o : out std_logic;
-- data channel (read/write completion)
cpl_req_i : in std_logic;
cpl_ack_o : out std_logic;
cpl_has_data_i : in std_logic;
cpl_data_i : out std_logic_vector(63 downto 0) := x"0000000000000000";
cpl_dtack_n_i : in std_logic := '0';
cpl_berr_i : in std_logic := '0';
aux_valid_o : out std_logic;
aux_ga_o : out std_logic_vector(5 downto 0);
aux_iackin_n_o : out std_logic;
aux_iack_n_o : out std_logic;
aux_irq_n_i : in std_logic_vector(7 downto 1);
aux_iackout_n_i : in std_logic
-- aux channel
);
end vme_sfpga_bridge;
architecture rtl of vme_sfpga_bridge is
constant c_tag_addr : std_logic_vector(7 downto 0) := x"a0";
constant c_tag_read : std_logic_vector(7 downto 0) := x"a1";
constant c_tag_write : std_logic_vector(7 downto 0) := x"a2";
constant c_tag_read_cpl : std_logic_vector(7 downto 0) := x"a3";
constant c_tag_irq : std_logic_vector(7 downto 0) := x"a4";
constant c_tag_iackin : std_logic_vector(7 downto 0) := x"a5";
constant c_tag_iackout : std_logic_vector(7 downto 0) := x"a6";
constant c_tag_aux : std_logic_vector(7 downto 0) := x"a7";
signal afpga_dout : std_logic_vector(15 downto 0);
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;
type t_rx_state is (IDLE, RX_ADDR0, RX_ADDR1, RX_DATA0, RX_DATA1, RX_DATA2, RX_DATA3);
signal rx_state : t_rx_state;
begin
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 => '0',
D0 => afpga_frame_out,
D1 => afpga_frame_out,
R => '0',
S => '0');
p_in_fsm : process(afpga_clk_i)
begin
if rising_edge(afpga_clk_i) then
if afpga_rst_n_i = '0' then
rx_state <= IDLE;
addr_req_o <= '0';
aux_valid_o <= '0';
else
case rx_state is
when IDLE =>
addr_req_o <= '0';
write_req_o <= '0';
if afpga_frame_in = '1' then
case afpga_din(15 downto 8) is
when c_tag_addr =>
report "[vmebridge] got addr tag";
rx_state <= RX_ADDR0;
addr_am_o <= afpga_din(7 downto 2);
addr_lword_n_o <= afpga_din(0);
when c_tag_aux =>
aux_valid_o <= '1';
aux_ga_o <= afpga_din(5 downto 0);
aux_iack_n_o <= afpga_din(6);
aux_iackin_n_o <= afpga_din(7);
rx_state <= IDLE;
when c_tag_write =>
write_ds_n_o <= afpga_din(1 downto 0);
rx_state <= RX_DATA0;
when others => null;
end case;
end if;
when RX_ADDR0 =>
addr_o (31 downto 16) <= afpga_din;
rx_state <= RX_ADDR1;
when RX_ADDR1 =>
addr_o (15 downto 1) <= afpga_din(15 downto 1);
addr_req_o <= '1';
rx_state <= IDLE;
when RX_DATA0 =>
write_data_o (63 downto 48) <= afpga_din;
rx_state <= RX_DATA1;
when RX_DATA1 =>
write_data_o (47 downto 32) <= afpga_din;
rx_state <= RX_DATA2;
when RX_DATA2 =>
write_data_o (31 downto 16) <= afpga_din;
rx_state <= RX_DATA3;
when RX_DATA3 =>
write_data_o (15 downto 0) <= afpga_din;
rx_state <= IDLE;
write_req_o <= '1';
end case;
end if;
end if;
end process;
end rtl;
......@@ -44,6 +44,10 @@ entity xvme64x_core 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
......@@ -108,13 +112,22 @@ entity xvme64x_core is
rst_n_o : out std_logic;
-- VME slave interface.
vme_i : in t_vme64x_in;
vme_i : in t_vme64x_in := c_default_vme64x_in;
vme_o : out t_vme64x_out;
-- Wishbone interface.
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_frame_o : out std_logic;
bridge_d_o : out std_logic_vector(7 downto 0);
bridge_frame_i : in std_logic := '0';
bridge_d_i : in std_logic_vector(7 downto 0) := x"00";
-- Interrupt input from the master side.
-- Previously it was part of the wishbone interface, but is now separate
-- as interrupt is not defined by wishbone.
......@@ -184,7 +197,7 @@ architecture rtl of xvme64x_core is
signal s_reset_n : std_logic;
signal s_vme_irq_n_o : std_logic_vector( 7 downto 1);
signal s_vme_irq_n : std_logic_vector(7 downto 1);
signal s_irq_ack : std_logic;
signal s_irq_pending : std_logic;
signal s_ga : std_logic_vector( 4 downto 0);
......@@ -224,6 +237,36 @@ architecture rtl of xvme64x_core is
signal s_vme_iack_n : std_logic;
signal s_vme_iackin_n : std_logic;
signal b2b_addr_req : std_logic;
signal b2b_addr : std_logic_vector(31 downto 1);
signal b2b_addr_am : std_logic_vector(5 downto 0);
signal b2b_addr_lword_n : std_logic;
signal b2b_write_req : std_logic;
signal b2b_write_ack : std_logic;
signal b2b_write_ds_n : std_logic_vector(1 downto 0);
signal b2b_write_data : std_logic_vector(63 downto 0);
signal b2b_write_dtack_n : std_logic;
signal b2b_write_berr : std_logic;
signal b2b_write_write_n : std_logic;
signal b2b_read_req : std_logic;
signal b2b_read_ack : std_logic;
signal b2b_read_ds_n : std_logic_vector(1 downto 0);
signal b2b_read_write_n : std_logic;
signal b2b_cpl_data : std_logic_vector(63 downto 0);
signal b2b_cpl_dtack_n : std_logic;
signal b2b_cpl_berr : std_logic;
signal b2b_cpl_req : std_logic;
signal b2b_cpl_ack : std_logic;
signal b2b_cpl_has_data : std_logic;
signal b2b_aux_valid : std_logic;
signal b2b_aux_ga : std_logic_vector(5 downto 0);
signal b2b_aux_irq_n : std_logic_vector(7 downto 1);
signal b2b_aux_iackout_n : std_logic;
-- List of supported AM.
constant c_AMCAP_ALLOWED : std_logic_vector(63 downto 0) :=
(16#38# to 16#3f# => '1', -- A24
......@@ -250,6 +293,13 @@ begin
severity failure;
end generate;
gen_no1 : if g_BRIDGED_MODE = true generate
s_vme_rst_n <= '1';
end generate;
gen1 : if g_BRIDGED_MODE = false generate
------------------------------------------------------------------------------
-- Metastability
------------------------------------------------------------------------------
......@@ -304,17 +354,89 @@ begin
d_i(0) => vme_i.iackin_n,
q_o(0) => s_vme_iackin_n);
end generate gen1;
gen3: if g_BRIDGED_MODE = true generate
bridge_clk_o <= clk_i;
bridge_rst_n_o <= s_reset_n;
inst_sfpga_bridge: entity work.vme_sfpga_bridge
generic map (
g_clock_period => g_clock_period)
port map (
afpga_rst_n_i => s_reset_n,
afpga_clk_i => clk_i,
afpga_d_i => bridge_d_i,
afpga_frame_i => bridge_frame_i,
afpga_d_o => bridge_d_o,
afpga_frame_o => bridge_frame_o,
addr_req_o => b2b_addr_req,
addr_o => b2b_addr,
addr_am_o => b2b_addr_am,
addr_lword_n_o => b2b_addr_lword_n,
write_req_o => b2b_write_req,
write_ack_i => b2b_write_ack,
write_ds_n_o => b2b_write_ds_n,
write_data_o => b2b_write_data,
write_dtack_n_i => b2b_write_dtack_n,
write_berr_i => b2b_write_berr,
read_req_o => b2b_read_req,
read_ack_i => b2b_read_ack,
read_ds_n_o => b2b_read_ds_n,
read_write_n_o => b2b_read_write_n,
cpl_req_i => b2b_cpl_req,
cpl_ack_o => b2b_cpl_ack,
cpl_data_i => b2b_cpl_data,
cpl_has_data_i => b2b_cpl_has_data,
cpl_dtack_n_i => b2b_cpl_dtack_n,
cpl_berr_i => b2b_cpl_berr,
aux_valid_o => b2b_aux_valid,
aux_ga_o => b2b_aux_ga,
aux_irq_n_i => b2b_aux_irq_n,
aux_iackout_n_i => b2b_aux_iackout_n
);
end generate;
------------------------------------------------------------------------------
-- VME Bus
------------------------------------------------------------------------------
inst_vme_bus : entity work.vme_bus
generic map (
g_BRIDGED_MODE => g_BRIDGED_MODE,
g_CLOCK_PERIOD => g_CLOCK_PERIOD,
g_WB_GRANULARITY => g_WB_GRANULARITY)
port map (
clk_i => clk_i,
rst_n_i => s_reset_n,
-- Bridged VME
bridge_addr_req_i => b2b_addr_req,
bridge_addr_i => b2b_addr,
bridge_addr_am_i => b2b_addr_am,
bridge_addr_lword_n_i => b2b_addr_lword_n,
bridge_write_req_i => b2b_write_req,
bridge_write_ack_o => b2b_write_ack,
bridge_write_ds_n_i => b2b_write_ds_n,
bridge_write_data_i => b2b_write_data,
bridge_write_write_n_i => b2b_write_write_n,
bridge_read_req_i => b2b_read_req,
bridge_read_ack_o => b2b_read_ack,
bridge_read_ds_n_i => b2b_read_ds_n,
bridge_read_write_n_i => b2b_read_write_n,
bridge_cpl_req_o => b2b_cpl_req,
bridge_cpl_ack_i => b2b_cpl_ack,
bridge_cpl_data_o => b2b_cpl_data,
bridge_cpl_has_data_o => b2b_cpl_has_data,
bridge_cpl_dtack_n_o => b2b_cpl_dtack_n,
bridge_cpl_berr_o => b2b_cpl_berr,
-- VME
vme_as_n_i => s_vme_as_n,
vme_lword_n_o => vme_o.lword_n,
......@@ -375,7 +497,6 @@ begin
s_reset_n <= rst_n_i and s_vme_rst_n;
rst_n_o <= s_reset_n and (not s_module_reset);
vme_o.berr_n <= s_vme_berr_n;
inst_vme_funct_match : entity work.vme_funct_match
generic map (
......@@ -414,7 +535,7 @@ begin
int_req_i => int_i,
irq_pending_o => s_irq_pending,
irq_ack_i => s_irq_ack,
vme_irq_n_o => vme_o.irq_n
vme_irq_n_o => s_vme_irq_n
);
------------------------------------------------------------------------------
......@@ -423,9 +544,29 @@ begin
s_ga_parity <= vme_i.ga(5) xor vme_i.ga(4) xor vme_i.ga(3) xor
vme_i.ga(2) xor vme_i.ga(1) xor vme_i.ga(0);
-- ANSI/VITA 1.1-1997 Recommendation 3.8: set the "amnesia address"
-- of 0x1E if bad parity.
s_ga <= not vme_i.ga(4 downto 0) when s_ga_parity = '1' else '1' & x"e";
gen_no_bridge_mode : if g_BRIDGED_MODE = false generate
-- ANSI/VITA 1.1-1997 Recommendation 3.8: set the "amnesia address"
-- of 0x1E if bad parity.
s_ga <= not vme_i.ga(4 downto 0) when s_ga_parity = '1' else '1' & x"e";
vme_o.irq_n <= s_vme_irq_n;
vme_o.berr_n <= s_vme_berr_n;
end generate gen_no_bridge_mode;
gen_bridge_mode : if g_BRIDGED_MODE = true generate
-- handle ga and irq_n
process(clk_i)
begin
if rising_edge(clk_i) then
if b2b_aux_valid = '1' then
s_ga <= not b2b_aux_ga(4 downto 0);
end if;
end if;
end process;
end generate gen_bridge_mode;
------------------------------------------------------------------------------
-- CR/CSR space
......@@ -446,7 +587,8 @@ begin
g_END_USER_CSR => g_END_USER_CSR,
g_BEG_SN => g_BEG_SN,
g_END_SN => g_END_SN,
g_DECODER => g_DECODER
g_DECODER => g_DECODER,
g_BRIDGED_MODE => g_BRIDGED_MODE
)
port map (
clk_i => clk_i,
......@@ -471,7 +613,10 @@ begin
user_cr_addr_o => user_cr_addr_o,
user_cr_data_i => user_cr_data_i,
ader_o => s_ader
ader_o => s_ader,
bridge_aux_valid_i => b2b_aux_valid,
bridge_aux_ga_i => s_ga
);
-- User CSR space
......
......@@ -7,7 +7,10 @@
`define assert_wait(name, condition, timeout) \
begin\
time t=$time;\
time t=$time; logic cond=condition;\
$display("Cond: %b %d", cond, cond != 1'bx );\
if ( (condition) != 1'b1 && (condition) != 1'b0 )\
$error ("DTACK or BERR in undefined state!");\
while(!(condition)) begin\
#1ns;\
if($time - t > timeout) begin\
......@@ -286,6 +289,9 @@ class CBusAccessor_VME64x extends CBusAccessor;
a_out = { a[31:2], 2'b00};
endcase // case (xtype)
$display("SetAaddr: %x", a_out[31:2]);
vme.q_addr[31:2] = a_out[31:2];
endtask // set_address
......
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