• SPI bus master for System09


      1 -- SPI bus master for System09 
      2 -- (http://members.optushome.com.au/jekent/system09/index.html)
      3 
      4 -- This core implements a SPI master interface.  Transfer size is 4, 8, 12 or
      5 -- 16 bits.  The SPI clock is 0 when idle, sampled on the rising edge of the SPI
      6 -- clock.  The SPI clock is derived from the bus clock input divided 
      7 -- by 2, 4, 8 or 16.
      8 
      9 -- clk, reset, cs, rw, addr, data_in, data_out and irq represent the System09
     10 -- bus interface.
     11 -- spi_clk, spi_mosi, spi_miso and spi_cs_n are the standard SPI signals meant
     12 -- to be routed off-chip.
     13 
     14 -- The SPI core provides for four register addresses that the CPU can read or
     15 -- write:
     16 
     17 -- 0 -> DL: Data LSB
     18 -- 1 -> DH: Data MSB
     19 -- 2 -> CS: Command/Status
     20 -- 3 -> CO: Config
     21 
     22 -- Write bits, CS:
     23 --
     24 -- START CS[0]:   Start transfer
     25 -- END   CS[1]:   Deselect device after transfer (or immediately if START = '0')
     26 -- IRQEN CS[2]:   Generate IRQ at end of transfer
     27 -- SPIAD CS[6:4]: SPI device address
     28 -- 
     29 -- Read bits, CS:
     30 --
     31 -- BUSY  CS[0]: Currently transmitting data
     32 --
     33 -- Write BITS, CO:
     34 --
     35 -- DIVIDE CO[1:0]: SPI clock divisor, 00=clk/2, 01=clk/4, 10=clk/8, 11=clk/16
     36 -- LENGTH CO[3:2]: Transfer length, 00=4 bits, 01=8 bits, 10=12 bits, 11=16 bits
     37 --
     38 
     39 library ieee;
     40 use ieee.std_logic_1164.all;
     41 use ieee.std_logic_unsigned.all;
     42 
     43 entity spi_master is
     44   port (
     45     clk, reset, cs, rw : in  std_logic;
     46     addr               : in  std_logic_vector(1 downto 0);
     47     data_in            : in  std_logic_vector(7 downto 0);
     48     data_out           : out std_logic_vector(7 downto 0);
     49     irq                : out std_logic;
     50     spi_clk, spi_mosi  : out std_logic;
     51     spi_cs_n           : out std_logic_vector(7 downto 0);
     52     spi_miso           : in  std_logic);
     53 end;
     54 
     55 architecture rtl of spi_master is
     56 
     57   -- State type of the SPI transfer state machine
     58   type   state_type is (s_idle, s_running, s_done);
     59   signal state : state_type;
     60   -- Shift register
     61   signal shift_reg : std_logic_vector(15 downto 0);
     62   -- Buffer to hold data to be sent
     63   signal spi_data_buf : std_logic_vector(15 downto 0);
     64   -- Start transmission flag
     65   signal start : std_logic;
     66   -- Number of bits transfered
     67   signal count : std_logic_vector(3 downto 0);
     68   -- Buffered SPI clock
     69   signal spi_clk_buf : std_logic;
     70   -- Buffered SPI clock output
     71   signal spi_clk_out : std_logic;
     72   -- Previous SPI clock state
     73   signal prev_spi_clk : std_logic;
     74   -- Number of clk cycles-1 in this SPI clock period
     75   signal spi_clk_count : std_logic_vector(2 downto 0);
     76   -- SPI clock divisor
     77   signal spi_clk_divide : std_logic_vector(1 downto 0);
     78   -- SPI transfer length
     79   signal transfer_length : std_logic_vector(1 downto 0);
     80   -- Flag to indicate that the SPI slave should be deselected after the current
     81   -- transfer
     82   signal deselect : std_logic;
     83   -- Flag to indicate that an IRQ should be generated at the end of a transfer
     84   signal irq_enable : std_logic;
     85   -- Signal to clear IRQ
     86   signal irqack : std_logic;
     87   -- Internal chip select signal, will be demultiplexed through the cs_mux
     88   signal spi_cs : std_logic;
     89   -- Current SPI device address
     90   signal spi_addr : std_logic_vector(2 downto 0);
     91 begin
     92 
     93   -- Read CPU bus into internal registers
     94   cpu_write : process(clk, reset)
     95   begin
     96     if reset = '1' then
     97       deselect        <= '0';
     98       irq_enable      <= '0';
     99       start           <= '0';
    100       spi_clk_divide  <= "11";
    101       transfer_length <= "11";
    102       spi_data_buf    <= (others => '0');
    103     elsif falling_edge(clk) then
    104       start  <= '0';
    105       irqack <= '0';
    106       if cs = '1' and rw = '0' then
    107         case addr is
    108           when "00" =>
    109             spi_data_buf(7 downto 0) <= data_in;
    110           when "01" =>
    111             spi_data_buf(15 downto 8) <= data_in;
    112           when "10" =>
    113             start      <= data_in(0);
    114             deselect   <= data_in(1);
    115             irq_enable <= data_in(2);
    116             spi_addr   <= data_in(6 downto 4);
    117             irqack     <= '1';
    118           when "11" =>
    119             spi_clk_divide  <= data_in(1 downto 0);
    120             transfer_length <= data_in(3 downto 2);
    121           when others =>
    122             null;
    123         end case;
    124       end if;
    125     end if;
    126   end process;
    127 
    128   -- Provide data for the CPU to read
    129   cpu_read : process(shift_reg, addr, state, deselect, start)
    130   begin
    131     data_out <= (others => '0');
    132     case addr is
    133       when "00" =>
    134         data_out <= shift_reg(7 downto 0);
    135       when "01" =>
    136         data_out <= shift_reg(15 downto 8);
    137       when "10" =>
    138         if state = s_idle then
    139           data_out(0) <= '0';
    140         else
    141           data_out(0) <= '1';
    142         end if;
    143         data_out(1) <= deselect;
    144       when others =>
    145         null;
    146     end case;
    147   end process;
    148 
    149   spi_cs_n <= "11111110" when spi_addr = "000" and spi_cs = '1' else
    150               "11111101" when spi_addr = "001" and spi_cs = '1' else
    151               "11111011" when spi_addr = "010" and spi_cs = '1' else
    152               "11110111" when spi_addr = "011" and spi_cs = '1' else
    153               "11101111" when spi_addr = "100" and spi_cs = '1' else
    154               "11011111" when spi_addr = "101" and spi_cs = '1' else
    155               "10111111" when spi_addr = "110" and spi_cs = '1' else
    156               "01111111" when spi_addr = "111" and spi_cs = '1' else
    157               "11111111";
    158 
    159   -- SPI transfer state machine
    160   spi_proc : process(clk, reset)
    161   begin
    162     if reset = '1' then
    163       count        <= (others => '0');
    164       shift_reg    <= (others => '0');
    165       prev_spi_clk <= '0';
    166       spi_clk_out  <= '0';
    167       spi_cs       <= '0';
    168       state        <= s_idle;
    169       irq          <= '0';
    170     elsif falling_edge(clk) then
    171       prev_spi_clk <= spi_clk_buf;
    172       irq          <= '0';
    173       case state is
    174         when s_idle =>
    175           if start = '1' then
    176             count     <= (others => '0');
    177             shift_reg <= spi_data_buf;
    178             spi_cs    <= '1';
    179             state     <= s_running;
    180           elsif deselect = '1' then
    181             spi_cs <= '0';
    182           end if;
    183         when s_running =>
    184           if prev_spi_clk = '1' and spi_clk_buf = '0' then
    185             spi_clk_out <= '0';
    186             count       <= count + "0001";
    187             shift_reg   <= shift_reg(14 downto 0) & spi_miso;
    188             if ((count = "0011" and transfer_length = "00")
    189               or (count = "0111" and transfer_length = "01")
    190                 or (count = "1011" and transfer_length = "10")
    191                 or (count = "1111" and transfer_length = "11")) then
    192               if deselect = '1' then
    193                 spi_cs <= '0';
    194               end if;
    195               if irq_enable = '1' then
    196                 irq   <= '1';
    197                 state <= s_done;
    198               end if;
    199               state <= s_idle;
    200             end if;
    201           elsif prev_spi_clk = '0' and spi_clk_buf = '1' then
    202             spi_clk_out <= '1';
    203           end if;
    204         when s_done =>
    205           if irqack = '1' then
    206             state <= s_idle;
    207           end if;
    208         when others =>
    209           null;
    210       end case;
    211     end if;
    212   end process;
    213 
    214   -- Generate SPI clock
    215   spi_clock_gen : process(clk, reset)
    216   begin
    217     if reset = '1' then
    218       spi_clk_count <= (others => '0');
    219       spi_clk_buf   <= '0';
    220     elsif falling_edge(clk) then
    221       if state = s_running then
    222         if ((spi_clk_divide = "00")
    223           or (spi_clk_divide = "01" and spi_clk_count = "001")
    224             or (spi_clk_divide = "10" and spi_clk_count = "011")
    225             or (spi_clk_divide = "11" and spi_clk_count = "111")) then
    226           spi_clk_buf   <= not spi_clk_buf;
    227           spi_clk_count <= (others => '0');
    228         else
    229           spi_clk_count <= spi_clk_count + "001";
    230         end if;
    231       else
    232         spi_clk_buf <= '0';
    233       end if;
    234     end if;
    235   end process;
    236 
    237   spi_mosi_mux : process(shift_reg, transfer_length)
    238   begin
    239     case transfer_length is
    240       when "00" =>
    241         spi_mosi <= shift_reg(3);
    242       when "01" =>
    243         spi_mosi <= shift_reg(7);
    244       when "10" =>
    245         spi_mosi <= shift_reg(11);
    246       when "11" =>
    247         spi_mosi <= shift_reg(15);
    248       when others =>
    249         null;
    250     end case;
    251   end process;
    252 
    253   spi_clk <= spi_clk_out;
    254 
    255 end rtl;

  • 相关阅读:
    Spring
    vue实现大文件上传下载
    javascript实现大文件上传下载
    js实现大文件上传下载
    php实现大文件上传下载
    jsp实现大文件上传下载
    java实现大文件上传下载
    java实现大文件上传功能
    百度ueditor编辑器 复制word里面带图文的文章,图片可以直接显示
    百度ueditor 复制word里面带图文的文章,图片可以直接显示
  • 原文地址:https://www.cnblogs.com/shangdawei/p/2503733.html
Copyright © 2020-2023  润新知