?? spi_master_tb.vhd
字號:
go <= '0';
wait until uc_done = '1';
-- continue reading status register until bus busy negates
while data_in(BUS_BUSY_BIT) = '1' loop
write <= '0';
uc_addr <= BASE_ADDR & SPISR_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 loop;
end loop; -- end loop for CPHA, CPOL
end loop; -- end loop for CLKDIV
wait;
end process;
-- *********************************** uC Process *********************************
-- Synthesize uProc bus protocol
UCBUS: process
begin
-- Set up defaults
uc_done <= '1';
ad_oe <= '0';
ale_n <= '1';
psen_n <= '1';
addr <= (others => '0');
ad_out <= (others => '0');
data_in_ce <= '0';
wr_n <= '1';
rd_n <= '1';
-- Wait for go to assert
wait until go'event and go = '1';
-- start bus cycle
uc_done <= '0';
-- wait part of ALE_N negation cycle (ALE_N pulse width - address setup time)
wait for TLHLL - TAVLL;
-- setup address on busses
addr <= uc_addr(15 downto 8);
ad_out <= uc_addr(7 downto 0);
ad_oe <= '1';
-- wait address setup time then assert ALE_N
wait for TAVLL;
ale_n <= '0';
-- determine if this is a program store cycle, write cycle, or read cycle
if assert_psen = '1' then
-- program store cycle
-- wait before asserting PSEN_N
wait for TLLPL;
psen_n <= '0';
-- wait address hold time then tri-state
wait for TPLAZ;
ad_oe <= '0'; -- tri-state ad bus
-- wait for instruction access time then capture data
-- by asserting clock enable for input data register
wait for TPLIV;
data_in_ce <= '1';
-- wait remainder of PSEN_N pulse width then negate PSEN_N and ALE_N
-- and negate clock enable for input data register
wait for TPLPH - TPLIV;
psen_n <= '1';
ale_n <= '1';
data_in_ce <= '0';
elsif write = '1' then
-- write cycle
-- wait address hold time
wait for TLLAX;
-- write cycle, put data on ad
ad_oe <= '1';
ad_out <= uc_data;
-- wait data setup time then assert WR_N
wait for TQVWX;
wr_n <= '0';
-- wait write pulse width then negate WR_N
wait for TWLWH;
wr_n <= '1';
-- wait data hold time after WR_N then remove data
wait for TWHQX;
ad_oe <= '0';
-- wait remaining ALE_N hold time after WR_N then negate ALE_N
wait for TWHLH - TWHQX;
ale_n <= '1';
else
-- read cycle
-- wait address hold time
wait for TLLAX;
ad_oe <= '0';
-- read cycle, wait address Z time before asserting RD_N
wait for TRLAZ;
rd_n <= '0';
-- wait for data to be valid, then capture it
-- by asserting clock enable for input data register
wait for TRLDV;
data_in_ce <= '1';
-- wait remainding time in read pulse then negate RD_N
-- by negating clock enable for input data register
wait for TRLRH - TRLDV;
rd_n <= '1';
data_in_ce <= '0';
-- wait ALE_N hold time then negate ALE_N;
wait for TWHLH;
ale_n <= '1';
end if;
-- signify end of bus cycle by asserting UC_DONE
uc_done <= '1';
-- process will now return to beginning to wait for GO
end process;
-- *********************************** Input Register Process *********************************
-- This process captures data from the ADDR_DATA bus during read and program store bus cycles
-- Data is clocked into the register when the clock enable is asserted from the uC bus cycle
-- process
INPUT_REGS: process(reset, clk)
begin
if reset = RESET_ACTIVE then
data_in <= (others => '0');
elsif clk'event and clk = '1' then
if data_in_ce = '1' then
data_in <= addr_data;
else
data_in <= data_in;
end if;
end if;
end process;
-- *********************************** SS_IN_N Process *********************************
-- This process will asynchronously assert SS_IN_N as determined by the constant SS_IN_ASSERT_TIME.
-- If this time is set to 0, then SS_IN_N will never be asserted. This allows the testbench to be
-- run without interference of this signal
SS_IN_PROC: process
begin
ss_in_n <= '1';
if SS_IN_ASSERT_TIME = 0 uS then
wait;
else
wait for SS_IN_ASSERT_TIME;
ss_in_n <= '0';
wait for SS_IN_ASSERT_TIME;
ss_in_n <= '1';
wait;
end if;
end process;
-- *********************************** SPI Slave Processes *********************************
-- This process will "mock-up" an SPI slave. A shift register will be pre-loaded with a constant.
-- MOSI will be shifted in and MISO will be shifted out. An additional register will be loaded
-- with the SPI shifted in data just for verification purposes.
-- For now, this process will use the edge of SCK specified by SLAVE_CPHA and SLAVE_CPOL
--
-- SLAVE_CPHA SLAVE_CPOL slave_clkedge (to input data, opposite edge used to output)
-- ---------- ---------- -------------
-- 0 0 1
-- 0 1 0
-- 1 0 0
-- 1 1 1
--
slave_clkedge <= '1' when SLAVE_CPHA = SLAVE_CPOL
else '0';
-- Define a 3-bit counter to count SCK edges and data into register so that parallel
-- register is loaded. Use same clock edge that is used to input data
SLAVE_IN_CNTR: process(sck, reset)
begin
-- Clear output register
if (reset = RESET_ACTIVE) then
slave_cnt_int <= (others => '0');
-- On SLAVE_CLKEDGE edge of clock count
elsif sck'event and sck = slave_clkedge then
if ss_n /= ALL_ONES then
slave_cnt_int <= slave_cnt_int + 1;
end if;
end if;
end process;
slave_cnt <= STD_LOGIC_VECTOR(slave_cnt_int);
-- Count bits going out to help control mux for MISO data
-- This count is on the same edge as data being output
SLAVE_OUT_CNTR: process(sck, reset)
begin
-- Clear output register
if (reset = RESET_ACTIVE) or ss_n = ALL_ONES then
slave_outcnt_int <= (others => '0');
-- On SLAVE_CLKEDGE edge of clock count
elsif sck'event and sck = not(slave_clkedge) then
slave_outcnt_int <= slave_outcnt_int + 1;
end if;
end process;
slave_outcnt <= STD_LOGIC_VECTOR(slave_outcnt_int);
-- Define an 8-bit shift register for shifting in MOSI and shifting out MISO
-- Preset register to CE
SLAVE_SHFTREG: process(sck, reset)
begin
if (reset = RESET_ACTIVE) then
slave_data <= CE;
-- On SLAVE_CLKEDGE edge of spi clock, shift in data
elsif sck'event and sck = slave_clkedge then
-- Shift the data if SS_N is asserted
if ss_n /= ALL_ONES then
slave_data <= slave_data(6 downto 0) & mosi;
end if;
end if;
end process;
-- MISO will be shifted out using opposite edge of clock
-- If CPHA=1 then first sck edge clocks out first data
MISO_REG_PROC: process(sck, reset)
begin
if reset = RESET_ACTIVE then
miso_reg <= '0';
elsif sck'event and sck = not(slave_clkedge) then
miso_reg <= slave_data(7);
end if;
end process;
-- If CPHA=0, falling edge of SS_N clocks out first data
-- NOTE: A gated clock is described here ONLY for test purposes
ssn_ck <= '1' when ss_n /= ALL_ONES
else '0';
MISO_REG_SSN_PROC: process(ssn_ck, reset)
begin
if reset = RESET_ACTIVE then
miso_reg_ssn <= '0';
elsif ssn_ck'event and ssn_ck = '1' then
miso_reg_ssn <= slave_data(7);
end if;
end process;
miso <= miso_reg_ssn when SLAVE_CPHA = '0' and slave_outcnt = "000"
else miso_reg;
-- Define an 8-bit parallel load register that holds data received from the SPI bus
SLAVE_RCVREG: process(clk, reset)
begin
if (reset = RESET_ACTIVE) then
slave_rcvdata <= (others => '0');
elsif clk'event and clk = '1' then
if slave_cnt = "000" then
slave_rcvdata <= slave_data;
else
slave_rcvdata <= slave_rcvdata;
end if;
end if;
end process;
END;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -