]> jspc29.x-matter.uni-frankfurt.de Git - trb3sc.git/commitdiff
Adding Michaels Flash-tool to template design
authorJan Michel <j.michel@gsi.de>
Thu, 13 Aug 2015 12:05:08 +0000 (14:05 +0200)
committerJan Michel <j.michel@gsi.de>
Thu, 13 Aug 2015 12:05:08 +0000 (14:05 +0200)
Adding option for backplane serdes to config

code/load_settings.vhd [new file with mode: 0644]
code/spi_master_generic.vhd [new file with mode: 0644]
code/trb3sc_tools.vhd
pinout/basic_constraints.lpf
template/config.vhd
template/trb3sc_basic.prj
template/trb3sc_basic.vhd

diff --git a/code/load_settings.vhd b/code/load_settings.vhd
new file mode 100644 (file)
index 0000000..a89f4f4
--- /dev/null
@@ -0,0 +1,667 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.trb_net_std.all;
+
+entity load_settings is
+  generic(
+    HEADER_PAGE_ADDR    : std_logic_vector(15 downto 0) := x"7000";
+    
+    -- = floor(256/6), because 256 bytes per page, 6 bytes per register
+    REGISTERS_PER_PAGE  : integer := 42
+  );
+  port(
+    CLK        : in std_logic;
+    RST        : in std_logic;
+    
+   -- the bus handler signals 
+    BUS_RX           : in  CTRLBUS_RX;
+    BUS_TX           : out CTRLBUS_TX;
+    
+    IS_ACTIVE        : out std_logic;
+    
+    BUS_MASTER_TX    : out CTRLBUS_RX;
+    BUS_MASTER_RX    : in  CTRLBUS_TX;
+    
+    SPI_MOSI         : out  std_logic;
+    SPI_MISO         : in   std_logic;
+    SPI_SCK          : out  std_logic;
+    SPI_NCS          : out  std_logic
+    
+    );
+end entity;
+
+
+
+architecture load_settings_arch of load_settings is
+
+
+
+-- -- local register addresses
+
+constant ADDR_TAKE_SPI              : std_logic_vector( 7 downto 0) := x"00";
+constant ADDR_NCS                   : std_logic_vector( 7 downto 0) := x"02";
+constant ADDR_DATA_IN               : std_logic_vector( 7 downto 0) := x"03";
+constant ADDR_DATA_OUT              : std_logic_vector( 7 downto 0) := x"04";
+constant ADDR_TRANSMISSION_COUNTER  : std_logic_vector( 7 downto 0) := x"05";
+
+constant ADDR_PAGE_SELECT           : std_logic_vector( 7 downto 0) := x"06"; 
+constant ADDR_PAGE_POS              : std_logic_vector( 7 downto 0) := x"07"; 
+constant ADDR_POP_PAGE_DATA         : std_logic_vector( 7 downto 0) := x"08";
+constant ADDR_POP_PAGE_NOBYTES      : std_logic_vector( 7 downto 0) := x"09";
+constant ADDR_FEEDBACK              : std_logic_vector( 7 downto 0) := x"0A";
+constant ADDR_PARSE_TRIGGER         : std_logic_vector( 7 downto 0) := x"0B";
+constant ADDR_SC_WRITE_ERRORS       : std_logic_vector( 7 downto 0) := x"0C";
+
+-- -- spi related signals
+
+signal take_spi          : std_logic := '0';
+signal spi_ncs_latch     : std_logic := '1';
+signal spi_ready, spi_trigger : std_logic;
+
+signal spi_data_in   : std_logic_vector(7 downto 0);
+signal spi_data_out  : std_logic_vector(7 downto 0);
+
+-- signal loopback : std_logic;
+
+signal transmission_counter : std_logic_vector(15 downto 0) := x"0000";
+
+-- page ram handling
+
+signal ram_wr               : std_logic;
+signal ram_addr             : std_logic_vector(7 downto 0);
+signal ram_dout             : std_logic_vector(7 downto 0);
+signal ram_din              : std_logic_vector(7 downto 0);
+
+signal ram_waddr, ram_raddr : std_logic_vector(7 downto 0);
+signal select_write_ram     : std_logic := '0';
+
+signal page_number          : std_logic_vector(15 downto 0);
+
+-- signals for READ_PAGE_TO_RAM process
+
+type   read_page_state_t is (IDLE,SEND_CMD,SEND_A0,SEND_A1,SEND_A2,READ_DATA,WAIT_FOR_SPI_READY,STORE_DATA);
+signal read_page_state,next_read_page_state : read_page_state_t := IDLE;
+signal trigger_read_page : std_logic;
+signal read_page_ready   : std_logic;
+signal ram_wr_pointer    : std_logic_vector (7 downto 0);
+
+-- signal read_page_init_counter : std_logic_vector (8 downto 0) := (others => '0');
+
+-- signals for the POP_PAGE_DATA process
+signal trigger_pop_page_data : std_logic;
+-- signal pop_page_word_counter : integer range 0 to 63;
+signal pop_page_position, new_pop_page_position : integer range 0 to 255 := 0;
+signal set_pop_page_position : std_logic := '0';
+signal pop_page_noBytes              : integer range 0 to 255;
+signal pop_page_noBytes_popped       : integer range 0 to 255;
+signal pop_page_noBytes_pushed       : integer range 0 to 255;
+signal pop_page_ram_delay            : integer range 0 to 2;
+type   pop_page_state_t is (IDLE,ACTIVE);
+signal pop_page_state : pop_page_state_t := IDLE;
+signal pop_page_data_word  : std_logic_vector (31 downto 0);
+signal pop_page_data_ready : std_logic;
+-- signal pop_page_rewind     : std_logic;
+
+
+
+-- signals for the PARSE_PAGE process
+
+signal parse_trigger : std_logic;
+type   parse_state_t is (
+  IDLE,
+  READ_HEADER_PAGE,
+  WAIT4PAGE,
+  WAIT4RAM,
+  VERIFY_START_STRING,
+  GET_NO_REGISTERS,
+  STORE_NO_REGISTERS,
+  GET_NO_PAGES,
+  STORE_NO_PAGES,
+  READ_NEXT_PAGE,
+  READ_SC_ADDR,
+  STORE_SC_ADDR,
+  READ_SC_VALUE,
+  STORE_SC_VALUE,
+  SEND_SC_DATA,
+  WAIT4_SC_ACK,
+  SUCCESS,FAIL);
+signal parse_state : parse_state_t := IDLE;
+signal next_parse_state : parse_state_t := IDLE;
+signal parse_counter : integer range 0 to 255;
+
+signal parse_feedback : std_logic_vector(31 downto 0) := (others=>'0');
+
+signal registers_to_read : std_logic_vector(31 downto 0);
+signal     pages_to_read : std_logic_vector(31 downto 0);
+
+signal current_sc_addr  : std_logic_vector(15 downto 0);
+signal current_sc_value : std_logic_vector(31 downto 0);
+
+signal sc_ack_timeout   : integer range 0 to 31;
+signal sc_write_errors  : std_logic_vector(31 downto 0) := (others =>'0');
+
+
+
+type header_string_t is array(7 downto 0) of std_logic_vector(7 downto 0);
+-- 53 4c 4f 57 43 54 52 4c
+-- a set of ascii characters that reads "SLOWCTRL"
+signal header_string : header_string_t := ( 0=>x"53", 1=>x"4c", 2=>x"4f", 3=>x"57", 4=>x"43", 5=>x"54", 6=>x"52", 7=>x"4c");
+
+begin
+
+
+THE_SPI_MASTER : entity work.spi_master_generic
+  generic map(
+    WORDSIZE          => 8,
+    CPOL              => '0',
+    CPHA              => '0',
+    SPI_CLOCK_DIVIDER => 10
+  )
+  port map(
+    MOSI => SPI_MOSI,
+    MISO => SPI_MISO,
+    SCK  => SPI_SCK,
+    
+    CLK => CLK,
+    RST => RST,
+    
+    DATA_OUT => spi_data_out,
+    DATA_IN  => spi_data_in,
+    
+    TRANSFER_COMPLETE => spi_ready,
+    TRIGGER_TRANSFER  => spi_trigger
+  );
+
+THE_PAGE_RAM : entity work.ram
+  generic map(
+    depth => 8,
+    width => 8
+  )
+  port map(
+    CLK  => CLK,
+    wr   => ram_wr,
+    a    => ram_addr, 
+    dout => ram_dout, 
+    din  => ram_din
+  );
+
+
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+-- Memory Interface
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+
+IS_ACTIVE <= take_spi;
+SPI_NCS   <= spi_ncs_latch;
+
+-- multiplexed access to the page ram address input
+ram_addr <= ram_waddr when (select_write_ram = '1') else ram_raddr;
+
+-- POP_PAGE_DATA : process begin
+-- -- read 32 bit from the page, to send it over trb_net
+--   wait until rising_edge(CLK);
+--   
+--   pop_page_data_ready <= '0';
+--   
+--   case pop_page_state is
+--     when IDLE =>
+--       ram_raddr <= x"00";
+--       pop_page_byte_counter <= 0;
+--       
+--       if pop_page_rewind = '1' then
+--         pop_page_word_counter <= 0;
+--       end if;
+--       
+--       if trigger_pop_page_data = '1' then
+--         pop_page_state <= READ_BYTE;
+--       end if;
+--       
+--     when READ_BYTE =>
+--       ram_raddr <= std_logic_vector(to_unsigned(pop_page_byte_counter + pop_page_word_counter*4,8));
+--       pop_page_state <= WAIT4RAM;
+--     when WAIT4RAM =>
+--       pop_page_state <= PUSH_BYTE;
+--     when PUSH_BYTE =>
+--       pop_page_data_word( (pop_page_byte_counter*8 + 7) downto (pop_page_byte_counter*8) ) <= ram_dout;
+--       if pop_page_byte_counter < 3 then
+--         pop_page_state <= READ_BYTE;
+--         pop_page_byte_counter <= pop_page_byte_counter +1;
+--       else -- pushed last byte
+--         pop_page_state <= IDLE;
+--         pop_page_word_counter <= pop_page_word_counter +1;
+--         pop_page_data_ready <= '1';
+--       end if;
+--   end case;
+--   
+--   if RST = '1' then
+--     pop_page_state <= IDLE;
+--   end if;
+-- end process;
+
+POP_PAGE_DATA : process begin
+  -- read n byte from the ram to a 32 bit output register "pop_page_data_word", new bytes get shifted in from the right
+  wait until rising_edge(CLK);
+  pop_page_data_ready <= '0';
+  
+  case pop_page_state is
+    when IDLE =>
+      
+      pop_page_ram_delay <= 0;
+      
+      if set_pop_page_position = '1' then
+        pop_page_position <= new_pop_page_position;
+      end if;
+      
+      if trigger_pop_page_data = '1' then
+        pop_page_state <= ACTIVE;
+        pop_page_noBytes_popped  <= 0;
+        pop_page_noBytes_pushed  <= 0;
+        pop_page_data_word <= (others => '0'); -- reset output register
+      end if;
+      
+    when ACTIVE =>
+      
+      ram_raddr <= std_logic_vector(to_unsigned(pop_page_position,8)); -- give address to ram
+      
+      if pop_page_noBytes_popped < pop_page_noBytes  then
+        pop_page_position <= pop_page_position +1; -- increment ram pointer
+        pop_page_noBytes_popped <= pop_page_noBytes_popped +1;
+      end if;
+      
+      -- set first addr when ram_delay = 0, do nothing when ram_delay = 1, use ram_dout when ram_delay = 2
+      if pop_page_ram_delay < 2 then
+        pop_page_ram_delay <= pop_page_ram_delay +1;
+      else -- now ram is ready
+        -- shift old content to the left
+        pop_page_data_word(31 downto 8) <= pop_page_data_word(23 downto 0);
+        -- shift in new byte from the ram
+        pop_page_data_word(7 downto 0) <= ram_dout;
+        pop_page_noBytes_pushed <= pop_page_noBytes_pushed +1;
+        
+        if pop_page_noBytes_pushed = (pop_page_noBytes -1) then -- this is the last byte we want
+          pop_page_state <= IDLE;
+          pop_page_data_ready <= '1';
+        end if;
+      end if;
+  end case;
+  
+  if RST = '1' then
+    pop_page_state <= IDLE;
+  end if;
+end process;
+
+
+
+READ_PAGE_TO_RAM : process begin
+-- read a complete page from flash and store it in the page ram
+  wait until rising_edge(CLK);
+  
+  spi_trigger <= '0';
+  ram_wr <= '0';
+  read_page_ready <= '0';
+  select_write_ram <= '0'; -- free access to ram_addr again
+  
+  case read_page_state is
+  
+    when IDLE =>
+      spi_ncs_latch <= '1';
+      if trigger_read_page = '1' then
+        read_page_state <= SEND_CMD;
+        spi_ncs_latch <= '0';
+      end if;
+      
+    when WAIT_FOR_SPI_READY =>
+      if spi_ready = '1' then
+        read_page_state <= next_read_page_state;
+      end if;
+    
+    when SEND_CMD  =>
+      spi_data_in   <= x"03"; -- the read command for the flash
+      spi_trigger   <= '1';
+      read_page_state      <= WAIT_FOR_SPI_READY;
+      next_read_page_state <= SEND_A0;
+      
+    when SEND_A0   =>
+      spi_data_in   <= page_number(15 downto 8);
+      spi_trigger   <= '1';
+      read_page_state      <= WAIT_FOR_SPI_READY;
+      next_read_page_state <= SEND_A1;
+      
+    when SEND_A1   =>
+      spi_data_in   <= page_number(7 downto 0);
+      spi_trigger   <= '1';
+      read_page_state      <= WAIT_FOR_SPI_READY;
+      next_read_page_state <= SEND_A2;
+      
+    when SEND_A2   =>
+      spi_data_in   <= x"00";
+      spi_trigger   <= '1';
+      read_page_state      <= WAIT_FOR_SPI_READY;
+      next_read_page_state <= READ_DATA;
+      ram_wr_pointer       <= x"00"; -- go to beginning of ram
+      
+    when READ_DATA =>
+      spi_data_in   <= x"00";
+      spi_trigger   <= '1';
+      read_page_state      <= WAIT_FOR_SPI_READY;
+      next_read_page_state <= STORE_DATA;
+      
+    when STORE_DATA =>
+      select_write_ram <= '1'; -- take exclusive access to ram_addr
+      ram_wr  <= '1';
+      ram_din <= spi_data_out;
+      ram_waddr <= ram_wr_pointer;
+      -- increment ram address
+      if unsigned(ram_wr_pointer) < 255 then
+        ram_wr_pointer <= std_logic_vector(unsigned(ram_wr_pointer)+1);
+        read_page_state <= READ_DATA;
+      else -- we just read in the last byte
+        read_page_ready  <= '1';
+        read_page_state  <= IDLE;
+      end if;
+      
+  
+  end case;
+  
+  if RST = '1' then
+    read_page_state <= IDLE;
+  end if;
+  
+  
+--   -- init ram with bogus data
+--   
+--   if unsigned(read_page_init_counter) < 256 then
+--     select_write_ram <= '1';
+--     read_page_init_counter <= std_logic_vector(unsigned(read_page_init_counter)+1);
+--     ram_wr <= '1';
+--     ram_waddr <= read_page_init_counter(7 downto 0);
+--     ram_din   <= read_page_init_counter(7 downto 0);
+--   end if;
+  
+  
+
+end process;
+
+
+PARSE : process begin
+  wait until rising_edge(CLK);
+  
+  trigger_read_page <= '0';
+  trigger_pop_page_data <= '0';
+  set_pop_page_position <= '0';
+  
+  BUS_MASTER_TX.data    <= (others => '0');
+  BUS_MASTER_TX.addr    <= (others => '0');
+  BUS_MASTER_TX.write   <=            '0' ;
+  BUS_MASTER_TX.read    <=            '0' ;
+  BUS_MASTER_TX.timeout <=            '0' ;
+   
+  case parse_state is
+  
+    when IDLE =>
+      take_spi <= '0';
+      if parse_trigger = '1' then
+        parse_state <= READ_HEADER_PAGE;
+        take_spi <= '1';
+        sc_write_errors <= (others => '0');
+      end if;
+      
+    when READ_HEADER_PAGE =>
+      page_number <= HEADER_PAGE_ADDR;
+      trigger_read_page <= '1';
+      parse_state <= WAIT4PAGE;
+      parse_counter <= 0;
+      next_parse_state <= VERIFY_START_STRING;
+
+    when WAIT4PAGE =>
+      if read_page_ready = '1' then
+        parse_state <= next_parse_state;
+      end if;
+
+    when VERIFY_START_STRING =>
+      parse_state <= WAIT4RAM;
+      next_parse_state <= VERIFY_START_STRING;
+      
+     
+     
+      if parse_counter = 0 then
+        pop_page_noBytes <= 1;
+        new_pop_page_position <= 0;
+        set_pop_page_position <= '1';
+      else
+        if parse_counter = 8 then
+          -- so far everything has evaluated fine
+          parse_state <= GET_NO_REGISTERS;
+        end if;
+        -- if one of the characters is not there, goto FAIL
+        if not(pop_page_data_word(7 downto 0) = header_string(parse_counter-1)) then
+          parse_state <= FAIL;
+        end if;
+      end if;
+      
+      if parse_counter < 8 then
+        trigger_pop_page_data <= '1';
+        parse_counter <= parse_counter +1;
+      end if;
+      
+    when WAIT4RAM =>
+      if pop_page_data_ready = '1' then
+        parse_state <= next_parse_state;
+      end if;
+      
+    when GET_NO_REGISTERS =>
+      pop_page_noBytes <= 4;
+      trigger_pop_page_data <= '1';
+      
+      next_parse_state <= STORE_NO_REGISTERS;
+      parse_state <= WAIT4RAM;
+    
+    when STORE_NO_REGISTERS =>
+      registers_to_read <= pop_page_data_word;
+      parse_state <= GET_NO_PAGES;
+    
+    when GET_NO_PAGES =>
+      trigger_pop_page_data <= '1';
+      
+      next_parse_state <= STORE_NO_PAGES;
+      parse_state <= WAIT4RAM;
+      
+    when STORE_NO_PAGES =>
+      pages_to_read <= pop_page_data_word;
+      parse_state <= READ_NEXT_PAGE;
+      
+      
+    when READ_NEXT_PAGE =>
+    
+      if unsigned(pages_to_read) > 0 then
+        page_number <= std_logic_vector(unsigned(page_number)+1);
+        trigger_read_page <= '1';
+        parse_state <= WAIT4PAGE;
+        parse_counter <= 0;
+        
+        -- reset page read position
+        new_pop_page_position <= 0;
+        set_pop_page_position <= '1';
+        pages_to_read <= std_logic_vector(unsigned(pages_to_read)-1);
+        
+        next_parse_state <= READ_SC_ADDR;
+      else
+        parse_state <= SUCCESS;
+      end if;
+      
+    when READ_SC_ADDR =>
+      pop_page_noBytes <= 2;
+      trigger_pop_page_data <= '1';
+      next_parse_state <= STORE_SC_ADDR;
+      parse_state <= WAIT4RAM;
+      
+    when STORE_SC_ADDR =>
+      current_sc_addr <= pop_page_data_word(15 downto 0);
+      parse_state <= READ_SC_VALUE;
+      
+    when READ_SC_VALUE =>
+      pop_page_noBytes <= 4;
+      trigger_pop_page_data <= '1';
+      next_parse_state <= STORE_SC_VALUE;
+      parse_state <= WAIT4RAM;
+      
+    when STORE_SC_VALUE =>
+      current_sc_value <= pop_page_data_word;
+      parse_state <= SEND_SC_DATA;
+      registers_to_read <= std_logic_vector(unsigned(registers_to_read)-1);
+      
+    when SEND_SC_DATA =>
+      BUS_MASTER_TX.data    <= current_sc_value;
+      BUS_MASTER_TX.addr    <= current_sc_addr;
+      BUS_MASTER_TX.write   <= '1';
+      parse_state <= WAIT4_SC_ACK;
+      sc_ack_timeout <= 31;
+      
+    when WAIT4_SC_ACK =>
+      if sc_ack_timeout = 0 
+        or BUS_MASTER_RX.ack     = '1'   
+        or BUS_MASTER_RX.wack    = '1'   
+        or BUS_MASTER_RX.rack    = '1' 
+        or BUS_MASTER_RX.nack    = '1' 
+        or BUS_MASTER_RX.unknown = '1' then
+        
+        -- timeout or error
+        if sc_ack_timeout = 0 
+          or BUS_MASTER_RX.rack    = '1'
+          or BUS_MASTER_RX.nack    = '1'
+          or BUS_MASTER_RX.unknown = '1' then
+          sc_write_errors <= std_logic_vector(unsigned(sc_write_errors)+1);
+        end if;
+      
+        parse_counter <= parse_counter +1;
+        parse_state   <= READ_SC_ADDR;
+        
+        if parse_counter >= (REGISTERS_PER_PAGE -1) then
+          if unsigned(pages_to_read) > 0 then
+            parse_state <= READ_NEXT_PAGE;
+          else
+            parse_state <= SUCCESS;
+          end if;
+        end if;
+        
+        if unsigned(registers_to_read) = 0 then
+          parse_state <= SUCCESS;
+        end if;
+        
+      else
+        sc_ack_timeout <= sc_ack_timeout -1;
+      end if;
+      
+    when SUCCESS =>
+      parse_state <= IDLE;
+      parse_feedback <= current_sc_addr & current_sc_value(15 downto 0);
+    
+    when FAIL => 
+      parse_state <= IDLE;
+      parse_feedback <= x"000000F0";
+  
+  end case;
+  
+  if RST = '1' then
+    parse_state <= IDLE;
+    sc_write_errors <= (others => '0');
+  end if;
+  
+end process;
+
+
+sync : process begin
+  wait until rising_edge(CLK);
+  BUS_TX.data <= (others => '0'); -- default 
+  BUS_TX.nack <= '0';
+  BUS_TX.unknown <= '0';
+  BUS_TX.ack <= '0';
+  
+--   spi_trigger <= '0';
+--   trigger_read_page <= '0';
+--   trigger_pop_page_data <= '0';
+--   set_pop_page_position <= '0';
+  parse_trigger <= '0';
+  
+  if( BUS_RX.write = '1') then -- got a write command
+    BUS_TX.ack <= '1';    
+    
+    case BUS_RX.addr(7 downto 0) is
+      when ADDR_TAKE_SPI =>
+--         take_spi <= BUS_RX.data(0);
+      when ADDR_DATA_IN =>
+--         spi_data_in <= BUS_RX.data(7 downto 0);
+--         spi_trigger <= '1';
+      when ADDR_NCS =>
+--         spi_ncs_latch <= BUS_RX.data(0);
+        
+      when ADDR_PAGE_SELECT =>
+--         page_number <= BUS_RX.data(15 downto 0);
+--         trigger_read_page <= '1';
+      when ADDR_PAGE_POS =>
+--         set_pop_page_position <= '1';
+--         new_pop_page_position <= to_integer(unsigned(BUS_RX.data(7 downto 0)));
+      when ADDR_POP_PAGE_NOBYTES =>
+--         pop_page_noBytes <= to_integer(unsigned(BUS_RX.data(7 downto 0)));
+      when ADDR_PARSE_TRIGGER =>
+        parse_trigger <= '1';
+      when others =>
+        BUS_TX.ack <= '0';
+        BUS_TX.unknown <= '1';
+    end case;
+  end if;
+  
+  if( BUS_RX.read = '1') then -- got a read command
+    BUS_TX.ack <= '1';
+    BUS_TX.data(15 downto 0) <= (others => '0');
+    case BUS_RX.addr(7 downto 0) is
+      when ADDR_TAKE_SPI =>
+        BUS_TX.data(0) <= take_spi;
+      when ADDR_DATA_OUT =>
+        BUS_TX.data(7 downto 0) <= spi_data_out;
+      when ADDR_DATA_IN =>
+        BUS_TX.data(7 downto 0) <= spi_data_in;
+      when ADDR_TRANSMISSION_COUNTER =>
+        BUS_TX.data(15 downto 0) <= transmission_counter;
+      when ADDR_NCS =>
+        BUS_TX.data(0) <= spi_ncs_latch;
+      when ADDR_PAGE_SELECT =>
+        BUS_TX.data(15 downto 0) <= page_number;
+      when ADDR_POP_PAGE_NOBYTES =>
+        BUS_TX.data(7 downto 0) <= std_logic_vector(to_unsigned(pop_page_noBytes,8));
+      when ADDR_POP_PAGE_DATA =>
+--         trigger_pop_page_data <= '1';
+        BUS_TX.ack <= '0'; -- don't ack yet, wait for pop_page_data_ready
+      when ADDR_FEEDBACK =>
+        BUS_TX.data <= parse_feedback;
+      when ADDR_SC_WRITE_ERRORS =>
+        BUS_TX.data <= sc_write_errors;
+      -- DEFAULT --
+      when others =>
+        BUS_TX.ack <= '0';
+        BUS_TX.unknown <= '1';        
+    end case;
+  end if;
+  
+  if pop_page_data_ready = '1' then
+    BUS_TX.data(31 downto 0) <= pop_page_data_word;
+    BUS_TX.ack <= '1';
+  end if;
+  
+  if RST = '1' then
+    transmission_counter <= (others => '0');
+  end if;
+  
+  if(spi_ready = '1') then 
+    transmission_counter <= std_logic_vector(unsigned(transmission_counter) +1);
+  end if;
+  
+  
+end process;
+  
+
+end architecture;
+
diff --git a/code/spi_master_generic.vhd b/code/spi_master_generic.vhd
new file mode 100644 (file)
index 0000000..576a124
--- /dev/null
@@ -0,0 +1,174 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+use trb_net_std.all;
+
+
+
+entity spi_master_generic is
+  generic(
+    -- default settings are:
+    -- wordsize 8 bits, sck idle=LO
+    -- data is valid at rising edges
+    WORDSIZE          : integer   := 8;
+    CPOL              : std_logic := '0';
+    CPHA              : std_logic := '0';
+    SPI_CLOCK_DIVIDER : integer   := 5 -- 100 MHz/5 = 20 MHz
+  );
+  port(
+    CLK        : in std_logic;
+    RST        : in std_logic;
+    
+    DATA_OUT          : out  std_logic_vector(WORDSIZE-1 downto 0);
+    DATA_IN           : in   std_logic_vector(WORDSIZE-1 downto 0);
+    TRANSFER_COMPLETE : out std_logic;
+    TRIGGER_TRANSFER  : in std_logic;
+    
+    MOSI       : out std_logic;
+    MISO       : in  std_logic;
+    SCK        : out std_logic
+    
+    );
+end entity;
+
+
+
+architecture spi_master_generic_arch of spi_master_generic is
+
+signal sck_rise,sck_fall                     : std_logic;
+signal sck_raw,sck_raw_buf,sck_gate          : std_logic := '0';
+signal transition_strobe, sample_strobe, sample_strobe_buf  : std_logic;
+signal trigger_transfer_latch                : std_logic := '0';
+
+
+-- sck generation
+signal bit_counter              : integer range 0 to WORDSIZE-1 := 0;
+signal sck_clock_div_counter    : integer range 0 to (SPI_CLOCK_DIVIDER-1) :=0;
+
+
+-- transfer state machine
+type   transfer_state_t is (IDLE,TRANSFER);
+signal transfer_state : transfer_state_t := IDLE;
+
+-- internal data transmission
+signal data_out_buffer   : std_logic_vector((WORDSIZE-1) downto 0);
+signal data_in_buffer    : std_logic_vector((WORDSIZE-1) downto 0);
+signal data_out_ready    : std_logic;
+
+
+
+begin
+
+
+----------------------------
+-- SCK Generation
+----------------------------
+
+generate_sck : process begin
+
+-- Generate a square wave with frequency CLK/SPI_CLOCK_DIVIDER
+-- more precisely, generate strobes at the rising and falling
+-- edges of such a square wave
+
+  wait until rising_edge(CLK);
+  
+  sck_rise    <= '0';
+  sck_fall    <= '0';
+  sck_raw_buf <= sck_raw; -- delayed by one CLK cycle
+  
+  sck_clock_div_counter <= sck_clock_div_counter + 1;
+  if sck_clock_div_counter >= (SPI_CLOCK_DIVIDER -1) then
+    sck_clock_div_counter <= 0;
+  end if;
+  
+  if sck_clock_div_counter = 0 then
+    sck_rise <= '1';
+    sck_raw  <= '1';
+  end if;
+  
+  if sck_clock_div_counter = (SPI_CLOCK_DIVIDER/2) then
+    sck_fall <= '1';
+    sck_raw  <= '0';
+  end if;
+  
+end process;
+
+-- multiplexers to accomodate different SPI modes
+transition_strobe  <= sck_rise when (CPHA = '1') else sck_fall;
+sample_strobe      <= sck_fall when (CPHA = '1') else sck_rise;
+
+
+transfer_state_machine : process begin
+  wait until rising_edge(CLK);
+  trigger_transfer_latch <= trigger_transfer_latch or TRIGGER_TRANSFER; -- latch transfer trigger
+  
+  case transfer_state is
+    when IDLE =>
+      -- start transfer at next full sck cycle
+      if (transition_strobe = '1') and (trigger_transfer_latch = '1') then 
+        sck_gate <= '1';
+        transfer_state <= TRANSFER;
+        trigger_transfer_latch <= '0'; -- clear your trigger memory
+      end if;
+    when TRANSFER =>
+      if transition_strobe = '1' then
+        if bit_counter < (WORDSIZE-1) then
+          -- after processing bits 0-(WORDSIZE-2)
+          bit_counter <= bit_counter + 1;
+        else
+          -- after last bit (WORDSIZE-1)
+          bit_counter <= 0;
+          sck_gate <= '0';
+          transfer_state <= IDLE;
+        end if;
+      end if;
+  end case;
+  
+  if RST = '1' then
+    transfer_state <= IDLE;
+    bit_counter <= 0 ;
+    sck_gate <= '0';
+  end if;
+
+end process;
+
+
+sample_and_hold_data_in : process begin
+  wait until rising_edge(CLK);
+  if TRIGGER_TRANSFER = '1' then
+    data_in_buffer <= DATA_IN;
+  end if;
+end process;
+
+
+rx_process : process begin
+  wait until rising_edge(CLK);
+  sample_strobe_buf <= sample_strobe;
+  data_out_ready <= '0';
+  TRANSFER_COMPLETE <= '0';
+  
+  if sample_strobe_buf = '1' then
+    data_out_buffer( (WORDSIZE-1) - bit_counter ) <= MISO;
+    if bit_counter = (WORDSIZE-1) then
+      data_out_ready <= '1';
+    end if;
+  end if;
+  
+  if data_out_ready = '1' then
+    DATA_OUT          <= data_out_buffer;
+    TRANSFER_COMPLETE <= '1';
+  end if;
+  
+end process;
+
+sync_output : process begin
+  wait until rising_edge(CLK);
+  
+  SCK  <= CPOL xor ( sck_raw_buf and sck_gate ); -- accomodate for reversed clock polarity
+  MOSI <= data_in_buffer( (WORDSIZE-1) - bit_counter ) and sck_gate;
+
+end process;
+  
+  
+end architecture;
\ No newline at end of file
index 965bb0813906270fc54503e286b1d1f47a787103..24286b5d06f745f609bae27aacda6e13937dce33 100644 (file)
@@ -46,6 +46,11 @@ entity trb3sc_tools is
     BUS_RX     : in  CTRLBUS_RX;
     BUS_TX     : out CTRLBUS_TX;
     
+    --Control master for default settings
+    BUS_MASTER_IN  : in CTRLBUS_TX;
+    BUS_MASTER_OUT : out CTRLBUS_RX;
+    BUS_MASTER_ACTIVE : out std_logic;
+    
     DEBUG_OUT  : out std_logic_vector(31 downto 0)
     );
 end entity;
@@ -54,14 +59,19 @@ end entity;
 
 architecture trb3sc_tools_arch of trb3sc_tools is
 
-signal busflash_rx, busspi_rx, busadc_rx, bussed_rx, busuart_rx : CTRLBUS_RX;
-signal busflash_tx, busspi_tx, busadc_tx, bussed_tx, busuart_tx : CTRLBUS_TX;
+signal busflash_rx, busspi_rx, busadc_rx, bussed_rx, busuart_rx, busflashset_rx : CTRLBUS_RX;
+signal busflash_tx, busspi_tx, busadc_tx, bussed_tx, busuart_tx, busflashset_tx : CTRLBUS_TX;
 
 signal spi_sdi, spi_sdo, spi_sck : std_logic;
 signal spi_cs                    : std_logic_vector(15 downto 0);
 signal lcd_cs, lcd_dc, lcd_mosi, lcd_sck, lcd_rst : std_logic;
 signal uart_rx, uart_tx          : std_logic;
 
+signal flashset_active : std_logic;
+signal flash_cs_i, flash_clk_i, flash_out_i  : std_logic;
+signal flash_cs_s, flash_clk_s, flash_out_s  : std_logic;
+     
+
 begin
 
 ---------------------------------------------------------------------------
@@ -69,9 +79,9 @@ begin
 ---------------------------------------------------------------------------
   THE_BUS_HANDLER : entity work.trb_net16_regio_bus_handler_record
     generic map(
-      PORT_NUMBER      => 5,
-      PORT_ADDRESSES   => (0 => x"0000", 1 => x"0400", 2 => x"0480", 3 => x"0500", 4 => x"0600", others => x"0000"),
-      PORT_ADDR_MASK   => (0 => 9,       1 => 5,       2 => 5,       3 => 1,       4 => 2,       others => 0),
+      PORT_NUMBER      => 6,
+      PORT_ADDRESSES   => (0 => x"0000", 1 => x"0400", 2 => x"0480", 3 => x"0500", 4 => x"0600", 5 => x"0180", others => x"0000"),
+      PORT_ADDR_MASK   => (0 => 9,       1 => 5,       2 => 5,       3 => 1,       4 => 2,       5 => 4,       others => 0),
       PORT_MASK_ENABLE => 1
       )
     port map(
@@ -86,11 +96,13 @@ begin
       BUS_RX(2) => busadc_rx,
       BUS_RX(3) => bussed_rx,
       BUS_RX(4) => busuart_rx,
+      BUS_RX(5) => busflashset_rx,
       BUS_TX(0) => busflash_tx,
       BUS_TX(1) => busspi_tx,
       BUS_TX(2) => busadc_tx,
       BUS_TX(3) => bussed_tx,
       BUS_TX(4) => busuart_tx,
+      BUS_TX(5) => busflashset_tx,
       
       STAT_DEBUG => open
       );
@@ -111,12 +123,43 @@ begin
       DO_REBOOT_IN         => REBOOT_IN,     
       PROGRAMN             => PROGRAMN,
       
-      SPI_CS_OUT           => FLASH_CS,
-      SPI_SCK_OUT          => FLASH_CLK,
-      SPI_SDO_OUT          => FLASH_OUT,
+      SPI_CS_OUT           => flash_cs_i,
+      SPI_SCK_OUT          => flash_clk_i,
+      SPI_SDO_OUT          => flash_out_i,
       SPI_SDI_IN           => FLASH_IN
       );
 
+      
+---------------------------------------------------------------------------
+-- Load Settings from Flash
+---------------------------------------------------------------------------      
+THE_FLASH_REGS : entity work.load_settings
+  port map(
+    CLK        => CLK,
+    RST        => RESET,
+    
+   -- the bus handler signals 
+    BUS_RX          => busflashset_rx,
+    BUS_TX          => busflashset_tx,
+    
+    IS_ACTIVE       => flashset_active,
+    
+    BUS_MASTER_TX   => BUS_MASTER_OUT,
+    BUS_MASTER_RX   => BUS_MASTER_IN,
+    
+    SPI_MOSI        => flash_out_s,
+    SPI_MISO        => FLASH_IN,
+    SPI_SCK         => flash_clk_s,
+    SPI_NCS         => flash_cs_s
+    
+    );      
+
+  BUS_MASTER_ACTIVE <= flashset_active;
+  FLASH_CS  <= flash_cs_i  when flashset_active = '0' else flash_cs_s;
+  FLASH_CLK <= flash_clk_i when flashset_active = '0' else flash_clk_s;
+  FLASH_OUT <= flash_out_i when flashset_active = '0' else flash_out_s;
+    
 ---------------------------------------------------------------------------
 -- SED Detection
 ---------------------------------------------------------------------------
index 785d3858b1c342de450610c3c306a159a7c61894..9692b0c78f32b97adfcf685b106ff95fe5422741 100644 (file)
@@ -46,6 +46,7 @@ REGION "REGION_SPI" "R19C150D" 20 20 DEVSIZE;
 LOCATE UGROUP "THE_TOOLS/THE_SPI_RELOAD/THE_SPI_MASTER/SPI_group" REGION "REGION_SPI" ;
 LOCATE UGROUP "THE_TOOLS/THE_SPI_RELOAD/THE_SPI_MEMORY/SPI_group" REGION "REGION_SPI" ;
 
+LOCATE COMP          "THE_MEDIA_INTERFACE/gen_pcs0.THE_SERDES/PCSD_INST" SITE "PCSA" ;
 LOCATE COMP          "THE_MEDIA_INTERFACE/gen_pcs3.THE_SERDES/PCSD_INST" SITE "PCSB" ;
 REGION               "MEDIA_UPLINK" "R102C55D" 13 50;
 LOCATE UGROUP        "THE_MEDIA_INTERFACE/media_interface_group" REGION "MEDIA_UPLINK" ;
index 2f2ec1f548353f84f9a5ca4622be7494fa0e745b..abe29a010ad33fa16b083a93261e0c060c8aee49 100644 (file)
@@ -21,7 +21,9 @@ package config is
     constant INIT_ADDRESS           : std_logic_vector := x"F3CC";
     constant BROADCAST_SPECIAL_ADDR : std_logic_vector := x"60";
    
-
+--set to 0 for backplane serdes, set to 3 for front SFP serdes
+    constant SERDES_NUM             : integer := 0;
+   
     constant INCLUDE_UART           : integer  := c_YES;
     constant INCLUDE_SPI            : integer  := c_YES;
     constant INCLUDE_LCD            : integer  := c_YES;
index 00d82b390e3c5da08fdf286ad1250d5e8bb7d400..dbda519d342ea44f034ae23313f65af497ba8bca 100644 (file)
@@ -112,6 +112,8 @@ add_file -vhdl -lib work "../../trbnet/special/uart.vhd"
 add_file -vhdl -lib work "../../trbnet/special/uart_rec.vhd"
 add_file -vhdl -lib work "../../trbnet/special/uart_trans.vhd"
 add_file -vhdl -lib work "../../trbnet/special/spi_ltc2600.vhd"
+add_file -vhdl -lib work "../../trb3sc/code/load_settings.vhd"
+add_file -vhdl -lib work "../../trb3sc/code/spi_master_generic.vhd"
 
 #SlowControl files
 add_file -vhdl -lib work "../../trbnet/trb_net16_regio_bus_handler.vhd"
index c349bec70c2503985be3768d8c18a12ee07bf0d5..200f19f087898d5b46fd82a7b85203b86fea6877 100644 (file)
@@ -128,23 +128,22 @@ architecture trb3sc_arch of trb3sc_basic is
   signal readout_rx        : READOUT_RX;
   signal readout_tx        : readout_tx_array_t(0 to 0);
 
-  signal ctrlbus_rx, bussci_rx, bustools_rx, bustc_rx  : CTRLBUS_RX;
-  signal ctrlbus_tx, bussci_tx, bustools_tx, bustc_tx  : CTRLBUS_TX;
+  signal ctrlbus_rx, bussci_rx, bustools_rx, bustc_rx, bus_master_out, handlerbus_rx  : CTRLBUS_RX;
+  signal ctrlbus_tx, bussci_tx, bustools_tx, bustc_tx, bus_master_in   : CTRLBUS_TX;
   
   signal common_stat_reg   : std_logic_vector(std_COMSTATREG*32-1 downto 0) := (others => '0');
   signal common_ctrl_reg   : std_logic_vector(std_COMCTRLREG*32-1 downto 0);
   
   signal sed_error_i       : std_logic;
   signal clock_select      : std_logic;
+  signal bus_master_active : std_logic;
   
   signal spi_cs, spi_mosi, spi_miso, spi_clk : std_logic_vector(15 downto 0);
 
   signal timer    : TIMERS;
   signal lcd_data : std_logic_vector(511 downto 0);
 
-
-  signal timer             : TIMERS;
-  signal lcd_data          : std_logic_vector(511 downto 0);
+  signal sfp_los_i, sfp_txdis_i, sfp_prsnt_i : std_logic;
   
   attribute syn_keep of GSR_N     : signal is true;
   attribute syn_preserve of GSR_N : signal is true;  
@@ -192,7 +191,7 @@ THE_CLOCK_RESET :  entity work.clock_reset_handler
 
   THE_MEDIA_INTERFACE : entity work.med_ecp3_sfp_sync
     generic map(
-      SERDES_NUM    => 3,
+      SERDES_NUM    => SERDES_NUM,
       IS_SYNC_SLAVE => c_YES
       )
     port map(
@@ -213,9 +212,9 @@ THE_CLOCK_RESET :  entity work.clock_reset_handler
       --SFP Connection
       SD_REFCLK_P_IN => '0',
       SD_REFCLK_N_IN => '0',
-      SD_PRSNT_N_IN  => SFP_MOD0(1),
-      SD_LOS_IN      => SFP_LOS(1),
-      SD_TXDIS_OUT   => SFP_TX_DIS(1),
+      SD_PRSNT_N_IN  => sfp_prsnt_i,
+      SD_LOS_IN      => sfp_los_i,
+      SD_TXDIS_OUT   => sfp_txdis_i,
       --Control Interface
       BUS_RX         => bussci_rx,
       BUS_TX         => bussci_tx,
@@ -225,8 +224,17 @@ THE_CLOCK_RESET :  entity work.clock_reset_handler
       );
 
   SFP_TX_DIS(0) <= '1';
-
-
+  gen_sfp_con : if SERDES_NUM = 3 generate
+    sfp_los_i   <= SFP_LOS(1);
+    sfp_prsnt_i <= SFP_MOD0(1); 
+    SFP_TX_DIS(1) <= sfp_txdis_i;
+  end generate;  
+  gen_bpl_con : if SERDES_NUM = 0 generate
+    sfp_los_i   <= BACK_GPIO(1);
+    sfp_prsnt_i <= BACK_GPIO(1); 
+    BACK_GPIO(0) <= sfp_txdis_i;
+  end generate;  
+  
 ---------------------------------------------------------------------------
 -- Endpoint
 ---------------------------------------------------------------------------
@@ -267,6 +275,7 @@ THE_ENDPOINT : entity work.trb_net16_endpoint_hades_full_handler_record
     REGIO_COMMON_CTRL_REG_OUT    => common_ctrl_reg,  --0x20
     BUS_RX                       => ctrlbus_rx,
     BUS_TX                       => ctrlbus_tx,
+
     ONEWIRE_INOUT                => TEMPSENS,
     --Timing registers
     TIMERS_OUT                   => timer
@@ -275,6 +284,9 @@ THE_ENDPOINT : entity work.trb_net16_endpoint_hades_full_handler_record
 ---------------------------------------------------------------------------
 -- Bus Handler
 ---------------------------------------------------------------------------
+
+  handlerbus_rx <= ctrlbus_rx when bus_master_active = '0' else bus_master_out;
+
   THE_BUS_HANDLER : entity work.trb_net16_regio_bus_handler_record
     generic map(
       PORT_NUMBER      => 3,
@@ -286,7 +298,7 @@ THE_ENDPOINT : entity work.trb_net16_endpoint_hades_full_handler_record
       CLK   => clk_sys,
       RESET => reset_i,
 
-      REGIO_RX  => ctrlbus_rx,
+      REGIO_RX  => handlerbus_rx,
       REGIO_TX  => ctrlbus_tx,
       
       BUS_RX(0) => bustools_rx, --Flash, SPI, UART, ADC, SED
@@ -333,7 +345,10 @@ THE_ENDPOINT : entity work.trb_net16_endpoint_hades_full_handler_record
       --Slowcontrol
       BUS_RX     => bustools_rx,
       BUS_TX     => bustools_tx,
-      
+      --Control master for default settings
+      BUS_MASTER_IN  => ctrlbus_tx,
+      BUS_MASTER_OUT => bus_master_out,
+      BUS_MASTER_ACTIVE => bus_master_active,      
       DEBUG_OUT  => open
       );