Commit ea24fca9 authored by Tristan Gingold's avatar Tristan Gingold

Add a testbench for the vmecore_test board.

parent 5128aee2
files = ["vme64x_sim_pkg.vhd"]
library ieee;
use ieee.std_logic_1164.all;
use work.vme64x_pkg.all;
package vme64x_sim_pkg is
constant c_log : boolean := false;
constant slave_ga : std_logic_vector (4 downto 0) := b"0_1101";
subtype cfg_addr_t is std_logic_vector (19 downto 0);
subtype byte_t is std_logic_vector (7 downto 0);
subtype word_t is std_logic_vector (15 downto 0);
subtype lword_t is std_logic_vector (31 downto 0);
subtype qword_t is std_logic_vector (63 downto 0);
type word_array_t is array (natural range <>) of word_t;
type lword_array_t is array (natural range <>) of lword_t;
type qword_array_t is array (natural range <>) of qword_t;
subtype vme_am_t is std_logic_vector (5 downto 0);
-- Debug utility.
function hex (v : std_logic_vector) return string;
-- Bus timer.
-- Set TIMEOUT to true when the slave has not ack-ed the transaction.
procedure bus_timer (signal vme_in : in t_vme64x_in;
signal timeout : out boolean;
signal clk : std_logic);
-- Write a byte to the CS/CSR space.
procedure write8_conf (signal vme_in : out t_vme64x_in;
signal vme_out : in t_vme64x_out;
signal vme_timeout : boolean;
addr : cfg_addr_t;
data : byte_t);
-- Read a byte from the CS/CSR space.
procedure read8_conf (signal vme_in : out t_vme64x_in;
signal vme_out : in t_vme64x_out;
signal vme_timeout : boolean;
addr : cfg_addr_t;
variable data : out byte_t);
procedure read32 (signal vme_in : out t_vme64x_in;
signal vme_out : in t_vme64x_out;
signal vme_timeout : boolean;
addr : std_logic_vector (31 downto 0);
am : vme_am_t;
variable data : out lword_t);
procedure Dump_CR (signal vme_in : out t_vme64x_in;
signal vme_out : in t_vme64x_out;
signal vme_timeout : boolean);
end vme64x_sim_pkg;
library ieee;
use ieee.numeric_std.all;
use std.textio.all;
package body vme64x_sim_pkg is
function hex1 (v : std_logic_vector (3 downto 0)) return character is
begin
case v is
when x"0" => return '0';
when x"1" => return '1';
when x"2" => return '2';
when x"3" => return '3';
when x"4" => return '4';
when x"5" => return '5';
when x"6" => return '6';
when x"7" => return '7';
when x"8" => return '8';
when x"9" => return '9';
when x"a" => return 'a';
when x"b" => return 'b';
when x"c" => return 'c';
when x"d" => return 'd';
when x"e" => return 'e';
when x"f" => return 'f';
when "ZZZZ" => return 'Z';
when "XXXX" => return 'X';
when others => return '?';
end case;
end hex1;
function hex2 (v : byte_t) return string is
begin
return hex1 (v(7 downto 4)) & hex1 (v(3 downto 0));
end hex2;
function hex6 (v : std_logic_vector (23 downto 0)) return string is
variable res : string (6 downto 1);
begin
for i in res'range loop
res (i) := hex1 (v (i * 4 - 1 downto i * 4 - 4));
end loop;
return res;
end hex6;
function hex8 (v : std_logic_vector (31 downto 0)) return string is
variable res : string (8 downto 1);
begin
for i in res'range loop
res (i) := hex1 (v (i * 4 - 1 downto i * 4 - 4));
end loop;
return res;
end hex8;
function hex (v : std_logic_vector) return string
is
constant ndigits : natural := v'length / 4;
subtype av_t is std_logic_vector (ndigits * 4 - 1 downto 0);
alias av : av_t is v;
variable res : string (ndigits downto 1);
begin
for i in res'range loop
res (i) := hex1 (av (i * 4 - 1 downto i * 4 - 4));
end loop;
return res;
end hex;
function Image_AM (am : natural range 0 to 63) return string is
begin
case am is
when 16#3f# => return "A24S-BLT";
when 16#3e# => return "A24S-PRG";
when 16#3d# => return "A24S-DAT";
when 16#3c# => return "A24S-MBL";
when 16#3b# => return "A24U-BLT";
when 16#3a# => return "A24U-PRG";
when 16#39# => return "A24U-DAT";
when 16#38# => return "A24U-MBL";
when 16#37# => return "A40x-BLT";
when 16#36# => return "Resvd-46";
when 16#35# => return "A40x-LCK";
when 16#34# => return "A40x-TFR";
when 16#33# => return "Resvd-33";
when 16#32# => return "A24x-LCK";
when 16#31# => return "Resvd-31";
when 16#30# => return "Resvd-30";
when 16#2f# => return "CR-CSR ";
when 16#2e# => return "Resvd-2e";
when 16#2d# => return "A16S ";
when 16#2c# => return "A16x-LCK";
when 16#2b# => return "Resvd-2b";
when 16#2a# => return "Resvd-2a";
when 16#29# => return "A16U ";
when 16#28# => return "Resvd-28";
when 16#27# downto 16#20# => return "Resvd-2x";
when 16#1f# downto 16#10# => return "UD-1x";
when 16#0f# => return "A32S-BLT";
when 16#0e# => return "A32S-PRG";
when 16#0d# => return "A32S-DAT";
when 16#0c# => return "A32S-MBL";
when 16#0b# => return "A32U-BLT";
when 16#0a# => return "A32U-PRG";
when 16#09# => return "A32U-DAT";
when 16#08# => return "A32U-MBL";
when 16#07# => return "Resvd-07";
when 16#06# => return "Resvd-06";
when 16#05# => return "A32x-LCK";
when 16#04# => return "A64x-LCK";
when 16#03# => return "A64x-BLT";
when 16#02# => return "Resvd-02";
when 16#01# => return "A64x-TFR";
when 16#00# => return "A64x-MBL";
end case;
end Image_AM;
-- Bus timer. See VME spec 2.3.3 Bus Timer
procedure bus_timer (signal vme_in : in t_vme64x_in;
signal timeout : out boolean;
signal clk : std_logic)
is
type state_t is (IDLE, WAIT_DS, COUNTING, WAIT_END, ERR);
variable state : state_t;
variable count : natural;
begin
loop
if rising_edge (clk) then
if VME_in.RST_n = '0' then
state := IDLE;
timeout <= false;
else
timeout <= false;
case state is
when IDLE =>
if VME_in.AS_n = '0' then
state := WAIT_DS;
end if;
when WAIT_DS =>
count := 20;
if VME_in.DS_n /= "11" then
state := COUNTING;
end if;
when COUNTING =>
if VME_in.DS_n = "11" then
state := WAIT_END;
else
if count = 0 then
state := ERR;
else
count := count - 1;
end if;
end if;
when WAIT_END =>
if VME_in.AS_n = '1' then
state := IDLE;
end if;
when ERR =>
timeout <= true;
-- VITAL 1 Rule 2.60
-- Once it has driven BERR* low, the bus timer MUST NOT release
-- BERR* until it detected both DS0* and DS1* high.
if VME_in.DS_n = "11" then
state := IDLE;
end if;
end case;
end if;
end if;
end loop;
end bus_timer;
-- Convert a CR/CSR address to the VME address: insert GA.
-- The ADDR is on 20 bits (so the x"" notation can be used), but as
-- ADDR(19) is stipped, it must be '0'.
function to_vme_cfg_addr (addr : cfg_addr_t)
return std_logic_vector is
begin
assert addr (19) = '0' report "a19 is discarded" severity error;
return x"00" & slave_ga & addr (18 downto 0);
end to_vme_cfg_addr;
procedure read_setup_addr (signal vme_in : out t_vme64x_in;
signal vme_out : in t_vme64x_out;
addr : std_logic_vector (31 downto 0);
am : vme_am_t) is
begin
VME_in.ADDR <= addr (31 downto 1);
VME_in.AM <= am;
VME_in.IACK_n <= '1';
wait for 35 ns;
VME_in.AS_n <= '0';
VME_in.WRITE_n <= '1';
if not (VME_out.DTACK_OE = '0' and VME_out.BERR_n = '1') then
wait until VME_out.DTACK_OE = '0' and VME_out.BERR_n = '1';
end if;
end read_setup_addr;
procedure read_wait_dtack (signal vme_out : in t_vme64x_out;
signal vme_timeout : boolean) is
begin
wait until (VME_out.DTACK_OE = '1' and VME_out.DTACK_n = '0')
or vme_timeout;
if not vme_timeout then
assert VME_out.DATA_DIR = '1' report "bad data_dir";
assert VME_out.DATA_OE_N = '0' report "bad data_oe_n";
end if;
end read_wait_dtack;
procedure read_release (signal vme_in : out t_vme64x_in) is
begin
-- Release
VME_in.AS_n <= '1';
VME_in.DS_n <= "11";
end read_release;
procedure read8 (signal vme_in : out t_vme64x_in;
signal vme_out : in t_vme64x_out;
signal vme_timeout : boolean;
addr : std_logic_vector (31 downto 0);
am : vme_am_t;
variable data : out byte_t)
is
variable res : byte_t;
begin
if c_log then
write (output, "read8 at 0x" & hex (addr) & " ["
& Image_AM (to_integer (unsigned (am))) & " ]" & LF);
end if;
VME_in.LWORD_n <= '1';
read_setup_addr (vme_in, vme_out, addr, am);
if addr (0) = '0' then
VME_in.DS_n <= "01";
else
VME_in.DS_n <= "10";
end if;
read_wait_dtack (vme_out, vme_timeout);
if not vme_timeout then
if addr (0) = '0' then
res := VME_out.DATA (15 downto 8);
else
res := VME_out.DATA (7 downto 0);
end if;
else
res := (others => 'X');
end if;
data := res;
read_release (vme_in);
if c_log then
write (output, " => 0x" & hex(res) & LF);
end if;
end read8;
procedure read16 (signal vme_in : out t_vme64x_in;
signal vme_out : in t_vme64x_out;
signal vme_timeout : boolean;
addr : std_logic_vector (31 downto 0);
am : vme_am_t;
variable data : out word_t)
is
variable res : word_t;
begin
if c_log then
write (output, "read16 at 0x" & hex (addr) & " ["
& Image_AM (to_integer (unsigned (am))) & " ]" & LF);
end if;
VME_in.LWORD_n <= '1';
read_setup_addr (vme_in, vme_out, addr, am);
assert addr (0) = '0' report "unaligned read16" severity error;
VME_in.DS_n <= "00";
read_wait_dtack (vme_out, vme_timeout);
if not vme_timeout then
res := VME_out.DATA (15 downto 0);
else
res := (others => 'X');
end if;
data := res;
read_release (vme_in);
if c_log then
write (output, " => 0x" & hex(res) & LF);
end if;
end read16;
procedure read32 (signal vme_in : out t_vme64x_in;
signal vme_out : in t_vme64x_out;
signal vme_timeout : boolean;
addr : std_logic_vector (31 downto 0);
am : vme_am_t;
variable data : out lword_t)
is
variable res : lword_t;
begin
if c_log then
write (output, "read32 at 0x" & hex (addr) & " ["
& Image_AM (to_integer (unsigned (am))) & " ]" & LF);
end if;
VME_in.LWORD_n <= '0';
read_setup_addr (vme_in, vme_out, addr, am);
assert addr (1 downto 0) = "00" report "unaligned read32" severity error;
VME_in.DS_n <= "00";
read_wait_dtack (vme_out, vme_timeout);
if not vme_timeout then
res := VME_out.DATA (31 downto 0);
else
res := (others => 'X');
end if;
data := res;
read_release (vme_in);
if c_log then
write (output, " => 0x" & hex(res) & LF);
end if;
end read32;
procedure read8_conf (signal vme_in : out t_vme64x_in;
signal vme_out : in t_vme64x_out;
signal vme_timeout : boolean;
addr : cfg_addr_t;
variable data : out byte_t) is
begin
read8 (vme_in, vme_out, vme_timeout,
to_vme_cfg_addr (addr), c_AM_CR_CSR, data);
end read8_conf;
procedure read8_conf_mb (signal vme_in : out t_vme64x_in;
signal vme_out : in t_vme64x_out;
signal vme_timeout : boolean;
addr : cfg_addr_t;
variable data : out std_logic_vector)
is
variable ad : cfg_addr_t := addr;
constant bsize : natural := data'length / 8;
subtype d_type is std_logic_vector (bsize * 8 - 1 downto 0);
alias d : d_type is data;
begin
assert data'length mod 8 = 0 report "data is not a multiple of bytes"
severity error;
for i in bsize - 1 downto 0 loop
read8_conf (vme_in, vme_out, vme_timeout,
ad, d (i * 8 + 7 downto i * 8));
ad := cfg_addr_t (unsigned(ad) + 4);
end loop;
end read8_conf_mb;
procedure write_setup_addr (signal vme_in : out t_vme64x_in;
signal vme_out : in t_vme64x_out;
addr : std_logic_vector (31 downto 0);
lword_n : std_logic;
am : vme_am_t) is
begin
if not (VME_out.DTACK_OE = '0' and VME_out.BERR_n = '1') then
wait until VME_out.DTACK_OE = '0' and VME_out.BERR_n = '1';
end if;
VME_in.ADDR <= addr(31 downto 1);
VME_in.AM <= am;
VME_in.LWORD_n <= lword_n;
VME_in.IACK_n <= '1';
wait for 35 ns;
VME_in.AS_n <= '0';
VME_in.WRITE_n <= '0';
end write_setup_addr;
procedure write_wait_dtack_pulse (signal vme_in : out t_vme64x_in;
signal vme_out : in t_vme64x_out) is
begin
wait until VME_out.DTACK_OE = '1' and VME_out.DTACK_n = '0';
VME_in.DS_n <= "11";
wait until VME_out.DTACK_OE = '0' or VME_out.DTACK_n = '1';
end write_wait_dtack_pulse;
procedure write_wait_dtack (signal vme_in : out t_vme64x_in;
signal vme_out : in t_vme64x_out) is
begin
write_wait_dtack_pulse (vme_in, vme_out);
VME_in.AS_n <= '1';
end write_wait_dtack;
procedure write8 (signal vme_in : out t_vme64x_in;
signal vme_out : in t_vme64x_out;
signal vme_timeout : boolean;
addr : std_logic_vector (31 downto 0);
am : vme_am_t;
data : byte_t) is
begin
write_setup_addr (vme_in, vme_out, addr, '1', am);
if addr (0) = '0' then
VME_in.DS_n <= "01";
VME_in.DATA (15 downto 8) <= data;
else
VME_in.DS_n <= "10";
VME_in.DATA (7 downto 0) <= data;
end if;
write_wait_dtack (vme_in, vme_out);
end write8;
procedure write16 (signal vme_in : out t_vme64x_in;
signal vme_out : in t_vme64x_out;
signal vme_timeout : boolean;
addr : std_logic_vector (31 downto 0);
am : vme_am_t;
data : word_t) is
begin
assert addr(0) = '0' report "unaligned write16" severity error;
write_setup_addr (vme_in, vme_out, addr, '1', am);
VME_in.DS_n <= "00";
VME_in.DATA (15 downto 0) <= data;
write_wait_dtack (vme_in, vme_out);
end write16;
procedure write32 (signal vme_in : out t_vme64x_in;
signal vme_out : in t_vme64x_out;
signal vme_timeout : boolean;
addr : std_logic_vector (31 downto 0);
am : vme_am_t;
data : lword_t) is
begin
assert addr(1 downto 0) = "00"
report "unaligned write16" severity error;
write_setup_addr (vme_in, vme_out, addr, '0', am);
VME_in.DS_n <= "00";
VME_in.DATA (31 downto 0) <= data;
write_wait_dtack (vme_in, vme_out);
end write32;
procedure write8_conf (signal vme_in : out t_vme64x_in;
signal vme_out : in t_vme64x_out;
signal vme_timeout : boolean;
addr : cfg_addr_t;
data : byte_t) is
begin
if c_log then
write (output,
"write8_conf at 0x" & hex (addr) & " <= " & hex2 (data));
end if;
write8(vme_in, vme_out, vme_timeout,
to_vme_cfg_addr (addr), c_AM_CR_CSR, data);
end write8_conf;
procedure ack_int (signal vme_in : out t_vme64x_in;
signal vme_out : in t_vme64x_out;
signal vme_timeout : boolean;
vec : out byte_t) is
begin
if VME_out.IRQ_n = "1111111" then
vec := (others => 'X');
return;
end if;
for i in 6 downto 0 loop
if VME_out.IRQ_n (i) = '0' then
VME_in.ADDR (3 downto 1) <= std_logic_vector (to_unsigned (i + 1, 3));
exit;
end if;
end loop;
VME_in.IACK_n <= '0';
VME_in.WRITE_n <= '1';
wait for 35 ns;
VME_in.AS_n <= '0';
if not (VME_out.DTACK_OE = '0' and VME_out.BERR_n = '1') then
wait until VME_out.DTACK_OE = '0' and VME_out.BERR_n = '1';
end if;
VME_in.DS_n <= "10";
read_wait_dtack (vme_out, vme_timeout);
if not vme_timeout then
vec := VME_out.DATA (7 downto 0);
else
vec := (others => 'X');
end if;
read_release (vme_in);
VME_in.IACK_n <= '1';
end ack_int;
function Disp_DAWPR (v : byte_t) return string is
begin
case v is
when x"81" => return "D08(O)";
when x"82" => return "D08(EO)";
when x"83" => return "D16 + D08";
when x"84" => return "D32 + D16 + D08";
when x"85" => return "MD32 + D16 + D08";
when others => return "??";
end case;
end Disp_DAWPR;
procedure Disp_AMCAP (cap : std_logic_vector (63 downto 0)) is
begin
if cap = (cap'range => '0') then
write (output, " -");
else
for i in cap'range loop
if cap (i) = '1' then
write (output, " ");
write (output, Image_AM (i));
end if;
end loop;
end if;
end Disp_AMCAP;
procedure Dump_CR (signal vme_in : out t_vme64x_in;
signal vme_out : in t_vme64x_out;
signal vme_timeout : boolean)
is
variable d : byte_t;
variable b3 : std_logic_vector (23 downto 0);
variable w : std_logic_vector (31 downto 0);
variable b8 : std_logic_vector (63 downto 0);
variable b32 : std_logic_vector (255 downto 0);
begin
if false then
read8_conf (vme_in, vme_out, vme_timeout, x"0_0003", d);
write (output, "CR checksum: 0x" & hex2 (d) & LF);
read8_conf (vme_in, vme_out, vme_timeout, x"0_0013", d);
assert d = x"81" report "invalid data width at 0x13" severity error;
write (output, "CR data width: 0x" & hex2 (d) & LF);
read8_conf (vme_in, vme_out, vme_timeout, x"0_0017", d);
assert d = x"81" report "invalid data width at 0x17" severity error;
write (output, "CSR data width: 0x" & hex2 (d) & LF);
read8_conf (vme_in, vme_out, vme_timeout, x"0_001b", d);
assert d = x"02" report "invalid spec ID at 0x1b" severity error;
write (output, "CR/CSR version: 0x" & hex2 (d) & LF);
read8_conf (vme_in, vme_out, vme_timeout, x"0_001f", d);
assert d = x"43" report "invalid valid CR byte at 0x1f" severity error;
write (output, "CR valid 'C': 0x" & hex2 (d) & LF);
read8_conf (vme_in, vme_out, vme_timeout, x"0_0023", d);
assert d = x"52" report "invalid valid CR byte at 0x23" severity error;
write (output, "CR valid 'R': 0x" & hex2 (d) & LF);
read8_conf_mb (vme_in, vme_out, vme_timeout, x"0_0027", b3);
write (output, "CR Manu ID: 0x" & hex6 (b3) & LF);
read8_conf_mb (vme_in, vme_out, vme_timeout, x"0_0033", w);
write (output, "CR Board ID: 0x" & hex8 (w) & LF);
read8_conf_mb (vme_in, vme_out, vme_timeout, x"0_0043", w);
write (output, "CR Rev ID: 0x" & hex8 (w) & LF);
read8_conf_mb (vme_in, vme_out, vme_timeout, x"0_0053", b3);
write (output, "CR ASCII ptr: 0x" & hex6 (b3) & LF);
read8_conf (vme_in, vme_out, vme_timeout, x"0_007F", d);
write (output, "CR Program ID: 0x" & hex2 (d) & LF);
end if;
-- VME64x
if false then
read8_conf_mb (vme_in, vme_out, vme_timeout, x"0_0083", b3);
write (output, "CR BEG_USER_CR: 0x" & hex6 (b3) & LF);
read8_conf_mb (vme_in, vme_out, vme_timeout, x"0_008F", b3);
write (output, "CR END_USER_CR: 0x" & hex6 (b3) & LF);
read8_conf_mb (vme_in, vme_out, vme_timeout, x"0_009B", b3);
write (output, "CR BEG_CRAM: 0x" & hex6 (b3) & LF);
read8_conf_mb (vme_in, vme_out, vme_timeout, x"0_00A7", b3);
write (output, "CR END_CRAM: 0x" & hex6 (b3) & LF);
read8_conf_mb (vme_in, vme_out, vme_timeout, x"0_00B3", b3);
write (output, "CR BEG_USER_CSR: 0x" & hex6 (b3) & LF);
read8_conf_mb (vme_in, vme_out, vme_timeout, x"0_00B3", b3);
write (output, "CR END_USER_CSR: 0x" & hex6 (b3) & LF);
read8_conf_mb (vme_in, vme_out, vme_timeout, x"0_00CB", b3);
write (output, "CR BEG_SN: 0x" & hex6 (b3) & LF);
read8_conf_mb (vme_in, vme_out, vme_timeout, x"0_00D7", b3);
write (output, "CR END_SN: 0x" & hex6 (b3) & LF);
read8_conf (vme_in, vme_out, vme_timeout, x"0_00E3", d);
write (output, "CR Slave charac: 0x" & hex2 (d) & LF);
read8_conf (vme_in, vme_out, vme_timeout, x"0_00E7", d);
write (output, "CR user-def: 0x" & hex2 (d) & LF);
read8_conf (vme_in, vme_out, vme_timeout, x"0_00EB", d);
write (output, "CR master chara: 0x" & hex2 (d) & LF);
read8_conf (vme_in, vme_out, vme_timeout, x"0_00EF", d);
write (output, "CR user-def: 0x" & hex2 (d) & LF);
read8_conf (vme_in, vme_out, vme_timeout, x"0_00F3", d);
write (output, "CR INT hand cap: 0x" & hex2 (d) & LF);
read8_conf (vme_in, vme_out, vme_timeout, x"0_00F7", d);
write (output, "CR INT cap: 0x" & hex2 (d) & LF);
read8_conf (vme_in, vme_out, vme_timeout, x"0_00FF", d);
write (output, "CR CRAM acc wd: 0x" & hex2 (d) & LF);
for i in 0 to 7 loop
read8_conf (vme_in, vme_out, vme_timeout,
std_logic_vector (unsigned'(x"0_0103") + i * 4), d);
write (output, "CR FN" & natural'image (i) & " DAW: 0x"
& hex2 (d) & " [" & Disp_DAWPR (d) & ']' & LF);
end loop;
for i in 0 to 7 loop
read8_conf_mb (vme_in, vme_out, vme_timeout,
std_logic_vector (unsigned'(x"0_0123") + i * 32), b8);
write (output, "CR FN" & natural'image (i) & " AMCAP: 0x"
& hex (b8) & " [");
Disp_AMCAP (b8);
write (output, " ]" & LF);
end loop;
end if;
read8_conf_mb (vme_in, vme_out, vme_timeout, x"0_0223", b32);
write (output, "CR FN0 XAMCAP: 0x" & hex (b32) & LF);
read8_conf_mb (vme_in, vme_out, vme_timeout, x"0_02a3", b32);
write (output, "CR FN1 XAMCAP: 0x" & hex (b32) & LF);
-- ...
read8_conf_mb (vme_in, vme_out, vme_timeout, x"0_0623", w);
write (output, "CR FN0 ADEM: 0x" & hex (w) & LF);
read8_conf_mb (vme_in, vme_out, vme_timeout, x"0_0633", w);
write (output, "CR FN1 ADEM: 0x" & hex (w) & LF);
-- ...
read8_conf_mb (vme_in, vme_out, vme_timeout, x"7_FF63", w);
write (output, "CR FN0 ADER: 0x" & hex (w) & LF);
read8_conf_mb (vme_in, vme_out, vme_timeout, x"7_FF73", w);
write (output, "CR FN1 ADER: 0x" & hex (w) & LF);
read8_conf (vme_in, vme_out, vme_timeout, x"0_06af", d);
write (output, "CR master DAWPR: 0x" & hex2 (d) & LF);
read8_conf_mb (vme_in, vme_out, vme_timeout, x"0_06b3", b8);
write (output, "CR master AMCAP: 0x" & hex (b8) & LF);
read8_conf_mb (vme_in, vme_out, vme_timeout, x"0_06d3", b32);
write (output, "CR mastr XAMCAP: 0x" & hex (b32) & LF);
end Dump_CR;
end vme64x_sim_pkg;
action = "simulation"
target = "xilinx"
sim_tool = "ghdl"
sim_top = "tb_vmecore_test"
vcom_opt = "-93 -mixedsvvh"
ghdl_opt = "-fsynopsys"
svec_template_ucf = []
syn_device = "xc6slx150t" # For rams.
board = "svec"
ctrls = ["bank4_64b_32b"]
# Allow the user to override fetchto using:
# hdlmake -p "fetchto='xxx'"
if locals().get('fetchto', None) is None:
fetchto = "../../ip_cores"
#include_dirs=[fetchto + "/vme64x-core/hdl/sim/vme64x_bfm",
# fetchto + "/general-cores/sim"]
files = [ "buildinfo_pkg.vhd", "tb_vmecore_test.vhd"]
modules = {
"local" : [
"../../sim/vhdl_sim",
"../../top/vmecore_test" ],
"git" : [
# "https://ohwr.org/project/wr-cores.git",
"https://ohwr.org/project/general-cores.git",
"https://ohwr.org/project/vme64x-core.git",
# "https://ohwr.org/project/ddr3-sp6-core.git",
],
}
# Do not fail during hdlmake fetch
try:
exec(open(fetchto + "/general-cores/tools/gen_buildinfo.py").read())
except:
pass
use std.textio.all;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.vme64x_pkg.all;
use work.vme64x_sim_pkg.all;
entity tb_vmecore_test is
end tb_vmecore_test;
architecture behav of tb_vmecore_test is
signal rst_n_i : std_logic;
signal clk_20m_vcxo_i : std_logic := '0';
signal vme_write_n_i : std_logic;
signal vme_sysreset_n_i : std_logic;
signal vme_retry_oe_o : std_logic;
signal vme_retry_n_o : std_logic;
signal vme_lword_n_b : std_logic;
signal vme_iackout_n_o : std_logic;
signal vme_iackin_n_i : std_logic;
signal vme_iack_n_i : std_logic;
signal vme_gap_i : std_logic;
signal vme_dtack_oe_o : std_logic;
signal vme_dtack_n_o : std_logic;
signal vme_ds_n_i : std_logic_vector(1 downto 0);
signal vme_data_oe_n_o : std_logic;
signal vme_data_dir_o : std_logic;
signal vme_berr_o : std_logic;
signal vme_as_n_i : std_logic;
signal vme_addr_oe_n_o : std_logic;
signal vme_addr_dir_o : std_logic;
signal vme_irq_o : std_logic_vector(7 downto 1);
signal vme_ga_i : std_logic_vector(4 downto 0);
signal vme_data_b : std_logic_vector(31 downto 0);
signal vme_am_i : std_logic_vector(5 downto 0);
signal vme_addr_b : std_logic_vector(31 downto 1);
signal pcbrev_i : std_logic_vector(4 downto 0);
signal fp_led_line_oen_o : std_logic_vector(1 downto 0);
signal fp_led_line_o : std_logic_vector(1 downto 0);
signal fp_led_column_o : std_logic_vector(3 downto 0);
signal fp_gpio1_b : std_logic;
signal fp_gpio2_b : std_logic;
signal fp_gpio3_b : std_logic;
signal fp_gpio4_b : std_logic;
signal fp_term_en_o : std_logic_vector(4 downto 1);
signal fp_gpio1_a2b_o : std_logic;
signal fp_gpio2_a2b_o : std_logic;
signal fp_gpio34_a2b_o : std_logic;
signal vme_in : t_vme64x_in;
signal vme_out : t_vme64x_out;
signal vme_timeout : boolean := false;
signal stop : boolean := false;
begin
-- Clock.
process
begin
clk_20m_vcxo_i <= '0';
wait for 25 ns;
clk_20m_vcxo_i <= '1';
wait for 25 ns;
if stop then
wait;
end if;
end process;
process
is
procedure dump32 (base : natural; nword : natural)
is
variable addr : std_logic_vector (31 downto 0);
variable d32 : lword_t;
begin
for i in 0 to nword - 1 loop
addr := std_logic_vector(to_unsigned(base + i * 4, 32));
read32 (vme_in, vme_out, vme_timeout, x"00_10_00_00" or addr,
c_AM_A24, d32);
write(output, hex(addr) & ": " & hex(d32) & LF);
end loop;
end dump32;
variable d8 : byte_t;
variable d16 : word_t;
variable d32 : lword_t;
begin
-- Each scenario starts with a reset.
-- VME reset
report "VME reset";
vme_in.ga <= '1' & slave_ga;
rst_n_i <= '0';
VME_in.RST_n <= '0';
VME_in.AS_n <= '1';
VME_in.ADDR <= (others => '1');
VME_in.AM <= (others => '1');
VME_in.DS_n <= "11";
VME_in.iackin_n <= '1';
wait for 40 ns;
VME_in.RST_n <= '1';
rst_n_i <= '1';
wait for 40 ns;
report "Set ADER";
-- Set ADER
write8_conf (vme_in, vme_out, vme_timeout, x"7_ff77", x"10");
write8_conf (vme_in, vme_out, vme_timeout, x"7_ff7f", c_AM_A24 & "00");
read8_conf (vme_in, vme_out, vme_timeout, x"7_ff77", d8);
assert d8 = x"10" report "bad ADER0 value" severity error;
report "Set ENable";
-- Enable card
write8_conf (vme_in, vme_out, vme_timeout, x"7_fffb", b"0001_0000");
read8_conf (vme_in, vme_out, vme_timeout, x"7_fffb", d8);
assert d8 = b"0001_0000" report "module must be enabled"
severity error;
report "read data: " & hex (d8);
-- dump_CR (vme_in, vme_out, vme_timeout);
report "Dump patterns";
dump32 (16#c000#, 4);
if false then
report "VME CR";
dump_CR (vme_in, vme_out, vme_timeout);
end if;
report "done";
stop <= true;
wait;
end process;
vme_data_b <= vme_in.data when not (vme_out.data_oe_n = '0'
and vme_out.data_dir = '1')
else (others => 'H');
vme_out.data <= vme_data_b;
vme_addr_b <= vme_in.addr when not (vme_out.addr_oe_n = '0'
and vme_out.addr_dir = '1')
else (others => 'H');
vme_out.addr <= vme_addr_b;
vme_lword_n_b <= vme_in.lword_n when not (vme_out.addr_oe_n = '0'
and vme_out.addr_dir = '1')
else 'H';
vme_out.lword_n <= vme_lword_n_b;
-- ga is inverted.
vme_ga_i <= not vme_in.ga (4 downto 0);
vme_gap_i <= vme_in.ga(5);
vme_out.berr_n <= not vme_berr_o;
dut: entity work.svec_vmecore_test_top
generic map (
g_SIMULATION => True
)
port map (
rst_n_i => rst_n_i,
clk_20m_vcxo_i => clk_20m_vcxo_i,
vme_gap_i => vme_gap_i,
vme_ga_i => vme_ga_i,
vme_as_n_i => vme_in.as_n,
vme_sysreset_n_i => vme_in.rst_n,
vme_write_n_i => vme_in.write_n,
vme_am_i => vme_in.am,
vme_ds_n_i => vme_in.ds_n,
vme_iack_n_i => vme_in.iack_n,
vme_iackin_n_i => vme_in.iackin_n,
vme_iackout_n_o => vme_out.iackout_n,
vme_dtack_n_o => vme_out.dtack_n,
vme_dtack_oe_o => vme_out.dtack_oe,
vme_data_dir_o => vme_out.data_dir,
vme_data_oe_n_o => vme_out.data_oe_n,
vme_addr_dir_o => vme_out.addr_dir,
vme_addr_oe_n_o => vme_out.addr_oe_n,
vme_retry_n_o => vme_out.retry_n,
vme_retry_oe_o => vme_out.retry_oe,
vme_berr_o => vme_berr_o,
vme_irq_o => vme_irq_o,
vme_lword_n_b => vme_lword_n_b,
vme_data_b => vme_data_b,
vme_addr_b => vme_addr_b,
fp_led_line_oen_o => fp_led_line_oen_o,
fp_led_line_o => fp_led_line_o,
fp_led_column_o => fp_led_column_o);
end behav;
......@@ -7,7 +7,7 @@
-- Author(s) : Tristan Gingold <tristan.gingold@cern.ch>
-- Company : CERN (BE-CO-HT)
-- Created : 2017-09-19
-- Last update: 2020-03-12
-- Last update: 2020-05-29
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: Top-level file for the test design .
......@@ -48,6 +48,9 @@ library unisim;
use unisim.vcomponents.all;
entity svec_vmecore_test_top is
generic (
g_SIMULATION : boolean := False
);
port (
---------------------------------------------------------------------------
-- Clocks/resets
......@@ -199,80 +202,94 @@ architecture top of svec_vmecore_test_top is
signal sys_locked : std_logic;
begin -- architecture top
p_powerup_reset : process(clk_sys)
begin
if rising_edge(clk_sys) then
if(vme_sysreset_n_i = '0' or rst_n_i = '0') then
powerup_rst_n <= '0';
elsif sys_locked = '1' then
if(powerup_reset_cnt = "11111111") then
powerup_rst_n <= '1';
gen_pll: if not g_SIMULATION generate
p_powerup_reset : process(clk_sys)
begin
if rising_edge(clk_sys) then
if(vme_sysreset_n_i = '0' or rst_n_i = '0') then
powerup_rst_n <= '0';
elsif sys_locked = '1' then
if(powerup_reset_cnt = "11111111") then
powerup_rst_n <= '1';
else
powerup_rst_n <= '0';
powerup_reset_cnt <= powerup_reset_cnt + 1;
end if;
else
powerup_rst_n <= '0';
powerup_reset_cnt <= powerup_reset_cnt + 1;
powerup_reset_cnt <= "00000000";
end if;
else
powerup_rst_n <= '0';
powerup_reset_cnt <= "00000000";
end if;
end if;
end process;
-------------------------------------------------------------------------------
-- Clock distribution/PLL and reset
-------------------------------------------------------------------------------
-- Input is 20Mhz
U_cmp_sys_pll : PLL_BASE
generic map (
BANDWIDTH => "OPTIMIZED",
CLK_FEEDBACK => "CLKFBOUT",
COMPENSATION => "INTERNAL",
DIVCLK_DIVIDE => 1,
CLKFBOUT_MULT => 50, -- 1Ghz
CLKFBOUT_PHASE => 0.000,
CLKOUT0_DIVIDE => 8, -- 2*62.5 MHz
CLKOUT0_PHASE => 0.000,
CLKOUT0_DUTY_CYCLE => 0.500,
CLKOUT1_DIVIDE => 8, -- 2*62.5 MHz
CLKOUT1_PHASE => 0.000,
CLKOUT1_DUTY_CYCLE => 0.500,
CLKOUT2_DIVIDE => 8,
CLKOUT2_PHASE => 0.000,
CLKOUT2_DUTY_CYCLE => 0.500,
CLKIN_PERIOD => 50.0,
REF_JITTER => 0.016)
port map (
CLKFBOUT => pllout_clk_fb_sys,
CLKOUT0 => pllout_clk_sys,
CLKOUT1 => open, -- pllout_clk_sys,
CLKOUT2 => open,
CLKOUT3 => open,
CLKOUT4 => open,
CLKOUT5 => open,
LOCKED => sys_locked,
RST => '0',
CLKFBIN => pllout_clk_fb_sys,
CLKIN => clk_20m_vcxo_buf);
U_Sync_Reset : gc_sync_ffs
port map (
clk_i => clk_sys,
rst_n_i => '1',
data_i => powerup_rst_n,
synced_o => local_reset_n);
U_cmp_clk_vcxo_buf : BUFG
port map (
O => clk_20m_vcxo_buf,
I => clk_20m_vcxo_i);
U_cmp_clk_sys_buf : BUFG
port map (
O => clk_sys,
I => pllout_clk_sys);
end process;
--------------------------------------------------------------------------
-- Clock distribution/PLL and reset
--------------------------------------------------------------------------
-- Input is 20Mhz
U_cmp_sys_pll : PLL_BASE
generic map (
BANDWIDTH => "OPTIMIZED",
CLK_FEEDBACK => "CLKFBOUT",
COMPENSATION => "INTERNAL",
DIVCLK_DIVIDE => 1,
CLKFBOUT_MULT => 50, -- 1Ghz
CLKFBOUT_PHASE => 0.000,
CLKOUT0_DIVIDE => 8, -- 2*62.5 MHz
CLKOUT0_PHASE => 0.000,
CLKOUT0_DUTY_CYCLE => 0.500,
CLKOUT1_DIVIDE => 8, -- 2*62.5 MHz
CLKOUT1_PHASE => 0.000,
CLKOUT1_DUTY_CYCLE => 0.500,
CLKOUT2_DIVIDE => 8,
CLKOUT2_PHASE => 0.000,
CLKOUT2_DUTY_CYCLE => 0.500,
CLKIN_PERIOD => 50.0,
REF_JITTER => 0.016)
port map (
CLKFBOUT => pllout_clk_fb_sys,
CLKOUT0 => pllout_clk_sys,
CLKOUT1 => open, -- pllout_clk_sys,
CLKOUT2 => open,
CLKOUT3 => open,
CLKOUT4 => open,
CLKOUT5 => open,
LOCKED => sys_locked,
RST => '0',
CLKFBIN => pllout_clk_fb_sys,
CLKIN => clk_20m_vcxo_buf);
U_Sync_Reset : gc_sync_ffs
port map (
clk_i => clk_sys,
rst_n_i => '1',
data_i => powerup_rst_n,
synced_o => local_reset_n);
U_cmp_clk_vcxo_buf : BUFG
port map (
O => clk_20m_vcxo_buf,
I => clk_20m_vcxo_i);
U_cmp_clk_sys_buf : BUFG
port map (
O => clk_sys,
I => pllout_clk_sys);
end generate;
gen_nopll: if g_SIMULATION generate
process
begin
clk_sys <= '0';
wait for 8 ns;
clk_sys <= '1';
wait for 8 ns;
end process;
local_reset_n <= '0', '1' after 16 ns;
end generate;
-----------------------------------------------------------------------------
-- VME64x Core and buffers
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment