-
Notifications
You must be signed in to change notification settings - Fork 59
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
4 changed files
with
882 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,270 @@ | ||
------------------------------------------------------------------------------- | ||
-- Title : SACI Protocol: https://confluence.slac.stanford.edu/x/YYcRDQ | ||
------------------------------------------------------------------------------- | ||
-- Company : SLAC National Accelerator Laboratory | ||
------------------------------------------------------------------------------- | ||
-- Description: AXI-Lite bridge to SACI bus | ||
------------------------------------------------------------------------------- | ||
-- This file is part of 'SLAC Firmware Standard Library'. | ||
-- It is subject to the license terms in the LICENSE.txt file found in the | ||
-- top-level directory of this distribution and at: | ||
-- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. | ||
-- No part of 'SLAC Firmware Standard Library', including this file, | ||
-- may be copied, modified, propagated, or distributed except according to | ||
-- the terms contained in the LICENSE.txt file. | ||
------------------------------------------------------------------------------- | ||
|
||
library ieee; | ||
use ieee.std_logic_1164.all; | ||
use ieee.std_logic_unsigned.all; | ||
use ieee.std_logic_arith.all; | ||
|
||
|
||
library surf; | ||
use surf.StdRtlPkg.all; | ||
use surf.AxiLitePkg.all; | ||
use surf.Saci2CoordinatorPkg.all; | ||
|
||
entity AxiLiteSaci2Coordinator is | ||
generic ( | ||
TPD_G : time := 1 ns; | ||
AXIL_CLK_PERIOD_G : real := 8.0e-9; -- In units of seconds | ||
AXIL_TIMEOUT_G : real := 1.0E-3; -- In units of seconds | ||
SACI_CLK_PERIOD_G : real := 1.0e-6; -- In units of seconds | ||
SACI_CLK_FREERUN_G : boolean := false; | ||
SACI_ADDR_BITS_G : integer range 2 to 30 := 24; | ||
SACI_NUM_CHIPS_G : positive := 1; | ||
SACI_RSP_BUSSED_G : boolean := false); | ||
port ( | ||
-- SACI interface | ||
saciClk : out sl; | ||
saciCmd : out sl; | ||
saciSelL : out slv(SACI_NUM_CHIPS_G-1 downto 0); | ||
saciRsp : in slv(ite(SACI_RSP_BUSSED_G, 0, SACI_NUM_CHIPS_G-1) downto 0); | ||
-- Optional SACI bus arbitration | ||
saciBusReq : out sl; | ||
saciBusGr : in sl := '1'; | ||
-- Optional ASIC Global Reset | ||
asicRstL : in sl := '1'; | ||
-- AXI-Lite Register Interface | ||
axilClk : in sl; | ||
axilRst : in sl; | ||
axilReadMaster : in AxiLiteReadMasterType; | ||
axilReadSlave : out AxiLiteReadSlaveType; | ||
axilWriteMaster : in AxiLiteWriteMasterType; | ||
axilWriteSlave : out AxiLiteWriteSlaveType); | ||
end AxiLiteSaci2Coordinator; | ||
|
||
architecture rtl of AxiLiteSaci2Coordinator is | ||
|
||
constant CHIP_BITS_C : integer := log2(SACI_NUM_CHIPS_G); | ||
constant TIMEOUT_C : integer := integer(AXIL_TIMEOUT_G/AXIL_CLK_PERIOD_G)-1; | ||
|
||
type StateType is ( | ||
IDLE_S, | ||
SACI_REQ_S, | ||
SACI_ACK_S); | ||
|
||
type RegType is record | ||
state : StateType; | ||
saciBusReq : sl; | ||
saciRst : sl; | ||
req : sl; | ||
chip : slv(log2(SACI_NUM_CHIPS_G)-1 downto 0); | ||
op : sl; | ||
addr : slv(29 downto 0); | ||
wrData : slv(31 downto 0); | ||
timer : integer range 0 to TIMEOUT_C; | ||
axilReadSlave : AxiLiteReadSlaveType; | ||
axilWriteSlave : AxiLiteWriteSlaveType; | ||
|
||
end record RegType; | ||
|
||
constant REG_INIT_C : RegType := ( | ||
state => IDLE_S, | ||
saciBusReq => '0', | ||
saciRst => '1', | ||
req => '0', | ||
chip => (others => '0'), | ||
op => '0', | ||
addr => (others => '0'), | ||
wrData => (others => '0'), | ||
timer => 0, | ||
axilReadSlave => AXI_LITE_READ_SLAVE_INIT_C, | ||
axilWriteSlave => AXI_LITE_WRITE_SLAVE_INIT_C); | ||
|
||
signal r : RegType := REG_INIT_C; | ||
signal rin : RegType; | ||
|
||
signal ack : sl; | ||
signal fail : sl; | ||
signal rdData : slv(31 downto 0); | ||
|
||
-- attribute dont_touch : string; | ||
-- attribute dont_touch of r : signal is "true"; | ||
|
||
begin | ||
|
||
assert (AXIL_CLK_PERIOD_G < 1.0) | ||
report "AXIL_CLK_PERIOD_G must be < 1.0 seconds" severity failure; | ||
assert (AXIL_TIMEOUT_G < 1.0) | ||
report "AXIL_TIMEOUT_G must be < 1.0 seconds" severity failure; | ||
assert (SACI_CLK_PERIOD_G < 1.0) | ||
report "SACI_CLK_PERIOD_G must be < 1.0 seconds" severity failure; | ||
assert (AXIL_CLK_PERIOD_G < AXIL_TIMEOUT_G) | ||
report "AXIL_CLK_PERIOD_G must be < AXIL_TIMEOUT_G" severity failure; | ||
assert (AXIL_CLK_PERIOD_G < SACI_CLK_PERIOD_G) | ||
report "AXIL_CLK_PERIOD_G must be < SACI_CLK_PERIOD_G" severity failure; | ||
assert (SACI_CLK_PERIOD_G < AXIL_TIMEOUT_G) | ||
report "SACI_CLK_PERIOD_G must be < AXIL_TIMEOUT_G" severity failure; | ||
|
||
U_Saci2Coordinator_1 : entity surf.Saci2Coordinator | ||
generic map ( | ||
TPD_G => TPD_G, | ||
SYS_CLK_PERIOD_G => AXIL_CLK_PERIOD_G, | ||
SACI_CLK_PERIOD_G => SACI_CLK_PERIOD_G, | ||
SACI_CLK_FREERUN_G => SACI_CLK_FREERUN_G, | ||
SACI_NUM_CHIPS_G => SACI_NUM_CHIPS_G, | ||
SACI_RSP_BUSSED_G => SACI_RSP_BUSSED_G) | ||
port map ( | ||
sysClk => axilClk, -- [in] | ||
sysRst => r.saciRst, -- [in] | ||
asicRstL => asicRstL, -- [in] | ||
req => r.req, -- [in] | ||
ack => ack, -- [out] | ||
fail => fail, -- [out] | ||
chip => r.chip, -- [in] | ||
op => r.op, -- [in] | ||
addr => r.addr, -- [in] | ||
wrData => r.wrData, -- [in] | ||
rdData => rdData, -- [out] | ||
saciClk => saciClk, -- [out] | ||
saciSelL => saciSelL, -- [out] | ||
saciCmd => saciCmd, -- [out] | ||
saciRsp => saciRsp); -- [in] | ||
|
||
comb : process (ack, asicRstL, axilReadMaster, axilRst, axilWriteMaster, fail, r, rdData, saciBusGr) is | ||
variable v : RegType; | ||
variable axilStatus : AxiLiteStatusType; | ||
variable resp : slv(1 downto 0); | ||
begin | ||
-- Latch the current value | ||
v := r; | ||
|
||
-- Reset the strobing signals | ||
resp := AXI_RESP_OK_C; | ||
|
||
-- Check the timer | ||
if r.timer /= TIMEOUT_C then | ||
-- Increment the counter | ||
v.timer := r.timer + 1; | ||
end if; | ||
|
||
-- Determine the transaction type | ||
axiSlaveWaitTxn(axilWriteMaster, axilReadMaster, v.axilWriteSlave, v.axilReadSlave, axilStatus); | ||
|
||
-- State Machine | ||
case (r.state) is | ||
---------------------------------------------------------------------- | ||
when IDLE_S => | ||
-- Reset the timer | ||
v.saciRst := '0'; | ||
v.timer := 0; | ||
v.saciBusReq := '0'; | ||
if (saciBusGr = '1') and (asicRstL = '1') then | ||
-- Check for a write request | ||
if (axilStatus.writeEnable = '1') then | ||
v.saciBusReq := '1'; | ||
-- SACI Commands | ||
v.req := '1'; | ||
v.op := '1'; | ||
v.chip := axilWriteMaster.awaddr(SACI_ADDR_BITS_G+CHIP_BITS_C-1 downto SACI_ADDR_BITS_G); | ||
if (SACI_NUM_CHIPS_G = 1) then | ||
v.chip := "0"; | ||
end if; | ||
v.addr(SACI_ADDR_BITS_G-1 downto 0) := axilWriteMaster.awaddr(SACI_ADDR_BITS_G+1 downto 2); | ||
v.wrData := axilWriteMaster.wdata; | ||
-- Next state | ||
v.state := SACI_REQ_S; | ||
-- Check for a read request | ||
elsif (axilStatus.readEnable = '1') then | ||
v.saciBusReq := '1'; | ||
-- SACI Commands | ||
v.req := '1'; | ||
v.op := '0'; | ||
v.chip := axilReadMaster.araddr(SACI_ADDR_BITS_G+CHIP_BITS_C-1 downto SACI_ADDR_BITS_G); | ||
if (SACI_NUM_CHIPS_G = 1) then | ||
v.chip := "0"; | ||
end if; | ||
v.addr := axilReadMaster.araddr(SACI_ADDR_BITS_G+1 downto 2); | ||
v.wrData := (others => '0'); | ||
-- Next state | ||
v.state := SACI_REQ_S; | ||
end if; | ||
else | ||
if (axilStatus.writeEnable = '1') then | ||
axiSlaveWriteResponse(v.axilWriteSlave, AXI_RESP_SLVERR_C); | ||
elsif (axilStatus.readEnable = '1') then | ||
axiSlaveReadResponse(v.axilReadSlave, AXI_RESP_SLVERR_C); | ||
end if; | ||
end if; | ||
---------------------------------------------------------------------- | ||
when SACI_REQ_S => | ||
if (ack = '1' and fail = '1') or (r.timer = TIMEOUT_C) then | ||
-- Set the error flags | ||
resp := AXI_RESP_SLVERR_C; | ||
v.req := '0'; | ||
v.saciRst := '1'; | ||
elsif (ack = '1') then | ||
-- Reset the flag | ||
v.req := '0'; | ||
end if; | ||
|
||
|
||
if (v.req = '0') then | ||
-- Check for Write operation | ||
if (r.op = '1') then | ||
--- Send AXI-Lite response | ||
axiSlaveWriteResponse(v.axilWriteSlave, resp); | ||
else | ||
-- Return the read data bus | ||
v.axilReadSlave.rdata := rdData; | ||
-- Send AXI-Lite Response | ||
axiSlaveReadResponse(v.axilReadSlave, resp); | ||
end if; | ||
-- Next state | ||
v.state := SACI_ACK_S; | ||
end if; | ||
---------------------------------------------------------------------- | ||
when SACI_ACK_S => | ||
-- Check status of ACK flag | ||
if (ack = '0') then | ||
-- Next state | ||
v.state := IDLE_S; | ||
end if; | ||
---------------------------------------------------------------------- | ||
end case; | ||
|
||
-- Synchronous Reset | ||
if axilRst = '1' then | ||
v := REG_INIT_C; | ||
end if; | ||
|
||
-- Register the variable for next clock cycle | ||
rin <= v; | ||
|
||
-- Outputs | ||
axilReadSlave <= r.axilReadSlave; | ||
axilWriteSlave <= r.axilWriteSlave; | ||
saciBusReq <= r.saciBusReq; | ||
|
||
end process comb; | ||
|
||
seq : process (axilClk) is | ||
begin | ||
if rising_edge(axilClk) then | ||
r <= rin after TPD_G; | ||
end if; | ||
end process seq; | ||
|
||
end rtl; |
Oops, something went wrong.