?? spi_control_sm.vhd
字號:
case spi_state is
--********************* IDLE State *****************
when IDLE =>
if start = '1' and xmit_empty = '0' then
next_spi_state <= ASSERT_SSN1;
end if;
--********************* ASSERT_SSN1 State *****************
when ASSERT_SSN1 =>
-- this state asserts SS_N and waits for first edge of SCK_INT
-- SS_N must be asserted ~1 SCK before SCK is output from chip
if sck_int_re = '1' then
next_spi_state <= ASSERT_SSN2;
end if;
--********************* ASSERT_SSN2 State *****************
when ASSERT_SSN2 =>
-- this state asserts SS_N and waits for next edge of SCK_INT
-- SS_N must be asserted ~1 SCK before SCK is output from chip
if sck_int_fe = '1' then
next_spi_state <= UNMASK_SCK;
end if;
--********************* UNMASK_SCK State *****************
when UNMASK_SCK =>
bit_cnt_rst <= not(RESET_ACTIVE); -- release bit counter from reset
bit_cnt_en <= '1'; -- enable bit counter
clk1_mask <= '1'; -- unmask sck_1
xmit_load <= '1'; -- load SPI shift register
if sck_int_re = '1' then
-- first rising edge of CPHA=1 clock with SS_N asserted
-- transition to XFER_BIT state and unmask CPHA=0 clk
next_spi_state <= XFER_BIT;
end if;
--********************* XFER_BIT State *****************
when XFER_BIT =>
clk0_mask <= '1'; -- unmask CPHA=0 clock
clk1_mask <= '1'; -- unmask CPHA=1 clock
bit_cnt_en <= '1'; -- enable bit counter
bit_cnt_rst <= not(RESET_ACTIVE); -- release bit counter from reset
xmit_shift <= '1'; -- enable shifting of SPI shift registers
if bit_cnt = EIGHT then
-- all 8 bits have transferred
next_spi_state <= ASSERT_DONE;
end if;
--********************* ASSERT_DONE State *****************
when ASSERT_DONE =>
-- this state asserts done to the uC so that new data
-- can be written into the transmit register or data
-- can be read from the receive register
done <= '1';
clk0_mask <= '1';
clk1_mask <= '1';
xmit_shift <= '1';
if sck_int_fe = '1' then
next_spi_state <= CHK_START;
end if;
--********************* CHK_START State *****************
when CHK_START =>
clk0_mask <= '1';
clk1_mask <= '1';
done <= '1';
bit_cnt_en <= '1';
bit_cnt_rst <= not(RESET_ACTIVE); -- release bit counter from reset
if cpha = '0' then
-- when CPHA = 0, have to negate slave select and then
-- re-assert it. Need to wait for last SCK pulse to complete
-- and mask SCK before negating SS_N.
if (sck_re = '1' and cpol = '1') or (sck_fe = '1' and cpol = '0') then
clk0_mask <= '0';
clk1_mask <= '0';
next_spi_state <= MASK_SCK;
end if;
elsif start = '1' and xmit_empty = '0' then
-- CPHA=1 and have more data to transfer, go back to
-- UNMASK_CK state
clk1_mask <= '1';
xmit_load <= '1'; -- load SPI shift register
next_spi_state <= UNMASK_SCK;
else
-- CPHA=1 and no more data to transfer
-- wait for last SCKs and then mask SCK
if (sck_re = '1' and cpol = '1') or (sck_fe = '1' and cpol = '0') then
clk0_mask <= '0';
clk1_mask <= '0';
next_spi_state <= MASK_SCK;
end if;
clk0_mask <= '0';
clk1_mask <= '1';
end if;
--********************* MASK_SCK State *****************
when MASK_SCK =>
done <= '1';
-- wait for next internal SCK edge
-- to help provide SS_N hold time
if sck_int_fe <= '1' then
next_spi_state <= HOLD_SSN1;
end if;
--********************* HOLD_SSN1 State *****************
when HOLD_SSN1 =>
-- This state waits for another SCK edge
-- to provide SS_N hold time
if sck_int_fe = '1' then
next_spi_state <= HOLD_SSN2;
end if;
--********************* HOLD_SSN2 State *****************
when HOLD_SSN2 =>
-- This state waits for another SCK edge
-- to provide SS_N hold time
if sck_int_fe = '1' then
next_spi_state <= NEGATE_SSN;
end if;
--********************* NEGATE_SSN State *****************
when NEGATE_SSN =>
-- SS_N should negate for an entire SCK
-- This state waits for an SCK edge
if sck_int_fe = '1' then
next_spi_state <= IDLE;
end if;
--********************* Default State *****************
when others =>
next_spi_state <= IDLE;
end case;
end process;
-- assert slave select when spi_state machine is in any state but IDLE or NEGATE_SSN
ss_n_int <= '1' when (spi_state = IDLE or spi_state = NEGATE_SSN) else '0';
--xmit_load <= '1' when (spi_state = UNMASK_SCK) else '0';
--************************** Register Full/Empty flags *******************************
-- When data is loaded into the SPI transmit shift register from SPITR, the XMIT_EMPTY
-- flag is set, indicating to the uC that new data can be written into SPITR. Note that
-- the SPI transmit shift register is clocked from SCK, therefore, this flag is clocked
-- from SCK.
mt_flag_process: process (sck_int, xmit_empty_reset, reset)
begin
if xmit_empty_reset = RESET_ACTIVE or reset = RESET_ACTIVE then
xmit_empty <= '0';
elsif sck_int'event and sck_int = '1' then
if xmit_empty_reset = RESET_ACTIVE then
-- reset empty flag because uC has written data to SPITR
xmit_empty <= '0';
elsif xmit_load = '1' then
-- set empty flag because SPITR data has been loaded into
-- SPI transmit shift register
xmit_empty <= '1';
end if;
end if;
end process;
-- When data is loaded into SPIRR, the RCV_FULL flag is set, indicating to the uC that
-- new data from the SPI bus has been received.
full_flag_process: process (reset, clk)
begin
if reset = RESET_ACTIVE then
rcv_full <= '0';
elsif clk'event and clk = '1' then
if rcv_full_reset = RESET_ACTIVE then
-- reset the full flag because the spirr has been read
rcv_full <= '0';
elsif rcv_load = '1' then
-- set the full flag because data has been loaded in spirr
rcv_full <= '1';
end if;
end if;
end process;
--************************** Slave Selects *******************************
-- The internal slave select signal generated by the SPI Control state machine
-- is masked by the uC slave select register. The SS_N outputs are clocked on the
-- falling edge of the system clock.
ss_n_process: process ( reset, clk)
variable i : integer;
begin
if reset = RESET_ACTIVE then
ss_n_out <= (others => '1');
elsif clk'event and clk = '0' then
for i in 0 to 7 loop
if ss_n_int = '0' and ss_mask_reg (i) = '1' then
ss_n_out(i) <= '0'; -- assert corresponding slave select
else
ss_n_out(i) <= '1';
end if;
end loop;
end if;
end process;
-- Slave selects are 3-stated if SS_IN_INT is asserted
ss_n <= ss_n_out when ss_in_int = '1'
else (others => 'Z');
end DEFINITION;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -