]> jspc29.x-matter.uni-frankfurt.de Git - vhdlbasics.git/commitdiff
add first files to generic VHDL repo
authorJan Michel <j.michel@gsi.de>
Tue, 18 Jul 2017 16:35:13 +0000 (18:35 +0200)
committerJan Michel <j.michel@gsi.de>
Tue, 18 Jul 2017 16:35:13 +0000 (18:35 +0200)
interface/code/uart_rec.vhd [new file with mode: 0644]
interface/code/uart_trans.vhd [new file with mode: 0644]
interface/spi_slave.vhd [new file with mode: 0644]
interface/uart_sctrl.vhd [new file with mode: 0644]
io/pwm.vhd [new file with mode: 0644]
machxo3/sedcheck.vhd [new file with mode: 0644]

diff --git a/interface/code/uart_rec.vhd b/interface/code/uart_rec.vhd
new file mode 100644 (file)
index 0000000..f168832
--- /dev/null
@@ -0,0 +1,160 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+
+
+entity uart_rec is
+--   generic(
+--     CLK_DIV : integer
+--     );
+  port(
+    CLK_DIV        : in integer;
+    CLK            : in std_logic;
+    RST            : in std_logic;
+    RX             : in std_logic;
+    
+    DATA_OUT       : out  std_logic_vector(7 downto 0);
+    DATA_WAITING   : out std_logic;
+    DEBUG          : out std_logic_vector(3 downto 0)
+    );
+end entity;
+
+
+
+architecture uart_rec_arch of uart_rec is
+
+signal clk_div_counter: unsigned(15 downto 0) := x"0000";
+signal symbol_pulse : std_logic := '0';
+signal symbol_counter: unsigned(3 downto 0) := x"0";
+
+type state_type is (idle,receiving,update_parallel_output);
+signal state: state_type := idle;
+
+-- MSB is the stopbit, LSB is the start bit, both are never changed
+signal rx_shift_register: std_logic_vector(9 downto 0); 
+signal symbol : std_logic := '1';
+signal data_waiting_sig: std_logic := '0';
+signal current_data_out: std_logic_vector(7 downto 0) := "00000000";
+signal symbol_start_pulse : std_logic := '0'; -- just debug
+signal rst_clk_div_counter : std_logic;
+signal rx_reg : std_logic;
+
+begin
+----------------------------
+-- debug
+----------------------------
+
+DEBUG(0) <= symbol_start_pulse;
+DEBUG(1) <= symbol_pulse;
+DEBUG(2) <= data_waiting_sig;
+DEBUG(3) <= '0';
+
+----------------------------
+-- Inputs
+----------------------------
+  sync_input : process begin
+    wait until rising_edge(CLK);
+    rx_reg <= RX;
+    symbol <= rx_reg;
+  end process;
+  
+----------------------------
+-- Outputs
+----------------------------
+  sync_output : process begin
+    wait until rising_edge(CLK);
+    DATA_WAITING <= data_waiting_sig;
+    DATA_OUT <= current_data_out;
+  end process;
+----------------------------
+-- Generate Serial Clock
+----------------------------
+  clock_division : process begin
+    wait until rising_edge(CLK);
+    -- scaling down the main clock to the desired baudrate
+    if clk_div_counter = to_unsigned(CLK_DIV,16)-1 then
+      clk_div_counter <= x"0000";
+    else
+      clk_div_counter <= clk_div_counter + 1;
+    end if;
+    -- generates symbol_pulse, a signal that has 1 clock cycle pulses, one symbol duration period apart 
+    -- in contrast to the transceiver module, the symbol pulse is generated in the middle of the
+    -- symbol period
+    --  if clk_div_counter = '0' & CLK_DIV(15 downto 1) then  -- CLK_DIV/2 by >> (right shifting)
+    if clk_div_counter =  to_unsigned(CLK_DIV/2,16) then 
+      symbol_pulse <= '1';
+    else 
+      symbol_pulse <= '0';
+    end if;
+    
+    if clk_div_counter = x"0000" then
+      symbol_start_pulse <= '1';
+    else 
+      symbol_start_pulse <= '0';
+    end if;
+    if (RST or rst_clk_div_counter) = '1' then
+      clk_div_counter <= x"0000";
+    end if;
+    
+  end process;  
+----------------------------
+-- State Machine of the Receiver
+----------------------------
+  state_machine : process begin
+    wait until rising_edge(CLK);
+    data_waiting_sig <= '0';
+    rst_clk_div_counter <= '0';
+
+  --  state machine rules:
+  case state is
+    when idle =>
+      rst_clk_div_counter<= '1';
+      if symbol = '0' then -- the start bit comes!
+        state <= receiving;
+        -- restart the divcounter
+  --       clk_div_counter <= x"0000";
+        symbol_counter <= x"0";
+        
+      end if;
+    
+    when receiving =>
+      if symbol_pulse = '1' then
+        if symbol_counter <= x"9" then -- reception process
+          rx_shift_register(to_integer(symbol_counter)) <= symbol;
+          symbol_counter <= symbol_counter + 1;
+        end if;
+        if symbol_counter = x"9" then
+          state <= update_parallel_output;
+        end if;
+        
+
+      end if;
+    when update_parallel_output =>
+      -- check start and stop bit consistency
+      -- (checking the start bit again seems a little obsolete)
+      -- only if bit was received correctly output the data!
+--       if rx_shift_register(0) = '0' and rx_shift_register(9) = '1' then
+      if symbol = '1' then
+        state <= idle;
+        if rx_shift_register(0) = '0' and rx_shift_register(9) = '1' then
+          current_data_out <= rx_shift_register(8 downto 1);
+          data_waiting_sig <= '1';
+        end if;  
+      end if;
+      
+  end case;
+  
+  -- reset clock divider counters when reset signal is on 
+  if RST = '1' then
+    symbol_counter <= x"0";
+    data_waiting_sig <= '0';
+    state <= idle;
+  end if;
+  
+  end process;
+
+
+end architecture;
\ No newline at end of file
diff --git a/interface/code/uart_trans.vhd b/interface/code/uart_trans.vhd
new file mode 100644 (file)
index 0000000..01967dc
--- /dev/null
@@ -0,0 +1,148 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+
+
+entity uart_trans is
+--   generic(
+--     CLK_DIV : integer
+--     );
+  port(
+    CLK_DIV    : in integer;
+    CLK        : in std_logic;
+    RST        : in std_logic;
+    
+    DATA_IN    : in  std_logic_vector(7 downto 0);
+    SEND       : in  std_logic;
+    READY      : out std_logic;
+    
+    TX         : out std_logic;
+    DEBUG      : out std_logic_vector(3 downto 0)
+    
+    );
+end entity;
+
+
+
+architecture uart_trans_arch of uart_trans is
+
+
+
+signal clk_div_counter: unsigned(15 downto 0) := x"0000";
+signal symbol_start_pulse : std_logic := '0';
+signal symbol_counter: unsigned(3 downto 0) := x"0";
+
+type state_type is (idle,transmitting);
+signal state: state_type := idle;
+
+-- MSB is the stopbit, LSB is the start bit, both are never changed
+signal tx_shift_register: std_logic_vector(9 downto 0) := "1000000000"; 
+signal symbol: std_logic := '1';
+signal ready_sig: std_logic := '1';
+signal rst_clk_div_counter : std_logic;
+
+
+begin
+----------------------------
+-- debug
+----------------------------
+
+DEBUG(0) <= symbol_start_pulse;
+DEBUG(1) <= '0';
+DEBUG(2) <= ready_sig;
+DEBUG(3) <= '0';
+
+----------------------------
+-- Inputs
+----------------------------
+--   sync_input : process begin
+--     wait until rising_edge(CLK);
+--     synced_send <= SEND;
+--   end process;
+-- hard wired stuff
+
+----------------------------
+-- Outputs
+----------------------------
+  sync_output : process begin
+    wait until rising_edge(CLK);
+    TX <= symbol;
+  end process;
+  
+  READY <= ready_sig and not SEND;
+  
+----------------------------
+-- Generate Serial Clock
+----------------------------
+  clock_division : process begin
+    wait until rising_edge(CLK);
+    -- scaling down the main clock to the desired baudrate
+    if clk_div_counter = to_unsigned(CLK_DIV,16)-1 then
+      clk_div_counter <= x"0000";
+    else
+      clk_div_counter <= clk_div_counter + 1;
+    end if;
+
+    
+    if clk_div_counter = x"0001" then
+      symbol_start_pulse <= '1';
+    else 
+      symbol_start_pulse <= '0';
+    end if;
+    if (RST or rst_clk_div_counter) = '1' then
+      clk_div_counter <= x"0000";
+    end if;
+    
+  end process;   
+  
+----------------------------
+-- State Machine of the Transmitter
+----------------------------
+
+  state_machine : process begin
+    wait until rising_edge(CLK);
+    --  state machine rules:
+    rst_clk_div_counter <= '0';
+    
+    case state is
+      when idle =>
+        rst_clk_div_counter <= '1';
+        ready_sig <= '1';
+        if SEND = '1' then
+          state <= transmitting;
+          symbol_counter <= x"0";
+          -- capture the byte at the parallel input
+          tx_shift_register <= '1' & DATA_IN & '0';
+          ready_sig <= '0';
+        end if;
+      
+      when transmitting =>
+        if symbol_start_pulse = '1' then
+          if symbol_counter <= 9 then -- transmission process
+            symbol <= tx_shift_register(to_integer(symbol_counter));
+          end if;
+
+          symbol_counter <= symbol_counter + 1;
+          if symbol_counter = 10 then -- pulse #10 (1 start, 8 data, 1 stop) has been sent
+            --, time to go to idle mode again
+            -- pull the tx line high again, actually obsolete, because stop bit is 1
+            symbol <= '1';
+            state <= idle;
+          end if;
+        end if;    
+    end case; 
+    
+    -- reset clock divider counters when reset signal is on 
+    if RST = '1' then
+      state <= idle;
+      ready_sig <= '1';
+      symbol <= '1';
+    end if;
+
+  end process;
+
+
+
+end architecture;
+
diff --git a/interface/spi_slave.vhd b/interface/spi_slave.vhd
new file mode 100644 (file)
index 0000000..f234756
--- /dev/null
@@ -0,0 +1,154 @@
+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     : in  std_logic;
+    
+    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;
+
+begin
+
+spi_clk_last <= spi_clk_reg when rising_edge(CLK);
+spi_clk_reg <= SPI_CLK when rising_edge(CLK);
+spi_cs_reg  <= SPI_CS  when rising_edge(CLK);
+spi_in_reg  <= SPI_IN  when rising_edge(CLK);
+
+DATA_OUT      <= data_write;
+
+PROC_OUTPUT : process begin
+  wait until rising_edge(CLK);
+  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);
+  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);
+  --write_i <= (others => '0');
+   READ_OUT  <= '0';
+   WRITE_OUT <= '0';
+  case state is
+    when IDLE =>
+      --operation_i <= x"0";
+      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  <= '1';
+        else
+          WRITE_OUT <= '1';
+        end if;
+        ADDR_OUT    <= input(31 downto 24);
+        state       <= GET_DATA;
+      end if;
+      
+    when GET_DATA =>
+      state <= PREPARE_OUTPUT;
+      
+    when PREPARE_OUTPUT =>
+      if READY_IN = '1' then
+        output_data(15 downto 0) <= DATA_IN;
+      end if;
+      state <= WRITE_DATA;
+      
+    when WRITE_DATA =>
+      if bitcnt = 31 then
+        if operation_i = '1' then
+          WRITE_OUT <= '1';
+          data_write <= input(15 downto 0);
+          --write_i(to_integer(unsigned(input(31 downto 28)))) <= '1';
+        end if;
+        state <= WAIT_FINISH;
+      end if;
+      
+    when WAIT_FINISH =>
+     WRITE_OUT <= '0';
+      --if spi_cs_reg = '1' then
+        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;
\ No newline at end of file
diff --git a/interface/uart_sctrl.vhd b/interface/uart_sctrl.vhd
new file mode 100644 (file)
index 0000000..0b1f71b
--- /dev/null
@@ -0,0 +1,198 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.trb_net_std.all;
+-- use work.version.all;
+-- 
+-- library machxo2;
+-- use machxo2.all;
+
+
+entity uart_sctrl is
+  generic(
+    CLOCK_SPEED : integer := 33250000;
+    BAUD : integer := 115200
+    
+    );
+  port(
+    CLK     : in  std_logic;
+    RESET   : in  std_logic;
+    UART_RX : in  std_logic;
+    UART_TX : out std_logic;
+    
+    DATA_OUT  : out std_logic_vector(31 downto 0);
+    DATA_IN   : in  std_logic_vector(31 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 uart_sctrl_arch of uart_sctrl is
+
+constant CLK_DIV : integer := CLOCK_SPEED/BAUD;
+
+signal rx_data   : std_logic_vector(7 downto 0);
+signal tx_data   : std_logic_vector(7 downto 0);
+signal rx_ready  : std_logic;
+signal tx_send   : std_logic;
+signal tx_ready  : std_logic;
+signal bytecount : integer range 0 to 15;
+type   rx_state_t is (IDLE,START,START2,DO_COMMAND,DO_READ,SEND_BYTE1,SEND_BYTE2,SEND_BYTE3,SEND_TERM,SEND_FINISH);
+signal state     : rx_state_t;
+signal addr_data : std_logic_vector(39 downto 0);
+signal addr_data_tx : std_logic_vector(31 downto 0);
+
+signal timer     : unsigned(25 downto 0) := (others => '0');
+signal timeout   : std_logic := '0';
+signal cmd_wr    : std_logic := '0';
+signal cmd_rd    : std_logic := '0';
+
+begin
+
+
+THE_RX : entity work.uart_rec
+  port map(
+    CLK_DIV      => CLK_DIV,
+    CLK          => CLK,
+    RST          => RESET,
+    RX           => UART_RX,
+    DATA_OUT     => rx_data,
+    DATA_WAITING => rx_ready
+    );
+
+THE_TX : entity work.uart_trans
+  port map(
+    CLK_DIV      => CLK_DIV,
+    CLK          => CLK,
+    RST          => RESET,
+    DATA_IN      => tx_data,
+    SEND         => tx_send,
+    READY        => tx_ready,
+    TX           => UART_TX
+    );
+    
+PROC_RX : process 
+  variable tmp,tmp2 : unsigned(7 downto 0);
+begin
+  wait until rising_edge(CLK);
+  READ_OUT  <= '0';
+  WRITE_OUT <= '0';
+  tx_send   <= '0';
+  timer     <= timer + 1;
+  case state is
+    when IDLE =>
+      cmd_rd <= '0';
+      cmd_wr <= '0';
+      bytecount  <= 9;
+      timer  <= (others => '0');
+      if rx_ready = '1' then
+        state <= START;
+        if rx_data = x"52" then
+          cmd_rd <= '1';
+        elsif rx_data = x"57" then
+          cmd_wr <= '1';
+        end if;
+      end if;
+
+    when START =>
+      if rx_ready = '1' then
+        if rx_data >= x"40" then  
+          tmp2 := unsigned(rx_data) + x"09";
+        else
+          tmp2 := unsigned(rx_data);
+        end if;
+        state <= START2;
+      end if;      
+        
+    when START2 =>    
+      addr_data(bytecount*4+3 downto bytecount*4) <= std_logic_vector(tmp2(3 downto 0));
+      if (bytecount = 0 and cmd_wr = '1') or (bytecount = 8 and cmd_rd = '1') then
+        state <= DO_COMMAND;
+      else
+        bytecount <= bytecount - 1;
+        state <= START;
+      end if;
+      
+    when DO_COMMAND =>
+      WRITE_OUT <= cmd_wr;
+      READ_OUT  <= cmd_rd;
+      if cmd_rd = '1' then 
+        state <= DO_READ;
+      else
+        state <= IDLE;
+      end if;  
+
+--Read cycle
+    when DO_READ =>
+      if READY_IN = '1' then
+        addr_data_tx(31 downto 0) <= DATA_IN;
+        tx_send <= '1';
+        tx_data <= x"52";
+        state   <= SEND_BYTE1;
+        bytecount <= 7;
+      end if;
+
+    when SEND_BYTE1 =>
+      tmp := x"0" & unsigned(addr_data_tx(bytecount*4+3 downto bytecount*4));
+      state <= SEND_BYTE2;
+      
+    when SEND_BYTE2 =>     
+      if tmp(3 downto 0) > x"9" then
+        tmp := tmp + x"41" - x"0a";
+      else
+        tmp := tmp + x"30";
+      end if;     
+      state <= SEND_BYTE3;
+    
+    
+    when SEND_BYTE3 =>
+      
+      if tx_ready = '1' then
+        tx_data <= std_logic_vector(tmp);
+        tx_send <= '1';
+        if bytecount = 0 then
+          state <= SEND_TERM;
+        else
+          bytecount <= bytecount - 1;
+          state <= SEND_BYTE1;
+        end if;      
+      end if;
+
+      
+      
+    when SEND_TERM=>
+      if tx_ready = '1' then
+        tx_send <= '1';
+        tx_data <= x"0a";
+        state   <= SEND_FINISH;
+      end if;
+    when SEND_FINISH=>
+      if tx_ready = '1' then
+        tx_send <= '1';
+        tx_data <= x"0d";
+        state   <= IDLE;
+      end if;
+        
+  end case;
+
+  if RESET = '1' or timeout = '1' then
+    state <= IDLE;
+    timer <= (others => '0');
+  end if;
+end process;
+
+DATA_OUT  <= addr_data(31 downto 0);
+ADDR_OUT  <= addr_data(39 downto 32);
+      
+timeout <= timer(19);
+
+
+
+end architecture;
\ No newline at end of file
diff --git a/io/pwm.vhd b/io/pwm.vhd
new file mode 100644 (file)
index 0000000..a0045bf
--- /dev/null
@@ -0,0 +1,82 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+
+
+entity pwm_generator is
+  generic(
+    CHANNELS : integer := 32
+    );
+  port(
+    CLK        : in std_logic;
+    
+    DATA_IN    : in  std_logic_vector(15 downto 0) := (others => '0');
+    DATA_OUT   : out std_logic_vector(15 downto 0);
+    WRITE_IN   : in  std_logic := '0';
+    COMP_IN    : in  signed(15 downto 0);
+    ADDR_IN    : in  std_logic_vector(4 downto 0) := (others => '0');
+    
+    
+    PWM        : out std_logic_vector(CHANNELS-1 downto 0)
+    
+    );
+end entity;
+
+
+
+architecture pwm_arch of pwm_generator is
+
+type ram_t is array(0 to CHANNELS-1) of unsigned(15 downto 0);
+signal set : ram_t := (others => x"87C1");
+signal set_tmp : ram_t;
+
+type cnt_t is array(0 to CHANNELS-1) of unsigned(16 downto 0);
+signal cnt : cnt_t := (others => (others => '0'));
+
+signal last_flag : std_logic_vector(CHANNELS-1 downto 0) := (others => '0');
+signal flag      : std_logic_vector(CHANNELS-1 downto 0) := (others => '0');
+signal pwm_i     : std_logic_vector(CHANNELS-1 downto 0) := (others => '0');
+
+signal i         : integer range 0 to CHANNELS-1 := 0;
+signal clock_enable : std_logic_vector(15 downto 0) := x"0001";
+begin
+
+PROC_MEM : process begin
+  wait until rising_edge(CLK);
+  if WRITE_IN = '1' then
+    set(to_integer(unsigned(ADDR_IN))) <= unsigned(DATA_IN);
+  end if;
+  DATA_OUT <= std_logic_vector(set(to_integer(unsigned(ADDR_IN))));
+end process;
+
+
+GEN_REAL_VALUES : process begin
+  wait until rising_edge(CLK);
+  set_tmp(i) <= unsigned(signed(set(i)) + COMP_IN);
+  i <= i + 1;
+end process;
+
+process begin
+  wait until rising_edge(CLK);
+  clock_enable <= clock_enable(14 downto 0) & clock_enable(15);
+end process;
+
+gen_channels : for i in 0 to CHANNELS-1 generate
+  flag(i)      <= cnt(i)(16);
+  
+  process begin
+    wait until rising_edge(CLK);
+    if clock_enable(i mod 16) = '1' then
+      last_flag(i) <= flag(i);
+      pwm_i(i)     <= (last_flag(i) xor flag(i));
+      cnt(i)       <= cnt(i) + resize(set_tmp(i),17);
+    end if;
+  end process;  
+end generate;
+
+
+
+PWM(CHANNELS-1 downto 0 ) <= pwm_i(CHANNELS-1 downto 0);
+
+end architecture;
diff --git a/machxo3/sedcheck.vhd b/machxo3/sedcheck.vhd
new file mode 100644 (file)
index 0000000..b1149da
--- /dev/null
@@ -0,0 +1,201 @@
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use ieee.numeric_std.all;\r
+\r
+library work;\r
+use work.trb_net_std.all;\r
+\r
+library ecp5um;\r
+use ecp5um.components.all;\r
+\r
+entity sedcheck is\r
+  generic (\r
+    DEV_DENSITY : string := "2100L"\r
+    );\r
+  port(\r
+    CLK        : in std_logic;\r
+    ERROR_OUT  : out std_logic;\r
+    \r
+    CONTROL_IN : in std_logic_vector(3 downto 0);\r
+    DEBUG      : out std_logic_vector(31 downto 0)\r
+    );\r
+end entity;\r
+\r
+\r
+architecture sed_arch of sedcheck is\r
\r
+  component SEDFA\r
+    generic (\r
+      CHECKALWAYS : string :="DISABLED";\r
+      SED_CLK_FREQ : string :="3.5" ;\r
+      DEV_DENSITY : string :="2100L" \r
+      );\r
+    port (\r
+      SEDSTDBY  : in std_logic;\r
+      SEDENABLE : in std_logic;\r
+      SEDSTART : in std_logic;\r
+      SEDFRCERR : in std_logic;\r
+      SEDERR : out std_logic;\r
+      SEDDONE : out std_logic;\r
+      SEDINPROG : out std_logic;\r
+      SEDCLKOUT : out std_logic\r
+      );\r
+  end component;  \r
\r
+  type state_t is (IDLE, INIT_1, INIT_2, INIT_3, START_1, START_2, WAITACTIVE, WAITDONE);\r
+  signal state          : state_t;\r
+  signal state_bits     : std_logic_vector(3 downto 0);\r
+\r
+  signal sed_edge       : std_logic;\r
+  signal sed_clock_last : std_logic;\r
+\r
+  signal sed_clock      : std_logic;\r
+  signal sed_done       : std_logic;\r
+  signal sed_enable     : std_logic;\r
+  signal sed_error      : std_logic;\r
+  signal sed_inprogress : std_logic;\r
+  signal sed_start      : std_logic;\r
+\r
+  signal sed_clock_q      : std_logic;\r
+  signal sed_done_q       : std_logic;\r
+  signal sed_error_q      : std_logic;\r
+  signal sed_inprogress_q : std_logic;\r
+\r
+  signal status_i       : std_logic_vector(31 downto 0);\r
+  \r
+  signal run_counter    : unsigned(7 downto 0) := (others => '0');\r
+  signal error_counter  : unsigned(7 downto 0) := (others => '0');\r
+  signal timer          : unsigned(22 downto 0);\r
+  \r
+begin\r
+\r
+sed_clock_last <= sed_clock_q when rising_edge(CLK);\r
+sed_edge       <= sed_clock_q and not sed_clock_last when rising_edge(CLK);\r
+\r
+sed_clock_q      <= sed_clock when rising_edge(CLK);\r
+sed_done_q       <= sed_done when rising_edge(CLK);\r
+sed_inprogress_q <= sed_inprogress when rising_edge(CLK);\r
+sed_error_q      <= sed_error when rising_edge(CLK);\r
+\r
+\r
+---------------------------------------------------------------------------\r
+-- SED control state machine\r
+---------------------------------------------------------------------------\r
+proc_ctrl : process begin\r
+  wait until rising_edge(CLK);\r
+  timer <= timer + 1;\r
+  case state is\r
+    when IDLE =>\r
+      sed_enable   <= '0';\r
+      sed_start    <= '0';\r
+      if CONTROL_IN(0) = '1' then\r
+        state      <= INIT_1;\r
+        timer      <= (0 => '1', others => '0');\r
+      end if;\r
+    when INIT_1 =>\r
+      sed_enable   <= '0';\r
+      sed_start    <= '0';\r
+      if timer(5 downto 0) = 0 then\r
+        state      <= INIT_2;\r
+      end if;\r
+    when INIT_2 =>\r
+      sed_enable   <= '1';\r
+      sed_start    <= '0';\r
+      if timer(5 downto 0) = 0 then\r
+        state      <= INIT_3;\r
+      end if;\r
+    when INIT_3 =>\r
+      sed_enable   <= '1';\r
+      sed_start    <= '0';\r
+      if timer(5 downto 0) = 0 then\r
+        state      <= START_1;\r
+      end if;\r
+    when START_1 =>\r
+      sed_enable   <= '1';\r
+      sed_start    <= '0';\r
+      if sed_edge = '1' then\r
+        state      <= START_2;\r
+      end if;\r
+    when START_2 =>      \r
+      sed_enable   <= '1';\r
+      sed_start    <= '1';\r
+      if sed_edge = '1' and sed_inprogress_q = '1' then\r
+        state      <= WAITACTIVE;\r
+      end if;\r
+    when WAITACTIVE =>\r
+      sed_enable   <= '1';\r
+      sed_start    <= '1';\r
+      if sed_edge = '1' and sed_done_q = '0' then\r
+        state      <= WAITDONE;\r
+      end if;\r
+    when WAITDONE =>\r
+      sed_enable   <= '1';\r
+      sed_start    <= '1';\r
+      if (sed_edge = '1' and sed_inprogress_q = '0' and sed_done_q = '1') then\r
+        state       <= INIT_1;\r
+               timer       <= (0 => '1', others => '0');\r
+        run_counter <= run_counter + 1;\r
+        if sed_error_q = '1' then\r
+          error_counter <= error_counter + 1;\r
+        end if;\r
+      end if;\r
+  end case;\r
+  \r
+  if CONTROL_IN(0) = '0' or (timer = 0 and state /= IDLE) then\r
+    sed_enable <= '0';\r
+    state      <= IDLE;\r
+  end if;\r
+  \r
+end process;\r
+\r
+---------------------------------------------------------------------------\r
+-- Status Information\r
+---------------------------------------------------------------------------\r
+state_bits <= x"8" when state = IDLE else\r
+              x"1" when state = INIT_1 else\r
+              x"2" when state = INIT_2 else\r
+              x"3" when state = INIT_3 else\r
+              x"4" when state = START_1 else\r
+              x"5" when state = START_2 else\r
+              x"6" when state = WAITACTIVE else\r
+              x"7" when state = WAITDONE else\r
+--               x"9" when state = RESULT else\r
+              x"F";\r
+\r
+status_i(3 downto 0) <= state_bits;\r
+status_i(4)          <= sed_clock_q;\r
+status_i(5)          <= sed_enable;\r
+status_i(6)          <= sed_start;\r
+status_i(7)          <= sed_done_q;\r
+status_i(8)          <= sed_inprogress_q;\r
+status_i(9)          <= sed_error_q;\r
+status_i(10)         <= not sed_edge;\r
+status_i(15 downto 11) <= (others => '0');\r
+status_i(23 downto 16) <= std_logic_vector(run_counter)(7 downto 0);\r
+status_i(31 downto 24) <= std_logic_vector(error_counter)(7 downto 0);\r
+              \r
+ERROR_OUT <= sed_error;              \r
+DEBUG     <= status_i when rising_edge(CLK);\r
+\r
+---------------------------------------------------------------------------\r
+-- SED\r
+---------------------------------------------------------------------------\r
+THE_SED : SEDFA\r
+  generic map(\r
+      CHECKALWAYS  => "DISABLED",\r
+      SED_CLK_FREQ   => "3.5",\r
+      DEV_DENSITY  => DEV_DENSITY \r
+      )\r
+  port map(\r
+    SEDSTDBY  => '0',\r
+    SEDENABLE => sed_enable,\r
+    SEDSTART  => sed_start,\r
+    SEDFRCERR => '0',\r
+    SEDERR    => sed_error,\r
+    SEDDONE   => sed_done,\r
+    SEDINPROG => sed_inprogress,\r
+    SEDCLKOUT => sed_clock\r
+    );\r
+    \r
+    \r
+end architecture; \r