1 --===========================================================================-- 2 -- -- 3 -- Synthesizable Serial Peripheral Interface Master -- 4 -- -- 5 --===========================================================================-- 6 -- 7 -- File name : spi-master.vhd 8 -- 9 -- Entity name : spi-master 10 -- 11 -- Purpose : Implements a SPI Master Controller 12 -- 13 -- Dependencies : ieee.std_logic_1164 14 -- ieee.std_logic_unsigned 15 -- 16 -- Author : Hans Huebner 17 -- 18 -- Email : hans@huebner.org 19 -- 20 -- Web : http://opencores.org/project,system09 21 -- 22 -- Description : This core implements a SPI master interface. 23 -- Transfer size is 4, 8, 12 or 16 bits. 24 -- The SPI clock is 0 when idle, sampled on 25 -- the rising edge of the SPI clock. 26 -- The SPI clock is derived from the bus clock input 27 -- divided by 2, 4, 8 or 16. 28 -- 29 -- clk, reset, cs, rw, addr, data_in, data_out and irq 30 -- represent the System09 bus interface. 31 -- spi_clk, spi_mosi, spi_miso and spi_cs_n are the 32 -- standard SPI signals meant to be routed off-chip. 33 -- 34 -- The SPI core provides for four register addresses 35 -- that the CPU can read or writen to: 36 -- 37 -- Base + $00 -> DL: Data Low LSB 38 -- Base + $01 -> DH: Data High MSB 39 -- Base + $02 -> CS: Command/Status 40 -- Base + $03 -> CO: Config 41 -- 42 -- CS: Write bits: 43 -- 44 -- CS[0] START : Start transfer 45 -- CS[1] END : Deselect device after transfer 46 -- (or immediately if START = '0') 47 -- CS[2] IRQEN : Generate IRQ at end of transfer 48 -- CS[6:4] SPIAD : SPI device address 49 -- 50 -- CS: Read bits 51 -- 52 -- CS[0] BUSY : Currently transmitting data 53 -- 54 -- CO: Write bits 55 -- 56 -- CO[1:0] DIVIDE: SPI clock divisor, 57 -- 00=clk/2, 58 -- 01=clk/4, 59 -- 10=clk/8, 60 -- 11=clk/16 61 -- CO[3:2] LENGTH: Transfer length, 62 -- 00= 4 bits, 63 -- 01= 8 bits, 64 -- 10=12 bits, 65 -- 11=16 bits 66 -- 67 -- Copyright (C) 2009 - 2010 Hans Huebner 68 -- 69 -- This program is free software: you can redistribute it and/or modify 70 -- it under the terms of the GNU General Public License as published by 71 -- the Free Software Foundation, either version 3 of the License, or 72 -- (at your option) any later version. 73 -- 74 -- This program is distributed in the hope that it will be useful, 75 -- but WITHOUT ANY WARRANTY; without even the implied warranty of 76 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 77 -- GNU General Public License for more details. 78 -- 79 -- You should have received a copy of the GNU General Public License 80 -- along with this program. If not, see <http://www.gnu.org/licenses/>. 81 -- 82 -- 83 --===========================================================================-- 84 -- -- 85 -- Revision History -- 86 -- -- 87 --===========================================================================-- 88 -- 89 -- Version Author Date Description 90 -- 91 -- 0.1 Hans Huebner 23 February 2009 SPI bus master for System09 92 -- 0.2 John Kent 16 June 2010 Added GPL notice 93 -- 94 -- 95 96 library ieee; 97 use ieee.std_logic_1164.all; 98 use ieee.std_logic_unsigned.all; 99 100 entity spi_master is 101 port ( 102 -- 103 -- CPU Interface Signals 104 -- 105 clk : in std_logic; 106 reset : in std_logic; 107 cs : in std_logic; 108 rw : in std_logic; 109 addr : in std_logic_vector(1 downto 0); 110 data_in : in std_logic_vector(7 downto 0); 111 data_out : out std_logic_vector(7 downto 0); 112 irq : out std_logic; 113 -- 114 -- SPI Interface Signals 115 -- 116 spi_miso : in std_logic; 117 spi_mosi : out std_logic; 118 spi_clk : out std_logic; 119 spi_cs_n : out std_logic_vector(7 downto 0) 120 ); 121 end; 122 123 architecture rtl of spi_master is 124 125 -- State type of the SPI transfer state machine 126 type state_type is (s_idle, s_running); 127 signal state : state_type; 128 -- Shift register 129 signal shift_reg : std_logic_vector(15 downto 0); 130 -- Buffer to hold data to be sent 131 signal spi_data_buf : std_logic_vector(15 downto 0); 132 -- Start transmission flag 133 signal start : std_logic; 134 -- Number of bits transfered 135 signal count : std_logic_vector(3 downto 0); 136 -- Buffered SPI clock 137 signal spi_clk_buf : std_logic; 138 -- Buffered SPI clock output 139 signal spi_clk_out : std_logic; 140 -- Previous SPI clock state 141 signal prev_spi_clk : std_logic; 142 -- Number of clk cycles-1 in this SPI clock period 143 signal spi_clk_count : std_logic_vector(2 downto 0); 144 -- SPI clock divisor 145 signal spi_clk_divide : std_logic_vector(1 downto 0); 146 -- SPI transfer length 147 signal transfer_length : std_logic_vector(1 downto 0); 148 -- Flag to indicate that the SPI slave should be deselected after the current 149 -- transfer 150 signal deselect : std_logic; 151 -- Flag to indicate that an IRQ should be generated at the end of a transfer 152 signal irq_enable : std_logic; 153 -- Internal chip select signal, will be demultiplexed through the cs_mux 154 signal spi_cs : std_logic; 155 -- Current SPI device address 156 signal spi_addr : std_logic_vector(2 downto 0); 157 begin 158 159 -- Read CPU bus into internal registers 160 cpu_write : process(clk, reset) 161 begin 162 if reset = '1' then 163 deselect <= '0'; 164 irq_enable <= '0'; 165 start <= '0'; 166 spi_clk_divide <= "11"; 167 transfer_length <= "11"; 168 spi_data_buf <= (others => '0'); 169 elsif falling_edge(clk) then 170 start <= '0'; 171 if cs = '1' and rw = '0' then 172 case addr is 173 when "00" => 174 spi_data_buf(7 downto 0) <= data_in; 175 when "01" => 176 spi_data_buf(15 downto 8) <= data_in; 177 when "10" => 178 start <= data_in(0); 179 deselect <= data_in(1); 180 irq_enable <= data_in(2); 181 spi_addr <= data_in(6 downto 4); 182 when "11" => 183 spi_clk_divide <= data_in(1 downto 0); 184 transfer_length <= data_in(3 downto 2); 185 when others => 186 null; 187 end case; 188 end if; 189 end if; 190 end process; 191 192 -- Provide data for the CPU to read 193 cpu_read : process(shift_reg, addr, state, deselect, start) 194 begin 195 data_out <= (others => '0'); 196 case addr is 197 when "00" => 198 data_out <= shift_reg(7 downto 0); 199 when "01" => 200 data_out <= shift_reg(15 downto 8); 201 when "10" => 202 if state = s_idle then 203 data_out(0) <= '0'; 204 else 205 data_out(0) <= '1'; 206 end if; 207 data_out(1) <= deselect; 208 when others => 209 null; 210 end case; 211 end process; 212 213 spi_cs_n <= "11111110" when spi_addr = "000" and spi_cs = '1' else 214 "11111101" when spi_addr = "001" and spi_cs = '1' else 215 "11111011" when spi_addr = "010" and spi_cs = '1' else 216 "11110111" when spi_addr = "011" and spi_cs = '1' else 217 "11101111" when spi_addr = "100" and spi_cs = '1' else 218 "11011111" when spi_addr = "101" and spi_cs = '1' else 219 "10111111" when spi_addr = "110" and spi_cs = '1' else 220 "01111111" when spi_addr = "111" and spi_cs = '1' else 221 "11111111"; 222 223 -- SPI transfer state machine 224 spi_proc : process(clk, reset) 225 begin 226 if reset = '1' then 227 count <= (others => '0'); 228 shift_reg <= (others => '0'); 229 prev_spi_clk <= '0'; 230 spi_clk_out <= '0'; 231 spi_cs <= '0'; 232 state <= s_idle; 233 irq <= 'Z'; 234 elsif falling_edge(clk) then 235 prev_spi_clk <= spi_clk_buf; 236 irq <= 'Z'; 237 case state is 238 when s_idle => 239 if start = '1' then 240 count <= (others => '0'); 241 shift_reg <= spi_data_buf; 242 spi_cs <= '1'; 243 state <= s_running; 244 elsif deselect = '1' then 245 spi_cs <= '0'; 246 end if; 247 when s_running => 248 if prev_spi_clk = '1' and spi_clk_buf = '0' then 249 spi_clk_out <= '0'; 250 count <= count + "0001"; 251 shift_reg <= shift_reg(14 downto 0) & spi_miso; 252 if ((count = "0011" and transfer_length = "00") 253 or (count = "0111" and transfer_length = "01") 254 or (count = "1011" and transfer_length = "10") 255 or (count = "1111" and transfer_length = "11")) then 256 if deselect = '1' then 257 spi_cs <= '0'; 258 end if; 259 if irq_enable = '1' then 260 irq <= '1'; 261 end if; 262 state <= s_idle; 263 end if; 264 elsif prev_spi_clk = '0' and spi_clk_buf = '1' then 265 spi_clk_out <= '1'; 266 end if; 267 when others => 268 null; 269 end case; 270 end if; 271 end process; 272 273 -- Generate SPI clock 274 spi_clock_gen : process(clk, reset) 275 begin 276 if reset = '1' then 277 spi_clk_count <= (others => '0'); 278 spi_clk_buf <= '0'; 279 elsif falling_edge(clk) then 280 if state = s_running then 281 if ((spi_clk_divide = "00") 282 or (spi_clk_divide = "01" and spi_clk_count = "001") 283 or (spi_clk_divide = "10" and spi_clk_count = "011") 284 or (spi_clk_divide = "11" and spi_clk_count = "111")) then 285 spi_clk_buf <= not spi_clk_buf; 286 spi_clk_count <= (others => '0'); 287 else 288 spi_clk_count <= spi_clk_count + "001"; 289 end if; 290 else 291 spi_clk_buf <= '0'; 292 end if; 293 end if; 294 end process; 295 296 spi_mosi_mux : process(shift_reg, transfer_length) 297 begin 298 case transfer_length is 299 when "00" => 300 spi_mosi <= shift_reg(3); 301 when "01" => 302 spi_mosi <= shift_reg(7); 303 when "10" => 304 spi_mosi <= shift_reg(11); 305 when "11" => 306 spi_mosi <= shift_reg(15); 307 when others => 308 null; 309 end case; 310 end process; 311 312 spi_clk <= spi_clk_out; 313 314 end rtl;