]> jspc29.x-matter.uni-frankfurt.de Git - trbnet.git/commitdiff
add old SPI interface for designs not compatible with the new features added in January
authorJan Michel <j.michel@gsi.de>
Mon, 8 Apr 2019 13:33:11 +0000 (15:33 +0200)
committerJan Michel <j.michel@gsi.de>
Mon, 8 Apr 2019 13:33:11 +0000 (15:33 +0200)
special/spi_ltc2600_singleoutput.vhd [new file with mode: 0644]

diff --git a/special/spi_ltc2600_singleoutput.vhd b/special/spi_ltc2600_singleoutput.vhd
new file mode 100644 (file)
index 0000000..27cf185
--- /dev/null
@@ -0,0 +1,257 @@
+library IEEE;
+use IEEE.STD_LOGIC_1164.all;
+use IEEE.numeric_std.all;
+
+
+entity spi_ltc2600 is
+  generic(
+    BITS       : integer range 8 to 32   := 32;
+    WAITCYCLES : integer range 2 to 1024 := 7
+    );
+  port(
+    CLK_IN       : in  std_logic;
+    RESET_IN     : in  std_logic;
+    -- Slave bus
+    BUS_READ_IN  : in  std_logic;
+    BUS_WRITE_IN : in  std_logic;
+    BUS_BUSY_OUT : out std_logic;
+    BUS_ACK_OUT  : out std_logic;
+    BUS_ADDR_IN  : in  std_logic_vector(4 downto 0);
+    BUS_DATA_IN  : in  std_logic_vector(31 downto 0);
+    BUS_DATA_OUT : out std_logic_vector(31 downto 0);
+    -- SPI connections
+    SPI_CS_OUT   : out std_logic_vector(15 downto 0);
+    SPI_SDI_IN   : in  std_logic;
+    SPI_SDO_OUT  : out std_logic;
+    SPI_SCK_OUT  : out std_logic;
+    SPI_CLR_OUT  : out std_logic_vector(15 downto 0)
+    );
+end entity;
+
+
+architecture spi_ltc2600_arch of spi_ltc2600 is
+
+  type   ram_t is array(0 to 15) of std_logic_vector(31 downto 0);
+  signal ram : ram_t;
+
+  signal ram_addr       : integer range 0 to 31;
+  signal ram_data       : std_logic_vector(31 downto 0);
+  signal ctrl_reg       : std_logic_vector(31 downto 0);
+  signal start          : std_logic;
+  signal chipselect_reg : std_logic_vector(15 downto 0) := x"0001";
+  signal clear_reg      : std_logic_vector(15 downto 0) := x"0000";
+  signal invert_reg     : std_logic;
+
+  signal spi_cs  : std_logic_vector(15 downto 0);
+  signal spi_sck : std_logic;
+  signal spi_sd  : std_logic;
+
+  signal word_count : integer range 0 to BITS-1;
+  signal bit_count  : integer range 0 to BITS-1;
+  signal time_count : integer range 0 to 1023;
+  signal readback   : std_logic_vector(31 downto 0);
+  signal blocked    : std_logic;
+  signal sudolock   : std_logic;
+
+  type   fsm_t is (IDLE, WAIT_STATE, SET, TOGGLE_CS, TOGGLE_CS_0, TOGGLE_CS_1, TOGGLE_CS_2, FINISH);
+  signal fsm_state : fsm_t;
+  signal word_length : integer range 0 to BITS := BITS;
+  
+  signal wait_cycles : integer range 0 to 1023 := WAITCYCLES;
+  
+begin
+
+  PROC_MEM : process
+    variable addr : integer range 0 to 15;
+  begin
+    wait until rising_edge(CLK_IN);
+    addr := to_integer(unsigned(BUS_ADDR_IN(3 downto 0)));
+
+    BUS_ACK_OUT  <= '0';
+    BUS_BUSY_OUT <= '0';
+    start        <= '0';
+
+    if BUS_WRITE_IN = '1' then
+      if fsm_state = IDLE and blocked = '0' then
+        BUS_ACK_OUT <= '1';
+        if BUS_ADDR_IN(4) = '0' then     --0x00..0x0F
+          ram(addr) <= BUS_DATA_IN;
+        elsif BUS_ADDR_IN(3 downto 0) = x"4" then  --0x14
+          clear_reg <= BUS_DATA_IN(15 downto 0);
+        elsif BUS_ADDR_IN(3 downto 0) = x"8" then  --0x18
+          invert_reg <= BUS_DATA_IN(0);
+        elsif BUS_ADDR_IN(3 downto 0) = x"9" then  -- 0x19
+          word_length <= to_integer(unsigned(BUS_DATA_IN(5 downto 0)));
+        elsif BUS_ADDR_IN(3 downto 0) = x"a" then  -- 0x1a
+          wait_cycles <= to_integer(unsigned(BUS_DATA_IN(9 downto 0)));
+        elsif BUS_ADDR_IN(3 downto 0) = x"1" then  --0x11
+          ctrl_reg <= BUS_DATA_IN;
+          blocked  <= BUS_DATA_IN(16);
+          start    <= not sudolock or BUS_DATA_IN(17) ;
+        elsif BUS_ADDR_IN(3 downto 0) = x"0" then  --0x10
+          chipselect_reg <= BUS_DATA_IN(15 downto 0);
+        end if;
+      elsif BUS_ADDR_IN = "10011" then   --Reg. 0x13
+        sudolock    <= BUS_DATA_IN(17);
+        BUS_ACK_OUT <= '1';
+      else
+        BUS_BUSY_OUT <= '1';
+      end if;
+    end if;
+
+    if BUS_READ_IN = '1' then
+      if BUS_ADDR_IN(4) = '0' then
+        BUS_DATA_OUT <= ram(addr);
+      elsif BUS_ADDR_IN(3 downto 0) = x"0" then
+        BUS_DATA_OUT(15 downto 0)  <= chipselect_reg;
+        BUS_DATA_OUT(31 downto 16) <= x"0000";
+      elsif BUS_ADDR_IN(3 downto 0) = x"1" then
+        BUS_DATA_OUT <= ctrl_reg;
+      elsif BUS_ADDR_IN(3 downto 0) = x"2" then
+        BUS_DATA_OUT <= readback;
+        blocked      <= '0';
+      elsif BUS_ADDR_IN(3 downto 0) = x"3" then
+        BUS_DATA_OUT     <= (others => '0');
+        BUS_DATA_OUT(17) <= sudolock;
+      elsif BUS_ADDR_IN(3 downto 0) = x"4" then
+        BUS_DATA_OUT(15 downto 0)  <= clear_reg;
+        BUS_DATA_OUT(31 downto 16) <= x"0000";
+      elsif BUS_ADDR_IN(3 downto 0) = x"8" then
+        BUS_DATA_OUT(0)           <= invert_reg;
+        BUS_DATA_OUT(31 downto 1) <= (others => '0');
+      elsif BUS_ADDR_IN(3 downto 0) = x"9" then
+        BUS_DATA_OUT             <= (others => '0');
+        BUS_DATA_OUT(5 downto 0) <= std_logic_vector(to_unsigned(word_length,6));
+      elsif BUS_ADDR_IN(3 downto 0) = x"a" then
+        BUS_DATA_OUT             <= (others => '0');
+        BUS_DATA_OUT(9 downto 0) <= std_logic_vector(to_unsigned(wait_cycles,10));
+      end if;
+      BUS_ACK_OUT <= '1';
+    end if;
+
+    ram_data <= ram(ram_addr);
+    
+  end process;
+
+
+
+
+  PROC_FSM : process
+  begin
+    wait until rising_edge(CLK_IN);
+    case fsm_state is
+      when IDLE =>
+
+        if start = '1' then
+          ram_addr   <= 0;
+          word_count <= to_integer(unsigned(ctrl_reg(4 downto 0)));
+          bit_count  <= word_length-1;
+          time_count <= wait_cycles;
+          fsm_state  <= WAIT_STATE;
+          spi_cs     <= not chipselect_reg;
+          spi_sck    <= '1';
+        else
+          spi_cs  <= x"ffff";
+          spi_sck <= '1';
+        end if;
+        
+      when WAIT_STATE =>
+        if time_count = 0 then
+          fsm_state <= SET;
+        else
+          time_count <= time_count - 1;
+        end if;
+        
+      when SET =>
+        time_count <= wait_cycles;
+        spi_sck    <= not spi_sck;
+        if spi_sck = '1' then
+          spi_sd <= ram_data(bit_count);
+          if bit_count /= 0 then
+            bit_count <= bit_count - 1;
+            fsm_state <= WAIT_STATE;
+          else
+            ram_addr  <= ram_addr + 1;
+            bit_count <= word_length-1;
+            if ram_addr /= word_count -1 then
+              if ctrl_reg(7) = '0' then  --one CS phase
+                fsm_state <= WAIT_STATE;
+              else                       --one CS per word
+                fsm_state <= TOGGLE_CS;
+              end if;
+            else
+              fsm_state <= FINISH;
+            end if;
+          end if;
+        else
+          fsm_state <= WAIT_STATE;
+          readback  <= readback(30 downto 0) & SPI_SDI_IN;
+        end if;
+      when TOGGLE_CS =>
+        if time_count = 0 and spi_sck = '0' then
+          time_count <= 7;
+          spi_sck    <= not spi_sck;
+          readback   <= readback(30 downto 0) & SPI_SDI_IN;
+        elsif time_count = 0 and spi_sck = '1' then
+          fsm_state <= TOGGLE_CS_0;
+        else
+          time_count <= time_count - 1;
+        end if;
+      when TOGGLE_CS_0 =>
+        time_count <= time_count - 1;
+        if time_count = 0 then
+          spi_cs     <= x"ffff";
+          fsm_state  <= TOGGLE_CS_1;
+          time_count <= 7;
+        end if;
+      when TOGGLE_CS_1 =>
+        time_count <= time_count - 1;
+        if time_count = 0 then
+          spi_cs     <= not chipselect_reg;
+          bit_count  <= word_length-1;
+          fsm_state  <= WAIT_STATE;
+          time_count <= wait_cycles;
+        end if;
+      when TOGGLE_CS_2 =>
+        time_count <= time_count - 1;
+        if time_count = 0 then
+          spi_sck    <= not spi_sck;
+          fsm_state  <= WAIT_STATE;
+          time_count <= wait_cycles;
+        end if;
+      when FINISH =>
+        if time_count = 0 and spi_sck = '0' then
+          time_count <= wait_cycles;
+          spi_sck    <= not spi_sck;
+          readback   <= readback(30 downto 0) & SPI_SDI_IN;
+        elsif time_count = 0 and spi_sck = '1' then
+          fsm_state <= IDLE;
+        else
+          time_count <= time_count - 1;
+        end if;
+    end case;
+    if RESET_IN = '1' then
+      fsm_state <= IDLE;
+    end if;
+  end process;
+
+
+
+-- Outputs
+  Invert : process(invert_reg, spi_cs,spi_sck,spi_sd)
+  begin
+    if invert_reg = '1' then
+      SPI_CS_OUT  <= not spi_cs;
+      SPI_SCK_OUT <= not spi_sck;
+      SPI_SDO_OUT <= not spi_sd;
+    else
+      SPI_CS_OUT  <= spi_cs;
+      SPI_SCK_OUT <= spi_sck;
+      SPI_SDO_OUT <= spi_sd;
+    end if;
+  end process Invert;
+  SPI_CLR_OUT <= clear_reg;
+  
+
+  
+end architecture;