?? spi_master_tb.vhd
字號:
-- VHDL Test Bench Created from source file spi_master.vhd -- 9/18/00 5:07:59 PM
--
-- spi_master_tb.vhd
--
-- Created: 10/12/00 ALS
-- This file, created from the WebPACK generated template, models the uC
-- and a simple slave to test the SPI Master. It also generates the system clock.
--
-- Revised: 10/13/00 ALS
-- Revised: 10/22/00 ALS
-- Revised: 10/25/00 ALS
-- Revised: 10/26/00 ALS
-- Revised: 10/27/00 ALS
-- Revised: 12/12/02 JRH
--
-- **************************************************************************************
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY testbench IS
END testbench;
ARCHITECTURE behavior OF testbench IS
-- ************************************* Constant Declarations **************************
constant RESET_ACTIVE : STD_LOGIC := '0';
constant CLK_PERIOD : time := 50 nS; -- system clock period
-- 8051 Timing constants
-- The constant TCLCL should be set to match the actual clock period of the 8051
-- The equations for the other constants to be modified to match the data sheet of the
-- 8051 uC used in the design
constant TCLCL : time := 62500 pS; -- 8051 clock period - 16MHz
constant TLHLL : time := 2*TCLCL - 40 nS; -- ALE negated pulse width
constant TAVLL : time := TCLCL - 50 nS; -- Address valid to ALE low
constant TLLAX : time := TCLCL - 35 nS; -- Address low after ALE low
constant TQVWX : time := TCLCL - 60 nS; -- Data valid to WR_N transition
constant TWLWH : time := 6*TCLCL - 100 nS; -- WR_N pulse width
constant TWHQX : time := TCLCL - 50 nS; -- Data hold after WR_N negation
constant TWHLH : time := TCLCL - 40 nS; -- WR_N or RD_N negation to ALE_N negation
constant TRLAZ : time := 0 nS; -- RD_N assertion to address float
constant TRLDV : time := 5*TCLCL - 165 nS; -- RD_N assertion to valid data in
constant TRLRH : time := 6*TCLCL - 100 nS; -- RD_N pulse width
constant TLLPL : time := TCLCL - 40 nS; -- ALE_N assertion to PSEN_N assertion
constant TPLAZ : time := 10 nS; -- PSEN_N assertion to address float
constant TPLIV : time := 3*TCLCL - 115 nS; -- PSEN_N assertion to instruction valid
constant TPLPH : time := 3*TCLCL - 45 nS; -- PSEN_N pulse width
-- the constant below is used to assert SS_IN_N. If set to 0, SS_IN_N will never assert.
-- if non-zero, SS_IN_N will assert this time period after beginning of simulation, stay
-- asserted for this time period, and then negate.
-- Note that setting this constant and running a test of SS_IN_N will probably cause the
-- data read in from the SPIRR not to match the expected value, thus ERROR may assert for
-- a data period
constant SS_IN_ASSERT_TIME : time := 0 uS;
-- register addresses
constant BASE_ADDR : STD_LOGIC_VECTOR(7 downto 0) := "00000000"; -- Base Address (addr_bus[15:8])
constant SPISR_ADDR : STD_LOGIC_VECTOR(7 downto 0) := "10000000"; -- Status Register (BASE + 80h)
constant SPICR_ADDR : STD_LOGIC_VECTOR(7 downto 0) := "10000100"; -- Control Register (BASE + 84h)
constant SPISSR_ADDR : STD_LOGIC_VECTOR(7 downto 0) := "10001000"; -- Slave Select Register (BASE + 88h)
constant SPITR_ADDR : STD_LOGIC_VECTOR(7 downto 0) := "10001010"; -- Transmit Data Register (BASE + 8Ah)
constant SPIRR_ADDR : STD_LOGIC_VECTOR(7 downto 0) := "10001110"; -- Receive Data Register (BASE + 8Eh)
-- data words
constant ALL_ONES : std_logic_vector(7 downto 0) := "11111111";
constant ALL_ZEROS : std_logic_vector(7 downto 0) := "00000000";
constant DE : std_logic_vector(7 downto 0) := "11011110";
constant AD : std_logic_vector(7 downto 0) := "10101101";
constant BE : std_logic_vector(7 downto 0) := "10111110";
constant EF : std_logic_vector(7 downto 0) := "11101111";
constant FA : std_logic_vector(7 downto 0) := "11111010";
constant CE : std_logic_vector(7 downto 0) := "11001110";
-- bit locations in status register
constant SPIERR_BIT : integer := 6; -- spi err is bit 6 in SPISR
constant BUS_BUSY_BIT : integer := 5; -- bus busy is bit 5 in SPISR
constant XMIT_EMPTY_BIT : integer := 3; -- xmit empty is bit 3 in SPISR
constant RCV_FULL_BIT : integer := 2; -- receive full is bit 2 in SPISR
-- Slave select register settings
constant SEL_SLAVE_0 : std_logic_vector(7 downto 0) := "00000001";
constant SEL_SLAVE_1 : std_logic_vector(7 downto 0) := "00000010";
constant SEL_SLAVE_2 : std_logic_vector(7 downto 0) := "00000100";
constant SEL_SLAVE_3 : std_logic_vector(7 downto 0) := "00001000";
constant SEL_SLAVE_4 : std_logic_vector(7 downto 0) := "00010000";
constant SEL_SLAVE_5 : std_logic_vector(7 downto 0) := "00100000";
constant SEL_SLAVE_6 : std_logic_vector(7 downto 0) := "01000000";
constant SEL_SLAVE_7 : std_logic_vector(7 downto 0) := "10000000";
-- test data
type TEST_DATA is array (0 to 3) of std_logic_vector (7 downto 0);
constant TST_DATA_OUT : TEST_DATA := (
(DE), -- write first word to be transmitted
(AD), -- data word to be transmited
(BE), -- data word to be transmitted
(EF) -- last word to be transmitted
);
--*************************************** Component Declaration *****************************
-- SPI Master logic
COMPONENT spi_master
PORT(
addr : in std_logic_vector(7 downto 0);
ale_n : in std_logic;
clk : in std_logic;
miso : in std_logic;
psen_n : in std_logic;
rd_n : in std_logic;
reset : in std_logic;
ss_in_n : in std_logic;
wr_n : in std_logic;
addr_data : inout std_logic_vector(7 downto 0);
int_n : inout std_logic;
rcv_full : inout std_logic;
sck : inout std_logic;
xmit_empty : inout std_logic;
mosi : out std_logic;
ss_n : out std_logic_vector(7 downto 0)
);
END COMPONENT;
-- ************************************** Signal Declarations *******************************
-- uC bus signals
signal addr : std_logic_vector(7 downto 0);
signal addr_data : std_logic_vector(7 downto 0);
signal ale_n : std_logic;
signal psen_n : std_logic;
signal rd_n : std_logic;
signal wr_n : std_logic;
signal int_n : std_logic;
signal xmit_empty : std_logic;
signal rcv_full : std_logic;
-- SPI bus signals
signal miso : std_logic;
signal mosi : std_logic;
signal sck : std_logic;
signal ss_in_n : std_logic;
signal ss_n : std_logic_vector(7 downto 0);
-- reset and clock
signal reset : std_logic;
signal clk : std_logic;
-- testbench signals
signal ad_out,data_in : std_logic_vector(7 downto 0);
signal data_in_ce : std_logic; -- clock enable for input data register
signal write : std_logic; -- indicates a write cycle
signal assert_psen : std_logic; -- indicates a program store cycle
signal go, uc_done : std_logic; -- handshake signals to state machine
signal ad_oe : std_logic; -- address/data bus output enable
signal uc_addr : std_logic_vector(15 downto 0);-- addr to be output by uC
signal uc_data : std_logic_vector(7 downto 0); -- data to be output by uC
signal error : std_logic; -- indicates that data received <> data transmitted
signal exit_loop : std_logic; -- indicates that SPIERR was asserted
-- signals used to create control register data word
signal spien, inten : std_logic; -- spien and inten settings for the test
signal clkdiv : std_logic_vector(1 downto 0); -- CLKDIV setting for test
signal cpha, cpol : std_logic; -- cpha and cpol settings for test
signal rcv_cpol : std_logic; -- rcv_cpol setting for test
-- signals needed for slave
signal slave_cpha, slave_cpol : std_logic; -- cpha and cpol settings for slave
signal slave_cnt_int : unsigned (2 downto 0); -- internal count of received bits
signal slave_cnt : std_logic_vector(2 downto 0); -- counter output
signal slave_outcnt_int : unsigned (2 downto 0); -- internal count of transmitted bits
signal slave_outcnt : std_logic_vector(2 downto 0); -- counter output
signal slave_data : std_logic_vector(7 downto 0); -- shift register data
signal slave_rcvdata : std_logic_vector(7 downto 0); -- parallel slave rcv register
signal miso_reg : std_logic; -- registered version of MISO
signal miso_reg_ssn : std_logic; -- registered version of MISO using SS_N assertion as clock
signal slave_clkedge : std_logic; -- =1 if rising edge or =0 for falling edge
signal ssn_ck : std_logic; -- clock signal when any slave select asserts
-- used when CPHA=0 to clock data out on SS_N assertion
BEGIN
-- ************************************ UUT Instantiation ********************************
uut: spi_master PORT MAP(
addr => addr,
addr_data => addr_data,
ale_n => ale_n,
clk => clk,
int_n => int_n,
miso => miso,
mosi => mosi,
psen_n => psen_n,
rcv_full => rcv_full,
rd_n => rd_n,
reset => reset,
sck => sck,
ss_in_n => ss_in_n,
ss_n => ss_n,
wr_n => wr_n,
xmit_empty => xmit_empty
);
-- ************************************* Test Bench Processes and Code **************************
-- Define the bi-directional data bus
-- use pulldowns when tri-stated
addr_data <= ad_out when ad_oe = '1'
else (others => 'L');
-- ************************************ Clock Process *************************************
-- Process: CREATE_CLK
-- Function: Create 20Mhz clock
CREATE_CLK: process
begin
clk <= '0';
wait for CLK_PERIOD/2;
clk <= '1';
wait for CLK_PERIOD/2;
end process;
-- *********************************** Main Control Process *********************************
-- define the main controlling process that triggers the state machines
MAIN : process
variable i,j,k : integer := 0; -- loop counters
begin
-- initialize control signals
uc_addr <= (others => '0');
uc_data <= (others => '0');
go <= '0';
write <= '0';
assert_psen <= '0';
error <= '0';
spien <= '0';
inten <= '0';
cpha <= '0';
cpol <= '0';
rcv_cpol <= '0';
clkdiv <= (others => '0');
slave_cpha <= '0';
slave_cpol <= '0';
exit_loop <= '0';
-- assert RESET for two clocks
reset <= RESET_ACTIVE;
wait for 200 ns;
wait until clk'event and clk = '1';
wait until clk'event and clk = '1';
reset <= not(RESET_ACTIVE);
-- run a uC bus cycle with PSEN_N asserted to insure that these
-- bus cycles are ignored
assert_psen <= '1';
write <= '0';
uc_addr <= BASE_ADDR & SPICR_ADDR;
uc_data <= FA;
go <= '1';
wait until clk'event and clk = '1';
wait until clk'event and clk = '1';
go <= '0';
wait until uc_done = '1';
assert_psen <= '0';
-- run a uC bus cycle with the wrong address to insure that these
-- bus cycles are ignored
write <= '1';
uc_addr <= BASE_ADDR & DE;
uc_data <= FA;
go <= '1';
wait until clk'event and clk = '1';
wait until clk'event and clk = '1';
go <= '0';
wait until uc_done = '1';
-- start the loops of different SPI transfers
-- loop through all combinations of CLKDIV. For each CLKDIV, loop
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -