EmbDev.net

Forum: FPGA, VHDL & Verilog ADC on DEO NANO not working


Author: chinmaye (Guest)
Posted on:

Rate this post
0 useful
not useful
Hello,

I am trying to get the ADC on the DEO Nano board working. I am dividing 
the 50 MHz clock to 1MHz and trying to read channel zero. But it doesn't 
seem to be working. Here is the code. The simulation works fine. But it 
is not showing up on the board.
I am trying to give the analog input through a POT and trying to get the 
output on LEDS. The LEDs simply do not glow for any input.

I have connected the IGO key to the dip switch. I am not sure if it 
works. Plz help.
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    17:04:43 03/19/2018 
// Design Name: 
// Module Name:    adc 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module ADC_CNTRL  (  
          iRST,
          CLK,
          //iCLK_n,
          iGO,
          //iCH,
          oLED,
          
          oDIN,
          oCS_n,
          oSCLK,
          iDOUT
        
          
        );
          
input        iRST;
input        CLK;
//input        iCLK_n;
input        iGO;
//input  [2:0]    iCH;
output  [7:0]    oLED;
//output [3:0] m_cont;
output        oDIN;
output        oCS_n;
output        oSCLK;
input        iDOUT;

reg          data;
reg          go_en;
wire  [2:0]    ch_sel;
reg          sclk;
reg    [3:0]    cont;
reg    [3:0]    m_cont;
reg    [11:0]    adc_data;
reg    [11:0]    led;
//reg [2:0] iCH;
reg iCLK = 0, iCLK_n = 1;
parameter sys_clk = 50000000;  // 50 MHz system clock
parameter clk_out = 1000000;  // 1 MHz clock output
parameter max = sys_clk / (2*clk_out); // max-counter size

reg [4:0]counter = 0; // 5-bit counter size
always@(posedge CLK) begin
  if (counter == max-1)
    begin
    counter <= 0;
    iCLK <= ~iCLK;
    iCLK_n <= ~iCLK_n;
    end
  else
    begin
    counter <= counter + 1'd1;
    end
  //Clk_out <= (counter == 5'd0);
  end




assign  oCS_n    =  ~go_en;
assign  oSCLK    =  (go_en)? iCLK:1;
assign  oDIN    =  data;
//assign  ch_sel    =  iCH;
assign  oLED    =  led;

always@(posedge iGO or negedge iRST)
begin
  if(!iRST)
    go_en  <=  0;
  else
  begin
    if(iGO)
      go_en  <=  1;
  end
end

always@(posedge iCLK or negedge go_en)
begin
  if(!go_en)
    cont  <=  0;
  else
  begin
    if(iCLK)
      cont  <=  cont + 1;
  end
end

always@(posedge iCLK_n)
begin
  if(iCLK_n)
    m_cont  <=  cont;
end

always@(posedge iCLK_n or negedge go_en)
begin
  if(!go_en)
    data  <=  0;
  else
  begin
    if(iCLK_n)
    begin
      if (cont == 2)
        data  <=  0;
      else if (cont == 3)
        data  <=  0;
      else if (cont == 4)
        data  <=  0;
      else
        data  <=  0;
    end
  end
end

always@(posedge iCLK or negedge go_en)
begin
  if(!go_en)
  begin
    adc_data  <=  0;
    led      <=  8'b00;
  end
  else
  begin
    if(iCLK)
    begin
      if (m_cont == 4)
        adc_data[11]  <=  iDOUT;
      else if (m_cont == 5)
        adc_data[10]  <=  iDOUT;
      else if (m_cont == 6)
        adc_data[9]    <=  iDOUT;
      else if (m_cont == 7)
        adc_data[8]    <=  iDOUT;
      else if (m_cont == 8)
        adc_data[7]    <=  iDOUT;
      else if (m_cont == 9)
        adc_data[6]    <=  iDOUT;
      else if (m_cont == 10)
        adc_data[5]    <=  iDOUT;
      else if (m_cont == 11)
        adc_data[4]    <=  iDOUT;
      else if (m_cont == 12)
        adc_data[3]    <=  iDOUT;
      else if (m_cont == 13)
        adc_data[2]    <=  iDOUT;
      else if (m_cont == 14)
        adc_data[1]    <=  iDOUT;
      else if (m_cont == 15)
        adc_data[0]    <=  iDOUT;
      else if (m_cont == 1)
        led  <=  adc_data[11:4];
    end
  end
end

endmodule

Author: ElKo (Guest)
Posted on:

Rate this post
0 useful
not useful
Is the demo project working, which Terasic delivers on the CD? (and 
which you copied)

What do the LED show, if you assign "counter" to them?

Is this module your Toplevel? If so, did you change the pin assignments?

Author: Christian G. (Guest)
Posted on:

Rate this post
0 useful
not useful
Hi, a few days ago, I tried to get that same example project to run and 
also failed, it just did not work on the real hardware. To be honest I 
have no clue of verilog, so I ended up building my own adc_controller in 
vhdl and it turned out to be surprisingly easy once you read the adc 
datasheet, I used a PLL to create a clock double the speed of the adc 
clock I want than on the falling edge of the adc clock I push out the 
channel I want to read and on the rising edge of the adc clock I read 
the channel data back. It might not be by far the best solution but it 
works :
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity adc_controller is
  port
  (
    clk : in std_logic;    
    reset : in std_logic;
    output : out std_logic_vector(11 downto 0);
    output_valid : out std_logic;
    go : in std_logic;
    ch_sel : in std_logic_vector(2 downto 0);
    adc_clk : out std_logic;          -- The ADC clock (0.8 - 3.2 MHz) will be half the speed of clk !
    adc_cs_n : out std_logic;
    adc_sadr : out std_logic;
    adc_dat : in std_logic
  );
end entity;

architecture behavioural of adc_controller is

  signal adc_data_out : std_logic_vector(15 downto 0) := (others => '0');
  signal adc_data_in: std_logic_vector(15 downto 0) := (others => '0');
  signal di_counter : natural range 0 to 15 := 0;
  signal do_counter : natural range 0 to 15 := 0;
  type tstate is (init, start, clock_low, clock_high, last_clock_high, stop);
  signal state :tstate := init;
  
begin

  process
  begin
    wait until rising_edge(clk);
    if (reset = '1') then
      output <= (others => '0');
      di_counter <= 15;
      do_counter <= 15;
      adc_data_in <= (others => '0');
      adc_cs_n <= '1';
      adc_clk <= '0';
      output_valid <= '0';
      state <= init;
    else
      case state is
        when init =>
          adc_clk <= '1';
          adc_cs_n <= '1';
          do_counter <= 15;
          di_counter <= 15;
          adc_sadr <= '0';
          adc_data_in <= (others => '0');
          adc_data_out <= "00" & ch_sel & "000" & "00000000";
          output_valid <= '0';
          if (go <= '1') then
            state <= start;
          else
            state <= init;
          end if;
          
        when start =>
          adc_cs_n <= '0';
          state <= clock_low;

        when clock_low =>
          adc_clk <= '0';
          adc_sadr <= adc_data_out(do_counter);
          if (di_counter > 0) then
            do_counter <= do_counter - 1;
            state <= clock_high;
          else
            state <= last_clock_high;
          end if;

        when clock_high =>
          adc_clk <= '1';
          adc_sadr <= adc_data_out(do_counter);
          adc_data_in(di_counter) <= adc_dat;
          di_counter <= di_counter - 1;
          state <= clock_low;

        when last_clock_high =>
          adc_clk <= '1';
          adc_data_in(di_counter) <= adc_dat;
          state <= stop;

        when stop =>
          adc_cs_n <= '1';
          output <= adc_data_in(15 downto 4);
          output_valid <= '1';
          state <= init;
          
        when others =>
          adc_cs_n <= '1';
          state <= init;
      end case;      
    end if;
  end process;
  
end behavioural;

top-level entity:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity adc_test is
  port
  (
    CLK_50 : in std_logic;
    BTN_RST : in std_logic;
    LED : out std_logic_vector(7 downto 0);
    SWITCH : in std_logic_vector(3 downto 0);
    ADC_CS : out std_logic;
    ADC_DAT_IN : out std_logic;
    ADC_DAT_OUT : in std_logic;
    ADC_CLK : out std_logic
  );
end adc_test;

architecture adc_test_arc of adc_test is

  component pll_clock IS
    PORT
    (
      inclk0    : IN STD_LOGIC  := '0';
      c0    : OUT STD_LOGIC -- I used a 4MHz clock
    );
  END component;
    
  component adc_controller is
    port
    (
      clk : in std_logic;
      reset : in std_logic;
      output : out std_logic_vector(11 downto 0);
      output_valid : out std_logic;
      go : in std_logic;
      ch_sel : in std_logic_vector(2 downto 0);
      adc_clk : out std_logic;
      adc_cs_n : out std_logic;
      adc_sadr : out std_logic;
      adc_dat : in std_logic
    );
  end component;
  
  signal adc_controller_clk : std_logic := '0';
  signal adc_data : std_logic_vector(11 downto 0) := (others => '0');
  signal adc_data_valid : std_logic := '0';
  signal adc_go : std_logic := '0';
  signal rst_btn_sr : std_logic_vector(2 downto 0) := (others =>'0');
  signal adc_reset : std_logic := '0';
  signal rst_counter : natural := 0;
  signal reset_me : std_logic := '0';
  
begin
  
  pll_clock_inst : pll_clock port map(
    inclk0 => CLK_50,
    c0 => adc_controller_clk
  );
  
  adc_controller_inst : adc_controller port map(
    clk => adc_controller_clk,
    reset => adc_reset,
    output => adc_data,
    output_valid => adc_data_valid,
    go => adc_go,
    ch_sel => SWITCH(2 downto 0),
    adc_clk => ADC_CLK,
    adc_cs_n => ADC_CS,
    adc_sadr => ADC_DAT_IN,
    adc_dat => ADC_DAT_OUT
  );
  
    
-- RESET button process
  reset_btn_proc : process
  begin
    wait until rising_edge(CLK_50);
    rst_btn_sr <= rst_btn_sr(1 downto 0) & (NOT BTN_RST);
    if (rst_btn_sr = "111") then 
      reset_me <= '1'; 
    else 
      reset_me <= '0';
    end if;
  end process reset_btn_proc;
  
--RESET process  
  reset_proc :process
  begin
    wait until rising_edge(CLK_50);
    if (reset_me = '1') then
      rst_counter <= 100;
    end if;
    if (rst_counter > 0) then
      adc_reset <= '1';
      adc_go <= '0';
      rst_counter <= rst_counter - 1;
    else
      adc_reset <= '0';
      adc_go <= '1';
    end if;
  end process reset_proc;
  
-- LED process
  led_proc : process
  begin
    wait until rising_edge(CLK_50);
    if (adc_reset = '1') then
      LED <= (others => '0');
    else
      if (adc_data_valid = '1') then
        LED <= adc_data(7 downto 0);
      end if;
    end if;
  end process led_proc;
  
end adc_test_arc;

Reply

Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [vhdl]VHDL code[/vhdl]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]




Bild automatisch verkleinern, falls nötig