jjl3 发表于 2015-1-23 20:28:23

发一个自己写的SPI接口程序,请大家评测

LIBRARY ieee;
USE ieee.std_logic_1164.all;

ENTITY spi_bus IS
GENERIC(
         sysCLK   : INTEGER := 100000000;--system clock default is 100MHz
         d_width: INTEGER := 16;         --data bus width
                          clk_freq : INTEGER := 10000000    --SPI clock fequency default is 10MHz
                       );
                          
PORT(
       clock   : IN   STD_LOGIC;                           --system clock
       reset_n : IN   STD_LOGIC;                           --asynchronous reset
       tx_data : IN   STD_LOGIC_VECTOR(d_width-1 DOWNTO 0);--data to transmit
               rx_data : OUT    STD_LOGIC_VECTOR(d_width-1 DOWNTO 0);--data received
               RD_dat: IN   STD_LOGIC;
               WR_dat: IN   STD_LOGIC;

       miso    : IN   STD_LOGIC;                           --master in, slave out
       sclk    : BUFFER STD_LOGIC := '0';                      --spi clock
       ss_n    : BUFFER STD_LOGIC := '1';                      --slave select
       mosi    : OUT    STD_LOGIC                              --master out, slave in
       );
END spi_bus;

ARCHITECTURE logic OF spi_bus IS
signal clk_counter: integer range 0 to (sysCLK / clk_freq / 2 - 1) := 0;
signal width_counter: integer range 0 to (2 * d_width + 3) := 2 * d_width + 1;
signal tx_buf    : STD_LOGIC_VECTOR(d_width-1 DOWNTO 0);--data to transmit
signal        rx_buf    : STD_LOGIC_VECTOR(d_width-1 DOWNTO 0);--data received
signal regclk    : STD_LOGIC;

BEGIN

   regclk <= sclk   when WR_dat = '1' else
                clockwhen WR_dat = '0' else
                               '1';
                               
process (reset_n, WR_dat, RD_dat, regclk, clock)   
variablei,j : integer;
   
begin
           if(reset_n = '1') then
                   if(WR_dat = '0') then
                           if(regclk'event and regclk = '1') then
                                tx_buf      <= tx_data;                                                   
                           end if;
                   end if;
                       
                   if(RD_dat = '0') then
                           if(clock'event and clock = '1') then
                                rx_data <= rx_buf;   
                           end if;
                   end if;
                       
                  if(regclk'event and regclk = '1' and WR_dat = '1' and width_counter > 0) then
                     mosi   <= tx_buf(d_width -1);
                       
                     for i in d_width-1 downto 1 loop
                              tx_buf(i) <= tx_buf(i-1);
                          end loop;
                       
                          tx_buf(0)   <= '0';

                  end if;
                  
                  if(regclk'event and regclk = '0' and ss_n = '0') then
                     for j in 1 to d_width-1 loop
                              rx_buf(j) <= rx_buf(j-1);
                          end loop;
                       
                          rx_buf(0) <= miso;
                  end if;                  
                  
                  
                  if(WR_dat = '1') then
                     if (clock'event and clock = '1') then
                         if (clk_counter = (sysCLK / clk_freq / 2 - 1)) then
                                if (width_counter < 2 * d_width) then
                                      sclk            <= not sclk;
                                     end if;
                                               
                                               if (width_counter < 2 * d_width + 1) then
                                                     width_counter   <= width_counter + 1;
                                               end if;
                                               
                   clk_counter   <= 0;       
                             else clk_counter   <= clk_counter + 1;      
                              end if;
                          end if;
                        else width_counter <= 0;
                                  clk_counter   <= 0;
                  end if;
                  
                  if (width_counter < 2 * d_width + 1 and wr_dat = '1') then
                 ss_n            <= '0';
                          else ss_n      <= '1';
                  end if;
                  
                  else tx_buf      <= (others => '0');
                               ss_n          <= '1';
                               rx_data       <= (others => '0');
                               sclk          <= '0';
           end if;       
end process;
END logic;

wangzh 发表于 2015-1-24 12:14:45

沙发帮顶

NJ8888 发表于 2015-1-24 18:59:03

真不懂你那VHDL中用FOR能支持综合吗?

jjl3 发表于 2015-1-24 19:53:23

NJ8888 发表于 2015-1-24 18:59
真不懂你那VHDL中用FOR能支持综合吗?

综合之后就是移位积存器呀

RUANJI 发表于 2015-1-27 11:27:16

NJ8888 发表于 2015-1-24 18:59
真不懂你那VHDL中用FOR能支持综合吗?

for语句有些情况下是可以综合的,就是少些一些语句。

但是有时候综合起来很耗费面积。
页: [1]
查看完整版本: 发一个自己写的SPI接口程序,请大家评测