【问题标题】:Trying to implement spi bus in vhdl试图在 vhdl 中实现 spi 总线
【发布时间】:2013-07-04 18:50:35
【问题描述】:

我一直在尝试通过 SPI 与 LTC2426 DAC 通信,但我失败了。现在我正在寻求帮助。有人可以告诉我为什么我的代码不起作用。 CSDAC 工作正常,生成 SCLK 并发送 32 位,但我仍然可能搞砸了时序。我将非常感谢 şf 有人帮我修复代码。

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;

编辑:新代码

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;

我正在脉冲 MOSI,因为当我发送几个位时,SCLK 会恢复。第一个 SCLK 在大约 1.4 mhz 上运行,当我将 mosi 脉冲恢复到 4.167MHZ 请注意,1.4mhz 左右可能是 ​​1.5mhz,我记不太清楚了。

【问题讨论】:

    标签: vhdl fpga spi dac spartan


    【解决方案1】:

    你的第二个进程应该对 SCLK(或斜率)i.s.o 敏感吗?时钟? 您可以查看opencores.org 以获取 SPI 模块的一些示例。即使用 Verilog 编写,这也不是一个很好的例子。

    【讨论】:

    • @baldyHDL 有更好的答案。将您的代码放在一个进程中会更好。你也可以考虑构建一个 FSM。对于您当前的需求来说有点过头了,但是一段时间后解决方案总是会变得更加复杂:-)
    【解决方案2】:

    您必须更新与 SCK 相关的位计数器 (CurrentBit)。 例如:

    ...
    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
     ...
    

    【讨论】:

    • 我的代码基于您的建议,我的逻辑分析仪解码了 spi 总线,但 lt2624 仍然无法工作。我的新代码将在几分钟内完成
    • 您使用模拟器吗?你可以例如使用包含 lite 模拟器的 Xilinx WebPack(免费)。模拟帮助您发现明显的错误;在您的新代码中,例如您必须在“if counter=5 then”行之后将“Counter”重置为 0。
    • 我直接给板子编程,接上logic8逻辑分析仪
    • 我也用范围检查过了
    • 如前所述...在“if counter=5 then”行之后重置计数器。模拟可以让您深入了解您的代码。检查范围很棒...在模拟之后将其用作第二步!
    猜你喜欢
    • 1970-01-01
    • 2011-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多