Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
V
VME64x core
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
VME64x core
Commits
a5b91e65
Commit
a5b91e65
authored
Jan 22, 2020
by
Tristan Gingold
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add vme_bus.vhd original modifications from Milos Vojinovic.
parent
350d15cc
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
1280 additions
and
779 deletions
+1280
-779
vme_bus.vhd
hdl/rtl/vme_bus.vhd
+1280
-779
No files found.
hdl/rtl/vme_bus.vhd
View file @
a5b91e65
--------------------------------------------------------------------------------
-- CERN (BE-CO-HT)
-- VME64x Core
-- http://www.ohwr.org/projects/vme64x-core
--------------------------------------------------------------------------------
--
-- unit name: VME_bus
--
-- description:
--
-- This block acts as interface between the VMEbus and the CR/CSR space or
-- WB bus.
--
--------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE
--------------------------------------------------------------------------------
-- This source file is free software; you can redistribute it and/or modify it
-- under the terms of the GNU Lesser General Public License as published by the
-- Free Software Foundation; either version 2.1 of the License, or (at your
-- option) any later version. This source is distributed in the hope that it
-- will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
-- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-- See the GNU Lesser General Public License for more details. You should have
-- received a copy of the GNU Lesser General Public License along with this
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html
--------------------------------------------------------------------------------
library
ieee
;
use
ieee
.
std_logic_1164
.
all
;
use
ieee
.
numeric_std
.
all
;
use
work
.
vme64x_pkg
.
all
;
use
work
.
wishbone_pkg
.
all
;
entity
vme_bus
is
generic
(
g_CLOCK_PERIOD
:
integer
;
g_VME32
:
boolean
;
g_WB_GRANULARITY
:
t_wishbone_address_granularity
;
g_WB_MODE
:
t_wishbone_interface_mode
);
port
(
clk_i
:
in
std_logic
;
rst_n_i
:
in
std_logic
;
-- VME signals
vme_as_n_i
:
in
std_logic
;
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_dtack_n_o
:
out
std_logic
;
vme_dtack_oe_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'
);
vme_addr_dir_o
:
out
std_logic
;
vme_addr_oe_n_o
:
out
std_logic
;
vme_data_i
:
in
std_logic_vector
(
31
downto
0
);
vme_data_o
:
out
std_logic_vector
(
31
downto
0
)
:
=
(
others
=>
'0'
);
vme_data_dir_o
:
out
std_logic
;
vme_data_oe_n_o
:
out
std_logic
;
vme_am_i
:
in
std_logic_vector
(
5
downto
0
);
vme_iackin_n_i
:
in
std_logic
;
vme_iack_n_i
:
in
std_logic
;
vme_iackout_n_o
:
out
std_logic
;
-- WB signals
wb_stb_o
:
out
std_logic
;
wb_ack_i
:
in
std_logic
;
wb_dat_o
:
out
std_logic_vector
(
31
downto
0
);
wb_dat_i
:
in
std_logic_vector
(
31
downto
0
);
wb_adr_o
:
out
std_logic_vector
(
31
downto
0
);
wb_sel_o
:
out
std_logic_vector
(
3
downto
0
);
wb_we_o
:
out
std_logic
;
wb_cyc_o
:
out
std_logic
;
wb_err_i
:
in
std_logic
;
wb_stall_i
:
in
std_logic
;
-- Function decoder
addr_decoder_i
:
in
std_logic_vector
(
31
downto
1
);
addr_decoder_o
:
out
std_logic_vector
(
31
downto
1
);
decode_start_o
:
out
std_logic
;
decode_done_i
:
in
std_logic
;
am_o
:
out
std_logic_vector
(
5
downto
0
);
decode_sel_i
:
in
std_logic
;
-- CR/CSR space signals:
cr_csr_addr_o
:
out
std_logic_vector
(
18
downto
2
);
cr_csr_data_i
:
in
std_logic_vector
(
7
downto
0
);
cr_csr_data_o
:
out
std_logic_vector
(
7
downto
0
);
cr_csr_we_o
:
out
std_logic
;
module_enable_i
:
in
std_logic
;
bar_i
:
in
std_logic_vector
(
4
downto
0
);
-- Interrupts
int_level_i
:
in
std_logic_vector
(
2
downto
0
);
int_vector_i
:
in
std_logic_vector
(
7
downto
0
);
irq_pending_i
:
in
std_logic
;
irq_ack_o
:
out
std_logic
);
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
signal
s_ADDRlatched
:
std_logic_vector
(
31
downto
1
);
signal
s_LWORDlatched_n
:
std_logic
;
signal
s_DSlatched_n
:
std_logic_vector
(
1
downto
0
);
signal
s_AMlatched
:
std_logic_vector
(
5
downto
0
);
signal
s_WRITElatched_n
:
std_logic
;
-- Address and data from the VME bus. There are two registers so that the
-- first one can be placed in the IOBs.
signal
s_vme_addr_reg
:
std_logic_vector
(
31
downto
1
);
signal
s_vme_data_reg
:
std_logic_vector
(
31
downto
0
);
signal
s_vme_lword_n_reg
:
std_logic
;
signal
s_vme_addr_dir
:
std_logic
;
type
t_addressingType
is
(
A24
,
A24_BLT
,
A24_MBLT
,
CR_CSR
,
A16
,
A32
,
A32_BLT
,
A32_MBLT
,
AM_ERROR
);
type
t_transferType
is
(
SINGLE
,
BLT
,
MBLT
,
TFR_ERROR
);
-- Addressing type (depending on vme_am_i)
signal
s_addressingType
:
t_addressingType
;
signal
s_transferType
:
t_transferType
;
type
t_mainFSMstates
is
(
-- Wait until AS is asserted.
IDLE
,
-- Reformat address according to AM.
REFORMAT_ADDRESS
,
-- Decoding ADDR and AM (selecting card or conf).
DECODE_ACCESS
,
-- Wait until DS is asserted.
WAIT_FOR_DS
,
-- Wait until DS is stable (and asserted).
LATCH_DS
,
-- Decode DS, generate WB request
CHECK_TRANSFER_TYPE
,
-- Wait for WB reply
MEMORY_REQ
,
-- Negate STB between half MBLT transactions
MEMORY_PAUSE
,
-- For read cycle, put data on the bus
DATA_TO_BUS
,
-- Assert DTACK
DTACK_LOW
,
-- Increment address for block transfers
INCREMENT_ADDR
,
-- Check if IACK is for this slave
IRQ_CHECK
,
-- Pass IACKIN to IACKOUT
IRQ_PASS
,
-- Wait until AS is deasserted
WAIT_END
);
-- 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
signal
s_conf_sel
:
std_logic
;
-- CR or CSR is addressed
signal
s_card_sel
:
std_logic
;
-- WB memory is addressed
signal
s_irq_sel
:
std_logic
;
-- IACK transaction
signal
s_err
:
std_logic
;
-- Stall status. Set to one until wb_stall_i is cleared.
signal
s_stall
:
std_logic
;
-- Calculate the number of LATCH DS states necessary to match the timing
-- rule 2.39 page 113 VMEbus specification ANSI/IEEE STD1014-1987.
-- (max skew for the slave is 20 ns)
constant
c_num_latchDS
:
natural
range
1
to
8
:
=
(
20
+
g_CLOCK_PERIOD
-
1
)
/
g_CLOCK_PERIOD
;
signal
s_DS_latch_count
:
unsigned
(
2
downto
0
);
begin
-- These output signals are connected to the buffers on the board
-- SN74VMEH22501A Function table: (A is fpga, B is VME connector)
-- OEn | DIR | OUTPUT OEAB | OEBYn | OUTPUT
-- H | X | Z L | H | Z
-- L | H | A to B H | H | A to B
-- L | L | B to A L | L | B to Y
-- H | L |A to B, B to Y |
vme_data_oe_n_o
<=
'0'
;
-- Driven IFF DIR = 1
vme_addr_oe_n_o
<=
'0'
;
-- Driven IFF DIR = 1
------------------------------------------------------------------------------
-- Access Mode Decoders
------------------------------------------------------------------------------
-- Type of data transfer decoder
-- VME64 ANSI/VITA 1-1994...Table 2-2 "Signal levels during data transfers"
-- Bytes position on VMEbus:
--
-- A24-31 | A16-23 | A08-15 | A00-07 | D24-31 | D16-23 | D08-15 | D00-07
-- | | | | | | BYTE 0 |
-- | | | | | | | BYTE 1
-- | | | | | | BYTE 2 |
-- | | | | | | | BYTE 3
-- | | | | | | BYTE 0 | BYTE 1
-- | | | | | | BYTE 2 | BYTE 3
-- | | | | BYTE 0 | BYTE 1 | BYTE 2 | BYTE 3
-- BYTE 0 | BYTE 1 | BYTE 2 | BYTE 3 | BYTE 4 | BYTE 5 | BYTE 6 | BYTE 7
-- Address modifier decoder
-- Both the supervisor and the user access modes are supported
with
s_AMlatched
select
s_addressingType
<=
A24
when
c_AM_A24_SUP
|
c_AM_A24
,
A24_BLT
when
c_AM_A24_BLT
|
c_AM_A24_BLT_SUP
,
A24_MBLT
when
c_AM_A24_MBLT
|
c_AM_A24_MBLT_SUP
,
CR_CSR
when
c_AM_CR_CSR
,
A16
when
c_AM_A16
|
c_AM_A16_SUP
,
A32
when
c_AM_A32
|
c_AM_A32_SUP
,
A32_BLT
when
c_AM_A32_BLT
|
c_AM_A32_BLT_SUP
,
A32_MBLT
when
c_AM_A32_MBLT
|
c_AM_A32_MBLT_SUP
,
AM_ERROR
when
others
;
-- Transfer type decoder
with
s_addressingType
select
s_transferType
<=
SINGLE
when
A24
|
CR_CSR
|
A16
|
A32
,
BLT
when
A24_BLT
|
A32_BLT
,
MBLT
when
A24_MBLT
|
A32_MBLT
,
TFR_ERROR
when
others
;
------------------------------------------------------------------------------
-- 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
-- FSM reset after power up,
-- software reset, manually reset,
-- on rising edge of AS.
s_conf_req
<=
'0'
;
decode_start_o
<=
'0'
;
-- VME
vme_dtack_oe_o
<=
'0'
;
vme_dtack_n_o
<=
'1'
;
vme_data_dir_o
<=
'0'
;
vme_addr_dir_o
<=
'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
;
-- WB
wb_sel_o
<=
"0000"
;
wb_cyc_o
<=
'0'
;
wb_stb_o
<=
'0'
;
s_err
<=
'0'
;
s_ADDRlatched
<=
(
others
=>
'0'
);
s_AMlatched
<=
(
others
=>
'0'
);
s_vme_addr_reg
<=
(
others
=>
'0'
);
s_vme_addr_dir
<=
'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_dtack_oe_o
<=
'0'
;
vme_dtack_n_o
<=
'1'
;
vme_data_dir_o
<=
'0'
;
vme_addr_dir_o
<=
'0'
;
vme_berr_n_o
<=
'1'
;
vme_iackout_n_o
<=
'1'
;
irq_ack_o
<=
'0'
;
case
s_mainFSMstate
is
when
IDLE
=>
-- Can only be here if vme_as_n_i has fallen to 0, which starts a
-- cycle.
assert
vme_as_n_i
=
'0'
;
-- Store ADDR, AM and LWORD
s_ADDRlatched
<=
vme_addr_i
;
s_LWORDlatched_n
<=
vme_lword_n_i
;
s_AMlatched
<=
vme_am_i
;
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.
s_mainFSMstate
<=
REFORMAT_ADDRESS
;
else
-- IACK cycle.
s_mainFSMstate
<=
IRQ_CHECK
;
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.
s_vme_addr_reg
<=
s_ADDRlatched
;
case
s_addressingType
is
when
A16
=>
s_vme_addr_reg
(
31
downto
16
)
<=
(
others
=>
'0'
);
-- A16
when
A24
|
A24_BLT
|
A24_MBLT
=>
s_vme_addr_reg
(
31
downto
24
)
<=
(
others
=>
'0'
);
-- A24
when
others
=>
null
;
-- A32
end
case
;
s_vme_lword_n_reg
<=
s_LWORDlatched_n
;
-- Address is not yet decoded.
s_card_sel
<=
'0'
;
s_conf_sel
<=
'0'
;
s_irq_sel
<=
'0'
;
-- DS latch counter
s_DS_latch_count
<=
to_unsigned
(
c_num_latchDS
,
3
);
-- 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
-- capability.
if
s_LWORDlatched_n
=
'0'
and
s_ADDRlatched
(
1
)
=
'1'
then
-- unaligned.
s_mainFSMstate
<=
WAIT_END
;
elsif
g_VME32
=
False
and
s_LWORDlatched_n
=
'0'
then
-- No 32bit access on VME16.
s_mainFSMstate
<=
WAIT_END
;
else
if
s_ADDRlatched
(
23
downto
19
)
=
bar_i
and
s_AMlatched
=
c_AM_CR_CSR
then
-- conf_sel = '1' it means CR/CSR space addressed
s_conf_sel
<=
'1'
;
s_mainFSMstate
<=
WAIT_FOR_DS
;
else
s_mainFSMstate
<=
DECODE_ACCESS
;
decode_start_o
<=
'1'
;
end
if
;
end
if
;
when
DECODE_ACCESS
=>
-- Check if this slave board is addressed.
-- Wait for DS in parallel.
if
vme_ds_n_i
/=
"11"
then
s_WRITElatched_n
<=
vme_write_n_i
;
if
s_DS_latch_count
/=
0
then
s_DS_latch_count
<=
s_DS_latch_count
-
1
;
end
if
;
end
if
;
if
decode_done_i
=
'1'
then
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.
s_vme_addr_reg
<=
addr_decoder_i
;
if
vme_ds_n_i
=
"11"
then
s_mainFSMstate
<=
WAIT_FOR_DS
;
else
s_mainFSMstate
<=
LATCH_DS
;
end
if
;
else
-- Another board will answer; wait here the rising edge on
-- vme_as_i (done by top if).
s_mainFSMstate
<=
WAIT_END
;
end
if
;
else
-- Not yet decoded.
s_mainFSMstate
<=
DECODE_ACCESS
;
end
if
;
when
WAIT_FOR_DS
=>
-- 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
s_WRITElatched_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
;
when
LATCH_DS
=>
-- This state is necessary indeed the VME master can assert the
-- DS lines not at the same time.
-- ANSI/VITA 1-1994 Rule 2.53a
-- During all read cycles [...], the responding slave MUST NOT
-- drive the D[] lines until DSA* goes low.
vme_data_dir_o
<=
s_WRITElatched_n
;
vme_addr_dir_o
<=
'0'
;
if
g_VME32
and
s_transferType
=
MBLT
then
s_dataPhase
<=
'1'
;
-- Start with D[31..0] when writing, but D[63..32] when reading.
s_vme_addr_reg
(
2
)
<=
not
s_WRITElatched_n
;
else
s_dataPhase
<=
'0'
;
end
if
;
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
;
else
s_mainFSMstate
<=
CHECK_TRANSFER_TYPE
;
end
if
;
-- Read DS (which is delayed to avoid metastability).
s_DSlatched_n
<=
vme_ds_n_i
;
-- Read DATA (which are stable)
s_locDataIn
(
63
downto
33
)
<=
vme_addr_i
;
s_LWORDlatched_n
<=
vme_lword_n_i
;
s_vme_data_reg
<=
vme_data_i
;
else
s_mainFSMstate
<=
LATCH_DS
;
s_DS_latch_count
<=
s_DS_latch_count
-
1
;
end
if
;
when
CHECK_TRANSFER_TYPE
=>
vme_data_dir_o
<=
s_WRITElatched_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
s_WRITElatched_n
=
'1'
and
g_VME32
then
s_vme_addr_dir
<=
'1'
;
else
s_vme_addr_dir
<=
'0'
;
end
if
;
s_locDataIn
(
32
)
<=
s_LWORDlatched_n
;
s_locDataIn
(
31
downto
0
)
<=
s_vme_data_reg
;
if
s_vme_lword_n_reg
=
'1'
and
s_vme_addr_reg
(
1
)
=
'0'
and
g_VME32
then
-- Word/byte access with A1=0
s_locDataIn
(
31
downto
16
)
<=
s_vme_data_reg
(
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
s_DSlatched_n
;
elsif
s_vme_lword_n_reg
=
'0'
then
-- 32bit access
wb_sel_o
<=
"1111"
;
else
-- 16bit access on a 32bit bus.
wb_sel_o
<=
"0000"
;
case
s_vme_addr_reg
(
1
)
is
when
'0'
=>
wb_sel_o
(
3
downto
2
)
<=
not
s_DSlatched_n
;
when
'1'
=>
wb_sel_o
(
1
downto
0
)
<=
not
s_DSlatched_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
-- capability.
if
s_vme_lword_n_reg
=
'0'
and
s_DSlatched_n
/=
"00"
then
-- unaligned.
s_mainFSMstate
<=
WAIT_END
;
else
s_mainFSMstate
<=
MEMORY_REQ
;
s_conf_req
<=
s_conf_sel
;
-- Start WB cycle.
wb_cyc_o
<=
s_card_sel
;
wb_stb_o
<=
s_card_sel
;
s_stall
<=
'1'
;
-- Can stall
s_err
<=
'0'
;
end
if
;
when
MEMORY_REQ
=>
-- To request the memory CR/CSR or WB memory it is sufficient to
-- generate a pulse on s_conf_req signal
vme_dtack_oe_o
<=
'1'
;
vme_data_dir_o
<=
s_WRITElatched_n
;
vme_addr_dir_o
<=
s_vme_addr_dir
;
-- Assert STB if stall was asserted.
case
g_WB_MODE
is
when
CLASSIC
=>
-- Maintain STB.
wb_stb_o
<=
s_card_sel
;
when
PIPELINED
=>
-- Maintain STB if stall was set in the previous cycle.
wb_stb_o
<=
s_card_sel
and
s_stall
and
wb_stall_i
;
end
case
;
s_stall
<=
s_stall
and
wb_stall_i
;
if
s_conf_sel
=
'1'
or
(
s_card_sel
=
'1'
and
(
wb_ack_i
=
'1'
or
wb_err_i
=
'1'
))
then
-- WB ack
wb_stb_o
<=
'0'
;
s_err
<=
s_card_sel
and
wb_err_i
;
if
(
s_card_sel
and
wb_err_i
)
=
'1'
then
-- Error
s_mainFSMstate
<=
DTACK_LOW
;
elsif
s_WRITElatched_n
=
'0'
then
-- Write cycle.
if
s_dataPhase
=
'1'
then
-- MBLT
s_dataPhase
<=
'0'
;
s_vme_addr_reg
(
2
)
<=
'0'
;
s_locDataIn
(
31
downto
0
)
<=
s_locDataIn
(
63
downto
32
);
-- STB is 0, wait one cycle before the 2nd xfer.
s_mainFSMstate
<=
MEMORY_PAUSE
;
else
s_mainFSMstate
<=
DTACK_LOW
;
end
if
;
else
-- Read cycle
-- Mux (CS-CSR or WB)
s_locDataOut
(
63
downto
32
)
<=
s_locDataOut
(
31
downto
0
);
s_locDataOut
(
31
downto
0
)
<=
(
others
=>
'0'
);
if
s_card_sel
=
'1'
then
if
g_VME32
and
s_vme_lword_n_reg
=
'1'
and
s_vme_addr_reg
(
1
)
=
'0'
then
-- Word/byte access with A1 = 0 on a 32bit bus.
s_locDataOut
(
15
downto
0
)
<=
wb_dat_i
(
31
downto
16
);
else
s_locDataOut
(
31
downto
0
)
<=
wb_dat_i
;
end
if
;
else
s_locDataOut
(
7
downto
0
)
<=
cr_csr_data_i
;
end
if
;
if
s_dataPhase
=
'1'
and
g_VME32
then
-- MBLT
s_dataPhase
<=
'0'
;
s_vme_addr_reg
(
2
)
<=
'1'
;
-- STB is 0, wait one cycle before the 2nd xfer.
s_mainFSMstate
<=
MEMORY_PAUSE
;
else
s_mainFSMstate
<=
DATA_TO_BUS
;
end
if
;
end
if
;
else
s_mainFSMstate
<=
MEMORY_REQ
;
end
if
;
when
MEMORY_PAUSE
=>
-- Wait until ACK is 0. Strictly speaking, this is not needed
-- according to WB specs.
wb_stb_o
<=
'0'
;
if
wb_ack_i
=
'0'
then
wb_stb_o
<=
'1'
;
s_stall
<=
'1'
;
s_mainFSMstate
<=
MEMORY_REQ
;
else
s_mainFSMstate
<=
MEMORY_PAUSE
;
end
if
;
when
DATA_TO_BUS
=>
vme_dtack_oe_o
<=
'1'
;
vme_data_dir_o
<=
s_WRITElatched_n
;
vme_addr_dir_o
<=
s_vme_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
;
when
DTACK_LOW
=>
vme_dtack_oe_o
<=
'1'
;
vme_data_dir_o
<=
s_WRITElatched_n
;
vme_addr_dir_o
<=
s_vme_addr_dir
;
-- Set DTACK (or retry or berr)
if
s_card_sel
=
'1'
and
s_err
=
'1'
then
vme_berr_n_o
<=
'0'
;
else
vme_dtack_n_o
<=
'0'
;
end
if
;
-- ANSI/VITA 1-1994 Rule 2.57
-- 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
vme_data_dir_o
<=
'0'
;
vme_berr_n_o
<=
'1'
;
-- Rescind DTACK.
vme_dtack_n_o
<=
'1'
;
-- DS latch counter
s_DS_latch_count
<=
to_unsigned
(
c_num_latchDS
,
3
);
if
s_irq_sel
=
'1'
then
s_mainFSMstate
<=
WAIT_END
;
elsif
s_transferType
=
SINGLE
then
-- Cycle should be finished, but allow another access at
-- the same address (RMW).
s_mainFSMstate
<=
WAIT_FOR_DS
;
else
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
;
end
if
;
else
s_mainFSMstate
<=
DTACK_LOW
;
end
if
;
when
INCREMENT_ADDR
=>
vme_dtack_oe_o
<=
'1'
;
vme_addr_dir_o
<=
s_vme_addr_dir
;
if
g_VME32
and
s_vme_lword_n_reg
=
'0'
then
if
s_transferType
=
MBLT
then
-- 64 bit
addr_word_incr
:
=
4
;
else
-- 32 bit
addr_word_incr
:
=
2
;
end
if
;
else
if
s_DSlatched_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)
s_vme_addr_reg
(
11
downto
1
)
<=
std_logic_vector
(
unsigned
(
s_vme_addr_reg
(
11
downto
1
))
+
addr_word_incr
);
s_mainFSMstate
<=
WAIT_FOR_DS
;
when
IRQ_CHECK
=>
if
vme_iackin_n_i
=
'0'
then
if
s_ADDRlatched
(
3
downto
1
)
=
int_level_i
and
irq_pending_i
=
'1'
then
-- That's for us
s_locDataOut
<=
(
others
=>
'0'
);
s_locDataOut
(
7
downto
0
)
<=
int_vector_i
;
s_irq_sel
<=
'1'
;
irq_ack_o
<=
'1'
;
s_mainFSMstate
<=
WAIT_FOR_DS
;
else
-- Pass
vme_iackout_n_o
<=
'0'
;
s_mainFSMstate
<=
IRQ_PASS
;
end
if
;
else
s_mainFSMstate
<=
IRQ_CHECK
;
end
if
;
when
IRQ_PASS
=>
-- Will stay here until AS is released.
vme_iackout_n_o
<=
'0'
;
s_mainFSMstate
<=
IRQ_PASS
;
when
WAIT_END
=>
-- Will stay here until AS is released.
s_mainFSMstate
<=
WAIT_END
;
when
others
=>
-- No-op, wait until AS is released.
s_mainFSMstate
<=
WAIT_END
;
end
case
;
end
if
;
end
if
;
end
process
;
-- Retry is not supported
vme_retry_n_o
<=
'1'
;
vme_retry_oe_o
<=
'0'
;
-- WB Master
g_wb_addr32
:
if
g_VME32
generate
with
g_WB_GRANULARITY
select
wb_adr_o
<=
"00"
&
s_vme_addr_reg
(
31
downto
2
)
when
WORD
,
s_vme_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"
&
s_vme_addr_reg
(
31
downto
1
)
when
WORD
,
s_vme_addr_reg
(
31
downto
1
)
&
"0"
when
BYTE
;
end
generate
;
wb_we_o
<=
not
s_WRITElatched_n
;
wb_dat_o
<=
s_locDataIn
(
31
downto
0
);
-- Function Decoder
addr_decoder_o
<=
s_vme_addr_reg
;
am_o
<=
s_AMlatched
;
-- CR/CSR In/Out
cr_csr_data_o
<=
s_locDataIn
(
7
downto
0
);
cr_csr_addr_o
<=
s_vme_addr_reg
(
18
downto
2
);
cr_csr_we_o
<=
'1'
when
s_conf_req
=
'1'
and
s_WRITElatched_n
=
'0'
else
'0'
;
end
rtl
;
-- 1 Tclk saved @CTT -> REQ
-- 1 Tclk saved during WRITE when MEM_REQ -> DTACK LOW
-- This means that single access write, MBLT write should have intact speed (TEST!)
-- Next step is achieving read when MEM_REQ -> DTACK LOW with a saved TCLK which
-- should bring signle read to intact speed, and slightly boost MBLT (1st read only)
-- (Later might think of something similar for MBLT read )
-- 2 more cycles saved during MBLT added s1 and s2
-- Attempting to save 1 more TCLK between the data is prefetched and DTACK is driven down DONE
-- Attempting to save 1 tclk during single access read DONE ()
-- Attempting to start prefetch earlier than in v07
-- Spitting out data as early as possible on vme bus from different states depending on master read ack (DONE)
-- Rate: 34.424901 MB/sec
-- OK: DMA read
-- Rate: 26.073180 MB/sec
-- OK: DMA write
--------------------------------------------------------------------------------
-- CERN (BE-CO-HT)
-- VME64x Core
-- http://www.ohwr.org/projects/vme64x-core
--------------------------------------------------------------------------------
--
-- unit name: VME_bus
--
-- description:
--
-- This block acts as interface between the VMEbus and the CR/CSR space or
-- WB bus.
--
--------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE
--------------------------------------------------------------------------------
-- This source file is free software; you can redistribute it and/or modify it
-- under the terms of the GNU Lesser General Public License as published by the
-- Free Software Foundation; either version 2.1 of the License, or (at your
-- option) any later version. This source is distributed in the hope that it
-- will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
-- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-- See the GNU Lesser General Public License for more details. You should have
-- received a copy of the GNU Lesser General Public License along with this
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html
--------------------------------------------------------------------------------
library
ieee
;
use
ieee
.
std_logic_1164
.
all
;
use
ieee
.
numeric_std
.
all
;
use
work
.
vme64x_pkg
.
all
;
use
work
.
wishbone_pkg
.
all
;
entity
vme_bus
is
generic
(
g_CLOCK_PERIOD
:
integer
;
g_VME32
:
boolean
;
g_WB_GRANULARITY
:
t_wishbone_address_granularity
;
g_WB_MODE
:
t_wishbone_interface_mode
);
port
(
clk_i
:
in
std_logic
;
rst_n_i
:
in
std_logic
;
-- VME signals
vme_as_n_i
:
in
std_logic
;
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_dtack_n_o
:
out
std_logic
;
vme_dtack_oe_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'
);
vme_addr_dir_o
:
out
std_logic
;
vme_addr_oe_n_o
:
out
std_logic
;
vme_data_i
:
in
std_logic_vector
(
31
downto
0
);
vme_data_o
:
out
std_logic_vector
(
31
downto
0
)
:
=
(
others
=>
'0'
);
vme_data_dir_o
:
out
std_logic
;
vme_data_oe_n_o
:
out
std_logic
;
vme_am_i
:
in
std_logic_vector
(
5
downto
0
);
vme_iackin_n_i
:
in
std_logic
;
vme_iack_n_i
:
in
std_logic
;
vme_iackout_n_o
:
out
std_logic
;
-- WB signals
wb_stb_o
:
out
std_logic
;
wb_ack_i
:
in
std_logic
;
wb_dat_o
:
out
std_logic_vector
(
31
downto
0
);
wb_dat_i
:
in
std_logic_vector
(
31
downto
0
);
wb_adr_o
:
out
std_logic_vector
(
31
downto
0
);
wb_sel_o
:
out
std_logic_vector
(
3
downto
0
);
wb_we_o
:
out
std_logic
;
wb_cyc_o
:
out
std_logic
;
wb_err_i
:
in
std_logic
;
wb_stall_i
:
in
std_logic
;
-- Function decoder
addr_decoder_i
:
in
std_logic_vector
(
31
downto
1
);
addr_decoder_o
:
out
std_logic_vector
(
31
downto
1
);
decode_start_o
:
out
std_logic
;
decode_done_i
:
in
std_logic
;
am_o
:
out
std_logic_vector
(
5
downto
0
);
decode_sel_i
:
in
std_logic
;
-- CR/CSR space signals:
cr_csr_addr_o
:
out
std_logic_vector
(
18
downto
2
);
cr_csr_data_i
:
in
std_logic_vector
(
7
downto
0
);
cr_csr_data_o
:
out
std_logic_vector
(
7
downto
0
);
cr_csr_we_o
:
out
std_logic
;
module_enable_i
:
in
std_logic
;
bar_i
:
in
std_logic_vector
(
4
downto
0
);
-- Interrupts
int_level_i
:
in
std_logic_vector
(
2
downto
0
);
int_vector_i
:
in
std_logic_vector
(
7
downto
0
);
irq_pending_i
:
in
std_logic
;
irq_ack_o
:
out
std_logic
);
end
vme_bus
;
architecture
rtl
of
vme_bus
is
signal
a
:
std_logic
;
-- Local data
signal
s_locDataIn
:
std_logic_vector
(
63
downto
0
);
signal
s_locDataOut
:
std_logic_vector
(
63
downto
0
);
-- VME latched signals
signal
s_ADDRlatched
:
std_logic_vector
(
31
downto
1
);
signal
s_LWORDlatched_n
:
std_logic
;
signal
s_DSlatched_n
:
std_logic_vector
(
1
downto
0
);
signal
s_AMlatched
:
std_logic_vector
(
5
downto
0
);
signal
s_WRITElatched_n
:
std_logic
;
-- Address and data from the VME bus. There are two registers so that the
-- first one can be placed in the IOBs.
signal
s_vme_addr_reg
:
std_logic_vector
(
31
downto
1
);
signal
s_vme_data_reg
:
std_logic_vector
(
31
downto
0
);
signal
s_vme_lword_n_reg
:
std_logic
;
signal
s_vme_addr_dir
:
std_logic
;
type
t_addressingType
is
(
A24
,
A24_BLT
,
A24_MBLT
,
CR_CSR
,
A16
,
A32
,
A32_BLT
,
A32_MBLT
,
AM_ERROR
);
type
t_transferType
is
(
SINGLE
,
BLT
,
MBLT
,
TFR_ERROR
);
-- Addressing type (depending on vme_am_i)
signal
s_addressingType
:
t_addressingType
;
signal
s_transferType
:
t_transferType
;
type
t_mainFSMstates
is
(
-- Wait until AS is asserted.
IDLE
,
-- Reformat address according to AM.
REFORMAT_ADDRESS
,
-- Decoding ADDR and AM (selecting card or conf).
DECODE_ACCESS
,
-- Wait until DS is asserted.
WAIT_FOR_DS
,
-- Wait until DS is stable (and asserted).
LATCH_DS
,
-- 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
,
-- Assert DTACK
DTACK_LOW
,
-- Increment address for block transfers
INCREMENT_ADDR
,
-- Check if IACK is for this slave
IRQ_CHECK
,
-- Pass IACKIN to IACKOUT
IRQ_PASS
,
-- Wait until AS is deasserted
WAIT_END
,
-- Data2Bus during MBLT read
S1
,
-- DtackLow during MBLT read
S2
);
-- 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
signal
s_conf_sel
:
std_logic
;
-- CR or CSR is addressed
signal
s_card_sel
:
std_logic
;
-- WB memory is addressed
signal
s_irq_sel
:
std_logic
;
-- IACK transaction
signal
s_err
:
std_logic
;
-- Stall status. Set to one until wb_stall_i is cleared.
signal
s_stall
:
std_logic
;
-- Calculate the number of LATCH DS states necessary to match the timing
-- rule 2.39 page 113 VMEbus specification ANSI/IEEE STD1014-1987.
-- (max skew for the slave is 20 ns)
constant
c_num_latchDS
:
natural
range
1
to
8
:
=
(
20
+
g_CLOCK_PERIOD
-
1
)
/
g_CLOCK_PERIOD
;
signal
s_DS_latch_count
:
unsigned
(
2
downto
0
);
-- WB FSM states
type
t_WBFSMstates
is
(
-- Wait until the Main FSM issues a WB cycle.
IDLE
,
-- Wait for WB reply
MEMORY_REQ
,
-- Negate STB between half MBLT transactions
MEMORY_PAUSE
);
-- 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_data_on_bus
:
std_logic
;
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)
-- OEn | DIR | OUTPUT OEAB | OEBYn | OUTPUT
-- H | X | Z L | H | Z
-- L | H | A to B H | H | A to B
-- L | L | B to A L | L | B to Y
-- H | L |A to B, B to Y |
vme_data_oe_n_o
<=
'0'
;
-- Driven IFF DIR = 1
vme_addr_oe_n_o
<=
'0'
;
-- Driven IFF DIR = 1
------------------------------------------------------------------------------
-- Access Mode Decoders
------------------------------------------------------------------------------
-- Type of data transfer decoder
-- VME64 ANSI/VITA 1-1994...Table 2-2 "Signal levels during data transfers"
-- Bytes position on VMEbus:
--
-- A24-31 | A16-23 | A08-15 | A00-07 | D24-31 | D16-23 | D08-15 | D00-07
-- | | | | | | BYTE 0 |
-- | | | | | | | BYTE 1
-- | | | | | | BYTE 2 |
-- | | | | | | | BYTE 3
-- | | | | | | BYTE 0 | BYTE 1
-- | | | | | | BYTE 2 | BYTE 3
-- | | | | BYTE 0 | BYTE 1 | BYTE 2 | BYTE 3
-- BYTE 0 | BYTE 1 | BYTE 2 | BYTE 3 | BYTE 4 | BYTE 5 | BYTE 6 | BYTE 7
-- Address modifier decoder
-- Both the supervisor and the user access modes are supported
with
s_AMlatched
select
s_addressingType
<=
A24
when
c_AM_A24_SUP
|
c_AM_A24
,
A24_BLT
when
c_AM_A24_BLT
|
c_AM_A24_BLT_SUP
,
A24_MBLT
when
c_AM_A24_MBLT
|
c_AM_A24_MBLT_SUP
,
CR_CSR
when
c_AM_CR_CSR
,
A16
when
c_AM_A16
|
c_AM_A16_SUP
,
A32
when
c_AM_A32
|
c_AM_A32_SUP
,
A32_BLT
when
c_AM_A32_BLT
|
c_AM_A32_BLT_SUP
,
A32_MBLT
when
c_AM_A32_MBLT
|
c_AM_A32_MBLT_SUP
,
AM_ERROR
when
others
;
-- Transfer type decoder
with
s_addressingType
select
s_transferType
<=
SINGLE
when
A24
|
CR_CSR
|
A16
|
A32
,
BLT
when
A24_BLT
|
A32_BLT
,
MBLT
when
A24_MBLT
|
A32_MBLT
,
TFR_ERROR
when
others
;
------------------------------------------------------------------------------
-- 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
-- FSM reset after power up,
-- software reset, manually reset,
-- on rising edge of AS.
s_conf_req
<=
'0'
;
decode_start_o
<=
'0'
;
-- VME
vme_dtack_oe_o
<=
'0'
;
vme_dtack_n_o
<=
'1'
;
vme_data_dir_o
<=
'0'
;
vme_addr_dir_o
<=
'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'
;
s_ADDRlatched
<=
(
others
=>
'0'
);
s_AMlatched
<=
(
others
=>
'0'
);
s_vme_addr_reg
<=
(
others
=>
'0'
);
s_vme_addr_dir
<=
'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_dtack_oe_o
<=
'0'
;
vme_dtack_n_o
<=
'1'
;
vme_data_dir_o
<=
'0'
;
vme_addr_dir_o
<=
'0'
;
vme_berr_n_o
<=
'1'
;
vme_iackout_n_o
<=
'1'
;
irq_ack_o
<=
'0'
;
case
s_mainFSMstate
is
when
IDLE
=>
-- Can only be here if vme_as_n_i has fallen to 0, which starts a
-- cycle.
assert
vme_as_n_i
=
'0'
;
-- Store ADDR, AM and LWORD
s_ADDRlatched
<=
vme_addr_i
;
s_LWORDlatched_n
<=
vme_lword_n_i
;
s_AMlatched
<=
vme_am_i
;
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.
s_mainFSMstate
<=
REFORMAT_ADDRESS
;
else
-- IACK cycle.
s_mainFSMstate
<=
IRQ_CHECK
;
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.
s_vme_addr_reg
<=
s_ADDRlatched
;
case
s_addressingType
is
when
A16
=>
s_vme_addr_reg
(
31
downto
16
)
<=
(
others
=>
'0'
);
-- A16
when
A24
|
A24_BLT
|
A24_MBLT
=>
s_vme_addr_reg
(
31
downto
24
)
<=
(
others
=>
'0'
);
-- A24
when
others
=>
null
;
-- A32
end
case
;
s_vme_lword_n_reg
<=
s_LWORDlatched_n
;
-- Address is not yet decoded.
s_card_sel
<=
'0'
;
s_conf_sel
<=
'0'
;
s_irq_sel
<=
'0'
;
-- DS latch counter
s_DS_latch_count
<=
to_unsigned
(
c_num_latchDS
,
3
);
-- 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
-- capability.
if
s_LWORDlatched_n
=
'0'
and
s_ADDRlatched
(
1
)
=
'1'
then
-- unaligned.
s_mainFSMstate
<=
WAIT_END
;
elsif
g_VME32
=
False
and
s_LWORDlatched_n
=
'0'
then
-- No 32bit access on VME16.
s_mainFSMstate
<=
WAIT_END
;
else
if
s_ADDRlatched
(
23
downto
19
)
=
bar_i
and
s_AMlatched
=
c_AM_CR_CSR
then
-- conf_sel = '1' it means CR/CSR space addressed
s_conf_sel
<=
'1'
;
s_mainFSMstate
<=
WAIT_FOR_DS
;
else
s_mainFSMstate
<=
DECODE_ACCESS
;
decode_start_o
<=
'1'
;
end
if
;
end
if
;
when
DECODE_ACCESS
=>
-- Check if this slave board is addressed.
-- Wait for DS in parallel.
if
vme_ds_n_i
/=
"11"
then
s_WRITElatched_n
<=
vme_write_n_i
;
if
s_DS_latch_count
/=
0
then
s_DS_latch_count
<=
s_DS_latch_count
-
1
;
end
if
;
end
if
;
if
decode_done_i
=
'1'
then
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.
s_vme_addr_reg
<=
addr_decoder_i
;
if
vme_ds_n_i
=
"11"
then
s_mainFSMstate
<=
WAIT_FOR_DS
;
else
s_mainFSMstate
<=
LATCH_DS
;
end
if
;
else
-- Another board will answer; wait here the rising edge on
-- vme_as_i (done by top if).
s_mainFSMstate
<=
WAIT_END
;
end
if
;
else
-- Not yet decoded.
s_mainFSMstate
<=
DECODE_ACCESS
;
end
if
;
when
WAIT_FOR_DS
=>
-- 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
-- s_WRITElatched_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'
;
else
null
;
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
-- ANSI/VITA 1-1994 Table 4-1
-- For interrupts ack, the handler MUST NOT drive WRITE* low
s_WRITElatched_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'
;
--s_wb_start <= '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
s_WRITElatched_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
;
when
LATCH_DS
=>
-- This state is necessary indeed the VME master can assert the
-- DS lines not at the same time.
-- ANSI/VITA 1-1994 Rule 2.53a
-- During all read cycles [...], the responding slave MUST NOT
-- drive the D[] lines until DSA* goes low.
vme_data_dir_o
<=
s_WRITElatched_n
;
vme_addr_dir_o
<=
'0'
;
if
g_VME32
and
s_transferType
=
MBLT
then
s_dataPhase
<=
'1'
;
-- Start with D[31..0] when writing, but D[63..32] when reading.
s_vme_addr_reg
(
2
)
<=
not
s_WRITElatched_n
;
else
s_dataPhase
<=
'0'
;
end
if
;
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
;
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
else
null
;
end
if
;
end
if
;
-- Read DS (which is delayed to avoid metastability).
s_DSlatched_n
<=
vme_ds_n_i
;
-- Read DATA (which are stable)
s_locDataIn
(
63
downto
33
)
<=
vme_addr_i
;
s_LWORDlatched_n
<=
vme_lword_n_i
;
s_vme_data_reg
<=
vme_data_i
;
else
s_mainFSMstate
<=
LATCH_DS
;
s_DS_latch_count
<=
s_DS_latch_count
-
1
;
end
if
;
when
CHECK_TRANSFER_TYPE
=>
vme_data_dir_o
<=
s_WRITElatched_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
s_WRITElatched_n
=
'1'
and
g_VME32
then
s_vme_addr_dir
<=
'1'
;
else
s_vme_addr_dir
<=
'0'
;
end
if
;
s_locDataIn
(
32
)
<=
s_LWORDlatched_n
;
s_locDataIn
(
31
downto
0
)
<=
s_vme_data_reg
;
if
s_vme_lword_n_reg
=
'1'
and
s_vme_addr_reg
(
1
)
=
'0'
and
g_VME32
then
-- Word/byte access with A1=0
s_locDataIn
(
31
downto
16
)
<=
s_vme_data_reg
(
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
s_DSlatched_n
;
elsif
s_vme_lword_n_reg
=
'0'
then
-- 32bit access
wb_sel_o
<=
"1111"
;
else
-- 16bit access on a 32bit bus.
wb_sel_o
<=
"0000"
;
case
s_vme_addr_reg
(
1
)
is
when
'0'
=>
wb_sel_o
(
3
downto
2
)
<=
not
s_DSlatched_n
;
when
'1'
=>
wb_sel_o
(
1
downto
0
)
<=
not
s_DSlatched_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
-- capability.
if
s_vme_lword_n_reg
=
'0'
and
s_DSlatched_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_conf_req
<=
s_conf_sel
;
end
if
;
-- Needed to add this here because it must be availible sooner for prefetch. May be reduntant at CTT
if
g_VME32
and
s_vme_lword_n_reg
=
'0'
and
s_WRITElatched_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
<=
s_WRITElatched_n
;
vme_addr_dir_o
<=
s_vme_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
;
if
s_WRITElatched_n
=
'1'
then
-- if it is a read, but not MBLT or 1st MBLT data
vme_dtack_n_o
<=
'0'
;
else
null
;
end
if
;
if
s_wb_prefetch
=
'1'
then
s_wb_start
<=
'0'
;
else
null
;
end
if
;
when
DTACK_LOW
=>
-- Think this block can execute when moving from WAIT_WB_FSM to DTACK_LOW
vme_dtack_oe_o
<=
'1'
;
vme_data_dir_o
<=
s_WRITElatched_n
;
vme_addr_dir_o
<=
s_vme_addr_dir
;
-- Set DTACK (or retry or berr)
if
s_card_sel
=
'1'
and
s_err
=
'1'
then
vme_berr_n_o
<=
'0'
;
else
vme_dtack_n_o
<=
'0'
;
end
if
;
-- ANSI/VITA 1-1994 Rule 2.57
-- 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
vme_data_dir_o
<=
'0'
;
vme_berr_n_o
<=
'1'
;
-- Rescind DTACK.
vme_dtack_n_o
<=
'1'
;
-- DS latch counter
s_DS_latch_count
<=
to_unsigned
(
c_num_latchDS
,
3
);
if
s_irq_sel
=
'1'
then
s_mainFSMstate
<=
WAIT_END
;
elsif
s_transferType
=
SINGLE
then
-- Cycle should be finished, but allow another access at
-- the same address (RMW).
s_mainFSMstate
<=
WAIT_FOR_DS
;
else
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
;
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'
;
else
null
;
end
if
;
when
INCREMENT_ADDR
=>
vme_dtack_oe_o
<=
'1'
;
vme_addr_dir_o
<=
s_vme_addr_dir
;
if
g_VME32
and
s_vme_lword_n_reg
=
'0'
then
if
s_transferType
=
MBLT
then
-- 64 bit
addr_word_incr
:
=
4
;
else
-- 32 bit
addr_word_incr
:
=
2
;
end
if
;
else
if
s_DSlatched_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)
s_vme_addr_reg
(
11
downto
1
)
<=
std_logic_vector
(
unsigned
(
s_vme_addr_reg
(
11
downto
1
))
+
addr_word_incr
);
s_mainFSMstate
<=
WAIT_FOR_DS
;
if
s_wb_prefetch
=
'1'
then
s_pom
<=
'1'
;
else
null
;
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'
;
else
null
;
end
if
;
when
IRQ_CHECK
=>
if
vme_iackin_n_i
=
'0'
then
if
s_ADDRlatched
(
3
downto
1
)
=
int_level_i
and
irq_pending_i
=
'1'
then
-- That's for us
s_locDataOut
<=
(
others
=>
'0'
);
s_locDataOut
(
7
downto
0
)
<=
int_vector_i
;
s_irq_sel
<=
'1'
;
irq_ack_o
<=
'1'
;
s_mainFSMstate
<=
WAIT_FOR_DS
;
else
-- Pass
vme_iackout_n_o
<=
'0'
;
s_mainFSMstate
<=
IRQ_PASS
;
end
if
;
else
s_mainFSMstate
<=
IRQ_CHECK
;
end
if
;
when
IRQ_PASS
=>
-- Will stay here until AS is released.
vme_iackout_n_o
<=
'0'
;
s_mainFSMstate
<=
IRQ_PASS
;
when
WAIT_END
=>
-- 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 unalligned data during write
s_locDataIn
<=
s_wb_locDataIn
;
elsif
s_WBFSMstate
=
MEMORY_PAUSE
then
s_locDataIn
<=
s_wb_locDataIn
;
else
null
;
end
if
;
s_locDataOut
<=
s_wb_locDataOut
;
s_vme_addr_reg
<=
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
(
s_WRITElatched_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
s_vme_addr_reg
(
11
downto
1
)
<=
std_logic_vector
(
unsigned
(
s_vme_addr_reg
(
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
;
else
null
;
end
if
;
if
s_WRITElatched_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
<=
s_WRITElatched_n
;
vme_addr_dir_o
<=
s_vme_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
(
s_WRITElatched_n
=
'0'
)
and
(
wb_ack_i
=
'1'
)))
then
-- added or to not loose a cycle for acknoledging. 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'
;
s_wb_start
<=
'0'
;
vme_data_dir_o
<=
'1'
;
vme_addr_dir_o
<=
'1'
;
vme_dtack_oe_o
<=
'1'
;
when
s2
=>
s_wb_start
<=
'0'
;
vme_data_dir_o
<=
'1'
;
vme_addr_dir_o
<=
'1'
;
vme_dtack_oe_o
<=
'1'
;
if
vme_ds_n_i
/=
"11"
then
s_mainFSMstate
<=
s2
;
vme_dtack_n_o
<=
'0'
;
else
s_mainFSMstate
<=
INCREMENT_ADDR
;
vme_dtack_n_o
<=
'1'
;
s_DS_latch_count
<=
s_DS_latch_count
+
1
;
end
if
;
if
s_WBFSMstate
=
MEMORY_PAUSE
then
s_pom
<=
'0'
;
else
null
;
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'
;
else
null
;
end
if
;
when
others
=>
-- No-op, wait until AS is released.
s_mainFSMstate
<=
WAIT_END
;
end
case
;
if
s_WBFSMstate
=
MEMORY_REQ
then
-- We want this state machine to drive them, but under the same condition
vme_dtack_oe_o
<=
'1'
;
vme_data_dir_o
<=
s_WRITElatched_n
;
vme_addr_dir_o
<=
s_vme_addr_dir
;
else
null
;
end
if
;
end
if
;
end
if
;
incr
<=
addr_word_incr
;
end
process
;
------------------------------------------------------------------------------
-- WB FSM
------------------------------------------------------------------------------
p_WB_FSM
:
process
(
clk_i
)
is
begin
if
rising_edge
(
clk_i
)
then
if
rst_n_i
=
'0'
or
vme_as_n_i
=
'1'
then
-- FSM reset after power up,
-- software reset, manually reset,
-- on rising edge of AS.
s_WBFSMstate
<=
IDLE
;
-- WB
wb_cyc_o
<=
'0'
;
wb_stb_o
<=
'0'
;
s_err
<=
'0'
;
s_wb_DTACK_LOW
<=
'0'
;
s_wb_done
<=
'0'
;
else
case
s_WBFSMstate
is
when
IDLE
=>
-- Can only be here if vme_as_n_i has fallen to 0, which starts a
-- cycle.
assert
vme_as_n_i
=
'0'
;
s_wb_DTACK_LOW
<=
'0'
;
s_wb_done
<=
'0'
;
-- Latching some important signals from the main FSM
s_wb_dataPhase
<=
s_dataPhase
;
s_wb_vme_addr_reg
<=
s_vme_addr_reg
;
s_wb_locDataIn
<=
s_locDataIn
;
if
s_wb_start
/=
'1'
then
if
vme_ds_n_i
/=
"11"
and
s_wb_prefetch
=
'1'
and
s_pom
=
'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
;
s_wb_dataPhase
<=
'1'
;
else
-- Wait in IDLE until s_wb_start = '1'
s_WBFSMstate
<=
IDLE
;
end
if
;
else
-- 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
;
end
if
;
when
MEMORY_REQ
=>
-- To request the memory CR/CSR or WB memory it is sufficient to
-- 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
;
else
null
;
end
if
;
case
g_WB_MODE
is
when
CLASSIC
=>
-- Maintain STB.
wb_stb_o
<=
s_card_sel
;
when
PIPELINED
=>
-- Maintain STB if stall was set in the previous cycle.
wb_stb_o
<=
s_card_sel
and
s_stall
and
wb_stall_i
;
end
case
;
s_stall
<=
s_stall
and
wb_stall_i
;
if
s_conf_sel
=
'1'
or
(
s_card_sel
=
'1'
and
(
wb_ack_i
=
'1'
or
wb_err_i
=
'1'
))
then
-- WB ack
wb_stb_o
<=
'0'
;
s_err
<=
s_card_sel
and
wb_err_i
;
if
(
s_card_sel
and
wb_err_i
)
=
'1'
then
-- Error
s_wb_DTACK_LOW
<=
'1'
;
s_WBFSMstate
<=
IDLE
;
elsif
s_WRITElatched_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
);
-- STB is 0, wait one cycle before the 2nd xfer.
s_WBFSMstate
<=
MEMORY_PAUSE
;
else
s_wb_DTACK_LOW
<=
'1'
;
-- done, IDLE?
s_WBFSMstate
<=
IDLE
;
end
if
;
else
-- 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'
);
if
s_card_sel
=
'1'
then
if
g_VME32
and
s_vme_lword_n_reg
=
'1'
and
s_wb_vme_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
);
else
s_wb_locDataOut
(
31
downto
0
)
<=
wb_dat_i
;
end
if
;
else
s_wb_locDataOut
(
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
;
else
s_wb_done
<=
'1'
;
s_WBFSMstate
<=
IDLE
;
end
if
;
end
if
;
else
s_WBFSMstate
<=
MEMORY_REQ
;
end
if
;
when
MEMORY_PAUSE
=>
-- Wait until ACK is 0. Strictly speaking, this is not needed
-- according to WB specs.
wb_stb_o
<=
'0'
;
if
wb_ack_i
=
'0'
then
wb_stb_o
<=
'1'
;
s_stall
<=
'1'
;
s_WBFSMstate
<=
MEMORY_REQ
;
else
s_WBFSMstate
<=
MEMORY_PAUSE
;
end
if
;
when
others
=>
-- No-op, wait until AS is released.
null
;
end
case
;
end
if
;
end
if
;
end
process
;
-- Retry is not supported
vme_retry_n_o
<=
'1'
;
vme_retry_oe_o
<=
'0'
;
-- WB Master
-- g_wb_addr32: if g_VME32 generate
-- with g_WB_GRANULARITY select
-- wb_adr_o <= "00" & s_vme_addr_reg(31 downto 2) when WORD,
-- s_vme_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" & s_vme_addr_reg(31 downto 1) when WORD,
-- s_vme_addr_reg(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
(
s_vme_addr_reg
,
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"
&
s_vme_addr_reg
(
31
downto
2
);
elsif
g_WB_GRANULARITY
=
BYTE
then
wb_adr_o
<=
s_vme_addr_reg
(
31
downto
2
)
&
"00"
;
else
null
;
end
if
;
elsif
(
not
g_VME32
)
then
if
g_WB_GRANULARITY
=
WORD
then
wb_adr_o
<=
"0"
&
s_vme_addr_reg
(
31
downto
1
);
elsif
g_WB_GRANULARITY
=
BYTE
then
wb_adr_o
<=
s_vme_addr_reg
(
31
downto
1
)
&
"0"
;
else
null
;
end
if
;
else
null
;
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"
;
else
null
;
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"
;
else
null
;
end
if
;
else
null
;
end
if
;
else
null
;
end
if
;
end
process
;
wb_we_o
<=
not
s_WRITElatched_n
;
wb_dat_o
<=
s_locDataIn
(
31
downto
0
);
-- Function Decoder
addr_decoder_o
<=
s_vme_addr_reg
;
am_o
<=
s_AMlatched
;
-- CR/CSR In/Out
cr_csr_data_o
<=
s_locDataIn
(
7
downto
0
);
cr_csr_addr_o
<=
s_vme_addr_reg
(
18
downto
2
);
cr_csr_we_o
<=
'1'
when
s_conf_req
=
'1'
and
s_WRITElatched_n
=
'0'
else
'0'
;
end
rtl
;
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment