Commit c8c501f5 authored by Tristan Gingold's avatar Tristan Gingold

vme_bus: new prefetch.

parent e9ae25eb
......@@ -55,6 +55,7 @@ use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.vme64x_pkg.all;
use work.wishbone_pkg.all;
use work.gencores_pkg.all;
entity vme_bus is
generic (
......@@ -128,13 +129,10 @@ entity vme_bus is
end vme_bus;
architecture rtl of vme_bus is
-- Local data
signal s_locDataIn : std_logic_vector(63 downto 0);
signal s_locDataOut : std_logic_vector(63 downto 0);
-- VME latched signals - corresponds to the input dff in the pad.
-- latched at the rising edge of /AS:
signal vme_idff_addr : std_logic_vector(31 downto 1);
signal vme_idff_data : std_logic_vector(31 downto 0);
signal vme_idff_lword_n : std_logic;
signal vme_idff_am : std_logic_vector(5 downto 0);
......@@ -146,7 +144,17 @@ architecture rtl of vme_bus is
signal vme_odff_addr : std_logic_vector(31 downto 1);
signal vme_odff_data : std_logic_vector(31 downto 0);
signal vme_odff_lword_n : std_logic;
signal vme_odff_addr_dir : std_logic;
signal vme_odff_addr_dir : std_logic;
-- Register containing the address. Initialized from VME, adjusted
-- by address decoder, and incremented during DMA.
signal addr_reg : std_logic_vector(31 downto 0);
-- Load addr_reg from vme idff (for address phase1).
signal load_addr_reg_phase1 : std_logic;
-- Data register, owned by the WB fsm.
signal data_reg : std_logic_vector(63 downto 0);
type t_addressingType is (
A24,
......@@ -190,9 +198,6 @@ architecture rtl of vme_bus is
-- Decode DS, generate WB request
CHECK_TRANSFER_TYPE,
-- Wait for WB FSM
WAIT_WB_FSM,
-- For read cycle, put data on the bus
DATA_TO_BUS,
......@@ -221,7 +226,6 @@ architecture rtl of vme_bus is
-- Main FSM signals
signal s_mainFSMstate : t_mainFSMstates;
signal s_conf_req : std_logic; -- Global memory request
signal s_dataPhase : std_logic; -- for MBLT
signal s_MBLT_Data : std_logic; -- for MBLT: '1' in Addr
-- Access decode signals
......@@ -256,26 +260,18 @@ architecture rtl of vme_bus is
-- WB FSM signals
signal s_WBFSMstate : t_WBFSMstates;
signal s_WB_prefetch_buffer : std_logic_vector(63 downto 0);
-- Synch signals for MAIN FSM and WB FSM
signal s_wb_done : std_logic;
signal s_wb_start : std_logic;
signal s_wb_DTACK_LOW : std_logic;
signal s_wb_prefetch : std_logic;
signal s_wb_first_pf : std_logic;
signal s_wb_dataPhase : std_logic;
signal s_wb_vme_addr_reg : std_logic_vector(31 downto 1);
signal s_wb_locDataIn : std_logic_vector(63 downto 0);
signal s_wb_locDataOut : std_logic_vector(63 downto 0);
signal s_wb_dataphase : std_logic;
signal s_data_on_bus : std_logic;
-- Set after address increment to enable a new prefetch.
signal s_pom : std_logic;
signal incr : natural range 0 to 7; -- just to keep track of addr_word_incr
begin
-- These output signals are connected to the buffers on the board
-- SN74VMEH22501A Function table: (A is fpga, B is VME connector)
......@@ -330,7 +326,6 @@ begin
-- MAIN FSM
------------------------------------------------------------------------------
p_VMEmainFSM : process (clk_i) is
variable addr_word_incr : natural range 0 to 7;
begin
if rising_edge(clk_i) then
if rst_n_i = '0' or vme_as_n_i = '1' then
......@@ -344,21 +339,18 @@ begin
vme_dtack_oe_o <= '0';
vme_dtack_n_o <= '1';
vme_data_dir_o <= '0';
vme_addr_dir_o <= '0';
vme_odff_addr_dir <= '0';
vme_berr_n_o <= '1';
vme_addr_o <= (others => '0');
vme_lword_n_o <= '1';
vme_data_o <= (others => '0');
vme_iackout_n_o <= '1';
s_dataPhase <= '0';
s_MBLT_Data <= '0';
s_mainFSMstate <= IDLE;
s_data_on_bus <= '0';
-- WB
wb_sel_o <= "0000";
s_wb_start <= '0';
s_wb_first_pf <= '1';
s_wb_prefetch <= '0';
vme_idff_addr <= (others => '0');
......@@ -367,6 +359,8 @@ begin
vme_odff_addr <= (others => '0');
vme_odff_addr_dir <= '0';
load_addr_reg_phase1 <= '0';
s_card_sel <= '0';
s_conf_sel <= '0';
s_irq_sel <= '0';
......@@ -377,11 +371,14 @@ begin
vme_dtack_oe_o <= '0';
vme_dtack_n_o <= '1';
vme_data_dir_o <= '0';
vme_addr_dir_o <= '0';
vme_odff_addr_dir <= '0';
vme_berr_n_o <= '1';
vme_iackout_n_o <= '1';
irq_ack_o <= '0';
load_addr_reg_phase1 <= '0';
s_wb_start <= '0';
case s_mainFSMstate is
when IDLE =>
......@@ -394,6 +391,9 @@ begin
vme_idff_lword_n <= vme_lword_n_i;
vme_idff_am <= vme_am_i;
-- Address will be put to addr_reg.
load_addr_reg_phase1 <= '1';
if vme_iack_n_i = '1' then
-- ANSI/VITA 1-1994 Rule 2.11
-- Slaves MUST NOT respond to DTB cycles when IACK* is low.
......@@ -404,21 +404,6 @@ begin
end if;
when REFORMAT_ADDRESS =>
-- Reformat address according to the mode (A16, A24, A32)
-- FIXME: not needed if ADEM are correctly reduced to not compare
-- MSBs of A16 or A24 addresses.
vme_odff_addr <= vme_idff_addr;
case s_addressingType is
when A16 =>
vme_odff_addr (31 downto 16) <= (others => '0'); -- A16
when A24 | A24_BLT | A24_MBLT =>
vme_odff_addr (31 downto 24) <= (others => '0'); -- A24
when others =>
null; -- A32
end case;
vme_odff_lword_n <= vme_idff_lword_n;
-- Address is not yet decoded.
s_card_sel <= '0';
s_conf_sel <= '0';
......@@ -465,10 +450,9 @@ begin
if decode_sel_i = '1' and module_enable_i = '1' then
-- card_sel = '1' it means WB application addressed
s_card_sel <= '1';
-- Keep only the local part of the address.
vme_odff_addr <= addr_decoder_i;
if vme_ds_n_i = "11" then
-- Still have to wait for DS...
s_mainFSMstate <= WAIT_FOR_DS;
else
s_mainFSMstate <= LATCH_DS;
......@@ -487,79 +471,17 @@ begin
-- wait until DS /= "11"
-- Note: before entering this state, s_DS_latch_count must be set.
-- if vme_ds_n_i /= "11" then
-- -- ANSI/VITA 1-1994 Table 4-1
-- -- For interrupts ack, the handler MUST NOT drive WRITE* low
-- vme_idff_write_n <= vme_write_n_i;
-- if s_DS_latch_count /= 0 then
-- s_DS_latch_count <= s_DS_latch_count - 1;
-- end if;
-- s_mainFSMstate <= LATCH_DS;
-- else
-- s_mainFSMstate <= WAIT_FOR_DS;
-- end if;
if s_wb_prefetch = '1'
and s_transferType = MBLT
and s_WBFSMstate = IDLE
and vme_ds_n_i = "11"
and s_data_on_bus = '0'
then
-- Previous Data was read, new Data is prefetched, but a new
-- read req is not yet issued by the master
-- Already prepare data on vmebus
-- Put data to VME bus from s_wb_locDataOut
vme_addr_o <= s_wb_locDataOut(63 downto 33);
vme_lword_n_o <= s_wb_locDataOut(32);
vme_data_o <= s_wb_locDataOut(31 downto 0);
vme_data_dir_o <= '1';
vme_addr_dir_o <= '1';
vme_dtack_oe_o <= '1';
s_data_on_bus <= '1';
end if;
-- MBLT read only going to S1, S2 (Should optimize this state
-- obviously)
if vme_ds_n_i /= "11"
and s_transferType = MBLT
and s_wb_prefetch = '1'
and s_WBFSMstate = IDLE
then
if vme_ds_n_i /= "11" then
-- ANSI/VITA 1-1994 Table 4-1
-- For interrupts ack, the handler MUST NOT drive WRITE* low
vme_idff_write_n <= vme_write_n_i;
if s_DS_latch_count /= 0 then
s_DS_latch_count <= s_DS_latch_count - 1;
end if;
if s_data_on_bus = '0' then
s_mainFSMstate <= S1;
-- Put data to VME bus from s_wb_locDataOut
vme_addr_o <= s_wb_locDataOut(63 downto 33);
vme_lword_n_o <= s_wb_locDataOut(32);
vme_data_o <= s_wb_locDataOut(31 downto 0);
vme_data_dir_o <= '1';
vme_addr_dir_o <= '1';
vme_dtack_oe_o <= '1';
else
s_mainFSMstate <= S2;
vme_dtack_n_o <= '0';
-- start prefetch
s_wb_start <= '1';
vme_data_dir_o <= '1';
vme_addr_dir_o <= '1';
vme_dtack_oe_o <= '1';
s_data_on_bus <= '0';
end if;
elsif vme_ds_n_i /= "11" and s_wb_prefetch /= '1' then
-- ANSI/VITA 1-1994 Table 4-1
-- For interrupts ack, the handler MUST NOT drive WRITE* low
-- Sample write. It must be stable before DS.
vme_idff_write_n <= vme_write_n_i;
if s_DS_latch_count /= 0 then
s_DS_latch_count <= s_DS_latch_count - 1;
end if;
s_mainFSMstate <= LATCH_DS;
else
s_mainFSMstate <= WAIT_FOR_DS;
......@@ -573,39 +495,35 @@ begin
-- During all read cycles [...], the responding slave MUST NOT
-- drive the D[] lines until DSA* goes low.
vme_data_dir_o <= vme_idff_write_n;
vme_addr_dir_o <= '0';
vme_odff_addr_dir <= '0';
if g_VME32 and s_transferType = MBLT then
s_dataPhase <= '1';
if s_DS_latch_count = 0 or s_transferType = MBLT then
-- Read DS (which is delayed to avoid metastability).
vme_idff_ds_n <= vme_ds_n_i;
-- Start with D[31..0] when writing, but D[63..32] when reading.
vme_odff_addr(2) <= not vme_idff_write_n;
else
s_dataPhase <= '0';
end if;
-- Read DATA (which are stable)
vme_idff_addr <= vme_addr_i;
vme_idff_lword_n <= vme_lword_n_i;
vme_idff_data <= vme_data_i;
if s_DS_latch_count = 0 or s_transferType = MBLT then
if s_irq_sel = '1' then
s_mainFSMstate <= DATA_TO_BUS;
elsif s_transferType = MBLT and s_MBLT_Data = '0' then
-- MBLT: ack address.
-- (Data are also read but discarded).
s_mainFSMstate <= DTACK_LOW;
if vme_idff_write_n = '1' then
-- Can fetch the first data.
s_wb_start <= '1';
end if;
else
s_mainFSMstate <= CHECK_TRANSFER_TYPE;
if s_wb_prefetch = '0' then
-- For every single access or every access at MBLT WRITE
s_wb_start <= '1'; -- lets do it when entering CTT
-- For every single access or every access at MBLT WRITE
if not (s_transferType = MBLT and vme_idff_write_n = '1') then
s_wb_start <= '1';
end if;
end if;
-- Read DS (which is delayed to avoid metastability).
vme_idff_ds_n <= vme_ds_n_i;
-- Read DATA (which are stable)
s_locDataIn(63 downto 33) <= vme_addr_i;
vme_idff_lword_n <= vme_lword_n_i;
vme_odff_data <= vme_data_i;
else
s_mainFSMstate <= LATCH_DS;
s_DS_latch_count <= s_DS_latch_count - 1;
......@@ -613,8 +531,6 @@ begin
when CHECK_TRANSFER_TYPE =>
vme_data_dir_o <= vme_idff_write_n;
vme_addr_dir_o <= '0';
s_dataPhase <= s_dataPhase;
-- vme_addr is an output during MBLT *read* data transfer.
if s_transferType = MBLT and vme_idff_write_n = '1' and g_VME32 then
......@@ -623,34 +539,6 @@ begin
vme_odff_addr_dir <= '0';
end if;
s_locDataIn(32) <= vme_idff_lword_n;
s_locDataIn(31 downto 0) <= vme_odff_data;
if vme_odff_lword_n = '1' and vme_odff_addr(1) = '0' and g_VME32 then
-- Word/byte access with A1=0
s_locDataIn(31 downto 16) <= vme_odff_data(15 downto 0);
end if;
-- Translate DS+LWORD+ADDR to WB byte selects
if not g_VME32 then
-- 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 vme_odff_lword_n = '0' then
-- 32bit access
wb_sel_o <= "1111";
else
-- 16bit access on a 32bit bus.
wb_sel_o <= "0000";
case vme_odff_addr(1) is
when '0' =>
wb_sel_o (3 downto 2) <= not vme_idff_ds_n;
when '1' =>
wb_sel_o (1 downto 0) <= not vme_idff_ds_n;
when others =>
null;
end case;
end if;
-- ANSI/VITA 1-1994 Rule 2.6
-- A Slave MUST NOT respond with a falling edge on DTACK* during
-- an unaligned transfer cycle, if it does not have UAT
......@@ -658,63 +546,39 @@ begin
if vme_odff_lword_n = '0' and vme_idff_ds_n /= "00" then
-- unaligned.
s_mainFSMstate <= WAIT_END;
elsif s_WBFSMstate = IDLE and s_wb_prefetch = '1' then
-- There was a prefetch that has finished. So, only if prefetch
-- is done and there is a new read request
s_mainFSMstate <= DATA_TO_BUS;
s_wb_start <= '1'; -- start next prefetch
s_locDataOut <= s_wb_locDataOut; -- Take the prefetched data
else
s_mainFSMstate <= WAIT_WB_FSM;
-- s_wb_start <= '1'; -- lets do it when entering CTT
s_mainFSMstate <= DATA_TO_BUS;
s_conf_req <= s_conf_sel;
end if;
-- Needed to add this here because it must be available sooner
-- for prefetch. May be reduntant at CTT
if g_VME32 and vme_odff_lword_n = '0' and vme_idff_write_n = '1' then
if s_transferType = MBLT then
-- 64 bit
addr_word_incr := 4;
else
-- 32 bit
addr_word_incr := 2;
end if;
else
null; -- Just do it for MBLT read, let other cases be determined at their places
end if;
when DATA_TO_BUS =>
vme_dtack_oe_o <= '1';
vme_data_dir_o <= vme_idff_write_n;
vme_addr_dir_o <= vme_odff_addr_dir;
if g_VME32 then
-- only for MBLT
vme_addr_o <= s_locDataOut(63 downto 33);
vme_lword_n_o <= s_locDataOut(32);
end if;
vme_data_o <= s_locDataOut(31 downto 0);
-- ANSI/VITA 1-1994 Rule 2.54a
-- During all read cycles, the responding Slave MUST NOT drive
-- DTACK* low before it drives D[].
s_mainFSMstate <= DTACK_LOW;
-- Update what WB FSM prepared
if s_conf_sel = '1' or s_wb_done = '1' or s_irq_sel = '1' then
vme_dtack_oe_o <= '1';
vme_data_dir_o <= vme_idff_write_n;
if g_VME32 then
-- only for MBLT
vme_addr_o <= data_reg(63 downto 33);
vme_lword_n_o <= data_reg(32);
end if;
vme_data_o <= data_reg(31 downto 0);
if vme_idff_write_n = '1' then
-- if it is a read, but not MBLT or 1st MBLT data
vme_dtack_n_o <= '0';
end if;
if s_transferType = MBLT and vme_idff_write_n = '1' then
-- Prefetch.
s_wb_start <= '1';
end if;
if s_wb_prefetch = '1' then
s_wb_start <= '0';
-- ANSI/VITA 1-1994 Rule 2.54a
-- During all read cycles, the responding Slave MUST NOT drive
-- DTACK* low before it drives D[].
s_mainFSMstate <= DTACK_LOW;
end if;
when DTACK_LOW =>
-- Think this block can execute when moving from WAIT_WB_FSM to DTACK_LOW
-- Set /DTACK, wait until /DS[1:0] are released.
vme_dtack_oe_o <= '1';
vme_data_dir_o <= vme_idff_write_n;
vme_addr_dir_o <= vme_odff_addr_dir;
-- Set DTACK (or retry or berr)
if s_card_sel = '1' and s_err = '1' then
......@@ -744,65 +608,21 @@ begin
-- the same address (RMW).
s_mainFSMstate <= WAIT_FOR_DS;
else
-- Any block transfer.
if g_VME32 and s_transferType = MBLT and s_MBLT_Data = '0' then
-- MBLT: end of address phase.
s_mainFSMstate <= WAIT_FOR_DS;
s_MBLT_Data <= '1';
else
-- Block
s_mainFSMstate <= INCREMENT_ADDR;
end if;
s_mainFSMstate <= WAIT_FOR_DS;
end if;
else
s_mainFSMstate <= DTACK_LOW;
end if;
if s_wb_prefetch = '1'
and s_transferType = MBLT
and s_WBFSMstate = IDLE
and vme_ds_n_i = "11"
and s_data_on_bus = '0'
then
-- Previous Data was read, new Data is prefetched, but a new read
-- req is not yet issued by the master
-- Already prepare data on vmebus
-- Put data to VME bus from s_wb_locDataOut
vme_addr_o <= s_wb_locDataOut(63 downto 33);
vme_lword_n_o <= s_wb_locDataOut(32);
vme_data_o <= s_wb_locDataOut(31 downto 0);
vme_data_dir_o <= '1';
vme_addr_dir_o <= '1';
vme_dtack_oe_o <= '1';
s_data_on_bus <= '1';
end if;
when INCREMENT_ADDR =>
vme_dtack_oe_o <= '1';
vme_addr_dir_o <= vme_odff_addr_dir;
if g_VME32 and vme_odff_lword_n = '0' then
if s_transferType = MBLT then
-- 64 bit
addr_word_incr := 4;
else
-- 32 bit
addr_word_incr := 2;
end if;
else
if vme_idff_ds_n (0) = '0' then
-- Next word for D16 or D08(O)
addr_word_incr := 1;
else
addr_word_incr := 0;
end if;
end if;
-- Only increment within the window, don't check the limit.
-- BLT --> limit = 256 bytes (rule 2.12a ANSI/VITA 1-1994)
-- MBLT --> limit = 2048 bytes (rule 2.78 ANSI/VITA 1-1994)
vme_odff_addr (11 downto 1) <= std_logic_vector
(unsigned(vme_odff_addr (11 downto 1)) + addr_word_incr);
s_mainFSMstate <= WAIT_FOR_DS;
if s_wb_prefetch = '1' then
......@@ -819,9 +639,9 @@ begin
-- read req is not yet issued by the master
-- Already prepare data on vmebus
-- Put data to VME bus from s_wb_locDataOut
vme_addr_o <= s_wb_locDataOut(63 downto 33);
vme_lword_n_o <= s_wb_locDataOut(32);
vme_data_o <= s_wb_locDataOut(31 downto 0);
vme_addr_o <= data_reg(63 downto 33);
vme_lword_n_o <= data_reg(32);
vme_data_o <= data_reg(31 downto 0);
vme_data_dir_o <= '1';
vme_addr_dir_o <= '1';
vme_dtack_oe_o <= '1';
......@@ -835,8 +655,8 @@ begin
and irq_pending_i = '1'
then
-- That's for us
s_locDataOut <= (others => '0');
s_locDataOut (7 downto 0) <= int_vector_i;
vme_odff_data <= (others => '0');
vme_odff_data (7 downto 0) <= int_vector_i;
s_irq_sel <= '1';
irq_ack_o <= '1';
......@@ -859,71 +679,6 @@ begin
-- Will stay here until AS is released.
s_mainFSMstate <= WAIT_END;
when WAIT_WB_FSM =>
-- Update what WB FSM prepared
s_dataPhase <= s_wb_dataPhase;
if s_wb_done = '1' then -- Solving the unaligned data during write
s_locDataIn <= s_wb_locDataIn;
elsif s_WBFSMstate = MEMORY_PAUSE then
s_locDataIn <= s_wb_locDataIn;
end if;
s_locDataOut <= s_wb_locDataOut;
vme_odff_addr <= s_wb_vme_addr_reg; --may be possible only 1 bit
s_wb_start <= '0';
if s_wb_done = '1' then
s_mainFSMstate <= DATA_TO_BUS;
if (s_transferType = MBLT) and (vme_idff_write_n = '1') then
-- MBLT read (Might want to specify exactly the one MBLT of
-- interest)
s_wb_prefetch <= '1'; -- needs to be reset somewhere
s_wb_start <= '1';
s_dataPhase <= '1'; -- because WB FMS will be reading 1st
-- 32 bit word first when prefetching
-- Only increment within the window, don't check the limit.
-- MBLT --> limit = 2048 bytes (rule 2.78 ANSI/VITA 1-1994)
if s_wb_first_pf = '1' then
vme_odff_addr (11 downto 1) <= std_logic_vector
(unsigned(vme_odff_addr (11 downto 1)) + addr_word_incr/2 ); -- Only for first prefetch, @ A32 MBLT 64
s_wb_first_pf <= '0';
else
null; -- the other MAIN FSM states will prepare the adress in case of not first prefetch
end if;
end if;
if vme_idff_write_n = '1' and s_wb_prefetch = '0' then
-- if it is a read, but not MBLT or 1st MBLT data
vme_dtack_oe_o <= '1';
vme_data_dir_o <= vme_idff_write_n;
vme_addr_dir_o <= vme_odff_addr_dir;
if g_VME32 then
-- only for MBLT
vme_addr_o <= s_wb_locDataOut(63 downto 33);
vme_lword_n_o <= s_wb_locDataOut(32);
end if;
vme_data_o <= s_wb_locDataOut(31 downto 0);
end if;
elsif ((s_wb_DTACK_LOW = '1')
or ((s_WBFSMstate = MEMORY_REQ) and (s_DataPhase = '0')
and (vme_idff_write_n = '0') and (wb_ack_i = '1')))
then
-- added or to not loose a cycle for acknowledging.
-- Solving for write only 1st.
s_mainFSMstate <= DTACK_LOW;
-- Maybe DTACK LOW needs to use this info for further actions?
else
s_mainFSMstate <= WAIT_WB_FSM;
end if;
when s1 =>
s_mainFSMstate <= s2;
vme_dtack_n_o <= '0';
......@@ -962,9 +717,9 @@ begin
-- Previous Data was read, new Data is prefetched, but a new read req is not yet issued by the master
-- Already prepare data on vmebus
-- Put data to VME bus from s_wb_locDataOut
vme_addr_o <= s_wb_locDataOut(63 downto 33);
vme_lword_n_o <= s_wb_locDataOut(32);
vme_data_o <= s_wb_locDataOut(31 downto 0);
vme_addr_o <= data_reg(63 downto 33);
vme_lword_n_o <= data_reg(32);
vme_data_o <= data_reg(31 downto 0);
vme_data_dir_o <= '1';
vme_addr_dir_o <= '1';
vme_dtack_oe_o <= '1';
......@@ -986,7 +741,6 @@ begin
end if;
end if;
end if;
incr <= addr_word_incr;
end process;
------------------------------------------------------------------------------
......@@ -1004,10 +758,10 @@ begin
-- WB
wb_cyc_o <= '0';
wb_stb_o <= '0';
wb_sel_o <= "0000";
wb_we_o <= '0';
s_err <= '0';
s_wb_DTACK_LOW <= '0';
s_wb_done <= '0';
else
case s_WBFSMstate is
......@@ -1016,31 +770,85 @@ begin
-- cycle.
assert vme_as_n_i = '0';
s_wb_DTACK_LOW <= '0';
s_wb_done <= '0';
if load_addr_reg_phase1 = '1' then
addr_reg (31 downto 1) <= vme_idff_addr;
addr_reg (0) <= vme_idff_lword_n;
-- Reformat address according to the mode (A16, A24, A32)
-- FIXME: not needed if ADEM are correctly reduced to not compare
-- MSBs of A16 or A24 addresses.
case s_addressingType is
when A16 =>
addr_reg (31 downto 16) <= (others => '0'); -- A16
when A24 | A24_BLT | A24_MBLT =>
addr_reg (31 downto 24) <= (others => '0'); -- A24
when others =>
null; -- A32
end case;
end if;
-- Latching some important signals from the main FSM
s_wb_dataPhase <= s_dataPhase;
s_wb_vme_addr_reg <= vme_odff_addr;
s_wb_locDataIn <= s_locDataIn;
if decode_done_i = '1' then
-- Keep only the local part of the address.
addr_reg (31 downto 1) <= addr_decoder_i;
end if;
if s_wb_start = '1' then
-- Start WB cycle.
wb_cyc_o <= s_card_sel;
wb_stb_o <= s_card_sel;
s_stall <= '1'; -- Can stall
s_err <= '0';
s_WBFSMstate <= MEMORY_REQ;
elsif vme_ds_n_i /= "11" and s_wb_prefetch = '1' and s_pom = '1'
then
if s_wb_start = '1' or s_wb_prefetch = '1' then
-- Start WB cycle.
wb_cyc_o <= s_card_sel;
wb_stb_o <= s_card_sel;
wb_we_o <= not vme_idff_write_n;
s_wb_done <= '0';
--if vme_odff_lword_n = '1' and vme_odff_addr(1) = '0' and g_VME32 then
-- -- Word/byte access with A1=0
-- s_locDataIn(31 downto 16) <= vme_odff_data(15 downto 0);
--end if;
if vme_idff_write_n = '0' then
-- Get the data to write (in case of write!).
if g_VME32 and s_transferType = MBLT then
data_reg (0) <= vme_idff_lword_n;
data_reg (31 downto 1) <= vme_idff_addr;
data_reg (63 downto 32) <= vme_idff_data;
else
data_reg (31 downto 0) <= vme_idff_data;
data_reg (32) <= vme_idff_lword_n;
data_reg (63 downto 33) <= vme_idff_addr;
end if;
end if;
-- Translate DS+LWORD+ADDR to WB byte selects
if not g_VME32 then
-- 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' then
-- 32bit access
wb_sel_o <= "1111";
else
-- 16bit access on a 32bit bus.
wb_sel_o <= "0000";
case addr_reg(1) is
when '0' =>
wb_sel_o (3 downto 2) <= not vme_idff_ds_n;
when '1' =>
wb_sel_o (1 downto 0) <= not vme_idff_ds_n;
when others =>
null;
end case;
end if;
s_wb_dataphase <= f_to_std_logic (s_transferType = MBLT);
s_stall <= '1'; -- Can stall
s_err <= '0';
s_WBFSMstate <= MEMORY_REQ;
s_wb_dataPhase <= '1';
if s_card_sel = '1' then
s_WBFSMstate <= MEMORY_REQ;
else
s_wb_done <= '1';
s_WBFSMstate <= IDLE;
end if;
else
-- Wait in IDLE until s_wb_start = '1'
s_WBFSMstate <= IDLE;
......@@ -1051,10 +859,6 @@ begin
-- generate a pulse on s_conf_req signal
-- Assert STB if stall was asserted.
if s_dataPhase = '1' then -- fix Data for write
s_wb_locDataIn <= s_locDataIn;
end if;
case g_WB_MODE is
when CLASSIC =>
-- Maintain STB.
......@@ -1071,26 +875,31 @@ begin
then
-- WB ack
wb_stb_o <= '0';
s_err <= s_card_sel and wb_err_i;
if s_transferType /= SINGLE then
-- Next word for any block transfer.
addr_reg (11 downto 2) <=
std_logic_vector (unsigned(addr_reg (11 downto 2)) + 1);
end if;
if (s_card_sel and wb_err_i) = '1' then
-- Error
s_wb_DTACK_LOW <= '1';
s_err <= '1';
s_WBFSMstate <= IDLE;
elsif vme_idff_write_n = '0' then
-- Write cycle.
if s_wb_dataPhase = '1' then
-- MBLT
s_wb_dataPhase <= '0';
s_wb_vme_addr_reg(2) <= '0';
s_wb_locDataIn(31 downto 0) <= s_wb_locDataIn(63 downto 32);
data_reg(31 downto 0) <= data_reg(63 downto 32);
-- STB is 0, wait one cycle before the 2nd xfer.
s_WBFSMstate <= MEMORY_PAUSE;
else
s_wb_DTACK_LOW <= '1';
-- done, IDLE?
s_wb_done <= '1';
s_WBFSMstate <= IDLE;
end if;
......@@ -1098,23 +907,23 @@ begin
-- Read cycle
-- Mux (CS-CSR or WB)
s_wb_locDataOut(63 downto 32) <= s_wb_locDataOut(31 downto 0);
s_wb_locDataOut(31 downto 0) <= (others => '0');
data_reg(63 downto 32) <= data_reg(31 downto 0);
data_reg(31 downto 0) <= (others => '0');
if s_card_sel = '1' then
if g_VME32 and vme_odff_lword_n = '1' and s_wb_vme_addr_reg(1) = '0' then
if g_VME32 and vme_odff_lword_n = '1' and addr_reg(1) = '0'
then
-- Word/byte access with A1 = 0 on a 32bit bus.
s_wb_locDataOut(15 downto 0) <= wb_dat_i(31 downto 16);
data_reg(15 downto 0) <= wb_dat_i(31 downto 16);
else
s_wb_locDataOut(31 downto 0) <= wb_dat_i;
data_reg(31 downto 0) <= wb_dat_i;
end if;
else
s_wb_locDataOut(7 downto 0) <= cr_csr_data_i;
data_reg(7 downto 0) <= cr_csr_data_i;
end if;
if s_wb_dataPhase = '1' and g_VME32 then
-- MBLT
s_wb_dataPhase <= '0';
s_wb_vme_addr_reg(2) <= '1';
-- STB is 0, wait one cycle before the 2nd xfer.
s_WBFSMstate <= MEMORY_PAUSE;
......@@ -1151,74 +960,29 @@ begin
-- WB Master
-- g_wb_addr32: if g_VME32 generate
-- with g_WB_GRANULARITY select
-- wb_adr_o <= "00" & vme_odff_addr(31 downto 2) when WORD,
-- vme_odff_addr(31 downto 2) & "00" when BYTE;
-- end generate;
-- g_wb_addr16: if not g_VME32 generate
-- with g_WB_GRANULARITY select
-- wb_adr_o <= "0" & vme_odff_addr(31 downto 1) when WORD,
-- vme_odff_addr(31 downto 1) & "0" when BYTE;
-- end generate;
-- -- g_wb_addr32_pf: if g_VME32 generate
-- -- with g_WB_GRANULARITY select
-- -- wb_adr_o <= "00" & s_wb_vme_addr_reg(31 downto 2) when WORD,
-- -- s_wb_vme_addr_reg(31 downto 2) & "00" when BYTE;
-- -- end generate;
-- -- g_wb_addr16_pf: if not g_VME32 generate
-- -- with g_WB_GRANULARITY select
-- -- wb_adr_o <= "0" & s_wb_vme_addr_reg(31 downto 1) when WORD,
-- -- s_wb_vme_addr_reg(31 downto 1) & "0" when BYTE;
-- -- end generate;
process (vme_odff_addr, s_wb_vme_addr_reg)
begin
if (s_wb_prefetch = '0') then
if g_VME32 then
if g_WB_GRANULARITY = WORD then
wb_adr_o <= "00" & vme_odff_addr(31 downto 2);
elsif g_WB_GRANULARITY = BYTE then
wb_adr_o <= vme_odff_addr(31 downto 2) & "00";
end if;
elsif(not g_VME32) then
if g_WB_GRANULARITY = WORD then
wb_adr_o <= "0" & vme_odff_addr(31 downto 1);
elsif g_WB_GRANULARITY = BYTE then
wb_adr_o <= vme_odff_addr(31 downto 1) & "0";
end if;
end if;
elsif (s_wb_prefetch = '1') then
if g_VME32 then
if g_WB_GRANULARITY = WORD then
wb_adr_o <= "00" & s_wb_vme_addr_reg(31 downto 2);
elsif g_WB_GRANULARITY = BYTE then
wb_adr_o <= s_wb_vme_addr_reg(31 downto 2) & "00";
end if;
elsif(not g_VME32) then
if g_WB_GRANULARITY = WORD then
wb_adr_o <= "0" & s_wb_vme_addr_reg(31 downto 1);
elsif g_WB_GRANULARITY = BYTE then
wb_adr_o <= s_wb_vme_addr_reg(31 downto 1) & "0";
end if;
end if;
end if;
end process;
g_wb_addr32: if g_VME32 generate
with g_WB_GRANULARITY select
wb_adr_o <= "00" & addr_reg(31 downto 2) when WORD,
addr_reg(31 downto 2) & "00" when BYTE;
end generate;
g_wb_addr16: if not g_VME32 generate
with g_WB_GRANULARITY select
wb_adr_o <= "0" & addr_reg(31 downto 1) when WORD,
addr_reg(31 downto 1) & "0" when BYTE;
end generate;
wb_we_o <= not vme_idff_write_n;
wb_dat_o <= s_locDataIn(31 downto 0);
wb_dat_o <= data_reg(31 downto 0);
-- Function Decoder
addr_decoder_o <= vme_odff_addr;
addr_decoder_o <= addr_reg (31 downto 1);
am_o <= vme_idff_am;
-- CR/CSR In/Out
cr_csr_data_o <= s_locDataIn(7 downto 0);
cr_csr_addr_o <= vme_odff_addr(18 downto 2);
cr_csr_we_o <= '1' when s_conf_req = '1' and
vme_idff_write_n = '0'
else '0';
cr_csr_data_o <= data_reg(7 downto 0);
cr_csr_addr_o <= addr_reg(18 downto 2);
cr_csr_we_o <= '1' when s_conf_req = '1' and vme_idff_write_n = '0'
else '0';
vme_addr_dir_o <= vme_odff_addr_dir;
end rtl;
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