Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • project/vme64x-core
  • msaccani/vme64x-core-msaccani
2 results
Show changes
Commits on Source (19)
---
# SPDX-FileCopyrightText: 2024 CERN (home.cern)
#
# SPDX-License-Identifier: BSD-3-Clause
version: '1.0.0'
name: 'VME64x core'
description: 'https://ohwr.org/project/vme64x-core/wikis/home'
website: 'https://ohwr.org/project/vme64x-core'
images:
- 'https://ohwr.org/project/vme64x-core/uploads/c9c5d9563f3db625faa7bc2d4ab10051/VME64x_BlockDiagram2.png'
documentation: 'https://ohwr.org/project/vme64x-core/wikis'
issues: 'https://ohwr.org/project/vme64x-core/issues'
newsfeed: 'https://ohwr.org/project/vme64x-core/wikis/news'
forum: 'https://forums.ohwr.org/c/vme64x-core'
...@@ -5,4 +5,5 @@ files = [ "vme64x_core.vhd", ...@@ -5,4 +5,5 @@ files = [ "vme64x_core.vhd",
"vme_funct_match.vhd", "vme_funct_match.vhd",
"vme_irq_controller.vhd", "vme_irq_controller.vhd",
"vme_user_csr.vhd", "vme_user_csr.vhd",
"xvme64x_core.vhd"] "xvme64x_core.vhd",
"vme64x_core_verilog.vhd"]
...@@ -17,6 +17,7 @@ entity vme64x_core is ...@@ -17,6 +17,7 @@ entity vme64x_core is
g_USER_CSR_EXT : boolean := false; g_USER_CSR_EXT : boolean := false;
g_VME32 : boolean := true; g_VME32 : boolean := true;
g_VME_2e : boolean := False; g_VME_2e : boolean := False;
g_ASYNC_DTACK : boolean := False;
g_WB_GRANULARITY : t_wishbone_address_granularity; g_WB_GRANULARITY : t_wishbone_address_granularity;
g_MANUFACTURER_ID : std_logic_vector(23 downto 0); g_MANUFACTURER_ID : std_logic_vector(23 downto 0);
g_BOARD_ID : std_logic_vector(31 downto 0); g_BOARD_ID : std_logic_vector(31 downto 0);
...@@ -119,6 +120,7 @@ begin ...@@ -119,6 +120,7 @@ begin
g_WB_GRANULARITY => g_WB_GRANULARITY, g_WB_GRANULARITY => g_WB_GRANULARITY,
g_WB_MODE => CLASSIC, g_WB_MODE => CLASSIC,
g_VME_2e => g_VME_2e, g_VME_2e => g_VME_2e,
g_ASYNC_DTACK => g_ASYNC_DTACK,
g_MANUFACTURER_ID => g_MANUFACTURER_ID, g_MANUFACTURER_ID => g_MANUFACTURER_ID,
g_BOARD_ID => g_BOARD_ID, g_BOARD_ID => g_BOARD_ID,
g_REVISION_ID => g_REVISION_ID, g_REVISION_ID => g_REVISION_ID,
......
...@@ -22,6 +22,7 @@ entity vme64x_core_verilog is ...@@ -22,6 +22,7 @@ entity vme64x_core_verilog is
g_USER_CSR_EXT : natural := 0; g_USER_CSR_EXT : natural := 0;
g_VME32 : natural := 1; g_VME32 : natural := 1;
g_VME_2e : natural := 0; g_VME_2e : natural := 0;
g_ASYNC_DTACK : natural := 0;
g_WB_GRANULARITY : string(1 to 4); g_WB_GRANULARITY : string(1 to 4);
g_MANUFACTURER_ID : std_logic_vector(23 downto 0); g_MANUFACTURER_ID : std_logic_vector(23 downto 0);
g_BOARD_ID : std_logic_vector(31 downto 0); g_BOARD_ID : std_logic_vector(31 downto 0);
...@@ -143,6 +144,7 @@ begin ...@@ -143,6 +144,7 @@ begin
g_USER_CSR_EXT => nat_to_bool(g_USER_CSR_EXT), g_USER_CSR_EXT => nat_to_bool(g_USER_CSR_EXT),
g_VME32 => nat_to_bool(g_VME32), g_VME32 => nat_to_bool(g_VME32),
g_VME_2e => nat_to_bool(g_VME_2e), g_VME_2e => nat_to_bool(g_VME_2e),
g_ASYNC_DTACK => nat_to_bool(g_ASYNC_DTACK),
g_WB_GRANULARITY => string_to_wb_grn(g_WB_GRANULARITY), g_WB_GRANULARITY => string_to_wb_grn(g_WB_GRANULARITY),
g_MANUFACTURER_ID => g_MANUFACTURER_ID, g_MANUFACTURER_ID => g_MANUFACTURER_ID,
g_BOARD_ID => g_BOARD_ID, g_BOARD_ID => g_BOARD_ID,
......
...@@ -185,6 +185,21 @@ package vme64x_pkg is ...@@ -185,6 +185,21 @@ package vme64x_pkg is
dawpr => x"84"), dawpr => x"84"),
others => c_vme64x_decoder_disabled); others => c_vme64x_decoder_disabled);
type t_vme_tga is record
-- Address modifier
am : std_logic_vector(5 downto 0);
-- Transfer width: 00: byte, 01: word(16b), 10: long-word(32b), 11: MBLT
wd : std_logic_vector(1 downto 0);
-- If set, do not release the bus (rmw or dma).
keep_bus : std_logic;
-- Special cycles
iack : std_logic;
ado : std_logic;
end record;
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- Components declaration -- Components declaration
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
......
...@@ -37,6 +37,7 @@ entity vme_bus is ...@@ -37,6 +37,7 @@ entity vme_bus is
g_CLOCK_PERIOD : integer; g_CLOCK_PERIOD : integer;
g_VME32 : boolean; g_VME32 : boolean;
g_VME_2E : boolean; g_VME_2E : boolean;
g_ASYNC_DTACK : boolean;
g_WB_GRANULARITY : t_wishbone_address_granularity; g_WB_GRANULARITY : t_wishbone_address_granularity;
g_WB_MODE : t_wishbone_interface_mode g_WB_MODE : t_wishbone_interface_mode
); );
...@@ -49,12 +50,12 @@ entity vme_bus is ...@@ -49,12 +50,12 @@ entity vme_bus is
vme_lword_n_o : out std_logic := '0'; vme_lword_n_o : out std_logic := '0';
vme_lword_n_i : in std_logic; vme_lword_n_i : in std_logic;
vme_retry_n_o : out std_logic; vme_retry_n_o : out std_logic;
vme_retry_oe_o : out std_logic; vme_retry_oe_n_o : out std_logic;
vme_write_n_i : in std_logic; vme_write_n_i : in std_logic;
vme_ds_n_i : in std_logic_vector(1 downto 0); vme_ds_n_i : in std_logic_vector(1 downto 0);
vme_nsync_ds_n_i : in std_logic_vector(1 downto 0); -- Not synch. vme_nsync_ds_n_i : in std_logic_vector(1 downto 0); -- Not synch.
vme_dtack_n_o : out std_logic; vme_dtack_n_o : out std_logic;
vme_dtack_oe_o : out std_logic; vme_dtack_oe_n_o : out std_logic;
vme_berr_n_o : out std_logic; vme_berr_n_o : out std_logic;
vme_addr_i : in std_logic_vector(31 downto 1); vme_addr_i : in std_logic_vector(31 downto 1);
vme_addr_o : out std_logic_vector(31 downto 1) := (others => '0'); vme_addr_o : out std_logic_vector(31 downto 1) := (others => '0');
...@@ -112,6 +113,9 @@ entity vme_bus is ...@@ -112,6 +113,9 @@ entity vme_bus is
irq_pending_i : in std_logic; irq_pending_i : in std_logic;
irq_ack_o : out std_logic; irq_ack_o : out std_logic;
-- Disable slave
slave_dis_i : in std_logic := '0';
--Card selection --Card selection
card_sel_o : out std_logic card_sel_o : out std_logic
); );
...@@ -138,10 +142,11 @@ architecture rtl of vme_bus is ...@@ -138,10 +142,11 @@ architecture rtl of vme_bus is
signal vme_odff_data_dir : std_logic; signal vme_odff_data_dir : std_logic;
signal vme_odff_dtack_n : std_logic; signal vme_odff_dtack_n : std_logic;
signal vme_odff_dtack_oe : std_logic; signal vme_odff_dtack_oe_n : std_logic;
signal vme_dtack_n_out : std_logic;
signal vme_odff_retry_n : std_logic; signal vme_odff_retry_n : std_logic;
signal vme_odff_retry_oe : std_logic; signal vme_odff_retry_oe_n : std_logic;
signal vme_cycles : unsigned (7 downto 0); signal vme_cycles : unsigned (7 downto 0);
...@@ -152,6 +157,10 @@ architecture rtl of vme_bus is ...@@ -152,6 +157,10 @@ architecture rtl of vme_bus is
-- Register containing the address. Initialized from VME, adjusted -- Register containing the address. Initialized from VME, adjusted
-- by address decoder, and incremented during DMA. -- by address decoder, and incremented during DMA.
signal addr_reg : std_logic_vector(31 downto 0); signal addr_reg : std_logic_vector(31 downto 0);
signal lword_n_reg : std_logic;
-- Next address (within the page) for a burst transfer
signal n_addr_reg : std_logic_vector(10 downto 0);
-- Load addr_reg from vme idff (for address phase1 and 2). -- Load addr_reg from vme idff (for address phase1 and 2).
signal load_addr_reg_phase1 : std_logic; signal load_addr_reg_phase1 : std_logic;
...@@ -160,6 +169,10 @@ architecture rtl of vme_bus is ...@@ -160,6 +169,10 @@ architecture rtl of vme_bus is
-- Data register, owned by the WB fsm. -- Data register, owned by the WB fsm.
signal data_reg : std_logic_vector(63 downto 0); signal data_reg : std_logic_vector(63 downto 0);
-- For block transfers, number of bytes by which the address is
-- incremented between transfers.
signal inc_reg : unsigned(2 downto 0);
type t_transferType is ( type t_transferType is (
SINGLE, SINGLE,
BLT, BLT,
...@@ -265,6 +278,8 @@ architecture rtl of vme_bus is ...@@ -265,6 +278,8 @@ architecture rtl of vme_bus is
signal s_wb_done : std_logic; signal s_wb_done : std_logic;
signal s_wb_start : std_logic; signal s_wb_start : std_logic;
signal wb_stb_out : std_logic;
-- Set if the next WB access will cross boundary for BLT/MBLT -- Set if the next WB access will cross boundary for BLT/MBLT
-- transfer. It will prevent from doing the next transfer. -- transfer. It will prevent from doing the next transfer.
signal s_cross_boundary : std_logic; signal s_cross_boundary : std_logic;
...@@ -306,59 +321,71 @@ begin ...@@ -306,59 +321,71 @@ begin
p_VMEmainFSM : process (clk_i) is p_VMEmainFSM : process (clk_i) is
begin begin
if rising_edge(clk_i) then if rising_edge(clk_i) then
if rst_n_i = '0' or vme_as_n_i = '1' then if rst_n_i = '0' or vme_as_n_i = '1' or slave_dis_i = '1' then
-- FSM reset after power up, -- FSM reset after power up,
-- software reset, manually reset, -- software reset, manually reset,
-- on rising edge of AS. -- on rising edge of AS.
s_conf_req <= '0'; s_conf_req <= '0';
decode_start_o <= '0'; decode_start_o <= '0';
-- VME -- VME
vme_odff_dtack_oe <= '0'; vme_odff_dtack_oe_n <= '1';
vme_odff_dtack_n <= '1'; vme_odff_dtack_n <= '1';
vme_dtack_async_ctrl <= '0'; vme_dtack_async_ctrl <= '0';
vme_odff_retry_oe <= '0'; vme_odff_retry_oe_n <= '1';
vme_odff_retry_n <= '1'; vme_odff_retry_n <= '1';
vme_odff_data_dir <= '0'; vme_odff_data_dir <= '0';
vme_odff_addr_dir <= '0'; vme_odff_addr_dir <= '0';
vme_odff_lword_n <= '0'; vme_odff_lword_n <= '0';
vme_berr_n_o <= '1'; vme_berr_n_o <= '1';
vme_iackout_n_o <= '1'; vme_iackout_n_o <= '1';
s_MBLT_Data <= '0'; s_MBLT_Data <= '0';
s_mainFSMstate <= IDLE; s_mainFSMstate <= IDLE;
-- WB -- WB
s_wb_start <= '0'; s_wb_start <= '0';
vme_idff_addr <= (others => '0'); vme_cycles <= (others => '0');
vme_idff_am <= (others => '0'); vme_idff_addr <= (others => '0');
vme_idff_data <= (others => '0');
vme_idff_am <= (others => '0');
vme_idff_ds_n <= (others => '1');
vme_idff_write_n <= '1';
vme_idff_lword_n <= '0';
vme_odff_addr <= (others => '0'); vme_odff_addr <= (others => '0');
vme_odff_data <= (others => '0');
load_addr_reg_phase1 <= '0'; load_addr_reg_phase1 <= '0';
load_addr_reg_phase2 <= '0'; load_addr_reg_phase2 <= '0';
s_transferType <= TFR_ERROR; s_transferType <= TFR_ERROR;
s_card_sel <= '0'; s_2e_dtack <= '0';
s_conf_sel <= '0'; s_DS_latch_count <= (others => '0');
s_irq_sel <= '0'; s_setup <= (others => '0');
irq_ack_o <= '0'; s_sst_timing <= (others => '0');
s_card_sel <= '0';
s_conf_sel <= '0';
s_irq_sel <= '0';
irq_ack_o <= '0';
else else
s_conf_req <= '0'; s_conf_req <= '0';
decode_start_o <= '0'; decode_start_o <= '0';
vme_odff_dtack_oe <= '0'; vme_odff_dtack_oe_n <= '1';
vme_odff_dtack_n <= '1'; vme_odff_dtack_n <= '1';
vme_odff_retry_oe <= '0'; vme_odff_retry_oe_n <= '1';
vme_odff_retry_n <= '1'; vme_odff_retry_n <= '1';
vme_dtack_async_ctrl <= '0'; vme_dtack_async_ctrl <= '0';
vme_berr_n_o <= '1'; vme_berr_n_o <= '1';
vme_iackout_n_o <= '1'; vme_iackout_n_o <= '1';
irq_ack_o <= '0'; irq_ack_o <= '0';
load_addr_reg_phase1 <= '0'; load_addr_reg_phase1 <= '0';
load_addr_reg_phase2 <= '0'; load_addr_reg_phase2 <= '0';
s_wb_start <= '0'; s_wb_start <= '0';
case s_mainFSMstate is case s_mainFSMstate is
...@@ -482,7 +509,7 @@ begin ...@@ -482,7 +509,7 @@ begin
when WAIT_FOR_DS => when WAIT_FOR_DS =>
-- wait until DS /= "11" -- wait until DS /= "11"
-- Note: before entering this state, s_DS_latch_count must be set. -- Note: before entering this state, s_DS_latch_count must be set.
vme_odff_dtack_oe <= '1'; vme_odff_dtack_oe_n <= '0';
vme_odff_dtack_n <= '1'; vme_odff_dtack_n <= '1';
if s_transferType = MBLT if s_transferType = MBLT
...@@ -533,7 +560,7 @@ begin ...@@ -533,7 +560,7 @@ begin
-- Already assert dtack (assume that data have been on the -- Already assert dtack (assume that data have been on the
-- vme bus for at least one cycle). -- vme bus for at least one cycle).
vme_odff_dtack_oe <= '1'; vme_odff_dtack_oe_n <= '0';
vme_odff_dtack_n <= s_err; vme_odff_dtack_n <= s_err;
vme_dtack_async_ctrl <= '0'; vme_dtack_async_ctrl <= '0';
...@@ -553,7 +580,7 @@ begin ...@@ -553,7 +580,7 @@ begin
-- if both are asserted or not. -- if both are asserted or not.
-- This state is necessary indeed the VME master can assert the -- This state is necessary indeed the VME master can assert the
-- DS lines not at the same time. -- DS lines not at the same time.
vme_odff_dtack_oe <= '1'; vme_odff_dtack_oe_n <= '0';
vme_odff_dtack_n <= '1'; vme_odff_dtack_n <= '1';
-- ANSI/VITA 1-1994 Rule 2.53a -- ANSI/VITA 1-1994 Rule 2.53a
...@@ -605,7 +632,7 @@ begin ...@@ -605,7 +632,7 @@ begin
end if; end if;
when CHECK_TRANSFER_TYPE => when CHECK_TRANSFER_TYPE =>
vme_odff_dtack_oe <= '1'; vme_odff_dtack_oe_n <= '0';
vme_odff_dtack_n <= '1'; vme_odff_dtack_n <= '1';
vme_odff_data_dir <= vme_idff_write_n; vme_odff_data_dir <= vme_idff_write_n;
...@@ -630,7 +657,7 @@ begin ...@@ -630,7 +657,7 @@ begin
when DATA_TO_BUS => when DATA_TO_BUS =>
-- Update what WB FSM prepared -- Update what WB FSM prepared
vme_odff_dtack_oe <= '1'; vme_odff_dtack_oe_n <= '0';
vme_odff_dtack_n <= '1'; vme_odff_dtack_n <= '1';
if s_conf_sel = '1' or s_wb_done = '1' or s_irq_sel = '1' then if s_conf_sel = '1' or s_wb_done = '1' or s_irq_sel = '1' then
...@@ -657,7 +684,7 @@ begin ...@@ -657,7 +684,7 @@ begin
when DTACK_LOW => when DTACK_LOW =>
-- Set /DTACK, wait until /DS[1:0] are released. -- Set /DTACK, wait until /DS[1:0] are released.
vme_odff_dtack_oe <= '1'; vme_odff_dtack_oe_n <= '0';
vme_odff_dtack_n <= '1'; vme_odff_dtack_n <= '1';
vme_odff_data_dir <= vme_idff_write_n; vme_odff_data_dir <= vme_idff_write_n;
...@@ -679,7 +706,10 @@ begin ...@@ -679,7 +706,10 @@ begin
-- Once the responding Slave has driven DTACK* or BERR* low, it -- Once the responding Slave has driven DTACK* or BERR* low, it
-- MUST NOT release them or drive DTACK* high until it detects -- MUST NOT release them or drive DTACK* high until it detects
-- both DS0* and DS1* high. -- both DS0* and DS1* high.
if vme_ds_n_i = "11" then if vme_ds_n_i = "11"
or (g_ASYNC_DTACK
and vme_dtack_async_ctrl = '1' and vme_dtack_n_out = '0')
then
vme_berr_n_o <= '1'; vme_berr_n_o <= '1';
-- Rescind DTACK. -- Rescind DTACK.
...@@ -717,7 +747,7 @@ begin ...@@ -717,7 +747,7 @@ begin
when APHASE_2 => when APHASE_2 =>
-- Address phase 2; wait until DS0 is 1. -- Address phase 2; wait until DS0 is 1.
vme_odff_dtack_oe <= '1'; vme_odff_dtack_oe_n <= '0';
vme_odff_dtack_n <= '0'; vme_odff_dtack_n <= '0';
vme_odff_data_dir <= '0'; vme_odff_data_dir <= '0';
vme_odff_addr_dir <= '0'; vme_odff_addr_dir <= '0';
...@@ -735,7 +765,7 @@ begin ...@@ -735,7 +765,7 @@ begin
end if; end if;
when APHASE_3 => when APHASE_3 =>
vme_odff_dtack_oe <= '1'; vme_odff_dtack_oe_n <= '0';
vme_odff_dtack_n <= '1'; vme_odff_dtack_n <= '1';
vme_odff_data_dir <= '0'; vme_odff_data_dir <= '0';
vme_odff_addr_dir <= '0'; vme_odff_addr_dir <= '0';
...@@ -758,7 +788,7 @@ begin ...@@ -758,7 +788,7 @@ begin
when VME_2E_TURN => when VME_2E_TURN =>
-- Wait until DS1 = 0 -- Wait until DS1 = 0
vme_odff_dtack_oe <= '1'; vme_odff_dtack_oe_n <= '0';
vme_odff_dtack_n <= '0'; vme_odff_dtack_n <= '0';
vme_odff_data_dir <= '0'; vme_odff_data_dir <= '0';
vme_odff_addr_dir <= '0'; vme_odff_addr_dir <= '0';
...@@ -777,7 +807,7 @@ begin ...@@ -777,7 +807,7 @@ begin
when VME_2E_DATA | VME_2E_SETUP => when VME_2E_DATA | VME_2E_SETUP =>
-- Setup: drive data and wait. -- Setup: drive data and wait.
vme_odff_dtack_oe <= '1'; vme_odff_dtack_oe_n <= '0';
vme_odff_dtack_n <= s_2e_dtack; vme_odff_dtack_n <= s_2e_dtack;
vme_odff_data_dir <= '1'; vme_odff_data_dir <= '1';
vme_odff_addr_dir <= '1'; vme_odff_addr_dir <= '1';
...@@ -801,7 +831,7 @@ begin ...@@ -801,7 +831,7 @@ begin
when VME_2E_DTACK => when VME_2E_DTACK =>
-- Drives new dtack. -- Drives new dtack.
vme_odff_dtack_oe <= '1'; vme_odff_dtack_oe_n <= '0';
vme_odff_dtack_n <= s_2e_dtack; vme_odff_dtack_n <= s_2e_dtack;
vme_odff_data_dir <= '1'; vme_odff_data_dir <= '1';
vme_odff_addr_dir <= '1'; vme_odff_addr_dir <= '1';
...@@ -811,7 +841,7 @@ begin ...@@ -811,7 +841,7 @@ begin
-- That was the last transfer. -- That was the last transfer.
vme_berr_n_o <= '0'; vme_berr_n_o <= '0';
vme_odff_retry_n <= '0'; vme_odff_retry_n <= '0';
vme_odff_retry_oe <= '1'; vme_odff_retry_oe_n <= '0';
s_mainFSMstate <= VME_2E_DONE; s_mainFSMstate <= VME_2E_DONE;
elsif s_wb_done = '1' then elsif s_wb_done = '1' then
s_mainFSMstate <= VME_2E_DATA; s_mainFSMstate <= VME_2E_DATA;
...@@ -836,19 +866,19 @@ begin ...@@ -836,19 +866,19 @@ begin
vme_odff_addr_dir <= '0'; vme_odff_addr_dir <= '0';
-- Drive dtack -- Drive dtack
vme_odff_dtack_oe <= '1'; vme_odff_dtack_oe_n <= '0';
vme_odff_dtack_n <= s_2e_dtack; vme_odff_dtack_n <= s_2e_dtack;
-- Assert BERR and RESP... -- Assert BERR and RESP...
vme_berr_n_o <= '0'; vme_berr_n_o <= '0';
vme_odff_retry_n <= '0'; vme_odff_retry_n <= '0';
vme_odff_retry_oe <= '1'; vme_odff_retry_oe_n <= '0';
-- Until DS is released. -- Until DS is released.
if vme_ds_n_i /= "00" then if vme_ds_n_i /= "00" then
vme_berr_n_o <= '1'; vme_berr_n_o <= '1';
vme_odff_retry_n <= '1'; vme_odff_retry_n <= '1';
vme_odff_retry_oe <= '0'; vme_odff_retry_oe_n <= '1';
s_mainFSMstate <= WAIT_END; s_mainFSMstate <= WAIT_END;
end if; end if;
...@@ -894,6 +924,8 @@ begin ...@@ -894,6 +924,8 @@ begin
end if; end if;
end process; end process;
n_addr_reg <= std_logic_vector (unsigned(addr_reg (10 downto 0)) + inc_reg);
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- WB FSM -- WB FSM
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
...@@ -908,25 +940,35 @@ begin ...@@ -908,25 +940,35 @@ begin
s_WBFSMstate <= IDLE; s_WBFSMstate <= IDLE;
-- WB -- WB
wb_cyc_o <= '0'; wb_cyc_o <= '0';
wb_stb_o <= '0'; wb_stb_out <= '0';
wb_sel_o <= "0000"; wb_sel_o <= "0000";
wb_we_o <= '0'; wb_we_o <= '0';
addr_reg <= (others => '0'); addr_reg <= (others => '0');
lword_n_reg <= '0';
data_reg <= (others => '0');
s_err <= '0'; s_err <= '0';
s_wb_done <= '0'; s_wb_done <= '0';
s_cross_boundary <= '0'; s_cross_boundary <= '0';
inc_reg <= (others => '0');
s_stall <= '0';
s_wb_dataphase <= '0';
else else
case s_WBFSMstate is case s_WBFSMstate is
when IDLE => when IDLE =>
wb_cyc_o <= '0'; wb_cyc_o <= '0';
wb_stb_o <= '0'; wb_stb_out <= '0';
if load_addr_reg_phase1 = '1' then if load_addr_reg_phase1 = '1' then
-- VME address phase 1. -- VME address phase 1.
addr_reg (31 downto 1) <= vme_idff_addr; addr_reg <= vme_idff_addr & '0';
addr_reg (0) <= vme_idff_lword_n; lword_n_reg <= vme_idff_lword_n;
s_cross_boundary <= '0'; s_cross_boundary <= '0';
...@@ -953,7 +995,8 @@ begin ...@@ -953,7 +995,8 @@ begin
if load_addr_reg_phase2 = '1' then if load_addr_reg_phase2 = '1' then
-- VME address phase 2 (for 2eVME oand 2eSST) -- VME address phase 2 (for 2eVME oand 2eSST)
addr_reg(7 downto 0) <= vme_idff_addr (7 downto 1) & vme_idff_lword_n; addr_reg (7 downto 0) <= vme_idff_addr (7 downto 1) & '0';
lword_n_reg <= vme_idff_lword_n;
end if; end if;
if decode_done_i = '1' then if decode_done_i = '1' then
...@@ -966,10 +1009,11 @@ begin ...@@ -966,10 +1009,11 @@ begin
s_wb_done <= '0'; s_wb_done <= '0';
end if; end if;
if s_wb_start = '1' and s_cross_boundary = '0' then if s_wb_start = '1' then
-- Start WB cycle. -- Start WB cycle (only for memory access and not
wb_cyc_o <= s_card_sel; -- crossing boundaries).
wb_stb_o <= s_card_sel; wb_cyc_o <= s_card_sel and not s_cross_boundary;
wb_stb_out <= s_card_sel and not s_cross_boundary;
wb_we_o <= not vme_idff_write_n; wb_we_o <= not vme_idff_write_n;
if vme_idff_write_n = '0' then if vme_idff_write_n = '0' then
...@@ -979,7 +1023,7 @@ begin ...@@ -979,7 +1023,7 @@ begin
data_reg (31 downto 1) <= vme_idff_addr; data_reg (31 downto 1) <= vme_idff_addr;
data_reg (63 downto 32) <= vme_idff_data; data_reg (63 downto 32) <= vme_idff_data;
else else
if addr_reg(0) = '0' then if lword_n_reg = '0' then
-- 32bit access (lword is set) -- 32bit access (lword is set)
data_reg (31 downto 0) <= vme_idff_data; data_reg (31 downto 0) <= vme_idff_data;
else else
...@@ -995,7 +1039,7 @@ begin ...@@ -995,7 +1039,7 @@ begin
-- 16bit access on a 16bit bus. -- 16bit access on a 16bit bus.
wb_sel_o (3 downto 2) <= "00"; wb_sel_o (3 downto 2) <= "00";
wb_sel_o (1 downto 0) <= not vme_idff_ds_n; wb_sel_o (1 downto 0) <= not vme_idff_ds_n;
elsif addr_reg(0) = '0' or s_transferType = VME2E then elsif lword_n_reg = '0' or s_transferType = VME2E then
-- 32bit access -- 32bit access
wb_sel_o <= "1111"; wb_sel_o <= "1111";
else else
...@@ -1011,11 +1055,28 @@ begin ...@@ -1011,11 +1055,28 @@ begin
end case; end case;
end if; end if;
-- Compute beat size (and therefore increment) in case of block transfer.
if s_transferType = BLT then
if lword_n_reg = '0' then
-- 32-bit beat
inc_reg <= "100";
elsif vme_idff_ds_n = "00" then
-- 16-bit beat
inc_reg <= "010";
else
-- 8-bit beat
-- NOTE: as it provides no advantages over d16, maybe get rid of it.
inc_reg <= "001";
end if;
else
inc_reg <= "100";
end if;
s_wb_dataphase <= f_to_std_logic (s_transferType = MBLT or s_transferType = VME2E); s_wb_dataphase <= f_to_std_logic (s_transferType = MBLT or s_transferType = VME2E);
s_stall <= '1'; -- Can stall s_stall <= '1'; -- Can stall
s_err <= '0'; s_err <= '0';
if s_card_sel = '1' then if s_card_sel = '1' and s_cross_boundary = '0' then
s_WBFSMstate <= MEMORY_REQ; s_WBFSMstate <= MEMORY_REQ;
elsif s_conf_sel = '1' then elsif s_conf_sel = '1' then
if vme_idff_write_n = '1' then if vme_idff_write_n = '1' then
...@@ -1042,10 +1103,10 @@ begin ...@@ -1042,10 +1103,10 @@ begin
case g_WB_MODE is case g_WB_MODE is
when CLASSIC => when CLASSIC =>
-- Maintain STB. -- Maintain STB.
wb_stb_o <= '1'; wb_stb_out <= '1';
when PIPELINED => when PIPELINED =>
-- Maintain STB if stall was set in the previous cycle. -- Maintain STB if stall was set in the previous cycle.
wb_stb_o <= s_stall and wb_stall_i; wb_stb_out <= s_stall and wb_stall_i;
end case; end case;
s_stall <= s_stall and wb_stall_i; s_stall <= s_stall and wb_stall_i;
...@@ -1053,7 +1114,7 @@ begin ...@@ -1053,7 +1114,7 @@ begin
if wb_ack_i = '1' or wb_err_i = '1' then if wb_ack_i = '1' or wb_err_i = '1' then
-- WB ack -- WB ack
-- For classic mode, be sure strobe is negated. -- For classic mode, be sure strobe is negated.
wb_stb_o <= '0'; wb_stb_out <= '0';
if s_transferType /= SINGLE then if s_transferType /= SINGLE then
-- Next word for any block transfer. -- Next word for any block transfer.
...@@ -1061,12 +1122,12 @@ begin ...@@ -1061,12 +1122,12 @@ begin
-- BLT must not cross any 256 byte boundary. -- BLT must not cross any 256 byte boundary.
-- VITA 1-1994 RULE 2.78 -- VITA 1-1994 RULE 2.78
-- MBLT cycles MUST not cross any 2048 byte boundary. -- MBLT cycles MUST not cross any 2048 byte boundary.
addr_reg (10 downto 2) <= addr_reg (10 downto 0) <= n_addr_reg;
std_logic_vector (unsigned(addr_reg (10 downto 2)) + 1);
if addr_reg(7 downto 2) = b"1111_11" then if addr_reg(7 downto 2) = b"1111_11" then
if s_transferType = MBLT and addr_reg (10 downto 8) = "111" then if s_transferType = MBLT and addr_reg (10 downto 8) = "111" then
s_cross_boundary <= '1'; s_cross_boundary <= '1';
elsif s_transferType = BLT then elsif s_transferType = BLT and n_addr_reg (1 downto 0) = "00" then
-- For BLT, crossing depends on the data size.
s_cross_boundary <= '1'; s_cross_boundary <= '1';
end if; end if;
end if; end if;
...@@ -1098,7 +1159,7 @@ begin ...@@ -1098,7 +1159,7 @@ begin
-- Mux (CS-CSR or WB) -- Mux (CS-CSR or WB)
data_reg(63 downto 32) <= data_reg(31 downto 0); data_reg(63 downto 32) <= data_reg(31 downto 0);
data_reg(31 downto 0) <= (others => '0'); data_reg(31 downto 0) <= (others => '0');
if g_VME32 and addr_reg(0) = '1' and addr_reg(1) = '0' if g_VME32 and lword_n_reg = '1' and addr_reg(1) = '0'
then then
-- Word/byte access with A1 = 0 on a 32bit bus. -- Word/byte access with A1 = 0 on a 32bit bus.
data_reg(15 downto 0) <= wb_dat_i(31 downto 16); data_reg(15 downto 0) <= wb_dat_i(31 downto 16);
...@@ -1116,7 +1177,7 @@ begin ...@@ -1116,7 +1177,7 @@ begin
s_WBFSMstate <= MEMORY_PAUSE; s_WBFSMstate <= MEMORY_PAUSE;
when PIPELINED => when PIPELINED =>
-- No need to pause, can directly start a new xfer. -- No need to pause, can directly start a new xfer.
wb_stb_o <= '1'; wb_stb_out <= '1';
s_stall <= '1'; s_stall <= '1';
s_WBFSMstate <= MEMORY_REQ; s_WBFSMstate <= MEMORY_REQ;
end case; end case;
...@@ -1133,10 +1194,10 @@ begin ...@@ -1133,10 +1194,10 @@ begin
when MEMORY_PAUSE => when MEMORY_PAUSE =>
-- Wait until ACK is 0. Strictly speaking, this is not needed -- Wait until ACK is 0. Strictly speaking, this is not needed
-- according to WB specs. -- according to WB specs.
wb_stb_o <= '0'; wb_stb_out <= '0';
if wb_ack_i = '0' then if wb_ack_i = '0' then
wb_stb_o <= '1'; wb_stb_out <= '1';
s_stall <= '1'; s_stall <= '1';
s_WBFSMstate <= MEMORY_REQ; s_WBFSMstate <= MEMORY_REQ;
else else
...@@ -1179,20 +1240,23 @@ begin ...@@ -1179,20 +1240,23 @@ begin
vme_lword_n_o <= vme_odff_lword_n; vme_lword_n_o <= vme_odff_lword_n;
vme_retry_n_o <= vme_odff_retry_n; vme_retry_n_o <= vme_odff_retry_n;
vme_retry_oe_o <= vme_odff_retry_oe; vme_retry_oe_n_o <= vme_odff_retry_oe_n;
vme_dtack_oe_o <= vme_odff_dtack_oe; vme_dtack_oe_n_o <= vme_odff_dtack_oe_n;
card_sel_o <= s_card_sel; card_sel_o <= s_card_sel;
process (vme_odff_dtack_n, vme_nsync_ds_n_i, vme_dtack_async_ctrl) process (vme_odff_dtack_n, vme_nsync_ds_n_i, vme_dtack_async_ctrl)
begin begin
if vme_dtack_async_ctrl = '0' then if vme_dtack_async_ctrl = '0' or not g_ASYNC_DTACK then
vme_dtack_n_o <= vme_odff_dtack_n; vme_dtack_n_out <= vme_odff_dtack_n;
else else
-- Asserted (to 0) as soon as one ds signal is asserted (to 0). -- Asserted (to 0) as soon as one ds signal is asserted (to 0).
-- Negated (to 1) as soon as both ds signal is negated (to 1). -- Negated (to 1) as soon as both ds signal is negated (to 1).
vme_dtack_n_o <= vme_nsync_ds_n_i(0) and vme_nsync_ds_n_i(1); vme_dtack_n_out <= vme_nsync_ds_n_i(0) and vme_nsync_ds_n_i(1);
end if; end if;
end process; end process;
vme_dtack_n_o <= vme_dtack_n_out;
wb_stb_o <= wb_stb_out;
end rtl; end rtl;
...@@ -67,6 +67,14 @@ entity xvme64x_core is ...@@ -67,6 +67,14 @@ entity xvme64x_core is
-- Do not forget to assign g_DECODER if set to True. -- Do not forget to assign g_DECODER if set to True.
g_VME_2e : boolean := False; g_VME_2e : boolean := False;
-- If True, allows to directly drives DTACK from DS inputs.
-- This improves performance as synchronizers and registers are skipped.
-- But it then requires a minimal frequency, otherwise the master may
-- change the bus before the slave latched the data.
-- No problems have been reported when the clock is faster than 62.5Mhz.
-- Problems have been reported for clock slower than 40Mhz.
g_ASYNC_DTACK : boolean := False;
-- Address granularity on the WB bus. Value can be: -- Address granularity on the WB bus. Value can be:
-- WORD: VME address bits 31:2 are translated to WB address bits 29:0, -- WORD: VME address bits 31:2 are translated to WB address bits 29:0,
-- the WB data represents bytes for VME address bits 1:0. -- the WB data represents bytes for VME address bits 1:0.
...@@ -237,12 +245,16 @@ architecture rtl of xvme64x_core is ...@@ -237,12 +245,16 @@ architecture rtl of xvme64x_core is
signal s_vme_iack_n : std_logic; signal s_vme_iack_n : std_logic;
signal s_vme_iackin_n : std_logic; signal s_vme_iackin_n : std_logic;
signal vme_retry_oe_n : std_logic;
signal vme_dtack_oe_n : std_logic;
-- List of supported AM. -- List of supported AM.
-- (use downto in the aggregate as a workaround Vivado 2020 bug).
constant c_AMCAP_ALLOWED : std_logic_vector(63 downto 0) := constant c_AMCAP_ALLOWED : std_logic_vector(63 downto 0) :=
(16#38# to 16#3f# => '1', -- A24 (16#3f# downto 16#38# => '1', -- A24
16#2d# | 16#29# => '1', -- A16 16#2d# | 16#29# => '1', -- A16
16#20# => f_to_std_logic(g_VME32 and g_VME_2e), 16#20# => f_to_std_logic(g_VME32 and g_VME_2e),
16#08# to 16#0f# => f_to_std_logic(g_VME32), -- A32 16#0f# downto 16#08# => f_to_std_logic(g_VME32), -- A32
others => '0'); others => '0');
begin begin
assert g_CLOCK_PERIOD > 0 report "g_CLOCK_PERIOD generic must be set" assert g_CLOCK_PERIOD > 0 report "g_CLOCK_PERIOD generic must be set"
...@@ -326,6 +338,7 @@ begin ...@@ -326,6 +338,7 @@ begin
g_CLOCK_PERIOD => g_CLOCK_PERIOD, g_CLOCK_PERIOD => g_CLOCK_PERIOD,
g_VME32 => g_VME32, g_VME32 => g_VME32,
g_VME_2E => g_VME_2E, g_VME_2E => g_VME_2E,
g_ASYNC_DTACK => g_ASYNC_DTACK,
g_WB_GRANULARITY => g_WB_GRANULARITY, g_WB_GRANULARITY => g_WB_GRANULARITY,
g_WB_MODE => g_WB_MODE) g_WB_MODE => g_WB_MODE)
port map ( port map (
...@@ -337,12 +350,12 @@ begin ...@@ -337,12 +350,12 @@ begin
vme_lword_n_o => vme_o.lword_n, vme_lword_n_o => vme_o.lword_n,
vme_lword_n_i => vme_i.lword_n, vme_lword_n_i => vme_i.lword_n,
vme_retry_n_o => vme_o.retry_n, vme_retry_n_o => vme_o.retry_n,
vme_retry_oe_o => vme_o.retry_oe, vme_retry_oe_n_o => vme_retry_oe_n,
vme_write_n_i => s_vme_write_n, vme_write_n_i => s_vme_write_n,
vme_ds_n_i => s_vme_ds_n, vme_ds_n_i => s_vme_ds_n,
vme_nsync_ds_n_i => vme_i.ds_n, -- Not synchronized. vme_nsync_ds_n_i => vme_i.ds_n, -- Not synchronized.
vme_dtack_n_o => vme_o.dtack_n, vme_dtack_n_o => vme_o.dtack_n,
vme_dtack_oe_o => vme_o.dtack_oe, vme_dtack_oe_n_o => vme_dtack_oe_n,
vme_berr_n_o => s_vme_berr_n, vme_berr_n_o => s_vme_berr_n,
vme_addr_i => vme_i.addr, vme_addr_i => vme_i.addr,
vme_addr_o => vme_o.addr, vme_addr_o => vme_o.addr,
...@@ -389,13 +402,17 @@ begin ...@@ -389,13 +402,17 @@ begin
int_vector_i => s_irq_vector, int_vector_i => s_irq_vector,
irq_pending_i => s_irq_pending, irq_pending_i => s_irq_pending,
irq_ack_o => s_irq_ack, irq_ack_o => s_irq_ack,
card_sel_o => open); card_sel_o => open
);
s_reset_n <= rst_n_i and s_vme_rst_n; s_reset_n <= rst_n_i and s_vme_rst_n;
rst_n_o <= s_reset_n and (not s_module_reset); rst_n_o <= s_reset_n and (not s_module_reset);
vme_o.berr_n <= s_vme_berr_n; vme_o.berr_n <= s_vme_berr_n;
vme_o.retry_oe <= not vme_retry_oe_n;
vme_o.dtack_oe <= not vme_dtack_oe_n;
inst_vme_funct_match : entity work.vme_funct_match inst_vme_funct_match : entity work.vme_funct_match
generic map ( generic map (
g_DECODER => g_DECODER, g_DECODER => g_DECODER,
...@@ -512,14 +529,14 @@ begin ...@@ -512,14 +529,14 @@ begin
gen_ext_user_csr : if g_USER_CSR_EXT = true generate gen_ext_user_csr : if g_USER_CSR_EXT = true generate
s_user_csr_data_i <= user_csr_data_i; s_user_csr_data_i <= user_csr_data_i;
s_irq_vector <= irq_vector_i; s_irq_vector <= irq_vector_i;
s_irq_level <= irq_level_i(2 downto 0); s_irq_level <= irq_level_i;
end generate; end generate;
end generate; end generate;
gen_disable_cr_csr : if g_ENABLE_CR_CSR = false generate gen_disable_cr_csr : if g_ENABLE_CR_CSR = false generate
s_user_csr_data_i <= user_csr_data_i; s_user_csr_data_i <= user_csr_data_i;
s_cr_csr_data_o <= s_user_csr_data_i; s_cr_csr_data_o <= s_user_csr_data_i;
s_irq_vector <= irq_vector_i; s_irq_vector <= irq_vector_i;
s_irq_level <= irq_level_i(2 downto 0); s_irq_level <= irq_level_i;
s_user_csr_addr <= s_cr_csr_addr; s_user_csr_addr <= s_cr_csr_addr;
s_user_csr_data_o <= s_cr_csr_data_i; s_user_csr_data_o <= s_cr_csr_data_i;
s_user_csr_we <= s_cr_csr_we; s_user_csr_we <= s_cr_csr_we;
......
...@@ -3,10 +3,10 @@ set -e ...@@ -3,10 +3,10 @@ set -e
GHDL=${GHDL:-ghdl} GHDL=${GHDL:-ghdl}
for i in 1 2 3 4 5 6 7 8 9 11; do for i in 1 2 3 4 5 6 7 8 9 11 12; do
echo echo
echo "Scenario $i" echo "Scenario $i"
$GHDL -r --ieee=synopsys top_tb -gg_scenario=$i --stop-time=5us --assert-level=error --ieee-asserts=disable-at-0 | tee sim.log $GHDL -r --ieee=synopsys top_tb -gg_scenario=$i --stop-time=50us --assert-level=error --ieee-asserts=disable-at-0 | tee sim.log
if [ $? != 0 ]; then if [ $? != 0 ]; then
echo "Simulation failed!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" echo "Simulation failed!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
exit 1 exit 1
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html -- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html
entity top_tb is entity top_tb is
generic (g_SCENARIO : natural range 0 to 11 := 6); generic (g_SCENARIO : natural range 0 to 12 := 12);
end top_tb; end top_tb;
library ieee; library ieee;
...@@ -256,6 +256,8 @@ architecture behaviour of top_tb is ...@@ -256,6 +256,8 @@ architecture behaviour of top_tb is
signal bus_timer : std_logic; signal bus_timer : std_logic;
signal end_tb : boolean := false; signal end_tb : boolean := false;
signal gen_int : boolean := false;
signal err_8000 : natural := 0; signal err_8000 : natural := 0;
begin begin
set_ga: block set_ga: block
...@@ -475,6 +477,9 @@ begin ...@@ -475,6 +477,9 @@ begin
irq_i <= '1'; irq_i <= '1';
end if; end if;
end if; end if;
if gen_int then
irq_i <= '1';
end if;
if STB_o = '1' and CYC_o = '1' then if STB_o = '1' and CYC_o = '1' then
ACK_i <= '1'; ACK_i <= '1';
...@@ -1167,7 +1172,7 @@ begin ...@@ -1167,7 +1172,7 @@ begin
variable d16 : word_t; variable d16 : word_t;
variable d32 : lword_t; variable d32 : lword_t;
variable v64 : qword_array_t (0 to 16); variable v64 : qword_array_t (0 to 255);
variable v32 : lword_array_t (0 to 16); variable v32 : lword_array_t (0 to 16);
variable v16 : word_array_t (0 to 16); variable v16 : word_array_t (0 to 16);
begin begin
...@@ -1318,17 +1323,15 @@ begin ...@@ -1318,17 +1323,15 @@ begin
and v32 (4) = x"8765_4321" and v32 (4) = x"8765_4321"
report "incorrect BLT data 32" severity error; report "incorrect BLT data 32" severity error;
if false then -- D16 BLT now supported
-- D16 BLT not supported read16_blt (x"64_00_00_14", c_AM_A32_BLT, v16 (0 to 5));
read16_blt (x"64_00_00_14", c_AM_A32_BLT, v16 (0 to 5)); assert v16 (0) = x"0000"
assert v16 (0) = x"0000" and v16 (1) = x"0500"
and v16 (1) = x"0500" and v16 (2) = x"0006"
and v16 (2) = x"0006" and v16 (3) = x"0000"
and v16 (3) = x"0000" and v16 (4) = x"0700"
and v16 (4) = x"0700" and v16 (5) = x"0000"
and v16 (5) = x"0000" report "incorrect BLT data 16" severity error;
report "incorrect BLT data 16" severity error;
end if;
v32 (0 to 3) := (x"00_11_22_33", v32 (0 to 3) := (x"00_11_22_33",
x"44_55_66_77", x"44_55_66_77",
...@@ -1555,7 +1558,37 @@ begin ...@@ -1555,7 +1558,37 @@ begin
assert d32 = x"C000_3004" assert d32 = x"C000_3004"
report "incorrect read 32" severity error; report "incorrect read 32" severity error;
-- TODO: check IACK propagation. when 12 =>
-- Test MBLT followed by interrupt
-- Set ADER
write8_conf (x"7_ff63", x"64");
write8_conf (x"7_ff6f", c_AM_A32_MBLT & "00");
-- Set IRQ level
write8_conf (x"7_ff5b", x"03");
-- Set IRQ vector
write8_conf (x"7_ff5f", x"a3");
-- Enable card
write8_conf (x"7_fffb", b"0001_0000");
read64_mblt (x"64_00_00_00", c_AM_A32_MBLT, v64 (0 to 255));
report "at 04: " & hex8 (v64(2)(63 downto 32));
gen_int <= true;
wait for 2 * g_CLOCK_PERIOD * 1 ns;
assert VME_IRQ_n_o = "1111011" report "IRQ incorrectly reported"
severity error;
gen_int <= false;
ack_int (d8);
assert d8 = x"a3" report "incorrect vector" severity error;
assert VME_IRQ_n_o = "1111111" report "IRQ not disabled after ack"
severity error;
-- TODO: check IACK propagation.
end case; end case;
wait for 4 * g_CLOCK_PERIOD * 1 ns; wait for 4 * g_CLOCK_PERIOD * 1 ns;
......
...@@ -11,5 +11,6 @@ files = [ ...@@ -11,5 +11,6 @@ files = [
] ]
modules = { modules = {
"local": [ "../../rtl", fetchto + "/general-cores" ], "local": ["../../rtl"],
"git": ["https://ohwr.org/project/general-cores.git"],
} }
$GHDL -r --std=08 vme16_tb -gg_scenario=3 --assert-level=error