]> jspc29.x-matter.uni-frankfurt.de Git - vhdlbasics.git/commitdiff
spi interface with 2 clocks, IF
authorIngo Froehlich <ingo@nomail.fake>
Tue, 6 Mar 2018 21:20:50 +0000 (22:20 +0100)
committerIngo Froehlich <ingo@nomail.fake>
Tue, 6 Mar 2018 21:20:50 +0000 (22:20 +0100)
interface/spi_slave_async.vhd [new file with mode: 0644]

diff --git a/interface/spi_slave_async.vhd b/interface/spi_slave_async.vhd
new file mode 100644 (file)
index 0000000..36df75a
--- /dev/null
@@ -0,0 +1,177 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.trb_net_std.all;
+
+
+entity spi_slave is
+  port(
+    CLK_ext    : in  std_logic; --fast clock
+    CLK_int    : in  std_logic; --slow clock
+    
+    SPI_CLK    : in  std_logic;
+    SPI_CS     : in  std_logic;
+    SPI_IN     : in  std_logic;
+    SPI_OUT    : out std_logic;
+    
+    DATA_OUT  : out std_logic_vector(15 downto 0);
+    DATA_IN   : in  std_logic_vector(15 downto 0);
+    ADDR_OUT  : out std_logic_vector(7 downto 0);
+    WRITE_OUT : out std_logic;
+    READ_OUT  : out std_logic;
+    READY_IN  : in  std_logic;
+    
+    DEBUG   : out std_logic_vector(15 downto 0)
+    );
+end entity;
+
+architecture SPI_Slave_arch of spi_slave is
+signal spi_clk_last : std_logic;
+signal spi_clk_reg : std_logic;
+signal spi_cs_reg  : std_logic;
+signal spi_in_reg  : std_logic;
+
+signal operation_i : std_logic;
+signal data_write  : std_logic_vector(15 downto 0);
+signal data_in_i   : std_logic_vector(15 downto 0);
+signal addr_i      : std_logic_vector(7 downto 0);
+signal last_input  : std_logic;
+signal input       : std_logic_vector(31 downto 0);
+
+signal next_output : std_logic;
+signal output_data : std_logic_vector (31 downto 0);
+
+signal bitcnt      : integer range 0 to 31 := 31;
+
+type state_t is (IDLE, WAIT_FOR_CMD, GET_DATA, PREPARE_OUTPUT, WRITE_DATA, WAIT_FINISH);
+signal state : state_t;
+
+signal buf_SPI_OUT : std_logic;
+
+signal DATA_OUT_inz  : std_logic_vector(15 downto 0);
+signal ADDR_OUT_int  : std_logic_vector(7 downto 0);
+signal READ_OUT_int  : std_logic;
+signal WRITE_OUT_int : std_logic;
+
+
+begin
+
+spi_clk_last <= spi_clk_reg when rising_edge(CLK_ext);
+spi_clk_reg <= SPI_CLK when rising_edge(CLK_ext);
+spi_cs_reg  <= SPI_CS  when rising_edge(CLK_ext);
+spi_in_reg  <= SPI_IN  when rising_edge(CLK_ext);
+
+DATA_OUT  <= data_write     when rising_edge(CLK_int);
+READ_OUT  <= READ_OUT_int   when rising_edge(CLK_int);
+WRITE_OUT <= WRITE_OUT_int  when rising_edge(CLK_int);
+ADDR_OUT  <= ADDR_OUT_int   when rising_edge(CLK_int);
+
+
+PROC_OUTPUT : process begin
+  wait until rising_edge(CLK_ext);
+  next_output <= output_data(bitcnt);
+  if spi_clk_reg = '0' and spi_clk_last = '1' then
+    SPI_OUT <= last_input;
+    if operation_i = '0' and bitcnt <= 15 then
+      SPI_OUT <= next_output;
+    end if;
+  end if;
+end process;
+
+PROC_INPUT_SHIFT : process begin
+  wait until rising_edge(CLK_ext);
+  if spi_cs_reg = '1' then
+    bitcnt <= 31;
+  else
+    if spi_clk_reg = '1' and spi_clk_last = '0' then
+      if bitcnt /= 0 then
+        bitcnt <= bitcnt - 1;
+      else
+        bitcnt <= 31;
+      end if;
+      last_input <= spi_in_reg;
+      input(bitcnt) <= spi_in_reg;
+    end if;
+  end if;
+end process;
+
+PROC_GEN_SIGNALS : process begin
+  wait until rising_edge(CLK_ext);
+  
+  READ_OUT_int  <= '0';
+  WRITE_OUT_int <= '0';
+
+  case state is
+    when IDLE =>
+      if spi_cs_reg = '0' then
+        state <= WAIT_FOR_CMD;
+      end if;
+      
+    when WAIT_FOR_CMD =>
+      if bitcnt = 22 then
+        operation_i <= input(23);
+        if (input(23) = '0') then  
+          READ_OUT_int  <= '1';
+        end if;
+        ADDR_OUT_int <= input(31 downto 24);
+        state        <= GET_DATA;
+      end if;
+      
+    when GET_DATA =>
+      output_data(15 downto 0) <= x"0000";
+      if operation_i = '0' then  --read
+        READ_OUT_int  <= '1';
+      end if;
+      state <= PREPARE_OUTPUT;
+      
+    when PREPARE_OUTPUT =>
+      if operation_i = '0' then  --read
+        READ_OUT_int  <= '1';
+        if READY_IN = '1' then
+          output_data(15 downto 0) <= DATA_IN;
+          state <= WRITE_DATA;
+        end if;
+      else --write
+        output_data(15 downto 0) <= x"0000";
+        state <= WRITE_DATA;
+      end if;
+      
+    when WRITE_DATA =>
+      if bitcnt = 31 then
+        if operation_i = '1' then
+          WRITE_OUT_int <= '1'; 
+          data_write <= input(15 downto 0);
+        end if;
+        state <= WAIT_FINISH;
+      end if;
+      
+    when WAIT_FINISH =>
+     if operation_i = '1' then
+       WRITE_OUT_int <= '1';
+       if WRITE_OUT = '1' then
+         WRITE_OUT_int <= '0';
+         state <= IDLE;
+       end if;
+     else
+       state <= IDLE;
+     end if;
+     
+  end case;
+   
+  if spi_cs_reg = '1' then
+    state <= IDLE;
+    operation_i <= '0';    
+  end if;
+end process;
+
+DEBUG(0) <= spi_clk_reg;
+DEBUG(1) <= spi_cs_reg;
+DEBUG(2) <= spi_in_reg;
+DEBUG(3) <= buf_SPI_OUT;
+DEBUG(7 downto 4) <= std_logic_vector(to_unsigned(bitcnt,4));
+DEBUG(14 downto 8) <= input(30 downto 24);
+--DEBUG_OUT(15) <= write_i(4);
+
+end;