我正在尝试实现SPI接口。我有2个问题,这是第一个。 (我决定单独提出每个问题以简化事情。
似乎没有任何工作,所以我将我的设计剥离到一个移位寄存器,其中输入的数据应该返回到SPI主设备。
这就是我现在所拥有的。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity interface is
port
(
-- SPI
SPI_MOSI: in std_logic;
SPI_MISO: out std_logic;
SPI_CLK: in std_logic;
);
end interface;
architecture Behavioral of interface is
-- SPI
signal SPI_REG: std_logic_vector(7 downto 0) := (others => '0');
-- SPI interface
process(SPI_CLK)
begin
if rising_edge(SPI_CLK) then
SPI_MISO <= SPI_REG(7);
SPI_REG <= SPI_REG(6 downto 0) & SPI_MOSI; -- Concatenate bits
end if;
end process;
end Behavioral;
我还有一个在Raspberry Pi上运行的主(cpp)程序。
它再次非常基础,这就是它的作用。
#include <wiringPiSPI.h>
#include <iostream>
int main()
{
wiringPiSPISetup(0, 500000); // Device 0, slowest speed available
// Create array of 64 bytes (unsigned char)
// Print this array
wiringPiSPIDataRW(0, data, 64);
// Print array again and compare data by eye
}
目前我已经设置了数组创建,因此它按顺序包含数字0到63。在将每个转换为int之后打印出来。 (为简单起见,我省略了这段代码。)
这是一个典型的输入:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ...
这是典型的输出:
31 128 0 129 1 130 2 131 3 132 4 135 5 134 6 ...
所以前2个字节是垃圾。我本来期望返回1个垃圾字节...一个被设置为包含零! (与VHDL代码一样。)
然后在此之后,每隔一个字节都是垃圾,我不知道为什么......并且发送的实际数据似乎被返回,尽管它返回中间有垃圾字节......
我不确定这是因为我误解了SPI硬件定义,还是我的VHDL代码不正确。
答案 0 :(得分:1)
第一个时钟输入位需要9个时钟周期才能出现在输出端。
我将代码更改为以下内容,并注意到与将MOSI连接到MISO的直线相比,输出延迟了1位。 (将这2个引脚短接,没有延迟,正如预期的那样,但是下面的代码产生了1位延迟。)
请注意,对于熟悉VHDL的人来说,这应该是非常明显的。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity interface is
port
(
-- SPI
SPI_MOSI: in std_logic;
SPI_MISO: out std_logic;
SPI_CLK: in std_logic;
);
end interface;
architecture Behavioral of interface is
-- SPI
signal SPI_REG: std_logic_vector(7 downto 0) := (others => '0');
-- SPI interface
process(SPI_CLK)
begin
if rising_edge(SPI_CLK) then
SPI_MISO <= SPI_MOSI;
end if;
end process;
end Behavioral;
如果这会产生1位延迟,那么你应该明白为什么,如果你已经完成了一些基本的数字电子设备。 (这是由于时钟边缘通过系统传输数据的方式,当然。)
因此,为了解决这个问题,您只需更改代码即可使用异步数据传输。 (不确定VHDL世界中这个名称的正确名称。)
这是改变:
process(SPI_CLK)
begin
SPI_MISO <= SPI_MOSI;
if rising_edge(SPI_CLK) then
end if;
end process;
这种数据传输立即发生(或至少非常快,纳秒或更短),而不仅仅是在时钟边缘。
所以8位的完整解决方案就是这样:
实体界面
port
(
-- SPI
SPI_MOSI: in std_logic;
SPI_MISO: out std_logic;
SPI_CLK: in std_logic;
);
end interface;
architecture Behavioral of interface is
-- SPI
signal SPI_REG: std_logic_vector(7 downto 0) := (others => '0');
-- SPI interface
process(SPI_CLK)
begin
SPI_MISO <= SPI_REG(7);
if rising_edge(SPI_CLK) then
SPI_REG <= SPI_REG(6 downto 0) & SPI_MOSI; -- Concatenate bits
end if;
end process;
end Behavioral;
输入需要8个时钟周期才能出现在输出端,而不是9。