圖5 SPI接口寫(xiě)工作時(shí)序圖
圖6 SPI接口讀工作時(shí)序圖
4 軟件編程
軟件的編程主要分為移位寄存器的移位、數(shù)據(jù)寄存器的讀寫(xiě)、系統(tǒng)時(shí)鐘的分頻、時(shí)鐘的相位極性確定等幾大部分。如下為它們的VHDL語(yǔ)言源代碼,由于篇幅原因,結(jié)構(gòu)體內(nèi)的定義語(yǔ)句沒(méi)有給出。
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_signed.all;
entity spi_top is
port( clk, wr_n, rd_n, misoi : in std_logic;
irq, mosio, scko : out std_logic;
addr : in std_logic_vector(9 downto 0);
data : inout std_logic_vector(7 downto 0);
rdy : in std_logic_vector(2 downto 0);
slv_sel : out std_logic_vector(2 downto 0) );
end spi_top;
architecture spi of spi_top is
begin
data <= shift_reg when addr=SPIFT_ADDR and rd_n='0' else
stat_reg when addr=SPISR_ADDR and rd_n='0' else
"ZZZZZZZZ";
mosio <= shift_dataout when open_drain ='0' else 'Z';
sr_proc : process(clk)
begin
if(clk'event and clk='1')then
if(spi_go='1')then shift_reg<=data_reg;
elsif(shift_clk='1')then
shift_reg <= shift_reg(6 downto 0) & shift_datain;
end if;
end if;
end process;
neg_proc : process(clk)
begin
if (clk'event and clk='1') then
if (shift_clk_negedge='1') then
shift_negative_edge <= shift_negative_edge_nxt;
elsif (spi_go='1') then
shift_negative_edge <= shift_reg(7);
end if;
end if;
end process;
shift_negative_edge_nxt <= shift_reg(7) when phase='1' else misoi ;
shift_dataout <= shift_negative_edge when phase='1' else shift_reg(7);
shift_datain <= shift_negative_edge when phase='0' else misoi;
tr_proc : process(clk)
begin
if (clk'event and clk='1') then
if (tx_start='1') then tx_run <= '1';
elsif (tx_end='1') then tx_run <= '0';
end if;
end if;
end process;
bc_proc : process (clk)
begin
if (clk'event and clk='1') then
if (tx_start='1') then bit_ctr <= bit_counter;
elsif (shift_clk='1') then bit_ctr <= bit_ctr-1;
end if;
end if;
end process;
tx_end <= '1' when bit_ctr=001 and shift_clk='1' and tx_run='1' else '0';
tx_start <= '1' when spi_go='1' else '0';
elr_proc : process (clk)
begin
if (clk'event and clk='1') then
if (tx_end ='1')then irq_flag <='1';
elsif (tx_run='1')then irq_flag <='0';
end if;
end if;
end process;
dvd_proc : process (clk)
begin-
if (clk'event and clk='1') then
if (not (tx_run='1' ) or tx_end='1') then
dvd_ctr <= "00000", dvd2 <= '0';
else
if (dvd_ctr=00000) then dvd_ctr <= clock_div;
if(tx_start_r1 ='0')then dvd2 <= not dvd2;
end if;
else dvd_ctr <= dvd_ctr-1;
end if;
end if;
end if;
end process;
dvd_zero <= '1' when dvd_ctr=00000 else '0';
shift_clk <= dvd_zero and dvd2 and tx_run and not tx_start_r1;
shift_clk_negedge <= dvd_zero and not dvd2 and tx_run;
scko <= dvd2 xor polck;
wr_data : process(wr_n,tx_run)
begin
if(tx_run='1')then spi_go<='0';
elsif (wr_n'event and wr_n='1' ) then
if( addr=spift_addr) then
data_reg <= data, spi_go <='1';
end if;
end if;
end process;
wr_ctl : process(wr_n)
begin
if (wr_n'event and wr_n='1') then
if addr=spic_addr then ctl_reg <= data;
end if;
end if;
end process;
slv_sel(2 downto 0)<= ctl_reg(2 downto 0);
irq_en <= ctl_reg(7), open_drain <= ctl_reg(6);
phase <= ctl_reg(5), polck <= ctl_reg(4);
irq <= irq_flag and ctl_reg(7);
stat_proc:process(rdy,irq_flag)
begin
stat_reg <= irq_flag & "0000" & rdy(2 downto 0);
end process;
end spi;
5結(jié)論
隨著SPI通信方式的廣泛應(yīng)用,但對(duì)于很多并行總線與之通信成了很大的障礙,本文提出的解決方案具有非常好的可移植性和產(chǎn)品開(kāi)發(fā)能力。本系統(tǒng)既可以作為一個(gè)單獨(dú)的系統(tǒng)運(yùn)行,又可以作為一個(gè)通信模塊植入一個(gè)大系統(tǒng)中,而其中的SPI接口又是一個(gè)可移植SPI接口。利用CPLD的邏輯可編程性,還可以在其剩下的資源中再開(kāi)發(fā)所需要的邏輯器件,既能降低硬件成本又能大大減少系統(tǒng)主板的面積,使電路的設(shè)計(jì)更具靈活性。該設(shè)計(jì)已經(jīng)被應(yīng)用到轉(zhuǎn)臺(tái)速率校準(zhǔn)裝置中,在該設(shè)計(jì)中共有兩個(gè)SPI模塊,同時(shí)還利用了CPLD控制繼電器等其它電路,在歷次試驗(yàn)中其性能指標(biāo)及穩(wěn)定性均達(dá)到了要求。
參考文獻(xiàn)
[1] Xilinx Limited. CoolRunner-II Serial Peripheral Interface Master. 2002
[2] 北京華夏龍科技有限公司.HXL/486II 技術(shù)手冊(cè).
[3] Altera. MAX 7000 Programmable Logic Device Family Data Sheet.1995
[4] 趙俊超 集成電路設(shè)計(jì)VHDL教程. —北京:北京希望電子出版社2002,8





