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;
posted @ 2012-05-16 11:51  IAmAProgrammer  阅读(451)  评论(0编辑  收藏  举报