• spi master vhd


      1 ----------------------------------------------------------------------------------
      2 -- Company: 
      3 -- Engineer:       shangdawei@gmail.com
      4 -- 
      5 -- Create Date:    08:46:25 05/12/2012 
      6 -- Design Name: 
      7 -- Module Name:    spi_master - Behavioral 
      8 -- Project Name: 
      9 -- Target Devices: 
     10 -- Tool versions: 
     11 -- Description: 
     12 --
     13 -- Dependencies: 
     14 --
     15 -- Revision: 
     16 -- Revision 0.01 - File Created
     17 -- Additional Comments: 
     18 --
     19 ----------------------------------------------------------------------------------
     20 
     21 library IEEE;
     22 use IEEE.std_logic_1164.all;
     23 
     24 -- Uncomment the following library declaration if using
     25 -- arithmetic functions with Signed or Unsigned values
     26 use IEEE.NUMERIC_STD.all;
     27 
     28 -- Uncomment the following library declaration if instantiating
     29 -- any Xilinx primitives in this code.
     30 -- library UNISIM;
     31 -- use UNISIM.VComponents.all;
     32 
     33 entity spi_master is
     34   generic (
     35     C_MODE  : natural := 0; -- dymatic change enabled when C_MODE > 3
     36     C_WIDTH : natural := 9 );
     37   port (
     38     i_clock    : in std_logic; -- system clock
     39     i_tick     : in std_logic; -- xfer enable
     40     i_cpol     : in std_logic; -- spi clock polarity
     41     i_cpha     : in std_logic; -- spi clock phase
     42     o_sck      : out std_logic; -- spi clock
     43     o_ss_n     : out std_logic; -- spi ss_n ( Ready/nBusy )
     44     o_mosi     : out std_logic; -- master out, slave in
     45     i_miso     : in std_logic; -- master in, slave out
     46     i_repeat   : in std_logic; -- repeat receive
     47     i_tx_valid : in std_logic; -- initiate transaction
     48     o_tx_taken : out std_logic; -- tx data taken
     49     o_rx_valid : out std_logic; -- rx data valid
     50     i_tx_msb   : in std_logic_vector (4 downto 0); -- msb of transmit word
     51     o_rx_data  : out std_logic_vector (C_WIDTH-1 downto 0); -- ( to fifo or rdr )
     52     i_tx_data  : in std_logic_vector (C_WIDTH-1 downto 0)); -- ( from fifo or tdr )
     53 end spi_master;
     54 
     55 architecture Behavioral of spi_master is
     56 
     57   signal cpha       : std_logic;
     58   signal cpol       : std_logic;
     59   signal cpol_cpha  : unsigned (1 downto 0);
     60   signal rx_sample  : std_logic;
     61   signal tx_taken   : std_logic := '0';
     62   signal tx_pending : std_logic := '0';
     63   signal rx_last    : std_logic;
     64   signal rx_done    : std_logic := '0';
     65   signal xfer_done  : std_logic := '0';
     66   signal rx_valid   : std_logic := '0';
     67   signal miso       : std_logic;
     68   signal sck        : std_logic := '0';
     69   signal mosi       : std_logic := '0';
     70   signal ss_n       : std_logic := '1';
     71   signal rx_cntr    : unsigned( 5 downto 0 ) := ( others => '0' ); -- max 32 bits
     72   signal shift_reg  : std_logic_vector (C_WIDTH-1 downto 0) := ( others => '0' );
     73   signal sreg_load  : std_logic;
     74 
     75 begin
     76   o_sck      <= sck;
     77   o_mosi     <= mosi;
     78   o_ss_n     <= ss_n;
     79   o_tx_taken <= tx_taken;
     80   o_rx_valid <= rx_valid;
     81   o_rx_data  <= shift_reg;
     82 
     83   cpol_cpha <= to_unsigned( C_MODE, 2 );
     84   cpha      <= i_cpha when C_MODE > 3 else cpol_cpha(0);
     85   cpol      <= i_cpol when C_MODE > 3 else cpol_cpha(1);
     86 
     87   rx_sample <= ( not ( sck xor cpha xor cpol ) ) and ( not ss_n ); -- diff with cpha/cpol
     88   rx_last   <= '1' when ( rx_cntr = unsigned(i_tx_msb) ) and ( sck = ( cpha xor cpol) ) else '0';
     89   rx_done   <= rx_last when rising_edge( i_clock ) and (i_tick = '1' ); -- for both cpha
     90   sreg_load <= ( i_tx_valid and ss_n ) or ( i_tx_valid and rx_done ); -- idle or running 
     91 
     92   -- xfer done : whether restart next xfer, or go idle
     93   process begin
     94     wait until rising_edge( i_clock );
     95     if (i_tick = '1' ) then
     96       if ( cpha = '0' ) then
     97         xfer_done <= rx_done;
     98       else -- ( cpha = '1' )
     99         xfer_done <= rx_last;
    100       end if;
    101     end if;
    102   end process;
    103 
    104   process begin
    105     wait until rising_edge( i_clock );
    106     if rx_last = '1' then -- rx_last : 1 spi clock cycle
    107       rx_valid <= i_tick; -- rx_valid : 1 clock cycle
    108     else
    109       rx_valid <= '0';
    110     end if;
    111   end process;
    112 
    113   -- host can write next data to xfer
    114   process begin
    115     wait until rising_edge( i_clock );
    116     if ss_n = '1' then -- first xfer only, always tx_taken
    117       tx_taken <= i_tick and sreg_load;
    118     else -- last xfer no tx_taken ( sreg_load = '0' )
    119       tx_taken <= i_tick and rx_done and sreg_load;
    120     end if; -- other xfer give ack
    121   end process;
    122 
    123   -- Counting SPI word length : rx_bit #
    124   process begin
    125     wait until rising_edge( i_clock );
    126     if (i_tick = '1' ) then
    127       if ( ss_n = '1' ) or ( rx_last = '1' ) then
    128         rx_cntr <= ( others => '0' );
    129       elsif (sck = ( cpha xor cpol ) ) then
    130         rx_cntr <= rx_cntr + 1;
    131       end if;
    132     end if;
    133   end process;
    134 
    135   process begin
    136     wait until rising_edge( i_clock );
    137     if (i_tick = '1' ) then
    138       if cpha = '0' then
    139         if ( rx_done = '1' ) then
    140           tx_pending <= sreg_load;
    141         elsif ( xfer_done = '1' ) then
    142           tx_pending <= '0';
    143         end if;
    144       end if;
    145     end if;
    146   end process;
    147 
    148 
    149   -- Writing the ss_n
    150   -- xfer done : whether restart next xfer, or go idle
    151   process begin
    152     wait until rising_edge( i_clock );
    153     if (i_tick = '1' ) then
    154       if ( i_tx_valid = '1' ) then -- xfer_done -> tx_taken -> i_tx_valid
    155         ss_n <= '0'; -- i_tx_valid until xfer_done for cpha = '1'
    156 
    157       elsif ( xfer_done = '1' ) then -- cpha = '0'
    158         ss_n <= (not i_repeat) and ( not tx_pending ) ;
    159       end if;
    160     end if;
    161   end process;
    162 
    163   -- Generating the SPI clock
    164   -- xfer done : whether restart next xfer, or go idle
    165   process begin
    166     wait until rising_edge( i_clock );
    167     if (i_tick = '1' ) then
    168       if ( xfer_done = '1' ) then --- cpha = '1' ---    --- cpha = '0' ---
    169         if ( i_repeat = '1' ) or ( sreg_load = '1' ) or ( tx_pending = '1' ) then
    170           sck <= not sck;
    171         else
    172           sck <= cpol; -- idle
    173         end if;
    174       elsif ( ss_n = '0' ) then
    175         sck <= not sck;
    176       else
    177         sck <= cpol; -- idle
    178       end if;
    179     end if;
    180   end process;
    181 
    182   -- Writing the mosi from init data or shifted data
    183   process begin
    184     wait until rising_edge( i_clock );
    185     if (i_tick = '1' ) then
    186       if sreg_load = '1' then
    187         -- mosi <= i_tx_data( to_integer( unsigned(i_tx_msb) ) );
    188         mosi <= shift_reg( to_integer( unsigned(i_tx_msb) ) );
    189       else
    190         mosi <= shift_reg( to_integer( unsigned(i_tx_msb) ) );
    191       end if;
    192     end if;
    193   end process;
    194 
    195   -- Reading the miso line and shifting for mosi at next tick
    196   process begin
    197     wait until rising_edge( i_clock );
    198     if (i_tick = '1' ) then
    199       if sreg_load = '1' then
    200         shift_reg <= i_tx_data;
    201       elsif ( rx_sample = '1' ) then -- mosi is ready to set at next i_tick
    202         shift_reg <= shift_reg(shift_reg'high-1 downto 0 ) & i_miso;
    203 
    204       end if;
    205     end if;
    206   end process;
    207 
    208 end Behavioral;

      1 --------------------------------------------------------------------------------
      2 -- Company: 
      3 -- Engineer:
      4 --
      5 -- Create Date:   23:02:26 05/13/2012
      6 -- Design Name:   
      7 -- Module Name:   D:/projects/arm9_ise/chapter8/chapter8/spi_xfer_tb.vhd
      8 -- Project Name:  chapter8
      9 -- Target Device:  
     10 -- Tool versions:  
     11 -- Description:   
     12 -- 
     13 -- VHDL Test Bench Created by ISE for module: spi_xfer
     14 -- 
     15 -- Dependencies:
     16 -- 
     17 -- Revision:
     18 -- Revision 0.01 - File Created
     19 -- Additional Comments:
     20 --
     21 -- Notes: 
     22 -- This testbench has been automatically generated using types std_logic and
     23 -- std_logic_vector for the ports of the unit under test.  Xilinx recommends
     24 -- that these types always be used for the top-level I/O of a design in order
     25 -- to guarantee that the testbench will bind correctly to the post-implementation 
     26 -- simulation model.
     27 --------------------------------------------------------------------------------
     28 library ieee;
     29 use ieee.std_logic_1164.all;
     30 
     31 -- Uncomment the following library declaration if using
     32 -- arithmetic functions with Signed or Unsigned values
     33 use ieee.numeric_std.all;
     34 
     35 entity spi_xfer_tb is
     36 end spi_xfer_tb;
     37 
     38 architecture behavior of spi_xfer_tb is
     39 
     40   constant C_MODE  : natural := 4;
     41   constant C_WIDTH : natural := 8;
     42 
     43   -- Component Declaration for the Unit Under Test (UUT)
     44 
     45   component spi_xfer
     46     generic (
     47       C_MODE  : natural := 4; -- dymatic change enabled
     48       C_WIDTH : natural := 16 );
     49     port (
     50       i_clock    : in  std_logic; --system clock
     51       i_tick     : in  std_logic; -- xfer enable
     52       i_cpol     : in  std_logic; --spi clock polarity -- sck when idle
     53       i_cpha     : in  std_logic; --spi clock phase
     54       i_miso     : in  std_logic; --master in, slave out
     55       o_mosi     : out  std_logic; --master out, slave in
     56       o_sck      : out  std_logic; --spi clock
     57       o_ss_n     : out  std_logic; -- spi ss_n
     58       i_repeat   : in  std_logic; -- xfering ...
     59       i_tx_valid : in  std_logic; --initiate transaction
     60       i_tx_data  : in  std_logic_vector (C_WIDTH-1 downto 0); --data to transmit
     61       i_tx_msb   : in  std_logic_vector (4 downto 0); -- # of bit to transmit word
     62       o_tx_taken : out  std_logic; -- tx data complete
     63       o_rx_data  : out  std_logic_vector (C_WIDTH-1 downto 0); --data received
     64       o_rx_valid : out  std_logic); -- rx data ready
     65   end component;
     66 
     67 
     68    --Inputs
     69   signal i_repeat   : std_logic := '0';
     70   signal i_clock    : std_logic := '0';
     71   signal i_tick     : std_logic := '0';
     72   signal i_cpol     : std_logic := '0';
     73   signal i_cpha     : std_logic := '0';
     74   signal i_miso     : std_logic := '0';
     75   signal i_tx_valid : std_logic := '0';
     76   signal i_tx_data  : std_logic_vector(C_WIDTH-1 downto 0) := (others => '0');
     77   signal i_tx_msb   : std_logic_vector(4 downto 0) := std_logic_vector( to_unsigned(C_WIDTH-1, 5) );
     78 
     79   --Outputs
     80   signal o_ss_n     : std_logic; -- spi ss_n
     81   signal o_mosi     : std_logic;
     82   signal o_sck      : std_logic;
     83   signal o_tx_taken : std_logic;
     84   signal o_rx_data  : std_logic_vector(C_WIDTH-1  downto 0);
     85   signal o_rx_valid : std_logic;
     86 
     87   signal tx_cntr : unsigned(15 downto 0) := X"0000";
     88    -- Clock period definitions
     89   constant i_clock_period : time := 10 ns;
     90 
     91   constant spi_div : natural := 1;
     92   signal tick_sr   : unsigned(spi_div downto 0) := to_unsigned( 1, spi_div+1);
     93 
     94 begin
     95 
     96   -- Instantiate the Unit Under Test (UUT)
     97   uut : spi_xfer
     98   generic map (
     99     C_MODE  => C_MODE,
    100     C_WIDTH => C_WIDTH )
    101   port map (
    102     i_clock    => i_clock,
    103     i_tick     => i_tick,
    104     i_cpol     => i_cpol,
    105     i_cpha     => i_cpha,
    106     i_miso     => i_miso,
    107     o_mosi     => o_mosi,
    108     o_sck      => o_sck,
    109     o_ss_n     => o_ss_n,
    110     i_repeat   => i_repeat,
    111     i_tx_valid => i_tx_valid,
    112     i_tx_data  => i_tx_data,
    113     i_tx_msb   => i_tx_msb,
    114     o_tx_taken => o_tx_taken,
    115     o_rx_data  => o_rx_data,
    116     o_rx_valid => o_rx_valid
    117   );
    118 
    119    -- Clock process definitions
    120   i_clock_process : process
    121   begin
    122     i_clock <= '0';
    123     wait for i_clock_period/2;
    124     i_clock <= '1';
    125     wait for i_clock_period/2;
    126   end process;
    127 
    128   i_tick  <= tick_sr(0);
    129   tick_sr <= tick_sr(tick_sr'high-1 downto 0) & tick_sr(tick_sr'high) when rising_edge ( i_clock );
    130 
    131    -- Stimulus process
    132   stim_proc : 
    133   process ( i_clock )
    134   begin
    135     if rising_edge( i_clock ) then
    136       if ( tx_cntr < 100 ) then -- delay
    137         i_cpol    <= '0';
    138         i_cpha    <= '0';
    139         i_tx_msb  <= "00111";
    140         i_tx_data <= X"55";
    141         tx_cntr   <= tx_cntr + 1;
    142       elsif ( tx_cntr < 103 ) then -- setup
    143         if ( tx_cntr = 100 ) then
    144           i_tx_valid <= '1';
    145           tx_cntr    <= tx_cntr + 1;
    146         elsif ( o_tx_taken = '1' ) then
    147           i_tx_data <= i_tx_data(i_tx_data'high-1 downto 0) & i_tx_data(i_tx_data'high);
    148           tx_cntr   <= tx_cntr + 1;
    149         end if;
    150 
    151       elsif ( tx_cntr < 120 ) then  -- delay
    152         i_tx_valid <= '0';
    153         if ( o_ss_n = '1' ) then
    154           i_cpol  <= '0';
    155           i_cpha  <= '1';
    156           tx_cntr <= tx_cntr + 1;
    157         end if;
    158       elsif ( tx_cntr < 123 ) then
    159         if ( tx_cntr = 120 ) then
    160           i_tx_valid <= '1';
    161           tx_cntr    <= tx_cntr + 1;
    162         elsif ( o_tx_taken = '1' ) then
    163           i_tx_data <= i_tx_data(i_tx_data'high-1 downto 0) & i_tx_data(i_tx_data'high);
    164           tx_cntr   <= tx_cntr + 1;
    165         end if;
    166 
    167       elsif ( tx_cntr < 140 ) then  -- delay
    168         i_tx_valid <= '0';
    169         if ( o_ss_n = '1' ) then
    170           i_cpol  <= '1';
    171           i_cpha  <= '0';
    172           tx_cntr <= tx_cntr + 1;
    173         end if;
    174       elsif ( tx_cntr < 143 ) then
    175         if ( tx_cntr = 140 ) then
    176           i_tx_valid <= '1';
    177           tx_cntr    <= tx_cntr + 1;
    178         elsif ( o_tx_taken = '1' ) then
    179           i_tx_data <= i_tx_data(i_tx_data'high-1 downto 0) & i_tx_data(i_tx_data'high);
    180           tx_cntr   <= tx_cntr + 1;
    181         end if;
    182 
    183       elsif ( tx_cntr < 160 ) then
    184         i_tx_valid <= '0';
    185         if ( o_ss_n = '1' ) then
    186           i_cpol  <= '1';
    187           i_cpha  <= '1';
    188           tx_cntr <= tx_cntr + 1;
    189         end if;
    190       elsif ( tx_cntr < 163 ) then
    191         if ( tx_cntr = 160 ) then
    192           i_tx_valid <= '1';
    193           tx_cntr    <= tx_cntr + 1;
    194         elsif ( o_tx_taken = '1' ) then
    195           i_tx_data <= i_tx_data(i_tx_data'high-1 downto 0) & i_tx_data(i_tx_data'high);
    196           tx_cntr   <= tx_cntr + 1;
    197         end if;
    198 
    199       elsif ( tx_cntr < 180 ) then
    200         i_tx_valid <= '0';
    201         if ( o_ss_n = '1' ) then
    202           i_cpol  <= '0';
    203           i_cpha  <= '0';
    204           tx_cntr <= tx_cntr + 1;
    205         end if;
    206       elsif ( tx_cntr < 183 ) then
    207         if ( tx_cntr = 180 ) then
    208           i_tx_valid <= '1';
    209           tx_cntr    <= tx_cntr + 1;
    210         elsif ( o_tx_taken = '1' ) then
    211           i_repeat   <= '1';
    212           i_tx_valid <= '0';
    213           tx_cntr    <= to_unsigned(183, tx_cntr'length);
    214         end if;
    215       elsif ( tx_cntr < 185 ) then
    216         if o_rx_valid = '1' then
    217           tx_cntr <= tx_cntr + 1;
    218         end if;
    219       else
    220         i_repeat <= '0';
    221       end if;
    222     end if;
    223   end process;
    224 
    225 
    226 end;

  • 相关阅读:
    centos7 安装mysql
    ketlle windows下的安装(最基本)
    Spark参数详解 一(Spark1.6)
    SSM项目集成Lucene+IKAnalyzer在Junit单元测试中执行异常
    解决jquery.pjax加载后的异常滚动
    码云项目克隆至github
    JFinal获取多个model
    避免layui form表单重复触发submit绑定事件
    解决pjax重复绑定
    jfinal 拦截器中判断是否为pjax请求
  • 原文地址:https://www.cnblogs.com/shangdawei/p/2503706.html
Copyright © 2020-2023  润新知