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/gn4124-core
1 result
Show changes
Showing
with 0 additions and 10320 deletions
files = [
"gn412x_bfm.vhd",
"cmd_router.vhd",
"textutil.vhd",
"mem_model.vhd",
"util.vhd",
"tb_spec.vhd",
"cmd_router1.vhd",
]
library IEEE;
use IEEE.std_logic_1164.all;
use std.textio.all;
--library std_developerskit;
--use std_developerskit.std_iopak.all;
use work.util.all;
use work.textutil.all;
--==========================================================================--
--
-- *MODULE << cmd_router >>
--
-- *Description : This module routes commands to all command driven modules
-- in the simulation. It instanciates N_FILES instances of
-- cmd_router1 and agregates the outputs to control N_BFM BFMs.
--
-- *History: M. Alford (originaly created 1993 with subsequent updates)
--
--==========================================================================--
--==========================================================================--
-- Operation
--
-- This module opens a text file and passes commands to individual vhdl models.
--
--==========================================================================--
entity cmd_router is
generic( N_BFM : integer := 8;
N_FILES : integer := 3;
FIFO_DEPTH : integer := 16;
STRING_MAX : integer := 256
);
port( CMD : out string(1 to STRING_MAX);
CMD_REQ : out bit_vector(N_BFM-1 downto 0);
CMD_ACK : in bit_vector(N_BFM-1 downto 0);
CMD_ERR : in bit_vector(N_BFM-1 downto 0);
CMD_CLOCK_EN : out boolean
);
end cmd_router;
architecture MODEL of cmd_router is
component cmd_router1
generic( N_BFM : integer := 8;
FIFO_DEPTH : integer := 8;
STRING_MAX : integer := 256;
FILENAME : string :="cmdfile.vec"
);
port( CMD : out STRING(1 to STRING_MAX);
CMD_REQ : out bit_vector(N_BFM-1 downto 0);
CMD_ACK : in bit_vector(N_BFM-1 downto 0);
CMD_ERR : in bit_vector(N_BFM-1 downto 0);
CMD_CLOCK_EN : out boolean;
CMD_DONE_IN : in boolean;
CMD_DONE_OUT : out boolean
);
end component; -- cmd_router1
type FILE_ARRAY is array (natural range <>) of string(1 to 8);
type CMD_ARRAY is array (natural range <>) of string(CMD'range);
type CMD_REQ_ARRAY is array (natural range <>) of bit_vector(N_BFM-1 downto 0);
type integer_vector is array (natural range <>) of integer;
type boolean_vector is array (natural range <>) of boolean;
constant MAX_FILES : integer := 10;
constant FILENAMES : FILE_ARRAY(0 to MAX_FILES-1) := ( "cmd0.vec", "cmd1.vec",
"cmd2.vec", "cmd3.vec",
"cmd4.vec", "cmd5.vec",
"cmd6.vec", "cmd7.vec",
"cmd8.vec", "cmd9.vec" );
signal CMDo : CMD_ARRAY(N_FILES-1 downto 0);
signal REQ : bit_vector(CMD_REQ'range);
signal CMD_REQo : CMD_REQ_ARRAY(N_FILES-1 downto 0);
signal CMD_ACKi : CMD_REQ_ARRAY(N_FILES-1 downto 0);
signal CMD_ACK_MASK : CMD_REQ_ARRAY(N_FILES-1 downto 0); -- 1 bit_vector per file to mask CMD_ACK
signal CMD_CLOCK_ENo : boolean_vector(N_FILES-1 downto 0);
signal CMD_ALL_DONE : boolean;
signal CMD_DONE_OUT : boolean_vector(N_FILES-1 downto 0);
function or_reduce(ARG: bit_vector) return bit is
variable result: bit;
begin
result := '0';
for i in ARG'range loop
result := result or ARG(i);
end loop;
return result;
end;
function or_reduce(ARG: boolean_vector) return boolean is
variable result: boolean;
begin
result := FALSE;
for i in ARG'range loop
result := result or ARG(i);
end loop;
return result;
end;
function and_reduce(ARG: boolean_vector) return boolean is
variable result: boolean;
begin
result := TRUE;
for i in ARG'range loop
result := result and ARG(i);
end loop;
return result;
end;
begin
-----------------------------------------------------------------------------
-- Instanciate 1 cmd_router1 per file to be processed
-----------------------------------------------------------------------------
G1 : for i in 0 to N_FILES-1 generate
U1 : cmd_router1
generic map
( N_BFM => N_BFM,
FIFO_DEPTH => FIFO_DEPTH,
STRING_MAX => STRING_MAX,
FILENAME => FILENAMES(i)
)
port map
( CMD => CMDo(i),
CMD_REQ => CMD_REQo(i),
CMD_ACK => CMD_ACKi(i),
CMD_ERR => CMD_ERR,
CMD_CLOCK_EN => CMD_CLOCK_ENo(i),
CMD_DONE_IN => CMD_ALL_DONE,
CMD_DONE_OUT => CMD_DONE_OUT(i)
);
end generate;
-----------------------------------------------------------------------------
-- Multiplex the commands from the cmd_router1 modules
-----------------------------------------------------------------------------
process
variable vDONE : boolean;
begin
CMD <= (others => '0');
wait on CMD_REQo;
vDONE := FALSE;
while(not vDONE) loop
vDONE := TRUE;
for i in 0 to N_FILES-1 loop -- Loop on each file
if(or_reduce(CMD_REQo(i)) = '1') then -- this file wants to do a command
vDONE := FALSE;
--
-- if the ACK is already on from another cmd_router1
--
while(or_reduce(CMD_REQo(i) and CMD_ACK) = '1') loop
wait on CMD_ACK;
end loop;
--
-- Do the request
--
CMD <= CMDo(i);
REQ <= CMD_REQo(i);
--
-- Wait for the ACK
--
wait until(CMD_ACK'event and (or_reduce(CMD_ACK and REQ) = '1'));
--
-- send the ack to the proper file
--
for j in 0 to N_FILES-1 loop
if(i = j) then -- enable this one
CMD_ACK_MASK(j) <= CMD_ACK_MASK(j) or REQ;
else
CMD_ACK_MASK(j) <= CMD_ACK_MASK(j) and not REQ;
end if;
end loop;
--
-- Wait for the request to de-assert
--
while(or_reduce(CMD_REQo(i) and REQ) = '1') loop
wait on CMD_REQo;
end loop;
REQ <= (others => '0');
end if;
end loop;
end loop;
end process;
process(CMD_ACK, CMD_ACK_MASK)
begin
for i in 0 to N_FILES-1 loop -- Loop on each file
CMD_ACKi(i) <= CMD_ACK and CMD_ACK_MASK(i);
end loop;
end process;
CMD_REQ <= REQ;
CMD_ALL_DONE <= and_reduce(CMD_DONE_OUT);
CMD_CLOCK_EN <= CMD_CLOCK_ENo(0);
end MODEL;
library IEEE;
use IEEE.std_logic_1164.all;
use std.textio.all;
--library std_developerskit;
--use std_developerskit.std_iopak.all;
use work.util.all;
use work.textutil.all;
--==========================================================================--
--
-- *MODULE << model1 >>
--
-- *Description : This module routes commands to all command driven modules
-- in the simulation.
--
-- *History: M. Alford (originaly created 1993 with subsequent updates)
--
--==========================================================================--
--==========================================================================--
-- Operation
--
-- This module opens a text file and passes commands to individual vhdl models.
--
--==========================================================================--
entity cmd_router1 is
generic( N_BFM : integer := 8;
FIFO_DEPTH : integer := 8;
STRING_MAX : integer := 256;
FILENAME : string :="cmdfile.vec"
);
port( CMD : out STRING(1 to STRING_MAX);
CMD_REQ : out bit_vector(N_BFM-1 downto 0);
CMD_ACK : in bit_vector(N_BFM-1 downto 0);
CMD_ERR : in bit_vector(N_BFM-1 downto 0);
CMD_CLOCK_EN : out boolean;
CMD_DONE_IN : in boolean;
CMD_DONE_OUT : out boolean
);
end cmd_router1;
architecture MODEL of cmd_router1 is
type STRING_ARRAY is array (FIFO_DEPTH-1 downto 0) of STRING(1 to STRING_MAX);
type FD_ARRAY is array (N_BFM-1 downto 0) of STRING_ARRAY;
type integer_vector is array (natural range <>) of integer;
signal FD : FD_ARRAY;
signal ERR_CNT : integer;
signal PUSH_PTR : integer_vector(N_BFM-1 downto 0);
signal POP_PTR : integer_vector(N_BFM-1 downto 0);
signal SET_CHAN : std_ulogic;
signal POP_INIT : std_ulogic;
signal CMD_REQo : bit_vector(CMD_REQ'range);
signal LINE_NUM : integer;
begin
PUSH_PROCESS : process
file FOUT : text open write_mode is "usc.lst";
file stim_file : text open read_mode is FILENAME;
file out_file : text open write_mode is "STD_OUTPUT";
-------- For VHDL-87
-- file stim_file : text is in FILENAME;
-- file out_file : text is out "STD_OUTPUT";
variable input_line : line;
variable output_line : line;
variable tmp_lout : line;
variable command : string(1 to 8);
variable tmp_str : string(1 to STRING_MAX);
variable input_str : string(1 to STRING_MAX);
variable i : integer;
variable CHANNEL : integer;
variable S_PTR : integer;
variable vLINE_NUM : integer;
variable vPUSH_PTR : integer_vector(N_BFM-1 downto 0);
variable DONE : boolean;
variable EOS : integer;
variable ERR : integer;
begin
-----------------------------------------------------------------------------
-- Main Loop
-----------------------------------------------------------------------------
vLINE_NUM := 0;
PUSH_PTR <= (others => 0);
vPUSH_PTR := (others => 0);
CHANNEL := 0;
CMD_CLOCK_EN <= TRUE;
SET_CHAN <= '0';
CMD_DONE_OUT <= FALSE;
if(POP_INIT /= '1') then
wait until(POP_INIT'event and (POP_INIT = '1'));
end if;
ST_LOOP: while not endfile(stim_file) loop
readline(stim_file, input_line);
S_PTR := 1;
vLINE_NUM := vLINE_NUM + 1;
LINE_NUM <= vLINE_NUM;
-- Copy the line
input_str := (others => ' ');
input_str(1 to 6) := To_Strn(vLINE_NUM, 6);
input_str(7 to 8) := string'(": ");
input_str(9 to input_line'length+8) := string'(input_line.all);
while(input_str(S_PTR) /= ':') loop
S_PTR := S_PTR + 1;
end loop;
S_PTR := S_PTR + 1;
sget_token(input_str, S_PTR, command);
SET_CHAN <= '1';
for j in STRING_MAX downto 1 loop
if(input_str(j) /= ' ') then
EOS := j;
exit;
end if;
end loop;
---------------------------
-- "model" command ?
---------------------------
if(command(1 to 5) = "model") then
sget_int(input_str, S_PTR, i);
write(tmp_lout, FILENAME);
write(tmp_lout, input_str(1 to EOS));
writeline(out_file, tmp_lout);
if((i >= N_BFM) or (i < 0)) then
CHANNEL := N_BFM-1;
write(tmp_lout, string'("ERROR: Invalid Channel "));
write(tmp_lout, i);
writeline(out_file, tmp_lout);
else
CHANNEL := i;
end if;
---------------------------
-- "sync" command ?
---------------------------
elsif(command(1 to 4) = "sync") then
loop
DONE := TRUE;
for i in PUSH_PTR'reverse_range loop
if((vPUSH_PTR(i) /= POP_PTR(i)) or (CMD_ACK(i) /= '0')) then
DONE := FALSE;
end if;
end loop;
if(DONE) then
exit;
end if;
wait on POP_PTR, CMD_ACK;
end loop;
write(tmp_lout, FILENAME);
write(tmp_lout, input_str(1 to EOS));
writeline(out_file, tmp_lout);
---------------------------
-- "gsync" and "ckoff" command ?
---------------------------
elsif((command(1 to 5) = "gsync") or (command(1 to 5) = "ckoff")) then
write(tmp_lout, FILENAME);
write(tmp_lout, string'(": entering the gsync command"));
writeline(out_file, tmp_lout);
loop
DONE := TRUE;
for i in PUSH_PTR'reverse_range loop
if((vPUSH_PTR(i) /= POP_PTR(i)) or (CMD_ACK(i) /= '0')) then
DONE := FALSE;
end if;
end loop;
if(DONE) then
exit;
end if;
wait on POP_PTR, CMD_ACK;
end loop;
CMD_DONE_OUT <= TRUE;
-- wait for the external CMD_DONE_IN to be done
while (not CMD_DONE_IN) loop
wait on CMD_DONE_IN;
end loop;
CMD_DONE_OUT <= FALSE;
write(tmp_lout, FILENAME);
write(tmp_lout, input_str(1 to EOS));
writeline(out_file, tmp_lout);
if (command(1 to 5) = "ckoff") then
CMD_CLOCK_EN <= FALSE;
end if;
write(tmp_lout, FILENAME);
write(tmp_lout, string'(": gsync command is DONE"));
writeline(out_file, tmp_lout);
--------------------
-- ckon
--------------------
elsif (command(1 to 4) = "ckon") then
CMD_CLOCK_EN <= TRUE;
write(tmp_lout, FILENAME);
write(tmp_lout, input_str(1 to EOS));
writeline(out_file, tmp_lout);
---------------------------
-- put the line in the FIFO
---------------------------
else
FD(CHANNEL)(vPUSH_PTR(CHANNEL)) <= input_str;
vPUSH_PTR(CHANNEL) := vPUSH_PTR(CHANNEL) + 1;
if(vPUSH_PTR(CHANNEL) >= FIFO_DEPTH) then
vPUSH_PTR(CHANNEL) := 0;
end if;
if(vPUSH_PTR(CHANNEL) = POP_PTR(CHANNEL)) then -- The FIFO is full
wait until(POP_PTR'event and (vPUSH_PTR(CHANNEL) /= POP_PTR(CHANNEL)));
end if;
PUSH_PTR(CHANNEL) <= vPUSH_PTR(CHANNEL);
end if;
end loop;
loop
DONE := TRUE;
for i in POP_PTR'reverse_range loop
if((POP_PTR(i) /= vPUSH_PTR(i)) or (CMD_ACK(i) = '1')) then -- FIFO channel not empty
DONE := FALSE;
end if;
end loop;
if(DONE) then
exit;
end if;
wait on CMD_ACK, POP_PTR;
end loop;
CMD_DONE_OUT <= TRUE;
write(output_line, string'("******************************* Test Finished *******************************"));
writeline(out_file, output_line);
write(output_line, string'("* Total Errors for "));
write(output_line, FILENAME);
write(output_line, string'(": "));
write(output_line, err_cnt);
writeline(out_file, output_line);
write(output_line, string'("*****************************************************************************"));
writeline(out_file, output_line);
file_close(stim_file); -- Close File
loop
wait for 100000 us;
end loop;
end process;
-----------------------------------------------------------------------------
-- POP Process
-----------------------------------------------------------------------------
POP_PROCESS : process
variable vPOP_PTR : integer_vector(POP_PTR'range);
variable DONE : boolean;
file out_file : text open write_mode is "STD_OUTPUT";
-------- For VHDL-87
-- file out_file : text is out "STD_OUTPUT";
variable tmp_lout : line;
variable CHAR_PTR : integer;
variable EOS : integer;
begin
CHAR_PTR := 1;
ERR_CNT <= 0;
POP_PTR <= (others => 0);
vPOP_PTR := (others => 0);
CMD_REQo <= (others => '0');
POP_INIT <= '1';
if(SET_CHAN /= '1') then
wait until(SET_CHAN'event and (SET_CHAN = '1'));
end if;
loop
DONE := FALSE;
loop
DONE := TRUE;
for i in POP_PTR'reverse_range loop
if((vPOP_PTR(i) /= PUSH_PTR(i)) and (CMD_ACK(i) = '0')) then -- FIFO channel not empty
CMD <= FD(i)(vPOP_PTR(i));
CMD_REQo(i) <= '1';
for j in STRING_MAX downto 1 loop
if(FD(i)(vPOP_PTR(i))(j) /= ' ') then
EOS := j;
exit;
end if;
end loop;
write(tmp_lout, FILENAME);
write(tmp_lout, FD(i)(vPOP_PTR(i))(1 to EOS));
writeline(out_file, tmp_lout);
if(CMD_ACK(i) /= '1') then
wait until(CMD_ACK'event and (CMD_ACK(i) = '1'));
end if;
CMD_REQo(i) <= '0';
DONE := FALSE;
vPOP_PTR(i) := vPOP_PTR(i) + 1;
if(vPOP_PTR(i) >= FIFO_DEPTH) then
vPOP_PTR(i) := 0;
end if;
POP_PTR(i) <= vPOP_PTR(i);
end if;
end loop;
if(DONE) then
exit;
end if;
end loop;
wait on PUSH_PTR, CMD_ACK;
end loop;
end process;
CMD_REQ <= CMD_REQo;
end MODEL;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;
use work.util.all;
use work.textutil.all;
use work.mem_model.all;
--==========================================================================--
--
-- MODULE << gn412x_bfm >>
--
-- Description : This module generates local bus signals from a text file
--
-- History:
--
--==========================================================================--
--
-- To Do:
-- Implement rd_outstanding_in
-- Implement gpio for interrupts
-- Implement response_delay
entity GN412X_BFM is
generic
(
STRING_MAX : integer := 256; -- Command string maximum length
T_LCLK : time := 10 ns; -- Local Bus Clock Period
T_P2L_CLK_DLY : time := 2 ns; -- Delay from LCLK to P2L_CLK
INSTANCE_LABEL : string := "GN412X_BFM"; -- Label string to be used as a prefix for messages from the model
MODE_PRIMARY : boolean := TRUE -- TRUE for BFM acting as GN412x, FALSE for BFM acting as the DUT
);
port
(
--=========================================================--
-------------------------------------------------------------
-- CMD_ROUTER Interface
--
CMD : in STRING(1 to STRING_MAX);
CMD_REQ : in BIT;
CMD_ACK : out BIT;
CMD_CLOCK_EN : in boolean;
--=========================================================--
-------------------------------------------------------------
-- GN412x Signal I/O
-------------------------------------------------------------
-- This is the reset input to the BFM
--
RSTINn : in std_logic;
-------------------------------------------------------------
-- Reset outputs to DUT
--
RSTOUT18n : out std_logic;
RSTOUT33n : out std_logic;
-------------------------------------------------------------
----------------- Local Bus Clock ---------------------------
------------------------------------------------------------- __ Direction for primary mode
-- / \
LCLK, LCLKn : inout std_logic; -- Out
-------------------------------------------------------------
----------------- Local-to-PCI Dataflow ---------------------
-------------------------------------------------------------
-- Transmitter Source Synchronous Clock.
--
L2P_CLKp, L2P_CLKn : inout std_logic; -- In
-------------------------------------------------------------
-- L2P DDR Link
--
L2P_DATA : inout std_logic_vector(15 downto 0); -- In -- Parallel Transmit Data.
L2P_DFRAME : inout std_logic; -- In -- Transmit Data Frame.
L2P_VALID : inout std_logic; -- In -- Transmit Data Valid.
L2P_EDB : inout std_logic; -- In -- End-of-Packet Bad Flag.
-------------------------------------------------------------
-- L2P SDR Controls
--
L_WR_RDY : inout std_logic_vector( 1 downto 0); -- Out -- Local-to-PCIe Write.
P_RD_D_RDY : inout std_logic_vector( 1 downto 0); -- Out -- PCIe-to-Local Read Response Data Ready.
L2P_RDY : inout std_logic; -- Out -- Tx Buffer Full Flag.
TX_ERROR : inout std_logic; -- Out -- Transmit Error.
-------------------------------------------------------------
----------------- PCIe-to-Local Dataflow ---------------------
-------------------------------------------------------------
-- Transmitter Source Synchronous Clock.
--
P2L_CLKp, P2L_CLKn : inout std_logic; -- Out -- P2L Source Synchronous Clock.
-------------------------------------------------------------
-- P2L DDR Link
--
P2L_DATA : inout std_logic_vector(15 downto 0); -- Out -- Parallel Receive Data.
P2L_DFRAME : inout std_logic; -- Out -- Receive Frame.
P2L_VALID : inout std_logic; -- Out -- Receive Data Valid.
-------------------------------------------------------------
-- P2L SDR Controls
--
P2L_RDY : inout std_logic; -- In -- Rx Buffer Full Flag.
P_WR_REQ : inout std_logic_vector( 1 downto 0); -- Out -- PCIe Write Request.
P_WR_RDY : inout std_logic_vector( 1 downto 0); -- In -- PCIe Write Ready.
RX_ERROR : inout std_logic; -- In -- Receive Error.
VC_RDY : inout std_logic_vector( 1 downto 0); -- Out -- Virtual Channel Ready Status.
-------------------------------------------------------------
-- GPIO signals
--
GPIO : inout std_logic_vector(15 downto 0)
);
end GN412X_BFM;
architecture MODEL of GN412X_BFM is
--=========================================================================--
-- Routine for Data-Comparison
--=========================================================================--
procedure read_cmp(L : inout LINE; PREFIX : in string; DATA, CMP_VAL, MASK:in std_ulogic_vector; ERR: out integer) is
variable X : std_ulogic_vector(DATA'range);
variable STR : string(1 to 32);
begin
X := (others => 'X');
X := (not MASK and X) or (MASK and CMP_VAL);
STR(1 to X'length) := to_str(X);
if((DATA and MASK) /= (CMP_VAL and MASK)) then
write(L, PREFIX & string'("ERROR @ "));
write(L, now);
write(L, string'(" : "));
write(L, LF);
write(L, string'(" Expected => "));
write(L, STR(1 to X'length));
write(L, string'(" (0x"));
write_hex_vector(L, X);
write(L, string'(")"));
STR(1 to X'length) := to_str(DATA);
write(L, LF);
write(L, string'(" Actually Read => "));
write(L, STR(1 to X'length));
write(L, string'(" (0x"));
write_hex_vector(L, DATA);
write(L, string'(")"));
ERR := 1;
else
-- write(L, string'("Read OK @ "));
-- write(L, now);
-- write(L, string'(" : "));
-- write(L, LF);
-- write(L, string'(" Expected => "));
-- write(L, STR(1 to X'length));
ERR := 0;
end if;
end read_cmp;
--=========================================================================--
-- Routine to read a boolean from a string
--
-- it looks for true, false, on, off, 1, 0
--=========================================================================--
procedure sget_boolean(S : in string; P : inout integer; X : out boolean) is
variable char : character;
variable q : integer;
begin
if(S'length > P) then
char := S(P);
while(char = ' ') loop -- Skip spaces
P := P + 1;
char := S(P);
end loop;
if(S(P to P+4) = "true ") or (S(P to P+2) = "on ") or (S(P to P+1) = "1 ") then
X := TRUE;
elsif(S(P to P+5) = "false ") or (S(P to P+3) = "off ") or (S(P to P+1) = "0 ") then
X := FALSE;
else
assert false report "ERROR: Couldn't read a boolean" severity error;
end if;
-- skip over token
while((char /= ' ') and (P < S'length)) loop
char := S(P);
P := P + 1;
end loop;
else
assert false report "ERROR: Couldn't read a boolean" severity error;
end if;
end sget_boolean;
--=========================================================================--
-- Produce Another Random Number
--
-- RNDOUT is a number between MIN and MAX. SR must be stored and fed back each call.
--=========================================================================--
procedure next_random(SR : inout integer) is
variable SRV : std_ulogic_vector(22 downto 0);
variable SRI : integer;
begin
SRV := To_Vector(SR, SRV'length);
SRV := SRV(21 downto 0) & (SRV(22) xor SRV(17));
SRI := conv_integer(SRV);
SR := SRI;
end next_random;
-- function next_random(SR : integer) return integer is
-- variable SRV : std_ulogic_vector(22 downto 0);
-- variable SRI : integer;
-- begin
-- SRV := To_Vector(SR, SRV'length);
-- SRV := SRV(21 downto 0) & (SRV(22) xor SRV(17));
-- SRI := conv_integer(SRV);
-- return(SRI);
-- end next_random;
--=========================================================================--
-- Produce Another Random Number
--
-- RNDOUT is a number between MIN and MAX. SR must be stored and fed back each call.
--=========================================================================--
procedure get_random(SR : inout integer; MIN : in integer; MAX : in integer; RNDOUT : out integer) is
variable SRV : std_ulogic_vector(22 downto 0);
variable SRI : integer;
begin
SRV := To_Vector(SR, SRV'length);
SRV := SRV(21 downto 0) & (SRV(22) xor SRV(17));
SRI := conv_integer(SRV);
RNDOUT := MIN + (SRI mod (MAX - MIN + 1));
SR := SRI;
end get_random;
--=========================================================================--
-- Test a Random Number and test it
--
-- RNDOUT is a number between MIN and MAX. SR must be stored and fed back each call.
--=========================================================================--
function test_random(SR : integer; PROBABILITY : integer) return boolean is
begin
return((SR mod 101) < PROBABILITY);
end test_random;
--=========================================================================--
-- Produce a Random Number between MIN and MAX
--=========================================================================--
function range_random(SR : integer; MIN : integer; MAX : integer) return integer is
begin
return(MIN + (SR mod (MAX - MIN + 1)));
end range_random;
--=========================================================================--
-- Signal Declarations
--=========================================================================--
-----------------------------------------------------------------------------
-- Global Settings
-----------------------------------------------------------------------------
constant N_BARS : integer := 2;
constant N_RAM_MAX : integer := 30; -- Maximim size of BFM RAM address = 2**N_RAM_MAX
constant N_OUTBOUND_RD_OUTSTANDING : integer := 3; -- Maximim number of outstanding reads the BFM will generate
constant N_INBOUND_RD_OUTSTANDING : integer := 3; -- Maximim number of outstanding reads the BFM will accept
constant N_COMPLETION_ID : integer := 4; -- Maximim number of completion IDs
-------------------------------------------------------------------------
-- Settable versions of the generic constants
--
signal T_LCLKi : time := T_LCLK; -- Local Bus Clock Period
signal T_P2L_CLK_DLYi : time := T_P2L_CLK_DLY; -- Delay from LCLK to P2L_CLK
--
-------------------------------------------------------------------------
-- BFM Mode settings
--
signal PRIMARY : boolean;
signal SECONDARY : boolean;
signal GENERATE_X : boolean := FALSE;
signal EXPECT_ERROR : boolean := FALSE;
signal OUTBOUND_RD_OUTSTANDING : integer := N_OUTBOUND_RD_OUTSTANDING;
signal RESPONSE_DELAY : integer := 0;
-- signal BURST_LENGTH : integer := 0;
-- signal BURST_MODULO : integer := 0;
-- Acceptable values for TYPE are: "0000" for 32-bit memory read
-- Acceptable values for TYPE are: "0001" for 64-bit memory read
-- Acceptable values for TYPE are: "0010" for 32-bit memory write
-- Acceptable values for TYPE are: "0011" for 64-bit memory write
-- Acceptable values for TYPE are: "0100" for Completions without data
-- Acceptable values for TYPE are: "0101" for Completions with data
signal GPIOi : std_ulogic_vector(GPIO'range);
signal GPIOo : std_ulogic_vector(GPIO'range);
-----------------------------------------------------------------------------
-- Top Level I/O signals PRIMARY MODE
-----------------------------------------------------------------------------
-------------------------------------------------------------
----------------- Local Bus Clock ---------------------------
-------------------------------------------------------------
--
signal LCLKo, LCLKno : std_ulogic;
-------------------------------------------------------------
----------------- Local-to-PCI Dataflow ---------------------
-------------------------------------------------------------
-- Transmitter Source Synchronous Clock.
--
signal L2P_CLKpi, L2P_CLKni : std_ulogic;
signal L2P_CLKi_90 : std_ulogic;
-------------------------------------------------------------
-- L2P DDR Link
--
signal L2P_DATAi : std_ulogic_vector(15 downto 0); -- Parallel Transmit Data.
signal L2P_DFRAMEi : std_ulogic; -- Transmit Data Frame.
signal L2P_VALIDi : std_ulogic; -- Transmit Data Valid.
signal L2P_EDBi : std_ulogic; -- End-of-Packet Bad Flag.
-------------------------------------------------------------
-- L2P SDR Controls
--
signal L_WR_RDYo : std_ulogic_vector( 1 downto 0); -- Local-to-PCIe Write.
signal P_RD_D_RDYo : std_ulogic_vector( 1 downto 0); -- PCIe-to-Local Read Response Data Ready.
signal L2P_RDYo : std_ulogic; -- Tx Buffer Full Flag.
signal TX_ERRORo : std_ulogic; -- Transmit Error.
-------------------------------------------------------------
----------------- PCIe-to-Local Dataflow ---------------------
-------------------------------------------------------------
-- Transmitter Source Synchronous Clock.
--
signal P2L_CLKpo, P2L_CLKno : std_ulogic; -- P2L Source Synchronous Clock.
-------------------------------------------------------------
-- P2L DDR Link
--
signal P2L_DATAo : std_ulogic_vector(15 downto 0); -- Parallel Receive Data.
signal P2L_DFRAMEo : std_ulogic; -- Receive Frame.
signal P2L_VALIDo : std_ulogic; -- Receive Data Valid.
-------------------------------------------------------------
-- P2L SDR Controls
--
signal P2L_RDYi : std_ulogic; -- Rx Buffer Full Flag.
signal P_WR_REQo : std_ulogic_vector( 1 downto 0); -- PCIe Write Request.
signal P_WR_RDYi : std_ulogic_vector( 1 downto 0); -- PCIe Write Ready.
signal RX_ERRORi : std_ulogic; -- Receive Error.
signal VC_RDYo : std_ulogic_vector( 1 downto 0); -- Virtual Channel Ready Status.
-----------------------------------------------------------------------------
-- Top Level I/O signals SECONDARY MODE
-----------------------------------------------------------------------------
-------------------------------------------------------------
----------------- Local Bus Clock ---------------------------
-------------------------------------------------------------
--
signal LCLKi, LCLKni : std_ulogic;
-------------------------------------------------------------
----------------- Local-to-PCI Dataflow ---------------------
-------------------------------------------------------------
-- Transmitter Source Synchronous Clock.
--
signal L2P_CLKpo, L2P_CLKno : std_ulogic;
-------------------------------------------------------------
-- L2P DDR Link
--
signal L2P_DATAo : std_ulogic_vector(15 downto 0); -- Parallel Transmit Data.
signal L2P_DFRAMEo : std_ulogic; -- Transmit Data Frame.
signal L2P_VALIDo : std_ulogic; -- Transmit Data Valid.
signal L2P_EDBo : std_ulogic; -- End-of-Packet Bad Flag.
-------------------------------------------------------------
-- L2P SDR Controls
--
signal L_WR_RDYi : std_ulogic_vector( 1 downto 0); -- Local-to-PCIe Write.
signal P_RD_D_RDYi : std_ulogic_vector( 1 downto 0); -- PCIe-to-Local Read Response Data Ready.
signal L2P_RDYi : std_ulogic; -- Tx Buffer Full Flag.
signal TX_ERRORi : std_ulogic; -- Transmit Error.
-------------------------------------------------------------
----------------- PCIe-to-Local Dataflow ---------------------
-------------------------------------------------------------
-- Transmitter Source Synchronous Clock.
--
signal P2L_CLKpi, P2L_CLKni : std_ulogic; -- P2L Source Synchronous Clock.
-------------------------------------------------------------
-- P2L DDR Link
--
signal P2L_DATAi : std_ulogic_vector(15 downto 0); -- Parallel Receive Data.
signal P2L_DFRAMEi : std_ulogic; -- Receive Frame.
signal P2L_VALIDi : std_ulogic; -- Receive Data Valid.
-------------------------------------------------------------
-- P2L SDR Controls
--
signal P2L_RDYo : std_ulogic; -- Rx Buffer Full Flag.
signal P_WR_REQi : std_ulogic_vector( 1 downto 0); -- PCIe Write Request.
signal P_WR_RDYo : std_ulogic_vector( 1 downto 0); -- PCIe Write Ready.
signal RX_ERRORo : std_ulogic; -- Receive Error.
signal VC_RDYi : std_ulogic_vector( 1 downto 0); -- Virtual Channel Ready Status.
-------------------------------------------------------------
-- Used by the Inbound State Machine
--
signal ICLK : std_ulogic; -- Internal Inbound clock
signal LCLK_PERIOD : time := T_LCLK;
-----------------------------------------------------------------------------
-- Internal Model Signals
-----------------------------------------------------------------------------
type integer_vector is array (natural range <>) of integer;
type boolean_vector is array (natural range <>) of boolean;
-------------------------------------------------------------------------
-- Largest Cache line size supported
--
constant N_MAX_LENGTH : integer := 12;
constant MAX_LENGTH : integer := 2**N_MAX_LENGTH;
-------------------------------------------------------------------------
-- An array of MAX_CACHE * 32 bits
--
type ARRAY_OF_32 is array (natural range <>) of std_ulogic_vector(31 downto 0);
type ARRAY_OF_2 is array (natural range <>) of std_ulogic_vector(1 downto 0);
-- signal CACHE_BUFFER : ARRAY_OF_32(MAX_CACHE-1 downto 0);
-------------------------------------------------------------------------
--
signal CLK0o : std_ulogic;
signal CLK90o : std_ulogic;
signal CLK : std_ulogic; -- This one is used by the main loop
signal RSTOUTo : std_ulogic:= '0';
constant T_HOLD_OUT : time := 1 ns;
signal T_HOLD_OUTi : time := T_HOLD_OUT;
constant WR_FLUSH_POST : integer := 0;
constant WR_POST : integer := 1;
constant WR_POST_FLUSH : integer := 2;
constant WR_FLUSH_POST_LAST : integer := 3;
constant RD_POST : integer := 0;
constant RD_POST_IPR : integer := 1;
constant RD_IPR_POST : integer := 2;
constant RD_IPR_POST_LAST : integer := 3;
constant MAX_DW_PACKET_SIZE : integer := 1024; -- Maximum packet size in units of DW (32 bits)
type INT_VECTOR is array (natural range <>) of integer;
type DATA32 is array (natural range <>) of std_ulogic_vector(31 downto 0);
--=======================================================================
--==
--== Data Structures for INBOUND Read Requests that generate Outbound Completions
--==
--=======================================================================
-------------------------------------------------------------------------
-- Data Structure used to store inbound read requests
-- note: there are N_COMPLETION_ID size for this data structure rather
-- than N_INBOUND_RD_OUTSTANDING. Only up to N_INBOUND_RD_OUTSTANDING can be active at a time
type INBOUND_READ_REQUEST_TYPE is
record
ADDRESS : std_ulogic_vector(63 downto 0); -- BAR base address
BAR_HIT : std_ulogic_vector(1 downto 0); -- This is for secondary mode
TC : std_ulogic_vector(2 downto 0); -- Trafic class
V : std_ulogic; -- Virtual channel
LENGTH : integer; -- Transfer length in DW
STATE : boolean; -- Used to indicate if the entry is in use or not
end record;
type INBOUND_READ_REQUEST_ARRAY_TYPE is array (N_COMPLETION_ID-1 downto 0) of INBOUND_READ_REQUEST_TYPE;
signal INBOUND_READ_REQUEST_ARRAY : INBOUND_READ_REQUEST_ARRAY_TYPE;
-------------------------------------------------------------------------
-- This is the state of the CID for inbound read requests.
-- Used to signal back to the inbound process which completions have been serviced
-- When INBOUND_READ_REQUEST_ARRAY(CID).STATE = INBOUND_READ_REQUEST_CPL_STATE(CID) then the CID may be re-used
signal INBOUND_READ_REQUEST_CPL_STATE : boolean_vector(N_COMPLETION_ID-1 downto 0);
signal CURRENT_INBOUND_RD_IPR : integer; -- Indicates how many inbound reads are currently outstanding
--=======================================================================
--==
--== Data Structures for OUTBOUND Read Requests that result in Inbound Completions
--==
--=======================================================================
-- This data structure is written by the outbound process and
-- read by the inbound process to verify completion packets
type RD_BUFFER_TYPE is
record
ADDRESS : std_ulogic_vector(63 downto 0);
BAR_HIT : std_ulogic_vector(1 downto 0);
FBE : std_ulogic_vector(3 downto 0);
LBE : std_ulogic_vector(3 downto 0);
STATE : boolean;
DATA : DATA32(MAX_DW_PACKET_SIZE-1 downto 0);
MASK : DATA32(MAX_DW_PACKET_SIZE-1 downto 0);
end record;
type RD_BUFFER_ARRAY_TYPE is array (N_COMPLETION_ID-1 downto 0) of RD_BUFFER_TYPE;
signal RD_BUFFER : RD_BUFFER_ARRAY_TYPE;
-------------------------------------------------------------------------
-- Used to signal back to the inbound process which completions have been serviced
-- An entry is in use when OUTBOUND_READ_COMPLETION_STATE(i) /= INBOUND_READ_REQUEST_ARRAY(i).STATE
signal OUTBOUND_READ_REQUEST_CPL_STATE : boolean_vector(N_COMPLETION_ID-1 downto 0);
signal CURRENT_OUTBOUND_RD_IPR : integer; -- Indicates how many inbound reads are currently outstanding
--=======================================================================
--==
--== Data Structures for OUTBOUND Write Requests
--==
--=======================================================================
-- There is only a single write buffer and it lives as a variable in the outbound process
-- since the inbound process doesn't need to know anything about it
type WR_BUFFER_TYPE is
record
ADDRESS : std_ulogic_vector(63 downto 0);
BE : std_ulogic_vector(3 downto 0);
DATA : std_ulogic_vector(31 downto 0);
end record;
type WR_BUFFER_ARRAY_TYPE is array (MAX_DW_PACKET_SIZE-1 downto 0) of WR_BUFFER_TYPE;
-- signal WR_BUFFER : WR_BUFFER_ARRAY_TYPE;
signal RANDOM_NUMBER : integer := 0;
-------------------------------------------------------------------------
-- Data Structure used to store info about BARs that generate outbound
-- read/write packets
--
type BAR_ATTRIBUTE_TYPE is
record
BASE : std_ulogic_vector(63 downto 0); -- BAR base address
MASK : std_ulogic_vector(31 downto 0); -- BAR mask
VC : std_ulogic; -- Virtual Channel
TC : std_ulogic_vector(2 downto 0); -- Trafic class
S : std_ulogic; -- No Snoop Bit
end record;
type BAR_ATTRIBUTE_ARRAY_TYPE is array (1 downto 0) of BAR_ATTRIBUTE_TYPE;
signal BAR_ATTRIBUTE_ARRAY : BAR_ATTRIBUTE_ARRAY_TYPE;
-------------------------------------------------------------------------
-- Data Structure used to store info about memory BARs for internal BFM
--
type BFM_BAR_ATTRIBUTE_TYPE is
record
BASE : std_ulogic_vector(63 downto 0); -- BAR base address
MASK : std_ulogic_vector(31 downto 0); -- BAR mask
end record;
type BFM_BAR_ATTRIBUTE_ARRAY_TYPE is array (1 downto 0) of BFM_BAR_ATTRIBUTE_TYPE;
signal BFM_BAR_ATTRIBUTE_ARRAY : BFM_BAR_ATTRIBUTE_ARRAY_TYPE;
-- type VC_SIZE_VECTOR is array (natural range <>) of std_ulogic_vector(1 downto 0);
-----------------------------------------------------------------------------
-- Signals used by the outbound and inbound process to read the BFM RAM
-----------------------------------------------------------------------------
signal RAM_REQ0, RAM_REQ1 : boolean := FALSE; -- Request
signal RAM_WR0, RAM_WR1 : boolean; -- Write mode
signal RAM_ACK0, RAM_ACK1 : boolean; -- Acknowledge
signal RAM_ADDR0, RAM_ADDR1 : std_ulogic_vector(N_RAM_MAX-1 downto 0);
signal RAM_WR_DATA0, RAM_WR_DATA1 : std_ulogic_vector(7 downto 0);
signal RAM_RD_DATA0, RAM_RD_DATA1 : std_ulogic_vector(7 downto 0);
-----------------------------------------------------------------------------
-- Signals Related to the InBound Process
-----------------------------------------------------------------------------
signal IN_DATA : std_ulogic_vector(31 downto 0);
signal IN_DATA_LOW : std_ulogic_vector(15 downto 0);
signal IN_DFRAME : std_ulogic;
signal IN_VALID : std_ulogic;
signal Q_IN_DFRAME : std_ulogic;
-----------------------------------------------------------------------------
-- Signals Related to the OutBound Process
-----------------------------------------------------------------------------
signal Q_OUT_DATA, OUT_DATA : std_ulogic_vector(31 downto 0);
signal Q_OUT_DFRAME, OUT_DFRAME : std_ulogic;
signal Q_OUT_VALID, OUT_VALID : std_ulogic;
signal OUT_WR_REQ : std_ulogic_vector(P_WR_REQ'range);
signal OUT_WR_RDY : std_ulogic_vector(P_WR_RDY'range);
signal Q_OUT_WR_RDY : std_ulogic_vector(P_WR_RDY'range);
--#########################################################################--
--########################## Start of Code ################################--
--#########################################################################--
begin
--=========================================================================--
-- Reset Outputs
--=========================================================================--
RSTOUT18n <= not RSTOUTo when PRIMARY else 'Z';
RSTOUT33n <= not RSTOUTo when PRIMARY else 'Z';
--=========================================================================--
-- Generate the Internal LCLK
--=========================================================================--
process
begin
CLK0o <= '0';
CLK90o <= '0';
loop
if (CMD_CLOCK_EN and PRIMARY) then
CLK0o <= '1';
CLK0o <= transport '0' after (T_LCLKi/2);
CLK90o <= transport '1' after (T_LCLKi/4);
CLK90o <= transport '0' after ((T_LCLKi*3)/4);
wait for T_LCLKi;
else
wait until(CMD_CLOCK_EN'event and CMD_CLOCK_EN and PRIMARY);
end if;
end loop;
end process;
PRIMARY <= MODE_PRIMARY;
SECONDARY <= not MODE_PRIMARY;
--=========================================================================--
-- Top Level I/O signals with timing information
--=========================================================================--
--*************************************************************************--
-- Top Level I/O signals PRIMARY MODE
--*************************************************************************--
-------------------------------------------------------------
----------------- Local Bus Clock ---------------------------
-------------------------------------------------------------
--
LCLKo <= CLK0o;
LCLKno <= not CLK0o;
LCLK <= LCLKo when PRIMARY else 'Z';
LCLKn <= LCLKno when PRIMARY else 'Z';
-------------------------------------------------------------
----------------- Local-to-PCI Dataflow ---------------------
----------------- (GN412x is an input) ---------------------
-------------------------------------------------------------
-- Receiver Source Synchronous Clock.
--
L2P_CLKpi <= To_X01(L2P_CLKp);
L2P_CLKni <= To_X01(L2P_CLKn);
-------------------------------------------------------------
-- L2P DDR Link
--
L2P_DATAi <= To_X01(To_StdULogicVector(L2P_DATA));
L2P_DFRAMEi <= To_X01(L2P_DFRAME);
L2P_VALIDi <= To_X01(L2P_VALID);
L2P_EDBi <= To_X01(L2P_EDB);
-------------------------------------------------------------
-- L2P SDR Controls
--
L_WR_RDY <= To_StdLogicVector(L_WR_RDYo) after T_HOLD_OUTi when PRIMARY else (others => 'Z');
P_RD_D_RDY <= To_StdLogicVector(P_RD_D_RDYo) after T_HOLD_OUTi when PRIMARY else (others => 'Z');
L2P_RDY <= L2P_RDYo after T_HOLD_OUTi when PRIMARY else 'Z';
TX_ERROR <= TX_ERRORo after T_HOLD_OUTi when PRIMARY else 'Z';
-------------------------------------------------------------
----------------- PCIe-to-Local Dataflow ---------------------
----------------- (GN412x is an output) ---------------------
-------------------------------------------------------------
-- Transmitter Source Synchronous Clock.
--
P2L_CLKp <= P2L_CLKpo when PRIMARY else 'Z';
P2L_CLKn <= P2L_CLKno when PRIMARY else 'Z';
P2L_CLKpo <= transport not CLK0o after T_P2L_CLK_DLYi when PRIMARY else 'Z'; -- Note that P2L_CLK is effectively inverted
P2L_CLKno <= transport CLK0o after T_P2L_CLK_DLYi when PRIMARY else 'Z';
-------------------------------------------------------------
-- P2L DDR Link
--
P2L_DATA <= transport To_StdLogicVector(P2L_DATAo) after T_P2L_CLK_DLYi when PRIMARY else (others => 'Z');
P2L_DFRAME <= transport P2L_DFRAMEo after T_P2L_CLK_DLYi when PRIMARY else 'Z';
P2L_VALID <= transport P2L_VALIDo after T_P2L_CLK_DLYi when PRIMARY else 'Z';
-------------------------------------------------------------
-- P2L SDR Controls
--
P2L_RDYi <= To_X01(P2L_RDY);
P_WR_REQ <= To_StdLogicVector(P_WR_REQo) when PRIMARY else (others => 'Z');
P_WR_RDYi <= To_X01(To_StdULogicVector(P_WR_RDY));
RX_ERRORi <= To_X01(RX_ERROR);
VC_RDY <= To_StdLogicVector(VC_RDYo) when PRIMARY else (others => 'Z');
CLK <= CLK0o when PRIMARY else LCLK;
-----------------------------------------------------------------------------
-- PRIMARY MODE Internal Signals
-----------------------------------------------------------------------------
process
begin
wait until(CLK90o'event and (CLK90o = '1'));
P2L_DATAo <= Q_OUT_DATA(15 downto 0);
P2L_DFRAMEo <= Q_OUT_DFRAME;
P2L_VALIDo <= Q_OUT_VALID;
P_WR_REQo <= OUT_WR_REQ;
if(RSTOUTo = '1') then
VC_RDYo <= (others => '0');
else
VC_RDYo <= (others => '1');
end if;
wait until(CLK90o'event and (CLK90o = '0'));
P2L_DATAo <= Q_OUT_DATA(31 downto 16);
end process;
L_WR_RDYo <= (others => '1');
P_RD_D_RDYo <= (others => '1');
L2P_RDYo <= '1';
TX_ERRORo <= '0';
GPIO <= To_StdLogicVector(GPIOo);
GPIOo <= (others => 'Z');
GPIOi <= To_StdULogicVector(GPIO);
--*************************************************************************--
-- Top Level I/O signals SECONDARY MODE
--*************************************************************************--
-------------------------------------------------------------
----------------- Local-to-PCI Dataflow ---------------------
----------------- (GN412x is an output) ---------------------
-------------------------------------------------------------
-- Transmitter Source Synchronous Clock.
--
L2P_CLKp <= transport L2P_CLKpo after T_P2L_CLK_DLYi when SECONDARY else 'Z';
L2P_CLKn <= transport L2P_CLKno after T_P2L_CLK_DLYi when SECONDARY else 'Z';
-------------------------------------------------------------
-- L2P DDR Link
--
L2P_DATA <= transport To_StdLogicVector(L2P_DATAo) after T_P2L_CLK_DLYi when SECONDARY else (others => 'Z');
L2P_DFRAME <= transport L2P_DFRAMEo after T_P2L_CLK_DLYi when SECONDARY else 'Z';
L2P_VALID <= transport L2P_VALIDo after T_P2L_CLK_DLYi when SECONDARY else 'Z';
L2P_EDB <= transport L2P_EDBo after T_P2L_CLK_DLYi when SECONDARY else 'Z';
-------------------------------------------------------------
-- L2P SDR Controls
--
L_WR_RDYi <= To_X01(To_StdULogicVector(L_WR_RDY));
P_RD_D_RDYi <= To_X01(To_StdULogicVector(P_RD_D_RDY));
L2P_RDYi <= To_X01(L2P_RDY);
TX_ERRORi <= To_X01(TX_ERROR);
-------------------------------------------------------------
----------------- PCIe-to-Local Dataflow ---------------------
----------------- (GN412x is an input) ---------------------
-------------------------------------------------------------
-- Receiver Source Synchronous Clock.
--
P2L_CLKpi <= To_X01(P2L_CLKp);
P2L_CLKni <= To_X01(P2L_CLKn);
-------------------------------------------------------------
-- P2L DDR Link
--
P2L_DATAi <= To_X01(To_StdULogicVector(P2L_DATA));
P2L_DFRAMEi <= To_X01(P2L_DFRAME);
P2L_VALIDi <= To_X01(P2L_VALID);
-------------------------------------------------------------
-- P2L SDR Controls
--
P2L_RDY <= 'Z' when PRIMARY else P2L_RDYo after T_HOLD_OUTi;
P_WR_REQi <= To_X01(To_StdULogicVector(P_WR_REQ)); -- INPUT
P_WR_RDY <= (others => 'Z') when PRIMARY else To_StdLogicVector(P_WR_RDYo) after T_HOLD_OUTi; -- OUTPUT
VC_RDYi <= To_X01(To_StdULogicVector(VC_RDY)); -- INPUT
RX_ERROR <= 'Z' when PRIMARY else RX_ERRORo after T_HOLD_OUTi; -- OUTPUT
-----------------------------------------------------------------------------
-- SECONDARY MODE Internal Signals
-----------------------------------------------------------------------------
L2P_CLKpo <= CLK;
L2P_CLKno <= not CLK;
L2P_DATAo <= OUT_DATA(15 downto 0) when (L2P_CLKpo = '1') else OUT_DATA(31 downto 16);
L2P_DFRAMEo <= OUT_DFRAME;
L2P_VALIDo <= OUT_VALID;
L2P_EDBo <= '0'; -- CHANGE: Add L2P_EDB functionality
--*************************************************************************--
-- Signals Related to the OutBound Process
--*************************************************************************--
process
begin
wait until(CLK0o'event and (CLK0o = '1'));
Q_OUT_DATA <= OUT_DATA;
Q_OUT_DFRAME <= OUT_DFRAME;
Q_OUT_VALID <= OUT_VALID;
end process;
process
begin
wait until(CLK'event and (CLK = '1'));
if(PRIMARY) then
Q_OUT_WR_RDY <= P_WR_RDYi;
else
Q_OUT_WR_RDY <= L_WR_RDYi;
end if;
OUT_WR_RDY <= Q_OUT_WR_RDY;
end process;
--*************************************************************************--
-- Signals Related to the InBound Process
--*************************************************************************--
ICLK <= not L2P_CLKpi after T_LCLKi/4 when PRIMARY else not P2L_CLKpi;
-- process -- Determine LCLK period for when in secondary mode
-- variable DELTA : time;
-- begin
-- wait until(LCLKi'event and (LCLKi = '1'));
-- DELTA := NOW;
-- wait until(LCLKi'event and (LCLKi = '1'));
-- DELTA := NOW - DELTA;
-- LCLK_PERIOD <= DELTA;
-- end process;
process
begin
wait until(ICLK'event and (ICLK = '0'));
if(PRIMARY) then
IN_DATA_LOW <= L2P_DATAi;
else
IN_DATA_LOW <= P2L_DATAi;
end if;
wait until(ICLK'event and (ICLK = '1'));
if(IN_VALID = '1') then
Q_IN_DFRAME <= IN_DFRAME;
end if;
end process;
IN_DATA(31 downto 16) <= L2P_DATAi when PRIMARY else P2L_DATAi;
IN_DATA(15 downto 0) <= IN_DATA_LOW;
IN_DFRAME <= L2P_DFRAMEi when PRIMARY else P2L_DFRAMEi;
IN_VALID <= L2P_VALIDi when PRIMARY else P2L_VALIDi;
-- CHANGE: add ability to de-assert RDY
P_WR_RDYo <= P_WR_REQi;
--*************************************************************************--
-- Signals involving interaction between InBound/Outbound Processes
--*************************************************************************--
-----------------------------------------------------------------------------
-- Keep track of how many inbound reads requests are in progress
-----------------------------------------------------------------------------
process(INBOUND_READ_REQUEST_ARRAY, INBOUND_READ_REQUEST_CPL_STATE)
variable COUNT : integer;
begin
COUNT := 0;
for I in 0 to N_COMPLETION_ID-1 loop
if(INBOUND_READ_REQUEST_ARRAY(I).STATE /= INBOUND_READ_REQUEST_CPL_STATE(I)) then
COUNT := COUNT + 1;
end if;
end loop;
CURRENT_INBOUND_RD_IPR <= COUNT;
end process;
-----------------------------------------------------------------------------
-- Keep track of how many outbound reads requests are in progress
-----------------------------------------------------------------------------
process(RD_BUFFER, OUTBOUND_READ_REQUEST_CPL_STATE)
variable COUNT : integer;
begin
COUNT := 0;
for I in 0 to N_COMPLETION_ID-1 loop
if(RD_BUFFER(I).STATE /= OUTBOUND_READ_REQUEST_CPL_STATE(I)) then
COUNT := COUNT + 1;
end if;
end loop;
CURRENT_OUTBOUND_RD_IPR <= COUNT;
end process;
--#########################################################################--
--
-- OutBound State Machine
--
-- (Handles TX from the BFM: P2L for Primary and L2P for secondary)
--
--#########################################################################--
process
--file OUT_FILE : text is out "STD_OUTPUT";
file OUT_FILE : text open write_mode is "STD_OUTPUT";
variable OUTPUT_LINE : line;
variable ERR_CNT : integer;
variable L_CMD : string(1 to 80);
variable TMP_STR : string(1 to 80);
variable QCMD : string(CMD'range);
variable L_NUM : integer;
variable L_ADDR : std_ulogic_vector(63 downto 0);
variable L_BE : std_ulogic_vector( 3 downto 0);
variable L_DATA : std_ulogic_vector(31 downto 0);
variable MODULO_MASK : std_ulogic_vector(31 downto 2);
variable L_MASK : std_ulogic_vector(31 downto 0);
variable AMASK_TMP : std_ulogic_vector(31 downto 0); -- Will become 63:0
variable CHAR_PTR : integer;
variable I_TMP : integer;
variable I_TMP2 : integer;
variable I_TMP3 : integer;
variable I_TMP4 : integer;
variable I_TMP5 : integer;
variable vERR : integer;
variable B_TMP : boolean;
variable START : time;
variable N_BURST_MODULO : INT_VECTOR(0 to N_BARS-1);
variable BURST_LENGTH : INT_VECTOR(0 to N_BARS-1);
variable CURRENT_BAR : integer;
variable CURRENT_VC : integer;
variable IWAIT_RANDOM : integer;
variable IWAIT_RANDOM_N : integer;
variable RNDNUM : integer;
variable BAR_HIT : boolean_vector(1 downto 0);
variable BFM_BAR_HIT : boolean_vector(1 downto 0);
variable DATA_TMP8 : std_ulogic_vector(7 downto 0);
variable DATA_TMP32 : std_ulogic_vector(31 downto 0);
variable A_TMP : std_ulogic_vector(L_ADDR'range);
variable RD_ADDRESS : std_ulogic_vector(L_ADDR'range);
--
-- Write Buffer Management
variable WR_BUFFER_COUNT : integer;
variable WR_BUFFER_PTR : integer;
variable WR_CASE : integer;
variable RW_SEQUENTIAL : boolean;
variable WR_BUFFER : WR_BUFFER_ARRAY_TYPE;
variable WR_TYPE : std_ulogic_vector(3 downto 0);
--
-- Read Request Buffer Management
-- variable RD_BUFFER_COUNT : integer;
variable RD_BUFFER_PTR : integer;
variable CURRENT_CID : integer; -- Current read completion ID
variable NEXT_CID : integer; -- Next read completion ID
variable RD_CASE : integer;
variable RD_TYPE : std_ulogic_vector(3 downto 0);
variable RW_BLAST : boolean;
--
-- OUT variables
variable OUT_NOSNOOP : std_ulogic;
-- variable OUT_VC : std_ulogic;
variable OUT_TC : std_ulogic_vector(2 downto 0);
--
-- Read Completion Management
variable CPL_MODULO : integer; -- Modulo boundary for
variable CPL_ORDER : boolean;
variable CPL_LENGTH : integer;
variable CPL_LAST : std_ulogic;
variable CPL_CID : integer;
variable CPL_POP_PTR : INT_VECTOR(N_COMPLETION_ID-1 downto 0); -- DW pointer for each CID
variable IWAIT_RND_SEED : integer;
variable DEBUG : integer;
begin
-- Signal Initialization
OUT_DATA <= (others => 'Z');
OUT_DFRAME <= '0';
OUT_VALID <= '0';
OUT_WR_REQ <= (others => '0');
-- Variable Initialization
ERR_CNT := 0;
WR_BUFFER_COUNT := 0;
WR_BUFFER_PTR := 0;
RD_BUFFER_PTR := 0;
CURRENT_BAR := 0;
BURST_LENGTH := (others => 512);
NEXT_CID := N_COMPLETION_ID - 1;
CURRENT_CID := N_COMPLETION_ID - 1;
DEBUG := 0;
CPL_POP_PTR := (others => 0);
CPL_CID := 0;
CPL_MODULO := 64;
INBOUND_READ_REQUEST_CPL_STATE <= (others => FALSE);
loop
CMD_ACK <= '0';
wait on CMD_REQ, CLK;
--============================================================--
-- Load in a command
--============================================================--
if(CMD_REQ = '1') then
START := now;
-- if (CMD_REQ /= '1') then
-- wait until (CMD_REQ'EVENT and CMD_REQ = '1');
-- end if;
QCMD := CMD;
CMD_ACK <= '1';
if (CMD_REQ /= '0') then
wait until (CMD_REQ'EVENT and CMD_REQ = '0');
end if;
if (START /= now) then
wait until(CLK'event and (CLK = '1'));
end if;
CHAR_PTR := 1; -- Point to beginning of line
SGET_TOKEN(QCMD, CHAR_PTR, L_CMD); -- Strip off line number
SGET_TOKEN(QCMD, CHAR_PTR, L_CMD); -- Load the command
if(not MODE_PRIMARY) then
DEBUG := DEBUG + 1;
end if;
--============================================================--
-- Command Decode --
--============================================================--
--*-------------------------------------------------------------
--* wr ADDR BE DATA
--*
--* - handles the wr/wrb command
--*
--* Write Cases:
--*
--* Single Buffer Write Action
--* Write Empty Burstable Taken
--*
--* N N N FLUSH, POST : WR_CASE=WR_FLUSH_POST
--* N N Y POST : WR_CASE=WR_POST
--* N Y - POST : WR_CASE=WR_POST
--* Y N N FLUSH, POST, LAST: WR_CASE=WR_FLUSH_POST_LAST
--* Y N Y POST, FLUSH : WR_CASE=WR_POST_FLUSH
--* Y Y - POST, FLUSH : WR_CASE=WR_POST_FLUSH
--*
--*
--*-------------------------------------------------------------
if (L_CMD(1 to 2) = "wr") or (L_CMD(1 to 3) = "rd ") or (L_CMD(1 to 3) = "rdb") then
SGET_VECTOR_64(QCMD, CHAR_PTR, L_ADDR);
SGET_VECTOR(QCMD, CHAR_PTR, L_BE);
SGET_VECTOR(QCMD, CHAR_PTR, L_DATA);
if(L_CMD(1 to 2) = "rd") then
while(QCMD(CHAR_PTR) = ' ') loop -- Skip spaces
CHAR_PTR := CHAR_PTR + 1;
if(CHAR_PTR > QCMD'length) then
exit;
end if;
end loop;
if(CHAR_PTR > QCMD'length) then
L_MASK := (others => '0');
else
SGET_VECTOR(QCMD, CHAR_PTR, L_MASK);
end if;
end if;
BAR_HIT(0) := (((L_ADDR(31 downto 0) and BAR_ATTRIBUTE_ARRAY(0).MASK) = BAR_ATTRIBUTE_ARRAY(0).BASE(31 downto 0))
and (L_ADDR(63 downto 32) = BAR_ATTRIBUTE_ARRAY(0).BASE(63 downto 32)));
BAR_HIT(1) := (((L_ADDR(31 downto 0) and BAR_ATTRIBUTE_ARRAY(1).MASK) = BAR_ATTRIBUTE_ARRAY(1).BASE(31 downto 0))
and (L_ADDR(63 downto 32) = BAR_ATTRIBUTE_ARRAY(1).BASE(63 downto 32)));
BFM_BAR_HIT(0) := (((L_ADDR(31 downto 0) and BFM_BAR_ATTRIBUTE_ARRAY(0).MASK) = BFM_BAR_ATTRIBUTE_ARRAY(0).BASE(31 downto 0))
and (L_ADDR(63 downto 32) = BFM_BAR_ATTRIBUTE_ARRAY(0).BASE(63 downto 32)));
BFM_BAR_HIT(1) := (((L_ADDR(31 downto 0) and BFM_BAR_ATTRIBUTE_ARRAY(1).MASK) = BFM_BAR_ATTRIBUTE_ARRAY(1).BASE(31 downto 0))
and (L_ADDR(63 downto 32) = BFM_BAR_ATTRIBUTE_ARRAY(1).BASE(63 downto 32)));
if(BAR_HIT(1)) then
CURRENT_BAR := 1;
else
CURRENT_BAR := 0;
end if;
CURRENT_VC := to_int(BAR_ATTRIBUTE_ARRAY(CURRENT_BAR).VC);
if(BAR_HIT(0) or BAR_HIT(1)) then -- Address hits one of the external BARs
-- Burst-last
MODULO_MASK := to_vector((((2**N_BURST_MODULO(CURRENT_BAR))/4) - 1), MODULO_MASK'length);
RW_BLAST := (L_BE /= "1111")
or ((WR_BUFFER_COUNT-1) = (BURST_LENGTH(CURRENT_VC)/4))
or ((MODULO_MASK and L_ADDR(31 downto 2)) = MODULO_MASK)
or (L_CMD(3) /= 'b');
--========================================================--
-- Do Write Cycles
--========================================================--
if (L_CMD(1 to 2) = "wr") then -- Do Write Cycles
if(WR_BUFFER_COUNT > 0) then
I_TMP := To_Int(L_ADDR(31 downto 2));
-- CHANGE to do proper 64 bit address
RW_SEQUENTIAL := ((To_Int(WR_BUFFER(WR_BUFFER_PTR-1).ADDRESS(31 downto 2)) + 1) = I_TMP);
else
RW_SEQUENTIAL := FALSE;
end if;
if (L_CMD(3) = 'b') then -- See if it will go into the write cache
if (WR_BUFFER_COUNT = 0) then -- Buffer Empty
WR_CASE := WR_POST;
else -- Buffer Not Empty
if RW_SEQUENTIAL and (WR_CASE /= WR_FLUSH_POST_LAST) then
if RW_BLAST then
WR_CASE := WR_POST_FLUSH; -- POST, FLUSH
else
WR_CASE := WR_POST; -- POST
end if;
else
WR_CASE := WR_FLUSH_POST; -- FLUSH, POST
end if;
end if;
else -- Single Write
if(WR_BUFFER_COUNT = 0) then
WR_CASE := WR_POST_FLUSH;
elsif RW_SEQUENTIAL then -- Buffer not Empty and burstable
WR_CASE := WR_POST_FLUSH;
else
WR_CASE := WR_FLUSH_POST_LAST;
end if;
end if;
--========================================================--
-- Actualy generate the bus cycles
--========================================================--
------------------------------------------------------------
-- Post to the buffer
------------------------------------------------------------
if(WR_CASE = WR_POST) or (WR_CASE = WR_POST_FLUSH) then -- POST
WR_BUFFER(WR_BUFFER_PTR).ADDRESS := L_ADDR;
WR_BUFFER(WR_BUFFER_PTR).BE := L_BE;
WR_BUFFER(WR_BUFFER_PTR).DATA := L_DATA;
WR_BUFFER_COUNT := WR_BUFFER_COUNT + 1;
WR_BUFFER_PTR := WR_BUFFER_PTR + 1;
end if;
------------------------------------------------------------
-- Flush the buffer (write it out to the interface)
------------------------------------------------------------
if(WR_CASE = WR_FLUSH_POST) or (WR_CASE = WR_POST_FLUSH) or (WR_CASE = WR_FLUSH_POST_LAST) then -- FLUSH
-- CHANGE: ADD CHECK FOR PROPER RDY
loop
if(or_reduce(WR_BUFFER(0).ADDRESS(63 downto 32)) = '0') then -- 32 bit address
WR_TYPE := "0010";
elsif(PRIMARY) then -- Primary mode addresses are always 32 bit
WR_TYPE := "0010";
else -- 64 bit address
WR_TYPE := "0011";
end if;
--------------------------------------------------------
-- Header Phase
--------------------------------------------------------
OUT_DATA <= BAR_ATTRIBUTE_ARRAY(CURRENT_BAR).TC -- Bits 31:29
& BAR_ATTRIBUTE_ARRAY(CURRENT_BAR).S -- Bit 28
& WR_TYPE -- Bits 27:24
& WR_BUFFER(WR_BUFFER_COUNT-1).BE -- Bits 23:20
& WR_BUFFER(0).BE -- Bits 19:16
& "000" -- Bits 15:13
& BAR_ATTRIBUTE_ARRAY(CURRENT_BAR).VC -- Bit 12
& "00" -- Bits 11:10
& to_vector(WR_BUFFER_COUNT,10); -- Bits 9:0
OUT_VALID <= '1';
OUT_DFRAME <= '1';
OUT_WR_REQ <= BAR_ATTRIBUTE_ARRAY(CURRENT_BAR).VC & (not BAR_ATTRIBUTE_ARRAY(CURRENT_BAR).VC);
wait until(CLK'event and (CLK = '1'));
-- See if we want to insert random wait states
if(IWAIT_RANDOM > 0) then -- Insert wait states
next_random(IWAIT_RND_SEED);
if(test_random(IWAIT_RND_SEED, IWAIT_RANDOM)) then
OUT_VALID <= '0';
OUT_DATA <= (others => 'X');
next_random(IWAIT_RND_SEED);
I_TMP := range_random(IWAIT_RND_SEED, 1, IWAIT_RANDOM_N);
for J in 1 to I_TMP loop
wait until(CLK'event and (CLK = '1'));
end loop;
OUT_VALID <= '1';
end if;
end if;
--------------------------------------------------------
-- Address Phase
--------------------------------------------------------
if(WR_TYPE = "0011") then -- Do upper 32 bits of the address
OUT_DATA <= WR_BUFFER(0).ADDRESS(63 downto 32);
wait until(CLK'event and (CLK = '1'));
-- See if we want to insert random wait states
if(IWAIT_RANDOM > 0) then -- Insert wait states
next_random(IWAIT_RND_SEED);
if(test_random(IWAIT_RND_SEED, IWAIT_RANDOM)) then
OUT_VALID <= '0';
OUT_DATA <= (others => 'X');
next_random(IWAIT_RND_SEED);
I_TMP := range_random(IWAIT_RND_SEED, 1, IWAIT_RANDOM_N);
for J in 1 to I_TMP loop
wait until(CLK'event and (CLK = '1'));
end loop;
OUT_VALID <= '1';
end if;
end if;
end if;
if(PRIMARY) then
OUT_DATA <= WR_BUFFER(0).ADDRESS(31 downto 2) & '0' & to_mvl(CURRENT_BAR);
else
OUT_DATA <= WR_BUFFER(0).ADDRESS(31 downto 2) & "00";
end if;
wait until(CLK'event and (CLK = '1'));
--------------------------------------------------------
-- Data Phase
--------------------------------------------------------
for I in 0 to WR_BUFFER_COUNT-1 loop
-- See if we want to insert random wait states
if(IWAIT_RANDOM > 0) then -- Insert wait states
next_random(IWAIT_RND_SEED);
if(test_random(IWAIT_RND_SEED, IWAIT_RANDOM)) then
OUT_VALID <= '0';
OUT_DATA <= (others => 'X');
next_random(IWAIT_RND_SEED);
I_TMP := range_random(IWAIT_RND_SEED, 1, IWAIT_RANDOM_N);
for J in 1 to I_TMP loop
wait until(CLK'event and (CLK = '1'));
end loop;
OUT_VALID <= '1';
end if;
end if;
OUT_DATA <= WR_BUFFER(I).DATA;
if (I = (WR_BUFFER_COUNT-1)) then
OUT_DFRAME <= '0';
end if;
wait until(CLK'event and (CLK = '1'));
end loop;
OUT_VALID <= '0';
OUT_DFRAME <= '0';
OUT_DATA <= (others => 'Z');
OUT_WR_REQ <= (others => '0');
WR_BUFFER_COUNT := 0;
WR_BUFFER_PTR := 0;
if(WR_CASE = WR_FLUSH_POST_LAST) then -- The flush must be executed twice
WR_CASE := 99;
WR_BUFFER(WR_BUFFER_PTR).ADDRESS := L_ADDR;
WR_BUFFER(WR_BUFFER_PTR).BE := L_BE;
WR_BUFFER(WR_BUFFER_PTR).DATA := L_DATA;
WR_BUFFER_COUNT := WR_BUFFER_COUNT + 1;
WR_BUFFER_PTR := WR_BUFFER_PTR + 1;
else
exit;
end if;
end loop;
end if;
------------------------------------------------------------
-- Post to the buffer
------------------------------------------------------------
if(WR_CASE = WR_FLUSH_POST) then --POST
WR_BUFFER(WR_BUFFER_PTR).ADDRESS := L_ADDR;
WR_BUFFER(WR_BUFFER_PTR).BE := L_BE;
WR_BUFFER(WR_BUFFER_PTR).DATA := L_DATA;
WR_BUFFER_COUNT := WR_BUFFER_COUNT + 1;
WR_BUFFER_PTR := WR_BUFFER_PTR + 1;
end if;
--========================================================--
-- Do Read Request Cycles
--========================================================--
--*-------------------------------------------------------------
--* rd ADDR BE DATA MASK
--*
--* - handles the rd/rdb command
--*
--* Read Cases:
--*
--* rdb Buffer Read Action
--* command Empty Burstable Taken
--*
--* N Y - POST, IPR : RD_CASE=RD_POST_IPR*
--* N N Y POST, IPR : RD_CASE=RD_POST_IPR*
--* N N N IPR, POST_LAST : RD_CASE=RD_IPR_POST_LAST*
--* Y Y - POST : RD_CASE=RD_POST*
--* Y N Y POST : RD_CASE=RD_POST*
--* Y N N IPR, POST : RD_CASE=RD_IPR_POST*
--*
--* Note: POST means store the given read into the current CID buffer
--* POST_LAST store the given read into the current CID buffer and mark as LAST (cannot be combined)
--* IPR means set the current buffer state to "In Progress" and load the next CID as current CID
--* NEXT_CID means allocate the next CID and set as current CID
--*
--*-------------------------------------------------------------
else -- do read cycles
write(OUTPUT_LINE, string'("-- rd("));
write_hex_vector(OUTPUT_LINE, L_ADDR(63 downto 32));
write_hex_vector(OUTPUT_LINE, L_ADDR(31 downto 0));
write(OUTPUT_LINE, string'(", "));
write_hex_vector(OUTPUT_LINE, L_BE);
write(OUTPUT_LINE, string'(", "));
write_hex_vector(OUTPUT_LINE, L_DATA);
write(OUTPUT_LINE, string'(", "));
write_hex_vector(OUTPUT_LINE, L_MASK);
write(OUTPUT_LINE, string'(")"));
writeline(OUT_FILE, OUTPUT_LINE);
if(RD_BUFFER_PTR > 0) then -- current buffer has data
I_TMP := To_Int(L_ADDR(31 downto 2));
RW_SEQUENTIAL := (To_Int(RD_ADDRESS(31 downto 2)) = I_TMP);
else
RD_ADDRESS := L_ADDR;
RW_SEQUENTIAL := FALSE;
end if;
if (L_CMD(3) = 'b') then -- command is for a burst
if (RD_BUFFER_PTR = 0) then -- Buffer Empty
RD_CASE := RD_POST;
else -- Buffer Not Empty
if(RW_SEQUENTIAL and not RW_BLAST) then
RD_CASE := RD_POST;
else
RD_CASE := RD_IPR_POST;
end if;
end if;
else -- Single Write
if(RD_BUFFER_PTR = 0) then -- Buffer Empty
RD_CASE := RD_POST_IPR;
elsif RW_SEQUENTIAL and (RD_CASE /= RD_IPR_POST_LAST) then -- Buffer not Empty and burstable
RD_CASE := RD_POST_IPR;
else
RD_CASE := RD_IPR_POST_LAST;
end if;
end if;
------------------------------------------------------------
-- Stall until it is safe to post another buffer
------------------------------------------------------------
if(RD_BUFFER_PTR = 0) then
while(CURRENT_OUTBOUND_RD_IPR >= OUTBOUND_RD_OUTSTANDING) loop -- we must stall
wait until(CLK'event and (CLK = '1'));
end loop;
-- Allocate a new CID
NEXT_CID := CURRENT_CID;
for I in 0 to N_COMPLETION_ID-1 loop
NEXT_CID := NEXT_CID + 1;
if(NEXT_CID > (N_COMPLETION_ID-1)) then
NEXT_CID := 0;
end if;
if(RD_BUFFER(NEXT_CID).STATE = OUTBOUND_READ_REQUEST_CPL_STATE(NEXT_CID)) then
exit;
end if;
end loop;
CURRENT_CID := NEXT_CID;
end if;
------------------------------------------------------------
-- Post to the buffer
------------------------------------------------------------
if(RD_CASE = RD_POST_IPR) or (RD_CASE = RD_POST) then -- POST
if(RD_BUFFER_PTR = 0) then -- buffer empty
RD_BUFFER(CURRENT_CID).ADDRESS <= L_ADDR;
RD_BUFFER(CURRENT_CID).BAR_HIT <= to_mvl(BAR_HIT(1)) & to_mvl(BAR_HIT(1));
RD_BUFFER(CURRENT_CID).FBE <= L_BE;
end if;
RD_BUFFER(CURRENT_CID).LBE <= L_BE;
RD_BUFFER(CURRENT_CID).DATA(RD_BUFFER_PTR) <= L_DATA;
RD_BUFFER(CURRENT_CID).MASK(RD_BUFFER_PTR) <= L_MASK;
RD_BUFFER_PTR := RD_BUFFER_PTR + 1;
RD_ADDRESS(RD_ADDRESS'high downto 2) := L_ADDR(RD_ADDRESS'high downto 2) + '1';
wait on RD_BUFFER;
end if;
------------------------------------------------------------
-- Flush the read buffer (send request packet and set the buffer state to in-progress)
------------------------------------------------------------
if(RD_CASE = RD_POST_IPR) or (RD_CASE = RD_IPR_POST_LAST) or (RD_CASE = RD_IPR_POST) then -- IPR
RD_BUFFER(CURRENT_CID).STATE <= not RD_BUFFER(CURRENT_CID).STATE;
--------------------------------------------------------
-- Do the Read Request
--------------------------------------------------------
if(or_reduce(RD_BUFFER(CURRENT_CID).ADDRESS(63 downto 32)) = '0') then -- 32 bit address
RD_TYPE := "0000";
elsif(PRIMARY) then -- Primary mode addresses are always 32 bit
RD_TYPE := "0000";
else -- 64 bit address
RD_TYPE := "0001";
end if;
--------------------------------------------------------
-- Header Phase
--------------------------------------------------------
OUT_DATA <= BAR_ATTRIBUTE_ARRAY(CURRENT_BAR).TC -- Bits 31:29
& BAR_ATTRIBUTE_ARRAY(CURRENT_BAR).S -- Bit 28
& RD_TYPE -- Bits 27:24
& RD_BUFFER(CURRENT_CID).LBE -- Bits 23:20
& RD_BUFFER(CURRENT_CID).FBE -- Bits 19:16
& "000" -- Bits 15:13
& BAR_ATTRIBUTE_ARRAY(CURRENT_BAR).VC -- Bit 12
& to_vector(CURRENT_CID,2) -- Bits 11:10
& to_vector(RD_BUFFER_PTR,10); -- Bits 9:0
OUT_VALID <= '1';
OUT_DFRAME <= '1';
wait until(CLK'event and (CLK = '1'));
-- See if we want to insert random wait states
if(IWAIT_RANDOM > 0) then -- Insert wait states
next_random(IWAIT_RND_SEED);
if(test_random(IWAIT_RND_SEED, IWAIT_RANDOM)) then
OUT_VALID <= '0';
OUT_DATA <= (others => 'X');
next_random(IWAIT_RND_SEED);
I_TMP := range_random(IWAIT_RND_SEED, 1, IWAIT_RANDOM_N);
for J in 1 to I_TMP loop
wait until(CLK'event and (CLK = '1'));
end loop;
OUT_VALID <= '1';
end if;
end if;
--------------------------------------------------------
-- Address Phase
--------------------------------------------------------
if(RD_TYPE = "0001") then -- Do upper 32 bits of the address
OUT_DATA <= RD_BUFFER(CURRENT_CID).ADDRESS(63 downto 32);
wait until(CLK'event and (CLK = '1'));
-- See if we want to insert random wait states
if(IWAIT_RANDOM > 0) then -- Insert wait states
next_random(IWAIT_RND_SEED);
if(test_random(IWAIT_RND_SEED, IWAIT_RANDOM)) then
OUT_VALID <= '0';
OUT_DATA <= (others => 'X');
next_random(IWAIT_RND_SEED);
I_TMP := range_random(IWAIT_RND_SEED, 1, IWAIT_RANDOM_N);
for J in 1 to I_TMP loop
wait until(CLK'event and (CLK = '1'));
end loop;
OUT_VALID <= '1';
end if;
end if;
end if;
if(PRIMARY) then
OUT_DATA <= RD_BUFFER(CURRENT_CID).ADDRESS(31 downto 2) & '0' & to_mvl(CURRENT_BAR);
else
OUT_DATA <= RD_BUFFER(CURRENT_CID).ADDRESS(31 downto 2) & "00";
end if;
OUT_DFRAME <= '0';
wait until(CLK'event and (CLK = '1'));
OUT_VALID <= '0';
OUT_DATA <= (others => 'Z');
RD_BUFFER_PTR := 0;
end if;
------------------------------------------------------------
-- Post to the buffer
------------------------------------------------------------
if(RD_CASE = RD_IPR_POST_LAST) or (RD_CASE = RD_IPR_POST) then -- POST
if(RD_BUFFER_PTR = 0) then -- buffer empty
RD_BUFFER(CURRENT_CID).ADDRESS <= L_ADDR;
RD_BUFFER(CURRENT_CID).FBE <= L_BE;
end if;
RD_BUFFER(CURRENT_CID).LBE <= L_BE;
RD_BUFFER(CURRENT_CID).DATA(RD_BUFFER_PTR) <= L_DATA;
RD_BUFFER(CURRENT_CID).MASK(RD_BUFFER_PTR) <= L_MASK;
RD_BUFFER_PTR := RD_BUFFER_PTR + 1;
RD_ADDRESS(RD_ADDRESS'high downto 2) := L_ADDR(RD_ADDRESS'high downto 2) + '1';
end if;
end if;
elsif(BFM_BAR_HIT(0) or BFM_BAR_HIT(1)) then -- Address hits one of the internal BFM RAM BARs
------------------------------------------------------------
-- Write data to the local BFM memory
------------------------------------------------------------
A_TMP := L_ADDR(L_ADDR'high downto 2) & "00";
if (L_CMD(1 to 2) = "wr") then
for i in 0 to L_BE'high loop
if (L_BE(i) = '1') then
DATA_TMP8 := L_DATA(8*i+7 downto 8*i);
--write(OUTPUT_LINE, string'("-- Mem_Write("));
--write_hex_vector(OUTPUT_LINE, A_TMP(29 downto 0));
--write(OUTPUT_LINE, string'(", "));
--write_hex_vector(OUTPUT_LINE, DATA_TMP8);
--write(OUTPUT_LINE, string'(")"));
--writeline(OUT_FILE, OUTPUT_LINE);
RAM_WR0 <= TRUE;
RAM_ADDR0 <= A_TMP(N_RAM_MAX-1 downto 0);
RAM_WR_DATA0 <= DATA_TMP8;
RAM_REQ0 <= not RAM_REQ0;
wait on RAM_ACK0;
end if;
A_TMP := A_TMP + '1';
end loop;
------------------------------------------------------------
-- Read data from the local BFM memory
------------------------------------------------------------
else
for i in 0 to L_BE'high loop
if (L_BE(i) = '1') then
RAM_WR0 <= FALSE;
RAM_ADDR0 <= A_TMP(N_RAM_MAX-1 downto 0);
RAM_REQ0 <= not RAM_REQ0;
wait on RAM_ACK0;
DATA_TMP8 := RAM_RD_DATA0;
--write(OUTPUT_LINE, string'("-- Mem_Read("));
--write_hex_vector(OUTPUT_LINE, A_TMP(29 downto 0));
--write(OUTPUT_LINE, string'(", "));
--write_hex_vector(OUTPUT_LINE, DATA_TMP8);
--write(OUTPUT_LINE, string'(")"));
--writeline(OUT_FILE, OUTPUT_LINE);
DATA_TMP32(8*i+7 downto 8*i) := DATA_TMP8;
A_TMP := A_TMP + '1';
end if;
end loop;
read_cmp(OUTPUT_LINE, (INSTANCE_LABEL & "BFM Local Readback "), DATA_TMP32, L_DATA, L_MASK, vERR);
if(vERR = 1) then writeline(OUT_FILE, OUTPUT_LINE); end if;
end if;
else
write(OUTPUT_LINE, "-- ERROR: " & INSTANCE_LABEL);
write(OUTPUT_LINE, NOW, LEFT, 0, ps);
if (L_CMD(1 to 2) = "wr") then
write(OUTPUT_LINE, string'(" The write command didn't match any BAR address:"));
write_hex_vector(OUTPUT_LINE, L_ADDR);
else
write(OUTPUT_LINE, string'(" The read command didn't match any BAR address:"));
write_hex_vector(OUTPUT_LINE, L_ADDR);
end if;
writeline(OUT_FILE, OUTPUT_LINE);
end if;
--*-------------------------------------------------------------
--* init: Set the model to all the default values
--*-------------------------------------------------------------
elsif (L_CMD(1 to 4) = "init") then
GENERATE_X <= FALSE;
EXPECT_ERROR <= FALSE;
T_LCLKi <= T_LCLK;
T_P2L_CLK_DLYi <= T_P2L_CLK_DLY;
T_HOLD_OUTi <= T_HOLD_OUT;
OUTBOUND_RD_OUTSTANDING <= 1;
RESPONSE_DELAY <= 0;
BURST_LENGTH := (others => 512);
N_BURST_MODULO := (others => log2(512));
CURRENT_VC := 0;
CPL_MODULO := 64;
IWAIT_RANDOM := 0;
IWAIT_RND_SEED := 5000;
--CURRENT_BAR := 0;
--*-------------------------------------------------------------
--* reset N: Drive RSTOUT18n, RSTOUT33n for N clocks
--*-------------------------------------------------------------
elsif (L_CMD(1 to 5) = "reset") then
SGET_INT(QCMD, CHAR_PTR, I_TMP);
RSTOUTo <= '1';
if(CMD_CLOCK_EN) then
for i in 1 to I_TMP loop
wait until (CLK'event and CLK = '1');
end loop;
else
wait for I_TMP * T_LCLKi;
end if;
RSTOUTo <= '0';
--*-------------------------------------------------------------
--* expect_error on|off|true|false: Expect read error
--*
--* When true|on read results will expect a completor error
--* and an ERROR will be reported if it is not
--*
--* When false|off read results will expect the error bit to be
--* off and an ERROR will be reported if it is on
--*-------------------------------------------------------------
elsif (L_CMD(1 to 12) = "expect_error") then
SGET_BOOLEAN(QCMD, CHAR_PTR, B_TMP);
EXPECT_ERROR <= B_TMP;
--*-------------------------------------------------------------
--* generate_x on|off|true|false: Generate X when signals change
--*
--* When true|on output signals will go X after T_HOLD_OUT from
--* clock when the signal transitions. It will return to a valid
--* logic level after T_CO.
--*
--* CLK ______~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--* |
--* |<-----------T_CO--------->|
--* | |
--* |<--T_HOLD_OUT-->| |
--* | |
--* SIG ________________________XXXXXXXXXX~~~~~~~
--*
--*-------------------------------------------------------------
elsif (L_CMD(1 to 10) = "generate_x") then
SGET_BOOLEAN(QCMD, CHAR_PTR, B_TMP);
GENERATE_X <= B_TMP;
--*-------------------------------------------------------------
--* clk N: set clock period to N ps
--*-------------------------------------------------------------
elsif (L_CMD(1 to 4) = "lclk") then
SGET_INT(QCMD, CHAR_PTR, I_TMP);
T_LCLKi <= I_TMP * 1 ps;
--*-------------------------------------------------------------
--* iwait_random P N: Initiator random wait state insertion.
--*-------------------------------------------------------------
elsif (L_CMD(1 to 12) = "iwait_random") then
SGET_INT(QCMD, CHAR_PTR, I_TMP);
SGET_INT(QCMD, CHAR_PTR, I_TMP2);
if(I_TMP < 0) or (I_TMP > 100) then
assert false report "WARNING: Specified iwait_random probability is out of the acceptable range of 0-100: setting to 0";
I_TMP := 0;
end if;
if(I_TMP2 < 0) or (I_TMP2 > 99) then
assert false report "WARNING: Specified iwait_random max wait is out of the acceptable range of 1-32: setting to 1";
I_TMP2 := 1;
end if;
IWAIT_RANDOM := I_TMP;
IWAIT_RANDOM_N := I_TMP2;
--*-------------------------------------------------------------
--* bfm_bar BAR ADDR: Used to allocate local memory inside
--* the BFM for an external master to R/W.
--*-------------------------------------------------------------
elsif (L_CMD(1 to 7) = "bfm_bar") then
SGET_INT(QCMD, CHAR_PTR, I_TMP); -- BAR
SGET_VECTOR_64(QCMD, CHAR_PTR, L_ADDR); -- ADDR
SGET_INT(QCMD, CHAR_PTR, I_TMP2); -- SIZE
-- Check BAR
if(I_TMP /= 0) then
I_TMP := 1;
end if;
-- Check SIZE
if(I_TMP2 /= (2**log2(I_TMP2))) then
assert false report "WARNING: Specified SIZE is not a power of 2, rounding down.";
I_TMP2 := (2**log2(I_TMP2));
end if;
I_TMP2 := I_TMP2 - 1;
AMASK_TMP := to_vector(I_TMP2, AMASK_TMP'length);
AMASK_TMP := not AMASK_TMP;
BFM_BAR_ATTRIBUTE_ARRAY(I_TMP).MASK <= AMASK_TMP;
-- Check BASE
if(L_ADDR(AMASK_TMP'range) /= (L_ADDR(AMASK_TMP'range) and AMASK_TMP)) then
assert false report "WARNING: Specified Base Address will be alligned to match the BAR size.";
L_ADDR(AMASK_TMP'range) := (L_ADDR(AMASK_TMP'range) and AMASK_TMP);
end if;
BFM_BAR_ATTRIBUTE_ARRAY(I_TMP).BASE <= L_ADDR;
-- Make sure that BFM_BAR_ATTRIBUTE_ARRAY is updated before continuing
wait until (BFM_BAR_ATTRIBUTE_ARRAY'EVENT);
write(OUTPUT_LINE, "-- " & INSTANCE_LABEL);
write(OUTPUT_LINE, string'("BFM BAR set to: BAR="));
write(OUTPUT_LINE, I_TMP);
write(OUTPUT_LINE, string'(", BASE=0x"));
write_hex_vector(OUTPUT_LINE, BFM_BAR_ATTRIBUTE_ARRAY(I_TMP).BASE);
write(OUTPUT_LINE, string'(", MASK=0x"));
write_hex_vector(OUTPUT_LINE, BFM_BAR_ATTRIBUTE_ARRAY(I_TMP).MASK);
writeline(OUT_FILE, OUTPUT_LINE);
--*-------------------------------------------------------------
--* bar BAR ADDR SIZE VC TC: Sets up one of the base address
--* registers. All read/write transactions
--* that match a BAR will be routed external.
--*-------------------------------------------------------------
elsif (L_CMD(1 to 3) = "bar") then
SGET_INT(QCMD, CHAR_PTR, I_TMP); -- BAR
SGET_VECTOR_64(QCMD, CHAR_PTR, L_ADDR); -- ADDR
SGET_INT(QCMD, CHAR_PTR, I_TMP2); -- SIZE
SGET_INT(QCMD, CHAR_PTR, I_TMP3); -- VC
SGET_INT(QCMD, CHAR_PTR, I_TMP4); -- TC
SGET_INT(QCMD, CHAR_PTR, I_TMP5); -- S
-- Check BAR
if(I_TMP /= 0) then
I_TMP := 1;
end if;
-- Check SIZE
if(I_TMP2 /= (2**log2(I_TMP2))) then
assert false report "WARNING: Specified SIZE is not a power of 2, rounding down.";
I_TMP2 := (2**log2(I_TMP2));
end if;
I_TMP2 := I_TMP2 - 1;
AMASK_TMP := to_vector(I_TMP2, AMASK_TMP'length);
AMASK_TMP := not AMASK_TMP;
BAR_ATTRIBUTE_ARRAY(I_TMP).MASK <= AMASK_TMP;
-- Check BASE
if(L_ADDR(AMASK_TMP'range) /= (L_ADDR(AMASK_TMP'range) and AMASK_TMP)) then
assert false report "WARNING: Specified Base Address will be alligned to match the BAR size.";
L_ADDR(AMASK_TMP'range) := (L_ADDR(AMASK_TMP'range) and AMASK_TMP);
end if;
BAR_ATTRIBUTE_ARRAY(I_TMP).BASE <= L_ADDR;
-- Check VC
if(I_TMP3 < 0) or (I_TMP3 > 1) then
assert false report "WARNING: Specified VC is out of range, will be set to 0.";
I_TMP3 := 0;
end if;
if(I_TMP3 /= 0) then
BAR_ATTRIBUTE_ARRAY(I_TMP).VC <= '1';
else
BAR_ATTRIBUTE_ARRAY(I_TMP).VC <= '0';
end if;
-- Check Trafic Class
if(I_TMP4 < 0) or (I_TMP4 > 7) then
assert false report "WARNING: Specified TC is out of range, will be set to 0.";
I_TMP4 := 0;
end if;
BAR_ATTRIBUTE_ARRAY(I_TMP).TC <= to_vector(I_TMP4, 3);
-- Check Trafic Class
if(I_TMP5 < 0) or (I_TMP5 > 1) then
assert false report "WARNING: Specified NoSnoop is out of range, will be set to 0.";
I_TMP5 := 0;
end if;
BAR_ATTRIBUTE_ARRAY(I_TMP).S <= to_mvl(I_TMP5);
-- Make sure that BAR_ATTRIBUTE_ARRAY is updated before continuing
wait until (BAR_ATTRIBUTE_ARRAY'EVENT);
write(OUTPUT_LINE, "-- " & INSTANCE_LABEL);
write(OUTPUT_LINE, string'("BAR set to: BAR="));
write(OUTPUT_LINE, I_TMP);
write(OUTPUT_LINE, string'(", BASE=0x"));
write_hex_vector(OUTPUT_LINE, BAR_ATTRIBUTE_ARRAY(I_TMP).BASE);
write(OUTPUT_LINE, string'(", MASK=0x"));
write_hex_vector(OUTPUT_LINE, BAR_ATTRIBUTE_ARRAY(I_TMP).MASK);
write(OUTPUT_LINE, string'(", VC="));
write(OUTPUT_LINE, To_bit(BAR_ATTRIBUTE_ARRAY(I_TMP).VC));
write(OUTPUT_LINE, string'(", TC=0x"));
write_hex_vector(OUTPUT_LINE, BAR_ATTRIBUTE_ARRAY(I_TMP).TC);
write(OUTPUT_LINE, string'(", S="));
write(OUTPUT_LINE, To_bit(BAR_ATTRIBUTE_ARRAY(I_TMP).S));
writeline(OUT_FILE, OUTPUT_LINE);
--*-------------------------------------------------------------
--* rd_outstanding_out N: This determines how many outstanding
--* reads the BFM will generate before stalling.
--*-------------------------------------------------------------
elsif (L_CMD(1 to 18) = "rd_outstanding_out") then
SGET_INT(QCMD, CHAR_PTR, I_TMP); -- N
if(I_TMP < 1) or (I_TMP > 4) then
assert false report "WARNING: Specified reads outstanding is out of the acceptable range of 1-4: setting to 1";
I_TMP := 1;
end if;
OUTBOUND_RD_OUTSTANDING <= I_TMP;
write(OUTPUT_LINE, "-- " & INSTANCE_LABEL);
write(OUTPUT_LINE, string'("rd_outstanding_out set to: "));
write(OUTPUT_LINE, I_TMP);
writeline(OUT_FILE, OUTPUT_LINE);
--*-------------------------------------------------------------
--* cpl_modulo N: Sets the burst modulo boundary that
--* read completion packets will get truncated to.
--*-------------------------------------------------------------
elsif (L_CMD(1 to 10) = "cpl_modulo") then
SGET_INT(QCMD, CHAR_PTR, I_TMP); -- N
if(I_TMP < 8) or (I_TMP > 512) then
assert false report "WARNING: Specified completion modulo is out of the acceptable range of 8-512 bytes: setting to 512 bytes";
I_TMP := 512;
end if;
if((2**log2(I_TMP)) /= I_TMP) then
I_TMP := (2**log2(I_TMP));
write(OUTPUT_LINE, string'("-- WARNING: Specified completion modulo is not a power of 2: setting to "));
write(OUTPUT_LINE, I_TMP);
write(OUTPUT_LINE, string'(" bytes"));
writeline(OUT_FILE, OUTPUT_LINE);
end if;
CPL_MODULO := I_TMP;
write(OUTPUT_LINE, "-- " & INSTANCE_LABEL & "cpl_modulo set to: ");
write(OUTPUT_LINE, I_TMP);
write(OUTPUT_LINE, string'(" bytes"));
writeline(OUT_FILE, OUTPUT_LINE);
--*-------------------------------------------------------------
--* cpl_order N: Completion order: Determines the order of
--* completion packets put out by the BFM.
--*-------------------------------------------------------------
elsif (L_CMD(1 to 9) = "cpl_order") then
SGET_BOOLEAN(QCMD, CHAR_PTR, B_TMP); -- N
CPL_ORDER := B_TMP;
write(OUTPUT_LINE, "-- " & INSTANCE_LABEL);
write(OUTPUT_LINE, string'("cpl_modulo set to: "));
write(OUTPUT_LINE, I_TMP);
write(OUTPUT_LINE, string'(" bytes"));
writeline(OUT_FILE, OUTPUT_LINE);
--*-------------------------------------------------------------
--* burst_modulo N BAR: Sets the burst modulo boundary that
--* read/write packets will get truncated to.
--*-------------------------------------------------------------
elsif (L_CMD(1 to 12) = "burst_modulo") then
SGET_INT(QCMD, CHAR_PTR, I_TMP); -- N
SGET_INT(QCMD, CHAR_PTR, I_TMP2); -- BAR
if(I_TMP2 < 0) or (I_TMP2 > (N_BARS-1)) then
assert false report "WARNING: Specified Virtual Channel is out of range, defaulting to 1";
I_TMP2 := 1;
else
N_BURST_MODULO(I_TMP2) := log2(I_TMP);
end if;
if(I_TMP < 8) or (I_TMP > 4096) then
assert false report "WARNING: Specified burst modulo is out of the acceptable range of 8-4096 bytes: setting to 512 bytes";
I_TMP := 512;
end if;
if((2**log2(I_TMP)) /= I_TMP) then
I_TMP := (2**log2(I_TMP));
write(OUTPUT_LINE, string'("-- WARNING: Specified burst modulo is not a power of 2: setting to "));
write(OUTPUT_LINE, I_TMP);
write(OUTPUT_LINE, string'(" bytes"));
writeline(OUT_FILE, OUTPUT_LINE);
end if;
N_BURST_MODULO(I_TMP2) := log2(I_TMP);
write(OUTPUT_LINE, "-- " & INSTANCE_LABEL);
write(OUTPUT_LINE, string'("burst_modulo set to: ") & to_str(I_TMP) & " bytes for BAR" & to_str(I_TMP2));
writeline(OUT_FILE, OUTPUT_LINE);
--*-------------------------------------------------------------
--* burst_length N BAR: Sets the burst length that
--* read/write packets will get truncated to.
--*-------------------------------------------------------------
elsif (L_CMD(1 to 12) = "burst_length") then
SGET_INT(QCMD, CHAR_PTR, I_TMP); -- N
SGET_INT(QCMD, CHAR_PTR, I_TMP2); -- BAR
if(I_TMP2 < 0) or (I_TMP2 > (N_BARS-1)) then
assert false report "WARNING: Specified Virtual Channel is out of range, defaulting to 1";
I_TMP2 := 1;
end if;
if(I_TMP < 0) or (I_TMP > 4096) then
assert false report "WARNING: Specified burst length is out of range: setting to 512 bytes";
BURST_LENGTH(I_TMP2) := 512;
else
BURST_LENGTH(I_TMP2) := I_TMP;
end if;
write(OUTPUT_LINE, "-- " & INSTANCE_LABEL);
write(OUTPUT_LINE, string'("burst_length set to: ") & to_str(BURST_LENGTH(I_TMP2)) & " for BAR" & to_str(I_TMP2));
writeline(OUT_FILE, OUTPUT_LINE);
--*-------------------------------------------------------------
--* wait N: Idle for N clocks
--*-------------------------------------------------------------
elsif (L_CMD(1 to 4) = "wait") then
SGET_INT(QCMD, CHAR_PTR, I_TMP);
for i in 1 to I_TMP loop
wait until (CLK'event and (CLK = '1'));
end loop;
--*-------------------------------------------------------------
--* gpio_wait N P MASK Wait for N local bus clock intervals for GPIO to reach a defined state.
--*-------------------------------------------------------------
elsif (L_CMD(1 to 9) = "gpio_wait") then
SGET_INT(QCMD, CHAR_PTR, I_TMP);
SGET_VECTOR(QCMD, CHAR_PTR, L_DATA);
SGET_VECTOR(QCMD, CHAR_PTR, L_MASK);
for i in 1 to I_TMP loop
wait until (CLK'event and (CLK = '1'));
I_TMP2 := i;
-- if(and_reduce(((GPIOi and L_MASK(GPIO'range)) xnor (L_DATA(GPIO'range) and L_MASK(GPIO'range)))) = 0) then
if(((GPIOi and L_MASK(GPIO'range)) = (L_DATA(GPIO'range) and L_MASK(GPIO'range)))) then
exit;
end if;
end loop;
if(I_TMP2 = I_TMP) then -- command timed out
write(OUTPUT_LINE, "-- " & INSTANCE_LABEL & string'("ERROR: gpio_wait command timed out"));
writeline(OUT_FILE, OUTPUT_LINE);
end if;
--*-------------------------------------------------------------
--* flush N: Idle for N clocks
--*-------------------------------------------------------------
elsif (L_CMD(1 to 5) = "flush") then
SGET_INT(QCMD, CHAR_PTR, I_TMP);
for i in 1 to I_TMP loop
if(CURRENT_OUTBOUND_RD_IPR = 0) then
exit;
end if;
wait until (CLK'event and (CLK = '1'));
end loop;
if(CURRENT_OUTBOUND_RD_IPR /= 0) then
write(OUTPUT_LINE, "-- " & INSTANCE_LABEL);
write(OUTPUT_LINE, string'("ERROR: flush command timed out"));
writeline(OUT_FILE, OUTPUT_LINE);
end if;
elsif (L_CMD(1 to 2) /= "--") and (L_CMD(1 to 2) /= "//") and (L_CMD(1) /= ' ') then
assert false report "Unrecognized command";
end if;
end if;
--============================================================--
-- Send out a completion packet
--============================================================--
if(CURRENT_INBOUND_RD_IPR /= 0) then -- Send out a read completion
------------------------------------------------------------
-- Make sure we are alligned to the clock
------------------------------------------------------------
if not(CLK'event and (CLK = '1')) then
wait until (CLK'event and (CLK = '1'));
end if;
------------------------------------------------------------
-- Select the next CID to service (does a round robin and supports OoO)
------------------------------------------------------------
for I in 0 to N_COMPLETION_ID-1 loop
-- Point to the next possible Completion ID
if(CPL_ORDER or (I /= 0)) then
CPL_CID := CPL_CID + 1;
end if;
if(CPL_CID >= N_COMPLETION_ID) then
CPL_CID := 0;
end if;
if(INBOUND_READ_REQUEST_ARRAY(CPL_CID).STATE /= INBOUND_READ_REQUEST_CPL_STATE(CPL_CID)) then
exit;
end if;
end loop;
------------------------------------------------------------
-- Header Phase
------------------------------------------------------------
if(INBOUND_READ_REQUEST_ARRAY(CPL_CID).LENGTH = 0) then
RD_TYPE := "0100";
else
RD_TYPE := "0101";
end if;
-- Start Address = INBOUND_READ_REQUEST_ARRAY(CPL_CID).ADDRESS(31:2)
-- Start DW Address
A_TMP := (others => '0');
A_TMP(RAM_ADDR0'high) := INBOUND_READ_REQUEST_ARRAY(CPL_CID).BAR_HIT(1);
A_TMP(RAM_ADDR0'high-1 downto 2) := INBOUND_READ_REQUEST_ARRAY(CPL_CID).ADDRESS(RAM_ADDR0'high-1 downto 2);
I_TMP := to_int(A_TMP(RAM_ADDR0'high downto 2)); -- This is the DW base address relative to the BFM internal RAM
I_TMP := I_TMP + CPL_POP_PTR(CPL_CID); -- This is the DW base address + offset
-- I_TMP := to_int(INBOUND_READ_REQUEST_ARRAY(CPL_CID).BAR_HIT(1)
-- & INBOUND_READ_REQUEST_ARRAY(CPL_CID).ADDRESS(RAM_ADDR0'high-1 downto 2))
-- + CPL_POP_PTR(CPL_CID);
A_TMP := (others => '0');
A_TMP(RAM_ADDR0'range) := to_vector(I_TMP, RAM_ADDR0'length-2) & "00";
CPL_LENGTH := (CPL_MODULO/4) - (I_TMP mod (CPL_MODULO/4)); -- This determines the modulo alligned length
CPL_LENGTH := minimum(INBOUND_READ_REQUEST_ARRAY(CPL_CID).LENGTH - CPL_POP_PTR(CPL_CID), CPL_LENGTH);
CPL_LAST := to_mvl((CPL_POP_PTR(CPL_CID) + CPL_LENGTH) >= INBOUND_READ_REQUEST_ARRAY(CPL_CID).LENGTH);
OUT_DATA <= INBOUND_READ_REQUEST_ARRAY(CPL_CID).TC -- Bits 31:29 (TC)
& '0' -- Bit 28 (unused)
& RD_TYPE -- Bits 27:24 (TYPE)
& "000000" -- Bits 23:18 (unused)
& "00" -- Bits 17:16 (STAT) -- CHANGE to add exception cases
& CPL_LAST -- Bits 15 (L)
& "00" -- Bits 14:13 (unused)
& BAR_ATTRIBUTE_ARRAY(CURRENT_BAR).VC -- Bit 12
& to_vector(CPL_CID, 2) -- Bits 11:10
& to_vector(CPL_LENGTH,10); -- Bits 9:0
OUT_VALID <= '1';
OUT_DFRAME <= '1';
wait until(CLK'event and (CLK = '1'));
-- See if we want to insert random wait states
if(IWAIT_RANDOM > 0) then -- Insert wait states
next_random(IWAIT_RND_SEED);
if(test_random(IWAIT_RND_SEED, IWAIT_RANDOM)) then
OUT_VALID <= '0';
OUT_DATA <= (others => 'X');
next_random(IWAIT_RND_SEED);
I_TMP := range_random(IWAIT_RND_SEED, 1, IWAIT_RANDOM_N);
for J in 1 to I_TMP loop
wait until(CLK'event and (CLK = '1'));
end loop;
OUT_VALID <= '1';
end if;
end if;
------------------------------------------------------------
-- Data Phase
------------------------------------------------------------
if(INBOUND_READ_REQUEST_ARRAY(CPL_CID).LENGTH = 0) then -- no data to return
OUT_DATA <= (others => 'X');
wait until(CLK'event and (CLK = '1'));
else -- send back data
RAM_WR0 <= FALSE;
for I in 1 to CPL_LENGTH loop
for J in 0 to 3 loop -- Do all 4 bytes of the read
RAM_ADDR0 <= A_TMP(RAM_ADDR0'range);
RAM_REQ0 <= not RAM_REQ0;
wait on RAM_ACK0;
OUT_DATA(J*8+7 downto J*8) <= RAM_RD_DATA0;
A_TMP := A_TMP + '1';
end loop;
if(I = CPL_LENGTH) then
OUT_DFRAME <= '0';
end if;
wait until(CLK'event and (CLK = '1'));
CPL_POP_PTR(CPL_CID) := CPL_POP_PTR(CPL_CID) + 1;
-- See if we want to insert random wait states
if(IWAIT_RANDOM > 0) then -- Insert wait states
next_random(IWAIT_RND_SEED);
if(test_random(IWAIT_RND_SEED, IWAIT_RANDOM)) then
OUT_VALID <= '0';
OUT_DATA <= (others => 'X');
next_random(IWAIT_RND_SEED);
I_TMP := range_random(IWAIT_RND_SEED, 1, IWAIT_RANDOM_N);
for J in 1 to I_TMP loop
wait until(CLK'event and (CLK = '1'));
end loop;
OUT_VALID <= '1';
end if;
end if;
end loop;
end if;
if(CPL_LAST = '1') then -- Retire the CID
CPL_POP_PTR(CPL_CID) := 0;
INBOUND_READ_REQUEST_CPL_STATE(CPL_CID) <= INBOUND_READ_REQUEST_ARRAY(CPL_CID).STATE;
wait on INBOUND_READ_REQUEST_CPL_STATE;
end if;
OUT_VALID <= '0';
OUT_DFRAME <= '0';
OUT_DATA <= (others => 'Z');
end if;
end loop;
end process;
--#########################################################################--
--
-- InBound State Machine
--
-- (Handles RX to the BFM: L2P for Primary and P2L for secondary)
--
--#########################################################################--
process
--file OUT_FILE : text is out "STD_OUTPUT";
file OUT_FILE : text open write_mode is "STD_OUTPUT";
variable OUTPUT_LINE : line;
variable HEADER_TC : std_ulogic_vector(2 downto 0);
variable HEADER_S : std_ulogic;
variable HEADER_TYPE : std_ulogic_vector(3 downto 0);
variable HEADER_LBE : std_ulogic_vector(3 downto 0);
variable HEADER_FBE : std_ulogic_vector(3 downto 0);
variable HEADER_STAT : std_ulogic_vector(1 downto 0);
variable HEADER_L : std_ulogic;
variable HEADER_V : std_ulogic;
variable HEADER_CID : std_ulogic_vector(1 downto 0);
variable HEADER_LENGTH : std_ulogic_vector(9 downto 0);
variable HEADER : std_ulogic_vector(IN_DATA'range);
variable HEADER_ADDR_LOW : std_ulogic_vector(IN_DATA'range);
variable HEADER_ADDR_HI : std_ulogic_vector(IN_DATA'range);
variable BFM_BAR_HIT : boolean_vector(1 downto 0);
variable RAM_ADDR : std_ulogic_vector(N_RAM_MAX-1 downto 0);
variable RAM_BE : std_ulogic_vector(3 downto 0);
variable RAM_DATA : std_ulogic_vector(7 downto 0);
variable INBOUND_LABEL : string(1 to 3);
variable FIRST_DW : boolean;
variable COMPLETION_ID : integer; --
variable CID_COUNT : integer;
variable I_HEADER_LENGTH : integer;
variable I_CID : integer;
variable CMP_DATA : std_ulogic_vector(IN_DATA'range);
variable RD_DATA, RD_MASK: std_ulogic_vector(IN_DATA'range);
variable RD_BUFFER_PTR : INT_VECTOR(N_COMPLETION_ID-1 downto 0);
variable RD_CPL_RAM_ADDR : DATA32(N_COMPLETION_ID-1 downto 0);
variable vERR : integer;
variable TMP_I : integer;
variable TMP32 : std_ulogic_vector(31 downto 0);
begin
if(MODE_PRIMARY) then
INBOUND_LABEL := "L2P";
else
INBOUND_LABEL := "P2L";
end if;
COMPLETION_ID := 0;
for I in 0 to N_COMPLETION_ID-1 loop
INBOUND_READ_REQUEST_ARRAY(I).STATE <= FALSE;
RD_CPL_RAM_ADDR(I) := (others => '0');
end loop;
RD_BUFFER_PTR := (others => 0);
loop
wait until(ICLK'event and (ICLK = '1'));
if((IN_DFRAME and IN_VALID) = '1') then -- Start of a packet
--*-------------------------------------------------------------
--* Header Phase
--*-------------------------------------------------------------
HEADER := IN_DATA;
HEADER_TC := IN_DATA(31 downto 29);
HEADER_S := IN_DATA(28);
HEADER_TYPE := IN_DATA(27 downto 24);
HEADER_LBE := IN_DATA(23 downto 20);
HEADER_FBE := IN_DATA(19 downto 16);
HEADER_STAT := IN_DATA(17 downto 16);
HEADER_L := IN_DATA(15);
HEADER_V := IN_DATA(12);
HEADER_CID := IN_DATA(11 downto 10);
HEADER_LENGTH := IN_DATA(9 downto 0);
if(Q_IN_DFRAME = '1') then
write(OUTPUT_LINE, "-- ERROR: " & INSTANCE_LABEL);
write(OUTPUT_LINE, NOW);
write(OUTPUT_LINE, ": " & INBOUND_LABEL &" Packet is Improperly Framed (Doesn't start with a L-to-H transition on DFRAME)");
writeline(OUT_FILE, OUTPUT_LINE);
end if;
COMPLETION_ID := to_int(HEADER_CID);
--*-------------------------------------------------------------
--* Address Phase
--*-------------------------------------------------------------
if((HEADER_TYPE = "0000") or (HEADER_TYPE = "0010")) then -- 32 bit address
wait until(ICLK'event and (ICLK = '1') and (IN_VALID = '1'));
HEADER_ADDR_LOW := IN_DATA;
HEADER_ADDR_HI := (others => '0');
elsif((HEADER_TYPE = "0001") or (HEADER_TYPE = "0011")) then -- 64 bit address
wait until(ICLK'event and (ICLK = '1') and (IN_VALID = '1'));
HEADER_ADDR_HI := IN_DATA;
wait until(ICLK'event and (ICLK = '1') and (IN_VALID = '1'));
HEADER_ADDR_LOW := IN_DATA;
elsif(HEADER_TYPE = "0100") then -- Completion: No Data
-- wait until(ICLK'event and (ICLK = '1') and (IN_VALID = '1'));
elsif(HEADER_TYPE = "0101") then -- Completion: With Data
else
write(OUTPUT_LINE, "-- ERROR: " & INSTANCE_LABEL);
write(OUTPUT_LINE, NOW);
write(OUTPUT_LINE, string'(" Unrecognized TYPE=0x"));
write_hex_vector(OUTPUT_LINE, HEADER);
write(OUTPUT_LINE, string'(" --> Header Word=0x"));
write_hex_vector(OUTPUT_LINE, HEADER);
writeline(OUT_FILE, OUTPUT_LINE);
end if;
if(PRIMARY) then
BFM_BAR_HIT(0) := (((HEADER_ADDR_LOW and BFM_BAR_ATTRIBUTE_ARRAY(0).MASK) = BFM_BAR_ATTRIBUTE_ARRAY(0).BASE(31 downto 0))
and (HEADER_ADDR_HI = BFM_BAR_ATTRIBUTE_ARRAY(0).BASE(63 downto 32)));
BFM_BAR_HIT(1) := (((HEADER_ADDR_LOW and BFM_BAR_ATTRIBUTE_ARRAY(1).MASK) = BFM_BAR_ATTRIBUTE_ARRAY(1).BASE(31 downto 0))
and (HEADER_ADDR_HI = BFM_BAR_ATTRIBUTE_ARRAY(1).BASE(63 downto 32)));
else
if(HEADER_ADDR_LOW(1 downto 0) = "00") then
BFM_BAR_HIT(0) := TRUE;
BFM_BAR_HIT(1) := FALSE;
elsif(HEADER_ADDR_LOW(1 downto 0) = "01") then
BFM_BAR_HIT(0) := FALSE;
BFM_BAR_HIT(1) := TRUE;
else
BFM_BAR_HIT(0) := FALSE;
BFM_BAR_HIT(1) := FALSE;
end if;
end if;
RAM_ADDR := to_mvl(BFM_BAR_HIT(1)) & HEADER_ADDR_LOW(RAM_ADDR'high-1 downto 2) & "00";
RAM_BE := HEADER_FBE;
FIRST_DW := TRUE;
--*-------------------------------------------------------------
--* Data Phase - Write
--*-------------------------------------------------------------
if((HEADER_TYPE = "0010") or (HEADER_TYPE = "0011")) then -- Write Packet
if(BFM_BAR_HIT(0) or BFM_BAR_HIT(1)) then
L1: loop
wait until(ICLK'event and (ICLK = '1') and (IN_VALID = '1'));
if(FIRST_DW) then
RAM_BE := HEADER_FBE;
elsif(IN_DFRAME /= '1') then
RAM_BE := HEADER_LBE;
else
RAM_BE := (others => '1');
end if;
for i in 0 to RAM_BE'high loop
if (RAM_BE(i) = '1') then
RAM_DATA := IN_DATA(8*i+7 downto 8*i);
--write(OUTPUT_LINE, string'("-- " & INSTANCE_LABEL & INBOUND_LABEL &" Mem_Write("));
--write_hex_vector(OUTPUT_LINE, RAM_ADDR);
--write(OUTPUT_LINE, string'(", "));
--write_hex_vector(OUTPUT_LINE, RAM_DATA);
--write(OUTPUT_LINE, string'(")"));
--writeline(OUT_FILE, OUTPUT_LINE);
RAM_WR1 <= TRUE;
RAM_ADDR1 <= RAM_ADDR;
RAM_WR_DATA1 <= RAM_DATA;
RAM_REQ1 <= not RAM_REQ1;
wait on RAM_ACK1;
end if;
RAM_ADDR := RAM_ADDR + '1';
end loop;
FIRST_DW := false;
if(IN_DFRAME /= '1') then
exit L1;
end if;
end loop;
else
write(OUTPUT_LINE, "-- ERROR: " & INSTANCE_LABEL);
write(OUTPUT_LINE, NOW);
write(OUTPUT_LINE, (" " & INBOUND_LABEL & " Address didn't match any local BAR: HEADER=0x"));
write_hex_vector(OUTPUT_LINE, HEADER);
write(OUTPUT_LINE, string'(", ADDRESS=0x"));
write_hex_vector(OUTPUT_LINE, HEADER_ADDR_HI);
write_hex_vector(OUTPUT_LINE, HEADER_ADDR_LOW);
writeline(OUT_FILE, OUTPUT_LINE);
wait until(ICLK'event and (ICLK = '1') and (IN_VALID = '1') and (IN_DFRAME = '0'));
end if;
elsif((HEADER_TYPE = "0000") or (HEADER_TYPE = "0001")) then -- Read Request
--*-------------------------------------------------------------
--* Process the Read Request
--*-------------------------------------------------------------
-- INBOUND_READ_REQUEST_ARRAY(i).ADDRESS
-- INBOUND_READ_REQUEST_ARRAY(i).LENGTH
-- INBOUND_READ_REQUEST_ARRAY(i).STATE
-- constant N_INBOUND_RD_OUTSTANDING : integer := 3; -- Maximim number of outstanding reads
-- constant N_COMPLETION_ID : integer := 4; -- Maximim number of completion IDs
if(INBOUND_READ_REQUEST_CPL_STATE(COMPLETION_ID) /= INBOUND_READ_REQUEST_ARRAY(COMPLETION_ID).STATE) then -- ERROR: CID is in use
write(OUTPUT_LINE, "-- ERROR: " & INSTANCE_LABEL);
write(OUTPUT_LINE, NOW);
write(OUTPUT_LINE, (" " & INBOUND_LABEL & " Completion ID (CID=" & to_str(COMPLETION_ID) & ") is already in use: HEADER=0x"));
write_hex_vector(OUTPUT_LINE, HEADER);
write(OUTPUT_LINE, string'(", ADDRESS=0x"));
write_hex_vector(OUTPUT_LINE, HEADER_ADDR_HI);
write_hex_vector(OUTPUT_LINE, HEADER_ADDR_LOW);
writeline(OUT_FILE, OUTPUT_LINE);
else
-- Make sure we have a budget for completion IDs
CID_COUNT := 0;
for I in 0 to (N_COMPLETION_ID-1) loop
if(INBOUND_READ_REQUEST_CPL_STATE(I) /= INBOUND_READ_REQUEST_ARRAY(I).STATE) then
CID_COUNT := CID_COUNT + 1;
end if;
end loop;
if(CID_COUNT < N_INBOUND_RD_OUTSTANDING) then -- OK to accept the request
INBOUND_READ_REQUEST_ARRAY(COMPLETION_ID).ADDRESS <= HEADER_ADDR_HI & HEADER_ADDR_LOW;
INBOUND_READ_REQUEST_ARRAY(COMPLETION_ID).BAR_HIT <= to_mvl(BFM_BAR_HIT(1)) & to_mvl(BFM_BAR_HIT(0));
INBOUND_READ_REQUEST_ARRAY(COMPLETION_ID).LENGTH <= to_int(HEADER_LENGTH);
INBOUND_READ_REQUEST_ARRAY(COMPLETION_ID).STATE <= not INBOUND_READ_REQUEST_ARRAY(COMPLETION_ID).STATE;
INBOUND_READ_REQUEST_ARRAY(COMPLETION_ID).TC <= HEADER_TC;
INBOUND_READ_REQUEST_ARRAY(COMPLETION_ID).V <= HEADER_V;
wait on INBOUND_READ_REQUEST_ARRAY;
else
write(OUTPUT_LINE, "-- ERROR: " & INSTANCE_LABEL);
write(OUTPUT_LINE, NOW);
write(OUTPUT_LINE, (" " & INBOUND_LABEL & " Number of outstanding read requests exceeded: HEADER=0x"));
write_hex_vector(OUTPUT_LINE, HEADER);
write(OUTPUT_LINE, string'(", ADDRESS=0x"));
write_hex_vector(OUTPUT_LINE, HEADER_ADDR_HI);
write_hex_vector(OUTPUT_LINE, HEADER_ADDR_LOW);
writeline(OUT_FILE, OUTPUT_LINE);
end if;
end if;
elsif((HEADER_TYPE = "0100") or (HEADER_TYPE = "0101")) then -- Read Request
--*-------------------------------------------------------------
--* Process the Read Completion
--*-------------------------------------------------------------
I_HEADER_LENGTH := to_int(HEADER_LENGTH);
I_CID := to_int(HEADER_CID);
if(RD_BUFFER_PTR(I_CID) = 0) then -- start of a completion sequence
RD_CPL_RAM_ADDR(I_CID)(RAM_ADDR'high) := RD_BUFFER(I_CID).BAR_HIT(1);
RD_CPL_RAM_ADDR(I_CID)(RAM_ADDR'high-1 downto 0) := RD_BUFFER(I_CID).ADDRESS(RAM_ADDR'high-1 downto 2) & "00";
end if;
-- RAM_ADDR := RD_CPL_RAM_ADDR(I_CID)(RAM_ADDR'range);
-- CHANGE Can get rid of RD_CPL_RAM_ADDR
loop
wait until(ICLK'event and (ICLK = '1') and (IN_VALID = '1'));
I_HEADER_LENGTH := I_HEADER_LENGTH - 1;
-- for J in 0 to 3 loop -- Do all 4 bytes of the read
--
-- RAM_ADDR1 <= RAM_ADDR;
-- RAM_REQ1 <= not RAM_REQ1;
--
-- wait on RAM_ACK1;
--
-- CMP_DATA(J*8+7 downto J*8) := RAM_RD_DATA1;
-- RAM_ADDR := RAM_ADDR + '1';
--
-- end loop;
CMP_DATA := IN_DATA;
RD_DATA := RD_BUFFER(I_CID).DATA(RD_BUFFER_PTR(I_CID));
RD_MASK := RD_BUFFER(I_CID).MASK(RD_BUFFER_PTR(I_CID));
read_cmp(OUTPUT_LINE, (INSTANCE_LABEL & "BFM Master Mode Read "), CMP_DATA, RD_DATA, RD_MASK, vERR);
if(vERR /= 0) then
TMP_I := RD_BUFFER_PTR(I_CID)*4;
TMP_I := to_int(RD_BUFFER(I_CID).ADDRESS(31 downto 0)) + TMP_I;
TMP32 := to_vector(TMP_I, TMP32'length);
write(OUTPUT_LINE, LF);
write(OUTPUT_LINE, string'("Header=0x"));
write_hex_vector(OUTPUT_LINE, HEADER);
write(OUTPUT_LINE, string'(", CID=0x"));
write_hex_vector(OUTPUT_LINE, HEADER_CID);
write(OUTPUT_LINE, string'(", ADDRESS=0x"));
write_hex_vector(OUTPUT_LINE, RD_BUFFER(I_CID).ADDRESS(63 downto 32));
write_hex_vector(OUTPUT_LINE, TMP32);
writeline(OUT_FILE, OUTPUT_LINE);
end if;
RD_BUFFER_PTR(I_CID) := RD_BUFFER_PTR(I_CID) + 1;
if(IN_DFRAME = '0') or (I_HEADER_LENGTH = 0) then
exit;
end if;
end loop;
RD_CPL_RAM_ADDR(I_CID)(RAM_ADDR'range) := RAM_ADDR;
if not((IN_DFRAME = '0') and (I_HEADER_LENGTH = 0)) then
write(OUTPUT_LINE, "-- ERROR: " & INSTANCE_LABEL);
write(OUTPUT_LINE, NOW);
write(OUTPUT_LINE, (" " & INBOUND_LABEL & "_DFRAME is not in agreement with the header length value: HEADER=0x"));
write_hex_vector(OUTPUT_LINE, HEADER);
write(OUTPUT_LINE, string'(", ADDRESS=0x"));
write_hex_vector(OUTPUT_LINE, HEADER_ADDR_HI);
write_hex_vector(OUTPUT_LINE, HEADER_ADDR_LOW);
writeline(OUT_FILE, OUTPUT_LINE);
end if;
if(HEADER_L = '1') then
OUTBOUND_READ_REQUEST_CPL_STATE(I_CID) <= RD_BUFFER(I_CID).STATE;
RD_BUFFER_PTR(I_CID) := 0;
end if;
end if;
end if;
end loop;
end process;
--#########################################################################--
--
-- BFM Internal RAM Handler
--
-- Handles SRAM access from multiple processes
--
--#########################################################################--
process
--file OUT_FILE : text is out "STD_OUTPUT";
-- file OUT_FILE : text open write_mode is "STD_OUTPUT";
-- variable OUTPUT_LINE : line;
variable SRAM_BFM : MEM_ID_TYPE;
variable vRAM_DATA : std_ulogic_vector(7 downto 0);
begin
-- Initialize RAM model
SRAM_BFM := SRAM_INITIALIZE
( name => "BFM RAM",
length => (2**N_RAM_MAX),
width => 8,
default_word => STD_ULOGIC_VECTOR'("XXXXXXXX")
);
RAM_ACK0 <= FALSE;
RAM_ACK1 <= FALSE;
loop
wait on RAM_REQ0, RAM_REQ1;
if(RAM_REQ0'event) then
if(RAM_WR0) then
Mem_Write
( mem_id => SRAM_BFM,
address => RAM_ADDR0,
data => RAM_WR_DATA0
);
else
Mem_Read
( mem_id => SRAM_BFM,
address => RAM_ADDR0,
data => vRAM_DATA
);
RAM_RD_DATA0 <= vRAM_DATA;
end if;
RAM_ACK0 <= not RAM_ACK0;
-- wait until(RAM_REQ0'event);
end if;
if(RAM_REQ1'event) then
if(RAM_WR1) then
Mem_Write
( mem_id => SRAM_BFM,
address => RAM_ADDR1,
data => RAM_WR_DATA1
);
else
Mem_Read
( mem_id => SRAM_BFM,
address => RAM_ADDR1,
data => vRAM_DATA
);
RAM_RD_DATA1 <= vRAM_DATA;
end if;
RAM_ACK1 <= not RAM_ACK1;
-- wait until(RAM_REQ1'event);
end if;
end loop;
end process;
--#########################################################################--
--
-- Random # generator
--
-- Uses PRBS-23
--
--#########################################################################--
process(CLK0o)
variable RNDOUT : integer;
variable SEED : integer;
begin
if(RSTOUTo = '1') then
SEED := 5000;
elsif(CLK0o'event and CLK0o = '1') then
get_random(SEED, 0, 100, RNDOUT);
RANDOM_NUMBER <= RNDOUT;
end if;
end process;
--#########################################################################--
--
-- L2P Bus Sniffer
--
--#########################################################################--
process
begin
wait until(L2P_CLKpi'event);
L2P_CLKi_90 <= transport L2P_CLKpi after (T_LCLKi/4);
end process;
process
file OUT_FILE : text open write_mode is "STD_OUTPUT";
variable OUTPUT_LINE : line;
variable vHEADER : std_ulogic_vector(31 downto 0);
variable vADDRESS : std_ulogic_vector(63 downto 0);
variable vTYPE : std_ulogic_vector(3 downto 0);
variable START : time;
begin
wait until(L2P_CLKi_90'event and (L2P_CLKi_90 = '1') and (L2P_VALIDi='1') and MODE_PRIMARY);
START := NOW;
if(L2P_DFRAMEi = '1') then
vHEADER(15 downto 0) := L2P_DATAi;
wait until(L2P_CLKi_90'event and (L2P_CLKi_90 = '0'));
vHEADER(31 downto 16) := L2P_DATAi;
vTYPE := vHEADER(27 downto 24);
vADDRESS := (others => '0');
-- Upper Address
if((vTYPE = "0001") or (vTYPE = "0011")) then -- address is 64 bits
wait until(L2P_CLKi_90'event and (L2P_CLKi_90 = '1') and (L2P_VALIDi='1'));
vADDRESS(47 downto 32) := L2P_DATAi;
wait until(L2P_CLKi_90'event and (L2P_CLKi_90 = '0'));
vADDRESS(63 downto 48) := L2P_DATAi;
end if;
-- Lower Address
if((vTYPE = "0000") or (vTYPE = "0001") or (vTYPE = "0010") or (vTYPE = "0011") or (vTYPE = "0100")) then -- address is required
wait until(L2P_CLKi_90'event and (L2P_CLKi_90 = '1') and (L2P_VALIDi='1'));
vADDRESS(15 downto 0) := L2P_DATAi;
wait until(L2P_CLKi_90'event and (L2P_CLKi_90 = '0'));
vADDRESS(31 downto 16) := L2P_DATAi;
end if;
-- write(OUTPUT_LINE, ("-->> L2P Packet: " & to_string(START)));
-- writeline(OUT_FILE, OUTPUT_LINE);
write(OUTPUT_LINE, string'("-->>>> L2P Header: "));
case vTYPE is
when "0000" | "0001" =>
write(OUTPUT_LINE, string'("(L2P Master Read Request)"));
write(OUTPUT_LINE, string'(", FBE=0x"));
write_hex_vector(OUTPUT_LINE, vHEADER(23 downto 20));
write(OUTPUT_LINE, string'(", LBE=0x"));
write_hex_vector(OUTPUT_LINE, vHEADER(19 downto 16));
write(OUTPUT_LINE, string'(", V=" & to_str(vHEADER(12))));
write(OUTPUT_LINE, string'(", CID="));
write_hex_vector(OUTPUT_LINE, vHEADER(11 downto 10));
write(OUTPUT_LINE, string'(", LENGTH=0x"));
write_hex_vector(OUTPUT_LINE, vHEADER(9 downto 0));
-- writeline(OUT_FILE, OUTPUT_LINE);
write(OUTPUT_LINE, string'("-->>>> Address: 0x"));
write_hex_vector(OUTPUT_LINE, vADDRESS);
write(OUTPUT_LINE, string'(" @ "));
write(OUTPUT_LINE, START);
writeline(OUT_FILE, OUTPUT_LINE);
when "0010" | "0011" =>
write(OUTPUT_LINE, string'("(L2P Master Write)"));
write(OUTPUT_LINE, string'(", FBE=0x"));
write_hex_vector(OUTPUT_LINE, vHEADER(23 downto 20));
write(OUTPUT_LINE, string'(", LBE=0x"));
write_hex_vector(OUTPUT_LINE, vHEADER(19 downto 16));
write(OUTPUT_LINE, string'(", V=" & to_str(vHEADER(12))));
write(OUTPUT_LINE, string'(", LENGTH=0x"));
write_hex_vector(OUTPUT_LINE, vHEADER(9 downto 0));
-- writeline(OUT_FILE, OUTPUT_LINE);
write(OUTPUT_LINE, string'("-->>>> Address: 0x"));
write_hex_vector(OUTPUT_LINE, vADDRESS);
write(OUTPUT_LINE, string'(" @ "));
write(OUTPUT_LINE, START);
writeline(OUT_FILE, OUTPUT_LINE);
when "0100" =>
write(OUTPUT_LINE, string'("(L2P Target Read Completion Without Data)"));
write(OUTPUT_LINE, string'(", STAT="));
write_hex_vector(OUTPUT_LINE, vHEADER(17 downto 16));
write(OUTPUT_LINE, string'(", L=" & to_str(vHEADER(15))));
write(OUTPUT_LINE, string'(", V=" & to_str(vHEADER(12))));
write(OUTPUT_LINE, string'(", CID="));
write_hex_vector(OUTPUT_LINE, vHEADER(11 downto 10));
write(OUTPUT_LINE, string'(", LENGTH=0x"));
write_hex_vector(OUTPUT_LINE, vHEADER(9 downto 0));
write(OUTPUT_LINE, string'(" @ "));
write(OUTPUT_LINE, START);
writeline(OUT_FILE, OUTPUT_LINE);
when "0101" =>
write(OUTPUT_LINE, string'("(L2P Target Read Completion With Data)"));
write(OUTPUT_LINE, string'(", STAT="));
write_hex_vector(OUTPUT_LINE, vHEADER(17 downto 16));
write(OUTPUT_LINE, string'(", L=" & to_str(vHEADER(15))));
write(OUTPUT_LINE, string'(", V=" & to_str(vHEADER(12))));
write(OUTPUT_LINE, string'(", CID="));
write_hex_vector(OUTPUT_LINE, vHEADER(11 downto 10));
write(OUTPUT_LINE, string'(", LENGTH=0x"));
write_hex_vector(OUTPUT_LINE, vHEADER(9 downto 0));
write(OUTPUT_LINE, string'(" @ "));
write(OUTPUT_LINE, START);
writeline(OUT_FILE, OUTPUT_LINE);
when others =>
write(OUTPUT_LINE, string'("(Undefined)"));
write(OUTPUT_LINE, string'(" @ "));
write(OUTPUT_LINE, START);
writeline(OUT_FILE, OUTPUT_LINE);
assert false report "---- ERROR: Unsupported TYPE in L2P Header"
severity error;
end case;
if(L2P_DFRAMEi='1') then
wait until(L2P_CLKi_90'event and (L2P_CLKi_90 = '1') and (L2P_VALIDi='1') and (L2P_DFRAMEi='0'));
end if;
else
write(OUTPUT_LINE, string'("-- ERROR: L2P Bus: P2L_VALID asserted without P2L_DFRAME @"));
write(OUTPUT_LINE, START);
writeline(OUT_FILE, OUTPUT_LINE);
end if;
end process;
--#########################################################################--
--
-- P2L Bus Sniffer
--
--#########################################################################--
process
file OUT_FILE : text open write_mode is "STD_OUTPUT";
variable OUTPUT_LINE : line;
variable vHEADER : std_ulogic_vector(31 downto 0);
variable vADDRESS : std_ulogic_vector(63 downto 0);
variable vTYPE : std_ulogic_vector(3 downto 0);
variable START : time;
begin
wait until(P2L_CLKpi'event and (P2L_CLKpi = '1') and (P2L_VALIDi='1') and MODE_PRIMARY);
START := NOW;
if(P2L_DFRAMEi = '1') then
vHEADER(15 downto 0) := P2L_DATAi;
wait until(P2L_CLKpi'event and (P2L_CLKpi = '0'));
vHEADER(31 downto 16) := P2L_DATAi;
vTYPE := vHEADER(27 downto 24);
vADDRESS := (others => '0');
-- Upper Address
if((vTYPE = "0001") or (vTYPE = "0011")) then -- address is 64 bits
wait until(P2L_CLKpi'event and (P2L_CLKpi = '1') and (P2L_VALIDi='1'));
vADDRESS(47 downto 32) := P2L_DATAi;
wait until(P2L_CLKpi'event and (P2L_CLKpi = '0'));
vADDRESS(63 downto 48) := P2L_DATAi;
end if;
-- Lower Address
if((vTYPE = "0000") or (vTYPE = "0001") or (vTYPE = "0010") or (vTYPE = "0011") or (vTYPE = "0100")) then -- address is required
wait until(P2L_CLKpi'event and (P2L_CLKpi = '1') and (P2L_VALIDi='1'));
vADDRESS(15 downto 0) := P2L_DATAi;
wait until(P2L_CLKpi'event and (P2L_CLKpi = '0'));
vADDRESS(31 downto 16) := P2L_DATAi;
end if;
write(OUTPUT_LINE, string'("--<<<< P2L Header: "));
case vTYPE is
when "0000" | "0001" =>
write(OUTPUT_LINE, string'("(P2L Target Read Request)"));
write(OUTPUT_LINE, string'(", FBE=0x"));
write_hex_vector(OUTPUT_LINE, vHEADER(23 downto 20));
write(OUTPUT_LINE, string'(", LBE=0x"));
write_hex_vector(OUTPUT_LINE, vHEADER(19 downto 16));
write(OUTPUT_LINE, string'(", V=" & to_str(vHEADER(12))));
write(OUTPUT_LINE, string'(", CID="));
write_hex_vector(OUTPUT_LINE, vHEADER(11 downto 10));
write(OUTPUT_LINE, string'(", LENGTH=0x"));
write_hex_vector(OUTPUT_LINE, vHEADER(9 downto 0));
write(OUTPUT_LINE, string'("--<<<< Address: 0x"));
write_hex_vector(OUTPUT_LINE, vADDRESS);
write(OUTPUT_LINE, string'(" @ "));
write(OUTPUT_LINE, START);
writeline(OUT_FILE, OUTPUT_LINE);
when "0010" | "0011" =>
write(OUTPUT_LINE, string'("(P2L Target Write)"));
write(OUTPUT_LINE, string'(", FBE=0x"));
write_hex_vector(OUTPUT_LINE, vHEADER(23 downto 20));
write(OUTPUT_LINE, string'(", LBE=0x"));
write_hex_vector(OUTPUT_LINE, vHEADER(19 downto 16));
write(OUTPUT_LINE, string'(", V=" & to_str(vHEADER(12))));
write(OUTPUT_LINE, string'(", LENGTH=0x"));
write_hex_vector(OUTPUT_LINE, vHEADER(9 downto 0));
write(OUTPUT_LINE, string'("--<<<< Address: 0x"));
write_hex_vector(OUTPUT_LINE, vADDRESS);
write(OUTPUT_LINE, string'(" @ "));
write(OUTPUT_LINE, START);
writeline(OUT_FILE, OUTPUT_LINE);
when "0100" =>
write(OUTPUT_LINE, string'("(P2L Master Read Completion Without Data)"));
write(OUTPUT_LINE, string'(", STAT="));
write_hex_vector(OUTPUT_LINE, vHEADER(17 downto 16));
write(OUTPUT_LINE, string'(", L=" & to_str(vHEADER(15))));
write(OUTPUT_LINE, string'(", V=" & to_str(vHEADER(12))));
write(OUTPUT_LINE, string'(", CID="));
write_hex_vector(OUTPUT_LINE, vHEADER(11 downto 10));
write(OUTPUT_LINE, string'(", LENGTH=0x"));
write_hex_vector(OUTPUT_LINE, vHEADER(9 downto 0));
write(OUTPUT_LINE, string'(" @ "));
write(OUTPUT_LINE, START);
writeline(OUT_FILE, OUTPUT_LINE);
when "0101" =>
write(OUTPUT_LINE, string'("(P2L Master Read Completion With Data)"));
write(OUTPUT_LINE, string'(", STAT="));
write_hex_vector(OUTPUT_LINE, vHEADER(17 downto 16));
write(OUTPUT_LINE, string'(", L=" & to_str(vHEADER(15))));
write(OUTPUT_LINE, string'(", V=" & to_str(vHEADER(12))));
write(OUTPUT_LINE, string'(", CID="));
write_hex_vector(OUTPUT_LINE, vHEADER(11 downto 10));
write(OUTPUT_LINE, string'(", LENGTH=0x"));
write_hex_vector(OUTPUT_LINE, vHEADER(9 downto 0));
write(OUTPUT_LINE, string'(" @ "));
write(OUTPUT_LINE, START);
writeline(OUT_FILE, OUTPUT_LINE);
when others =>
write(OUTPUT_LINE, string'("(Undefined)"));
write(OUTPUT_LINE, string'(" @ "));
write(OUTPUT_LINE, START);
writeline(OUT_FILE, OUTPUT_LINE);
assert false report "---- ERROR: Unsupported TYPE in P2L Header"
severity error;
end case;
if(P2L_DFRAMEi='1') then
wait until(P2L_CLKpi'event and (P2L_CLKpi = '1') and (P2L_VALIDi='1') and (P2L_DFRAMEi='0'));
end if;
else
write(OUTPUT_LINE, string'("-- ERROR: P2L Bus: P2L_VALID asserted without P2L_DFRAME @"));
write(OUTPUT_LINE, START);
writeline(OUT_FILE, OUTPUT_LINE);
end if;
end process;
end MODEL;
library ieee;
use ieee.std_logic_1164.all;
library std;
use std.textio.all;
PACKAGE mem_model is
-- 2d array to store data for each row
type row_matrix is array (NATURAL RANGE <>, NATURAL RANGE <>) of UX01;
type rowptr_type is access row_matrix;
-- record for for storing refresh and memory ptr for each row
type row_data_type is
record
last_refresh : time; -- last time row was refreshed
rowptr : rowptr_type; -- ptr to 2d matrix with data
all_xs : BOOLEAN; -- true if row is filled with Xs
end record;
-- array of refresh times and memory ptrs for the rows
type row_data is array (NATURAL RANGE <>) of row_data_type;
type row_data_ptr_type is access row_data;
type strptr is access string;
type default_ptr_type is access std_logic_vector;
type mem_type is (DRAM, SRAM, ROM); -- memory types
-- record defining memory and holding general information
type mem_id_rtype is
record
memory_type : mem_type; -- memory type
refresh_period : time; -- refresh period
last_init : time; -- last time a refresh was performed
counter : NATURAL; -- refresh counter
name : strptr; -- pointer to memory name
rows : POSITIVE; -- # of rows
columns : POSITIVE; -- # of columns
width : POSITIVE; -- # word length
length : POSITIVE; -- # of memory locations
row_data_ptr : row_data_ptr_type; -- ptr to memory ptrs.
default : default_ptr_type; -- ptr to default memory word value
end record;
type mem_id_type is access mem_id_rtype;
--********************************************************************************
-- Function Name : SRAM_Initialize
--
-- Purpose : To create the data structure used to store a
-- static RAM and to initialize it
--
-- Parameters : name - string used to represent the memory
-- length - the number of "words" in the memory
-- width - the length of a "word" of memory
-- default_word - value to which each word of memory
-- should be initialized
--
-- RETURNED VALUE : mem_id_type - ptr to memory record
--
-- NOTE : initially the data structure is empty with no
-- space being allocated for the memory
--
-- Use : sram_l1 := SRAM_Initialize ("lsb_of_RAM",1048576,1,"0");
--********************************************************************************
impure Function SRAM_Initialize ( Constant name : IN string;
Constant length : IN POSITIVE;
Constant width : IN POSITIVE;
Constant default_word : IN std_ulogic_vector
) return mem_id_type;
--********************************************************************************
-- Procedure Name : Mem_Read
--
-- Purpose : To read a "word" from memory
--
-- Parameters : mem_id - ptr to memory data structure
-- address - address to read from
-- data - contents of memory location
--
--
-- NOTE : a read refreshes row of a DRAM
--
-- Use : Mem_Read (ROM1, "100100111", data_bus);
--********************************************************************************
Procedure Mem_Read ( Variable mem_id : INOUT mem_id_type;
Constant address : IN std_ulogic_vector;
Variable data : OUT std_ulogic_vector
);
--********************************************************************************
-- Procedure Name : Mem_Write
--
-- Purpose : To write a "word" to memory
--
-- Parameters : mem_id - ptr to memory data structure
-- address - address to read from
-- data - "word" to be written to memory
--
-- NOTE : a write refreshes row of a DRAM
--
-- Use : Mem_Write (ROM1, "100100111", "10X1");
--********************************************************************************
Procedure Mem_Write ( Variable mem_id : INOUT mem_id_type;
Constant address : IN std_ulogic_vector;
Constant data : IN std_ulogic_vector
);
END mem_model;
PACKAGE BODY mem_model is
Type D1_b_ulogic_type is array(bit) of std_ulogic;
type hex_ray is array(1 to 16) of character;
type IDENTIFIER is (HEX_NUM1, COMMENT1, WIDTH1, DEFAULT1, COLON1, DOTDOT1, BLANK1, SYN_ERROR1);
type digit_to_hex_type is array(0 to 15) of character;
-- mentor doesn't like the subtype UX01 - "resolved sybyte cannot be used as a discrete range"
type UX01_1DRAY is array(std_ulogic range 'U' to '1') of bit;
-------------------------------------------------------------------------------------------
-- THE FOLLOWING CONSTANTS MAY BE CHANGED BY THE USER TO CUSTOMIZE STD_MEMPAK
-------------------------------------------------------------------------------------------
-- defines the number of bits used to represent an integer on the machine used to run the vhdl simulator
CONSTANT IntegerBitLength : INTEGER := 32;
-- defines the maximum length of strings in this package
CONSTANT MAX_STR_LEN : NATURAL := 256;
-- constants used to map X's and U's in an address to valid values
CONSTANT ADDRESS_X_MAP : BIT := '1';
CONSTANT ADDRESS_U_MAP : BIT := '1';
CONSTANT ADDRESS_MAP : UX01_1DRAY :=
(ADDRESS_U_MAP, ADDRESS_X_MAP, '0', '1');
-- constants used to map X's and U's in memory locations to a bit value
-- when a bit or a bit_vector is returned by the memory read operation
CONSTANT DATA_X_MAP : BIT := '1';
CONSTANT DATA_U_MAP : BIT := '1';
CONSTANT DATA_MAP : UX01_1DRAY :=
(DATA_U_MAP, DATA_X_MAP, '0', '1');
-- constants setting collumn size of SRAM's and ROM's so that entire
-- memory does not have to be allocated if it is not used.
CONSTANT SRAM_COL_SIZE : NATURAL := 1024;
CONSTANT ROM_COL_SIZE : NATURAL := 1024;
-- constant used to enable/disable certain warning assertions
CONSTANT MEM_WARNINGS_ON : BOOLEAN := TRUE;
-- constant used to determine how many words per line to output when doing a memory dump
CONSTANT WORDS_PER_LINE : POSITIVE := 16;
----------------------------------------------------------------------------------------------------------
-- CONSTANTS THAT SHOULD NOT BE MODIFIED
-- These are used by the package to perform various conversions, comparisions, etc.
----------------------------------------------------------------------------------------------------------
CONSTANT DIGIT_TO_HEX : digit_to_hex_type := ('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
CONSTANT hex : hex_ray := ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F');
CONSTANT bit_to_std_ulogic : D1_b_ulogic_type := ('0', '1');
CONSTANT SPACESTR : STRING(1 to 20) := " ";
CONSTANT SPACE : CHARACTER := ' ';
CONSTANT TAB : CHARACTER := HT;
function StrLen1 ( Constant l_str : IN string ) return NATURAL is
Variable alias_l_str : string(1 to l_str'length) := l_str;
Variable i : integer := 1;
begin
while ( (i <= l_str'length) and (alias_l_str(i) /= NUL) ) loop
i := i + 1;
end loop;
i := i - 1;
return i;
end;
function to_str (Constant dd : IN std_logic) return Character is
begin
case dd is
when '1' => return '1';
when '0' => return '0';
when 'U' => return 'U';
when 'X' => return 'X';
when 'L' => return 'L';
when 'H' => return 'H';
when '-' => return '-';
when 'Z' => return 'Z';
when 'W' => return 'W';
end case;
end;
function to_str (Constant dd : IN bit) return character is
begin
if dd = '0' then
return '0';
else
return '1';
end if;
end;
function i_to_str (Constant int : IN integer) return string is
Constant length : integer := 33;
Variable i, len, pos : integer;
Variable str : string (1 to length);
Variable tint : integer := int;
Variable temp : Character;
Variable negative : BOOLEAN := FALSE;
begin
for i in 1 to length loop
str(i) := ' ';
end loop;
if (tint < 0 ) then
tint := -tint;
negative := TRUE;
end if;
i := length;
while ( (i >= 1 ) and (tint /= 0)) loop
str(i) := CHARACTER'Val(48 + (tint mod 10));
tint := tint/10;
i := i - 1;
end loop;
if (NEGATIVE) then
str(i) := '-';
i := i - 1;
end if;
len := length - i;
pos := i + 1;
for i in 1 to len loop
str(i) := str(pos);
pos := pos + 1;
end loop;
if (len = 0) then
len := 1;
str(1) := '0';
end if;
return (str(1 to len));
end;
function v_to_str (Constant vect : IN bit_vector) return string is
Variable str : string( 1 to vect'length);
Variable alias_vect : bit_vector(1 to vect'length) := vect;
Variable i : integer;
begin
for i in 1 to vect'length loop
case alias_vect(i) is
when '1' => str(i) := '1';
when '0' => str(i) := '0';
end case;
end loop;
return(str);
end;
function v_to_str (Constant vect : IN std_logic_vector) return string is
Variable str : string( 1 to vect'length);
Variable alias_vect : std_logic_vector(1 to vect'length) := vect;
Variable i : integer;
begin
for i in 1 to vect'length loop
case alias_vect(i) is
when '1' => str(i) := '1';
when '0' => str(i) := '0';
when 'U' => str(i) := 'U';
when 'X' => str(i) := 'X';
when 'L' => str(i) := 'L';
when 'H' => str(i) := 'H';
when '-' => str(i) := '-';
when 'Z' => str(i) := 'Z';
when 'W' => str(i) := 'W';
end case;
end loop;
return(str);
end;
-- used to return a printable string for the memory name
function pstr ( Constant name : in string ) return string is
variable j : integer;
begin
j := 1;
while ( (j < name'length) and (name(j) /= nul) ) loop
j := j + 1;
end loop;
if (name(j) = nul) then
j := j - 1;
end if;
return name(1 to j);
end;
---------------------------------------------------------------------------
-- Function Name : minimum
--
-- PURPOSE : to determine the smaller of two integers
--
-- Parameters : int1 - first integer
-- : int2 - second integer
--
-- Returned Value : integer - the smaller of int1 and int2
--
---------------------------------------------------------------------------
Function minimum ( Constant int1 : IN integer;
Constant int2 : IN integer
) return integer is
begin
if (int1 < int2) then
return int1;
else
return int2;
end if;
end;
--+-----------------------------------------------------------------------------
--| Procedure Name : StrCpy1
--| 1.2.3
--| Overloading : None
--|
--| Purpose : Copy r_string to l_string.
--|
--| Parameters :
--| l_str - output, STRING, target string
--| r_str - input, STRING, source string
--|
--| Result :
--|
--| NOTE : If the length of target string is greater than
--| the source string, then target string is padded
--| with space characters on the right side and when
--| the length of target string is shorter than the
--| length of source string only left most characters
--| of the source string will be be copied to the target.
--|
--|
--| USE :
--| Variable s1: string(1 TO 8);
--|
--| StrCpy1(s1, "123456789A");
--| s1 will hold "12345678"
--|-----------------------------------------------------------------------------
PROCEDURE StrCpy1 ( VARIABLE l_str : OUT STRING;
CONSTANT r_str : IN STRING) IS
VARIABLE l_len : integer := l_str'LENGTH;
VARIABLE r_len : integer := r_str'LENGTH;
VARIABLE r : STRING ( 1 to r_len) := r_str;
VARIABLE result : STRING (1 to l_len);
VARIABLE indx : integer := 1;
BEGIN
assert (l_len > 0)
report "StrCpy: target string is of zero length "
severity ERROR;
while ( (indx <= r_len) and (indx <= l_len) and (r(indx) /= NUL) ) loop
result(indx) := r(indx);
indx := indx + 1;
end loop;
if (indx <= l_len) then
result(indx) := NUL;
end if;
l_str := result;
return;
END StrCpy1;
--+---------------------------------------------------------------------------
--| Procedure Name : fgetline1
--|
--| Overloading : None
--|
--| Purpose : To read a line from the input TEXT file and
--| save into a string.
--|
--| Parameters :
--| l_str -- output, STRING,
--| stream -- input, TEXT, input file
--|
--| result : string.
--|
--| Note: : The TEXT is defined in the package TEXTIO to be
--| a file of string.
--| USE: :
--| VARIABLE line_buf : string(1 TO 256);
--| FILE in_file : TEXT IS IN "file_text_in.dat";
--|
--| fgetline1(line_buf, in_file);
--|
--| Will read a line from the file
--| file_text_in.dat and place into line_buf.
--|
--|-----------------------------------------------------------------------------
PROCEDURE fgetline1 ( VARIABLE l_str : OUT STRING;
FILE stream : TEXT;
VARIABLE line_ptr : INOUT LINE
) IS
VARIABLE str_copy : STRING(1 TO MAX_STR_LEN + 1);
VARIABLE ch : character;
VARIABLE indx : NATURAL := 0;
BEGIN
If ( (line_ptr /= NULL) and (line_ptr'LENGTH > 0) ) then
NULL;
elsif ( not ENDFILE(stream) ) then
READLINE(stream, line_ptr);
else
assert NOT MEM_WARNINGS_ON
report " fgetline1 --- end of file text, no text read "
severity WARNING;
l_str(l_str'left) := NUL;
return;
end if;
while ( (line_ptr /= NULL) and (line_ptr'length /= 0) ) loop
READ(line_ptr,ch);
indx := indx + 1;
str_copy(indx) := ch;
end loop;
str_copy(indx + 1) := NUL;
strcpy1(l_str, str_copy);
return;
END;
--+-----------------------------------------------------------------------------
--| Function Name : Is_White1
--| hidden.
--| Overloading : None
--|
--| Purpose : Test whether a character is a blank, a tab or
--| a newline character.
--|
--| Parameters :
--| c - input Character.
--|
--| Result :Booelan -- True if the argument c is a blank or a tab(HT),
--| or a line feed (LF), or carriage return (CR). false otherwise.
--|
--|
--| See Also : Is_Space
--|-----------------------------------------------------------------------------
FUNCTION Is_White1 ( CONSTANT c : IN CHARACTER
) RETURN BOOLEAN IS
VARIABLE result : BOOLEAN;
BEGIN
IF ( (c = ' ') OR (c = HT) OR (c = CR) OR (c=LF) ) THEN
result := TRUE;
ELSE
result := FALSE;
END IF;
RETURN result;
END;
--+-----------------------------------------------------------------------------
--| Function Name : Find_NonBlank1
--| hidden
--| Overloading : None
--|
--| Purpose : Find first non_blank character in a string.
--|
--| Parameters :
--| str_in - input ,
--|
--| Result : Natural, index of non_blank character. If string
--| has all the white character then str_in'LENGTH is
--| returned;
--|
--| NOTE :
--|
--| Use :
--| VARIABLE s_flag : String(1 TO 10) := " TRUE";
--| VARIABLE idx: Natural
--|
--| idx := Find_NonBlank1 (s_flag);
--|
--|-----------------------------------------------------------------------------
FUNCTION Find_NonBlank1 ( CONSTANT str_in : IN STRING
) RETURN NATURAL IS
VARIABLE str_copy : STRING (1 TO str_in'LENGTH) := str_in;
VARIABLE index : Natural := 1;
VARIABLE ch : character;
BEGIN
loop
EXIT WHEN (index > str_in'LENGTH);
if Is_White1(str_copy(index)) then
index := index + 1;
else
EXIT;
end if;
end loop;
return index;
--
-- old code
--
-- ch := str_copy(index);
-- while ( ( index < str_in'LENGTH) AND (Is_White1(ch) ) ) LOOP
-- index := index + 1;
-- ch := str_copy(index);
-- end LOOP;
-- return index;
END;
--+-----------------------------------------------------------------------------
--| Function Name : To_Upper1
--| 1.
--| Overloading : None
--|
--| Purpose :Convert a string to upper case.
--|
--| Parameters :
--| val - input, string to be converted
--|
--| Result : string .
--|
--|
--| See Also : To_Lower, Is_Upper, Is_Lower
--|-----------------------------------------------------------------------------
FUNCTION To_Upper1 ( CONSTANT val : IN String
) RETURN STRING IS
VARIABLE result : string (1 TO val'LENGTH) := val;
VARIABLE ch : character;
BEGIN
FOR i IN 1 TO val'LENGTH LOOP
ch := result(i);
EXIT WHEN ((ch = NUL) OR (ch = nul));
IF ( ch >= 'a' and ch <= 'z') THEN
result(i) := CHARACTER'VAL( CHARACTER'POS(ch)
- CHARACTER'POS('a')
+ CHARACTER'POS('A') );
END IF;
END LOOP;
RETURN result;
END To_Upper1;
--+-----------------------------------------------------------------------------
--| Function Name : From_HexString1
--|
--| Overloading : None
--|
--| Purpose : Convert from a Hex String to a bit_vector.
--|
--| Parameters :
--| str - input , Hex string to be converted,
--|
--| Result : bit_vector
--|
--| NOTE :
--|
--| Use :
--| VARIABLE b_vect : bit_vector( 15 DOWNTO 4) ;
--|
--| b_vect := From_HexString1 (" 3DD 1010");
--| This statement will set b_vect equal to "001111011101".
--|
--|-----------------------------------------------------------------------------
FUNCTION From_HexString1 ( CONSTANT str : IN STRING
) RETURN bit_vector IS
CONSTANT len : Integer := 4 * str'LENGTH;
CONSTANT hex_dig_len : Integer := 4;
VARIABLE str_copy : STRING (1 TO str'LENGTH) := To_Upper1(str);
VARIABLE index : Natural;
VARIABLE ch : character;
VARIABLE i, idx : Integer;
VARIABLE invalid : boolean := false;
VARIABLE r : bit_vector(1 TO len) ;
VARIABLE result : bit_vector(len - 1 DOWNTO 0) ;
CONSTANT BIT_ZERO : bit_vector(1 to 4) := "0000";
CONSTANT BIT_ONE : bit_vector(1 to 4) := "0001";
CONSTANT BIT_TWO : bit_vector(1 to 4) := "0010";
CONSTANT BIT_THREE : bit_vector(1 to 4) := "0011";
CONSTANT BIT_FOUR : bit_vector(1 to 4) := "0100";
CONSTANT BIT_FIVE : bit_vector(1 to 4) := "0101";
CONSTANT BIT_SIX : bit_vector(1 to 4) := "0110";
CONSTANT BIT_SEVEN : bit_vector(1 to 4) := "0111";
CONSTANT BIT_EIGHT : bit_vector(1 to 4) := "1000";
CONSTANT BIT_NINE : bit_vector(1 to 4) := "1001";
CONSTANT BIT_TEN : bit_vector(1 to 4) := "1010";
CONSTANT BIT_ELEVEN : bit_vector(1 to 4) := "1011";
CONSTANT BIT_TWELVE : bit_vector(1 to 4) := "1100";
CONSTANT BIT_THIRTEEN: bit_vector(1 to 4) := "1101";
CONSTANT BIT_FOURTEEN: bit_vector(1 to 4) := "1110";
CONSTANT BIT_FIFTEEN : bit_vector(1 to 4) := "1111";
BEGIN
-- Check for null input
IF (str'LENGTH = 0) THEN
assert false
report " From_HexString1 --- input string has zero length ";
RETURN "";
ELSIF (str(str'LEFT) = NUL) THEN
assert false
report " From_HexString1 --- input string has nul character"
& " at the LEFT position "
severity ERROR;
RETURN ""; -- null bit_vector
END IF;
-- find the position of the first non_white character
index := Find_NonBlank1(str_copy);
IF (index > str'length) THEN
assert false
report " From_HexString1 --- input string is empty ";
RETURN "";
ELSIF (str_copy(index)=NUL) THEN
assert false report " From_HexString1 -- first non_white character is a NUL ";
RETURN "";
END IF;
i := 0;
FOR idx IN index TO str'length LOOP
ch := str_copy(idx);
EXIT WHEN ((Is_White1(ch)) OR (ch = NUL));
CASE ch IS
WHEN '0' => r(i+1 TO i+ hex_dig_len) := BIT_ZERO;
WHEN '1' => r(i+1 TO i+ hex_dig_len) := BIT_ONE;
WHEN '2' => r(i+1 TO i+ hex_dig_len) := BIT_TWO;
WHEN '3' => r(i+1 TO i+ hex_dig_len) := BIT_THREE;
WHEN '4' => r(i+1 TO i+ hex_dig_len) := BIT_FOUR;
WHEN '5' => r(i+1 TO i+ hex_dig_len) := BIT_FIVE;
WHEN '6' => r(i+1 TO i+ hex_dig_len) := BIT_SIX;
WHEN '7' => r(i+1 TO i+ hex_dig_len) := BIT_SEVEN;
WHEN '8' => r(i+1 TO i+ hex_dig_len) := BIT_EIGHT;
WHEN '9' => r(i+1 TO i+ hex_dig_len) := BIT_NINE;
WHEN 'A' | 'a' => r(i+1 TO i+ hex_dig_len) := BIT_TEN;
WHEN 'B' | 'b' => r(i+1 TO i+ hex_dig_len) := BIT_ELEVEN;
WHEN 'C' | 'c' => r(i+1 TO i+ hex_dig_len) := BIT_TWELVE;
WHEN 'D' | 'd' => r(i+1 TO i+ hex_dig_len) := BIT_THIRTEEN;
WHEN 'E' | 'e' => r(i+1 TO i+ hex_dig_len) := BIT_FOURTEEN;
WHEN 'F' | 'f' => r(i+1 TO i+ hex_dig_len) := BIT_FIFTEEN;
WHEN NUL => exit;
WHEN OTHERS => -- a non binary value was passed
invalid := TRUE;
ASSERT FALSE
REPORT "From_HexString1(str(" & i_to_str(idx) & ") => "
& ch & ") is an invalid character"
SEVERITY ERROR;
END CASE;
i := i + hex_dig_len;
END LOOP;
-- check for invalid character in the string
if ( invalid ) THEN
r(1 TO i) := (OTHERS => '0');
end if;
result(i - 1 DOWNTO 0) := r(1 TO i);
return result(i - 1 DOWNTO 0); -- return slice of result
END;
-------------------------------------------------------------------------------
-- Function Name : RegFill1
-- 1.7.4
-- Overloading : None
--
-- Purpose : Fill an std_logic_vector with a given value
--
-- Parameters :
-- SrcReg - input std_logic_vector, the logic vector to be read.
-- DstLength - input NATURAL, length of the return logic vector.
-- FillVal - input std_ulogic, default is '0'
--
-- Result : std_logic_vector of length DstLength
--
-- NOTE : The length of the return logic vector is specified by the
-- parameter 'DstLength'. The input logic vector will
-- be filled with the FillVal
--
-- Use :
-- VARIABLE vect : std_logic_vector ( 15 DOWNTO 0 );
-- vect := RegFill1 ( "00000101", 16, 'U');
--
-- See Also : SignExtend
-------------------------------------------------------------------------------
FUNCTION RegFill1 ( CONSTANT SrcReg : IN std_logic_vector;
CONSTANT DstLength : IN NATURAL;
CONSTANT FillVal : IN std_ulogic := '0'
) RETURN std_logic_vector IS
CONSTANT reslen : INTEGER := DstLength;
VARIABLE result : std_logic_vector (reslen - 1 DOWNTO 0) := (OTHERS => '0');
VARIABLE reg : std_logic_vector (SrcReg'LENGTH - 1 DOWNTO 0) := SrcReg;
BEGIN
-- null range check
IF (SrcReg'LENGTH = 0) THEN
IF (DstLength = 0) THEN
ASSERT FALSE
REPORT " RegFill1 --- input has null range and" &
" Destination also has null range. "
SEVERITY ERROR;
RETURN result ;
ELSE
ASSERT FALSE
REPORT " RegFill1 --- input has null range"
SEVERITY ERROR;
result := (OTHERS => FillVal);
RETURN result ;
END IF;
ELSIF (DstLength = 0) THEN
ASSERT false
REPORT "RegFill1 --- Destination has null range "
SEVERITY ERROR;
RETURN result;
ELSIF (DstLength <= SrcReg'LENGTH) THEN
-- no need to sign extend
ASSERT (DstLength = SrcReg'LENGTH)
REPORT " RegFill1 --- Destination length is less than source"
SEVERITY ERROR;
RETURN reg; -- return the input data without any change
ELSE
result(SrcReg'LENGTH - 1 DOWNTO 0) := reg;
-- Fill the MSB's of result with the given fill value.
For i IN reslen - 1 DOWNTO SrcReg'LENGTH Loop
result(i) := FillVal;
END LOOP;
END IF;
-- convert to X01
result := To_X01(result);
-- That's all
RETURN result;
END;
--+-----------------------------------------------------------------------------
--| Function Name : bv_To_StdLogicVector
--|
--| Overloading :
--|
--| Purpose : Translate a BIt_VECTOR into an std_logic_vector.
--|
--| Parameters : SrcVect - input bit_vector , the value to be
--| translated.
--| width - input NATURAL, length of the return vector.
--| Default is IntegerBitLength (Machine integer length).
--|
--| Result : Std_logic_vector.
--|
--| NOTE : ****** this function not visible to the user **********
--|-----------------------------------------------------------------------------
-- **** function modified so as not to produce an assertion for a zero length vector
FUNCTION bv_To_StdLogicVector ( CONSTANT SrcVect : IN Bit_Vector;
CONSTANT width : IN Natural := 0
) RETURN Std_Logic_Vector IS
VARIABLE len : INTEGER := SrcVect'LENGTH;
VARIABLE result : Std_Logic_Vector(width - 1 DOWNTO 0) := (OTHERS=>'0');
VARIABLE loc_res : Std_Logic_Vector(len - 1 DOWNTO 0) := (OTHERS =>'0');
VARIABLE vect_copy : Bit_Vector(len - 1 DOWNTO 0) := SrcVect;
BEGIN
IF (SrcVect'LENGTH = 0) THEN
return loc_res;
ELSE
FOR i IN 0 TO len - 1 LOOP
CASE vect_copy(i) IS
WHEN '0' =>
loc_res(i) := '0';
WHEN '1' =>
loc_res(i) := '1';
END CASE;
END LOOP;
IF (width = 0) THEN
return loc_res;
ELSIF (width <= SrcVect'LENGTH) THEN
result := loc_res(width - 1 DOWNTO 0);
ELSIF (width > SrcVect'LENGTH) THEN
result := RegFill1(loc_res, width, '0');
END IF;
RETURN result;
END IF;
END;
FUNCTION bv_to_hexstr ( CONSTANT val : IN BIT_VECTOR
) RETURN STRING IS
CONSTANT hex_len : integer := (val'LENGTH + 3) / 4;
VARIABLE bin_str : STRING(1 to val'LENGTH);
VARIABLE hex_str : STRING(1 to hex_len);
VARIABLE hex_char : STRING(1 to 4);
VARIABLE bit_index : integer;
VARIABLE extended_bin_str : STRING(1 to hex_len * 4) := (others => '0');
BEGIN
bin_str := v_to_str (val);
if ( (val'LENGTH mod 4) /= 0 ) then
extended_bin_str ( 5 - (val'LENGTH mod 4) to hex_len * 4 ) := bin_str;
else
extended_bin_str := bin_str;
end if;
FOR i IN 1 TO hex_len LOOP
bit_index := ((i - 1) * 4) + 1;
hex_char := extended_bin_str(bit_index To bit_index + 3);
CASE hex_char IS
WHEN "0000" => hex_str(i) := '0';
WHEN "0001" => hex_str(i) := '1';
WHEN "0010" => hex_str(i) := '2';
WHEN "0011" => hex_str(i) := '3';
WHEN "0100" => hex_str(i) := '4';
WHEN "0101" => hex_str(i) := '5';
WHEN "0110" => hex_str(i) := '6';
WHEN "0111" => hex_str(i) := '7';
WHEN "1000" => hex_str(i) := '8';
WHEN "1001" => hex_str(i) := '9';
WHEN "1010" => hex_str(i) := 'A';
WHEN "1011" => hex_str(i) := 'B';
WHEN "1100" => hex_str(i) := 'C';
WHEN "1101" => hex_str(i) := 'D';
WHEN "1110" => hex_str(i) := 'E';
WHEN "1111" => hex_str(i) := 'F';
WHEN OTHERS => null;
END CASE;
END LOOP;
return (hex_str);
END;
---------------------------------------------------------------------------
-- Function Name : vector_size
--
-- PURPOSE : to determine the maximum number of bits needed to
-- represent an integer
--
-- Parameters : int - integer whose bit width is determined
--
-- Returned Value : NATURAL - # of bits needed
--
---------------------------------------------------------------------------
function vector_size ( Constant int : IN integer ) return natural is
variable i : integer := int;
variable size : integer := 0;
begin
while i > 0 loop
i := i / 2;
size := size + 1;
end loop;
return size;
end;
---------------------------------------------------------------------------
-- Function Name : address_trans
--
-- Purpose : to translate an address in vector form to a
-- NATURAL
--
-- Parameters : addr - address to be translated
--
-- Returned Value : NATURAL - address as a natural number
--
-- NOTE : ***** this procedure is NOT user visible *******
--
-- Use : address_trans(addr)
---------------------------------------------------------------------------
Function address_trans ( Constant mem_length : IN POSITIVE;
Constant addr : IN std_logic_vector
) return NATURAL is
Variable nad, power : NATURAL;
Variable uonce : BOOLEAN := TRUE;
Variable xonce : BOOLEAN := TRUE;
Variable vect_size : integer := vector_size(mem_length - 1);
Variable talias_addr : std_logic_vector(addr'length - 1 downto 0) := To_UX01(addr);
Variable alias_addr : std_logic_vector(vect_size - 1 downto 0) := (others => To_StdULogic(ADDRESS_X_MAP));
Variable temp_vect : bit_vector(vect_size - 1 downto 0);
begin
nad := 0;
power := 1;
alias_addr( minimum(vect_size, addr'length) - 1 downto 0) :=
talias_addr( minimum(vect_size,addr'length) - 1 downto 0 );
assert ( (vect_size >= addr'length) or NOT MEM_WARNINGS_ON )
report "Bit width of address vector greater than that needed to access the entire memory."
& LF & SPACESTR & "passed address bit width: " & i_to_str(addr'length)
& LF & SPACESTR & "required address bit width: " & i_to_str(vect_size)
severity WARNING;
assert ( (vect_size <= addr'length) or NOT MEM_WARNINGS_ON )
report "Bit width of address vector less than that needed to access the entire memory."
& LF & SPACESTR & "Resulting X's being mapped to: " & to_str(ADDRESS_X_MAP)
& LF & SPACESTR & "passed address bit width: " & i_to_str(addr'length)
& LF & SPACESTR & "required address bit width: " & i_to_str(vect_size)
severity WARNING;
for i IN 0 to vect_size - 1 loop
if ((alias_addr(i) = 'U') and MEM_WARNINGS_ON and uonce) then
uonce := FALSE;
assert FALSE
report "Address contains a U - it is being mapped to: " & to_str(ADDRESS_U_MAP)
severity WARNING;
end if;
if ((alias_addr(i) = 'X') and MEM_WARNINGS_ON and xonce) then
xonce := FALSE;
assert false
report "Address contains an X - it is being mapped to: " & to_str(ADDRESS_X_MAP)
severity WARNING;
end if;
temp_vect(i) := ADDRESS_MAP(alias_addr(i));
nad := nad + (power * bit'pos(temp_vect(i)));
power := power * 2;
end loop;
return nad;
end;
Function address_trans ( Constant mem_length : IN POSITIVE;
Constant addr : IN std_ulogic_vector
) return NATURAL is
Variable nad, power : NATURAL;
Variable uonce : BOOLEAN := TRUE;
Variable xonce : BOOLEAN := TRUE;
Variable talias_addr : std_ulogic_vector(addr'length - 1 downto 0) := To_UX01(addr);
Variable vect_size : integer := vector_size(mem_length - 1);
Variable alias_addr : std_ulogic_vector(vect_size - 1 downto 0) := (others => To_StdULogic(ADDRESS_X_MAP));
Variable temp_vect : bit_vector(vect_size - 1 downto 0);
begin
nad := 0;
power := 1;
alias_addr( minimum(vect_size, addr'length) - 1 downto 0) :=
talias_addr( minimum(vect_size,addr'length) - 1 downto 0);
assert ( (vect_size >= addr'length) or NOT MEM_WARNINGS_ON )
report "Bit width of address vector greater than that needed to access the entire memory."
& LF & SPACESTR & "passed address bit width: " & i_to_str(addr'length)
& LF & SPACESTR & "required address bit width: " & i_to_str(vect_size)
severity WARNING;
assert ( (vect_size <= addr'length) or NOT MEM_WARNINGS_ON )
report "Bit width of address vector less than that needed to access the entire memory."
& LF & SPACESTR & "Resulting X's being mapped to: " & to_str(ADDRESS_X_MAP)
& LF & SPACESTR & "passed address bit width: " & i_to_str(addr'length)
& LF & SPACESTR & "required address bit width: " & i_to_str(vect_size)
severity WARNING;
for i IN 0 to vect_size - 1 loop
if ((alias_addr(i) = 'U') and MEM_WARNINGS_ON and uonce) then
uonce := FALSE;
assert false
report "Address contains a U - it is being mapped to: " & to_str(ADDRESS_U_MAP)
severity WARNING;
end if;
if ((alias_addr(i) = 'X') and MEM_WARNINGS_ON and xonce) then
xonce := FALSE;
assert false
report "Address contains an X - it is being mapped to: " & to_str(ADDRESS_X_MAP)
severity WARNING;
end if;
temp_vect(i) := ADDRESS_MAP(alias_addr(i));
nad := nad + (power * bit'pos(temp_vect(i)));
power := power * 2;
end loop;
return nad;
end;
Function address_trans ( Constant mem_length : IN POSITIVE;
Constant addr : IN bit_vector
) return NATURAL is
Variable nad, power : NATURAL;
Variable vect_size : integer := vector_size(mem_length - 1);
Variable talias_addr : bit_vector(addr'length - 1 downto 0) := addr;
Variable alias_addr : bit_vector(vect_size - 1 downto 0) := (others => ADDRESS_X_MAP);
begin
nad := 0;
power := 1;
alias_addr( minimum(vect_size, addr'length) - 1 downto 0) :=
talias_addr( minimum(vect_size,addr'length) - 1 downto 0);
if ( MEM_WARNINGS_ON and (vect_size > addr'length) ) then
assert false
report "Bit width of address vector smaller than that needed to access the entire memory."
& LF & SPACESTR & "Resulting X's being mapped to: " & to_str(ADDRESS_X_MAP)
& LF & SPACESTR & "passed address bit width: " & i_to_str(addr'length)
& LF & SPACESTR & "required address bit width: " & i_to_str(vect_size)
severity WARNING;
elsif ( MEM_WARNINGS_ON and (vect_size < addr'length) ) then
assert false
report "Bit width of address vector larger than that needed to access the entire memory."
& LF & SPACESTR & "passed address bit width: " & i_to_str(addr'length)
& LF & SPACESTR & "required address bit width: " & i_to_str(vect_size)
severity WARNING;
end if;
for i in 0 to vect_size - 1 loop
nad := nad + (power * bit'pos(alias_addr(i)));
power := power * 2;
end loop;
return nad;
end;
---------------------------------------------------------------------------
-- Procedure Name : allocate_row
--
-- Purpose : to allocate a row of memory and initialize it
-- to the default value
--
-- Parameters : mem_id - ptr to memory data structure
-- row - row to be allocated
--
-- NOTE : allocate data space for 1 row of memory
-- ****** this procedure is NOT user visible *******
--
-- Use : allocate_row (ram1, 5);
---------------------------------------------------------------------------
procedure allocate_row ( Variable mem_id : INOUT mem_id_type;
Constant row : IN NATURAL
) is
subtype constrained_matrix is
row_matrix (0 to mem_id.columns-1, 0 to mem_id.width-1);
variable ptr : rowptr_type;
variable i, j : integer;
begin
if mem_id.row_data_ptr(row).all_xs then -- if row should be filled with X's then do so
mem_id.row_data_ptr(row).rowptr := new constrained_matrix'( others => (others => 'X'));
else -- otherwise, row should be filled with the default
mem_id.row_data_ptr(row).rowptr := new constrained_matrix;
ptr := mem_id.row_data_ptr(row).rowptr;
for i in 0 to mem_id.columns - 1 loop
for j in 0 to mem_id.width - 1 loop
ptr(i,j) := To_UX01(mem_id.default(j));
end loop;
end loop;
end if;
-- no longer necessary to indicate that its filled with X's
mem_id.row_data_ptr(row).all_xs := FALSE;
end;
---------------------------------------------------------------------------
-- Procedure Name : validate_row
--
-- Purpose : if memory is a DRAM then check if refresh period
-- has expired. If so, and space allocated, then
-- reset all locations to X's. This is done by setting
-- the filed all_xs to TRUE
--
-- Parameters : mem_id - pointer to memory data structure
-- row - row to be validated
--
-- NOTE : ****** this procedure is NOT user visible *******
--
-- Use : validate_row (dram1, 5);
---------------------------------------------------------------------------
Procedure validate_row ( Variable mem_id : INOUT mem_id_type;
Constant row : IN NATURAL
) IS
Variable rowdat : row_data_ptr_type := mem_id.row_data_ptr;
Variable i, j : INTEGER;
begin
-- check that it is a dram and that refresh period has expired
if ( (mem_id.memory_type = DRAM) and (NOW > (rowdat(row).last_refresh + mem_id.refresh_period)) ) then
if rowdat(row).all_xs then
-- if all_xs is true already then only an assertion is necessray
assert NOT MEM_WARNINGS_ON
report "Refresh time has expired on row " & i_to_str(row) & " of memory: "
& pstr(mem_id.name(1 to mem_id.name'length)) & LF & SPACESTR & "however, row was not filled with valid data."
severity WARNING;
elsif rowdat(row).rowptr = NULL then
-- if all_xs is false and no space has been allocated for this row then it must be at default
-- set all_xs to true and make an assertion
rowdat(row).all_xs := TRUE;
assert NOT MEM_WARNINGS_ON
report "Refresh time has expired on row " & i_to_str(row) & " of memory: "
& pstr(mem_id.name(1 to mem_id.name'length)) & LF & SPACESTR & "Row was filled with default value."
severity WARNING;
else
-- row has valid, non-default data in it
-- set all_xs to true and deallocate space for row
rowdat(row).all_xs := TRUE;
deallocate(mem_id.row_data_ptr(row).rowptr);
mem_id.row_data_ptr(row).rowptr := NULL;
assert NOT MEM_WARNINGS_ON
report "Refresh time has expired on row " & i_to_str(row) & " of memory: "
& pstr(mem_id.name(1 to mem_id.name'length)) & LF & SPACESTR & "Data is lost."
severity WARNING;
end if;
end if;
end;
---------------------------------------------------------------------------
-- Procedure Name : refresh_row
--
-- Purpose : if memory is a DRAM then update the last_refresh
-- time along with last time used (last_init)
--
-- Parameters : mem_id - pointer to memory data structure
-- row - row to be refreshed
--
-- NOTE : ****** this procedure is NOT user visible *******
--
-- Use : refresh_row (dram1, 5);
---------------------------------------------------------------------------
Procedure refresh_row ( VARIABLE mem_id : INOUT mem_id_type;
Constant row : IN NATURAL
) is
begin
if ( (mem_id.memory_type = DRAM) and (mem_id.last_init + mem_id.refresh_period >= NOW)) then
mem_id.row_data_ptr(row).last_refresh := NOW;
mem_id.last_init := NOW;
end if;
end;
---------------------------------------------------------------------------
-- Function Name : SRAM_Initialize
--
-- Purpose : To create the data structure used to store a
-- static RAM and to initialize it
--
-- Parameters : name - string used to represent the memory
-- length - the number of "words" in the memory
-- width - the length of a "word" of memory
-- default_word - value to which each word of
-- memory should be initialized
--
-- RETURNED VALUE : mem_id_type - pointer to memory record
--
-- NOTE : initially the data structure is empty with no
-- space being allocated for the memory
--
-- Use : SRAM_Initialize (sram_l1,"lsb_of_RAM",1048576,1);
---------------------------------------------------------------------------
impure Function SRAM_Initialize ( Constant name : IN string;
Constant length : IN POSITIVE;
Constant width : IN POSITIVE;
Constant default_word : IN std_logic_vector
) return mem_id_type IS
Variable i, name_len : INTEGER;
Variable mem_id : mem_id_type;
Variable alias_name : string (1 to name'length) := name;
begin
-- create and initialize data structure
mem_id := new mem_id_rtype '( memory_type => SRAM,
refresh_period => 0.0 ns,
last_init => 0.0 ns,
counter => 0,
name => NULL,
rows => 1,
columns => SRAM_COL_SIZE,
width => width,
length => length,
row_data_ptr => NULL,
default => NULL
);
if ( (length mod SRAM_COL_SIZE) /= 0) then
mem_id.rows := (length/SRAM_COL_SIZE) + 1;
else
mem_id.rows := length/SRAM_COL_SIZE;
end if;
-- store name of memory
name_len := 1;
while ( (name_len <= alias_name'length) and (alias_name(name_len) /= nul)) loop
name_len := name_len + 1;
end loop;
name_len := name_len - 1;
mem_id.name := new string(1 to name_len);
for i in 1 to name_len loop
mem_id.name(i) := alias_name(i);
end loop;
-- create and initialize data structure for rows
mem_id.row_data_ptr := new row_data(0 to mem_id.rows-1);
for i in 0 to mem_id.rows - 1 loop
mem_id.row_data_ptr(i) := (last_refresh => NOW,
rowptr => NULL,
all_xs => FALSE
);
end loop;
-- set default word
mem_id.default := new std_logic_vector(mem_id.width - 1 downto 0);
if (default_word'length /= mem_id.width) then
assert (default_word'length = 0)
report "SRAM_INITIALIZE: Default word width does not match word width of memory: "
& pstr(mem_id.name(1 to mem_id.name'length)) & LF & SPACESTR
& "default will be set to a word filled with 'U'"
severity ERROR;
for i in 0 to mem_id.width - 1 loop
mem_id.default(i) := 'U';
end loop;
else
mem_id.default.all := To_X01(default_word);
end if;
return mem_id;
end;
impure Function SRAM_Initialize ( Constant name : IN string;
Constant length : IN POSITIVE;
Constant width : IN POSITIVE;
Constant default_word : IN std_ulogic_vector
) return mem_id_type IS
Variable mem_id : mem_id_type;
begin
mem_id := SRAM_Initialize ( name,
length,
width,
std_logic_vector (default_word)
);
return mem_id;
end;
---------------------------------------------------------------------------
-- Procedure Name : Mem_Wake_Up
--
-- Purpose : to initialize a DRAM for use
--
-- Parameters : mem_id - ptr to memory data structure
--
-- NOTE : a DRAM must be woken up before it can be used or if
-- the refresh period passes without any operations
--
-- Use : Mem_Wake_Up (ROM_chip_1);
---------------------------------------------------------------------------
Procedure Mem_Wake_Up (Variable mem_id : INOUT mem_id_type) IS
begin
if (mem_id.memory_type = DRAM) then
mem_id.last_init := NOW;
else
assert false
report "Mem_Wake_Up: Memory: " & pstr(mem_id.name(1 to mem_id.name'length)) & " is a ROM or an SRAM."
& LF & SPACESTR &
"This operation only valid for DRAM's,operation ignored."
severity ERROR;
end if;
end;
---------------------------------------------------------------------------
-- Procedure Name : Mem_Basic_Write
--
-- Purpose : To write a "word" to memory
-- this procedure will write to a ROM
--
-- Parameters : mem_id - ptr to memory data structure
-- address - address to read from
-- data - "word" to be written to memory
-- must first be converted to X01
-- ingore_rom - if true then write even if ROM
--
-- NOTE : a write refreshes row of a DRAM
-- ***** this procedure not user visible *******
--
---------------------------------------------------------------------------
Procedure Mem_Basic_Write ( Variable mem_id : INOUT mem_id_type;
Constant address : IN NATURAL;
Constant data : IN std_logic_vector;
Constant ignore_rom : IN Boolean := FALSE
) IS
Constant alias_data : std_logic_vector (data'length - 1 downto 0) := data;
variable row, column, i : integer;
variable short_ptr : rowptr_type;
variable mem_word : std_logic_vector (mem_id.width - 1 downto 0)
:= (others => 'X');
begin
if ( (mem_id.memory_type /= ROM) or (ignore_rom) ) then -- make sure its not a rom
if address < mem_id.length then -- check that its a valid address
-- if memory is a dram make sure that it has been woken up
if ( (mem_id.memory_type /= DRAM) or (mem_id.last_init + mem_id.refresh_period >= NOW)) then
-- calculate row and column
row := address/mem_id.columns;
column := address mod mem_id.columns;
-- validate address and report if refresh time exceeded
validate_row (mem_id, row);
-- refresh the row
refresh_row (mem_id, row);
-- if row never allocated then allocate it
if (mem_id.row_data_ptr(row).rowptr = NULL) then
allocate_row(mem_id, row);
end if;
-- handle data of different width than memory
-- if data has less bits than memory than MSBs become Xs
assert ( (data'length = mem_id.width) OR NOT MEM_WARNINGS_ON)
report "Mem_Write: passed data size does not match word size"
& " of mem: " & pstr(mem_id.name(1 to mem_id.name'length)) & LF & SPACESTR &
"passed data size: " & i_to_str(data'length) & " bits"
& LF & SPACESTR & "memory word size: " &
i_to_str(mem_id.width) & " bits"
severity WARNING;
if (mem_id.width >= data'length) then
mem_word (data'length - 1 downto 0) := alias_data;
else
mem_word := To_X01(alias_data(mem_id.width-1 downto 0));
end if;
-- write data to memory
short_ptr := mem_id.row_data_ptr(row).rowptr;
for i IN 0 to mem_id.width - 1 loop
-- mem_id.row_data_ptr(row).rowptr(column,i) := mem_word(i);
-- *************************************
-- this is a bug work around for synopsys
-- replaces line commented out above
short_ptr(column,i) := mem_word(i);
-- end bug fix
-- *************************************
end loop;
else
assert false
report "Mem_Write: Device wake-up time limit exceeded for memory: "
& pstr(mem_id.name(1 to mem_id.name'length)) & LF & SPACESTR &
"Operation ignored, device must be woken up."
severity WARNING;
end if;
else
assert false
report "Mem_Write: Passed address exceeds address "
& "range of mem: " & pstr(mem_id.name(1 to mem_id.name'length)) & LF & SPACESTR
& "specified address: " & i_to_str(address) & LF &
SPACESTR & "address range: 0 to " & i_to_str(mem_id.length - 1)
severity ERROR;
end if;
else
assert false
report "Mem_Write: Attempt to write to memory: " & pstr(mem_id.name(1 to mem_id.name'length))
& LF & SPACESTR & "Writes to ROMs are not allowed. Operation ignored."
severity ERROR;
end if;
end;
---------------------------------------------------------------------------
-- Procedure Name : Mem_All_Reset
--
-- Purpose : To set the contents of a memory to some predetermined
-- value. The locations to reset are specified by a
-- range.
--
-- Parameters : mem_id - ptr to memory data structure
-- reset_value - value to reset memory to
-- start_addr - starting address within memory
-- end_addr - ending address withim memory
-- ROM_too - allows roms to be reset as well if true
--
-- NOTE : works for all mem types. call by Mem_Reset
-- **** NOT USER VISIBLE *****
--
-- Use : Mem_ALL_Reset (RAM1, "1010", 2048, 4096, FALSE);
---------------------------------------------------------------------------
procedure Mem_ALL_Reset ( Variable mem_id : INOUT mem_id_type;
Constant reset_value : IN std_logic_vector;
Constant start_addr : IN NATURAL := 0;
Constant end_addr : IN NATURAL := integer'high;
Constant ROM_too : IN BOOLEAN := FALSE
) IS
Variable real_end : NATURAL := end_addr;
Variable start_row, start_col, end_row, end_col : NATURAL;
Variable row, col, rstart_col, rend_col, bit_pos : NATURAL;
Variable row_ptr : rowptr_type;
Variable alias_reset : std_logic_vector (mem_id.width - 1 downto 0) := (others => 'U');
Variable xvector : std_logic_vector (mem_id.width - 1 downto 0) := (others => 'X');
Variable i : integer;
begin
if (reset_value'length /= mem_id.width) then
assert (reset_value'length <= 0)
report "Mem_Reset: reset value of memory does not match memory width " &
pstr(mem_id.name(1 to mem_id.name'length)) & LF & SPACESTR
& "Resetting memory all all 'U's."
severity ERROR;
alias_reset := (others => 'U');
else
alias_reset := To_X01(reset_value);
end if;
if ( (mem_id.memory_type /= ROM) or ROM_too) then -- make sure its not a rom
if (end_addr < start_addr) then -- check address ranges
assert false
report "Mem_Reset: ending address is less than starting address."
& LF & SPACESTR & "No operation performed."
severity ERROR;
elsif (start_addr >= mem_id.length) then
assert false
report "Mem_Reset: starting address outside of address "
& "range of memory: " & pstr(mem_id.name(1 to mem_id.name'length))
& LF & SPACESTR & "No operation performed."
severity ERROR;
else
If (end_addr >= mem_id.length) then
assert (end_addr = integer'high)
report "Mem_Reset: ending address outside address "
& "range of memory: " & pstr(mem_id.name(1 to mem_id.name'length)) & LF & SPACESTR
& "Memory will be refreshed until end is reached."
severity WARNING;
real_end := mem_id.length - 1;
end if;
-- if memory is a dram, then wake it up
if mem_id.memory_type = DRAM then
Mem_Wake_Up (mem_id);
end if;
-- calculate row and column of starting address
start_row := start_addr/mem_id.columns;
start_col := start_addr mod mem_id.columns;
-- calculate row and column of ending address
end_row := real_end/mem_id.columns;
end_col := real_end mod mem_id.columns;
-- starting column of row presently being written to
rstart_col := start_col;
for row in start_row to end_row loop
if row = end_row then -- set ending collumn of row presently being written to
rend_col := end_col;
else
rend_col := mem_id.columns - 1;
end if;
-- check for expired time period on row
if ( (rstart_col > 0) or (rend_col < mem_id.columns - 1) ) then
-- it is only necessary to validate row if only part of the row is being reset
validate_row (mem_id, row);
else
-- entire row being reset, check for expired refresh period
assert ( (mem_id.memory_type /= DRAM) or
((mem_id.row_data_ptr(row).last_refresh + mem_id.refresh_period) >= NOW)
or NOT MEM_WARNINGS_ON )
report "Mem_Reset: refresh period on row " &
i_to_str(row) & " has expired but"
& LF & SPACESTR
& "no data lost since entire row is being reset"
severity WARNING;
end if;
-- if collumn not allocated & fill value is not the default or all x's then allocate
if ( (mem_id.row_data_ptr(row).rowptr = NULL) and (alias_reset /= mem_id.default.all)
and (alias_reset /= xvector) ) then
allocate_row (mem_id, row);
-- if filling partial row with default and currently is Xs then allocate
elsif ( (mem_id.row_data_ptr(row).rowptr = NULL) and (alias_reset = mem_id.default.all)
and mem_id.row_data_ptr(row).all_xs and
( (rstart_col /= 0) or (rend_col /= mem_id.columns - 1)) ) then
allocate_row (mem_id, row);
-- if filling partial row with Xs and currently is default then allocate
elsif ( (mem_id.row_data_ptr(row).rowptr = NULL) and (alias_reset = xvector)
and (NOT mem_id.row_data_ptr(row).all_xs) and
( (rstart_col /= 0) or (rend_col /= mem_id.columns - 1)) ) then
allocate_row (mem_id, row);
end if;
-- if filling entire collumn with default then deallocate it
If ( (alias_reset = mem_id.default.all) and (rstart_col = 0) and
(rend_col = mem_id.columns - 1) ) then
if (mem_id.row_data_ptr(row).rowptr /= NULL) then
Deallocate (mem_id.row_data_ptr(row).rowptr);
mem_id.row_data_ptr(row).rowptr := NULL;
end if;
mem_id.row_data_ptr(row).all_xs := FALSE;
-- if filling entire collumn with X's then deallocate it
elsif ( (alias_reset = xvector) and (rstart_col = 0) and (rend_col = mem_id.columns - 1) ) then
if (mem_id.row_data_ptr(row).rowptr /= NULL) then
Deallocate (mem_id.row_data_ptr(row).rowptr);
mem_id.row_data_ptr(row).rowptr := NULL;
end if;
mem_id.row_data_ptr(row).all_xs := TRUE;
end if;
-- fill up the row if the entire row isn't being filled with Xs or default
row_ptr := mem_id.row_data_ptr(row).rowptr;
if (row_ptr /= NULL) then
for col in rstart_col to rend_col loop
for bit_pos in 0 to mem_id.width - 1 loop
row_ptr(col,bit_pos) := alias_reset(bit_pos);
end loop;
end loop;
end if;
rstart_col := 0; -- start at beginning of next collumn
refresh_row (mem_id, row); -- refresh the current row
end loop;
end if;
else
assert false
report "Mem_Reset: Reset of ROM not allowed. Operation ignored"
severity ERROR;
end if;
end;
--------------------------------------------------------------------------------------------------
-- The following functions and procedures are used in the recursive descent parser that is used
-- to parse the memory files.
-- ***************************** THESE ROUTINES ARE NOTE USER VISIBLE ***********************
--------------------------------------------------------------------------------------------------
-- return true if character is upper case character
function is_upper_case ( Constant ch : IN CHARACTER ) return BOOLEAN is
begin
return ( (ch >= 'A') and (ch <= 'Z') );
end;
-- return true if character is lower case character
function is_lower_case ( Constant ch : IN CHARACTER ) return BOOLEAN is
begin
return ( (ch >= 'a') and (ch <= 'z') );
end;
-- return true if character is a decimal digit
function is_dec_digit ( Constant ch : IN CHARACTER ) return BOOLEAN is
begin
return ( (ch >= '0') and (ch <= '9'));
end;
-- skip over blanks and tabs
-- read characters and numbers until space, tab, or symbol is encountered
-- get special identifiers such as :, --, or ..
-- convert lower case to upper case
-- update buffer index to point to first character after identifier that was read
procedure read_word ( Variable out_str : OUT STRING;
Constant in_str : IN STRING;
Variable b_ind : INOUT INTEGER
) is
Variable out_ind : integer := 1;
begin
-- skip over spaces and tabs
while ( ( (in_str(b_ind) = ' ') or (in_str(b_ind) = HT) ) and (b_ind <= StrLen1(in_str))) loop
b_ind := b_ind + 1;
end loop;
if ( b_ind > StrLen1(in_str) ) then -- return if blank line
out_str(out_ind) := NUL;
return;
end if;
-- check for --
if ( (StrLen1(in_str) >= b_ind+1) and (in_str(b_ind) = '-') and (in_str(b_ind + 1) = '-') ) then
out_str(1) := '-';
out_str(2) := '-';
out_str(3) := NUL;
b_ind := b_ind + 2;
return;
end if;
-- check for ..
if ( (StrLen1(in_str) >= b_ind+1) and (in_str(b_ind) = '.') and (in_str(b_ind + 1) = '.') ) then
out_str(1) := '.';
out_str(2) := '.';
out_str(3) := NUL;
b_ind := b_ind + 2;
return;
end if;
-- check for :
if ( (StrLen1(in_str) >= b_ind) and (in_str(b_ind) = ':') ) then
out_str(1) := ':';
out_str(2) := NUL;
b_ind := b_ind + 1;
return;
end if;
-- get an identifier
loop -- accept at least one character no matter what is is
if ( (in_str(b_ind) >= 'a') and (in_str(b_ind) <= 'z') ) then
out_str(out_ind) := Character'Val( (Character'POS(in_str(b_ind))) - 32 ); -- convert to upper case
else
out_str(out_ind) := in_str(b_ind);
end if;
out_ind := out_ind + 1;
b_ind := b_ind + 1;
exit when ( (b_ind > StrLen1(in_str)) or
not (is_upper_case (in_str(b_ind)) or is_lower_case(in_str(b_ind)) or
is_dec_digit(in_str(b_ind))
)
);
end loop;
out_str(out_ind) := NUL;
end;
-- make sure string is a valid hexadecimal number
Function valid_hex ( Constant str : IN STRING ) return BOOLEAN is
variable i : integer;
variable valid : BOOLEAN := TRUE;
begin
i := 1;
while ( (i <= StrLen1(str)) and valid ) loop
valid := ( (str(i) >= '0') and (str(i) <= '9') ) or
( (str(i) >= 'a') and (str(i) <= 'z') ) or
( (str(i) >= 'A') and (str(i) <= 'Z') );
i := i + 1;
end loop;
return valid;
end;
-- determine what kind of identifier the sring is
Function word_id (Constant str : IN STRING) return IDENTIFIER is
begin
if StrLen1(str) = 0 then
-- assert false report "BLANK1" severity NOTE;
return BLANK1;
elsif ( (StrLen1(str) = 1) and (str(1) = ':') ) then
-- assert false report "COLON1" severity NOTE;
return COLON1;
elsif ( (StrLen1(str) = 2) and (str(1) = '-') and (str(2) = '-') ) then
-- assert false report "COMMENT1" severity NOTE;
return COMMENT1;
elsif ( (StrLen1(str) = 2) and (str(1) = '.') and (str(2) = '.') ) then
-- assert false report "DOTDOT1" severity NOTE;
return DOTDOT1;
elsif ( (StrLen1(str) = 5) and (str(1 to 5) = "WIDTH") ) then
-- assert false report "WIDTH1" severity NOTE;
return WIDTH1;
elsif ( (StrLen1(str) = 7) and (str(1 to 7) = "DEFAULT") ) then
-- assert false report "DEFAULT1" severity NOTE;
return DEFAULT1;
elsif (valid_hex(str)) then
-- assert false report "HEX_NUM1" severity NOTE;
return HEX_NUM1;
else
-- assert false report "SYN_ERROR1" severity NOTE;
return SYN_ERROR1;
end if;
end;
-- force the parser to start parsing from the next line.
-- Reset the string buffer index to the first element
procedure new_line ( Variable str_buff : INOUT string;
Variable b_index : INOUT integer;
Variable file_error : INOUT integer;
File in_file : TEXT;
Variable line_num : INOUT integer
) is
Variable line_ptr : LINE;
begin
b_index := 1;
if not endfile(in_file) then
fgetline1(str_buff, in_file, line_ptr);
line_num := line_num + 1;
else
file_error := 1;
end if;
DEALLOCATE(line_ptr);
end;
-- get the next symbol in the file going to the next line if necessary
procedure get_sym ( Variable word : INOUT string;
Variable str_buff : INOUT string;
Variable b_index : INOUT integer;
Variable file_error : INOUT integer;
File in_file : TEXT;
Variable line_num : INOUT integer
) is
Variable line_ptr : LINE;
begin
if ( b_index > StrLen1(str_buff) ) then -- if end of line reached then get another line
b_index := 1;
if not endfile(in_file) then
fgetline1(str_buff, in_file, line_ptr);
line_num := line_num + 1;
else
file_error := 1;
end if;
word(1) := NUL;
else
read_word(word, str_buff, b_index);
end if;
DEALLOCATE(line_ptr);
end;
-- convert a hexadecimal string to an integer
function from_hex_to_int (word : IN string) return integer is
variable alias_word : string(1 to word'length) := word;
variable digit, start, leng : integer;
variable power : integer := 1;
variable result : integer := 0;
variable max_bit_num : integer := 0; -- max number of bits needed to represent hex number
begin
leng := StrLen1(alias_word);
start := 1;
-- eliminate preceeding 0's
while ( (alias_word(start) = '0') and (start < leng) ) loop -- less than leng handles the 0 case
start := start + 1;
end loop;
for i in leng downto start loop
max_bit_num := max_bit_num + 4;
if ( (alias_word(i) >= '0') and (alias_word(i) <= '9')) then
digit := Character'Pos(alias_word(i)) - 48;
else
digit := Character'Pos(alias_word(i)) - 55;
end if;
if ( (max_bit_num >= IntegerBitLength) and (digit > 7) ) then
assert FALSE
report "MemRead: hex value: " & word & " is too large to represent as an integer on this machine"
severity ERROR;
exit; -- exit the loop
end if;
result := result + digit * power;
if (i /= start) then -- power will not be multiplied by 16 on the last iteration.
power := power * 16; -- This will prevent an integer overflow when dealing with
end if; -- the maximum number of hex digits the machine can represent.
end loop;
return result;
end;
-- parse a width statement
procedure pwidth ( Variable word : INOUT string;
Variable str_buff : INOUT string;
Variable b_index : INOUT integer;
Variable file_error : INOUT integer;
File in_file : TEXT;
Variable file_width : INOUT integer;
Variable line_num : INOUT integer
) is
Variable w_id : IDENTIFIER;
variable error_line : integer;
begin
w_id := word_id(word);
if (w_id /= WIDTH1) then
file_error := 2;
assert false
report "Mem_Load: Width specification not first executable line in file. File load aborted."
& LF & SPACESTR & "Occurred on line number " & i_to_str(line_num) & " of the input file."
severity ERROR;
else
get_sym (word, str_buff, b_index, file_error, in_file, line_num);
w_id := word_id(word);
if (w_id = COLON1) then
get_sym (word, str_buff, b_index, file_error, in_file, line_num);
w_id := word_id(word);
if w_id = HEX_NUM1 then
file_width := from_hex_to_int(word);
get_sym (word, str_buff, b_index, file_error, in_file, line_num);
w_id := word_id(word);
error_line := line_num;
if w_id = COMMENT1 then
new_line (str_buff, b_index, file_error, in_file, line_num);
elsif w_id /= BLANK1 then
assert false
report "Mem_Load: Additional information on width specification line ignored."
& LF & SPACESTR & "File processing continuing."
& LF & SPACESTR & "Occurred on line number " & i_to_str(line_num)
& " of the input file."
severity ERROR;
new_line(str_buff, b_index, file_error, in_file, line_num);
end if;
if file_width = 0 then
file_error := 10;
assert false
report "Mem_load: Width must be greater than 0. File load aborted."
& LF & SPACESTR & "Occurred on line number " & i_to_str(error_line)
& " of the input file."
severity ERROR;
end if;
else
file_error := 3;
end if;
else
file_error := 3;
end if;
end if;
if file_error = 3 then
assert false
report "Mem_load: Syntax error in width specification. File load aborted."
& LF & SPACESTR & "Occurred on line number " & i_to_str(line_num) & " of the input file."
severity ERROR;
end if;
end;
-- parse a default statement
procedure pdefault ( Variable word : INOUT string; -- present word
Variable str_buff : INOUT string; -- string buffer
Variable b_index : INOUT integer; -- string buffer index
Variable file_error : INOUT integer; -- error?
File in_file : TEXT; -- file
Variable file_width : IN integer; -- width specified by file
Variable mem_id : INOUT mem_id_type; -- memory
Constant hex_size : IN integer; -- number of hex digits expected
Constant rwidth : IN integer; -- # of bits to be written to memory
Variable line_num : INOUT integer -- line # of file
) is
Variable w_id : IDENTIFIER;
Variable tdata : bit_vector (file_width - 1 downto 0);
Variable data : std_logic_vector (mem_id.width - 1 downto 0);
begin
get_sym (word, str_buff, b_index, file_error, in_file, line_num);
w_id := word_id(word);
if w_id = COLON1 then
get_sym (word, str_buff, b_index, file_error, in_file, line_num);
w_id := word_id(word);
if w_id = HEX_NUM1 then
if StrLen1(word) = hex_size then
data := (others => 'X');
tdata := From_HexString1(word)(file_width - 1 downto 0);
data(rwidth - 1 downto 0) := bv_To_StdLogicvector(tdata(rwidth - 1 downto 0));
if mem_id.default = NULL then
mem_id.default := new std_logic_vector(mem_id.width - 1 downto 0);
else
deallocate (mem_id.default);
mem_id.default := new std_logic_vector(mem_id.width - 1 downto 0);
end if;
mem_id.default.all := data;
get_sym (word, str_buff, b_Index, file_error, in_file, line_num);
w_id := word_id(word);
if w_id = COMMENT1 then
new_line (str_buff, b_index, file_error, in_file, line_num);
elsif w_id /= BLANK1 then
assert false
report "Mem_Load: Additional information on default specification line ignored."
& LF & SPACESTR & "File processing continuing."
& LF & SPACESTR & "Occurred on line number " & i_to_str(line_num)
& " of the input file."
severity ERROR;
new_line(str_buff, b_index, file_error, in_file, line_num);
end if;
else
assert false
report "Mem_Load: Default word length does not match file specification for width of memory. "
& " Default ignored."
& LF & SPACESTR & "Occurred on line number " & i_to_str(line_num)
& " of the input file."
severity ERROR;
new_line (str_buff, b_index, file_error, in_file, line_num);
end if;
else
file_error := 4;
end if;
else
file_error := 4;
end if;
if file_error = 4 then
assert false
report "Mem_Load: Syntax error in default word specification. Line ignored."
& LF & SPACESTR & "Occurred on line number " & i_to_str(line_num) & " of the input file."
severity ERROR;
new_line (str_buff, b_index, file_error, in_file, line_num);
file_error := 0;
end if;
end;
-- parse an assignment statement
procedure passign ( Variable addr1 : IN integer; -- starting address of assignment
Variable word : INOUT string; -- current word
Variable str_buff : INOUT string; -- string buffer
Variable b_index : INOUT integer; -- string buffer index
Variable file_error : INOUT integer; -- error?
File in_file : TEXT; -- file
Variable file_width : IN integer; -- width specified by file
Variable mem_id : INOUT mem_id_type; -- memory
Constant hex_size : IN integer; -- number of hex digits expected
Constant rwidth : IN integer; -- # of bits to be written to memory
Variable line_num : INOUT integer -- line # of file
) is
Variable addr : integer := addr1;
Variable w_id : IDENTIFIER := COLON1;
Variable tdata : bit_vector (file_width - 1 downto 0);
Variable data : std_logic_vector (mem_id.width - 1 downto 0);
begin
while ( (file_error = 0) and (w_id /= BLANK1) and (w_id /= COMMENT1) ) loop
get_sym (word, str_buff, b_Index, file_error, in_file, line_num);
w_id := word_id(word);
if w_id = HEX_NUM1 then
if StrLen1(word) = hex_size then
data := (others => 'X');
tdata := From_HexString1(word)(file_width - 1 downto 0);
data(rwidth - 1 downto 0) := bv_To_StdLogicVector(tdata(rwidth - 1 downto 0));
Mem_Basic_Write (mem_id, addr, data, TRUE);
else
assert false
report "Mem_Load: Data word length does not match width specification on line: "
& i_to_str(line_num) & "." & LF & SPACESTR
& "Data byte skipped."
severity ERROR;
end if;
addr := addr + 1;
elsif ( (w_id /= BLANK1) and (w_id /= COMMENT1) ) then
file_error := 5;
assert false
report "Mem_Load: Syntax error on assignment line. Line processed up to error." &
LF & SPACESTR & "Occurred on line number " & i_to_str(line_num) & " of the input file."
severity ERROR;
new_line (str_buff, b_index, file_error, in_file, line_num);
end if;
end loop;
if w_id = COMMENT1 then
new_line (str_buff, b_index, file_error, in_file, line_num);
end if;
if file_error = 5 then
file_error := 0;
end if;
end;
-- parse a range assignment
procedure prange ( Variable addr1 : IN integer; -- strarting address
Variable word : INOUT string; -- current word
Variable str_buff : INOUT string; -- string buffer
Variable b_index : INOUT integer; -- string buffer index
Variable file_error : INOUT integer; -- error?
File in_file : TEXT; -- file
Variable file_width : IN integer; -- width specified in file
Variable mem_id : INOUT mem_id_type; -- memory
Constant hex_size : IN integer; -- number of hex digits expected
Constant rwidth : IN integer; -- # of bits to be written to memory
Variable line_num : INOUT integer -- line # of file
) is
Variable addr2, addr : integer;
Variable w_id : IDENTIFIER;
Variable tdata : bit_vector (file_width - 1 downto 0);
Variable data : std_logic_vector (mem_id.width - 1 downto 0);
Variable error_line : integer;
begin
get_sym (word, str_buff, b_index, file_error, in_file, line_num);
w_id := word_id(word);
if w_id = HEX_NUM1 then
addr2 := from_hex_to_int(word);
if addr2 < addr1 then
file_error := 7;
error_line := line_num;
new_line (str_buff, b_index, file_error, in_file, line_num);
else
get_sym (word, str_buff, b_index, file_error, in_file, line_num);
w_id := word_id(word);
if w_id = COLON1 then
get_sym (word, str_buff, b_index, file_error, in_file, line_num);
w_id := word_id(word);
if w_id = HEX_NUM1 then
if StrLen1(word) = hex_size then
data := (others => 'X');
tdata := From_HexString1(word)(file_width - 1 downto 0);
data(rwidth - 1 downto 0) := bv_To_StdLogicVector(tdata(rwidth - 1 downto 0));
Mem_ALL_Reset (mem_id, data, addr1, addr2, TRUE);
get_sym (word, str_buff, b_Index, file_error, in_file, line_num);
w_id := word_id(word);
if w_id = COMMENT1 then
new_line (str_buff, b_index, file_error, in_file, line_num);
elsif w_id /= BLANK1 then
assert false
report "Mem_Load: Additional information on range assignment line ignored."
& LF & SPACESTR & "File processing continuing."
& LF & SPACESTR & "Occurred on line number " & i_to_str(line_num)
& " of the input file."
severity ERROR;
new_line(str_buff, b_index, file_error, in_file, line_num);
end if;
else
assert false
report "Mem_Load: Data word length does not match width specification."
& LF & SPACESTR & "Line skipped"
& LF & SPACESTR & "Occurred on line number " & i_to_str(line_num)
& " of the input file."
severity ERROR;
new_line(str_buff, b_index, file_error, in_file, line_num);
end if;
addr := addr + 1;
else
assert false
report "Mem_Load: Syntax Error on range assignment line. Line skipped."
& LF & SPACESTR & "Occurred on line number " & i_to_str(line_num)
& " of the input file."
severity ERROR;
new_line(str_buff, b_index, file_error, in_file, line_num);
end if;
-- get_sym (word, str_buff, b_index, file_error, in_file, line_num);
-- w_id := word_id(word);
else
file_error := 6;
error_line := line_num;
new_line (str_buff, b_index, file_error, in_file, line_num);
end if;
end if;
else
file_error := 6;
new_line (str_buff, b_index, file_error, in_file, line_num);
end if;
if file_error = 7 then
assert false
report "Mem_load: Addr2 < Addr1 in range specification. Line skipped."
& LF & SPACESTR & "Occurred on line number " & i_to_str(error_line) & " of the input file."
severity ERROR;
file_error := 0;
end if;
if file_error = 6 then
assert false
report "Mem_load: Syntax error in range specification. Line skipped."
& LF & SPACESTR & "Occurred on line number " & i_to_str(error_line) & " of the input file."
severity ERROR;
file_error := 0;
end if;
end;
-- decide if current statement is a simple assignment of a range assignment
-- then parse that statment
procedure p_op_statement ( Variable word : INOUT string;
Variable str_buff : INOUT string;
Variable b_index : INOUT integer;
Variable file_error : INOUT integer;
File in_file : TEXT;
Variable file_width : IN integer;
Variable mem_id : INOUT mem_id_type;
Constant hex_size : IN integer;
Constant rwidth : IN integer;
Variable line_num : INOUT integer
) is
Variable addr1 : integer;
Variable w_id : IDENTIFIER;
begin
addr1 := from_hex_to_int(word);
get_sym (word, str_buff, b_index, file_error, in_file, line_num);
w_id := word_id(word);
if w_id = COLON1 then
passign ( addr1, word, str_buff, b_index, file_error, in_file,
file_width, mem_id, hex_size, rwidth, line_num);
elsif w_id = DOTDOT1 then
prange ( addr1, word, str_buff, b_index, file_error, in_file,
file_width, mem_id, hex_size, rwidth, line_num);
else
assert false
report "Mem_Load: Syntax error. Line skipped."
& LF & SPACESTR & "Occurred on line number " & i_to_str(line_num) & " of the input file."
severity ERROR;
new_line (str_buff, b_index, file_error, in_file, line_num);
end if;
end;
---------------------------------------------------------------------------
-- Procedure Name : Mem_Basic_Read
--
-- Purpose : To read a "word" from memory
--
-- Parameters : data - contents of memory location
-- mem_id - ptr to memory data structure
-- address - address to read from
-- refresh_enable - if true a refresh is performed
-- for DRAMs
--
-- NOTE : a read refreshes the corresponding row of a DRAM
-- ***** this procedure is not exteranlly visible ****
--
---------------------------------------------------------------------------
Procedure Mem_Basic_Read ( Variable data : OUT std_logic_vector;
Variable mem_id : INOUT mem_id_type;
Constant address : IN NATURAL;
Constant refresh_enable : IN BOOLEAN := TRUE
) IS
Variable alias_data : std_logic_vector(data'length - 1 downto 0) := (others=>'X');
Variable mem_word : std_logic_vector(mem_id.width - 1 downto 0);
Variable row : NATURAL := address/mem_id.columns;
Variable column : NATURAL := address mod mem_id.columns;
Variable limit : integer;
Variable i : NATURAL;
variable short_ptr : rowptr_type;
begin
if address < mem_id.length then -- check for valid address range
-- if dram check if woken up and make assertion
-- nothing else has to be done since data will be invalidated due to refresh period violation
assert ( (mem_id.memory_type /= DRAM) or (NOT MEM_WARNINGS_ON) or
( (mem_id.last_init + mem_id.refresh_period) >= NOW) )
report "Mem_Read: Device wake-up time limit exceeded for memory: "
& pstr(mem_id.name(1 to mem_id.name'length)) & LF & SPACESTR &
"device must be woken up. All reads will return X's or default word"
severity WARNING;
-- invalidate data if refresh period has expired
validate_row (mem_id, row);
-- now refresh row
if refresh_enable then
refresh_row (mem_id, row);
end if;
-- handle data of different width than memory
assert ( (data'length = mem_id.width) OR NOT MEM_WARNINGS_ON)
report "Mem_Read: return data size does not match word size"
& " of mem: " & pstr(mem_id.name(1 to mem_id.name'length)) & LF & SPACESTR &
"return data size: " & i_to_str(data'length) & " bits"
& LF & SPACESTR & "memory word size: " &
i_to_str(mem_id.width) & " bits"
severity WARNING;
if (mem_id.row_data_ptr(row).all_xs) then -- if all xs then return x's
mem_word := (others => 'X');
elsif (mem_id.row_data_ptr(row).rowptr = NULL) then -- if not allocated return default
mem_word := mem_id.default.all;
else
short_ptr := mem_id.row_data_ptr(row).rowptr;
for i in 0 to mem_id.width - 1 loop -- else return word at that location
-- mem_word(i) := mem_id.row_data_ptr(row).rowptr(column,i);
-- *************************************
-- this is a bug work around for synopsys
-- replaces line commented out above
mem_word(i) := short_ptr(column,i);
-- end bug fix
-- *************************************
end loop;
end if;
if mem_id.width >= data'length then
limit := data'length;
else
limit := mem_id.width;
end if;
for i in 0 to limit - 1 loop
alias_data(i) := mem_word(i);
end loop;
else
assert false
report "Mem_Read: Passed address exceeds address " &
"range of mem: " & pstr(mem_id.name(1 to mem_id.name'length)) & LF & SPACESTR
& "specified address: " & i_to_str(address) & LF &
SPACESTR & "address range: 0 to " & i_to_str(mem_id.length - 1)
severity ERROR;
alias_data := (others => 'X');
end if;
data := alias_data;
end;
Procedure Mem_Basic_Read ( Variable data : OUT std_ulogic;
Variable mem_id : INOUT mem_id_type;
Constant address : IN NATURAL;
Constant refresh_enable : IN BOOLEAN := TRUE
) IS
Variable row : NATURAL := address/mem_id.columns;
Variable column : NATURAL := address mod mem_id.columns;
variable short_ptr : rowptr_type;
begin
if address < mem_id.length then
assert ( (mem_id.memory_type /= DRAM) or (NOT MEM_WARNINGS_ON) or
( (mem_id.last_init + mem_id.refresh_period) >= NOW) )
report "Mem_Read: Device wake-up time limit exceeded for memory: "
& pstr(mem_id.name(1 to mem_id.name'length)) & LF & SPACESTR &
"device must be woken up. All reads will return X's or default word."
severity WARNING;
validate_row (mem_id, row);
if refresh_enable then
refresh_row (mem_id, row);
end if;
-- handle data of different width than memory
assert ( (mem_id.width = 1) OR NOT MEM_WARNINGS_ON)
report "Mem_Read: return data size does not match word size"
& " of mem: " & pstr(mem_id.name(1 to mem_id.name'length)) & LF &
SPACESTR & "return data size: 1" & LF & SPACESTR & "memory word size: " &
i_to_str(mem_id.width) & " bits"
severity WARNING;
if (mem_id.row_data_ptr(row).all_xs) then
data := 'X';
elsif (mem_id.row_data_ptr(row).rowptr = NULL) then
data := mem_id.default(0);
else
--data := mem_id.row_data_ptr(row).rowptr(column,0);
-- *************************************
-- this is a bug work around for synopsys
-- replaces line commented out above
short_ptr := mem_id.row_data_ptr(row).rowptr;
data := short_ptr(column,0);
-- end bug fix
-- *************************************
end if;
else
assert false
report "Mem_Read: Passed address exceeds address " &
"range of mem: " & pstr(mem_id.name(1 to mem_id.name'length)) & LF & SPACESTR
& "specified address: " & i_to_str(address) & LF &
SPACESTR & "address range: 0 to "
& i_to_str(mem_id.length - 1)
severity ERROR;
data := 'X';
end if;
end;
---------------------------------------------------------------------------
-- Procedure Name : Mem_Read
--
-- Purpose : To read a "word" from memory
--
-- Parameters : mem_id - ptr to memory data structure
-- address - address to read from
-- data - contents of memory location
--
--
-- NOTE : a read refreshes row of a DRAM
--
-- Use : Mem_Read (ROM1, "100100111", data);
---------------------------------------------------------------------------
Procedure Mem_Read ( Variable mem_id : INOUT mem_id_type;
Constant address : IN std_ulogic_vector;
Variable data : OUT std_ulogic_vector
) IS
Variable temp : std_logic_vector(data'length - 1 downto 0);
begin
Mem_Basic_Read (temp, mem_id, address_trans(mem_id.length, address));
data := std_ulogic_vector (temp);
end;
---------------------------------------------------------------------------
-- Procedure Name : Mem_Write
--
-- Purpose : To write a "word" to memory
--
-- Parameters : mem_id - ptr to memory data structure
-- address - address to read from
-- data - "word" to be written to memory
--
-- NOTE : a write refreshes row of a DRAM
--
-- Use : Mem_Write (ROM1, "100100111", "10X1");
---------------------------------------------------------------------------
Procedure Mem_Write ( Variable mem_id : INOUT mem_id_type;
Constant address : IN std_ulogic_vector;
Constant data : IN std_ulogic_vector
) IS
begin
Mem_Basic_Write ( mem_id,
Address_trans(mem_id.length, address),
To_X01(std_logic_vector(data))
);
end;
END mem_model;
library IEEE;
use IEEE.std_logic_1164.all;
use std.textio.all;
--library std_developerskit;
--use std_developerskit.std_iopak.all;
use work.util.all;
use work.textutil.all;
--############################################################################
--############################################################################
--==========================================================================--
--
-- *Module : tb_lambo
--
-- *Description : Test Bench for the GN4124 BFM + Lambo Design
--
-- *History
--
--==========================================================================--
--############################################################################
--############################################################################
entity TB_LAMBO is
generic
(
T_LCLK : time := 30 ns -- Default LCLK Clock Period
);
end TB_LAMBO;
architecture TEST of TB_LAMBO is
--###########################################################################
--###########################################################################
--##
--## Component Declairations
--##
--###########################################################################
--###########################################################################
-----------------------------------------------------------------------------
-- GN4124 Local Bus Model
-----------------------------------------------------------------------------
component GN412X_BFM
generic
(
STRING_MAX : integer := 256; -- Command string maximum length
T_LCLK : time := 10 ns; -- Local Bus Clock Period
T_P2L_CLK_DLY : time := 2 ns; -- Delay from LCLK to P2L_CLK
INSTANCE_LABEL : string := "GN412X_BFM"; -- Label string to be used as a prefix for messages from the model
MODE_PRIMARY : boolean := TRUE -- TRUE for BFM acting as GN412x, FALSE for BFM acting as the DUT
);
port
(
--=========================================================--
-------------------------------------------------------------
-- CMD_ROUTER Interface
--
CMD : in STRING(1 to STRING_MAX);
CMD_REQ : in BIT;
CMD_ACK : out BIT;
CMD_CLOCK_EN : in boolean;
--=========================================================--
-------------------------------------------------------------
-- GN412x Signal I/O
-------------------------------------------------------------
-- This is the reset input to the BFM
--
RSTINn : in std_logic;
-------------------------------------------------------------
-- Reset outputs to DUT
--
RSTOUT18n : out std_logic;
RSTOUT33n : out std_logic;
-------------------------------------------------------------
----------------- Local Bus Clock ---------------------------
------------------------------------------------------------- __ Direction for primary mode
-- / \
LCLK, LCLKn : inout std_logic; -- Out
-------------------------------------------------------------
----------------- Local-to-PCI Dataflow ---------------------
-------------------------------------------------------------
-- Transmitter Source Synchronous Clock.
--
L2P_CLKp, L2P_CLKn : inout std_logic; -- In
-------------------------------------------------------------
-- L2P DDR Link
--
L2P_DATA : inout std_logic_vector(15 downto 0); -- In -- Parallel Transmit Data.
L2P_DFRAME : inout std_logic; -- In -- Transmit Data Frame.
L2P_VALID : inout std_logic; -- In -- Transmit Data Valid.
L2P_EDB : inout std_logic; -- In -- End-of-Packet Bad Flag.
-------------------------------------------------------------
-- L2P SDR Controls
--
L_WR_RDY : inout std_logic_vector( 1 downto 0); -- Out -- Local-to-PCIe Write.
P_RD_D_RDY : inout std_logic_vector( 1 downto 0); -- Out -- PCIe-to-Local Read Response Data Ready.
L2P_RDY : inout std_logic; -- Out -- Tx Buffer Full Flag.
TX_ERROR : inout std_logic; -- Out -- Transmit Error.
-------------------------------------------------------------
----------------- PCIe-to-Local Dataflow ---------------------
-------------------------------------------------------------
-- Transmitter Source Synchronous Clock.
--
P2L_CLKp, P2L_CLKn : inout std_logic; -- Out -- P2L Source Synchronous Clock.
-------------------------------------------------------------
-- P2L DDR Link
--
P2L_DATA : inout std_logic_vector(15 downto 0); -- Out -- Parallel Receive Data.
P2L_DFRAME : inout std_logic; -- Out -- Receive Frame.
P2L_VALID : inout std_logic; -- Out -- Receive Data Valid.
-------------------------------------------------------------
-- P2L SDR Controls
--
P2L_RDY : inout std_logic; -- In -- Rx Buffer Full Flag.
P_WR_REQ : inout std_logic_vector( 1 downto 0); -- Out -- PCIe Write Request.
P_WR_RDY : inout std_logic_vector( 1 downto 0); -- In -- PCIe Write Ready.
RX_ERROR : inout std_logic; -- In -- Receive Error.
VC_RDY : inout std_logic_vector( 1 downto 0); -- Out -- Virtual Channel Ready Status.
-------------------------------------------------------------
-- GPIO signals
--
GPIO : inout std_logic_vector(15 downto 0)
);
end component; --GN412X_BFM;
-----------------------------------------------------------------------------
-- CMD_ROUTER component
-----------------------------------------------------------------------------
component cmd_router
generic( N_BFM : integer := 8;
N_FILES : integer := 3;
FIFO_DEPTH : integer := 8;
STRING_MAX : integer := 256
);
port( CMD : out string(1 to STRING_MAX);
CMD_REQ : out bit_vector(N_BFM-1 downto 0);
CMD_ACK : in bit_vector(N_BFM-1 downto 0);
CMD_ERR : in bit_vector(N_BFM-1 downto 0);
CMD_CLOCK_EN : out boolean
);
end component; --cmd_router;
-----------------------------------------------------------------------------
-- CMD_ROUTER component
-----------------------------------------------------------------------------
component simple
port(
clk : in std_logic;
d : in std_logic_vector(15 downto 0);
q : out std_logic_vector(15 downto 0)
);
end component;
-----------------------------------------------------------------------------
-- The lambo design
-----------------------------------------------------------------------------
component lambo
generic
(
TAR_ADDR_WDTH : integer := 13
);
port
(
-- From ASIC Local bus
l_clkp : in std_logic; -- Running at 200 Mhz
l_clkn : in std_logic; -- Running at 200 Mhz
l_rst_n : in std_logic;
l_rst33_n : in std_logic;
sys_clkb : in std_logic; -- Running at 161 Mhz (for the SDRAM)
sys_clk : in std_logic; -- Running at 161 Mhz (for the SDRAM)
reset_in_n : in std_logic;
-- General Purpose Interface
gpio : inout std_logic_vector(15 downto 0); -- General Purpose Input/Output
-- PCIe to Local [Inbound Data] - RX
p2l_rdy : out std_logic; -- Rx Buffer Full Flag
p2l_clkn : in std_logic; -- Receiver Source Synchronous Clock-
p2l_clkp : in std_logic; -- Receiver Source Synchronous Clock+
p2l_data : in std_logic_vector(15 downto 0); -- Parallel receive data
p2l_dframe : in std_logic; -- Receive Frame
p2l_valid : in std_logic; -- Receive Data Valid
-- Inbound Buffer Request/Status
p_wr_req : in std_logic_vector(1 downto 0); -- PCIe Write Request
p_wr_rdy : out std_logic_vector(1 downto 0); -- PCIe Write Ready
rx_error : out std_logic; -- Receive Error
-- Local to Parallel [Outbound Data] - TX
l2p_data : out std_logic_vector(15 downto 0); -- Parallel transmit data
l2p_dframe : out std_logic; -- Transmit Data Frame
l2p_valid : out std_logic; -- Transmit Data Valid
l2p_clkn : out std_logic; -- Transmitter Source Synchronous Clock-
l2p_clkp : out std_logic; -- Transmitter Source Synchronous Clock+
l2p_edb : out std_logic; -- Packet termination and discard
-- Outbound Buffer Status
l2p_rdy : in std_logic; -- Tx Buffer Full Flag
l_wr_rdy : in std_logic_vector(1 downto 0); -- Local-to-PCIe Write
p_rd_d_rdy : in std_logic_vector(1 downto 0); -- PCIe-to-Local Read Response Data Ready
tx_error : in std_logic; -- Transmit Error
vc_rdy : in std_logic_vector(1 downto 0); -- Channel ready
-- DDR2 SDRAM Interface
cntrl0_ddr2_dq : inout std_logic_vector(31 downto 0);
cntrl0_ddr2_a : out std_logic_vector(12 downto 0);
cntrl0_ddr2_ba : out std_logic_vector( 1 downto 0);
cntrl0_ddr2_cke : out std_logic;
cntrl0_ddr2_cs_n : out std_logic;
cntrl0_ddr2_ras_n : out std_logic;
cntrl0_ddr2_cas_n : out std_logic;
cntrl0_ddr2_we_n : out std_logic;
cntrl0_ddr2_odt : out std_logic;
cntrl0_ddr2_dm : out std_logic_vector(3 downto 0);
cntrl0_rst_dqs_div_in : in std_logic;
cntrl0_rst_dqs_div_out : out std_logic;
cntrl0_ddr2_dqs : inout std_logic_vector(3 downto 0);
cntrl0_ddr2_dqs_n : inout std_logic_vector(3 downto 0);
cntrl0_ddr2_ck : out std_logic_vector(1 downto 0);
cntrl0_ddr2_ck_n : out std_logic_vector(1 downto 0);
mic_clka : out std_logic;
mic_clkb : out std_logic;
mic_data : out std_logic_vector(31 downto 0);
-- GN1559 related
ser : out std_logic_vector(19 downto 0);
ser_h : out std_logic;
ser_v : out std_logic;
ser_f : out std_logic;
ser_smpte_bypass : out std_logic;
ser_dvb_asi : out std_logic;
ser_sdhdn : out std_logic;
-- GN1531 de-serializer
des : in std_logic_vector(19 downto 0);
des_pclk : in std_logic;
des_h : in std_logic;
des_v : in std_logic;
des_f : in std_logic;
des_smpte_bypass : inout std_logic;
des_dvb_asi : inout std_logic;
des_sdhdn : inout std_logic;
-- GN4911 Timing Generator
syncseperator_h_timing : in std_logic;
syncseperator_v_timing : in std_logic;
syncseperator_f_timing : in std_logic;
-- I2C
sda : inout std_logic;
scl : in std_logic;
-- Debug Switches
debug : in std_logic_vector(7 downto 0);
led : out std_logic_vector(7 downto 0);
-- SPI
spi_sck : in std_logic;
spi_ss : in std_logic_vector(4 downto 0);
spi_mosi : in std_logic;
spi_miso : out std_logic;
pclk_4911_1531 : in std_logic; -- requested by Jared
gs4911_host_b : out std_logic;
gs4911_sclk : out std_logic;
gs4911_sdin : out std_logic;
gs4911_sdout : in std_logic;
gs4911_csb : out std_logic;
gs4911_lock_lost : in std_logic; -- requested by Jared
gs4911_ref_lost : in std_logic -- requested by Jared
);
end component; --lambo;
--###########################################################################
--###########################################################################
--##
--## Constants
--##
--###########################################################################
--###########################################################################
--
-- Number of Models receiving commands
constant N_BFM : integer := 2; -- 0 : GN412X_BFM in Model Mode
-- -- 1 : GN412X_BFM in DUT mode
-- Number of files to feed BFMs
constant N_FILES : integer := 2;
--
-- Depth of the command FIFO for each model
constant FIFO_DEPTH : integer := 16;
--
-- Maximum width of a command string
constant STRING_MAX : integer := 256;
--
--###########################################################################
--###########################################################################
--##
--## Signals
--##
--###########################################################################
--###########################################################################
-----------------------------------------------------------------------------
-- Command Router Signals
-----------------------------------------------------------------------------
signal CMD : STRING(1 to STRING_MAX);
signal CMD_REQ : BIT_VECTOR(N_BFM-1 downto 0);
signal CMD_ACK : BIT_VECTOR(N_BFM-1 downto 0);
signal CMD_ERR : BIT_VECTOR(N_BFM-1 downto 0);
signal CMD_CLOCK_EN : boolean;
-----------------------------------------------------------------------------
-- GN412x BFM Signals
-----------------------------------------------------------------------------
signal RSTINn : std_logic;
signal RSTOUT18n : std_logic;
signal RSTOUT33n : std_logic;
signal LCLK, LCLKn : std_logic;
signal L2P_CLKp, L2P_CLKn : std_logic;
signal L2P_DATA : std_logic_vector(15 downto 0);
signal L2P_DATA_32 : std_logic_vector(31 downto 0); -- For monitoring use
signal L2P_DFRAME : std_logic;
signal L2P_VALID : std_logic;
signal L2P_EDB : std_logic;
signal L_WR_RDY : std_logic_vector( 1 downto 0);
signal P_RD_D_RDY : std_logic_vector( 1 downto 0);
signal L2P_RDY : std_logic;
signal TX_ERROR : std_logic;
signal P2L_CLKp, P2L_CLKn : std_logic;
signal P2L_DATA : std_logic_vector(15 downto 0);
signal P2L_DATA_32 : std_logic_vector(31 downto 0); -- For monitoring use
signal P2L_DFRAME : std_logic;
signal P2L_VALID : std_logic;
signal P2L_RDY : std_logic;
signal P_WR_REQ : std_logic_vector( 1 downto 0);
signal P_WR_RDY : std_logic_vector( 1 downto 0);
signal RX_ERROR : std_logic;
signal VC_RDY : std_logic_vector( 1 downto 0);
-----------------------------------------------------------------------------
-- Unused Signals
-----------------------------------------------------------------------------
signal GPIO : std_logic_vector(15 downto 0);
-- Lambo
-- DDR2 SDRAM Interface
signal cntrl0_ddr2_dq : std_logic_vector(31 downto 0);
signal cntrl0_ddr2_a : std_logic_vector(12 downto 0);
signal cntrl0_ddr2_ba : std_logic_vector( 1 downto 0);
signal cntrl0_ddr2_cke : std_logic;
signal cntrl0_ddr2_cs_n : std_logic;
signal cntrl0_ddr2_ras_n : std_logic;
signal cntrl0_ddr2_cas_n : std_logic;
signal cntrl0_ddr2_we_n : std_logic;
signal cntrl0_ddr2_odt : std_logic;
signal cntrl0_ddr2_dm : std_logic_vector(3 downto 0);
signal cntrl0_rst_dqs_div_in : std_logic;
signal cntrl0_rst_dqs_div_out : std_logic;
signal cntrl0_ddr2_dqs : std_logic_vector(3 downto 0);
signal cntrl0_ddr2_dqs_n : std_logic_vector(3 downto 0);
signal cntrl0_ddr2_ck : std_logic_vector(1 downto 0);
signal cntrl0_ddr2_ck_n : std_logic_vector(1 downto 0);
signal mic_clka : std_logic;
signal mic_clkb : std_logic;
signal mic_data : std_logic_vector(31 downto 0);
-- GN1559 related
signal ser : std_logic_vector(19 downto 0);
signal ser_h : std_logic;
signal ser_v : std_logic;
signal ser_f : std_logic;
signal ser_smpte_bypass : std_logic;
signal ser_dvb_asi : std_logic;
signal ser_sdhdn : std_logic;
-- GN1531 de-serializer
signal des : std_logic_vector(19 downto 0);
signal des_pclk : std_logic;
signal des_h : std_logic;
signal des_v : std_logic;
signal des_f : std_logic;
signal des_smpte_bypass : std_logic;
signal des_dvb_asi : std_logic;
signal des_sdhdn : std_logic;
-- GN4911 Timing Generator
signal syncseperator_h_timing : std_logic;
signal syncseperator_v_timing : std_logic;
signal syncseperator_f_timing : std_logic;
-- I2C
signal sda : std_logic;
signal scl : std_logic;
-- Debug Switches
signal debug : std_logic_vector(7 downto 0);
signal led : std_logic_vector(7 downto 0);
-- SPI
signal spi_sck : std_logic;
signal spi_ss : std_logic_vector(4 downto 0);
signal spi_mosi : std_logic;
signal spi_miso : std_logic;
signal pclk_4911_1531 : std_logic; -- requested by Jared
signal gs4911_host_b : std_logic;
signal gs4911_sclk : std_logic;
signal gs4911_sdin : std_logic;
signal gs4911_sdout : std_logic;
signal gs4911_csb : std_logic;
signal gs4911_lock_lost : std_logic; -- requested by Jared
signal gs4911_ref_lost : std_logic; -- requested by Jared
-----------------------------------------------------------------------------
-- Bus Monitor Signals
-----------------------------------------------------------------------------
signal Q_P2L_DFRAME : std_logic;
signal SIMPLE_TEST : std_logic_vector(15 downto 0);
--###########################################################################
--###########################################################################
--##
--## Start of Code
--##
--###########################################################################
--###########################################################################
begin
-----------------------------------------------------------------------------
-- MODEL Component
-----------------------------------------------------------------------------
CMD_ERR <= (others => '0');
UC : cmd_router
generic map
( N_BFM => N_BFM,
N_FILES => N_FILES,
FIFO_DEPTH => FIFO_DEPTH,
STRING_MAX => STRING_MAX
)
port map
( CMD => CMD,
CMD_REQ => CMD_REQ,
CMD_ACK => CMD_ACK,
CMD_ERR => CMD_ERR,
CMD_CLOCK_EN => CMD_CLOCK_EN
);
-----------------------------------------------------------------------------
-- GN412x BFM - PRIMARY
-----------------------------------------------------------------------------
U0 : gn412x_bfm
generic map
(
STRING_MAX => STRING_MAX,
T_LCLK => 10 ns,
T_P2L_CLK_DLY => 2 ns,
INSTANCE_LABEL => "U0(Primary GN412x): ",
MODE_PRIMARY => TRUE
)
port map
(
--=========================================================--
-------------------------------------------------------------
-- CMD_ROUTER Interface
--
CMD => CMD,
CMD_REQ => CMD_REQ(0),
CMD_ACK => CMD_ACK(0),
CMD_CLOCK_EN => CMD_CLOCK_EN,
--=========================================================--
-------------------------------------------------------------
-- GN412x Signal I/O
-------------------------------------------------------------
-- This is the reset input to the BFM
--
RSTINn => RSTINn,
-------------------------------------------------------------
-- Reset outputs to DUT
--
RSTOUT18n => RSTOUT18n,
RSTOUT33n => RSTOUT33n,
-------------------------------------------------------------
----------------- Local Bus Clock ---------------------------
-------------------------------------------------------------
--
LCLK => LCLK,
LCLKn => LCLKn,
-------------------------------------------------------------
----------------- Local-to-PCI Dataflow ---------------------
-------------------------------------------------------------
-- Transmitter Source Synchronous Clock.
--
L2P_CLKp => L2P_CLKp,
L2P_CLKn => L2P_CLKn,
-------------------------------------------------------------
-- L2P DDR Link
--
L2P_DATA => L2P_DATA,
L2P_DFRAME => L2P_DFRAME,
L2P_VALID => L2P_VALID,
L2P_EDB => L2P_EDB,
-------------------------------------------------------------
-- L2P SDR Controls
--
L_WR_RDY => L_WR_RDY,
P_RD_D_RDY => P_RD_D_RDY,
L2P_RDY => L2P_RDY,
TX_ERROR => TX_ERROR,
-------------------------------------------------------------
----------------- PCIe-to-Local Dataflow ---------------------
-------------------------------------------------------------
-- Transmitter Source Synchronous Clock.
--
P2L_CLKp => P2L_CLKp,
P2L_CLKn => P2L_CLKn,
-------------------------------------------------------------
-- P2L DDR Link
--
P2L_DATA => P2L_DATA,
P2L_DFRAME => P2L_DFRAME,
P2L_VALID => P2L_VALID,
-------------------------------------------------------------
-- P2L SDR Controls
--
P2L_RDY => P2L_RDY,
P_WR_REQ => P_WR_REQ,
P_WR_RDY => P_WR_RDY,
RX_ERROR => RX_ERROR,
VC_RDY => VC_RDY,
GPIO => gpio
); -- GN412X_BFM;
-----------------------------------------------------------------------------
-- Lambo FPGA IP
-----------------------------------------------------------------------------
U1 : lambo
port map
(
-- From ASIC Local bus
l_clkp => LCLK, -- Running at 200 Mhz
l_clkn => LCLKn, -- Running at 200 Mhz
l_rst_n => RSTOUT18n,
l_rst33_n => RSTOUT33n,
sys_clkb => '1', -- Running at 161 Mhz (for the SDRAM)
sys_clk => '0', -- Running at 161 Mhz (for the SDRAM)
reset_in_n => RSTOUT18n,
-- General Purpose Interface
gpio => GPIO, -- General Purpose Input/Output
-- PCIe to Local [Inbound Data] - RX
p2l_rdy => P2L_RDY, -- Rx Buffer Full Flag
p2l_clkn => P2L_CLKn, -- Receiver Source Synchronous Clock-
p2l_clkp => P2L_CLKp, -- Receiver Source Synchronous Clock+
p2l_data => P2L_DATA, -- Parallel receive data
p2l_dframe => P2L_DFRAME, -- Receive Frame
p2l_valid => P2L_VALID, -- Receive Data Valid
-- Inbound Buffer Request/Status
p_wr_req => P_WR_REQ, -- PCIe Write Request
p_wr_rdy => P_WR_RDY, -- PCIe Write Ready
rx_error => RX_ERROR, -- Receive Error
-- Local to Parallel [Outbound Data] - TX
l2p_data => L2P_DATA, -- Parallel transmit data
l2p_dframe => L2P_DFRAME, -- Transmit Data Frame
l2p_valid => L2P_VALID, -- Transmit Data Valid
l2p_clkn => L2P_CLKn, -- Transmitter Source Synchronous Clock-
l2p_clkp => L2P_CLKp, -- Transmitter Source Synchronous Clock+
l2p_edb => L2P_EDB, -- Packet termination and discard
-- Outbound Buffer Status
l2p_rdy => L2P_RDY, -- Tx Buffer Full Flag
l_wr_rdy => L_WR_RDY, -- Local-to-PCIe Write
p_rd_d_rdy => P_RD_D_RDY, -- PCIe-to-Local Read Response Data Ready
tx_error => TX_ERROR, -- Transmit Error
vc_rdy => VC_RDY, -- Channel ready
-- DDR2 SDRAM Interface
cntrl0_ddr2_dq => cntrl0_ddr2_dq,
cntrl0_ddr2_a => cntrl0_ddr2_a,
cntrl0_ddr2_ba => cntrl0_ddr2_ba,
cntrl0_ddr2_cke => cntrl0_ddr2_cke,
cntrl0_ddr2_cs_n => cntrl0_ddr2_cs_n,
cntrl0_ddr2_ras_n => cntrl0_ddr2_ras_n,
cntrl0_ddr2_cas_n => cntrl0_ddr2_cas_n,
cntrl0_ddr2_we_n => cntrl0_ddr2_we_n,
cntrl0_ddr2_odt => cntrl0_ddr2_odt,
cntrl0_ddr2_dm => cntrl0_ddr2_dm,
cntrl0_rst_dqs_div_in => cntrl0_rst_dqs_div_in,
cntrl0_rst_dqs_div_out => cntrl0_rst_dqs_div_out,
cntrl0_ddr2_dqs => cntrl0_ddr2_dqs,
cntrl0_ddr2_dqs_n => cntrl0_ddr2_dqs_n,
cntrl0_ddr2_ck => cntrl0_ddr2_ck,
cntrl0_ddr2_ck_n => cntrl0_ddr2_ck_n,
mic_clka => mic_clka,
mic_clkb => mic_clkb,
mic_data => mic_data,
-- GN1559 related
ser => ser,
ser_h => ser_h,
ser_v => ser_v,
ser_f => ser_f,
ser_smpte_bypass => ser_smpte_bypass,
ser_dvb_asi => ser_dvb_asi,
ser_sdhdn => ser_sdhdn,
-- GN1531 de-serializer
des => des,
des_pclk => des_pclk,
des_h => des_h,
des_v => des_v,
des_f => des_f,
des_smpte_bypass => des_smpte_bypass,
des_dvb_asi => des_dvb_asi,
des_sdhdn => des_sdhdn,
-- GN4911 Timing Generator
syncseperator_h_timing => syncseperator_h_timing,
syncseperator_v_timing => syncseperator_v_timing,
syncseperator_f_timing => syncseperator_f_timing,
-- I2C
sda => sda,
scl => scl,
-- Debug Switches
debug => debug,
led => led,
-- SPI
spi_sck => spi_sck,
spi_ss => spi_ss,
spi_mosi => spi_mosi,
spi_miso => spi_miso,
pclk_4911_1531 => pclk_4911_1531,
gs4911_host_b => gs4911_host_b,
gs4911_sclk => gs4911_sclk,
gs4911_sdin => gs4911_sdin,
gs4911_sdout => gs4911_sdout,
gs4911_csb => gs4911_csb,
gs4911_lock_lost => gs4911_lock_lost,
gs4911_ref_lost => gs4911_ref_lost
);
process
variable vP2L_DATA_LOW : std_logic_vector(P2L_DATA'range);
begin
wait until(P2L_CLKp'event and (P2L_CLKp = '1'));
vP2L_DATA_LOW := P2L_DATA;
loop
wait on P2L_DATA, P2L_CLKp;
P2L_DATA_32 <= P2L_DATA & vP2L_DATA_LOW;
if(P2L_CLKp = '0') then
exit;
end if;
end loop;
end process;
end TEST;
library IEEE;
use IEEE.std_logic_1164.all;
use std.textio.all;
--library std_developerskit;
--use std_developerskit.std_iopak.all;
use work.util.all;
use work.textutil.all;
--############################################################################
--############################################################################
--==========================================================================--
--
-- *Module : tb_pfc
--
-- *Description : Test Bench for the GN4124 BFM + PFC Design
--
-- *History
--
--==========================================================================--
--############################################################################
--############################################################################
entity TB_PFC is
generic
(
T_LCLK : time := 30 ns -- Default LCLK Clock Period
);
end TB_PFC;
architecture TEST of TB_PFC is
--###########################################################################
--###########################################################################
--##
--## Component Declairations
--##
--###########################################################################
--###########################################################################
-----------------------------------------------------------------------------
-- GN4124 Local Bus Model
-----------------------------------------------------------------------------
component GN412X_BFM
generic
(
STRING_MAX : integer := 256; -- Command string maximum length
T_LCLK : time := 10 ns; -- Local Bus Clock Period
T_P2L_CLK_DLY : time := 2 ns; -- Delay from LCLK to P2L_CLK
INSTANCE_LABEL : string := "GN412X_BFM"; -- Label string to be used as a prefix for messages from the model
MODE_PRIMARY : boolean := true -- TRUE for BFM acting as GN412x, FALSE for BFM acting as the DUT
);
port
(
--=========================================================--
-------------------------------------------------------------
-- CMD_ROUTER Interface
--
CMD : in string(1 to STRING_MAX);
CMD_REQ : in bit;
CMD_ACK : out bit;
CMD_CLOCK_EN : in boolean;
--=========================================================--
-------------------------------------------------------------
-- GN412x Signal I/O
-------------------------------------------------------------
-- This is the reset input to the BFM
--
RSTINn : in std_logic;
-------------------------------------------------------------
-- Reset outputs to DUT
--
RSTOUT18n : out std_logic;
RSTOUT33n : out std_logic;
-------------------------------------------------------------
----------------- Local Bus Clock ---------------------------
------------------------------------------------------------- __ Direction for primary mode
-- / \
LCLK, LCLKn : inout std_logic; -- Out
-------------------------------------------------------------
----------------- Local-to-PCI Dataflow ---------------------
-------------------------------------------------------------
-- Transmitter Source Synchronous Clock.
--
L2P_CLKp, L2P_CLKn : inout std_logic; -- In
-------------------------------------------------------------
-- L2P DDR Link
--
L2P_DATA : inout std_logic_vector(15 downto 0); -- In -- Parallel Transmit Data.
L2P_DFRAME : inout std_logic; -- In -- Transmit Data Frame.
L2P_VALID : inout std_logic; -- In -- Transmit Data Valid.
L2P_EDB : inout std_logic; -- In -- End-of-Packet Bad Flag.
-------------------------------------------------------------
-- L2P SDR Controls
--
L_WR_RDY : inout std_logic_vector(1 downto 0); -- Out -- Local-to-PCIe Write.
P_RD_D_RDY : inout std_logic_vector(1 downto 0); -- Out -- PCIe-to-Local Read Response Data Ready.
L2P_RDY : inout std_logic; -- Out -- Tx Buffer Full Flag.
TX_ERROR : inout std_logic; -- Out -- Transmit Error.
-------------------------------------------------------------
----------------- PCIe-to-Local Dataflow ---------------------
-------------------------------------------------------------
-- Transmitter Source Synchronous Clock.
--
P2L_CLKp, P2L_CLKn : inout std_logic; -- Out -- P2L Source Synchronous Clock.
-------------------------------------------------------------
-- P2L DDR Link
--
P2L_DATA : inout std_logic_vector(15 downto 0); -- Out -- Parallel Receive Data.
P2L_DFRAME : inout std_logic; -- Out -- Receive Frame.
P2L_VALID : inout std_logic; -- Out -- Receive Data Valid.
-------------------------------------------------------------
-- P2L SDR Controls
--
P2L_RDY : inout std_logic; -- In -- Rx Buffer Full Flag.
P_WR_REQ : inout std_logic_vector(1 downto 0); -- Out -- PCIe Write Request.
P_WR_RDY : inout std_logic_vector(1 downto 0); -- In -- PCIe Write Ready.
RX_ERROR : inout std_logic; -- In -- Receive Error.
VC_RDY : inout std_logic_vector(1 downto 0); -- Out -- Virtual Channel Ready Status.
-------------------------------------------------------------
-- GPIO signals
--
GPIO : inout std_logic_vector(15 downto 0)
);
end component; --GN412X_BFM;
-----------------------------------------------------------------------------
-- CMD_ROUTER component
-----------------------------------------------------------------------------
component cmd_router
generic(N_BFM : integer := 8;
N_FILES : integer := 3;
FIFO_DEPTH : integer := 8;
STRING_MAX : integer := 256
);
port(CMD : out string(1 to STRING_MAX);
CMD_REQ : out bit_vector(N_BFM-1 downto 0);
CMD_ACK : in bit_vector(N_BFM-1 downto 0);
CMD_ERR : in bit_vector(N_BFM-1 downto 0);
CMD_CLOCK_EN : out boolean
);
end component; --cmd_router;
-----------------------------------------------------------------------------
-- CMD_ROUTER component
-----------------------------------------------------------------------------
component simple
port(
clk : in std_logic;
d : in std_logic_vector(15 downto 0);
q : out std_logic_vector(15 downto 0)
);
end component;
-----------------------------------------------------------------------------
-- Design top entity
-----------------------------------------------------------------------------
component pfc_top
generic(
g_SIMULATION : string := "FALSE";
g_CALIB_SOFT_IP : string := "TRUE"
);
port
(
-- Global ports
SYS_CLK_P : in std_logic; -- 25MHz system clock
SYS_CLK_N : in std_logic; -- 25MHz system clock
-- From GN4124 Local bus
L_CLKp : in std_logic; -- Local bus clock (frequency set in GN4124 config registers)
L_CLKn : in std_logic; -- Local bus clock (frequency set in GN4124 config registers)
L_RST_N : in std_logic; -- Reset from GN4124 (RSTOUT18_N)
-- General Purpose Interface
GPIO : inout std_logic_vector(1 downto 0); -- GPIO[0] -> GN4124 GPIO8
-- GPIO[1] -> GN4124 GPIO9
-- PCIe to Local [Inbound Data] - RX
P2L_RDY : out std_logic; -- Rx Buffer Full Flag
P2L_CLKn : in std_logic; -- Receiver Source Synchronous Clock-
P2L_CLKp : in std_logic; -- Receiver Source Synchronous Clock+
P2L_DATA : in std_logic_vector(15 downto 0); -- Parallel receive data
P2L_DFRAME : in std_logic; -- Receive Frame
P2L_VALID : in std_logic; -- Receive Data Valid
-- Inbound Buffer Request/Status
P_WR_REQ : in std_logic_vector(1 downto 0); -- PCIe Write Request
P_WR_RDY : out std_logic_vector(1 downto 0); -- PCIe Write Ready
RX_ERROR : out std_logic; -- Receive Error
-- Local to Parallel [Outbound Data] - TX
L2P_DATA : out std_logic_vector(15 downto 0); -- Parallel transmit data
L2P_DFRAME : out std_logic; -- Transmit Data Frame
L2P_VALID : out std_logic; -- Transmit Data Valid
L2P_CLKn : out std_logic; -- Transmitter Source Synchronous Clock-
L2P_CLKp : out std_logic; -- Transmitter Source Synchronous Clock+
L2P_EDB : out std_logic; -- Packet termination and discard
-- Outbound Buffer Status
L2P_RDY : in std_logic; -- Tx Buffer Full Flag
L_WR_RDY : in std_logic_vector(1 downto 0); -- Local-to-PCIe Write
P_RD_D_RDY : in std_logic_vector(1 downto 0); -- PCIe-to-Local Read Response Data Ready
TX_ERROR : in std_logic; -- Transmit Error
VC_RDY : in std_logic_vector(1 downto 0); -- Channel ready
-- Font panel LEDs
LED_RED : out std_logic;
LED_GREEN : out std_logic;
-- User IO (eSATA connector)
USER_IO_0_P : out std_logic;
USER_IO_0_N : out std_logic;
USER_IO_1_P : out std_logic;
USER_IO_1_N : out std_logic;
-- FMC connector management signals
PRSNT_M2C_L : in std_logic;
PG_C2M : out std_logic;
M2C_DIR : in std_logic; -- HPC only
FPGA_SDA : inout std_logic;
FPGA_SCL : out std_logic;
TMS_TO_FMC_P1V8 : out std_logic;
TDO_FROM_FMC_P1V8 : in std_logic;
TDI_TO_FMC_P1V8 : out std_logic;
TCK_TO_FMC_P1V8 : out std_logic;
-- FMC connector clock inputs
CLK1_M2C_P : in std_logic;
CLK1_M2C_N : in std_logic;
CLK0_M2C_P : in std_logic;
CLK0_M2C_N : in std_logic;
-- FMC connector user defined signals
LA33_P : out std_logic;
LA33_N : out std_logic;
LA32_P : out std_logic;
LA32_N : out std_logic;
LA31_P : out std_logic;
LA31_N : out std_logic;
LA30_P : out std_logic;
LA30_N : out std_logic;
LA29_P : out std_logic;
LA29_N : out std_logic;
LA28_P : out std_logic;
LA28_N : out std_logic;
LA27_P : out std_logic;
LA27_N : out std_logic;
LA26_P : out std_logic;
LA26_N : out std_logic;
LA25_P : out std_logic;
LA25_N : out std_logic;
LA24_P : out std_logic;
LA24_N : out std_logic;
LA23_P : out std_logic;
LA23_N : out std_logic;
LA22_P : out std_logic;
LA22_N : out std_logic;
LA21_P : out std_logic;
LA21_N : out std_logic;
LA20_P : out std_logic;
LA20_N : out std_logic;
LA19_P : out std_logic;
LA19_N : out std_logic;
LA18_P : out std_logic;
LA18_N : out std_logic;
LA17_P : out std_logic;
LA17_N : out std_logic;
LA16_P : out std_logic;
LA16_N : out std_logic;
LA15_P : out std_logic;
LA15_N : out std_logic;
LA14_P : out std_logic;
LA14_N : out std_logic;
LA13_P : out std_logic;
LA13_N : out std_logic;
LA12_P : out std_logic;
LA12_N : out std_logic;
LA11_P : out std_logic;
LA11_N : out std_logic;
LA10_P : in std_logic;
LA10_N : out std_logic;
LA09_P : out std_logic;
LA09_N : out std_logic;
LA08_P : out std_logic;
LA08_N : out std_logic;
LA07_P : out std_logic;
LA07_N : out std_logic;
LA06_P : out std_logic;
LA06_N : out std_logic;
LA05_P : out std_logic;
LA05_N : out std_logic;
LA04_P : out std_logic;
LA04_N : out std_logic;
LA03_P : out std_logic;
LA03_N : out std_logic;
LA02_P : out std_logic;
LA02_N : out std_logic;
LA01_P : in std_logic;
LA01_N : out std_logic;
LA00_P : out std_logic;
LA00_N : out std_logic;
-- SPI interface
SCLK_V_MON_P1V8 : out std_logic;
DIN_V_MON : out std_logic;
CSVR_V_MON_P1V8 : out std_logic; -- Digital potentiometer for VADJ
-- Power supplies control
ENABLE_VADJ : out std_logic;
-- DDR3 interface
ddr3_a_o : out std_logic_vector(13 downto 0);
ddr3_ba_o : out std_logic_vector(2 downto 0);
ddr3_cas_n_o : out std_logic;
ddr3_clk_p_o : out std_logic;
ddr3_clk_n_o : out std_logic;
ddr3_cke_o : out std_logic;
ddr3_dm_o : out std_logic;
ddr3_dq_b : inout std_logic_vector(15 downto 0);
ddr3_dqs_p_b : inout std_logic;
ddr3_dqs_n_b : inout std_logic;
ddr3_odt_o : out std_logic;
ddr3_ras_n_o : out std_logic;
ddr3_rst_n_o : out std_logic;
ddr3_udm_o : out std_logic;
ddr3_udqs_p_b : inout std_logic;
ddr3_udqs_n_b : inout std_logic;
ddr3_we_n_o : out std_logic;
ddr3_rzq_b : inout std_logic;
ddr3_zio_b : inout std_logic
);
end component; --pfc_top;
------------------------------------------------------------------------------
-- DDR3 model
------------------------------------------------------------------------------
component ddr3
port (
rst_n : in std_logic;
ck : in std_logic;
ck_n : in std_logic;
cke : in std_logic;
cs_n : in std_logic;
ras_n : in std_logic;
cas_n : in std_logic;
we_n : in std_logic;
dm_tdqs : inout std_logic_vector(1 downto 0);
ba : in std_logic_vector(2 downto 0);
addr : in std_logic_vector(13 downto 0);
dq : inout std_logic_vector(15 downto 0);
dqs : inout std_logic_vector(1 downto 0);
dqs_n : inout std_logic_vector(1 downto 0);
tdqs_n : out std_logic_vector(1 downto 0);
odt : in std_logic
);
end component;
--###########################################################################
--###########################################################################
--##
--## Constants
--##
--###########################################################################
--###########################################################################
--
-- Number of Models receiving commands
constant N_BFM : integer := 2; -- 0 : GN412X_BFM in Model Mode
-- -- 1 : GN412X_BFM in DUT mode
-- Number of files to feed BFMs
constant N_FILES : integer := 2;
--
-- Depth of the command FIFO for each model
constant FIFO_DEPTH : integer := 16;
--
-- Maximum width of a command string
constant STRING_MAX : integer := 256;
--
--###########################################################################
--###########################################################################
--##
--## Signals
--##
--###########################################################################
--###########################################################################
-----------------------------------------------------------------------------
-- Command Router Signals
-----------------------------------------------------------------------------
signal CMD : string(1 to STRING_MAX);
signal CMD_REQ : bit_vector(N_BFM-1 downto 0);
signal CMD_ACK : bit_vector(N_BFM-1 downto 0);
signal CMD_ERR : bit_vector(N_BFM-1 downto 0);
signal CMD_CLOCK_EN : boolean;
-----------------------------------------------------------------------------
-- GN412x BFM Signals
-----------------------------------------------------------------------------
signal RSTINn : std_logic;
signal RSTOUT18n : std_logic;
signal RSTOUT33n : std_logic;
signal LCLK, LCLKn : std_logic;
signal L2P_CLKp, L2P_CLKn : std_logic;
signal L2P_DATA : std_logic_vector(15 downto 0);
signal L2P_DATA_32 : std_logic_vector(31 downto 0); -- For monitoring use
signal L2P_DFRAME : std_logic;
signal L2P_VALID : std_logic;
signal L2P_EDB : std_logic;
signal L_WR_RDY : std_logic_vector(1 downto 0);
signal P_RD_D_RDY : std_logic_vector(1 downto 0);
signal L2P_RDY : std_logic;
signal TX_ERROR : std_logic;
signal P2L_CLKp, P2L_CLKn : std_logic;
signal P2L_DATA : std_logic_vector(15 downto 0);
signal P2L_DATA_32 : std_logic_vector(31 downto 0); -- For monitoring use
signal P2L_DFRAME : std_logic;
signal P2L_VALID : std_logic;
signal P2L_RDY : std_logic;
signal P_WR_REQ : std_logic_vector(1 downto 0);
signal P_WR_RDY : std_logic_vector(1 downto 0);
signal RX_ERROR : std_logic;
signal VC_RDY : std_logic_vector(1 downto 0);
signal GPIO : std_logic_vector(15 downto 0);
-- Font panel LEDs
signal LED_RED : std_logic;
signal LED_GREEN : std_logic;
-- User IO (eSATA connector)
signal USER_IO_0_P : std_logic;
signal USER_IO_0_N : std_logic;
signal USER_IO_1_P : std_logic;
signal USER_IO_1_N : std_logic;
-- FMC connector management signals
signal PRSNT_M2C_L : std_logic := '0';
signal PG_C2M : std_logic;
signal M2C_DIR : std_logic := '0';
signal FPGA_SDA : std_logic := 'Z';
signal FPGA_SCL : std_logic;
signal TMS_TO_FMC_P1V8 : std_logic;
signal TDO_FROM_FMC_P1V8 : std_logic := '0';
signal TDI_TO_FMC_P1V8 : std_logic;
signal TCK_TO_FMC_P1V8 : std_logic;
-- FMC connector clock inputs
signal CLK1_M2C_P : std_logic := '0';
signal CLK1_M2C_N : std_logic := '0';
signal CLK0_M2C_P : std_logic := '0';
signal CLK0_M2C_N : std_logic := '0';
-- FMC connector user defined signals
signal LA33_P : std_logic;
signal LA33_N : std_logic;
signal LA32_P : std_logic;
signal LA32_N : std_logic;
signal LA31_P : std_logic;
signal LA31_N : std_logic;
signal LA30_P : std_logic;
signal LA30_N : std_logic;
signal LA29_P : std_logic;
signal LA29_N : std_logic;
signal LA28_P : std_logic;
signal LA28_N : std_logic;
signal LA27_P : std_logic;
signal LA27_N : std_logic;
signal LA26_P : std_logic;
signal LA26_N : std_logic;
signal LA25_P : std_logic;
signal LA25_N : std_logic;
signal LA24_P : std_logic;
signal LA24_N : std_logic;
signal LA23_P : std_logic;
signal LA23_N : std_logic;
signal LA22_P : std_logic;
signal LA22_N : std_logic;
signal LA21_P : std_logic;
signal LA21_N : std_logic;
signal LA20_P : std_logic;
signal LA20_N : std_logic;
signal LA19_P : std_logic;
signal LA19_N : std_logic;
signal LA18_P : std_logic;
signal LA18_N : std_logic;
signal LA17_P : std_logic;
signal LA17_N : std_logic;
signal LA16_P : std_logic;
signal LA16_N : std_logic;
signal LA15_P : std_logic;
signal LA15_N : std_logic;
signal LA14_P : std_logic;
signal LA14_N : std_logic;
signal LA13_P : std_logic;
signal LA13_N : std_logic;
signal LA12_P : std_logic;
signal LA12_N : std_logic;
signal LA11_P : std_logic;
signal LA11_N : std_logic;
signal LA10_P : std_logic := '0';
signal LA10_N : std_logic;
signal LA09_P : std_logic;
signal LA09_N : std_logic;
signal LA08_P : std_logic;
signal LA08_N : std_logic;
signal LA07_P : std_logic;
signal LA07_N : std_logic;
signal LA06_P : std_logic;
signal LA06_N : std_logic;
signal LA05_P : std_logic;
signal LA05_N : std_logic;
signal LA04_P : std_logic;
signal LA04_N : std_logic;
signal LA03_P : std_logic;
signal LA03_N : std_logic;
signal LA02_P : std_logic;
signal LA02_N : std_logic;
signal LA01_P : std_logic := '0';
signal LA01_N : std_logic;
signal LA00_P : std_logic;
signal LA00_N : std_logic;
-- SPI interface
signal SCLK_V_MON_P1V8 : std_logic;
signal DIN_V_MON : std_logic;
signal CSVR_V_MON_P1V8 : std_logic;
-- Power supplies control
signal ENABLE_VADJ : std_logic;
-- DDR3 interface
signal ddr3_a_o : std_logic_vector(13 downto 0);
signal ddr3_ba_o : std_logic_vector(2 downto 0);
signal ddr3_cas_n_o : std_logic;
signal ddr3_clk_p_o : std_logic;
signal ddr3_clk_n_o : std_logic;
signal ddr3_cke_o : std_logic;
signal ddr3_dm_b : std_logic_vector(1 downto 0) := (others => 'Z');
signal ddr3_dq_b : std_logic_vector(15 downto 0) := (others => 'Z');
signal ddr3_dqs_p_b : std_logic_vector(1 downto 0) := (others => 'Z');
signal ddr3_dqs_n_b : std_logic_vector(1 downto 0) := (others => 'Z');
signal ddr3_odt_o : std_logic;
signal ddr3_ras_n_o : std_logic;
signal ddr3_rst_n_o : std_logic;
signal ddr3_dm_o : std_logic;
signal ddr3_udm_o : std_logic;
--signal ddr3_udqs_p_b : std_logic := 'Z';
--signal ddr3_udqs_n_b : std_logic := 'Z';
signal ddr3_we_n_o : std_logic;
signal ddr3_rzq_b : std_logic;
signal ddr3_zio_b : std_logic := 'Z';
-- 25MHz system clock
signal SYS_CLK_P : std_logic;
signal SYS_CLK_N : std_logic;
-----------------------------------------------------------------------------
-- Bus Monitor Signals
-----------------------------------------------------------------------------
signal Q_P2L_DFRAME : std_logic;
signal SIMPLE_TEST : std_logic_vector(15 downto 0);
--###########################################################################
--###########################################################################
--##
--## Start of Code
--##
--###########################################################################
--###########################################################################
begin
-----------------------------------------------------------------------------
-- MODEL Component
-----------------------------------------------------------------------------
CMD_ERR <= (others => '0');
UC : cmd_router
generic map
(N_BFM => N_BFM,
N_FILES => N_FILES,
FIFO_DEPTH => FIFO_DEPTH,
STRING_MAX => STRING_MAX
)
port map
(CMD => CMD,
CMD_REQ => CMD_REQ,
CMD_ACK => CMD_ACK,
CMD_ERR => CMD_ERR,
CMD_CLOCK_EN => CMD_CLOCK_EN
);
-----------------------------------------------------------------------------
-- GN412x BFM - PRIMARY
-----------------------------------------------------------------------------
U0 : gn412x_bfm
generic map
(
STRING_MAX => STRING_MAX,
T_LCLK => 10 ns,
T_P2L_CLK_DLY => 2 ns,
INSTANCE_LABEL => "U0(Primary GN412x): ",
MODE_PRIMARY => true
)
port map
(
--=========================================================--
-------------------------------------------------------------
-- CMD_ROUTER Interface
--
CMD => CMD,
CMD_REQ => CMD_REQ(0),
CMD_ACK => CMD_ACK(0),
CMD_CLOCK_EN => CMD_CLOCK_EN,
--=========================================================--
-------------------------------------------------------------
-- GN412x Signal I/O
-------------------------------------------------------------
-- This is the reset input to the BFM
--
RSTINn => RSTINn,
-------------------------------------------------------------
-- Reset outputs to DUT
--
RSTOUT18n => RSTOUT18n,
RSTOUT33n => RSTOUT33n,
-------------------------------------------------------------
----------------- Local Bus Clock ---------------------------
-------------------------------------------------------------
--
LCLK => LCLK,
LCLKn => LCLKn,
-------------------------------------------------------------
----------------- Local-to-PCI Dataflow ---------------------
-------------------------------------------------------------
-- Transmitter Source Synchronous Clock.
--
L2P_CLKp => L2P_CLKp,
L2P_CLKn => L2P_CLKn,
-------------------------------------------------------------
-- L2P DDR Link
--
L2P_DATA => L2P_DATA,
L2P_DFRAME => L2P_DFRAME,
L2P_VALID => L2P_VALID,
L2P_EDB => L2P_EDB,
-------------------------------------------------------------
-- L2P SDR Controls
--
L_WR_RDY => L_WR_RDY,
P_RD_D_RDY => P_RD_D_RDY,
L2P_RDY => L2P_RDY,
TX_ERROR => TX_ERROR,
-------------------------------------------------------------
----------------- PCIe-to-Local Dataflow ---------------------
-------------------------------------------------------------
-- Transmitter Source Synchronous Clock.
--
P2L_CLKp => P2L_CLKp,
P2L_CLKn => P2L_CLKn,
-------------------------------------------------------------
-- P2L DDR Link
--
P2L_DATA => P2L_DATA,
P2L_DFRAME => P2L_DFRAME,
P2L_VALID => P2L_VALID,
-------------------------------------------------------------
-- P2L SDR Controls
--
P2L_RDY => P2L_RDY,
P_WR_REQ => P_WR_REQ,
P_WR_RDY => P_WR_RDY,
RX_ERROR => RX_ERROR,
VC_RDY => VC_RDY,
GPIO => gpio
); -- GN412X_BFM;
-----------------------------------------------------------------------------
-- UUT
-----------------------------------------------------------------------------
U1 : pfc_top
generic map (
g_SIMULATION => "TRUE",
g_CALIB_SOFT_IP => "FALSE")
port map (
-- Global ports
SYS_CLK_P => SYS_CLK_P,
SYS_CLK_N => SYS_CLK_N,
-- From GN4124 Local bus
l_clkp => LCLK, -- Running at 200 Mhz
l_clkn => LCLKn, -- Running at 200 Mhz
l_rst_n => RSTOUT18n,
-- General Purpose Interface
gpio => GPIO(9 downto 8), -- General Purpose Input/Output
-- PCIe to Local [Inbound Data] - RX
p2l_rdy => P2L_RDY, -- Rx Buffer Full Flag
p2l_clkn => P2L_CLKn, -- Receiver Source Synchronous Clock-
p2l_clkp => P2L_CLKp, -- Receiver Source Synchronous Clock+
p2l_data => P2L_DATA, -- Parallel receive data
p2l_dframe => P2L_DFRAME, -- Receive Frame
p2l_valid => P2L_VALID, -- Receive Data Valid
-- Inbound Buffer Request/Status
p_wr_req => P_WR_REQ, -- PCIe Write Request
p_wr_rdy => P_WR_RDY, -- PCIe Write Ready
rx_error => RX_ERROR, -- Receive Error
-- Local to Parallel [Outbound Data] - TX
l2p_data => L2P_DATA, -- Parallel transmit data
l2p_dframe => L2P_DFRAME, -- Transmit Data Frame
l2p_valid => L2P_VALID, -- Transmit Data Valid
l2p_clkn => L2P_CLKn, -- Transmitter Source Synchronous Clock-
l2p_clkp => L2P_CLKp, -- Transmitter Source Synchronous Clock+
l2p_edb => L2P_EDB, -- Packet termination and discard
-- Outbound Buffer Status
l2p_rdy => L2P_RDY, -- Tx Buffer Full Flag
l_wr_rdy => L_WR_RDY, -- Local-to-PCIe Write
p_rd_d_rdy => P_RD_D_RDY, -- PCIe-to-Local Read Response Data Ready
tx_error => TX_ERROR, -- Transmit Error
vc_rdy => VC_RDY, -- Channel ready
-- Font panel LEDs
LED_RED => LED_RED,
LED_GREEN => LED_GREEN,
-- User IO (eSATA connector)
USER_IO_0_P => USER_IO_0_P,
USER_IO_0_N => USER_IO_0_N,
USER_IO_1_P => USER_IO_1_P,
USER_IO_1_N => USER_IO_1_N,
-- FMC connector management signals
PRSNT_M2C_L => PRSNT_M2C_L,
PG_C2M => PG_C2M,
M2C_DIR => M2C_DIR,
FPGA_SDA => FPGA_SDA,
FPGA_SCL => FPGA_SCL,
TMS_TO_FMC_P1V8 => TMS_TO_FMC_P1V8,
TDO_FROM_FMC_P1V8 => TDO_FROM_FMC_P1V8,
TDI_TO_FMC_P1V8 => TDI_TO_FMC_P1V8,
TCK_TO_FMC_P1V8 => TCK_TO_FMC_P1V8,
-- FMC connector clock inputs
CLK1_M2C_P => CLK1_M2C_P,
CLK1_M2C_N => CLK1_M2C_N,
CLK0_M2C_P => CLK0_M2C_P,
CLK0_M2C_N => CLK0_M2C_N,
-- FMC connector user defined signals
LA33_P => LA33_P,
LA33_N => LA33_N,
LA32_P => LA32_P,
LA32_N => LA32_N,
LA31_P => LA31_P,
LA31_N => LA31_N,
LA30_P => LA30_P,
LA30_N => LA30_N,
LA29_P => LA29_P,
LA29_N => LA29_N,
LA28_P => LA28_P,
LA28_N => LA28_N,
LA27_P => LA27_P,
LA27_N => LA27_N,
LA26_P => LA26_P,
LA26_N => LA26_N,
LA25_P => LA25_P,
LA25_N => LA25_N,
LA24_P => LA24_P,
LA24_N => LA24_N,
LA23_P => LA23_P,
LA23_N => LA23_N,
LA22_P => LA22_P,
LA22_N => LA22_N,
LA21_P => LA21_P,
LA21_N => LA21_N,
LA20_P => LA20_P,
LA20_N => LA20_N,
LA19_P => LA19_P,
LA19_N => LA19_N,
LA18_P => LA18_P,
LA18_N => LA18_N,
LA17_P => LA17_P,
LA17_N => LA17_N,
LA16_P => LA16_P,
LA16_N => LA16_N,
LA15_P => LA15_P,
LA15_N => LA15_N,
LA14_P => LA14_P,
LA14_N => LA14_N,
LA13_P => LA13_P,
LA13_N => LA13_N,
LA12_P => LA12_P,
LA12_N => LA12_N,
LA11_P => LA11_P,
LA11_N => LA11_N,
LA10_P => LA10_P,
LA10_N => LA10_N,
LA09_P => LA09_P,
LA09_N => LA09_N,
LA08_P => LA08_P,
LA08_N => LA08_N,
LA07_P => LA07_P,
LA07_N => LA07_N,
LA06_P => LA06_P,
LA06_N => LA06_N,
LA05_P => LA05_P,
LA05_N => LA05_N,
LA04_P => LA04_P,
LA04_N => LA04_N,
LA03_P => LA03_P,
LA03_N => LA03_N,
LA02_P => LA02_P,
LA02_N => LA02_N,
LA01_P => LA01_P,
LA01_N => LA01_N,
LA00_P => LA00_P,
LA00_N => LA00_N,
-- SPI interface
SCLK_V_MON_P1V8 => SCLK_V_MON_P1V8,
DIN_V_MON => DIN_V_MON,
CSVR_V_MON_P1V8 => CSVR_V_MON_P1V8,
-- Power supplies control
ENABLE_VADJ => ENABLE_VADJ,
-- DDR3 interface
ddr3_a_o => ddr3_a_o,
ddr3_ba_o => ddr3_ba_o,
ddr3_cas_n_o => ddr3_cas_n_o,
ddr3_clk_p_o => ddr3_clk_p_o,
ddr3_clk_n_o => ddr3_clk_n_o,
ddr3_cke_o => ddr3_cke_o,
ddr3_dm_o => ddr3_dm_b(0),
ddr3_dq_b => ddr3_dq_b,
ddr3_dqs_p_b => ddr3_dqs_p_b(0),
ddr3_dqs_n_b => ddr3_dqs_n_b(0),
ddr3_odt_o => ddr3_odt_o,
ddr3_ras_n_o => ddr3_ras_n_o,
ddr3_rst_n_o => ddr3_rst_n_o,
ddr3_udm_o => ddr3_dm_b(1),
ddr3_udqs_p_b => ddr3_dqs_p_b(1),
ddr3_udqs_n_b => ddr3_dqs_n_b(1),
ddr3_we_n_o => ddr3_we_n_o,
ddr3_rzq_b => ddr3_rzq_b,
ddr3_zio_b => ddr3_zio_b
);
cmp_ddr3_model : ddr3
port map(
rst_n => ddr3_rst_n_o,
ck => ddr3_clk_p_o,
ck_n => ddr3_clk_n_o,
cke => ddr3_cke_o,
cs_n => '0', -- Pulled down on PCB
ras_n => ddr3_ras_n_o,
cas_n => ddr3_cas_n_o,
we_n => ddr3_we_n_o,
dm_tdqs => ddr3_dm_b,
ba => ddr3_ba_o,
addr => ddr3_a_o,
dq => ddr3_dq_b,
dqs => ddr3_dqs_p_b,
dqs_n => ddr3_dqs_n_b,
tdqs_n => open, -- dqs outputs for chaining
odt => ddr3_odt_o
);
process
variable vP2L_DATA_LOW : std_logic_vector(P2L_DATA'range);
begin
wait until(P2L_CLKp'event and (P2L_CLKp = '1'));
vP2L_DATA_LOW := P2L_DATA;
loop
wait on P2L_DATA, P2L_CLKp;
P2L_DATA_32 <= P2L_DATA & vP2L_DATA_LOW;
if(P2L_CLKp = '0') then
exit;
end if;
end loop;
end process;
sys_clk : process
begin
SYS_CLK_P <= '1';
SYS_CLK_N <= '0';
wait for 20 ns;
SYS_CLK_P <= '0';
SYS_CLK_N <= '1';
wait for 20 ns;
end process sys_clk;
end TEST;
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.NUMERIC_STD.all;
use std.textio.all;
--library std_developerskit;
--use std_developerskit.std_iopak.all;
use work.util.all;
use work.textutil.all;
--############################################################################
--############################################################################
--==========================================================================--
--
-- *Module : tb_spec
--
-- *Description : Test Bench for the GN4124 BFM + SPEC Design
--
-- *History
--
--==========================================================================--
--############################################################################
--############################################################################
entity TB_SPEC is
generic
(
T_LCLK : time := 30 ns -- Default LCLK Clock Period
);
end TB_SPEC;
architecture TEST of TB_SPEC is
--###########################################################################
--###########################################################################
--##
--## Component Declairations
--##
--###########################################################################
--###########################################################################
-----------------------------------------------------------------------------
-- GN4124 Local Bus Model
-----------------------------------------------------------------------------
component GN412X_BFM
generic
(
STRING_MAX : integer := 256; -- Command string maximum length
T_LCLK : time := 10 ns; -- Local Bus Clock Period
T_P2L_CLK_DLY : time := 2 ns; -- Delay from LCLK to P2L_CLK
INSTANCE_LABEL : string := "GN412X_BFM"; -- Label string to be used as a prefix for messages from the model
MODE_PRIMARY : boolean := true -- TRUE for BFM acting as GN412x, FALSE for BFM acting as the DUT
);
port
(
--=========================================================--
-------------------------------------------------------------
-- CMD_ROUTER Interface
--
CMD : in string(1 to STRING_MAX);
CMD_REQ : in bit;
CMD_ACK : out bit;
CMD_CLOCK_EN : in boolean;
--=========================================================--
-------------------------------------------------------------
-- GN412x Signal I/O
-------------------------------------------------------------
-- This is the reset input to the BFM
--
RSTINn : in std_logic;
-------------------------------------------------------------
-- Reset outputs to DUT
--
RSTOUT18n : out std_logic;
RSTOUT33n : out std_logic;
-------------------------------------------------------------
----------------- Local Bus Clock ---------------------------
------------------------------------------------------------- __ Direction for primary mode
-- / \
LCLK, LCLKn : inout std_logic; -- Out
-------------------------------------------------------------
----------------- Local-to-PCI Dataflow ---------------------
-------------------------------------------------------------
-- Transmitter Source Synchronous Clock.
--
L2P_CLKp, L2P_CLKn : inout std_logic; -- In
-------------------------------------------------------------
-- L2P DDR Link
--
L2P_DATA : inout std_logic_vector(15 downto 0); -- In -- Parallel Transmit Data.
L2P_DFRAME : inout std_logic; -- In -- Transmit Data Frame.
L2P_VALID : inout std_logic; -- In -- Transmit Data Valid.
L2P_EDB : inout std_logic; -- In -- End-of-Packet Bad Flag.
-------------------------------------------------------------
-- L2P SDR Controls
--
L_WR_RDY : inout std_logic_vector(1 downto 0); -- Out -- Local-to-PCIe Write.
P_RD_D_RDY : inout std_logic_vector(1 downto 0); -- Out -- PCIe-to-Local Read Response Data Ready.
L2P_RDY : inout std_logic; -- Out -- Tx Buffer Full Flag.
TX_ERROR : inout std_logic; -- Out -- Transmit Error.
-------------------------------------------------------------
----------------- PCIe-to-Local Dataflow ---------------------
-------------------------------------------------------------
-- Transmitter Source Synchronous Clock.
--
P2L_CLKp, P2L_CLKn : inout std_logic; -- Out -- P2L Source Synchronous Clock.
-------------------------------------------------------------
-- P2L DDR Link
--
P2L_DATA : inout std_logic_vector(15 downto 0); -- Out -- Parallel Receive Data.
P2L_DFRAME : inout std_logic; -- Out -- Receive Frame.
P2L_VALID : inout std_logic; -- Out -- Receive Data Valid.
-------------------------------------------------------------
-- P2L SDR Controls
--
P2L_RDY : inout std_logic; -- In -- Rx Buffer Full Flag.
P_WR_REQ : inout std_logic_vector(1 downto 0); -- Out -- PCIe Write Request.
P_WR_RDY : inout std_logic_vector(1 downto 0); -- In -- PCIe Write Ready.
RX_ERROR : inout std_logic; -- In -- Receive Error.
VC_RDY : inout std_logic_vector(1 downto 0); -- Out -- Virtual Channel Ready Status.
-------------------------------------------------------------
-- GPIO signals
--
GPIO : inout std_logic_vector(15 downto 0)
);
end component; --GN412X_BFM;
-----------------------------------------------------------------------------
-- CMD_ROUTER component
-----------------------------------------------------------------------------
component cmd_router
generic(N_BFM : integer := 8;
N_FILES : integer := 3;
FIFO_DEPTH : integer := 8;
STRING_MAX : integer := 256
);
port(CMD : out string(1 to STRING_MAX);
CMD_REQ : out bit_vector(N_BFM-1 downto 0);
CMD_ACK : in bit_vector(N_BFM-1 downto 0);
CMD_ERR : in bit_vector(N_BFM-1 downto 0);
CMD_CLOCK_EN : out boolean
);
end component; --cmd_router;
-----------------------------------------------------------------------------
-- CMD_ROUTER component
-----------------------------------------------------------------------------
component simple
port(
clk : in std_logic;
d : in std_logic_vector(15 downto 0);
q : out std_logic_vector(15 downto 0)
);
end component;
-----------------------------------------------------------------------------
-- Design top entity
-----------------------------------------------------------------------------
component spec_gn4124_test
port
(
-- Local oscillator
clk20_vcxo_i : in std_logic; -- 20MHz VCXO clock
-- Carrier font panel LEDs
LED_RED_O : out std_logic;
LED_GREEN_O : out std_logic;
-- Auxiliary pins
AUX_LEDS_O : out std_logic_vector(3 downto 0);
AUX_BUTTONS_I : in std_logic_vector(1 downto 0);
-- GN4124 interface
L_CLKp : in std_logic; -- Local bus clock (frequency set in GN4124 config registers)
L_CLKn : in std_logic; -- Local bus clock (frequency set in GN4124 config registers)
L_RST_N : in std_logic; -- Reset from GN4124 (RSTOUT18_N)
P2L_RDY : out std_logic; -- Rx Buffer Full Flag
P2L_CLKn : in std_logic; -- Receiver Source Synchronous Clock-
P2L_CLKp : in std_logic; -- Receiver Source Synchronous Clock+
P2L_DATA : in std_logic_vector(15 downto 0); -- Parallel receive data
P2L_DFRAME : in std_logic; -- Receive Frame
P2L_VALID : in std_logic; -- Receive Data Valid
P_WR_REQ : in std_logic_vector(1 downto 0); -- PCIe Write Request
P_WR_RDY : out std_logic_vector(1 downto 0); -- PCIe Write Ready
RX_ERROR : out std_logic; -- Receive Error
L2P_DATA : out std_logic_vector(15 downto 0); -- Parallel transmit data
L2P_DFRAME : out std_logic; -- Transmit Data Frame
L2P_VALID : out std_logic; -- Transmit Data Valid
L2P_CLKn : out std_logic; -- Transmitter Source Synchronous Clock-
L2P_CLKp : out std_logic; -- Transmitter Source Synchronous Clock+
L2P_EDB : out std_logic; -- Packet termination and discard
L2P_RDY : in std_logic; -- Tx Buffer Full Flag
L_WR_RDY : in std_logic_vector(1 downto 0); -- Local-to-PCIe Write
P_RD_D_RDY : in std_logic_vector(1 downto 0); -- PCIe-to-Local Read Response Data Ready
TX_ERROR : in std_logic; -- Transmit Error
VC_RDY : in std_logic_vector(1 downto 0); -- Channel ready
GPIO : inout std_logic_vector(1 downto 0); -- GPIO[0] -> GN4124 GPIO8
-- GPIO[1] -> GN4124 GPIO9
-- PCB version
pcb_ver_i : in std_logic_vector(3 downto 0)
);
end component spec_gn4124_test;
--###########################################################################
--###########################################################################
--##
--## Constants
--##
--###########################################################################
--###########################################################################
--
-- Number of Models receiving commands
constant N_BFM : integer := 2; -- 0 : GN412X_BFM in Model Mode
-- -- 1 : GN412X_BFM in DUT mode
-- Number of files to feed BFMs
constant N_FILES : integer := 2;
--
-- Depth of the command FIFO for each model
constant FIFO_DEPTH : integer := 16;
--
-- Maximum width of a command string
constant STRING_MAX : integer := 256;
--###########################################################################
--###########################################################################
--##
--## Signals
--##
--###########################################################################
--###########################################################################
-----------------------------------------------------------------------------
-- Command Router Signals
-----------------------------------------------------------------------------
signal CMD : string(1 to STRING_MAX);
signal CMD_REQ : bit_vector(N_BFM-1 downto 0);
signal CMD_ACK : bit_vector(N_BFM-1 downto 0);
signal CMD_ERR : bit_vector(N_BFM-1 downto 0);
signal CMD_CLOCK_EN : boolean;
-----------------------------------------------------------------------------
-- GN412x BFM Signals
-----------------------------------------------------------------------------
-- System signals
signal clk20_vcxo_i : std_logic := '0'; -- 20MHz VCXO clock
-- GN4124 interface
signal RSTINn : std_logic;
signal RSTOUT18n : std_logic;
signal RSTOUT33n : std_logic;
signal LCLK, LCLKn : std_logic;
signal L2P_CLKp, L2P_CLKn : std_logic;
signal L2P_DATA : std_logic_vector(15 downto 0);
signal L2P_DATA_32 : std_logic_vector(31 downto 0); -- For monitoring use
signal L2P_DFRAME : std_logic;
signal L2P_VALID : std_logic;
signal L2P_EDB : std_logic;
signal L_WR_RDY : std_logic_vector(1 downto 0);
signal P_RD_D_RDY : std_logic_vector(1 downto 0);
signal L2P_RDY : std_logic;
signal TX_ERROR : std_logic;
signal P2L_CLKp, P2L_CLKn : std_logic;
signal P2L_DATA : std_logic_vector(15 downto 0);
signal P2L_DATA_32 : std_logic_vector(31 downto 0); -- For monitoring use
signal P2L_DFRAME : std_logic;
signal P2L_VALID : std_logic;
signal P2L_RDY : std_logic;
signal P_WR_REQ : std_logic_vector(1 downto 0);
signal P_WR_RDY : std_logic_vector(1 downto 0);
signal RX_ERROR : std_logic;
signal VC_RDY : std_logic_vector(1 downto 0);
signal GPIO : std_logic_vector(15 downto 0);
-- Aux signals
signal LED_RED : std_logic;
signal LED_GREEN : std_logic;
signal AUX_BUTTONS : std_logic_vector(1 downto 0);
signal AUX_LEDS : std_logic_vector(3 downto 0);
signal PCB_VER : std_logic_vector(3 downto 0) := "0011";
-----------------------------------------------------------------------------
-- Bus Monitor Signals
-----------------------------------------------------------------------------
signal Q_P2L_DFRAME : std_logic;
signal SIMPLE_TEST : std_logic_vector(15 downto 0);
--###########################################################################
--###########################################################################
--##
--## Start of Code
--##
--###########################################################################
--###########################################################################
begin
-----------------------------------------------------------------------------
-- MODEL Component
-----------------------------------------------------------------------------
CMD_ERR <= (others => '0');
UC : cmd_router
generic map
(N_BFM => N_BFM,
N_FILES => N_FILES,
FIFO_DEPTH => FIFO_DEPTH,
STRING_MAX => STRING_MAX
)
port map
(CMD => CMD,
CMD_REQ => CMD_REQ,
CMD_ACK => CMD_ACK,
CMD_ERR => CMD_ERR,
CMD_CLOCK_EN => CMD_CLOCK_EN
);
-----------------------------------------------------------------------------
-- GN412x BFM - PRIMARY
-----------------------------------------------------------------------------
U0 : gn412x_bfm
generic map
(
STRING_MAX => STRING_MAX,
T_LCLK => 6.25 ns,
T_P2L_CLK_DLY => 2 ns,
INSTANCE_LABEL => "U0(Primary GN412x): ",
MODE_PRIMARY => true
)
port map
(
--=========================================================--
-------------------------------------------------------------
-- CMD_ROUTER Interface
--
CMD => CMD,
CMD_REQ => CMD_REQ(0),
CMD_ACK => CMD_ACK(0),
CMD_CLOCK_EN => CMD_CLOCK_EN,
--=========================================================--
-------------------------------------------------------------
-- GN412x Signal I/O
-------------------------------------------------------------
-- This is the reset input to the BFM
--
RSTINn => RSTINn,
-------------------------------------------------------------
-- Reset outputs to DUT
--
RSTOUT18n => RSTOUT18n,
RSTOUT33n => RSTOUT33n,
-------------------------------------------------------------
----------------- Local Bus Clock ---------------------------
-------------------------------------------------------------
--
LCLK => LCLK,
LCLKn => LCLKn,
-------------------------------------------------------------
----------------- Local-to-PCI Dataflow ---------------------
-------------------------------------------------------------
-- Transmitter Source Synchronous Clock.
--
L2P_CLKp => L2P_CLKp,
L2P_CLKn => L2P_CLKn,
-------------------------------------------------------------
-- L2P DDR Link
--
L2P_DATA => L2P_DATA,
L2P_DFRAME => L2P_DFRAME,
L2P_VALID => L2P_VALID,
L2P_EDB => L2P_EDB,
-------------------------------------------------------------
-- L2P SDR Controls
--
L_WR_RDY => L_WR_RDY,
P_RD_D_RDY => P_RD_D_RDY,
L2P_RDY => L2P_RDY,
TX_ERROR => TX_ERROR,
-------------------------------------------------------------
----------------- PCIe-to-Local Dataflow ---------------------
-------------------------------------------------------------
-- Transmitter Source Synchronous Clock.
--
P2L_CLKp => P2L_CLKp,
P2L_CLKn => P2L_CLKn,
-------------------------------------------------------------
-- P2L DDR Link
--
P2L_DATA => P2L_DATA,
P2L_DFRAME => P2L_DFRAME,
P2L_VALID => P2L_VALID,
-------------------------------------------------------------
-- P2L SDR Controls
--
P2L_RDY => P2L_RDY,
P_WR_REQ => P_WR_REQ,
P_WR_RDY => P_WR_RDY,
RX_ERROR => RX_ERROR,
VC_RDY => VC_RDY,
GPIO => gpio
); -- GN412X_BFM;
-----------------------------------------------------------------------------
-- UUT
-----------------------------------------------------------------------------
U1 : spec_gn4124_test
port map (
clk20_vcxo_i => clk20_vcxo_i,
LED_RED_O => LED_RED,
LED_GREEN_O => LED_GREEN,
AUX_LEDS_O => AUX_LEDS,
AUX_BUTTONS_I => AUX_BUTTONS,
-- GN4124 interface
l_clkp => LCLK, -- Running at 200 Mhz
l_clkn => LCLKn, -- Running at 200 Mhz
l_rst_n => RSTOUT18n,
p2l_rdy => P2L_RDY, -- Rx Buffer Full Flag
p2l_clkn => P2L_CLKn, -- Receiver Source Synchronous Clock-
p2l_clkp => P2L_CLKp, -- Receiver Source Synchronous Clock+
p2l_data => P2L_DATA, -- Parallel receive data
p2l_dframe => P2L_DFRAME, -- Receive Frame
p2l_valid => P2L_VALID, -- Receive Data Valid
p_wr_req => P_WR_REQ, -- PCIe Write Request
p_wr_rdy => P_WR_RDY, -- PCIe Write Ready
rx_error => RX_ERROR, -- Receive Error
l2p_data => L2P_DATA, -- Parallel transmit data
l2p_dframe => L2P_DFRAME, -- Transmit Data Frame
l2p_valid => L2P_VALID, -- Transmit Data Valid
l2p_clkn => L2P_CLKn, -- Transmitter Source Synchronous Clock-
l2p_clkp => L2P_CLKp, -- Transmitter Source Synchronous Clock+
l2p_edb => L2P_EDB, -- Packet termination and discard
l2p_rdy => L2P_RDY, -- Tx Buffer Full Flag
l_wr_rdy => L_WR_RDY, -- Local-to-PCIe Write
p_rd_d_rdy => P_RD_D_RDY, -- PCIe-to-Local Read Response Data Ready
tx_error => TX_ERROR, -- Transmit Error
vc_rdy => VC_RDY, -- Channel ready
gpio => GPIO(9 downto 8), -- General Purpose Input/Output
pcb_ver_i => PCB_VER
);
process
variable vP2L_DATA_LOW : std_logic_vector(P2L_DATA'range);
begin
wait until(P2L_CLKp'event and (P2L_CLKp = '1'));
vP2L_DATA_LOW := P2L_DATA;
loop
wait on P2L_DATA, P2L_CLKp;
P2L_DATA_32 <= P2L_DATA & vP2L_DATA_LOW;
if(P2L_CLKp = '0') then
exit;
end if;
end loop;
end process;
sys_clk : process
begin
clk20_vcxo_i <= '1';
wait for 25 ns;
clk20_vcxo_i <= '0';
wait for 25 ns;
end process sys_clk;
end TEST;
library IEEE;
use IEEE.std_logic_1164.all;
use std.textio.all;
use work.util.all;
-----------------------------------------------------------------------------
-- *Module : textutil
--
-- *Description : Improved Free-format string and line manipulation
--
-- *History: M. Alford (originaly created 1993 with subsequent updates)
-----------------------------------------------------------------------------
package textutil is
procedure read_token(L : inout line; X : out STRING);
procedure sget_token(S : in string; P : inout integer; X : out STRING);
procedure sget_vector(S : in string; P : inout integer; VEC : out STD_ULOGIC_VECTOR);
procedure sget_vector_64(S : in string; P : inout integer; VEC : out STD_ULOGIC_VECTOR);
procedure sget_int(S : in string; P : inout integer; X : out integer);
function hex_char_to_vector(C : in character) return STD_ULOGIC_VECTOR;
function vector_to_hex_char(V : in STD_ULOGIC_VECTOR) return character;
function is_hex(C : in character) return BOOLEAN;
function hex_char_to_int(C : in character) return integer;
procedure read_vector(L : inout line; VEC : out STD_ULOGIC_VECTOR);
procedure read_int(L : inout line; I : out integer);
procedure write_hex_vector(L : inout line; V : in STD_ULOGIC_VECTOR);
function to_str(constant V: in STD_ULOGIC_VECTOR) return STRING;
function to_str(constant V: in STD_ULOGIC) return STRING;
function to_str(constant val : in INTEGER) return STRING;
function to_strn(constant val : in INTEGER; constant n : in INTEGER) return STRING;
end textutil;
package body textutil is
-----------------------------------------------------------------------------
-- *Module : read_token
--
-- *Description : Skip over spaces then load a token string from a line
-- until either the string is full or the token is finished
-- (i.e. another space). The output string is padded out
-- with blanks at the end if the token length is less then
-- the full string length.
-----------------------------------------------------------------------------
procedure read_token(L : inout line; X : out STRING) is
variable char : character;
begin
if(L'length > 0) then
char := ' ';
while((char = ' ') and (L'length > 0)) loop -- Skip spaces
read(L, char);
end loop;
for i in X'low to X'high loop
X(i) := char;
if(char /= ' ') then
if(L'length > 0) then
read(L, char);
else
char := ' ';
end if;
end if;
end loop;
else
assert false report "Couldn't read a token from file"
severity error;
end if;
end read_token;
-----------------------------------------------------------------------------
-- *Module : sget_token
--
-- *Description : Same as read_token except for strings.
-----------------------------------------------------------------------------
procedure sget_token(S : in string; P : inout integer; X : out STRING) is
variable char : character;
begin
if(S'length > P) then
char := ' ';
while((char = ' ') and (S'length >= P)) loop -- Skip spaces
char := S(P);
P := P + 1;
end loop;
for i in X'low to X'high loop
X(i) := char;
if(char /= ' ') then
if(S'length > P) then
char := S(P);
P := P + 1;
else
char := ' ';
end if;
end if;
end loop;
else
assert false report "Couldn't read a token from a string"
severity error;
end if;
end sget_token;
-----------------------------------------------------------------------------
-- *Module : hex_char_to_vector
--
-- *Description : Convert a hex character to a vector
-----------------------------------------------------------------------------
function hex_char_to_vector(C : in character) return STD_ULOGIC_VECTOR is
variable X : STD_ULOGIC_VECTOR( 3 downto 0);
begin
case C is
when '0' => X := "0000";
when '1' => X := "0001";
when '2' => X := "0010";
when '3' => X := "0011";
when '4' => X := "0100";
when '5' => X := "0101";
when '6' => X := "0110";
when '7' => X := "0111";
when '8' => X := "1000";
when '9' => X := "1001";
when 'A' => X := "1010";
when 'B' => X := "1011";
when 'C' => X := "1100";
when 'D' => X := "1101";
when 'E' => X := "1110";
when 'F' => X := "1111";
when 'a' => X := "1010";
when 'b' => X := "1011";
when 'c' => X := "1100";
when 'd' => X := "1101";
when 'e' => X := "1110";
when 'f' => X := "1111";
when others =>
X := "0000";
assert false report "Invalid Hex Character"
severity error;
end case;
return(X);
end hex_char_to_vector;
-----------------------------------------------------------------------------
-- *Module : vector_to_hex_char
--
-- *Description : Convert a vector to a hex character. Only uses low 4 bits.
-----------------------------------------------------------------------------
function vector_to_hex_char(V : in STD_ULOGIC_VECTOR) return character is
variable C : character;
variable VV : STD_ULOGIC_VECTOR(3 downto 0);
begin
if(V'length < 4) then
VV := To_X01(V(V'low + 3 downto V'low));
else
VV := To_X01(V(V'low + V'length - 1 downto V'low));
end if;
case VV is
when "0000" => C := '0';
when "0001" => C := '1';
when "0010" => C := '2';
when "0011" => C := '3';
when "0100" => C := '4';
when "0101" => C := '5';
when "0110" => C := '6';
when "0111" => C := '7';
when "1000" => C := '8';
when "1001" => C := '9';
when "1010" => C := 'A';
when "1011" => C := 'B';
when "1100" => C := 'C';
when "1101" => C := 'D';
when "1110" => C := 'E';
when "1111" => C := 'F';
when others => C := 'X';
end case;
return(C);
end vector_to_hex_char;
-----------------------------------------------------------------------------
-- *Module : is_hex
--
-- *Description : report if a char is ASCII hex
-----------------------------------------------------------------------------
function is_hex(C : in character) return BOOLEAN is
variable X : boolean;
begin
case C is
when '0' => X := TRUE;
when '1' => X := TRUE;
when '2' => X := TRUE;
when '3' => X := TRUE;
when '4' => X := TRUE;
when '5' => X := TRUE;
when '6' => X := TRUE;
when '7' => X := TRUE;
when '8' => X := TRUE;
when '9' => X := TRUE;
when 'A' => X := TRUE;
when 'B' => X := TRUE;
when 'C' => X := TRUE;
when 'D' => X := TRUE;
when 'E' => X := TRUE;
when 'F' => X := TRUE;
when 'a' => X := TRUE;
when 'b' => X := TRUE;
when 'c' => X := TRUE;
when 'd' => X := TRUE;
when 'e' => X := TRUE;
when 'f' => X := TRUE;
when others =>
X := FALSE;
end case;
return(X);
end is_hex;
-----------------------------------------------------------------------------
-- *Module : hex_char_to_int
--
-- *Description : Convert a hex character to an integer
-----------------------------------------------------------------------------
function hex_char_to_int(C : in character) return integer is
variable X : integer;
begin
case C is
when '0' => X := 0;
when '1' => X := 1;
when '2' => X := 2;
when '3' => X := 3;
when '4' => X := 4;
when '5' => X := 5;
when '6' => X := 6;
when '7' => X := 7;
when '8' => X := 8;
when '9' => X := 9;
when 'A' => X := 10;
when 'B' => X := 11;
when 'C' => X := 12;
when 'D' => X := 13;
when 'E' => X := 14;
when 'F' => X := 15;
when 'a' => X := 10;
when 'b' => X := 11;
when 'c' => X := 12;
when 'd' => X := 13;
when 'e' => X := 14;
when 'f' => X := 15;
when others =>
X := 0;
assert false report "Invalid Hex Character"
severity error;
end case;
return(X);
end hex_char_to_int;
-----------------------------------------------------------------------------
-- *Module : read_vector
--
-- *Description : load a vector from the input line in a free floating format
-----------------------------------------------------------------------------
procedure read_vector(L : inout line; VEC : out STD_ULOGIC_VECTOR) is
variable char : character;
variable base : integer;
variable q : integer;
variable v : STD_ULOGIC_VECTOR(31 downto 0);
begin
if(L'length > 0) then
char := ' ';
while(char = ' ') loop -- Skip spaces
read(L, char);
end loop;
base := 16; -- Hex is the default
if(char = '%') then -- determine base
read(L, char);
if(char = 'b' or char = 'B') then
base := 2;
elsif(char = 'x' or char = 'X') then
base := 16;
elsif(char = 'd' or char = 'D') then
base := 10;
else
assert false report "Unsupported Base detected when reading a Vector"
severity error;
end if;
read(L, char);
end if;
q := 0;
if(is_hex(char)) then
q := q * base + hex_char_to_int(char);
while(is_hex(char) and not (L'length = 0)) loop
read(L, char);
if(is_hex(char)) then
q := q * base + hex_char_to_int(char);
end if;
end loop;
end if;
if(q < 0) then
q := q-2147483648;
V(30 downto 0) := to_vector(q, 31);
V(31) := '1';
else
V(30 downto 0) := to_vector(q, 31);
V(31) := '0';
end if;
VEC := V((VEC'high - VEC'low) downto 0);
else
assert false report "Couldn't read a vector"
severity error;
end if;
end read_vector;
-----------------------------------------------------------------------------
-- *Module : sget_vector
--
-- *Description : Same as sget_vector except for strings
-----------------------------------------------------------------------------
procedure sget_vector(S : in string; P : inout integer; VEC : out STD_ULOGIC_VECTOR) is
variable char : character;
variable base : integer;
variable q : integer;
variable v : STD_ULOGIC_VECTOR(31 downto 0);
begin
while(S(P) = ' ') loop -- Skip spaces
if(P >= S'length) then
P := S'length;
exit;
end if;
P := P + 1;
end loop;
if(S'length > P) then
char := S(P);
if(char = '"') then -- read in as a literal
q := v'high;
v := (others => 'U');
VEC := v(VEC'range);
char := ' ';
P := P + 1;
while((char /= '"') and not (S'length = P)) loop
char := S(P);
P := P + 1;
case char is
when '0' =>
v(q) := '0';
when '1' =>
v(q) := '1';
when 'L' | 'l' =>
v(q) := 'L';
when 'H' | 'h' =>
v(q) := 'H';
when 'Z' | 'z' =>
v(q) := 'Z';
when 'X' | 'x' =>
v(q) := 'X';
when 'U' | 'u' =>
v(q) := 'U';
when others =>
-- char := '"';
exit;
end case;
q := q - 1;
end loop;
if(v'high-q < 2) then -- only a single bit was read
VEC(VEC'low) := v(v'high);
elsif((v'high - q) > VEC'length) then -- too many bits
VEC := v(q+VEC'length downto q+1);
else -- the number of bits read is same or less than required
VEC(v'high-q-1+VEC'low downto VEC'low) := v(v'high downto q+1);
end if;
else
base := 16; -- Hex is the default
if(char = '%') then -- determine base
P := P + 1;
char := S(P);
P := P + 1;
if(char = 'b' or char = 'B') then
base := 2;
elsif(char = 'x' or char = 'X') then
base := 16;
elsif(char = 'd' or char = 'D') then
base := 10;
else
assert false report "Unsupported Base detected when reading a Vector"
severity error;
end if;
elsif((char = '0') and ((S(P+1) = 'x') or (S(P+1) = 'X'))) then
P := P + 2;
end if;
q := 0;
char := S(P);
if(is_hex(char)) then
while(is_hex(char) and not (S'length = P)) loop
if(is_hex(char)) then
q := q * base + hex_char_to_int(char);
end if;
P := P + 1;
char := S(P);
end loop;
end if;
if(q < 0) then
q := q-2147483648;
V(30 downto 0) := to_vector(q, 31);
V(31) := '1';
else
V(30 downto 0) := to_vector(q, 31);
V(31) := '0';
end if;
VEC := V((VEC'high - VEC'low) downto 0);
end if;
else
assert false report "Couldn't read a vector"
severity error;
V := (others => '0');
VEC := V((VEC'high - VEC'low) downto 0);
end if;
end sget_vector;
-----------------------------------------------------------------------------
-- *Module : sget_vector_64
--
-- *Description : Same as sget_vector except can handle 64 bit quantities and hex or binary base (no base 10)
-----------------------------------------------------------------------------
procedure sget_vector_64(S : in string; P : inout integer; VEC : out STD_ULOGIC_VECTOR) is
variable char : character;
variable base : integer;
variable q : integer;
variable v : STD_ULOGIC_VECTOR(63 downto 0);
begin
while(S(P) = ' ') loop -- Skip spaces
if(P >= S'length) then
P := S'length;
exit;
end if;
P := P + 1;
end loop;
if(S'length > P) then
char := S(P);
if(char = '"') then -- read in as a literal
q := v'high;
v := (others => 'U');
VEC := v(VEC'range);
char := ' ';
P := P + 1;
while((char /= '"') and not (S'length = P)) loop
char := S(P);
P := P + 1;
case char is
when '0' =>
v(q) := '0';
when '1' =>
v(q) := '1';
when 'L' | 'l' =>
v(q) := 'L';
when 'H' | 'h' =>
v(q) := 'H';
when 'Z' | 'z' =>
v(q) := 'Z';
when 'X' | 'x' =>
v(q) := 'X';
when 'U' | 'u' =>
v(q) := 'U';
when others =>
-- char := '"';
exit;
end case;
q := q - 1;
end loop;
if(v'high-q < 2) then -- only a single bit was read
VEC(VEC'low) := v(v'high);
elsif((v'high - q) > VEC'length) then -- too many bits
VEC := v(q+VEC'length downto q+1);
else -- the number of bits read is same or less than required
VEC(v'high-q-1+VEC'low downto VEC'low) := v(v'high downto q+1);
end if;
else
base := 16; -- Hex is the default
if(char = '%') then -- determine base
P := P + 1;
char := S(P);
P := P + 1;
if(char = 'b' or char = 'B') then
base := 2;
elsif(char = 'x' or char = 'X') then
base := 16;
else
assert false report "Unsupported Base detected when reading a Vector"
severity error;
end if;
char := S(P);
-- P := P + 1;
elsif((char = '0') and ((S(P+1) = 'x') or (S(P+1) = 'X'))) then
P := P + 2;
end if;
v := (others => '0');
char := S(P);
if(base = 2) then
while(((char = '0') or (char = '1')) and not (P > S'length)) loop
if(char = '0') then
v := v(v'high-1 downto 0) & '0';
else
v := v(v'high-1 downto 0) & '1';
end if;
P := P + 1;
char := S(P);
end loop;
else
while(is_hex(char) and not (P > S'length)) loop
if(is_hex(char)) then
v := v(v'high-4 downto 0) & hex_char_to_vector(char);
end if;
P := P + 1;
char := S(P);
end loop;
end if;
VEC := V((VEC'high - VEC'low) downto 0);
end if;
else
assert false report "Couldn't read a vector"
severity error;
V := (others => '0');
VEC := V((VEC'high - VEC'low) downto 0);
end if;
end sget_vector_64;
-----------------------------------------------------------------------------
-- *Module : read_int
--
-- *Description : load an integer from the input line in a free floating format
-----------------------------------------------------------------------------
procedure read_int(L : inout line; I : out integer) is
variable char : character;
variable base : integer;
variable q : integer;
begin
if(L'length > 0) then
char := ' ';
while(char = ' ') loop -- Skip spaces
read(L, char);
end loop;
base := 16; -- Hex is the default
if(char = '%') then -- determine base
read(L, char);
if(char = 'b' or char = 'B') then
base := 2;
elsif(char = 'x' or char = 'X') then
base := 16;
elsif(char = 'd' or char = 'D') then
base := 10;
else
assert false report "Unsupported Base detected when reading an integer"
severity error;
end if;
read(L, char);
end if;
q := 0;
if(is_hex(char)) then
q := q * base + hex_char_to_int(char);
while(is_hex(char) and not (L'length = 0)) loop
read(L, char);
if(is_hex(char)) then
q := q * base + hex_char_to_int(char);
end if;
end loop;
end if;
I := q;
else
assert false report "Couldn't read an integer"
severity error;
end if;
end read_int;
-----------------------------------------------------------------------------
-- *Module : sget_int
--
-- *Description : Same as read_int except for strings
-----------------------------------------------------------------------------
procedure sget_int(S : in string; P : inout integer; X : out integer) is
variable char : character;
variable base : integer;
variable q : integer;
begin
if(S'length > P) then
char := ' ';
while(char = ' ') loop -- Skip spaces
char := S(P);
P := P + 1;
end loop;
base := 16; -- Hex is the default
if(char = '%') then -- determine base
char := S(P);
P := P + 1;
if(char = 'b' or char = 'B') then
base := 2;
elsif(char = 'x' or char = 'X') then
base := 16;
elsif(char = 'd' or char = 'D') then
base := 10;
else
assert false report "Unsupported Base detected when reading an integer"
severity error;
end if;
char := S(P);
P := P + 1;
end if;
q := 0;
if(is_hex(char)) then
q := q * base + hex_char_to_int(char);
while(is_hex(char) and not (S'length = P)) loop
char := S(P);
P := P + 1;
if(is_hex(char)) then
q := q * base + hex_char_to_int(char);
end if;
end loop;
end if;
X := q;
else
assert false report "Couldn't read an integer"
severity error;
end if;
end sget_int;
-----------------------------------------------------------------------------
-- *Module : write_hex_vector
--
-- *Description : writes out a vector as hex
-----------------------------------------------------------------------------
procedure write_hex_vector(L : inout line; V : in STD_ULOGIC_VECTOR) is
variable C : character;
variable VV : STD_ULOGIC_VECTOR(((V'length + 3)/4) * 4 - 1 downto 0);
begin
VV := (others => '0');
VV(V'length -1 downto 0) := V;
for i in VV'length/4 - 1 downto 0 loop
C := vector_to_hex_char(VV(i*4+3 downto i*4));
write(L, C);
end loop;
end write_hex_vector;
-----------------------------------------------------------------------------
-- *Module : to_str
--
-- *Description : Converts a STD_ULOGIC_VECTOR to a string of the same length
-----------------------------------------------------------------------------
function to_str(constant V: in STD_ULOGIC_VECTOR) return STRING is
variable S : STRING(1 to V'length);
variable sp : integer;
begin
sp := 1;
for i in V'range loop
case V(i) is
when '1' | 'H' =>
S(sp) := '1';
when '0' | 'L' =>
S(sp) := '0';
when others =>
S(sp) := 'X';
end case;
sp := sp + 1;
end loop;
return(S);
end to_str;
-----------------------------------------------------------------------------
-- *Module : to_str
--
-- *Description : Converts a STD_ULOGIC to a string
-----------------------------------------------------------------------------
function to_str(constant V: in STD_ULOGIC) return STRING is
-- variable S : STRING(1);
begin
case V is
when '1' | 'H' =>
return("1");
when '0' | 'L' =>
return("0");
when others =>
return("X");
end case;
return("X");
end to_str;
-----------------------------------------------------------------------------
-- *Module : to_str
--
-- *Description : Converts a integer to a string
-----------------------------------------------------------------------------
function to_str(constant val : in INTEGER) return STRING is
variable result : STRING(11 downto 1) := "-2147483648"; -- smallest integer and longest string
variable tmp : INTEGER;
variable pos : NATURAL := 1;
variable digit : NATURAL;
begin
-- for the smallest integer MOD does not seem to work...
--if val = -2147483648 then : compilation error with Xilinx tools...
if val < -2147483647 then
pos := 12;
else
tmp := abs(val);
loop
digit := abs(tmp MOD 10);
tmp := tmp / 10;
result(pos) := character'val(character'pos('0') + digit);
pos := pos + 1;
exit when tmp = 0;
end loop;
if val < 0 then
result(pos) := '-';
pos := pos + 1;
end if;
end if;
return result((pos-1) downto 1);
end to_str;
-----------------------------------------------------------------------------
-- *Module : to_strn
--
-- *Description : Converts an integer to a string of length N
-----------------------------------------------------------------------------
function to_strn(constant val : in INTEGER; constant n : in INTEGER) return STRING is
variable result : STRING(11 downto 1) := "-2147483648"; -- smallest integer and longest string
variable tmp : INTEGER;
variable pos : NATURAL := 1;
variable digit : NATURAL;
begin
-- for the smallest integer MOD does not seem to work...
--if val = -2147483648 then : compilation error with Xilinx tools...
if val < -2147483647 then
pos := 12;
else
result := (others => ' ');
tmp := abs(val);
loop
digit := abs(tmp MOD 10);
tmp := tmp / 10;
result(pos) := character'val(character'pos('0') + digit);
pos := pos + 1;
exit when tmp = 0;
end loop;
if val < 0 then
result(pos) := '-';
pos := pos + 1;
end if;
end if;
return result(n downto 1);
end to_strn;
end textutil;
library ieee;
use ieee.std_logic_1164.all;
--library synopsys;
--use synopsys.arithmetic.all;
package UTIL is
function to_mvl ( b: in boolean ) return STD_ULOGIC;
function to_mvl ( i: in integer ) return STD_ULOGIC;
function to_vector(input,num_bits:integer) return STD_ULOGIC_VECTOR;
-- function to_signed( b: in std_ulogic_vector ) return signed;
-- function to_std_ulogic_vector( b: in signed ) return std_ulogic_vector;
-- function std_logic_to_std_ulogic( b: in std_logic ) return std_ulogic;
-- function std_ulogic_to_std_logic( b: in std_ulogic ) return std_logic;
function "and"(l: STD_ULOGIC_VECTOR; r: STD_ULOGIC) return STD_ULOGIC_VECTOR;
function "and"(l: STD_ULOGIC; r: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR;
function "and"(l: STD_ULOGIC_VECTOR; r: BOOLEAN) return STD_ULOGIC_VECTOR;
function "and"(l: BOOLEAN; r: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR;
function "and"(l: BOOLEAN; r: STD_ULOGIC) return STD_ULOGIC;
function "and"(l: STD_ULOGIC; r: BOOLEAN) return STD_ULOGIC;
function exp(input: STD_ULOGIC; num_bits: integer) return STD_ULOGIC_VECTOR;
function exp(input: STD_ULOGIC_VECTOR; num_bits: integer) return STD_ULOGIC_VECTOR;
function conv_integer ( ARG: in STD_ULOGIC_VECTOR ) return integer;
function "+"(l: STD_ULOGIC_VECTOR; r: STD_ULOGIC) return STD_ULOGIC_VECTOR;
-- function "+"(l: STD_ULOGIC_VECTOR; r: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR;
-- function "-"(l: STD_ULOGIC_VECTOR; r: STD_ULOGIC) return STD_ULOGIC_VECTOR;
-- function "-"(l: STD_ULOGIC_VECTOR; r: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR;
function to_int(l: std_ulogic_vector) return natural;
function to_int(l: std_ulogic) return natural;
function and_reduce(ARG: STD_ULOGIC_VECTOR) return STD_ULOGIC;
function nand_reduce(ARG: STD_ULOGIC_VECTOR) return STD_ULOGIC;
function or_reduce(ARG: STD_ULOGIC_VECTOR) return STD_ULOGIC;
function nor_reduce(ARG: STD_ULOGIC_VECTOR) return STD_ULOGIC;
function xor_reduce(ARG: STD_ULOGIC_VECTOR) return STD_ULOGIC;
function xnor_reduce(ARG: STD_ULOGIC_VECTOR) return STD_ULOGIC;
function ge ( l, r : STD_ULOGIC_VECTOR ) return BOOLEAN;
function gt ( l, r : STD_ULOGIC_VECTOR ) return BOOLEAN;
function lt ( l, r : STD_ULOGIC_VECTOR ) return BOOLEAN;
function eq ( l, r : STD_ULOGIC_VECTOR ) return BOOLEAN;
function maximum ( arg1, arg2 : INTEGER) return INTEGER;
function minimum ( arg1, arg2 : INTEGER) return INTEGER;
procedure keep(signal X: inout STD_LOGIC);
function log2(A: in integer) return integer;
-------------------------------------------------------------------
-- Declaration of Synthesis directive attributes
-------------------------------------------------------------------
ATTRIBUTE synthesis_return : string ;
end UTIL;
package body UTIL is
--------------------------------------------------------------------
-- function to_signed ( b: in std_ulogic_vector ) return signed is
-- variable result : signed(b'range);
-- begin
-- for i in b'range loop
-- result(i) := b(i);
-- end loop;
-- return result;
-- end to_signed;
--------------------------------------------------------------------
-- function to_std_ulogic_vector ( b: in signed ) return std_ulogic_vector is
-- variable result : std_ulogic_vector(b'range);
-- begin
-- for i in b'range loop
-- result(i) := b(i);
-- end loop;
-- return result;
-- end to_std_ulogic_vector;
--------------------------------------------------------------------
function to_mvl ( b: in boolean ) return STD_ULOGIC is
begin
if ( b = TRUE ) then
return( '1' );
else
return( '0' );
end if;
end to_mvl;
--------------------------------------------------------------------
function to_mvl ( i: in integer ) return STD_ULOGIC is
begin
if ( i = 1 ) then
return( '1' );
else
return( '0' );
end if;
end to_mvl;
--------------------------------------------------------------------
function "and"(l: STD_ULOGIC; r: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is
variable rr: STD_ULOGIC_vector(r'range);
begin
if (l = '1') then
rr := r;
else
rr := (others => '0');
end if;
return(rr);
end;
--------------------------------------------------------------------
function "and"(l: STD_ULOGIC_VECTOR; r: STD_ULOGIC) return STD_ULOGIC_VECTOR is
variable ll: STD_ULOGIC_vector(l'range);
begin
if (r = '1') then
ll := l;
else
ll := (others => '0');
end if;
return(ll);
end;
--------------------------------------------------------------------
function "and"(l: BOOLEAN; r: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is
variable rr: STD_ULOGIC_vector(r'range);
begin
if (l) then
rr := r;
else
rr := (others => '0');
end if;
return(rr);
end;
--------------------------------------------------------------------
function "and"(l: STD_ULOGIC_VECTOR; r: BOOLEAN) return STD_ULOGIC_VECTOR is
variable ll: STD_ULOGIC_vector(l'range);
begin
if (r) then
ll := l;
else
ll := (others => '0');
end if;
return(ll);
end;
--------------------------------------------------------------------
function "and"(l: BOOLEAN; r: STD_ULOGIC) return STD_ULOGIC is
variable ll: STD_ULOGIC;
begin
if (l) then
ll := r;
else
ll := '0';
end if;
return(ll);
end;
--------------------------------------------------------------------
function "and"(l: STD_ULOGIC; r: BOOLEAN) return STD_ULOGIC is
variable ll: STD_ULOGIC;
begin
if (r) then
ll := l;
else
ll := '0';
end if;
return(ll);
end;
--------------------------------------------------------------------
-- function std_ulogic_to_std_logic(b : std_ulogic) return std_logic is
-- variable result: std_logic;
-- begin
-- result := b;
-- return result;
-- end;
--------------------------------------------------------------------
-- function std_logic_to_std_ulogic(b : std_logic) return std_ulogic is
-- variable result: std_ulogic;
-- begin
-- result := b;
-- return result;
-- end;
--------------------------------------------------------------------
function to_vector(input,num_bits: integer) return std_ulogic_vector is
variable vec: std_ulogic_vector(num_bits-1 downto 0);
variable a: integer;
begin
a := input;
for i in 0 to num_bits-1 loop
if ((a mod 2) = 1) then
vec(i) := '1';
else
vec(i) := '0';
end if;
a := a / 2;
end loop;
return vec;
end to_vector;
-- FUNCTION to_vector(input,num_bits:integer) RETURN STD_ULOGIC_VECTOR IS
-- VARIABLE result:STD_ULOGIC_VECTOR(num_bits-1 DOWNTO 0);
-- VARIABLE weight:integer;
-- VARIABLE temp:integer;
-- BEGIN
-- weight := 2**(num_bits-1);
-- temp := input;
-- FOR i in result'HIGH DOWNTO result'LOW LOOP
-- IF temp >= weight THEN
-- result(i) := '1';
-- temp := temp - weight;
-- ELSE
-- result(i) := '0';
-- END IF;
-- weight := weight/2;
-- END LOOP;
-- RETURN result;
-- END to_vector;
--------------------------------------------------------------------
-- exp: Expand one bit into many
--------------------------------------------------------------------
FUNCTION exp(input:STD_ULOGIC; num_bits:integer) RETURN STD_ULOGIC_VECTOR IS
VARIABLE result:STD_ULOGIC_VECTOR(num_bits-1 DOWNTO 0);
BEGIN
FOR i in result'HIGH DOWNTO result'LOW LOOP
result(i) := input;
END LOOP;
RETURN result;
END exp;
--------------------------------------------------------------------
-- exp: Expand n bits into m bits
--------------------------------------------------------------------
FUNCTION exp(input:STD_ULOGIC_VECTOR; num_bits:integer) RETURN STD_ULOGIC_VECTOR IS
VARIABLE result:STD_ULOGIC_VECTOR(num_bits-1 DOWNTO 0);
BEGIN
result(input'high-input'low downto 0) := input;
result(num_bits-1 downto input'high-input'low+1) := (others => '0');
RETURN result;
END exp;
--------------------------------------------------------------------
-- conv_integer
--------------------------------------------------------------------
function conv_integer ( ARG: in STD_ULOGIC_VECTOR ) return integer is
variable result: INTEGER;
begin
assert ARG'length <= 31
report "ARG is too large in CONV_INTEGER"
severity FAILURE;
result := 0;
for i in ARG'range loop
result := result * 2;
if(ARG(i) = 'H' or ARG(i) = '1') then
result := result + 1;
end if;
end loop;
return result;
end;
--------------------------------------------------------------------
-- "+" Increment function
--------------------------------------------------------------------
function "+"(L: STD_ULOGIC_VECTOR; R: STD_ULOGIC) return STD_ULOGIC_VECTOR is
variable Q: STD_ULOGIC_VECTOR(L'range);
variable A: STD_ULOGIC;
begin
A := R;
for i in L'low to L'high loop
Q(i) := L(i) xor A;
A := A and L(i);
end loop;
return Q;
end;
--------------------------------------------------------------------
-- "+" adder function
--------------------------------------------------------------------
-- function "+"(L: STD_ULOGIC_VECTOR; R: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is
-- variable Q : SIGNED(L'range);
-- variable result: STD_ULOGIC_VECTOR(L'range);
-- begin
-- Q := to_signed(L) + to_signed(R);
-- result := to_std_ulogic_vector(Q);
-- return result;
-- end;
--------------------------------------------------------------------
-- "-" Decrement function
--------------------------------------------------------------------
-- function "-"(L: STD_ULOGIC_VECTOR; R: STD_ULOGIC) return STD_ULOGIC_VECTOR is
-- variable Q: STD_ULOGIC_VECTOR(L'range);
-- variable A: STD_ULOGIC;
-- begin
-- A := R;
-- for i in L'low to L'high loop
-- Q(i) := L(i) xor A;
-- A := A and not L(i);
-- end loop;
-- return Q;
-- end;
--------------------------------------------------------------------
-- "-" subtractor function
--------------------------------------------------------------------
-- function "-"(L: STD_ULOGIC_VECTOR; R: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is
-- variable Q : SIGNED(L'range);
-- variable result: STD_ULOGIC_VECTOR(L'range);
-- begin
-- Q := to_signed(L) - to_signed(R);
-- result := to_std_ulogic_vector(Q);
-- return result;
-- end;
--------------------------------------------------------------------
-- to_int : Convert std_ulogic_vector to an integer
--------------------------------------------------------------------
function to_int(l: std_ulogic_vector) return natural is
variable result: natural := 0;
begin
for t1 in l'range loop
result := result * 2;
if (l(t1) = '1') or (l(t1) = 'H') then
result := result + 1;
end if;
end loop;
return result;
end to_int;
--------------------------------------------------------------------
-- to_int : Convert std_ulogic_vector to an integer
--------------------------------------------------------------------
function to_int(l: std_ulogic) return natural is
variable result: natural := 0;
begin
if (l = '1') or (l = 'H') then
result := 1;
else
result := 0;
end if;
return result;
end to_int;
--------------------------------------------------------------------
-- Reduce Functions
--------------------------------------------------------------------
function and_reduce(ARG: STD_ULOGIC_VECTOR) return STD_ULOGIC is
variable result: STD_ULOGIC;
begin
result := '1';
for i in ARG'range loop
result := result and ARG(i);
end loop;
return result;
end;
function nand_reduce(ARG: STD_ULOGIC_VECTOR) return STD_ULOGIC is
begin
return not and_reduce(ARG);
end;
function or_reduce(ARG: STD_ULOGIC_VECTOR) return STD_ULOGIC is
variable result: STD_ULOGIC;
begin
result := '0';
for i in ARG'range loop
result := result or ARG(i);
end loop;
return result;
end;
function nor_reduce(ARG: STD_ULOGIC_VECTOR) return STD_ULOGIC is
begin
return not or_reduce(ARG);
end;
function xor_reduce(ARG: STD_ULOGIC_VECTOR) return STD_ULOGIC is
variable result: STD_ULOGIC;
begin
result := '0';
for i in ARG'range loop
result := result xor ARG(i);
end loop;
return result;
end;
function xnor_reduce(ARG: STD_ULOGIC_VECTOR) return STD_ULOGIC is
begin
return not xor_reduce(ARG);
end;
--------------------------------------------------------------------
-- Some useful generic functions
--------------------------------------------------------------------
--//// Zero Extend ////
--
-- Function zxt
--
FUNCTION zxt( q : STD_ULOGIC_VECTOR; i : INTEGER ) RETURN STD_ULOGIC_VECTOR IS
VARIABLE qs : STD_ULOGIC_VECTOR (1 TO i);
VARIABLE qt : STD_ULOGIC_VECTOR (1 TO q'length);
-- Hidden function. Synthesis directives are present in its callers
BEGIN
qt := q;
IF i < q'length THEN
qs := qt( (q'length-i+1) TO qt'right);
ELSIF i > q'length THEN
qs := (OTHERS=>'0');
qs := qs(1 TO (i-q'length)) & qt;
ELSE
qs := qt;
END IF;
RETURN qs;
END;
FUNCTION maximum (arg1,arg2:INTEGER) RETURN INTEGER IS
BEGIN
IF(arg1 > arg2) THEN
RETURN(arg1) ;
ELSE
RETURN(arg2) ;
END IF;
END ;
FUNCTION minimum (arg1,arg2:INTEGER) RETURN INTEGER IS
BEGIN
IF(arg1 < arg2) THEN
RETURN(arg1) ;
ELSE
RETURN(arg2) ;
END IF;
END ;
--------------------------------------------------------------------
-- Comparision functions
--------------------------------------------------------------------
--
-- Equal functions.
--
TYPE stdlogic_boolean_table IS ARRAY(std_ulogic, std_ulogic) OF BOOLEAN;
CONSTANT eq_table : stdlogic_boolean_table := (
--
----------------------------------------------------------------------------
-- | U X 0 1 Z W L H D | |
--
----------------------------------------------------------------------------
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | U |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | X |
( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | 0 |
( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | 1 |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | Z |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | W |
( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | L |
( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | H |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ) -- | D |
);
FUNCTION eq ( l, r : STD_LOGIC ) RETURN BOOLEAN IS
-- Equal for two logic types
VARIABLE result : BOOLEAN ;
ATTRIBUTE synthesis_return OF result:VARIABLE IS "EQ" ;
BEGIN
result := eq_table( l, r );
RETURN result ;
END;
FUNCTION eq ( l,r : STD_ULOGIC_VECTOR ) RETURN BOOLEAN IS
CONSTANT ml : INTEGER := maximum( l'length, r'length );
VARIABLE lt : STD_ULOGIC_VECTOR ( 1 TO ml );
VARIABLE rt : STD_ULOGIC_VECTOR ( 1 TO ml );
-- Arithmetic Equal for two Unsigned vectors
VARIABLE result : BOOLEAN ;
ATTRIBUTE synthesis_return OF result:VARIABLE IS "EQ" ;
BEGIN
lt := zxt( l, ml );
rt := zxt( r, ml );
FOR i IN lt'range LOOP
IF NOT eq( lt(i), rt(i) ) THEN
result := FALSE;
RETURN result ;
END IF;
END LOOP;
RETURN TRUE;
END;
TYPE std_ulogic_fuzzy_state IS ('U', 'X', 'T', 'F', 'N');
TYPE std_ulogic_fuzzy_state_table IS ARRAY ( std_ulogic, std_ulogic ) OF std_ulogic_fuzzy_state;
CONSTANT ge_fuzzy_table : std_ulogic_fuzzy_state_table := (
-- ----------------------------------------------------
-- | U X 0 1 Z W L H D | |
-- ----------------------------------------------------
( 'U', 'U', 'N', 'U', 'U', 'U', 'N', 'U', 'U' ), -- | U |
( 'U', 'X', 'N', 'X', 'X', 'X', 'N', 'X', 'X' ), -- | X |
( 'U', 'X', 'N', 'F', 'X', 'X', 'N', 'F', 'X' ), -- | 0 |
( 'N', 'N', 'T', 'N', 'N', 'N', 'T', 'N', 'N' ), -- | 1 |
( 'U', 'X', 'N', 'X', 'X', 'X', 'N', 'X', 'X' ), -- | Z |
( 'U', 'X', 'N', 'X', 'X', 'X', 'N', 'X', 'X' ), -- | W |
( 'U', 'X', 'N', 'F', 'X', 'X', 'N', 'F', 'X' ), -- | L |
( 'N', 'N', 'T', 'N', 'N', 'N', 'T', 'N', 'N' ), -- | H |
( 'U', 'X', 'N', 'X', 'X', 'X', 'N', 'X', 'X' ) -- | D |
);
FUNCTION ge ( L,R : std_ulogic_vector ) RETURN boolean IS
CONSTANT ml : integer := maximum( L'LENGTH, R'LENGTH );
VARIABLE lt : std_ulogic_vector ( 1 to ml );
VARIABLE rt : std_ulogic_vector ( 1 to ml );
VARIABLE res : std_ulogic_fuzzy_state;
-- Greater-than-or-equal for two Unsigned vectors
VARIABLE result : BOOLEAN ;
ATTRIBUTE synthesis_return OF result:VARIABLE IS "GTE" ;
begin
lt := zxt( l, ml );
rt := zxt( r, ml );
FOR i IN lt'RANGE LOOP
res := ge_fuzzy_table( lt(i), rt(i) );
CASE res IS
WHEN 'U' => RETURN FALSE;
WHEN 'X' => RETURN FALSE;
WHEN 'T' => RETURN TRUE;
WHEN 'F' => RETURN FALSE;
WHEN OTHERS => null;
END CASE;
END LOOP;
result := TRUE ;
RETURN result;
end ;
--
-- Greater Than functions.
--
CONSTANT gtb_table : stdlogic_boolean_table := (
--
----------------------------------------------------------------------------
-- | U X 0 1 Z W L H D | |
--
----------------------------------------------------------------------------
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | U |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | X |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | 0 |
( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | 1 |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | Z |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | W |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | L |
( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | H |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ) -- | D |
);
FUNCTION gt ( l, r : std_logic ) RETURN BOOLEAN IS
-- Greater-than for two logic types
VARIABLE result : BOOLEAN ;
ATTRIBUTE synthesis_return OF result:VARIABLE IS "GT" ;
BEGIN
result := gtb_table( l, r );
RETURN result ;
END ;
FUNCTION gt ( l,r : STD_ULOGIC_VECTOR ) RETURN BOOLEAN IS
CONSTANT ml : INTEGER := maximum( l'length, r'length );
VARIABLE lt : STD_ULOGIC_VECTOR ( 1 TO ml );
VARIABLE rt : STD_ULOGIC_VECTOR ( 1 TO ml );
-- Greater-than for two logic unsigned vectors
VARIABLE result : BOOLEAN ;
ATTRIBUTE synthesis_return OF result:VARIABLE IS "GT" ;
BEGIN
lt := zxt( l, ml );
rt := zxt( r, ml );
FOR i IN lt'range LOOP
IF NOT eq( lt(i), rt(i) ) THEN
result := gt( lt(i), rt(i) );
RETURN result ;
END IF;
END LOOP;
RETURN FALSE;
END;
--
-- Less Than functions.
--
CONSTANT ltb_table : stdlogic_boolean_table := (
--
----------------------------------------------------------------------------
-- | U X 0 1 Z W L H D | |
--
----------------------------------------------------------------------------
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | U |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | X |
( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | 0 |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | 1 |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | Z |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | W |
( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | L |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | H |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ) -- | D |
);
FUNCTION lt ( l, r : STD_LOGIC ) RETURN BOOLEAN IS
-- Less-than for two logic types
VARIABLE result : BOOLEAN ;
ATTRIBUTE synthesis_return OF result:VARIABLE IS "LT" ;
BEGIN
result := ltb_table( l, r );
RETURN result ;
END;
FUNCTION lt ( l,r : STD_ULOGIC_VECTOR ) RETURN BOOLEAN IS
CONSTANT ml : INTEGER := maximum( l'length, r'length );
VARIABLE ltt : STD_ULOGIC_VECTOR ( 1 TO ml );
VARIABLE rtt : STD_ULOGIC_VECTOR ( 1 TO ml );
-- Less-than for two Unsigned vectors
VARIABLE result : BOOLEAN ;
ATTRIBUTE synthesis_return OF result:VARIABLE IS "LT" ;
BEGIN
ltt := zxt( l, ml );
rtt := zxt( r, ml );
FOR i IN ltt'range LOOP
IF NOT eq( ltt(i), rtt(i) ) THEN
result := lt( ltt(i), rtt(i) );
RETURN result ;
END IF;
END LOOP;
RETURN FALSE;
END;
--------------------------------------------------------------------
-- "keep" Retain Last value when floated
--------------------------------------------------------------------
procedure keep(signal X: inout STD_LOGIC) is
begin
if(X = 'Z') then
if(X'last_value = '0') then
X <= 'L';
elsif(X'last_value = '1') then
X <= 'H';
else
X <= 'Z';
end if;
else
X <= 'Z';
end if;
end keep;
---------------------------------------------------------------------
-- log base 2 function
---------------------------------------------------------------------
function log2 ( A: in integer ) return integer is
variable B : integer;
begin
B := 1;
for i in 0 to 31 loop
if not ( A > B ) then
return ( i );
exit;
end if;
B := B * 2;
end loop;
end log2;
end UTIL;
-------------------------------------------------------------------------------
-- simple.vec
-- Short example of using the lambo TestBench
-------------------------------------------------------------------------------
-- Select the GN4124 Primary BFM
model 0
-- Initialize the BFM to its default state
init
-- Drive reset to the FPGA
reset 10
-------------------------------------------------------------------------------
-- Initialize the Primary GN412x BFM model
-------------------------------------------------------------------------------
-- These address ranges will generate traffic from the Primary to the Secondary BFM
-- bar BAR ADDR SIZE VC TC S
bar 0 FF00000010000000 08000000 0 7 0
bar 1 FF000000A0000000 10000000 1 5 0
-- This allocates a RAM block inside the BFM for the FPGA to access
-- bfm_bar BAR ADDR SIZE
bfm_bar 0 8765432120000000 20000000
bfm_bar 1 BB00000040000000 20000000
-- Wait until the FPGA is un-reset and ready for traffic on the local bus
wait 40
-------------------------------------------------------------------------------
-- Access the descriptor memory in the Lambo design
-------------------------------------------------------------------------------
-- the following three writes will go out in a single packet
wrb FF00000010004000 F 87654321
wrb FF00000010004004 F FEEDFACE
wr FF00000010004008 F DEADBEEF
-- Now read back what was just written
-- the following three reads will go out as a single request
rdb FF00000010004000 F 87654321 FFFFFFFF
rdb FF00000010004004 F FEEDFACE FFFFFFFF
rd FF00000010004008 F DEADBEEF FFFFFFFF
flush 100
wait 10
sync
-------------------------------------------------------------------------------
-- File: simple.vec
-- Short example of using the lambo TestBench
-------------------------------------------------------------------------------
-- Select the GN4124 Primary BFM
model %d0
-- Initialize the BFM to its default state
init
-- Drive reset to the FPGA
reset %d16
-------------------------------------------------------------------------------
-- Initialize the Primary GN412x BFM model
-------------------------------------------------------------------------------
-- These address ranges will generate traffic from the BFM to the FPGA
-- bar BAR ADDR SIZE VC TC S
bar 0 FF00000010000000 08000000 0 7 0
bar 1 FF000000A0000000 10000000 1 5 0
-- This allocates a RAM block inside the BFM for the FPGA to access
-- bfm_bar BAR ADDR SIZE
bfm_bar 0 8765432120000000 20000000
bfm_bar 1 BB00000040000000 20000000
-- Wait until the FPGA is un-reset and ready for traffic on the local bus
wait %d64
-------------------------------------------------------------------------------
-- Access the descriptor memory in the Lambo design
-------------------------------------------------------------------------------
-- the following three writes will go out in a single packet
wrb FF00000010004000 F 87654321
wrb FF00000010004004 F FEEDFACE
wr FF00000010004008 F DEADBEEF
-- Now read back what was just written
-- the following three reads will go out as a single request
rdb FF00000010004000 F 87654321 FFFFFFFF
rdb FF00000010004004 F FEEDFACE FFFFFFFF
rd FF00000010004008 F DEADBEEF FFFFFFFF
flush %d256
wait %d16
sync
-------------------------------------------------------------------------------
-- A simple Lambo DMA Test
-------------------------------------------------------------------------------
-- Select the GN4124 Primary BFM
model %d0
init
reset %d16
-------------------------------------------------------------------------------
-- Initialize the Primary GN412x BFM model
-------------------------------------------------------------------------------
-- These address ranges will generate traffic from the Primary to the Secondary BFM
-- bar BAR ADDR SIZE VC TC S
bar 0 FF00000010000000 08000000 0 7 0
bar 1 FF000000A0000000 10000000 1 5 0
-- This allocates a RAM block inside the BFM for the FPGA to access
-- bfm_bar BAR ADDR SIZE
bfm_bar 0 8765432120000000 20000000
bfm_bar 1 BB00000040000000 20000000
cpl_modulo %d32
sync
wait 40
-------------------------------------------------------------------------------
-- DO some setup
-------------------------------------------------------------------------------
-- Lambo setup...
rd FF00000010000030 0xf 0x00000000
flush 100
wr FF00000010000020 0xf 0x0
wr FF00000010000014 0xf 0x0
wr FF0000001000000c 0xf 0xffffffff
wr FF00000010000054 0xf 0x6
wr FF00000010000054 0xf 0x0
wr FF00000010000004 0xf 0x1f
wr FF00000010000004 0xf 0x7
wr FF00000010000058 0xf 0x0
wr FF0000001000005c 0xf 0x0
wr FF00000010000060 0xf 0x0
wr FF00000010000034 0xf 0x8020
-------------------------------------------------------------------------------
-- Do some DMA (this comes from the VDMA builder utility)
-------------------------------------------------------------------------------
-- 0x0000 0x00000000 MAIN: vdma_nop()
wrb FF00000010004000 F 00000000
-- 0x0001 0x40000100 DO_L2P0: vdma_load_sys_addr(r=_IM, "L2P0_SYS_ADDR")
wrb FF00000010004004 F 40000100
-- 0x0002 0xF0000102 vdma_load_xfer_ctl(_IM, "L2P0_XFER_CTL")
wrb FF00000010004008 F F0000102
-- 0x0003 0x40000103 DO_L2P1: vdma_load_sys_addr(r=_IM, "L2P1_SYS_ADDR")
wrb FF0000001000400C F 40000103
-- 0x0004 0xF0000105 vdma_load_xfer_ctl(_IM, "L2P1_XFER_CTL")
wrb FF00000010004010 F F0000105
-- 0x0005 0x17210005 WAIT4IDLE: vdma_jmp(c=_EXT_COND_LO, ext_cond=_LDM_IDLE, "WAIT4IDLE")
wrb FF00000010004014 F 17210005
-- 0x0006 0x00000000 FOREVER: vdma_nop()
wrb FF00000010004018 F 00000000
-- 0x0007 0x1A000006 vdma_jmp(c=_ALWAYS, ext_cond=NA, "FOREVER")
wrb FF0000001000401C F 1A000006
-- 0x0100 0x20012000 L2P0_SYS_ADDR: vdma_constant_n(0x20012000)
wrb FF00000010004400 F 20012000
-- 0x0101 0x87654321 vdma_constant_n(0x87654321)
wrb FF00000010004404 F 87654321
-- 0x0102 0x00010080 L2P0_XFER_CTL: vdma_constant_n(0x10080)
wrb FF00000010004408 F 00010080
-- 0x0103 0x40034000 L2P1_SYS_ADDR: vdma_constant_n(0x40034000)
wrb FF0000001000440C F 40034000
-- 0x0104 0xBB000000 vdma_constant_n(0xBB000000)
wrb FF00000010004410 F BB000000
-- 0x0105 0x00040080 L2P1_XFER_CTL: vdma_constant_n(0x40080)
wrb FF00000010004414 F 00040080
-- Start VDMA
wr FF00000010000030 F 1
-- Read VDMA idle status
rd FF00000010000030 F 0
flush 100
wait 10
sync
-------------------------------------------------------------------------------
-- A simple Lambo DMA Test
-------------------------------------------------------------------------------
-- Select the GN4124 Primary BFM
model 0
init
reset 10
-------------------------------------------------------------------------------
-- Initialize the Primary GN412x BFM model
-------------------------------------------------------------------------------
-- These address ranges will generate traffic from the Primary to the Secondary BFM
-- bar BAR ADDR SIZE VC TC S
bar 0 FF00000010000000 08000000 0 7 0
bar 1 FF000000A0000000 10000000 1 5 0
-- This allocates a RAM block inside the BFM for the FPGA to access
-- bfm_bar BAR ADDR SIZE
bfm_bar 0 8765432120000000 20000000
bfm_bar 1 BB00000040000000 20000000
cpl_modulo %d32
sync
wait 40
-------------------------------------------------------------------------------
-- DO some setup
-------------------------------------------------------------------------------
-- Lambo setup...
rd FF00000010000030 0xf 0x00000000
flush 100
wr FF00000010000020 0xf 0x0
wr FF00000010000014 0xf 0x0
wr FF0000001000000c 0xf 0xffffffff
wr FF00000010000054 0xf 0x6
wr FF00000010000054 0xf 0x0
wr FF00000010000004 0xf 0x1f
wr FF00000010000004 0xf 0x7
wr FF00000010000058 0xf 0x0
wr FF0000001000005c 0xf 0x0
wr FF00000010000060 0xf 0x0
wr FF00000010000034 0xf 0x8020
-------------------------------------------------------------------------------
-- Do some DMA (this comes from the VDMA builder utility)
-------------------------------------------------------------------------------
-- 0x0000 0x00000000 MAIN: vdma_nop()
wrb FF00000010004000 F 00000000
-- 0x0001 0x40000100 DO_L2P0: vdma_load_sys_addr(r=_IM, "L2P0_SYS_ADDR")
wrb FF00000010004004 F 40000100
-- 0x0002 0xF0000102 vdma_load_xfer_ctl(_IM, "L2P0_XFER_CTL")
wrb FF00000010004008 F F0000102
-- 0x0003 0x40000103 DO_L2P1: vdma_load_sys_addr(r=_IM, "L2P1_SYS_ADDR")
wrb FF0000001000400C F 40000103
-- 0x0004 0xF0000105 vdma_load_xfer_ctl(_IM, "L2P1_XFER_CTL")
wrb FF00000010004010 F F0000105
-- 0x0005 0x17210005 WAIT4IDLE: vdma_jmp(c=_EXT_COND_LO, ext_cond=_LDM_IDLE, "WAIT4IDLE")
wrb FF00000010004014 F 17210005
-- 0x0006 0x00000000 FOREVER: vdma_nop()
wrb FF00000010004018 F 00000000
-- 0x0007 0x1A000006 vdma_jmp(c=_ALWAYS, ext_cond=NA, "FOREVER")
wrb FF0000001000401C F 1A000006
-- 0x0100 0x20012000 L2P0_SYS_ADDR: vdma_constant_n(0x20012000)
wrb FF00000010004400 F 20012000
-- 0x0101 0x87654321 vdma_constant_n(0x87654321)
wrb FF00000010004404 F 87654321
-- 0x0102 0x00010080 L2P0_XFER_CTL: vdma_constant_n(0x10080)
wrb FF00000010004408 F 00010080
-- 0x0103 0x40034000 L2P1_SYS_ADDR: vdma_constant_n(0x40034000)
wrb FF0000001000440C F 40034000
-- 0x0104 0xBB000000 vdma_constant_n(0xBB000000)
wrb FF00000010004410 F BB000000
-- 0x0105 0x00040080 L2P1_XFER_CTL: vdma_constant_n(0x40080)
wrb FF00000010004414 F 00040080
-- Start VDMA
wr FF00000010000030 F 1
-- Read VDMA idle status
rd FF00000010000030 F 0
flush 100
wait 10
sync
onerror {resume}
quietly WaveActivateNextPane {} 0
add wave -noupdate -divider {Local bus}
add wave -noupdate -radix hexadecimal /tb_spec/u1/l2p_clkp
add wave -noupdate -radix hexadecimal /tb_spec/u1/l2p_clkn
add wave -noupdate -radix hexadecimal /tb_spec/u1/l2p_data
add wave -noupdate -radix hexadecimal /tb_spec/u1/l2p_valid
add wave -noupdate -radix hexadecimal /tb_spec/u1/l2p_dframe
add wave -noupdate -radix hexadecimal /tb_spec/u1/l2p_edb
add wave -noupdate -radix hexadecimal /tb_spec/u1/l2p_rdy
add wave -noupdate -radix hexadecimal /tb_spec/u1/l_wr_rdy
add wave -noupdate -radix hexadecimal /tb_spec/u1/p2l_clkn
add wave -noupdate -radix hexadecimal /tb_spec/u1/p2l_clkp
add wave -noupdate -radix hexadecimal /tb_spec/u1/p2l_data
add wave -noupdate -radix hexadecimal /tb_spec/u1/p2l_valid
add wave -noupdate -radix hexadecimal /tb_spec/u1/p2l_dframe
add wave -noupdate -radix hexadecimal /tb_spec/u1/p2l_pll_locked
add wave -noupdate -radix hexadecimal /tb_spec/u1/p2l_rdy
add wave -noupdate -radix hexadecimal /tb_spec/u1/p_rd_d_rdy
add wave -noupdate -radix hexadecimal /tb_spec/u1/p_wr_rdy
add wave -noupdate -radix hexadecimal /tb_spec/u1/p_wr_req
add wave -noupdate -radix hexadecimal /tb_spec/u1/rx_error
add wave -noupdate -radix hexadecimal /tb_spec/u1/tx_error
add wave -noupdate -radix hexadecimal /tb_spec/u1/vc_rdy
add wave -noupdate -divider {P2L des}
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/cmp_p2l_des/p2l_data_i
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/cmp_p2l_des/p2l_dframe_i
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/cmp_p2l_des/p2l_valid_i
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/cmp_p2l_des/p2l_data_o
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/cmp_p2l_des/p2l_dframe_o
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/cmp_p2l_des/p2l_valid_o
add wave -noupdate -divider {L2P ser}
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/cmp_l2p_ser/rst_n_i
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/cmp_l2p_ser/l2p_data_i
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/cmp_l2p_ser/l2p_dframe_i
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/cmp_l2p_ser/l2p_valid_i
add wave -noupdate /tb_spec/u1/cmp_gn4124_core/cmp_l2p_ser/l2p_clk_p_o
add wave -noupdate /tb_spec/u1/cmp_gn4124_core/cmp_l2p_ser/l2p_clk_n_o
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/cmp_l2p_ser/l2p_data_o
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/cmp_l2p_ser/l2p_valid_o
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/cmp_l2p_ser/l2p_dframe_o
add wave -noupdate -divider {Gennum core arbiter}
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/pdm_arb_req
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/pdm_arb_data
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/pdm_arb_dframe
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/pdm_arb_valid
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/ldm_arb_req
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/ldm_arb_data
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/ldm_arb_dframe
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/ldm_arb_valid
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/wbm_arb_req
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/wbm_arb_data
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/wbm_arb_dframe
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/wbm_arb_valid
add wave -noupdate -divider {CSR wishbone master}
add wave -noupdate /tb_spec/u1/cmp_gn4124_core/cmp_wbmaster32/wishbone_current_state
add wave -noupdate -radix hexadecimal /tb_spec/u1/wbm_ack
add wave -noupdate -radix hexadecimal /tb_spec/u1/wbm_adr
add wave -noupdate -radix hexadecimal /tb_spec/u1/wbm_cyc
add wave -noupdate -radix hexadecimal /tb_spec/u1/wbm_dat_i
add wave -noupdate -radix hexadecimal /tb_spec/u1/wbm_dat_o
add wave -noupdate -radix hexadecimal /tb_spec/u1/wbm_sel
add wave -noupdate -radix hexadecimal /tb_spec/u1/wbm_stall
add wave -noupdate -radix hexadecimal /tb_spec/u1/wbm_stb
add wave -noupdate -radix hexadecimal /tb_spec/u1/wbm_we
add wave -noupdate -divider {Wishbone address decoder}
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_csr_wb_addr_decoder/s_wb_periph_addr
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_csr_wb_addr_decoder/wb_periph_addr
add wave -noupdate /tb_spec/u1/cmp_csr_wb_addr_decoder/s_wb_periph_select
add wave -noupdate /tb_spec/u1/cmp_csr_wb_addr_decoder/s_wb_ack_muxed
add wave -noupdate /tb_spec/u1/cmp_csr_wb_addr_decoder/s_wb_cyc_demuxed
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_csr_wb_addr_decoder/s_wb_dat_i_muxed
add wave -noupdate -divider {CSR wishbone}
add wave -noupdate -radix hexadecimal /tb_spec/u1/wb_ack(0)
add wave -noupdate -radix hexadecimal /tb_spec/u1/wb_ack(1)
add wave -noupdate /tb_spec/u1/wb_ack(2)
add wave -noupdate -radix hexadecimal /tb_spec/u1/wb_adr
add wave -noupdate -radix hexadecimal /tb_spec/u1/wb_cyc(0)
add wave -noupdate -radix hexadecimal /tb_spec/u1/wb_cyc(1)
add wave -noupdate /tb_spec/u1/wb_cyc(2)
add wave -noupdate -radix hexadecimal /tb_spec/u1/wb_dat_i
add wave -noupdate -radix hexadecimal /tb_spec/u1/wb_dat_o
add wave -noupdate -radix hexadecimal /tb_spec/u1/wb_sel
add wave -noupdate -radix hexadecimal /tb_spec/u1/wb_stb
add wave -noupdate -radix hexadecimal /tb_spec/u1/wb_we
add wave -noupdate /tb_spec/u1/wb_stall(0)
add wave -noupdate /tb_spec/u1/wb_stall(1)
add wave -noupdate /tb_spec/u1/wb_stall(2)
add wave -noupdate -divider {DMA wishbone}
add wave -noupdate -radix hexadecimal /tb_spec/u1/dma_dat_i
add wave -noupdate -radix hexadecimal /tb_spec/u1/dma_dat_o
add wave -noupdate -divider {DMA ctrl}
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/cmp_dma_controller/dma_ctrl_current_state
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/cmp_dma_controller/dma_done_irq
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/cmp_dma_controller/dma_error_irq
add wave -noupdate -divider L2P_DMA
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/cmp_l2p_dma_master/l2p_lbe_header
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/cmp_l2p_dma_master/l2p_len_header
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/cmp_l2p_dma_master/s_l2p_header
add wave -noupdate /tb_spec/u1/cmp_gn4124_core/cmp_l2p_dma_master/ldm_arb_dframe_o
add wave -noupdate /tb_spec/u1/cmp_gn4124_core/cmp_l2p_dma_master/ldm_arb_valid_o
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/cmp_l2p_dma_master/ldm_arb_data_o
add wave -noupdate -divider P2L_DMA
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/cmp_p2l_dma_master/l2p_lbe_header
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/cmp_p2l_dma_master/l2p_len_header
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/cmp_p2l_dma_master/s_l2p_header
add wave -noupdate /tb_spec/u1/cmp_gn4124_core/cmp_p2l_dma_master/pdm_arb_dframe_o
add wave -noupdate /tb_spec/u1/cmp_gn4124_core/cmp_p2l_dma_master/pdm_arb_valid_o
add wave -noupdate -radix hexadecimal /tb_spec/u1/cmp_gn4124_core/cmp_p2l_dma_master/pdm_arb_data_o
add wave -noupdate -divider LEDs
add wave -noupdate -radix hexadecimal /tb_spec/u1/led_green_o
add wave -noupdate /tb_spec/u1/led_red_o
add wave -noupdate -radix hexadecimal /tb_spec/u1/aux_leds_o
add wave -noupdate -radix hexadecimal /tb_spec/u1/led_cnt
add wave -noupdate -radix hexadecimal /tb_spec/u1/led_en
add wave -noupdate -radix hexadecimal /tb_spec/u1/led_k2000
add wave -noupdate -radix hexadecimal /tb_spec/u1/led_pps
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 1} {631250 ps} 0}
configure wave -namecolwidth 395
configure wave -valuecolwidth 120
configure wave -justifyvalue left
configure wave -signalnamewidth 0
configure wave -snapdistance 10
configure wave -datasetprefix 0
configure wave -rowmargin 4
configure wave -childrowmargin 2
configure wave -gridoffset 0
configure wave -gridperiod 1
configure wave -griddelta 40
configure wave -timeline 0
configure wave -timelineunits ns
update
WaveRestoreZoom {581738 ps} {643262 ps}
*
!*.ucf
!README
!.gitignore
!Manifest.py
target = "xilinx"
action = "synthesis"
syn_device = "xc6slx45t"
syn_grade = "-3"
syn_package = "fgg484"
syn_top = "spec_gn4124_test"
syn_project = "spec_gn4124_test.xise"
syn_tool = "ise"
files = [
"spec_gn4124_test.ucf",
]
modules = {
"local" : [
"../top",
"../rtl",
"../../gn4124core/rtl",
],
"git" : [
"git://ohwr.org/hdl-core-lib/general-cores.git",
],
}
fetchto = "../../ip_cores"
This example project was last tested on March 18st 2016,
using hdlmake (develop branch).
A binary of the generated gateware (spec_gn4124_test.bin) is stored in the
files section of the project:
http://www.ohwr.org/projects/gn4124-core/files
Procedure to generate the gateware binary:
$ cd <gn4124 core dir>/hdl/spec/syn/
$ hdlmake fetch
$ hdlmake
$ make
Memory map:
0x00000 : GN4124 DMA configuration registers
-> See GN4124 doc for register mapping.
0x40000 : Status registers
0 : 0xDEADBABE
4 : 0xBEEFFACE
8 : 0x12345678
C : Bit 0 = P2L PLL lock status (1=pll locked)
0x80000 : Control regiters
0 : Not connected internally, can be used to perform r/w
4 : Not connected internally, can be used to perform r/w
8 : Not connected internally, can be used to perform r/w
C : Bits 0 and 1 connected to SPEC front-panel LEDs (1=LED ON)
#===============================================================================
# The IO Location Constraints
#===============================================================================
#----------------------------------------
# Clock inputs
#----------------------------------------
NET "clk20_vcxo_i" LOC = H12; # CLK25_VCXO
NET "clk20_vcxo_i" IOSTANDARD = "LVCMOS25";
#NET "clk_125m_pllref_n_i" LOC = F10;
#NET "clk_125m_pllref_n_i" IOSTANDARD = "LVDS_25";
#NET "clk_125m_pllref_p_i" LOC = G9;
#NET "clk_125m_pllref_p_i" IOSTANDARD = "LVDS_25";
#----------------------------------------
# SFP slot
# !! SFP_TX_DISABLE and SFP_MOD_DEF1 are swapped in V1.1 schematics for control signals
#----------------------------------------
#NET "SFPRX_123_N" LOC = C15;
#NET "SFPRX_123_N" IOSTANDARD = "LVCMOS25";
#NET "SFPRX_123_P" LOC = D15;
#NET "SFPRX_123_P" IOSTANDARD = "LVCMOS25";
#NET "SFPTX_123_N" LOC = A16;
#NET "SFPTX_123_N" IOSTANDARD = "LVCMOS25";
#NET "SFPTX_123_P" LOC = B16;
#NET "SFPTX_123_P" IOSTANDARD = "LVCMOS25";
#NET "SFP_TX_FAULT" LOC = B18;
#NET "SFP_TX_FAULT" IOSTANDARD = "LVCMOS25";
#NET "SFP_TX_DISABLE" LOC = F17;
#NET "SFP_TX_DISABLE" IOSTANDARD = "LVCMOS25";
#NET "SFP_LOS" LOC = D18;
#NET "SFP_LOS" IOSTANDARD = "LVCMOS25";
#NET "SFP_MOD_DEF1" LOC = C17;
#NET "SFP_MOD_DEF1" IOSTANDARD = "LVCMOS25";
#NET "SFP_MOD_DEF0" LOC = G15;
#NET "SFP_MOD_DEF0" IOSTANDARD = "LVCMOS25";
#NET "SFP_MOD_DEF2" LOC = G16;
#NET "SFP_MOD_DEF2" IOSTANDARD = "LVCMOS25";
#NET "SFP_RATE_SELECT" LOC = H14;
#NET "SFP_RATE_SELECT" IOSTANDARD = "LVCMOS25";
#----------------------------------------
# DAC interface (for VCXO)
#----------------------------------------
#NET "PLL25DAC1_SYNC_N" LOC = A3;
#NET "PLL25DAC1_SYNC_N" IOSTANDARD = "LVCMOS25";
#NET "PLL25DAC2_SYNC_N" LOC = B3;
#NET "PLL25DAC2_SYNC_N" IOSTANDARD = "LVCMOS25";
#NET "PLL25DAC_DIN" LOC = C4;
#NET "PLL25DAC_DIN" IOSTANDARD = "LVCMOS25";
#NET "PLL25DAC_SCLK" LOC = A4;
#NET "PLL25DAC_SCLK" IOSTANDARD = "LVCMOS25";
#----------------------------------------
# 1-wire thermometer w/ ID
#----------------------------------------
#NET "THERMO_ID" LOC = D4;
#NET "THERMO_ID" IOSTANDARD = "LVCMOS25";
#----------------------------------------
# I2C interface
#----------------------------------------
#NET "FPGA_SCL" LOC = F7;
#NET "FPGA_SCL" IOSTANDARD = "LVCMOS25";
#NET "FPGA_SDA" LOC = F8;
#NET "FPGA_SDA" IOSTANDARD = "LVCMOS25";
#----------------------------------------
# GN4124 interface
#----------------------------------------
NET "L_RST_N" LOC = N20;
NET "L_RST_N" IOSTANDARD = "LVCMOS18";
NET "L2P_CLKN" LOC = K22;
NET "L2P_CLKN" IOSTANDARD = "DIFF_SSTL18_I";
NET "L2P_CLKP" LOC = K21;
NET "L2P_CLKP" IOSTANDARD = "DIFF_SSTL18_I";
NET "L2P_DFRAME" LOC = U22;
NET "L2P_DFRAME" IOSTANDARD = "SSTL18_I";
NET "L2P_EDB" LOC = U20;
NET "L2P_EDB" IOSTANDARD = "SSTL18_I";
NET "L2P_RDY" LOC = U19;
NET "L2P_RDY" IOSTANDARD = "SSTL18_I";
NET "L2P_VALID" LOC = T18;
NET "L2P_VALID" IOSTANDARD = "SSTL18_I";
NET "L_WR_RDY[0]" LOC = R20;
NET "L_WR_RDY[0]" IOSTANDARD = "SSTL18_I";
NET "L_WR_RDY[1]" LOC = T22;
NET "L_WR_RDY[1]" IOSTANDARD = "SSTL18_I";
NET "L_CLKN" LOC = N19;
NET "L_CLKN" IOSTANDARD = "DIFF_SSTL18_I";
NET "L_CLKP" LOC = P20;
NET "L_CLKP" IOSTANDARD = "DIFF_SSTL18_I";
NET "P2L_CLKN" LOC = M19;
NET "P2L_CLKN" IOSTANDARD = "DIFF_SSTL18_I";
NET "P2L_CLKP" LOC = M20;
NET "P2L_CLKP" IOSTANDARD = "DIFF_SSTL18_I";
NET "P2L_DFRAME" LOC = J22;
NET "P2L_DFRAME" IOSTANDARD = "SSTL18_I";
NET "P2L_RDY" LOC = J16;
NET "P2L_RDY" IOSTANDARD = "SSTL18_I";
NET "P2L_VALID" LOC = L19;
NET "P2L_VALID" IOSTANDARD = "SSTL18_I";
NET "P_RD_D_RDY[0]" LOC = N16;
NET "P_RD_D_RDY[0]" IOSTANDARD = "SSTL18_I";
NET "P_RD_D_RDY[1]" LOC = P19;
NET "P_RD_D_RDY[1]" IOSTANDARD = "SSTL18_I";
NET "P_WR_RDY[0]" LOC = L15;
NET "P_WR_RDY[0]" IOSTANDARD = "SSTL18_I";
NET "P_WR_RDY[1]" LOC = K16;
NET "P_WR_RDY[1]" IOSTANDARD = "SSTL18_I";
NET "P_WR_REQ[0]" LOC = M22;
NET "P_WR_REQ[0]" IOSTANDARD = "SSTL18_I";
NET "P_WR_REQ[1]" LOC = M21;
NET "P_WR_REQ[1]" IOSTANDARD = "SSTL18_I";
NET "RX_ERROR" LOC = J17;
NET "RX_ERROR" IOSTANDARD = "SSTL18_I";
NET "TX_ERROR" LOC = M17;
NET "TX_ERROR" IOSTANDARD = "SSTL18_I";
NET "VC_RDY[0]" LOC = B21;
NET "VC_RDY[0]" IOSTANDARD = "SSTL18_I";
NET "VC_RDY[1]" LOC = B22;
NET "VC_RDY[1]" IOSTANDARD = "SSTL18_I";
NET "L2P_DATA[0]" LOC = P16;
NET "L2P_DATA[0]" IOSTANDARD = "SSTL18_I";
NET "L2P_DATA[1]" LOC = P21;
NET "L2P_DATA[1]" IOSTANDARD = "SSTL18_I";
NET "L2P_DATA[2]" LOC = P18;
NET "L2P_DATA[2]" IOSTANDARD = "SSTL18_I";
NET "L2P_DATA[3]" LOC = T20;
NET "L2P_DATA[3]" IOSTANDARD = "SSTL18_I";
NET "L2P_DATA[4]" LOC = V21;
NET "L2P_DATA[4]" IOSTANDARD = "SSTL18_I";
NET "L2P_DATA[5]" LOC = V19;
NET "L2P_DATA[5]" IOSTANDARD = "SSTL18_I";
NET "L2P_DATA[6]" LOC = W22;
NET "L2P_DATA[6]" IOSTANDARD = "SSTL18_I";
NET "L2P_DATA[7]" LOC = Y22;
NET "L2P_DATA[7]" IOSTANDARD = "SSTL18_I";
NET "L2P_DATA[8]" LOC = P22;
NET "L2P_DATA[8]" IOSTANDARD = "SSTL18_I";
NET "L2P_DATA[9]" LOC = R22;
NET "L2P_DATA[9]" IOSTANDARD = "SSTL18_I";
NET "L2P_DATA[10]" LOC = T21;
NET "L2P_DATA[10]" IOSTANDARD = "SSTL18_I";
NET "L2P_DATA[11]" LOC = T19;
NET "L2P_DATA[11]" IOSTANDARD = "SSTL18_I";
NET "L2P_DATA[12]" LOC = V22;
NET "L2P_DATA[12]" IOSTANDARD = "SSTL18_I";
NET "L2P_DATA[13]" LOC = V20;
NET "L2P_DATA[13]" IOSTANDARD = "SSTL18_I";
NET "L2P_DATA[14]" LOC = W20;
NET "L2P_DATA[14]" IOSTANDARD = "SSTL18_I";
NET "L2P_DATA[15]" LOC = Y21;
NET "L2P_DATA[15]" IOSTANDARD = "SSTL18_I";
NET "P2L_DATA[0]" LOC = K20;
NET "P2L_DATA[0]" IOSTANDARD = "SSTL18_I";
NET "P2L_DATA[1]" LOC = H22;
NET "P2L_DATA[1]" IOSTANDARD = "SSTL18_I";
NET "P2L_DATA[2]" LOC = H21;
NET "P2L_DATA[2]" IOSTANDARD = "SSTL18_I";
NET "P2L_DATA[3]" LOC = L17;
NET "P2L_DATA[3]" IOSTANDARD = "SSTL18_I";
NET "P2L_DATA[4]" LOC = K17;
NET "P2L_DATA[4]" IOSTANDARD = "SSTL18_I";
NET "P2L_DATA[5]" LOC = G22;
NET "P2L_DATA[5]" IOSTANDARD = "SSTL18_I";
NET "P2L_DATA[6]" LOC = G20;
NET "P2L_DATA[6]" IOSTANDARD = "SSTL18_I";
NET "P2L_DATA[7]" LOC = K18;
NET "P2L_DATA[7]" IOSTANDARD = "SSTL18_I";
NET "P2L_DATA[8]" LOC = K19;
NET "P2L_DATA[8]" IOSTANDARD = "SSTL18_I";
NET "P2L_DATA[9]" LOC = H20;
NET "P2L_DATA[9]" IOSTANDARD = "SSTL18_I";
NET "P2L_DATA[10]" LOC = J19;
NET "P2L_DATA[10]" IOSTANDARD = "SSTL18_I";
NET "P2L_DATA[11]" LOC = E22;
NET "P2L_DATA[11]" IOSTANDARD = "SSTL18_I";
NET "P2L_DATA[12]" LOC = E20;
NET "P2L_DATA[12]" IOSTANDARD = "SSTL18_I";
NET "P2L_DATA[13]" LOC = F22;
NET "P2L_DATA[13]" IOSTANDARD = "SSTL18_I";
NET "P2L_DATA[14]" LOC = F21;
NET "P2L_DATA[14]" IOSTANDARD = "SSTL18_I";
NET "P2L_DATA[15]" LOC = H19;
NET "P2L_DATA[15]" IOSTANDARD = "SSTL18_I";
NET "GPIO[0]" LOC = U16;
NET "GPIO[0]" IOSTANDARD = "LVCMOS25";
NET "GPIO[1]" LOC = AB19;
NET "GPIO[1]" IOSTANDARD = "LVCMOS25";
#----------------------------------------
# FMC slot
#----------------------------------------
#NET "ext_trigger_n_i" LOC = AB13; # LA17_N
#NET "ext_trigger_n_i" IOSTANDARD = "LVDS_25";
#NET "ext_trigger_p_i" LOC = Y13; # LA17_P
#NET "ext_trigger_p_i" IOSTANDARD = "LVDS_25";
# dco_p and dco_n are swapped compared to the FMC ADC schematics
# this is to be coherent in the hdl design
#NET "adc_dco_n_i" LOC = AB11; # LA00_N
#NET "adc_dco_n_i" IOSTANDARD = "LVDS_25";
#NET "adc_dco_p_i" LOC = Y11; # LA00_P
#NET "adc_dco_p_i" IOSTANDARD = "LVDS_25";
# fr_p and fr_n are swapped compared to the FMC ADC schematics
# this is to be coherent in the hdl design
#NET "adc_fr_n_i" LOC = AB12; # LA01_N
#NET "adc_fr_n_i" IOSTANDARD = "LVDS_25";
#NET "adc_fr_p_i" LOC = AA12; # LA01_P
#NET "adc_fr_p_i" IOSTANDARD = "LVDS_25";
#NET "adc_outa_n_i[0]" LOC = AB4; # LA14_N
#NET "adc_outa_n_i[0]" IOSTANDARD = "LVDS_25";
#NET "adc_outa_p_i[0]" LOC = AA4; # LA14_P
#NET "adc_outa_p_i[0]" IOSTANDARD = "LVDS_25";
#NET "adc_outb_n_i[0]" LOC = W11; # LA15_N
#NET "adc_outb_n_i[0]" IOSTANDARD = "LVDS_25";
#NET "adc_outb_p_i[0]" LOC = V11; # LA15_P
#NET "adc_outb_p_i[0]" IOSTANDARD = "LVDS_25";
#NET "adc_outa_n_i[1]" LOC = Y12; # LA16_N
#NET "adc_outa_n_i[1]" IOSTANDARD = "LVDS_25";
#NET "adc_outa_p_i[1]" LOC = W12; # LA16_P
#NET "adc_outa_p_i[1]" IOSTANDARD = "LVDS_25";
#NET "adc_outb_n_i[1]" LOC = AB9; # LA13_N
#NET "adc_outb_n_i[1]" IOSTANDARD = "LVDS_25";
#NET "adc_outb_p_i[1]" LOC = Y9; # LA13_P
#NET "adc_outb_p_i[1]" IOSTANDARD = "LVDS_25";
#NET "adc_outa_n_i[2]" LOC = AB8; # LA10_N
#NET "adc_outa_n_i[2]" IOSTANDARD = "LVDS_25";
#NET "adc_outa_p_i[2]" LOC = AA8; # LA10_P
#NET "adc_outa_p_i[2]" IOSTANDARD = "LVDS_25";
#NET "adc_outb_n_i[2]" LOC = AB7; # LA09_N
#NET "adc_outb_n_i[2]" IOSTANDARD = "LVDS_25";
#NET "adc_outb_p_i[2]" LOC = Y7; # LA09_P
#NET "adc_outb_p_i[2]" IOSTANDARD = "LVDS_25";
#NET "adc_outa_n_i[3]" LOC = V9; # LA07_N
#NET "adc_outa_n_i[3]" IOSTANDARD = "LVDS_25";
#NET "adc_outa_p_i[3]" LOC = U9; # LA07_P
#NET "adc_outa_p_i[3]" IOSTANDARD = "LVDS_25";
#NET "adc_outb_n_i[3]" LOC = AB6; # LA05_N
#NET "adc_outb_n_i[3]" IOSTANDARD = "LVDS_25";
#NET "adc_outb_p_i[3]" LOC = AA6; # LA05_P
#NET "adc_outb_p_i[3]" IOSTANDARD = "LVDS_25";
#NET "spi_din_i" LOC = T15; # LA25_P
#NET "spi_din_i" IOSTANDARD = "LVCMOS25";
#NET "spi_dout_o" LOC = C18; # LA31_N
#NET "spi_dout_o" IOSTANDARD = "LVCMOS25";
#NET "spi_sck_o" LOC = D17; # LA31_P
#NET "spi_sck_o" IOSTANDARD = "LVCMOS25";
#NET "spi_cs_adc_n_o" LOC = V17; # LA30_P
#NET "spi_cs_adc_n_o" IOSTANDARD = "LVCMOS25";
#NET "spi_cs_dac1_n_o" LOC = B20; # LA32_P
#NET "spi_cs_dac1_n_o" IOSTANDARD = "LVCMOS25";
#NET "spi_cs_dac2_n_o" LOC = A20; # LA32_N
#NET "spi_cs_dac2_n_o" IOSTANDARD = "LVCMOS25";
#NET "spi_cs_dac3_n_o" LOC = C19; # LA33_P
#NET "spi_cs_dac3_n_o" IOSTANDARD = "LVCMOS25";
#NET "spi_cs_dac4_n_o" LOC = A19; # LA33_N
#NET "spi_cs_dac4_n_o" IOSTANDARD = "LVCMOS25";
#NET "gpio_dac_clr_n_o" LOC = W18; # LA30_N
#NET "gpio_dac_clr_n_o" IOSTANDARD = "LVCMOS25";
#NET "gpio_led_power_o" LOC = W15; # LA28_N
#NET "gpio_led_power_o" IOSTANDARD = "LVCMOS25";
#NET "gpio_led_trigger_o" LOC = Y16; # LA28_P
#NET "gpio_led_trigger_o" IOSTANDARD = "LVCMOS25";
#NET "gpio_ssr_ch1_o[0]" LOC = Y17; # LA26_P
#NET "gpio_ssr_ch1_o[0]" IOSTANDARD = "LVCMOS25";
#NET "gpio_ssr_ch1_o[1]" LOC = AB17; # LA26_N
#NET "gpio_ssr_ch1_o[1]" IOSTANDARD = "LVCMOS25";
#NET "gpio_ssr_ch1_o[2]" LOC = AB18; # LA27_N
#NET "gpio_ssr_ch1_o[2]" IOSTANDARD = "LVCMOS25";
#NET "gpio_ssr_ch1_o[3]" LOC = U15; # LA25_N
#NET "gpio_ssr_ch1_o[3]" IOSTANDARD = "LVCMOS25";
#NET "gpio_ssr_ch1_o[4]" LOC = W14; # LA24_P
#NET "gpio_ssr_ch1_o[4]" IOSTANDARD = "LVCMOS25";
#NET "gpio_ssr_ch1_o[5]" LOC = Y14; # LA24_N
#NET "gpio_ssr_ch1_o[5]" IOSTANDARD = "LVCMOS25";
#NET "gpio_ssr_ch1_o[6]" LOC = W17; # LA29_P
#NET "gpio_ssr_ch1_o[6]" IOSTANDARD = "LVCMOS25";
#NET "gpio_ssr_ch2_o[0]" LOC = R11; # LA20_P
#NET "gpio_ssr_ch2_o[0]" IOSTANDARD = "LVCMOS25";
#NET "gpio_ssr_ch2_o[1]" LOC = AB15; # LA19_N
#NET "gpio_ssr_ch2_o[1]" IOSTANDARD = "LVCMOS25";
#NET "gpio_ssr_ch2_o[2]" LOC = R13; # LA22_P
#NET "gpio_ssr_ch2_o[2]" IOSTANDARD = "LVCMOS25";
#NET "gpio_ssr_ch2_o[3]" LOC = T14; # LA22_N
#NET "gpio_ssr_ch2_o[3]" IOSTANDARD = "LVCMOS25";
#NET "gpio_ssr_ch2_o[4]" LOC = V13; # LA21_P
#NET "gpio_ssr_ch2_o[4]" IOSTANDARD = "LVCMOS25";
#NET "gpio_ssr_ch2_o[5]" LOC = AA18; # LA27_P
#NET "gpio_ssr_ch2_o[5]" IOSTANDARD = "LVCMOS25";
#NET "gpio_ssr_ch2_o[6]" LOC = W13; # LA21_N
#NET "gpio_ssr_ch2_o[6]" IOSTANDARD = "LVCMOS25";
#NET "gpio_ssr_ch3_o[0]" LOC = R9; # LA08_P
#NET "gpio_ssr_ch3_o[0]" IOSTANDARD = "LVCMOS25";
#NET "gpio_ssr_ch3_o[1]" LOC = R8; # LA08_N
#NET "gpio_ssr_ch3_o[1]" IOSTANDARD = "LVCMOS25";
#NET "gpio_ssr_ch3_o[2]" LOC = T10; # LA12_P
#NET "gpio_ssr_ch3_o[2]" IOSTANDARD = "LVCMOS25";
#NET "gpio_ssr_ch3_o[3]" LOC = U10; # LA12_N
#NET "gpio_ssr_ch3_o[3]" IOSTANDARD = "LVCMOS25";
#NET "gpio_ssr_ch3_o[4]" LOC = W10; # LA11_P
#NET "gpio_ssr_ch3_o[4]" IOSTANDARD = "LVCMOS25";
#NET "gpio_ssr_ch3_o[5]" LOC = Y10; # LA11_N
#NET "gpio_ssr_ch3_o[5]" IOSTANDARD = "LVCMOS25";
#NET "gpio_ssr_ch3_o[6]" LOC = T11; # LA20_N
#NET "gpio_ssr_ch3_o[6]" IOSTANDARD = "LVCMOS25";
#NET "gpio_ssr_ch4_o[0]" LOC = W6; # LA02_P
#NET "gpio_ssr_ch4_o[0]" IOSTANDARD = "LVCMOS25";
#NET "gpio_ssr_ch4_o[1]" LOC = Y6; # LA02_N
#NET "gpio_ssr_ch4_o[1]" IOSTANDARD = "LVCMOS25";
#NET "gpio_ssr_ch4_o[2]" LOC = V7; # LA03_P
#NET "gpio_ssr_ch4_o[2]" IOSTANDARD = "LVCMOS25";
#NET "gpio_ssr_ch4_o[3]" LOC = W8; # LA03_N
#NET "gpio_ssr_ch4_o[3]" IOSTANDARD = "LVCMOS25";
#NET "gpio_ssr_ch4_o[4]" LOC = T8; # LA04_P
#NET "gpio_ssr_ch4_o[4]" IOSTANDARD = "LVCMOS25";
#NET "gpio_ssr_ch4_o[5]" LOC = Y5; # LA06_P
#NET "gpio_ssr_ch4_o[5]" IOSTANDARD = "LVCMOS25";
#NET "gpio_ssr_ch4_o[6]" LOC = U8; # LA04_N
#NET "gpio_ssr_ch4_o[6]" IOSTANDARD = "LVCMOS25";
#NET "gpio_si570_oe_o" LOC = AB5; # LA06_N
#NET "gpio_si570_oe_o" IOSTANDARD = "LVCMOS25";
#NET "si570_thermo_scl_b" LOC = U12; # LA18_N
#NET "si570_thermo_scl_b" IOSTANDARD = "LVCMOS25";
#NET "si570_thermo_sda_b" LOC = T12; # LA18_P
#NET "si570_thermo_sda_b" IOSTANDARD = "LVCMOS25";
#NET "prsnt_m2c_n_i" LOC = AB14; # PRSNT_M2C_L
#NET "prsnt_m2c_n_i" IOSTANDARD = "LVCMOS25";
#----------------------------------------
# FMC slot (unused pins)
#----------------------------------------
#NET "PG_C2M" LOC = AA14;
#NET "PG_C2M" IOSTANDARD = "LVCMOS25";
#NET "LA19_P" LOC = Y15;
#NET "LA19_P" IOSTANDARD = "LVCMOS25";
#NET "LA23_N" LOC = AB16;
#NET "LA23_N" IOSTANDARD = "LVCMOS25";
#NET "LA23_P" LOC = AA16;
#NET "LA23_P" IOSTANDARD = "LVCMOS25";
#NET "LA29_N" LOC = Y18;
#NET "LA29_N" IOSTANDARD = "LVCMOS25";
#NET "TDO_FROM_FMC" LOC = F9;
#NET "TDO_FROM_FMC" IOSTANDARD = "LVCMOS25";
#NET "TCK_TO_FMC" LOC = G8;
#NET "TCK_TO_FMC" IOSTANDARD = "LVCMOS25";
#NET "TDI_TO_FMC" LOC = H11;
#NET "TDI_TO_FMC" IOSTANDARD = "LVCMOS25";
#NET "TMS_TO_FMC" LOC = H10;
#NET "TMS_TO_FMC" IOSTANDARD = "LVCMOS25";
#NET "TRST_TO_FMC" LOC = E6;
#NET "TRST_TO_FMC" IOSTANDARD = "LVCMOS25";
#NET "CLK0_M2C_P" LOC = E16;
#NET "CLK0_M2C_P" IOSTANDARD = "LVDS_25";
#NET "CLK0_M2C_N" LOC = F16;
#NET "CLK0_M2C_N" IOSTANDARD = "LVDS_25";
#NET "CLK1_M2C_P" LOC = L20;
#NET "CLK1_M2C_P" IOSTANDARD = "LVDS_18";
#NET "CLK1_M2C_N" LOC = L22;
#NET "CLK1_M2C_N" IOSTANDARD = "LVDS_18";
#----------------------------------------
# SI57x interface
#----------------------------------------
#NET "SI57X_SCL" LOC = A18;
#NET "SI57X_SCL" IOSTANDARD = "LVCMOS25";
#NET "SI57X_SDA" LOC = A17;
#NET "SI57X_SDA" IOSTANDARD = "LVCMOS25";
#NET "SI57X_OE" LOC = H13;
#NET "SI57X_OE" IOSTANDARD = "LVCMOS25";
#NET "SI57X_CLK_N" LOC = F15;
#NET "SI57X_CLK_N" IOSTANDARD = "LVDS_25";
#NET "SI57X_CLK_P" LOC = F14;
#NET "SI57X_CLK_P" IOSTANDARD = "LVDS_25";
#----------------------------------------
# Carrier front panel LEDs
#----------------------------------------
NET "led_red_o" LOC = D5;
NET "led_red_o" IOSTANDARD = "LVCMOS25";
NET "led_green_o" LOC = E5;
NET "led_green_o" IOSTANDARD = "LVCMOS25";
#----------------------------------------
# PCB version number (coded with resistors)
#----------------------------------------
NET "pcb_ver_i[0]" LOC = P5;
NET "pcb_ver_i[0]" IOSTANDARD = "LVCMOS15";
NET "pcb_ver_i[1]" LOC = P4;
NET "pcb_ver_i[1]" IOSTANDARD = "LVCMOS15";
NET "pcb_ver_i[2]" LOC = AA2;
NET "pcb_ver_i[2]" IOSTANDARD = "LVCMOS15";
NET "pcb_ver_i[3]" LOC = AA1;
NET "pcb_ver_i[3]" IOSTANDARD = "LVCMOS15";
#----------------------------------------
# DDR3 interface
#----------------------------------------
#NET "DDR3_CAS_N" LOC = M4;
#NET "DDR3_CAS_N" IOSTANDARD = "SSTL15_II";
#NET "DDR3_CK_N" LOC = K3;
#NET "DDR3_CK_N" IOSTANDARD = "DIFF_SSTL15_II";
#NET "DDR3_CK_P" LOC = K4;
#NET "DDR3_CK_P" IOSTANDARD = "DIFF_SSTL15_II";
#NET "DDR3_CKE" LOC = F2;
#NET "DDR3_CKE" IOSTANDARD = "SSTL15_II";
#NET "DDR3_LDM" LOC = N4;
#NET "DDR3_LDM" IOSTANDARD = "SSTL15_II";
#NET "DDR3_LDQS_N" LOC = N1;
#NET "DDR3_LDQS_N" IOSTANDARD = "DIFF_SSTL15_II";
#NET "DDR3_LDQS_P" LOC = N3;
#NET "DDR3_LDQS_P" IOSTANDARD = "DIFF_SSTL15_II";
#NET "DDR3_ODT" LOC = L6;
#NET "DDR3_ODT" IOSTANDARD = "SSTL15_II";
#NET "DDR3_RAS_N" LOC = M5;
#NET "DDR3_RAS_N" IOSTANDARD = "SSTL15_II";
#NET "DDR3_RESET_N" LOC = E3;
#NET "DDR3_RESET_N" IOSTANDARD = "SSTL15_II";
#NET "DDR3_UDM" LOC = P3;
#NET "DDR3_UDM" IOSTANDARD = "SSTL15_II";
#NET "DDR3_UDQS_N" LOC = V1;
#NET "DDR3_UDQS_N" IOSTANDARD = "DIFF_SSTL15_II";
#NET "DDR3_UDQS_P" LOC = V2;
#NET "DDR3_UDQS_P" IOSTANDARD = "DIFF_SSTL15_II";
#NET "DDR3_WE_N" LOC = H2;
#NET "DDR3_WE_N" IOSTANDARD = "SSTL15_II";
#NET "DDR3_RZQ" LOC = K7;
#NET "DDR3_RZQ" IOSTANDARD = "SSTL15_II";
#NET "DDR3_ZIO" LOC = M7;
#NET "DDR3_ZIO" IOSTANDARD = "SSTL15_II";
#NET "DDR3_A[0]" LOC = K2;
#NET "DDR3_A[0]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_A[1]" LOC = K1;
#NET "DDR3_A[1]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_A[2]" LOC = K5;
#NET "DDR3_A[2]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_A[3]" LOC = M6;
#NET "DDR3_A[3]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_A[4]" LOC = H3;
#NET "DDR3_A[4]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_A[5]" LOC = M3;
#NET "DDR3_A[5]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_A[6]" LOC = L4;
#NET "DDR3_A[6]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_A[7]" LOC = K6;
#NET "DDR3_A[7]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_A[8]" LOC = G3;
#NET "DDR3_A[8]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_A[9]" LOC = G1;
#NET "DDR3_A[9]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_A[10]" LOC = J4;
#NET "DDR3_A[10]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_A[11]" LOC = E1;
#NET "DDR3_A[11]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_A[12]" LOC = F1;
#NET "DDR3_A[12]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_A[13]" LOC = J6;
#NET "DDR3_A[13]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_A[14]" LOC = H5;
#NET "DDR3_A[14]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_BA[0]" LOC = J3;
#NET "DDR3_BA[0]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_BA[1]" LOC = J1;
#NET "DDR3_BA[1]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_BA[2]" LOC = H1;
#NET "DDR3_BA[2]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_DQ[0]" LOC = R3;
#NET "DDR3_DQ[0]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_DQ[1]" LOC = R1;
#NET "DDR3_DQ[1]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_DQ[2]" LOC = P2;
#NET "DDR3_DQ[2]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_DQ[3]" LOC = P1;
#NET "DDR3_DQ[3]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_DQ[4]" LOC = L3;
#NET "DDR3_DQ[4]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_DQ[5]" LOC = L1;
#NET "DDR3_DQ[5]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_DQ[6]" LOC = M2;
#NET "DDR3_DQ[6]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_DQ[7]" LOC = M1;
#NET "DDR3_DQ[7]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_DQ[8]" LOC = T2;
#NET "DDR3_DQ[8]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_DQ[9]" LOC = T1;
#NET "DDR3_DQ[9]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_DQ[10]" LOC = U3;
#NET "DDR3_DQ[10]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_DQ[11]" LOC = U1;
#NET "DDR3_DQ[11]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_DQ[12]" LOC = W3;
#NET "DDR3_DQ[12]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_DQ[13]" LOC = W1;
#NET "DDR3_DQ[13]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_DQ[14]" LOC = Y2;
#NET "DDR3_DQ[14]" IOSTANDARD = "SSTL15_II";
#NET "DDR3_DQ[15]" LOC = Y1;
#NET "DDR3_DQ[15]" IOSTANDARD = "SSTL15_II";
#----------------------------------------
# UART
#----------------------------------------
#NET "UART_TXD" LOC = A2; # FPGA input
#NET "UART_TXD" IOSTANDARD = "LVCMOS25";
#NET "UART_RXD" LOC = B2; # FPGA output
#NET "UART_RXD" IOSTANDARD = "LVCMOS25";
#----------------------------------------
# Buttons and LEDs
#----------------------------------------
NET "AUX_BUTTONS_I[0]" LOC = C22;
NET "AUX_BUTTONS_I[0]" IOSTANDARD = "LVCMOS18";
NET "AUX_BUTTONS_I[1]" LOC = D21;
NET "AUX_BUTTONS_I[1]" IOSTANDARD = "LVCMOS18";
NET "AUX_LEDS_O[0]" LOC = G19;
NET "AUX_LEDS_O[0]" IOSTANDARD = "LVCMOS18";
NET "AUX_LEDS_O[1]" LOC = F20;
NET "AUX_LEDS_O[1]" IOSTANDARD = "LVCMOS18";
NET "AUX_LEDS_O[2]" LOC = F18;
NET "AUX_LEDS_O[2]" IOSTANDARD = "LVCMOS18";
NET "AUX_LEDS_O[3]" LOC = C20;
NET "AUX_LEDS_O[3]" IOSTANDARD = "LVCMOS18";
#===============================================================================
# IOBs
#===============================================================================
INST "cmp_gn4124_core/l2p_rdy_t" IOB=FALSE;
INST "cmp_gn4124_core/l_wr_rdy_t*" IOB=FALSE;
#INST "cmp_fmc_spi/shift/s_out" IOB=FALSE;
#INST "cmp_fmc_spi/clgen/clk_out" IOB=FALSE;
#===============================================================================
# Terminations
#===============================================================================
# DDR3
#NET "DDR3_DQ[*]" IN_TERM = NONE;
#NET "DDR3_LDQS_P" IN_TERM = NONE;
#NET "DDR3_LDQS_N" IN_TERM = NONE;
#NET "DDR3_UDQS_P" IN_TERM = NONE;
#NET "DDR3_UDQS_N" IN_TERM = NONE;
#===============================================================================
# Clock constraints
#===============================================================================
# GN4124
NET "L_CLKp" TNM_NET = "l_clkp_grp";
TIMESPEC TS_l_clkp = PERIOD "l_clkp_grp" 5 ns HIGH 50%;
NET "P2L_CLKp" TNM_NET = "p2l_clkp_grp";
TIMESPEC TS_p2l_clkp = PERIOD "p2l_clkp_grp" 5 ns HIGH 50%;
NET "P2L_CLKn" TNM_NET = "p2l_clkn_grp";
TIMESPEC TS_p2l_clkn = PERIOD "p2l_clkn_grp" 5 ns HIGH 50%;
# System clock
NET "clk20_vcxo_i" TNM_NET = "clk20_vcxo_i_grp";
TIMESPEC TS_clk20_vcxo_i = PERIOD "clk20_vcxo_i_grp" 50 ns HIGH 50%;
# DDR3
#NET "cmp_ddr_ctrl/cmp_ddr_controller/memc3_infrastructure_inst/sys_clk_ibufg" TNM_NET = "SYS_CLK5";
#TIMESPEC "TS_SYS_CLK5" = PERIOD "SYS_CLK5" 3.0 ns HIGH 50 %;
# ADC
#NET "adc_dco_n_i" TNM_NET = adc_dco_n_i;
#TIMESPEC TS_adc_dco_n_i = PERIOD "adc_dco_n_i" 2 ns HIGH 50%;
#===============================================================================
# False Path
#===============================================================================
# GN4124
NET "l_rst_n" TIG;
NET "cmp_gn4124_core/rst_*" TIG;
# DDR3
#NET "cmp_ddr_ctrl/cmp_ddr_controller/memc3_wrapper_inst/memc3_mcb_raw_wrapper_inst/selfrefresh_mcb_mode" TIG;
#NET "cmp_ddr_ctrl/cmp_ddr_controller/c3_pll_lock" TIG;
#NET "cmp_ddr_ctrl/cmp_ddr_controller/memc3_wrapper_inst/memc3_mcb_raw_wrapper_inst/hard_done_cal" TIG;
#NET "cmp_ddr_ctrl/cmp_ddr_controller/memc3_wrapper_inst/memc3_mcb_raw_wrapper_inst/gen_term_calib.mcb_soft_calibration_top_inst/mcb_soft_calibration_inst/DONE_SOFTANDHARD_CAL" TIG;
files = ["spec_gn4124_test.vhd"]