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",
"vme_funct_match.vhd",
"vme_irq_controller.vhd",
"vme_user_csr.vhd",
"xvme64x_core.vhd"]
"xvme64x_core.vhd",
"vme64x_core_verilog.vhd"]
......@@ -17,6 +17,7 @@ entity vme64x_core is
g_USER_CSR_EXT : boolean := false;
g_VME32 : boolean := true;
g_VME_2e : boolean := False;
g_ASYNC_DTACK : boolean := False;
g_WB_GRANULARITY : t_wishbone_address_granularity;
g_MANUFACTURER_ID : std_logic_vector(23 downto 0);
g_BOARD_ID : std_logic_vector(31 downto 0);
......@@ -119,6 +120,7 @@ begin
g_WB_GRANULARITY => g_WB_GRANULARITY,
g_WB_MODE => CLASSIC,
g_VME_2e => g_VME_2e,
g_ASYNC_DTACK => g_ASYNC_DTACK,
g_MANUFACTURER_ID => g_MANUFACTURER_ID,
g_BOARD_ID => g_BOARD_ID,
g_REVISION_ID => g_REVISION_ID,
......
......@@ -22,6 +22,7 @@ entity vme64x_core_verilog is
g_USER_CSR_EXT : natural := 0;
g_VME32 : natural := 1;
g_VME_2e : natural := 0;
g_ASYNC_DTACK : natural := 0;
g_WB_GRANULARITY : string(1 to 4);
g_MANUFACTURER_ID : std_logic_vector(23 downto 0);
g_BOARD_ID : std_logic_vector(31 downto 0);
......@@ -143,6 +144,7 @@ begin
g_USER_CSR_EXT => nat_to_bool(g_USER_CSR_EXT),
g_VME32 => nat_to_bool(g_VME32),
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_MANUFACTURER_ID => g_MANUFACTURER_ID,
g_BOARD_ID => g_BOARD_ID,
......
......@@ -185,6 +185,21 @@ package vme64x_pkg is
dawpr => x"84"),
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
------------------------------------------------------------------------------
......
......@@ -37,6 +37,7 @@ entity vme_bus is
g_CLOCK_PERIOD : integer;
g_VME32 : boolean;
g_VME_2E : boolean;
g_ASYNC_DTACK : boolean;
g_WB_GRANULARITY : t_wishbone_address_granularity;
g_WB_MODE : t_wishbone_interface_mode
);
......@@ -49,12 +50,12 @@ entity vme_bus is
vme_lword_n_o : out std_logic := '0';
vme_lword_n_i : in std_logic;
vme_retry_n_o : out std_logic;
vme_retry_oe_o : out std_logic;
vme_write_n_i : in std_logic;
vme_ds_n_i : in std_logic_vector(1 downto 0);
vme_retry_oe_n_o : out std_logic;
vme_write_n_i : in std_logic;
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_dtack_n_o : out std_logic;
vme_dtack_oe_o : out std_logic;
vme_dtack_n_o : out std_logic;
vme_dtack_oe_n_o : out std_logic;
vme_berr_n_o : out std_logic;
vme_addr_i : in std_logic_vector(31 downto 1);
vme_addr_o : out std_logic_vector(31 downto 1) := (others => '0');
......@@ -112,6 +113,9 @@ entity vme_bus is
irq_pending_i : in std_logic;
irq_ack_o : out std_logic;
-- Disable slave
slave_dis_i : in std_logic := '0';
--Card selection
card_sel_o : out std_logic
);
......@@ -138,10 +142,11 @@ architecture rtl of vme_bus is
signal vme_odff_data_dir : 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_oe : std_logic;
signal vme_odff_retry_oe_n : std_logic;
signal vme_cycles : unsigned (7 downto 0);
......@@ -152,6 +157,10 @@ architecture rtl of vme_bus is
-- Register containing the address. Initialized from VME, adjusted
-- by address decoder, and incremented during DMA.
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).
signal load_addr_reg_phase1 : std_logic;
......@@ -160,6 +169,10 @@ architecture rtl of vme_bus is
-- Data register, owned by the WB fsm.
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 (
SINGLE,
BLT,
......@@ -265,6 +278,8 @@ architecture rtl of vme_bus is
signal s_wb_done : 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
-- transfer. It will prevent from doing the next transfer.
signal s_cross_boundary : std_logic;
......@@ -306,59 +321,71 @@ begin
p_VMEmainFSM : process (clk_i) is
begin
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,
-- software reset, manually reset,
-- on rising edge of AS.
s_conf_req <= '0';
decode_start_o <= '0';
s_conf_req <= '0';
decode_start_o <= '0';
-- VME
vme_odff_dtack_oe <= '0';
vme_odff_dtack_n <= '1';
vme_odff_dtack_oe_n <= '1';
vme_odff_dtack_n <= '1';
vme_dtack_async_ctrl <= '0';
vme_odff_retry_oe <= '0';
vme_odff_retry_n <= '1';
vme_odff_data_dir <= '0';
vme_odff_addr_dir <= '0';
vme_odff_lword_n <= '0';
vme_berr_n_o <= '1';
vme_iackout_n_o <= '1';
s_MBLT_Data <= '0';
s_mainFSMstate <= IDLE;
vme_odff_retry_oe_n <= '1';
vme_odff_retry_n <= '1';
vme_odff_data_dir <= '0';
vme_odff_addr_dir <= '0';
vme_odff_lword_n <= '0';
vme_berr_n_o <= '1';
vme_iackout_n_o <= '1';
s_MBLT_Data <= '0';
s_mainFSMstate <= IDLE;
-- WB
s_wb_start <= '0';
s_wb_start <= '0';
vme_idff_addr <= (others => '0');
vme_idff_am <= (others => '0');
vme_cycles <= (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_phase2 <= '0';
s_transferType <= TFR_ERROR;
s_card_sel <= '0';
s_conf_sel <= '0';
s_irq_sel <= '0';
irq_ack_o <= '0';
s_transferType <= TFR_ERROR;
s_2e_dtack <= '0';
s_DS_latch_count <= (others => '0');
s_setup <= (others => '0');
s_sst_timing <= (others => '0');
s_card_sel <= '0';
s_conf_sel <= '0';
s_irq_sel <= '0';
irq_ack_o <= '0';
else
s_conf_req <= '0';
decode_start_o <= '0';
vme_odff_dtack_oe <= '0';
vme_odff_dtack_n <= '1';
vme_odff_retry_oe <= '0';
vme_odff_retry_n <= '1';
s_conf_req <= '0';
decode_start_o <= '0';
vme_odff_dtack_oe_n <= '1';
vme_odff_dtack_n <= '1';
vme_odff_retry_oe_n <= '1';
vme_odff_retry_n <= '1';
vme_dtack_async_ctrl <= '0';
vme_berr_n_o <= '1';
vme_iackout_n_o <= '1';
irq_ack_o <= '0';
vme_berr_n_o <= '1';
vme_iackout_n_o <= '1';
irq_ack_o <= '0';
load_addr_reg_phase1 <= '0';
load_addr_reg_phase2 <= '0';
s_wb_start <= '0';
s_wb_start <= '0';
case s_mainFSMstate is
......@@ -482,7 +509,7 @@ begin
when WAIT_FOR_DS =>
-- wait until DS /= "11"
-- 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';
if s_transferType = MBLT
......@@ -533,7 +560,7 @@ begin
-- Already assert dtack (assume that data have been on the
-- 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_dtack_async_ctrl <= '0';
......@@ -553,7 +580,7 @@ begin
-- if both are asserted or not.
-- This state is necessary indeed the VME master can assert the
-- DS lines not at the same time.
vme_odff_dtack_oe <= '1';
vme_odff_dtack_oe_n <= '0';
vme_odff_dtack_n <= '1';
-- ANSI/VITA 1-1994 Rule 2.53a
......@@ -605,7 +632,7 @@ begin
end if;
when CHECK_TRANSFER_TYPE =>
vme_odff_dtack_oe <= '1';
vme_odff_dtack_oe_n <= '0';
vme_odff_dtack_n <= '1';
vme_odff_data_dir <= vme_idff_write_n;
......@@ -630,7 +657,7 @@ begin
when DATA_TO_BUS =>
-- Update what WB FSM prepared
vme_odff_dtack_oe <= '1';
vme_odff_dtack_oe_n <= '0';
vme_odff_dtack_n <= '1';
if s_conf_sel = '1' or s_wb_done = '1' or s_irq_sel = '1' then
......@@ -657,7 +684,7 @@ begin
when DTACK_LOW =>
-- 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_data_dir <= vme_idff_write_n;
......@@ -679,7 +706,10 @@ begin
-- Once the responding Slave has driven DTACK* or BERR* low, it
-- MUST NOT release them or drive DTACK* high until it detects
-- 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';
-- Rescind DTACK.
......@@ -717,7 +747,7 @@ begin
when APHASE_2 =>
-- 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_data_dir <= '0';
vme_odff_addr_dir <= '0';
......@@ -735,7 +765,7 @@ begin
end if;
when APHASE_3 =>
vme_odff_dtack_oe <= '1';
vme_odff_dtack_oe_n <= '0';
vme_odff_dtack_n <= '1';
vme_odff_data_dir <= '0';
vme_odff_addr_dir <= '0';
......@@ -758,7 +788,7 @@ begin
when VME_2E_TURN =>
-- Wait until DS1 = 0
vme_odff_dtack_oe <= '1';
vme_odff_dtack_oe_n <= '0';
vme_odff_dtack_n <= '0';
vme_odff_data_dir <= '0';
vme_odff_addr_dir <= '0';
......@@ -777,7 +807,7 @@ begin
when VME_2E_DATA | VME_2E_SETUP =>
-- 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_data_dir <= '1';
vme_odff_addr_dir <= '1';
......@@ -801,7 +831,7 @@ begin
when VME_2E_DTACK =>
-- Drives new dtack.
vme_odff_dtack_oe <= '1';
vme_odff_dtack_oe_n <= '0';
vme_odff_dtack_n <= s_2e_dtack;
vme_odff_data_dir <= '1';
vme_odff_addr_dir <= '1';
......@@ -811,7 +841,7 @@ begin
-- That was the last transfer.
vme_berr_n_o <= '0';
vme_odff_retry_n <= '0';
vme_odff_retry_oe <= '1';
vme_odff_retry_oe_n <= '0';
s_mainFSMstate <= VME_2E_DONE;
elsif s_wb_done = '1' then
s_mainFSMstate <= VME_2E_DATA;
......@@ -836,19 +866,19 @@ begin
vme_odff_addr_dir <= '0';
-- Drive dtack
vme_odff_dtack_oe <= '1';
vme_odff_dtack_oe_n <= '0';
vme_odff_dtack_n <= s_2e_dtack;
-- Assert BERR and RESP...
vme_berr_n_o <= '0';
vme_odff_retry_n <= '0';
vme_odff_retry_oe <= '1';
vme_odff_retry_oe_n <= '0';
-- Until DS is released.
if vme_ds_n_i /= "00" then
vme_berr_n_o <= '1';
vme_odff_retry_n <= '1';
vme_odff_retry_oe <= '0';
vme_odff_retry_oe_n <= '1';
s_mainFSMstate <= WAIT_END;
end if;
......@@ -894,6 +924,8 @@ begin
end if;
end process;
n_addr_reg <= std_logic_vector (unsigned(addr_reg (10 downto 0)) + inc_reg);
------------------------------------------------------------------------------
-- WB FSM
------------------------------------------------------------------------------
......@@ -908,25 +940,35 @@ begin
s_WBFSMstate <= IDLE;
-- WB
wb_cyc_o <= '0';
wb_stb_o <= '0';
wb_stb_out <= '0';
wb_sel_o <= "0000";
wb_we_o <= '0';
addr_reg <= (others => '0');
lword_n_reg <= '0';
data_reg <= (others => '0');
s_err <= '0';
s_wb_done <= '0';
s_wb_done <= '0';
s_cross_boundary <= '0';
inc_reg <= (others => '0');
s_stall <= '0';
s_wb_dataphase <= '0';
else
case s_WBFSMstate is
when IDLE =>
wb_cyc_o <= '0';
wb_stb_o <= '0';
wb_stb_out <= '0';
if load_addr_reg_phase1 = '1' then
-- VME address phase 1.
addr_reg (31 downto 1) <= vme_idff_addr;
addr_reg (0) <= vme_idff_lword_n;
addr_reg <= vme_idff_addr & '0';
lword_n_reg <= vme_idff_lword_n;
s_cross_boundary <= '0';
......@@ -953,7 +995,8 @@ begin
if load_addr_reg_phase2 = '1' then
-- 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;
if decode_done_i = '1' then
......@@ -966,10 +1009,11 @@ begin
s_wb_done <= '0';
end if;
if s_wb_start = '1' and s_cross_boundary = '0' then
-- Start WB cycle.
wb_cyc_o <= s_card_sel;
wb_stb_o <= s_card_sel;
if s_wb_start = '1' then
-- Start WB cycle (only for memory access and not
-- crossing boundaries).
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;
if vme_idff_write_n = '0' then
......@@ -979,7 +1023,7 @@ begin
data_reg (31 downto 1) <= vme_idff_addr;
data_reg (63 downto 32) <= vme_idff_data;
else
if addr_reg(0) = '0' then
if lword_n_reg = '0' then
-- 32bit access (lword is set)
data_reg (31 downto 0) <= vme_idff_data;
else
......@@ -995,7 +1039,7 @@ begin
-- 16bit access on a 16bit bus.
wb_sel_o (3 downto 2) <= "00";
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
wb_sel_o <= "1111";
else
......@@ -1011,11 +1055,28 @@ begin
end case;
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_stall <= '1'; -- Can stall
s_err <= '0';
if s_card_sel = '1' then
if s_card_sel = '1' and s_cross_boundary = '0' then
s_WBFSMstate <= MEMORY_REQ;
elsif s_conf_sel = '1' then
if vme_idff_write_n = '1' then
......@@ -1042,10 +1103,10 @@ begin
case g_WB_MODE is
when CLASSIC =>
-- Maintain STB.
wb_stb_o <= '1';
wb_stb_out <= '1';
when PIPELINED =>
-- 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;
s_stall <= s_stall and wb_stall_i;
......@@ -1053,7 +1114,7 @@ begin
if wb_ack_i = '1' or wb_err_i = '1' then
-- WB ack
-- For classic mode, be sure strobe is negated.
wb_stb_o <= '0';
wb_stb_out <= '0';
if s_transferType /= SINGLE then
-- Next word for any block transfer.
......@@ -1061,12 +1122,12 @@ begin
-- BLT must not cross any 256 byte boundary.
-- VITA 1-1994 RULE 2.78
-- MBLT cycles MUST not cross any 2048 byte boundary.
addr_reg (10 downto 2) <=
std_logic_vector (unsigned(addr_reg (10 downto 2)) + 1);
addr_reg (10 downto 0) <= n_addr_reg;
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';
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';
end if;
end if;
......@@ -1098,7 +1159,7 @@ begin
-- Mux (CS-CSR or WB)
data_reg(63 downto 32) <= data_reg(31 downto 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
-- Word/byte access with A1 = 0 on a 32bit bus.
data_reg(15 downto 0) <= wb_dat_i(31 downto 16);
......@@ -1116,7 +1177,7 @@ begin
s_WBFSMstate <= MEMORY_PAUSE;
when PIPELINED =>
-- No need to pause, can directly start a new xfer.
wb_stb_o <= '1';
wb_stb_out <= '1';
s_stall <= '1';
s_WBFSMstate <= MEMORY_REQ;
end case;
......@@ -1133,10 +1194,10 @@ begin
when MEMORY_PAUSE =>
-- Wait until ACK is 0. Strictly speaking, this is not needed
-- according to WB specs.
wb_stb_o <= '0';
wb_stb_out <= '0';
if wb_ack_i = '0' then
wb_stb_o <= '1';
wb_stb_out <= '1';
s_stall <= '1';
s_WBFSMstate <= MEMORY_REQ;
else
......@@ -1179,20 +1240,23 @@ begin
vme_lword_n_o <= vme_odff_lword_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;
process (vme_odff_dtack_n, vme_nsync_ds_n_i, vme_dtack_async_ctrl)
begin
if vme_dtack_async_ctrl = '0' then
vme_dtack_n_o <= vme_odff_dtack_n;
if vme_dtack_async_ctrl = '0' or not g_ASYNC_DTACK then
vme_dtack_n_out <= vme_odff_dtack_n;
else
-- 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).
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 process;
vme_dtack_n_o <= vme_dtack_n_out;
wb_stb_o <= wb_stb_out;
end rtl;
......@@ -67,6 +67,14 @@ entity xvme64x_core is
-- Do not forget to assign g_DECODER if set to True.
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:
-- 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.
......@@ -237,12 +245,16 @@ architecture rtl of xvme64x_core is
signal s_vme_iack_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.
-- (use downto in the aggregate as a workaround Vivado 2020 bug).
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#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');
begin
assert g_CLOCK_PERIOD > 0 report "g_CLOCK_PERIOD generic must be set"
......@@ -326,6 +338,7 @@ begin
g_CLOCK_PERIOD => g_CLOCK_PERIOD,
g_VME32 => g_VME32,
g_VME_2E => g_VME_2E,
g_ASYNC_DTACK => g_ASYNC_DTACK,
g_WB_GRANULARITY => g_WB_GRANULARITY,
g_WB_MODE => g_WB_MODE)
port map (
......@@ -337,12 +350,12 @@ begin
vme_lword_n_o => vme_o.lword_n,
vme_lword_n_i => vme_i.lword_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_ds_n_i => s_vme_ds_n,
vme_nsync_ds_n_i => vme_i.ds_n, -- Not synchronized.
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_addr_i => vme_i.addr,
vme_addr_o => vme_o.addr,
......@@ -389,13 +402,17 @@ begin
int_vector_i => s_irq_vector,
irq_pending_i => s_irq_pending,
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;
rst_n_o <= s_reset_n and (not s_module_reset);
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
generic map (
g_DECODER => g_DECODER,
......@@ -512,14 +529,14 @@ begin
gen_ext_user_csr : if g_USER_CSR_EXT = true generate
s_user_csr_data_i <= user_csr_data_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;
gen_disable_cr_csr : if g_ENABLE_CR_CSR = false generate
s_user_csr_data_i <= user_csr_data_i;
s_cr_csr_data_o <= s_user_csr_data_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_data_o <= s_cr_csr_data_i;
s_user_csr_we <= s_cr_csr_we;
......
......@@ -3,10 +3,10 @@ set -e
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 "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
echo "Simulation failed!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
exit 1
......
......@@ -30,7 +30,7 @@
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html
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;
library ieee;
......@@ -256,6 +256,8 @@ architecture behaviour of top_tb is
signal bus_timer : std_logic;
signal end_tb : boolean := false;
signal gen_int : boolean := false;
signal err_8000 : natural := 0;
begin
set_ga: block
......@@ -475,6 +477,9 @@ begin
irq_i <= '1';
end if;
end if;
if gen_int then
irq_i <= '1';
end if;
if STB_o = '1' and CYC_o = '1' then
ACK_i <= '1';
......@@ -1167,7 +1172,7 @@ begin
variable d16 : word_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 v16 : word_array_t (0 to 16);
begin
......@@ -1318,17 +1323,15 @@ begin
and v32 (4) = x"8765_4321"
report "incorrect BLT data 32" severity error;
if false then
-- D16 BLT not supported
read16_blt (x"64_00_00_14", c_AM_A32_BLT, v16 (0 to 5));
assert v16 (0) = x"0000"
and v16 (1) = x"0500"
and v16 (2) = x"0006"
and v16 (3) = x"0000"
and v16 (4) = x"0700"
and v16 (5) = x"0000"
report "incorrect BLT data 16" severity error;
end if;
-- D16 BLT now supported
read16_blt (x"64_00_00_14", c_AM_A32_BLT, v16 (0 to 5));
assert v16 (0) = x"0000"
and v16 (1) = x"0500"
and v16 (2) = x"0006"
and v16 (3) = x"0000"
and v16 (4) = x"0700"
and v16 (5) = x"0000"
report "incorrect BLT data 16" severity error;
v32 (0 to 3) := (x"00_11_22_33",
x"44_55_66_77",
......@@ -1555,7 +1558,37 @@ begin
assert d32 = x"C000_3004"
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;
wait for 4 * g_CLOCK_PERIOD * 1 ns;
......
......@@ -11,5 +11,6 @@ files = [
]
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