]> jspc29.x-matter.uni-frankfurt.de Git - trb3.git/commitdiff
Speed up slow control configuration of chip.
authorTobias Weber <toweber86@gmail.com>
Thu, 31 Aug 2017 07:24:24 +0000 (09:24 +0200)
committerTobias Weber <toweber86@gmail.com>
Thu, 31 Aug 2017 07:24:53 +0000 (09:24 +0200)
mupix/config.vhd [new file with mode: 0644]
mupix/sources/CRC.vhd [new file with mode: 0644]
mupix/sources/FIFO.vhd [new file with mode: 0644]
mupix/sources/FIFO_FWFT.vhd [new file with mode: 0644]
mupix/sources/FiFo.vhd [deleted file]
mupix/sources/MuPix3_PixCtr.vhd
mupix/sources/StdTypes.vhd
mupix/tb/CRCTest.vhd [new file with mode: 0644]
mupix/tb/MupixShiftReg.vhd [new file with mode: 0644]
mupix/tb/PixCtrlTest.vhd [new file with mode: 0644]

diff --git a/mupix/config.vhd b/mupix/config.vhd
new file mode 100644 (file)
index 0000000..1108620
--- /dev/null
@@ -0,0 +1,91 @@
+library ieee;
+USE IEEE.std_logic_1164.ALL;
+use ieee.numeric_std.all;
+use work.trb_net_std.all;
+
+package config is
+
+
+------------------------------------------------------------------------------
+--Begin of design configuration
+------------------------------------------------------------------------------
+
+    constant USE_DUMMY_READOUT      : integer := c_NO;  --use slowcontrol for readout, no trigger logic
+    
+--Run wih 125 MHz instead of 100 MHz     
+    constant USE_125_MHZ            : integer := c_NO;  --not implemented yet!  
+    constant USE_EXTERNALCLOCK      : integer := c_NO;  --not implemented yet!  
+    
+--Use sync mode, RX clock for all parts of the FPGA
+    constant USE_RXCLOCK            : integer := c_NO;  --not implemented yet!
+    
+   
+--Address settings   
+    constant INIT_ADDRESS           : std_logic_vector := x"F30a";
+    constant BROADCAST_SPECIAL_ADDR : std_logic_vector := x"4b";
+   
+--ADC sampling frequency (only 40 MHz supported a.t.m.)
+    constant ADC_SAMPLING_RATE      : integer := 40;
+    
+--These are currently used for the included features table only
+    constant ADC_PROCESSING_TYPE    : integer := 0;
+    constant ADC_BASELINE_LOGIC     : integer := c_YES;
+    constant ADC_TRIGGER_LOGIC      : integer := c_YES;
+    constant ADC_CHANNELS           : integer := 48;
+    
+------------------------------------------------------------------------------
+--End of design configuration
+------------------------------------------------------------------------------
+
+
+------------------------------------------------------------------------------
+--Select settings by configuration 
+------------------------------------------------------------------------------
+    type intlist_t is array(0 to 7) of integer;
+    type hw_info_t is array(0 to 7) of unsigned(31 downto 0);
+    constant HW_INFO_BASE            : unsigned(31 downto 0) := x"91009000";
+    
+    constant CLOCK_FREQUENCY_ARR  : intlist_t := (100,125, others => 0);
+    constant MEDIA_FREQUENCY_ARR  : intlist_t := (200,125, others => 0);
+                          
+  --declare constants, filled in body                          
+    constant HARDWARE_INFO        : std_logic_vector(31 downto 0);
+    constant CLOCK_FREQUENCY      : integer;
+    constant MEDIA_FREQUENCY      : integer;
+    constant INCLUDED_FEATURES      : std_logic_vector(63 downto 0);
+    
+    
+end;
+
+package body config is
+--compute correct configuration mode
+  
+  constant HARDWARE_INFO        : std_logic_vector(31 downto 0) := std_logic_vector(
+                                      HW_INFO_BASE );
+  constant CLOCK_FREQUENCY      : integer := CLOCK_FREQUENCY_ARR(USE_125_MHZ);
+  constant MEDIA_FREQUENCY      : integer := MEDIA_FREQUENCY_ARR(USE_125_MHZ);
+
+  
+  
+function generateIncludedFeatures return std_logic_vector is
+  variable t : std_logic_vector(63 downto 0);
+begin
+  t               := (others => '0');
+  t(63 downto 56) := std_logic_vector(to_unsigned(4,8)); --table version 2
+  t(7 downto 0)   := std_logic_vector(to_unsigned(ADC_SAMPLING_RATE,8));
+  t(11 downto 8)  := std_logic_vector(to_unsigned(ADC_PROCESSING_TYPE,4)); --processing type
+  t(14 downto 14) := std_logic_vector(to_unsigned(ADC_BASELINE_LOGIC,1));
+  t(15 downto 15) := std_logic_vector(to_unsigned(ADC_TRIGGER_LOGIC,1));
+  t(23 downto 16) := std_logic_vector(to_unsigned(ADC_CHANNELS,8));
+  t(42 downto 42) := "1"; --std_logic_vector(to_unsigned(INCLUDE_SPI,1));
+  t(44 downto 44) := "0"; --std_logic_vector(to_unsigned(INCLUDE_STATISTICS,1));
+  t(51 downto 48) := x"0";--std_logic_vector(to_unsigned(INCLUDE_TRIGGER_LOGIC,4));
+  t(52 downto 52) := std_logic_vector(to_unsigned(USE_125_MHZ,1));
+  t(53 downto 53) := std_logic_vector(to_unsigned(USE_RXCLOCK,1));
+  t(54 downto 54) := std_logic_vector(to_unsigned(USE_EXTERNALCLOCK,1));
+  return t;
+end function;  
+
+  constant INCLUDED_FEATURES : std_logic_vector(63 downto 0) := generateIncludedFeatures;    
+
+end package body;
\ No newline at end of file
diff --git a/mupix/sources/CRC.vhd b/mupix/sources/CRC.vhd
new file mode 100644 (file)
index 0000000..9803375
--- /dev/null
@@ -0,0 +1,70 @@
+-------------------------------------------------------------------------------
+--Computation of cyclic redundancy check
+--We use the CRC5 polynomial f(x) = 1 + x^2 + x^ 5 used by the USB2.0 protocol
+-------------------------------------------------------------------------------
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity CRC is
+       generic(
+         detect_enable_edge : boolean := false
+       );
+       port(
+               clk     : in  std_logic;
+               rst     : in  std_logic;
+               enable  : in  std_logic;
+               data_in : in  std_logic;
+               crc_out : out std_logic_vector(4 downto 0));
+end entity CRC;
+
+architecture rtl of CRC is
+       signal lfsr : std_logic_vector(4 downto 0) := (others => '1');
+       signal edge_detect : std_logic_vector(1 downto 0) := (others => '0');
+begin
+       
+       normal_gen : if detect_enable_edge = false generate
+               CRC_proc : process(clk) is
+               begin
+                       if rising_edge(clk) then
+                               if rst = '1' then
+                                       lfsr <= (others => '1');
+                               else
+                                       lfsr <= lfsr;
+                                       if enable = '1' then
+                                               lfsr(0) <= lfsr(4) xor data_in;
+                                               lfsr(1) <= lfsr(0);
+                                               lfsr(2) <= (lfsr(4) xor data_in) xor lfsr(1);
+                                               lfsr(3) <= lfsr(2);
+                                               lfsr(4) <= lfsr(3);
+                                       end if;
+                               end if;
+                       end if;
+               end process CRC_proc;
+       end generate;
+       
+       detect_enable_edge_gen : if detect_enable_edge = true generate
+               CRC_edge_proc : process(clk) is
+               begin
+                       if rising_edge(clk) then
+                               if rst = '1' then
+                                       lfsr <= (others => '1');
+                                       edge_detect <= (others => '0');
+                               else
+                                       edge_detect <= edge_detect(0) & enable;
+                                       lfsr <= lfsr;
+                                       if edge_detect = "01" then
+                                               lfsr(0) <= lfsr(4) xor data_in;
+                                               lfsr(1) <= lfsr(0);
+                                               lfsr(2) <= (lfsr(4) xor data_in) xor lfsr(1);
+                                               lfsr(3) <= lfsr(2);
+                                               lfsr(4) <= lfsr(3);
+                                       end if;
+                               end if;
+                       end if;
+               end process CRC_edge_proc;
+       end generate;
+       
+       crc_out <= lfsr;
+       
+end architecture rtl;
\ No newline at end of file
diff --git a/mupix/sources/FIFO.vhd b/mupix/sources/FIFO.vhd
new file mode 100644 (file)
index 0000000..2d286aa
--- /dev/null
@@ -0,0 +1,100 @@
+-------------------------------------------------------------------------------
+--Dummy implementation of FIFO for simulation
+--For production system use FPGA manufacturer IP core
+-------------------------------------------------------------------------------
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.all;
+use IEEE.NUMERIC_STD.all;
+
+entity STD_FIFO is
+  generic (
+    constant DATA_WIDTH : positive := 8;
+    constant FIFO_DEPTH : positive := 256
+    );
+  port (
+    CLK     : in  std_logic;
+    RST     : in  std_logic;
+    WriteEn : in  std_logic;
+    DataIn  : in  std_logic_vector (DATA_WIDTH - 1 downto 0);
+    ReadEn  : in  std_logic;
+    DataOut : out std_logic_vector (DATA_WIDTH - 1 downto 0);
+    Empty   : out std_logic;
+    Full    : out std_logic
+    );
+end STD_FIFO;
+
+architecture Behavioral of STD_FIFO is
+
+begin
+
+  -- Memory Pointer Process
+  fifo_proc : process (CLK)
+    type FIFO_Memory is array (0 to FIFO_DEPTH - 1) of std_logic_vector (DATA_WIDTH - 1 downto 0);
+    variable Memory : FIFO_Memory;
+
+    variable Head : natural range 0 to FIFO_DEPTH - 1;
+    variable Tail : natural range 0 to FIFO_DEPTH - 1;
+
+    variable Looped : boolean;
+  begin
+    if rising_edge(CLK) then
+      if RST = '1' then
+        Head := 0;
+        Tail := 0;
+
+        Looped := false;
+
+        Full  <= '0';
+        Empty <= '1';
+      else
+        if (ReadEn = '1') then
+          if ((Looped = true) or (Head /= Tail)) then
+                                        -- Update data output
+            DataOut <= Memory(Tail);
+
+                                        -- Update Tail pointer as needed
+            if (Tail = FIFO_DEPTH - 1) then
+              Tail := 0;
+
+              Looped := false;
+            else
+              Tail := Tail + 1;
+            end if;
+
+
+          end if;
+        end if;
+
+        if (WriteEn = '1') then
+          if ((Looped = false) or (Head /= Tail)) then
+                                        -- Write Data to Memory
+            Memory(Head) := DataIn;
+
+                                        -- Increment Head pointer as needed
+            if (Head = FIFO_DEPTH - 1) then
+              Head := 0;
+
+              Looped := true;
+            else
+              Head := Head + 1;
+            end if;
+          end if;
+        end if;
+
+        -- Update Empty and Full flags
+        if (Head = Tail) then
+          if Looped then
+            Full <= '1';
+          else
+            Empty <= '1';
+          end if;
+        else
+          Empty <= '0';
+          Full  <= '0';
+        end if;
+      end if;
+    end if;
+  end process;
+
+end Behavioral;
diff --git a/mupix/sources/FIFO_FWFT.vhd b/mupix/sources/FIFO_FWFT.vhd
new file mode 100644 (file)
index 0000000..6f9d910
--- /dev/null
@@ -0,0 +1,68 @@
+------------------------------------------------------------
+--!@brief Small implementation of a FIFO using shift register
+--!this implementation does not support seperate input and output clock
+--!and should be replaced with a FIFO from the manufacturer IP for production
+--!systems
+--!@author Tobias Weber
+--!@date March 2017
+------------------------------------------------------------
+library ieee;
+use ieee.numeric_std.all;
+use ieee.std_logic_1164.all;
+
+entity tiny_fifo is
+  generic(
+    fifo_depth : integer := 4; --! number words = fifo_depth**2
+    fifo_width : integer := 32); --! fifo data width
+  port(
+    clk_in : in std_logic;--! clock input
+    --fifo input channel
+    fifo_data_in   : in  std_logic_vector(fifo_width - 1 downto 0); --! fifo data input
+    fifo_valid_in  : in  std_logic; --! fifo input data is valid
+    fifo_ready_out : out std_logic; --! fifo is ready to accept data
+
+    --fifo output channel
+    fifo_data_out  : out std_logic_vector(fifo_width - 1 downto 0); --! fifo data output
+    fifo_valid_out : out std_logic; --! fifo output data is valid
+    fifo_ready_in  : in  std_logic); --! fifo reader is ready for new word (pushes new word to fifo output0
+end entity;
+
+architecture behavior of tiny_fifo is
+
+  type memory_type is array((2**fifo_depth - 1) downto 0) of std_logic_vector(fifo_width - 1 downto 0);
+  signal fifo_memory     : memory_type                      := (others => (others => '0'));
+  signal fifo_index      : signed (fifo_depth downto 0) := to_signed(-1, fifo_depth + 1);
+  signal fifo_full       : std_logic;
+  signal fifo_empty      : std_logic;
+  signal fifo_in_enable  : boolean;
+  signal fifo_out_enable : boolean;
+begin
+
+  fifo_full  <= '1' when (fifo_index = 2**fifo_depth - 1) else '0';
+  fifo_empty <= '1' when (fifo_index = -1) else '0';
+
+  fifo_ready_out <= '1' when (fifo_full = '0')  else '0';
+  fifo_valid_out <= '1' when (fifo_empty = '0') else '0';
+
+  fifo_in_enable  <= (fifo_valid_in = '1') and (fifo_full = '0');
+  fifo_out_enable <= (fifo_ready_in = '1') and (fifo_empty = '0');
+
+  fifo_data_out <= fifo_memory(to_integer(unsigned(fifo_index(fifo_depth - 1 downto 0))));
+
+  fifo_proc : process(clk_in)
+  begin
+    if rising_edge(clk_in) then
+      if fifo_in_enable then
+        fifo_memory((2**fifo_depth - 1) downto 1) <= fifo_memory((2**fifo_depth - 2) downto 0);
+        fifo_memory(0)                            <= fifo_data_in;
+        if not fifo_out_enable then
+          fifo_index <= fifo_index + 1;
+        end if;
+      elsif fifo_out_enable then
+        fifo_index <= fifo_index - 1;
+      end if;
+    end if;
+  end process fifo_proc;
+
+end architecture;
diff --git a/mupix/sources/FiFo.vhd b/mupix/sources/FiFo.vhd
deleted file mode 100644 (file)
index a4b00a5..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-------------------------------------------------------------
---VHDL description of very basic  FIFO
---T.Weber, Mainz University
-------------------------------------------------------------
-
-library IEEE;
-use IEEE.STD_LOGIC_1164.all;
-use IEEE.NUMERIC_STD.all;
-
-entity fifo is
-  generic(addr_wd : integer := 8;
-          word_wd : integer := 8);
-  port (Din     : in  std_logic_vector (word_wd - 1 downto 0);
-        Wr      : in  std_logic;        
-        Dout    : out std_logic_vector (word_wd - 1 downto 0);
-        Rd      : in  std_logic;         
-        Empty   : out std_logic;        
-        Full    : out std_logic;        
-        WrCnt_o : out std_logic_vector(addr_wd - 1 downto 0);
-        Reset   : in  std_logic;
-        CLK     : in  std_logic
-        );
-end fifo;
-
-
-architecture fifo_arch of fifo is
-  -- decl
-  signal wrcnt     : unsigned (addr_wd-1 downto 0) := (others => '0');
-  signal rdcnt     : unsigned (addr_wd-1 downto 0) := (others => '0');
-  signal din_int   : unsigned (word_wd-1 downto 0) := (others => '0');
-  type   memory_type is array(0 to (2**addr_wd)-1) of unsigned(word_wd-1 downto 0);
-  signal memory    : memory_type;
-  signal memory_address : unsigned(addr_wd-1 downto 0) := (others => '0');
-  
-  signal full_loc  : std_logic;
-  signal empty_loc : std_logic;
-  signal write_int : std_logic;
-  
-begin
-  
-  blockmemory: process(clk)
-  begin
-    if rising_edge(clk) then
-        if (write_int = '1') then
-          memory(to_integer(memory_address)) <= din_int;
-        end if;
-        dout  <= std_logic_vector(memory(to_integer(memory_address)));
-    end if;
-  end process blockmemory;
-
-  AddressMux: process (clk)
-  begin  -- process AddressMux
-    if rising_edge(clk) then
-      if Reset = '1' then
-        rdcnt <= (others => '0');
-        wrcnt <= (others => '0');
-      else
-        if Wr = '1' and full_loc = '0' then
-          memory_address <= wrcnt;
-          write_int      <= '1';
-          din_int        <= unsigned(Din);
-          wrcnt          <= wrcnt + 1;
-        elsif (Rd = '1' and empty_loc = '0') then
-          memory_address <= rdcnt ;
-          rdcnt <= rdcnt + 1;
-        else
-          write_int <= '0';
-          memory_address <= (others => '0');
-        end if;
-      end if;
-    end if;
-  end process AddressMux;
-      
-  full_loc  <= '1' when rdcnt = wrcnt+1 else '0';
-  empty_loc <= '1' when rdcnt = wrcnt   else '0';
-  Full      <= full_loc;
-  Empty     <= empty_loc;
-  WrCnt_o   <= std_logic_vector(wrcnt-rdcnt);
-  
-end architecture fifo_arch; 
index d1b6b8080df22b7495cd20262ba1efb684080126..119cc475a558b51e2b9f54a18f84bd434e3ea16f 100644 (file)
@@ -1,5 +1,5 @@
 -------------------------------------------------------------------------------
---Controll of MuPix DACs and Pixel Tune DACs
+--Control of MuPix DACs and Pixel Tune DACs
 --T. Weber, Mainz Univesity
 -------------------------------------------------------------------------------
 library IEEE;
@@ -9,9 +9,13 @@ use IEEE.numeric_std.all;
 use work.StdTypes.all;
 
 entity PixCtr is
-  
+  generic(
+       fpga_clk_speed : integer := 1e8;
+       spi_clk_speed : integer := 1e4
+  );
   port (
     clk                  : in  std_logic;
+    reset                : in  std_logic;
     sout_c_from_mupix    : in  std_logic;
     sout_d_from_mupix    : in  std_logic;
     mupix_ctrl           : out MupixSlowControl;
@@ -26,50 +30,266 @@ entity PixCtr is
 end PixCtr;
 
 architecture Behavioral of PixCtr is
-  
-
-  signal sout_from_mupix     : std_logic_vector(31 downto 0);
-  signal slowcontrol_reg_new : std_logic_vector(31 downto 0);
-  signal slowcontrol_reg_old : std_logic_vector(31 downto 0);
-  signal start_write_mupix   : std_logic;
-  signal done_write_mupix    : std_logic;
-  signal busy_write_mupix    : std_logic := '0';
-
-  type   delay_type is (idle, delay1, done);
-  signal delay_fsm : delay_type := idle;
+       
+       constant fifo_word_width : integer :=  32;
+       
+       signal bitcounter : unsigned(15 downto 0) := (others => '0');--number of transmitted configuration bits
+       signal bitstosend : unsigned(15 downto 0) := (others => '0');--number of bits which need to be send
+       signal bitcouner_word : integer range 0 to fifo_word_width - 1 := 0; --index to current bit in word from fifo
+       signal controlConfig : std_logic_vector(15 downto 0) := (others => '0');--configuration control
+       
+       --fifos storage of configuration bits
+       component STD_FIFO
+               generic(
+                       DATA_WIDTH : positive := 8;
+                       FIFO_DEPTH : positive := 256
+               );
+               port(
+                       CLK     : in  std_logic;
+                       RST     : in  std_logic;
+                       WriteEn : in  std_logic;
+                       DataIn  : in  std_logic_vector(fifo_word_width - 1 downto 0);
+                       ReadEn  : in  std_logic;
+                       DataOut : out std_logic_vector(fifo_word_width - 1 downto 0);
+                       Empty   : out std_logic;
+                       Full    : out std_logic
+               );
+       end component STD_FIFO;
+       
+       component CRC
+               generic(
+                       detect_enable_edge : boolean := false
+               );
+               port(
+                       clk     : in  std_logic;
+                       rst     : in  std_logic;
+                       enable  : in  std_logic;
+                       data_in : in  std_logic;
+                       crc_out : out std_logic_vector(4 downto 0)
+               );
+       end component CRC;
 
+       signal WriteEn : std_logic;
+       signal DataIn : std_logic_vector (fifo_word_width - 1 downto 0);
+       signal ReadEn : std_logic;
+       signal DataOut : std_logic_vector (fifo_word_width - 1 downto 0);
+       signal Empty : std_logic;
+       signal Full : std_logic;
+       
+       --clock enable signals
+       signal clk_enable : std_logic := '0';
+       constant clk_div_max : integer := fpga_clk_speed/spi_clk_speed - 1;
+       signal clk_div_counter : integer range 0 to clk_div_max := clk_div_max;
+       
+       --send single configuration bit
+       type bit_send_fsm_type is (idle, sendbit1, sendbit2, sendbit3);
+       signal bit_send_fsm : bit_send_fsm_type := idle;
+       signal start_send, sending : std_logic; 
+       
+       --configuration state machine
+       type config_fsm_type is (idle, config, readfifo, waitfifo, load);
+       signal config_fsm : config_fsm_type := idle;
+       
+       --check sum for data integrity
+       signal crc_checksum_out, crc_checksum_in : std_logic_vector(4 downto 0) := (others => '0');
+       signal crc_correct : std_logic;
+       signal enable_crc_to_mupix : std_logic;
+       signal data_in_crc_to_mupix : std_logic;
+       signal crc_out_crc_to_mupix : std_logic_vector(4 downto 0);
+       signal enable_crc_from_mupix : std_logic;
+       signal data_in_crc_from_mupix : std_logic;
+       signal crc_out_crc_from_mupix : std_logic_vector(4 downto 0);
+       
+       --control signals to mupix
+       signal mupix_ctrl_i, mupix_ctrl_reg : MupixSlowControl := MuPixSlowControlInit;
+       
+       
 begin  -- Behavioral
-
-  Delay : process (clk)
-  begin  -- process Delay
-    if rising_edge(clk) then
-      done_write_mupix <= '0';
-      case delay_fsm is
-        when idle =>
-          if start_write_mupix = '1' then
-            delay_fsm <= delay1;
-          end if;
-        when delay1 =>
-          delay_fsm <= done;
-        when done =>
-          done_write_mupix    <= '1';
-          sout_from_mupix     <= sout_from_mupix(29 downto 0) & sout_c_from_mupix & sout_d_from_mupix;
-          slowcontrol_reg_old <= slowcontrol_reg_new;
-          delay_fsm <= idle;
-      end case;
-    end if;
-  end process Delay;
-
-  mupix_ctrl.sin  <= slowcontrol_reg_old(0);
-  mupix_ctrl.ck_c <= slowcontrol_reg_old(1);
-  mupix_ctrl.ck_d <= slowcontrol_reg_old(2);
-  mupix_ctrl.ld_c <= slowcontrol_reg_old(3);
-
+       
+       fifo_1 : entity work.STD_FIFO
+               generic map(
+                       DATA_WIDTH => fifo_word_width,
+                       FIFO_DEPTH => 32
+               )
+               port map(
+                       CLK     => CLK,
+                       RST     => reset,
+                       WriteEn => WriteEn,
+                       DataIn  => DataIn,
+                       ReadEn  => ReadEn,
+                       DataOut => DataOut,
+                       Empty   => Empty,
+                       Full    => Full
+               );
+       
+       --TODO: CRC checking logic
+       crc_in : entity work.CRC
+               generic map(detect_enable_edge => true)
+               port map(
+                       clk     => clk,
+                       rst     => reset,
+                       enable  => enable_crc_to_mupix,
+                       data_in => data_in_crc_to_mupix,
+                       crc_out => crc_out_crc_to_mupix
+               );
+               
+       crc_out : entity work.CRC
+               generic map(detect_enable_edge => true)
+               port map(
+                       clk     => clk,
+                       rst     => reset,
+                       enable  => enable_crc_from_mupix,
+                       data_in => data_in_crc_from_mupix,
+                       crc_out => crc_out_crc_from_mupix
+               );
+       
+       spi_clk_div_proc : process (clk) is
+       begin
+               if rising_edge(clk) then
+                       if reset = '1' then
+                               clk_enable <= '0';
+                               clk_div_counter <= clk_div_max;
+                       else
+                               if clk_div_counter = 0 then
+                                       clk_div_counter <= clk_div_max;
+                                       clk_enable <= '1';
+                               else    
+                                       clk_div_counter <= clk_div_counter - 1;
+                                       clk_enable <= '0';
+                               end if;
+                       end if;
+               end if;
+       end process spi_clk_div_proc;
+       
+       
+       sendpixbit_proc : process (clk) is
+       begin
+               if rising_edge(clk) then
+                       if reset = '1' then
+                               mupix_ctrl_i.ck_c <= '0';
+                               mupix_ctrl_i.ck_d <= '0';
+                               mupix_ctrl_i.sin <= '0';
+                               sending <= '0';
+                               bit_send_fsm <= idle;
+                               bitcounter <= (others => '0');
+                               bitcouner_word <= fifo_word_width - 1;
+                       else
+                               if clk_enable = '1' then
+                                       mupix_ctrl_i.ck_c <= '0';
+                                       mupix_ctrl_i.ck_d <= '0';
+                                       mupix_ctrl_i.sin <= '0';
+                                       case bit_send_fsm is 
+                                               when idle =>
+                                                       bitcouner_word <= fifo_word_width - 1;
+                                                       if start_send = '1' then
+                                                               bit_send_fsm <= sendbit1;
+                                                               sending <= '1';
+                                                       else
+                                                               bit_send_fsm <= idle;
+                                                               sending <= '0';
+                                                       end if;
+                                               when sendbit1 =>
+                                                       mupix_ctrl_i.sin <= DataOut(bitcouner_word);
+                                                       sending <= '1';
+                                                       bit_send_fsm <= sendbit2;
+                                               when sendbit2 => --rising clock edge
+                                                       mupix_ctrl_i.sin <= DataOut(bitcouner_word);
+                                                       if controlConfig(0) = '1' then
+                                                               mupix_ctrl_i.ck_d <= '1';
+                                                       else
+                                                               mupix_ctrl_i.ck_c <= '1';
+                                                       end if;
+                                                       bit_send_fsm <= sendbit3;
+                                                       sending <= '1';
+                                               when sendbit3 =>
+                                                       sending <= '1';
+                                                       mupix_ctrl_i.sin <= DataOut(bitcouner_word);
+                                                       bitcouner_word <= bitcouner_word - 1;
+                                                       bitcounter <= bitcounter + 1;
+                                                       if bitcouner_word = 0 or bitcounter = bitstosend then
+                                                               bit_send_fsm <= idle;
+                                                       else
+                                                               bit_send_fsm <= sendbit1;
+                                                       end if;
+                                       end case;
+                               end if;
+                       end if;
+               end if;
+       end process sendpixbit_proc;
+               
+       
+       configure_proc : process (clk) is
+               variable hold_load_counter : integer range 0 to 7;
+       begin
+               if rising_edge(clk) then
+                       if reset = '1' then
+                               mupix_ctrl_i.ld_c <= '0';
+                               config_fsm <= idle;
+                               hold_load_counter := 0;
+                       else
+                               mupix_ctrl_i.ld_c <= '0';
+                               ReadEn <= '0';
+                               start_send <= '0';
+                               case config_fsm is  
+                                       when idle =>
+                                               hold_load_counter := 0;
+                                               if Empty = '0' then
+                                                       config_fsm <= readfifo;
+                                               else
+                                                       config_fsm <= idle;
+                                               end if;
+                                       when readfifo =>
+                                               if Empty = '0' then
+                                                       ReadEn <= '1';
+                                                       config_fsm <= waitfifo;
+                                               else
+                                                       ReadEn <= '0';
+                                                       config_fsm <= readfifo;
+                                               end if;
+                                       when waitfifo =>
+                                               config_fsm <= config;
+                                               if sending = '0' then
+                                                       start_send <= '1';
+                                                       config_fsm <= waitfifo;
+                                               else
+                                                       start_send <= '0';
+                                                       config_fsm <= config;
+                                               end if;
+                                       when config =>
+                                               if sending = '1' then
+                                                       config_fsm <= config;
+                                               else
+                                                       if bitcounter < bitstosend then
+                                                               config_fsm <= readfifo;
+                                                       else
+                                                               if controlConfig(1) = '0' then
+                                                                       config_fsm <= load;
+                                                               else
+                                                                       config_fsm <= idle;
+                                                               end if;
+                                                       end if;
+                                               end if; 
+                                       when load =>
+                                               hold_load_counter := hold_load_counter + 1;
+                                               mupix_ctrl_i.ld_c <= '1';
+                                               if hold_load_counter = 7 then
+                                                       mupix_ctrl_i.ld_c <= '0';
+                                                       config_fsm <= idle;
+                                               else
+                                                       config_fsm <= load;
+                                               end if;
+                               end case;
+                       end if;
+               end if;
+       end process configure_proc;
+       
+       
   -----------------------------------------------------------------------------
-  --x0080: Register for SlowControl
-  --x0081: Output of MuPix SlowControl Pins
+  --x0080: input to fifo (write)/current fifo output (read)
+  --x0081: current CRC check sum (read only)
+  --x0082: data fifo is full (read only)
+  --x0083: configure bit 0: configure chip dacs/pixel dacs, bit 1: readback bit 32-16 number of config bits 
   -----------------------------------------------------------------------------
-
   SLV_BUS : process (clk)
   begin  -- process SLV_BUS
     if rising_edge(clk) then
@@ -77,25 +297,19 @@ begin  -- Behavioral
       SLV_DATA_OUT         <= (others => '0');
       SLV_UNKNOWN_ADDR_OUT <= '0';
       SLV_NO_MORE_DATA_OUT <= '0';
-      SLV_ACK_OUT          <= '0';
-      start_write_mupix    <= '0';
-
-
-      if busy_write_mupix = '1' then
-        if done_write_mupix = '0'then
-          busy_write_mupix <= '1';
-        else
-          busy_write_mupix <= '0';
-          SLV_ACK_OUT      <= '1';
-        end if;
-        
-        
-      elsif SLV_WRITE_IN = '1' then
+      SLV_ACK_OUT          <= '0'; 
+      DataIn  <= (others => '0');
+      WriteEn <= '0'; 
+      if SLV_WRITE_IN = '1' then
         case SLV_ADDR_IN is
           when x"0080" =>
-            slowcontrol_reg_new <= SLV_DATA_IN;
-            start_write_mupix   <= '1';
-            busy_write_mupix    <= '1';
+               DataIn  <= SLV_DATA_IN;
+               WriteEn <= '1';
+               SLV_ACK_OUT  <= '1';
+          when x"0083" =>
+               controlConfig <= SLV_DATA_IN(15 downto 0);
+               bitstosend <= unsigned(SLV_DATA_IN(31 downto 16));
+               SLV_ACK_OUT  <= '1';
           when others =>
             SLV_UNKNOWN_ADDR_OUT <= '1';
         end case;
@@ -103,10 +317,16 @@ begin  -- Behavioral
       elsif SLV_READ_IN = '1' then
         case SLV_ADDR_IN is
           when x"0080" =>
-            SLV_DATA_OUT <= slowcontrol_reg_old;
+            SLV_DATA_OUT <= DataOut;
             SLV_ACK_OUT  <= '1';
           when x"0081" =>
-            SLV_DATA_OUT <= sout_from_mupix;
+            SLV_DATA_OUT(10 downto 0) <= crc_checksum_in & crc_checksum_out & crc_correct;
+            SLV_ACK_OUT  <= '1';
+          when x"0082" =>
+               SLV_DATA_OUT(1 downto 0) <= Empty & Full;
+            SLV_ACK_OUT  <= '1';
+          when x"0083" =>
+               SLV_DATA_OUT <= std_logic_vector(bitstosend) & controlConfig;
             SLV_ACK_OUT  <= '1';
           when others =>
             SLV_UNKNOWN_ADDR_OUT <= '1';
@@ -114,7 +334,23 @@ begin  -- Behavioral
       end if;
     end if;
   end process SLV_BUS;
+
+  crc_correct <= '1' when crc_checksum_out = crc_checksum_in else '0';
+       
+  output_pipe : process (clk) is
+  begin
+       if rising_edge(clk) then
+               if reset = '1' then
+                       mupix_ctrl_reg <= MuPixSlowControlInit;
+               else
+                       mupix_ctrl_reg <= mupix_ctrl_i;
+               end if;
+       end if;
+  end process output_pipe;
   
+  --matching to outputs        
+  mupix_ctrl <= mupix_ctrl_reg;
+
 end Behavioral;
 
 
index 1fddd75ccdcb70dbb94e3ffb3ae963c6172f8093..a0914ca88bb50fde380d83f05477794b6aaeec02 100644 (file)
@@ -31,5 +31,6 @@ package StdTypes is
     sin  : std_logic;                   --serial data in
   end record MupixSlowControl;
 
+  constant MuPixSlowControlInit : MupixSlowControl := (ck_d => '0', ck_c => '0', ld_c => '0', sin => '0');
   
 end package StdTypes;
diff --git a/mupix/tb/CRCTest.vhd b/mupix/tb/CRCTest.vhd
new file mode 100644 (file)
index 0000000..46acdc1
--- /dev/null
@@ -0,0 +1,67 @@
+-------------------------------------------------------------------------------
+--Test bench for cyclic redundancy check computation
+--We use the CRC5 polynomial f(x) = 1 + x^2 + x^ 5 used by the USB2.0 protocol
+-------------------------------------------------------------------------------
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity CRCTest is
+end entity CRCTest;
+
+architecture simulation of CRCTest is
+       
+       component CRC
+               port(
+                       clk     : in  std_logic;
+                       rst     : in  std_logic;
+                       enable  : in  std_logic;
+                       data_in : in  std_logic;
+                       crc_out : out std_logic_vector(4 downto 0)
+               );
+       end component CRC;
+       
+       signal clk : std_logic;
+       signal rst : std_logic := '0';
+       signal enable : std_logic := '0';
+       signal data_in : std_logic := '0';
+       signal crc_out : std_logic_vector(4 downto 0);
+       
+       constant clk_period : time :=  10 ns;
+       constant message : std_logic_vector(10 downto 0) := "10100111010";
+       
+begin
+       
+       dut : entity work.CRC
+               port map(
+                       clk     => clk,
+                       rst     => rst,
+                       enable  => enable,
+                       data_in => data_in,
+                       crc_out => crc_out
+               );
+       
+       clk_gen : process is
+       begin
+               clk <= '1';
+               wait for clk_period/2;
+               clk <= '0';
+               wait for clk_period/2;
+       end process clk_gen;
+       
+       stimulus : process is
+       begin
+               wait for 50 ns;
+               for i in 10 downto 0 loop
+                       enable <= '1';
+                       data_in <= message(i);
+                       wait for clk_period;
+               end loop;
+               enable <= '0';
+               assert crc_out = "11000" report "error during crc calculation" severity error;
+               
+               wait;
+       end process stimulus;
+       
+       
+end architecture simulation;
diff --git a/mupix/tb/MupixShiftReg.vhd b/mupix/tb/MupixShiftReg.vhd
new file mode 100644 (file)
index 0000000..687d67f
--- /dev/null
@@ -0,0 +1,46 @@
+------------------------------------------------------------
+--Simulation of mupix 6 shift register
+------------------------------------------------------------
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+entity MupixShiftReg is
+       generic(
+               pixeldac_shift_length : integer := 64;
+               chipdac_shift_length : integer := 16
+       );
+       port(
+               ck_c : in std_logic;
+               ck_d : in std_logic;
+               sin  : in std_logic;
+               sout_c : out std_logic;
+               sout_d : out std_logic);
+end entity MupixShiftReg;
+
+architecture RTL of MupixShiftReg is
+       
+       signal pixeldac_shift_reg : std_logic_vector(pixeldac_shift_length - 1 downto 0) := (others => '0');
+       signal chipdac_shift_reg : std_logic_vector(chipdac_shift_length - 1 downto 0) := (others => '0');
+       
+begin
+       
+       process(ck_c)
+       begin   
+               if ck_c'event and ck_c = '1' then
+                       pixeldac_shift_reg <= pixeldac_shift_reg(pixeldac_shift_length - 2 downto 0) & sin;
+               end if;
+       end process;    
+               
+    process(ck_d)
+    begin
+       if ck_d'event and ck_d = '1' then
+               chipdac_shift_reg <= chipdac_shift_reg(chipdac_shift_length - 2 downto 0) & sin;
+       end if;
+    end process;       
+       
+       sout_c <= pixeldac_shift_reg(pixeldac_shift_length - 1);
+       sout_d <= chipdac_shift_reg(chipdac_shift_length - 1);
+       
+end architecture RTL;
+
diff --git a/mupix/tb/PixCtrlTest.vhd b/mupix/tb/PixCtrlTest.vhd
new file mode 100644 (file)
index 0000000..798a27e
--- /dev/null
@@ -0,0 +1,121 @@
+library IEEE;
+use IEEE.STD_LOGIC_1164.all;
+use IEEE.numeric_std.all;
+
+use work.StdTypes.all;
+use work.TRBSimulationPkg.all;
+
+
+entity PixCtrlTest is
+end entity PixCtrlTest;
+
+architecture simulation of PixCtrlTest is
+       
+       component PixCtr
+               generic(
+                       fpga_clk_speed : integer := 1e8;
+                       spi_clk_speed  : integer := 1e4
+               );
+               port(
+                       clk                  : in  std_logic;
+                       reset                : in  std_logic;
+                       sout_c_from_mupix    : in  std_logic;
+                       sout_d_from_mupix    : in  std_logic;
+                       mupix_ctrl           : out MupixSlowControl;
+                       SLV_READ_IN          : in  std_logic;
+                       SLV_WRITE_IN         : in  std_logic;
+                       SLV_DATA_OUT         : out std_logic_vector(31 downto 0);
+                       SLV_DATA_IN          : in  std_logic_vector(31 downto 0);
+                       SLV_ADDR_IN          : in  std_logic_vector(15 downto 0);
+                       SLV_ACK_OUT          : out std_logic;
+                       SLV_NO_MORE_DATA_OUT : out std_logic;
+                       SLV_UNKNOWN_ADDR_OUT : out std_logic
+               );
+       end component PixCtr;
+       
+       component MupixShiftReg
+               generic(
+                       pixeldac_shift_length : integer := 64;
+                       chipdac_shift_length  : integer := 16
+               );
+               port(
+                       ck_c   : in  std_logic;
+                       ck_d   : in  std_logic;
+                       sin    : in  std_logic;
+                       sout_c : out std_logic;
+                       sout_d : out std_logic
+               );
+       end component MupixShiftReg;
+       
+       signal clk : std_logic;
+       signal reset : std_logic := '0';
+       signal sout_c_from_mupix : std_logic := '0';
+       signal sout_d_from_mupix : std_logic := '0';
+       signal mupix_ctrl : MupixSlowControl;
+       signal SLV_READ_IN : std_logic := '0';
+       signal SLV_WRITE_IN : std_logic := '0';
+       signal SLV_DATA_OUT : std_logic_vector(31 downto 0);
+       signal SLV_DATA_IN : std_logic_vector(31 downto 0) := (others => '0');
+       signal SLV_ADDR_IN : std_logic_vector(15 downto 0) := (others => '0');
+       signal SLV_ACK_OUT : std_logic;
+       signal SLV_NO_MORE_DATA_OUT : std_logic;
+       signal SLV_UNKNOWN_ADDR_OUT : std_logic;
+       
+       constant clk_period : time := 10 ns;
+       
+begin
+       
+       dut : entity work.PixCtr
+               generic map(
+                       fpga_clk_speed => 1e8,
+                       spi_clk_speed  => 5e7
+               )
+               port map(
+                       clk                  => clk,
+                       reset                => reset,
+                       sout_c_from_mupix    => sout_c_from_mupix,
+                       sout_d_from_mupix    => sout_d_from_mupix,
+                       mupix_ctrl           => mupix_ctrl,
+                       SLV_READ_IN          => SLV_READ_IN,
+                       SLV_WRITE_IN         => SLV_WRITE_IN,
+                       SLV_DATA_OUT         => SLV_DATA_OUT,
+                       SLV_DATA_IN          => SLV_DATA_IN,
+                       SLV_ADDR_IN          => SLV_ADDR_IN,
+                       SLV_ACK_OUT          => SLV_ACK_OUT,
+                       SLV_NO_MORE_DATA_OUT => SLV_NO_MORE_DATA_OUT,
+                       SLV_UNKNOWN_ADDR_OUT => SLV_UNKNOWN_ADDR_OUT
+               );
+               
+               mupix : entity work.MupixShiftReg
+                       generic map(
+                               pixeldac_shift_length => 64,
+                               chipdac_shift_length  => 16
+                       )
+                       port map(
+                               ck_c   => mupix_ctrl.ck_c,
+                               ck_d   => mupix_ctrl.ck_d,
+                               sin    => mupix_ctrl.sin,
+                               sout_c => sout_c_from_mupix,
+                               sout_d => sout_d_from_mupix
+                       );
+               
+       clk_gen : process is
+       begin
+               clk <= '1';
+               wait for clk_period/2;
+               clk <= '0';
+               wait for clk_period/2;
+       end process clk_gen;
+       
+       stimulus_gen : process is
+       begin
+               wait for 100 ns;
+               TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, x"004F0000",x"0083");
+               TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, x"BBBBBBBB",x"0080");
+               TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, x"AAAAAAAA",x"0080");
+               TRBRegisterWrite(SLV_WRITE_IN, SLV_DATA_IN, SLV_ADDR_IN, x"CCCCCCCC",x"0080");
+               wait;
+       end process stimulus_gen;
+       
+       
+end architecture simulation;