Skip to content
Snippets Groups Projects
Commit e0989069 authored by Jonathan Hargreaves's avatar Jonathan Hargreaves
Browse files

New testbenches for UniBoard2 sens and pmbus. They run but still need to add...

New testbenches for UniBoard2 sens and pmbus. They run but still need to add self checking. Also generic model for i2c pmbus devices
parent 592b1709
No related branches found
No related tags found
No related merge requests found
-------------------------------------------------------------------------------
--
-- Copyright (C) 2009
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-------------------------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
USE work.i2c_dev_unb2_pkg.ALL;
ENTITY dev_pmbus IS
GENERIC(
g_address : STD_LOGIC_VECTOR(6 DOWNTO 0)
);
PORT(
scl : IN STD_LOGIC;
sda : INOUT STD_LOGIC;
vin : IN INTEGER;
vout : IN INTEGER;
iout : IN INTEGER;
vcap : IN INTEGER;
temp : IN INTEGER
);
END dev_pmbus;
ARCHITECTURE beh OF dev_pmbus IS
SIGNAL enable : STD_LOGIC; --enable
SIGNAL stop : STD_LOGIC; --stop
SIGNAL wr_dat : STD_LOGIC_VECTOR(7 DOWNTO 0); --I2C write data
SIGNAL wr_val : STD_LOGIC;
SIGNAL rd_dat : STD_LOGIC_VECTOR(7 DOWNTO 0); --I2C read data
SIGNAL rd_req : STD_LOGIC;
SIGNAL cmd_en : STD_LOGIC := '0';
SIGNAL cmd : NATURAL; --device command
SIGNAL config_reg : STD_LOGIC_VECTOR(7 DOWNTO 0) := "00001000";
SIGNAL status_reg : STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS => '0');
SIGNAL temp_hi_reg : STD_LOGIC_VECTOR(7 DOWNTO 0) := "01111111";
SIGNAL temp_lo_reg : STD_LOGIC_VECTOR(7 DOWNTO 0) := "11001001";
BEGIN
i2c_slv_device : ENTITY work.i2c_slv_device
GENERIC MAP (
g_address => g_address
)
PORT MAP (
scl => scl,
sda => sda,
en => enable,
p => stop,
wr_dat => wr_dat,
wr_val => wr_val,
rd_req => rd_req,
rd_dat => rd_dat
);
p_write : PROCESS (enable, wr_val) --first write byte is treated as command
BEGIN
IF RISING_EDGE(enable) THEN
cmd_en <= '1';
ELSIF FALLING_EDGE(enable) THEN
cmd_en <= '0';
END IF;
IF RISING_EDGE(wr_val) THEN
cmd_en <= '0';
IF cmd_en='1' THEN
cmd <= TO_INTEGER(UNSIGNED(wr_dat));
ELSE
CASE cmd IS -- add write cmd later
WHEN OTHERS => NULL;
END CASE;
END IF;
END IF;
END PROCESS;
p_read : PROCESS (rd_req)
BEGIN
IF RISING_EDGE(rd_req) THEN
CASE cmd IS --only model some read cmd
WHEN PMBUS_REG_READ_VIN => rd_dat <= STD_LOGIC_VECTOR(TO_SIGNED(vin,8));
WHEN PMBUS_REG_READ_VOUT => rd_dat <= STD_LOGIC_VECTOR(TO_SIGNED(vout,8));
WHEN PMBUS_REG_READ_IOUT => rd_dat <= STD_LOGIC_VECTOR(TO_SIGNED(iout,8));
WHEN PMBUS_REG_READ_VCAP => rd_dat <= STD_LOGIC_VECTOR(TO_SIGNED(vcap,8));
WHEN PMBUS_REG_READ_TEMP => rd_dat <= STD_LOGIC_VECTOR(TO_SIGNED(temp,8));
WHEN OTHERS => rd_dat <= (OTHERS => '1');
END CASE;
END IF;
END PROCESS;
END beh;
-------------------------------------------------------------------------------
--
-- Copyright (C) 2012
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-------------------------------------------------------------------------------
-- Purpose: Verify the i2c_commander and create a u_protocol_ram init file
--
-- Description:
-- The protocols for the I2C slaves on UNB are stored in the dev_unb_pkg.
-- The protocols for the I2C slaves on ADU are stored in the dev_adu_pkg.
-- This tb can model both via g_board = "unb" or "adu". The protocols for the
-- board are concatenated into c_protocol_ram_init.
-- The p_mm_stimuli writes the c_protocol_ram_init bytes to u_protocol_ram
-- and in parallel they get written to a file by u_protocol_ram_init_file:
--
-- data/adu_protocol_ram_init.txt
-- or
-- data/unb_protocol_ram_init.txt
--
-- See data/how_to_create_memory_init_hex_file.txt for how to
-- create a memory initialization hex file from this.
--
-- The p_mm_stimuli continues with executing all protocol lists and checking
-- the expected results and ASSERTs ERROR if an access went not OK and in
-- case of read data if the read data value was not OK.
--
-- Remark:
-- . Use c_protocol_ram_init_file="UNUSED" to initialize the u_protocol_ram
-- with the c_protocol_ram_init sequence,
-- else use the actual protocol_ram_init.hex file and verify that it contains
-- the same as the c_protocol_ram_init sequence.
--
-- Usage:
-- > do wave_i2c_commander.do
-- > run -all
-- In the Wave Window view the signal u_commander/protocol_index to observe
-- the progress
--
-- Uniboard2 version derived from tb_i2c_commander November 2015
-- this version tests the PMBUS bus
ENTITY tb_i2c_commander_unb2_pmbus IS
GENERIC (
g_board : STRING := "unb2" -- only works with UniBoard2
);
END tb_i2c_commander_unb2_pmbus;
LIBRARY IEEE, common_lib, tst_lib;
USE IEEE.std_logic_1164.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE common_lib.tb_common_pkg.ALL;
USE common_lib.tb_common_mem_pkg.ALL;
USE work.i2c_smbus_pkg.ALL;
USE work.i2c_dev_max1617_pkg.ALL;
USE work.i2c_dev_unb2_pkg.ALL;
USE work.i2c_pkg.ALL;
USE work.i2c_commander_pkg.ALL;
USE work.i2c_commander_unb2_sens_pkg.ALL;
USE work.i2c_commander_unb2_pmbus_pkg.ALL; -- in case we can add the PMBUS later
ARCHITECTURE tb OF tb_i2c_commander_unb2_pmbus IS
--CONSTANT c_protocol_ram_init_file : STRING := "data/unb2_sens_protocol_ram_init.hex";
--CONSTANT c_protocol_ram_init_file : STRING := "data/unb2_pmbus_protocol_ram_init.hex";
CONSTANT c_protocol_ram_init_file : STRING := "UNUSED"; -- start with this, then make a hex file from the txt file?
CONSTANT c_use_result_ram : BOOLEAN := TRUE;
CONSTANT c_sim : BOOLEAN := TRUE; --FALSE
CONSTANT c_clk_freq_in_MHz : NATURAL := 100; -- 100 MHz
CONSTANT c_clk_period : TIME := (10**3/c_clk_freq_in_MHz) * 1 ns;
CONSTANT c_rst_period : TIME := 4 * c_clk_period;
CONSTANT c_phy_i2c : t_c_i2c_phy := func_i2c_sel_a_b(c_sim, c_i2c_phy_sim, func_i2c_calculate_phy(c_clk_freq_in_MHz));
--CONSTANT c_pmbus_temp_address : STD_LOGIC_VECTOR := TO_UVEC(MAX1617_ADR_LOW_LOW, 7); -- use other slave address to force I2C errors
CONSTANT c_pmbus_core_address : STD_LOGIC_VECTOR := TO_UVEC(I2C_UNB2_PMB_CORE_BMR464_ADR, 7);
CONSTANT c_pmbus_vccram_address : STD_LOGIC_VECTOR := TO_UVEC(I2C_UNB2_PMB_VCCRAM_BMR461_ADR, 7);
CONSTANT c_pmbus_tcvr0_address : STD_LOGIC_VECTOR := TO_UVEC(I2C_UNB2_PMB_TCVR0_BMR461_ADR, 7);
CONSTANT c_pmbus_tcvr1_address : STD_LOGIC_VECTOR := TO_UVEC(I2C_UNB2_PMB_TCVR1_BMR461_ADR, 7);
CONSTANT c_pmbus_ctrl_address : STD_LOGIC_VECTOR := TO_UVEC(I2C_UNB2_PMB_CTRL_BMR461_ADR, 7);
CONSTANT c_pmbus_fpgaio_address : STD_LOGIC_VECTOR := TO_UVEC(I2C_UNB2_PMB_FPGAIO_BMR461_ADR, 7);
CONSTANT c_max1618_temp : INTEGER := 60;
-- Select the expected read data arrays for the result data (the read data values are tb dependent, so therefore they are not obtained from a package)
TYPE t_i2c_unb2_natural_arr IS ARRAY (INTEGER RANGE 0 TO 31) OF NATURAL; -- needto test some long protocol lists
TYPE t_i2c_unb2_natural_mat IS ARRAY (INTEGER RANGE <>) OF t_i2c_unb2_natural_arr;
CONSTANT c_default_expected_data_arr : t_i2c_unb2_natural_arr := ( others => 254);
CONSTANT c_expected_data_mat : t_i2c_unb2_natural_mat(0 TO c_i2c_unb2_nof_protocol_lists-1) := (c_default_expected_data_arr,
c_default_expected_data_arr,
c_default_expected_data_arr,
c_default_expected_data_arr);
-- RAM sizes
CONSTANT c_mem_i2c : t_c_i2c_mm := c_i2c_cmdr_unb2_pmbus_i2c_mm;
-- Commander parameters
CONSTANT c_protocol_ram_init : t_nat_natural_arr := c_i2c_cmdr_unb2_pmbus_protocol_ram_init;
CONSTANT c_nof_result_data_arr : t_nat_natural_arr := c_i2c_cmdr_unb2_pmbus_nof_result_data_arr;
CONSTANT c_protocol_commander : t_c_i2c_cmdr_commander := c_i2c_cmdr_unb2_pmbus_protocol_commander;
-- Commander MM register word indexes
CONSTANT c_protocol_status_wi : NATURAL := 3*c_protocol_commander.nof_protocols;
CONSTANT c_result_error_cnt_wi : NATURAL := 3*c_protocol_commander.nof_protocols + 1;
CONSTANT c_result_data_wi : NATURAL := 3*c_protocol_commander.nof_protocols + 2;
-- Test bench PHY
SIGNAL tb_end : STD_LOGIC := '0';
SIGNAL clk : STD_LOGIC := '0';
SIGNAL rst : STD_LOGIC := '1';
SIGNAL sync : STD_LOGIC := '1';
SIGNAL scl_stretch : STD_LOGIC := 'Z';
SIGNAL scl : STD_LOGIC;
SIGNAL sda : STD_LOGIC;
-- File interface
SIGNAL file_miso : t_mem_miso;
SIGNAL file_mosi : t_mem_mosi;
-- MM registers interface
SIGNAL commander_miso : t_mem_miso;
SIGNAL commander_mosi : t_mem_mosi;
SIGNAL protocol_miso : t_mem_miso;
SIGNAL protocol_mosi : t_mem_mosi;
SIGNAL result_miso : t_mem_miso;
SIGNAL result_mosi : t_mem_mosi;
-- Commander results
SIGNAL protocol_data : NATURAL;
SIGNAL protocol_status : NATURAL;
SIGNAL result_data : NATURAL;
SIGNAL result_error_cnt : NATURAL;
BEGIN
-- run -all
rst <= '0' AFTER 4*c_clk_period;
clk <= (NOT clk) OR tb_end AFTER c_clk_period/2;
-- I2C bus
scl <= 'H'; -- model I2C pull up
sda <= 'H'; -- model I2C pull up, use '0' and '1' to verify SDA forced low or high error
scl <= scl_stretch;
sens_clk_stretch : PROCESS (scl)
BEGIN
IF falling_edge(scl) THEN
scl_stretch <= '0', 'Z' AFTER 50 ns; -- < 10 ns to effectively disable stretching, >= 50 ns to enable it
END IF;
END PROCESS;
u_protocol_ram_init_file : ENTITY tst_lib.tst_output
GENERIC MAP (
g_file_name => "data/" & g_board & "_protocol_ram_init.txt",
g_nof_data => 1,
g_data_width => c_byte_w,
g_data_type => "UNSIGNED"
)
PORT MAP (
clk => clk,
rst => rst,
in_dat => file_mosi.wrdata(c_byte_w-1 DOWNTO 0),
in_val => file_mosi.wr
);
p_mm_stimuli : PROCESS
BEGIN
-- Wait for reset release
commander_mosi <= c_mem_mosi_rst;
file_mosi <= c_mem_mosi_rst;
protocol_mosi <= c_mem_mosi_rst;
result_mosi <= c_mem_mosi_rst;
proc_common_wait_until_low(clk, rst);
proc_common_wait_some_cycles(clk, 10);
----------------------------------------------------------------------------
-- Initialize the u_protocol_ram or verify its default contents
----------------------------------------------------------------------------
IF c_protocol_ram_init_file="UNUSED" THEN
-- Write
FOR I IN 0 TO c_protocol_ram_init'LENGTH-1 LOOP
proc_mem_mm_bus_wr(I, c_protocol_ram_init(I), clk, protocol_miso, protocol_mosi); -- fill u_protocol_ram
END LOOP;
FOR I IN c_protocol_ram_init'LENGTH TO c_mem_i2c.protocol_nof_dat-1 LOOP
proc_mem_mm_bus_wr(I, SMBUS_C_END, clk, protocol_miso, protocol_mosi); -- fill remainder of u_protocol_ram with default
END LOOP;
ELSE
-- Read and verify
FOR I IN 0 TO c_protocol_ram_init'LENGTH-1 LOOP
proc_mem_mm_bus_rd(I, clk, protocol_miso, protocol_mosi);
proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, clk);
protocol_data <= TO_UINT(protocol_miso.rddata(c_byte_w-1 DOWNTO 0));
proc_common_wait_some_cycles(clk, 1);
ASSERT c_protocol_ram_init(I)=protocol_data
REPORT "Unexpected protocol data" SEVERITY ERROR;
END LOOP;
FOR I IN c_protocol_ram_init'LENGTH TO c_mem_i2c.protocol_nof_dat-1 LOOP
proc_mem_mm_bus_rd(I, clk, protocol_miso, protocol_mosi);
proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, clk);
protocol_data <= TO_UINT(protocol_miso.rddata(c_byte_w-1 DOWNTO 0));
proc_common_wait_some_cycles(clk, 1);
ASSERT SMBUS_C_END=protocol_data
REPORT "Unexpected protocol end data" SEVERITY ERROR;
END LOOP;
END IF;
proc_common_wait_some_cycles(clk, 10);
----------------------------------------------------------------------------
-- Create the u_protocol_ram_init_file
----------------------------------------------------------------------------
FOR I IN 0 TO c_protocol_ram_init'LENGTH-1 LOOP
proc_mem_mm_bus_wr(I, c_protocol_ram_init(I), clk, file_miso, file_mosi); -- fill u_protocol_ram_init_file
END LOOP;
FOR I IN c_protocol_ram_init'LENGTH TO c_mem_i2c.protocol_nof_dat-1 LOOP
proc_mem_mm_bus_wr(I, SMBUS_C_END, clk, file_miso, file_mosi); -- fill remainder of u_protocol_ram_init_file with default
END LOOP;
proc_common_wait_some_cycles(clk, 10);
----------------------------------------------------------------------------
-- Try and verify all commander protocols
----------------------------------------------------------------------------
FOR P IN 0 TO c_protocol_commander.nof_protocols-1 LOOP
-- Issue protocol list P
proc_mem_mm_bus_wr(P, 1, clk, commander_miso, commander_mosi);
-- Wait for protocol done
WHILE protocol_status/=c_i2c_cmdr_state_done LOOP
-- read commander protocol status register
proc_mem_mm_bus_rd(c_protocol_status_wi, clk, commander_miso, commander_mosi);
proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, clk);
protocol_status <= TO_UINT(commander_miso.rddata);
proc_common_wait_some_cycles(clk, 1);
END LOOP;
-- Read commander result error count
proc_mem_mm_bus_rd(c_result_error_cnt_wi, clk, commander_miso, commander_mosi);
proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, clk);
result_error_cnt <= TO_UINT(commander_miso.rddata);
proc_common_wait_some_cycles(clk, 1);
ASSERT result_error_cnt=0
REPORT "The result error count is not 0" SEVERITY ERROR;
-- Read commander result data
FOR I IN 0 TO c_nof_result_data_arr(P)-1 LOOP
proc_mem_mm_bus_rd(c_result_data_wi+I, clk, commander_miso, commander_mosi);
proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, clk);
result_data <= TO_UINT(commander_miso.rddata);
proc_common_wait_some_cycles(clk, 1);
ASSERT c_expected_data_mat(P)(I)=result_data
REPORT "Unexpected result data" SEVERITY WARNING;
END LOOP;
-- Wait for protocol idle
WHILE protocol_status/=c_i2c_cmdr_state_idle LOOP
-- read commander protocol status register
proc_mem_mm_bus_rd(c_protocol_status_wi, clk, commander_miso, commander_mosi);
proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, clk);
protocol_status <= TO_UINT(commander_miso.rddata);
proc_common_wait_some_cycles(clk, 1);
END LOOP;
-- Wait some time between the protocols
proc_common_wait_some_cycles(clk, 100);
END LOOP;
----------------------------------------------------------------------------
-- The end
----------------------------------------------------------------------------
proc_common_wait_some_cycles(clk, 100);
tb_end <= '1';
WAIT;
END PROCESS;
-- I2C commander
u_commander : ENTITY work.i2c_commander
GENERIC MAP (
g_sim => c_sim,
g_i2c_cmdr => c_protocol_commander,
g_i2c_mm => c_mem_i2c,
g_i2c_phy => c_phy_i2c,
g_protocol_ram_init_file => c_protocol_ram_init_file,
g_use_result_ram => c_use_result_ram
)
PORT MAP (
rst => rst,
clk => clk,
sync => sync,
---------------------------------------------------------------------------
-- Memory Mapped slave interfaces
---------------------------------------------------------------------------
commander_mosi => commander_mosi,
commander_miso => commander_miso,
-- If the default protocol list in u_protocol_ram is fine, then the protocol slave port can be left no connected
protocol_mosi => protocol_mosi,
protocol_miso => protocol_miso,
-- Typically the commander status registers are sufficient, so then the results slave port can be left no connected
result_mosi => result_mosi,
result_miso => result_miso,
---------------------------------------------------------------------------
-- I2C interface
---------------------------------------------------------------------------
scl => scl,
sda => sda
);
-- I2C slaves
u_pmbus_core : ENTITY work.dev_pmbus
GENERIC MAP (
g_address => c_pmbus_core_address
)
PORT MAP (
scl => scl,
sda => sda,
vin => 90,
vout => 9,
iout => 10,
vcap => 0,
temp => 34
);
u_pmbus_vccram : ENTITY work.dev_pmbus
GENERIC MAP (
g_address => c_pmbus_vccram_address
)
PORT MAP (
scl => scl,
sda => sda,
vin => 91,
vout => 12,
iout => 11,
vcap => 75,
temp => 35
);
u_pmbus_tcvr0 : ENTITY work.dev_pmbus
GENERIC MAP (
g_address => c_pmbus_tcvr0_address
)
PORT MAP (
scl => scl,
sda => sda,
vin => 92,
vout => 18,
iout => 12,
vcap => 0,
temp => 36
);
u_pmbus_tcvr1 : ENTITY work.dev_pmbus
GENERIC MAP (
g_address => c_pmbus_tcvr1_address
)
PORT MAP (
scl => scl,
sda => sda,
vin => 93,
vout => 18,
iout => 13,
vcap => 0,
temp => 37
);
u_pmbus_ctrl : ENTITY work.dev_pmbus
GENERIC MAP (
g_address => c_pmbus_ctrl_address
)
PORT MAP (
scl => scl,
sda => sda,
vin => 94,
vout => 33,
iout => 14,
vcap => 0,
temp => 38
);
u_pmbus_fpgaio : ENTITY work.dev_pmbus
GENERIC MAP (
g_address => c_pmbus_fpgaio_address
)
PORT MAP (
scl => scl,
sda => sda,
vin => 90,
vout => 33,
iout => 15,
vcap => 0,
temp => 39
);
END tb;
-------------------------------------------------------------------------------
--
-- Copyright (C) 2012
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-------------------------------------------------------------------------------
-- Purpose: Verify the i2c_commander and create a u_protocol_ram init file
--
-- Description:
-- The protocols for the I2C slaves on UNB are stored in the dev_unb_pkg.
-- The protocols for the I2C slaves on ADU are stored in the dev_adu_pkg.
-- This tb can model both via g_board = "unb" or "adu". The protocols for the
-- board are concatenated into c_protocol_ram_init.
-- The p_mm_stimuli writes the c_protocol_ram_init bytes to u_protocol_ram
-- and in parallel they get written to a file by u_protocol_ram_init_file:
--
-- data/adu_protocol_ram_init.txt
-- or
-- data/unb_protocol_ram_init.txt
--
-- See data/how_to_create_memory_init_hex_file.txt for how to
-- create a memory initialization hex file from this.
--
-- The p_mm_stimuli continues with executing all protocol lists and checking
-- the expected results and ASSERTs ERROR if an access went not OK and in
-- case of read data if the read data value was not OK.
--
-- Remark:
-- . Use c_protocol_ram_init_file="UNUSED" to initialize the u_protocol_ram
-- with the c_protocol_ram_init sequence,
-- else use the actual protocol_ram_init.hex file and verify that it contains
-- the same as the c_protocol_ram_init sequence.
--
-- Usage:
-- > do wave_i2c_commander.do
-- > run -all
-- In the Wave Window view the signal u_commander/protocol_index to observe
-- the progress
--
-- Uniboard2 version derived from tb_i2c_commander November 2015
-- this version tests the SENS bus
ENTITY tb_i2c_commander_unb2_sens IS
GENERIC (
g_board : STRING := "unb2" -- only works with UniBoard2
);
END tb_i2c_commander_unb2_sens;
LIBRARY IEEE, common_lib, tst_lib;
USE IEEE.std_logic_1164.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE common_lib.tb_common_pkg.ALL;
USE common_lib.tb_common_mem_pkg.ALL;
USE work.i2c_smbus_pkg.ALL;
USE work.i2c_dev_max1617_pkg.ALL;
USE work.i2c_dev_unb2_pkg.ALL;
USE work.i2c_pkg.ALL;
USE work.i2c_commander_pkg.ALL;
USE work.i2c_commander_unb2_sens_pkg.ALL;
USE work.i2c_commander_unb2_pmbus_pkg.ALL; -- in case we can add the PMBUS later
ARCHITECTURE tb OF tb_i2c_commander_unb2_sens IS
--CONSTANT c_protocol_ram_init_file : STRING := "data/unb2_sens_protocol_ram_init.hex";
--CONSTANT c_protocol_ram_init_file : STRING := "data/unb2_pmbus_protocol_ram_init.hex";
CONSTANT c_protocol_ram_init_file : STRING := "UNUSED"; -- start with this, then make a hex file from the txt file?
CONSTANT c_use_result_ram : BOOLEAN := TRUE;
CONSTANT c_sim : BOOLEAN := TRUE; --FALSE
CONSTANT c_clk_freq_in_MHz : NATURAL := 100; -- 100 MHz
CONSTANT c_clk_period : TIME := (10**3/c_clk_freq_in_MHz) * 1 ns;
CONSTANT c_rst_period : TIME := 4 * c_clk_period;
CONSTANT c_phy_i2c : t_c_i2c_phy := func_i2c_sel_a_b(c_sim, c_i2c_phy_sim, func_i2c_calculate_phy(c_clk_freq_in_MHz));
--CONSTANT c_sens_temp_address : STD_LOGIC_VECTOR := TO_UVEC(MAX1617_ADR_LOW_LOW, 7); -- use other slave address to force I2C errors
CONSTANT c_sens_temp_address : STD_LOGIC_VECTOR := TO_UVEC(I2C_UNB2_SENS_TEMP_MAX1617_ADR, 7);
CONSTANT c_sens_dcdc_address : STD_LOGIC_VECTOR := TO_UVEC(I2C_UNB2_SENS_DCDC_BMR456_ADR, 7);
CONSTANT c_sens_pim_address : STD_LOGIC_VECTOR := TO_UVEC(I2C_UNB2_SENS_PIM_PIM4328PD_ADR, 7);
CONSTANT c_sens_1v2_address : STD_LOGIC_VECTOR := TO_UVEC(I2C_UNB2_SENS_1V2_BMR461_ADR, 7);
CONSTANT c_sens_3v3_address : STD_LOGIC_VECTOR := TO_UVEC(I2C_UNB2_SENS_3V3_BMR461_ADR, 7);
CONSTANT c_sens_clk_address : STD_LOGIC_VECTOR := TO_UVEC(I2C_UNB2_SENS_CLK_BMR461_ADR, 7);
CONSTANT c_sens_qsfp0_address : STD_LOGIC_VECTOR := TO_UVEC(I2C_UNB2_SENS_QSFP0_BMR464_ADR, 7);
CONSTANT c_sens_qsfp1_address : STD_LOGIC_VECTOR := TO_UVEC(I2C_UNB2_SENS_QSFP1_BMR464_ADR, 7);
CONSTANT c_sens_eeprom_address : STD_LOGIC_VECTOR := TO_UVEC(I2C_UNB2_SENS_EEPROM_CAT24C02_ADR, 7);
CONSTANT c_sens_temp2_address : STD_LOGIC_VECTOR := TO_UVEC(I2C_UNB2_SENS_TEMP_TMP451_ADR, 7);
CONSTANT c_max1618_temp : INTEGER := 60;
-- Select the expected read data arrays for the result data (the read data values are tb dependent, so therefore they are not obtained from a package)
TYPE t_i2c_unb2_natural_arr IS ARRAY (INTEGER RANGE 0 TO 31) OF NATURAL; -- needto test some long protocol lists
TYPE t_i2c_unb2_natural_mat IS ARRAY (INTEGER RANGE <>) OF t_i2c_unb2_natural_arr;
CONSTANT c_max1618_expected_data_read_temp_arr : t_i2c_unb2_natural_arr := (c_max1618_temp, others => 254);
CONSTANT c_default_expected_data_arr : t_i2c_unb2_natural_arr := ( others => 254);
CONSTANT c_expected_data_mat : t_i2c_unb2_natural_mat(0 TO c_i2c_unb2_nof_protocol_lists-1) := (c_max1618_expected_data_read_temp_arr,
c_default_expected_data_arr,
c_default_expected_data_arr,
c_default_expected_data_arr);
-- RAM sizes
CONSTANT c_mem_i2c : t_c_i2c_mm := c_i2c_cmdr_unb2_sens_i2c_mm;
-- Commander parameters
CONSTANT c_protocol_ram_init : t_nat_natural_arr := c_i2c_cmdr_unb2_sens_protocol_ram_init;
CONSTANT c_nof_result_data_arr : t_nat_natural_arr := c_i2c_cmdr_unb2_sens_nof_result_data_arr;
CONSTANT c_protocol_commander : t_c_i2c_cmdr_commander := c_i2c_cmdr_unb2_sens_protocol_commander;
-- Commander MM register word indexes
CONSTANT c_protocol_status_wi : NATURAL := 3*c_protocol_commander.nof_protocols;
CONSTANT c_result_error_cnt_wi : NATURAL := 3*c_protocol_commander.nof_protocols + 1;
CONSTANT c_result_data_wi : NATURAL := 3*c_protocol_commander.nof_protocols + 2;
-- Test bench PHY
SIGNAL tb_end : STD_LOGIC := '0';
SIGNAL clk : STD_LOGIC := '0';
SIGNAL rst : STD_LOGIC := '1';
SIGNAL sync : STD_LOGIC := '1';
SIGNAL scl_stretch : STD_LOGIC := 'Z';
SIGNAL scl : STD_LOGIC;
SIGNAL sda : STD_LOGIC;
-- File interface
SIGNAL file_miso : t_mem_miso;
SIGNAL file_mosi : t_mem_mosi;
-- MM registers interface
SIGNAL commander_miso : t_mem_miso;
SIGNAL commander_mosi : t_mem_mosi;
SIGNAL protocol_miso : t_mem_miso;
SIGNAL protocol_mosi : t_mem_mosi;
SIGNAL result_miso : t_mem_miso;
SIGNAL result_mosi : t_mem_mosi;
-- Commander results
SIGNAL protocol_data : NATURAL;
SIGNAL protocol_status : NATURAL;
SIGNAL result_data : NATURAL;
SIGNAL result_error_cnt : NATURAL;
BEGIN
-- run -all
rst <= '0' AFTER 4*c_clk_period;
clk <= (NOT clk) OR tb_end AFTER c_clk_period/2;
-- I2C bus
scl <= 'H'; -- model I2C pull up
sda <= 'H'; -- model I2C pull up, use '0' and '1' to verify SDA forced low or high error
scl <= scl_stretch;
sens_clk_stretch : PROCESS (scl)
BEGIN
IF falling_edge(scl) THEN
scl_stretch <= '0', 'Z' AFTER 50 ns; -- < 10 ns to effectively disable stretching, >= 50 ns to enable it
END IF;
END PROCESS;
u_protocol_ram_init_file : ENTITY tst_lib.tst_output
GENERIC MAP (
g_file_name => "data/" & g_board & "_protocol_ram_init.txt",
g_nof_data => 1,
g_data_width => c_byte_w,
g_data_type => "UNSIGNED"
)
PORT MAP (
clk => clk,
rst => rst,
in_dat => file_mosi.wrdata(c_byte_w-1 DOWNTO 0),
in_val => file_mosi.wr
);
p_mm_stimuli : PROCESS
BEGIN
-- Wait for reset release
commander_mosi <= c_mem_mosi_rst;
file_mosi <= c_mem_mosi_rst;
protocol_mosi <= c_mem_mosi_rst;
result_mosi <= c_mem_mosi_rst;
proc_common_wait_until_low(clk, rst);
proc_common_wait_some_cycles(clk, 10);
----------------------------------------------------------------------------
-- Initialize the u_protocol_ram or verify its default contents
----------------------------------------------------------------------------
IF c_protocol_ram_init_file="UNUSED" THEN
-- Write
FOR I IN 0 TO c_protocol_ram_init'LENGTH-1 LOOP
proc_mem_mm_bus_wr(I, c_protocol_ram_init(I), clk, protocol_miso, protocol_mosi); -- fill u_protocol_ram
END LOOP;
FOR I IN c_protocol_ram_init'LENGTH TO c_mem_i2c.protocol_nof_dat-1 LOOP
proc_mem_mm_bus_wr(I, SMBUS_C_END, clk, protocol_miso, protocol_mosi); -- fill remainder of u_protocol_ram with default
END LOOP;
ELSE
-- Read and verify
FOR I IN 0 TO c_protocol_ram_init'LENGTH-1 LOOP
proc_mem_mm_bus_rd(I, clk, protocol_miso, protocol_mosi);
proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, clk);
protocol_data <= TO_UINT(protocol_miso.rddata(c_byte_w-1 DOWNTO 0));
proc_common_wait_some_cycles(clk, 1);
ASSERT c_protocol_ram_init(I)=protocol_data
REPORT "Unexpected protocol data" SEVERITY ERROR;
END LOOP;
FOR I IN c_protocol_ram_init'LENGTH TO c_mem_i2c.protocol_nof_dat-1 LOOP
proc_mem_mm_bus_rd(I, clk, protocol_miso, protocol_mosi);
proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, clk);
protocol_data <= TO_UINT(protocol_miso.rddata(c_byte_w-1 DOWNTO 0));
proc_common_wait_some_cycles(clk, 1);
ASSERT SMBUS_C_END=protocol_data
REPORT "Unexpected protocol end data" SEVERITY ERROR;
END LOOP;
END IF;
proc_common_wait_some_cycles(clk, 10);
----------------------------------------------------------------------------
-- Create the u_protocol_ram_init_file
----------------------------------------------------------------------------
FOR I IN 0 TO c_protocol_ram_init'LENGTH-1 LOOP
proc_mem_mm_bus_wr(I, c_protocol_ram_init(I), clk, file_miso, file_mosi); -- fill u_protocol_ram_init_file
END LOOP;
FOR I IN c_protocol_ram_init'LENGTH TO c_mem_i2c.protocol_nof_dat-1 LOOP
proc_mem_mm_bus_wr(I, SMBUS_C_END, clk, file_miso, file_mosi); -- fill remainder of u_protocol_ram_init_file with default
END LOOP;
proc_common_wait_some_cycles(clk, 10);
----------------------------------------------------------------------------
-- Try and verify all commander protocols
----------------------------------------------------------------------------
FOR P IN 0 TO c_protocol_commander.nof_protocols-1 LOOP
-- Issue protocol list P
proc_mem_mm_bus_wr(P, 1, clk, commander_miso, commander_mosi);
-- Wait for protocol done
WHILE protocol_status/=c_i2c_cmdr_state_done LOOP
-- read commander protocol status register
proc_mem_mm_bus_rd(c_protocol_status_wi, clk, commander_miso, commander_mosi);
proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, clk);
protocol_status <= TO_UINT(commander_miso.rddata);
proc_common_wait_some_cycles(clk, 1);
END LOOP;
-- Read commander result error count
proc_mem_mm_bus_rd(c_result_error_cnt_wi, clk, commander_miso, commander_mosi);
proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, clk);
result_error_cnt <= TO_UINT(commander_miso.rddata);
proc_common_wait_some_cycles(clk, 1);
ASSERT result_error_cnt=0
REPORT "The result error count is not 0" SEVERITY ERROR;
-- Read commander result data
FOR I IN 0 TO c_nof_result_data_arr(P)-1 LOOP
proc_mem_mm_bus_rd(c_result_data_wi+I, clk, commander_miso, commander_mosi);
proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, clk);
result_data <= TO_UINT(commander_miso.rddata);
proc_common_wait_some_cycles(clk, 1);
ASSERT c_expected_data_mat(P)(I)=result_data
REPORT "Unexpected result data" SEVERITY WARNING;
END LOOP;
-- Wait for protocol idle
WHILE protocol_status/=c_i2c_cmdr_state_idle LOOP
-- read commander protocol status register
proc_mem_mm_bus_rd(c_protocol_status_wi, clk, commander_miso, commander_mosi);
proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, clk);
protocol_status <= TO_UINT(commander_miso.rddata);
proc_common_wait_some_cycles(clk, 1);
END LOOP;
-- Wait some time between the protocols
proc_common_wait_some_cycles(clk, 100);
END LOOP;
----------------------------------------------------------------------------
-- The end
----------------------------------------------------------------------------
proc_common_wait_some_cycles(clk, 100);
tb_end <= '1';
WAIT;
END PROCESS;
-- I2C commander
u_commander : ENTITY work.i2c_commander
GENERIC MAP (
g_sim => c_sim,
g_i2c_cmdr => c_protocol_commander,
g_i2c_mm => c_mem_i2c,
g_i2c_phy => c_phy_i2c,
g_protocol_ram_init_file => c_protocol_ram_init_file,
g_use_result_ram => c_use_result_ram
)
PORT MAP (
rst => rst,
clk => clk,
sync => sync,
---------------------------------------------------------------------------
-- Memory Mapped slave interfaces
---------------------------------------------------------------------------
commander_mosi => commander_mosi,
commander_miso => commander_miso,
-- If the default protocol list in u_protocol_ram is fine, then the protocol slave port can be left no connected
protocol_mosi => protocol_mosi,
protocol_miso => protocol_miso,
-- Typically the commander status registers are sufficient, so then the results slave port can be left no connected
result_mosi => result_mosi,
result_miso => result_miso,
---------------------------------------------------------------------------
-- I2C interface
---------------------------------------------------------------------------
scl => scl,
sda => sda
);
-- I2C slaves
u_sens_dcdc : ENTITY work.dev_pmbus
GENERIC MAP (
g_address => c_sens_dcdc_address
)
PORT MAP (
scl => scl,
sda => sda,
vin => 48,
vout => 9,
iout => 5,
vcap => 0,
temp => 34
);
u_sens_pim : ENTITY work.dev_pmbus
GENERIC MAP (
g_address => c_sens_pim_address
)
PORT MAP (
scl => scl,
sda => sda,
vin => 48,
vout => 0,
iout => 12,
vcap => 75,
temp => 35
);
u_sens_1v2 : ENTITY work.dev_pmbus
GENERIC MAP (
g_address => c_sens_1v2_address
)
PORT MAP (
scl => scl,
sda => sda,
vin => 90,
vout => 12,
iout => 20,
vcap => 0,
temp => 36
);
u_sens_3v3 : ENTITY work.dev_pmbus
GENERIC MAP (
g_address => c_sens_3v3_address
)
PORT MAP (
scl => scl,
sda => sda,
vin => 90,
vout => 33,
iout => 20,
vcap => 0,
temp => 37
);
u_sens_clk : ENTITY work.dev_pmbus
GENERIC MAP (
g_address => c_sens_clk_address
)
PORT MAP (
scl => scl,
sda => sda,
vin => 90,
vout => 25,
iout => 20,
vcap => 0,
temp => 38
);
u_sens_qsfp0 : ENTITY work.dev_pmbus
GENERIC MAP (
g_address => c_sens_qsfp0_address
)
PORT MAP (
scl => scl,
sda => sda,
vin => 90,
vout => 32,
iout => 11,
vcap => 0,
temp => 39
);
u_sens_qsfp1 : ENTITY work.dev_pmbus
GENERIC MAP (
g_address => c_sens_qsfp1_address
)
PORT MAP (
scl => scl,
sda => sda,
vin => 90,
vout => 34,
iout => 10,
vcap => 0,
temp => 40
);
u_sens_temp : ENTITY work.dev_max1618 -- both on "unb" and on "adu"
GENERIC MAP (
g_address => c_sens_temp_address
)
PORT MAP (
scl => scl,
sda => sda,
temp => c_max1618_temp
);
END tb;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment