0

I've been trying to comunicate with the LTC2426 DAC via SPI and I've failed missrebly. Now I'm seeking for help. Could someone tell me why my code doesn't work. The CSDAC Works properly the SCLK is generated and the 32 bits are sent but still I may have screwed the timing. I would be very thankful şf someone help me fix the code.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity DAC is
    port
        (
            CLK : in STD_LOGIC;         
            SCLK : out STD_LOGIC;
            MOSI : out STD_LOGIC;
            CSDAC : out STD_LOGIC := '1'        
        );  
end DAC;

architecture Behavioral of DAC is
Signal Counter : Integer range 0 to 32 := 0;
Signal CurrentBit : Integer range 0 to 32 := 0;
Signal DataSent : STD_LOGIC := '1';
Constant Data : STD_LOGIC_VECTOR(31 downto 0) := X"0030FFF0";
Signal Slope : STD_LOGIC := '0';
begin
Prescaler : process(CLK) 
begin
    if rising_edge(CLK) then
        if Counter = 5 then
            Slope <= not(Slope);
            Counter <= 0;
        else
            Counter <= Counter + 1;
        end if;
    end if; 
end process;
SCLK <= SLOPE;
WriteDac : process(CLK) 
begin
    if rising_edge(CLK) then
         if DataSent = '1' then
            if CurrentBit <= 31 then
                CSDAC <= '0';
                MOSI <= Data(CurrentBit);
                CurrentBit <= CurrentBit +1;
            else
                CSDAC <= '1';       
                DataSent <= '0';                
            end if;
         end if;
    end if;
end process;
end Behavioral;

EDIT : NEW CODE

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity DAC is
    port
        (
            CLK : in STD_LOGIC;         
            SCLK : out STD_LOGIC;
            MOSI : out STD_LOGIC;
            DEBUG : out STD_LOGIC := '1';
            CSDAC : out STD_LOGIC := '1'        
        );  
end DAC;

architecture Behavioral of DAC is
Signal Counter : Integer range 0 to 6 := 0;
Signal Counter2 : Integer range 0 to 33 := 0;
Signal CurrentBit : Integer range 0 to 33 := 0;
Signal Fixed : STD_LOGIC := '0';
Signal DataSent : STD_LOGIC := '0';
Constant Data : STD_LOGIC_VECTOR(31 downto 0) := X"0FFF0C00";
Signal Slope_last : STD_LOGIC := '0'; 
Signal Slope : STD_LOGIC := '0';
Signal MSS : STD_LOGIC := '0';
begin

WriteDac : process(CLK) 
begin
    if rising_edge(CLK) then
        if Counter = 5 then
            Slope_last <= Slope;
            Slope <= not(Slope);
           if Slope_last = '1' and Slope = '0' then
                if Fixed = '1' then
                    if DataSent = '0' then
                        if CurrentBit <= 31 then
                            CSDAC <= '0';
                            DEBUG <= '0';
                            MOSI <= Data(CurrentBit);
                            CurrentBit <= CurrentBit +1;
                         else
                            MOSI <= '0';
                            CSDAC <= '1';
                            DEBUG <= '1';
                            DataSent <= '1';
                        end if;
                    end if;
                else
                  if Counter2 <= 31 then
                        CSDAC <= '1';
                        DEBUG <= '1';
                        Counter2 <= Counter2 + 1;
                        MSS <= not(MSS);
                        MOSI <= MSS;
                  else  
                        Fixed <= '1';
                        MOSI <= '0';
                  end if;
                end if;
            end if;
        else
            Counter <= Counter + 1;
        end if;
    end if;
end process;
SCLK <= SLOPE;

end Behavioral;

I'm pulsing the MOSI because when i send couple of bits the SCLK recovers. First SCLK runs on about 1.4 mhz when i pulse the mosi it recovers to 4.167MHZ note that 1.4mhz or so it can be 1.5mhz I cant remember it too good.

gv260ea
  • 21
  • 1
  • 5

2 Answers2

0

Could it be your second process should be sensitive to SCLK (or slope) i.s.o. CLK? You could check opencores.org for some examples of an SPI module. Even if written in Verilog, It't a nice example how things could be done.

vermaete
  • 1,330
  • 1
  • 17
  • 28
  • @baldyHDL had the better answer. Putting your code in one process will be better. You could also think of building a FSM. Slightly an overkill for your current need, but solutions always get more complicated after some time :-) – vermaete Jul 05 '13 at 07:23
0

you must update your bit counter (CurrentBit) related to SCK. e.g.:

...
WriteDac : process(CLK) 
begin
   if rising_edge(CLK) then
      slope_last<=slope;

      if slope_last='1' and slope='0' then -- e.g. falling edge!
          if DataSent = '1' then
 ...
baldyHDL
  • 1,387
  • 1
  • 10
  • 16
  • I have based my code on your recomendation my logic analyzer decodes the spi bus but the lt2624 still doesnt work. My new code will be up in a couple of minutes – gv260ea Jul 05 '13 at 15:59
  • do you use a simulator? you can e.g. use Xilinx WebPack (free) where a lite simulator is included. simulating helps you to find obvious errors; in your new code e.g. you must reset "Counter" to 0 after the "if counter=5 then" line. – baldyHDL Jul 05 '13 at 20:00
  • I directly program the board and hook up the logic8 logic analyzer – gv260ea Jul 05 '13 at 20:01
  • I have also checked it with the scope – gv260ea Jul 05 '13 at 20:02
  • as mentioned before... reset counter after the "if counter=5 then" line. Simulating gives you insight into your code. checking with scope is great... use it as second step, after simulation! – baldyHDL Jul 05 '13 at 20:04
  • I have reseted the counter but no luck. – gv260ea Jul 05 '13 at 22:50
  • in your implementation you have also to change the active "slope" edge (as slope is negated right at the time you detect the edge). it should be "if Slope_last = '0' and Slope = '1' then". with that, you should see the correct signals with your scope. now you should compare the datasheet carefully with what you're doing. I expect that you want to write a value to all dacs (CMD=0x0, Addr=0x0F)? however, you write the LSB of "DATA" first while you should start with MSB. also you have to write an "update" command after writing the DACs... AAAAAND... simulation helps you to see all that ;-) – baldyHDL Jul 06 '13 at 05:38
  • No I have inverted the data by hand in order to get msb first CMD=0x3 ADDR = 0x0 Value = 0xFFF this is equal to 0x0030FFF0 when its inverted its equal to 0x0FFF0C00. And the datasheet says that 0x3 writes the data and updates it. – gv260ea Jul 06 '13 at 12:12
  • I'm also using the 32-bit mode. – gv260ea Jul 06 '13 at 12:18
  • so what's not working yet? does your vhdl code give the output (measured with scope ;-) ) that you expect or not? – baldyHDL Jul 06 '13 at 17:10
  • and when I simulate your code it looks as if cmd=0x0, addr=0x0, data=0x30f, dummies=0xff0. is that different to what you measure with the scope? – baldyHDL Jul 06 '13 at 17:23
  • if you "invert" data as you say, then you should get 0x000FFF0C (first 4 bits are cmd, then 4 bits addr, then 12 bits data, then dummies) – baldyHDL Jul 06 '13 at 17:25
  • My scope shows that evrything is ok but the dac doesnt output something wait my CMD should be 0x3 addr = 0x0 data = 0xff0 – gv260ea Jul 06 '13 at 17:27
  • The output should be 0b00000000001100001111111111110000. – gv260ea Jul 06 '13 at 17:31
  • I have just tried 0x000FFF0C but the dac still doesnt output something. I also appreciate that you just simulated the code for me. – gv260ea Jul 06 '13 at 17:37
  • I'm sorry, just saw that in 32 bit mode the 8 dummy bits must be first... therefore your 0x0FFF0C00 was correct. could it be a problem with initial timing? it looks as if you'd write the value right after power up... is the DAC ready at this moment? however, if the VHDL code generates the output that you expect, then this is probably not a VHDL related issue anymore... – baldyHDL Jul 06 '13 at 18:03
  • Any ideas. Maybe the polarity of the clock – gv260ea Jul 06 '13 at 18:12
  • I have a question i just learnt how to simulate but why the sclk looks weird and has a value of X sometimes – gv260ea Jul 06 '13 at 18:14
  • I have probed the sck it looks very weird Has a large amount of undershoot and overshoot as well as decent amount of noise and ringing. – gv260ea Jul 06 '13 at 18:25
  • 1. polarity of the clock: did you change the active "slope" as mentioned in an earlier comment? 2. Simulation: what tools are you using? I simulated with Xilinx ISE and SCK seems to be stable... I could send the testbench if required. 3. overshoot/undershoot: check your ground connection (make it as short as possible) and validate the connections to the DAC. – baldyHDL Jul 06 '13 at 19:09
  • 1.Yes i did 2nd i renamed sclk with sck as the ise similator thought that it was a clock but still nothing on the dac. – gv260ea Jul 06 '13 at 20:15