📄 spi_master_tb.vhd
字号:
-- through all combinations of CPHA and CPOL
for i in 0 to 3 loop
-- setup CLKDIV
-- variable I will loop through CLKDIV
-- set CLKDIV according to value of I
case i is
when 0 =>
clkdiv <= "00";
when 1 =>
clkdiv <= "01";
when 2 =>
clkdiv <= "10";
when 3 =>
clkdiv <= "11";
when others =>
clkdiv <= "00";
end case;
-- enable spi interface logic and interrupts
spien <= '1';
inten <= '1';
-- variable J will loop through CPHA and CPOL
-- set RCV_CPOL, SLAVE_CPHA, SLAVE_CPOL based on CPHA and CPOL
for j in 0 to 3 loop
case j is
when 0 =>
cpha <= '0';
cpol <= '0';
rcv_cpol <= '1'; -- =1 when cpha = cpol
slave_cpha <= '0'; -- must match cpha
slave_cpol <= '0'; -- must match cpol
when 1 =>
cpha <= '0';
cpol <= '1';
rcv_cpol <= '0'; -- =0 when cpha <> cpol
slave_cpha <= '0'; -- must match cpha
slave_cpol <= '1'; -- must match cpol
when 2 =>
cpha <= '1';
cpol <= '0';
rcv_cpol <= '0'; -- =0 when cpha <> cpol
slave_cpha <= '1'; -- must match cpha
slave_cpol <= '0'; -- must match cpol
when 3 =>
cpha <= '1';
cpol <= '1';
rcv_cpol <= '1'; -- =1 when cpha = cpol
slave_cpha <= '1'; -- must match cpha
slave_cpol <= '1'; -- must match cpol
when others =>
cpha <= '0';
cpol <= '0';
rcv_cpol <= '1'; -- =1 when cpha = cpol
slave_cpha <= '0'; -- must match cpha
slave_cpol <= '0'; -- must match cpol
end case;
-- wait for a clock signal to allow signal assignments to
-- take effect
wait until clk'event and clk = '1';
-- Now need to call the state machine to write registers
-- to set up the SPI transaction, then need to generate the START signal
-- Variable K will loop through the register writes to set up the
-- control registers, slave select registers, first data word,
-- and assertion of the START signal
write <= '1';
for k in 0 to 3 loop
-- first setup data and address
case k is
when 0 =>
-- write to control register
uc_addr <= BASE_ADDR & SPICR_ADDR;
-- first set SPIEN, INTEN, CLKDIV, CPHA, CPOL,
-- and RCV_CPOL without setting start
uc_data <= spien & inten & '0' & clkdiv &
cpha & cpol & rcv_cpol;
when 1 =>
-- write to slave select register
uc_addr <= BASE_ADDR & SPISSR_ADDR;
-- set slave select based on test
-- first set slave select to all zeros
-- then set the bit indexed by test loops
uc_data <= (others => '0');
uc_data(4*(i mod 2) +j) <= '1';
when 2 =>
-- now write first data to be transmitted
uc_addr <= BASE_ADDR & SPITR_ADDR;
uc_data <= TST_DATA_OUT(0);
when 3 =>
-- now set start in the control register
uc_addr <= BASE_ADDR & SPICR_ADDR;
uc_data <= spien & inten & '1' & clkdiv &
cpha & cpol & rcv_cpol;
when others =>
uc_addr <= (others => '0');
uc_data <= (others => '0');
end case;
-- wait a clock signal for signal assignments to take affect
wait until clk'event and clk = '1';
-- now signal uC state machine to write to SPI interface
go <= '1';
wait until clk'event and clk = '1';
wait until clk'event and clk = '1';
go <= '0';
wait until uc_done = '1';
end loop;
-- wait for INT_N from the SPI interface to indicate that the XMIT register
-- is empty.
-- then write data to the transmit data register for transfer over SPI
-- and read data from the receive data register (if data is there)
for k in 0 to 3 loop
if int_n = '1' then
-- wait for interrupt
wait until int_n = '0';
end if;
-- interrupt has occurred, read status register
uc_addr <= BASE_ADDR & SPISR_ADDR;
write <= '0';
go <= '1';
wait until clk'event and clk ='1';
wait until clk'event and clk = '1';
go <= '0';
wait until uc_done = '1';
-- Determine cause of interrupt
-- if SPIERR is asserted, write a '0' to the bit to clear it
-- wait for this bit to clear (meaning that error went away)
-- then reset SPI logic
if data_in (SPIERR_BIT) = '1' then
while data_in(SPIERR_BIT) = '1' loop
-- SPIERR -
-- reset this bit and the interrupt by writing a '0' to
-- this bit in SPISR
uc_addr <= BASE_ADDR & SPISR_ADDR;
uc_data <= (others => '0');
write <= '1';
go <= '1';
wait until clk'event and clk = '1';
wait until clk'event and clk = '1';
go <= '0';
wait until uc_done = '1';
-- now read status register again to see if
-- SPIERR has gone away
uc_addr <= BASE_ADDR & SPISR_ADDR;
write <= '0';
go <= '1';
wait until clk'event and clk ='1';
wait until clk'event and clk = '1';
go <= '0';
wait until uc_done = '1';
end loop;
-- now reset logic by negating SPIEN in
-- control register
uc_addr <= BASE_ADDR & SPICR_ADDR;
uc_data <= '0' & inten & '1' & clkdiv &
cpha & cpol & rcv_cpol;
write <= '1';
go <= '1';
wait until clk'event and clk = '1';
wait until clk'event and clk = '1';
go <= '0';
wait until uc_done = '1';
-- set signal that will exit loop
exit_loop <= '1';
else
exit_loop <= '0';
if data_in(XMIT_EMPTY_BIT) = '1' then
-- xmit empty asserted
-- write new transmit data
-- unless last data has already been written
-- if last data has been written, write to control register
-- to negate start
if k = 3 then
-- all data words have been written to SPITR,
-- write to control register to negate start
uc_addr <= BASE_ADDR & SPICR_ADDR;
uc_data <= spien & inten & '0' & clkdiv &
cpha & cpol & rcv_cpol;
else
-- write next data word to be transmitted
-- to SPITR
uc_addr <= BASE_ADDR & SPITR_ADDR;
uc_data <= TST_DATA_OUT(k+1);
end if;
write <= '1';
go <= '1';
wait until clk'event and clk = '1';
wait until clk'event and clk = '1';
go <= '0';
wait until uc_done = '1';
end if;
-- if receive full, then read receive register
-- Note, first time through loop, receive register will not
-- be full because XMIT empty starts the loop and will
-- occur at the beginning of the first transaction
if data_in(RCV_FULL_BIT) = '1' then
if i=0 and j=0 and k=0 then
-- first test
-- error because receive register should not
-- be full first time through the loop on first test
error <= '1';
else
-- read receive register data
uc_addr <= BASE_ADDR & SPIRR_ADDR;
write <= '0';
go <= '1';
wait until clk'event and clk = '1';
wait until clk'event and clk = '1';
go <= '0';
wait until uc_done = '1';
-- if i=0, j=0, k=1 first received data is data from slave
if i=0 and j=0 and k=1 then
if data_in = CE then
error <= '0';
else
error <= '1';
end if;
elsif k=0 then
-- for all tests after the first, the slave
-- sends out last data received
-- check for data of TST_DATA_OUT(2)
if data_in = TST_DATA_OUT(2) then
error <= '0';
else
error <= '1';
end if;
elsif k=1 then
if data_in = TST_DATA_OUT(3) then
error <= '0';
else
error <= '1';
end if;
else
if data_in = TST_DATA_OUT(k-2) then
error <= '0';
else
error <= '1';
end if;
end if;
end if;
end if;
end if;
end loop;
if exit_loop = '0' then
if int_n = '1' then
-- wait for interrupt indicating that rcv register is full
-- for last data word
wait until int_n = '0';
end if;
-- read the receive data register
write <= '0';
uc_addr <= BASE_ADDR & SPIRR_ADDR;
go <= '1';
wait until clk'event and clk = '1';
wait until clk'event and clk = '1';
go <= '0';
wait until uc_done = '1';
end if;
-- Before exitying the test, read the status register SPISR
-- to insure that the bus is not busy and that this test
-- has completed
write <= '0';
uc_addr <= BASE_ADDR & SPISR_ADDR;
go <= '1';
wait until clk'event and clk ='1';
wait until clk'event and clk ='1';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -