我实现了非常简单的SPI从接口:8位,MSB优先,pol = 1 pha = 1。不需要CS引脚和SO的“Z”状态。最大SPI SCK为8 MHz。系统时钟50 MHz 代码:
entity spi_slave_if is Port (
si : in STD_LOGIC;
sck : in STD_LOGIC;
so : out STD_LOGIC;
clk : in std_logic;
reset : in std_logic;
data_out : in std_logic_vector(7 downto 0); -- data for send
data_in : out std_logic_vector(7 downto 0); -- received data
transaction_done : out std_logic);
end spi_slave_if;
architecture Behavioral of spi_slave_if is
signal cur_bit, prev_bit: unsigned(2 downto 0);
begin
process(sck) begin
if falling_edge(sck) then
so <= data_out(to_integer(cur_bit));
end if;
end process;
process(sck, reset) begin
if (reset = '1') then
data_in <= (others => '0');
cur_bit <= to_unsigned(7, 3);
elsif rising_edge(sck) then
data_in(to_integer(cur_bit)) <= si;
cur_bit <= cur_bit - 1;
end if;
end process;
process(clk, reset)
variable td_raised: boolean;
begin
if reset = '1' then
prev_bit <= to_unsigned(7, 3);
td_raised := false;
transaction_done <= '0';
elsif falling_edge(clk) then
prev_bit <= cur_bit;
if td_raised then
transaction_done <= '0';
td_raised := false;
elsif (to_integer(prev_bit) = 0 and to_integer(cur_bit) = 7 ) then
transaction_done <= '1';
td_raised := true;
end if;
end if;
end process;
end Behavioral;
在testbench中,我尝试建模异步主接口(随机数据字节)和随机延迟:
loop
UNIFORM(seed1, seed2, rand);
int_rand := INTEGER(TRUNC(rand*255.0)); -- rescale to 0..255
test_1_transact(125 ns, std_logic_vector(to_unsigned(int_rand, 8)));
wait for 1us; -- model async delay
wait for ((rand*0.00000001)*1 sec);
wait for ((rand*0.000000001)*1 sec);
wait for ((rand*0.0000000001)*1 sec);
end loop;
test_1_transact是:
procedure test_1_transact(constant prd : time; constant si_data : std_logic_vector (7 downto 0)) is begin
data_out <= not si_data; --for back test invert dorward data
wait for 20ns; -- wait for data apply
FOR i IN 7 downto 0 LOOP
si <= si_data(i);
sck <= '0'; wait for prd / 2;
sck <= '1'; wait for prd / 2;
END LOOP;
end procedure;
当我做behevioral模拟代码一直工作正常。 但是当我尝试执行路径后模拟时,代码也会先工作47us,但之后就失败了,ISIM说我:
at 49422978 ps(3), Instance /test_spi_slv_if/uut/prev_bit_0/ : Warning: /X_FF HOLD Low VIOLATION ON I WITH RESPECT TO CLK;
Expected := 0.048 ns; Observed := 0.036 ns; At : 49422.978 ns
at 49922978 ps(3), Instance /test_spi_slv_if/uut/prev_bit_0/ : Warning: /X_FF HOLD Low VIOLATION ON I WITH RESPECT TO CLK;
Expected := 0.048 ns; Observed := 0.036 ns; At : 49922.978 ns
在这一刻transaction_done
不起作用。
vhdl是否有某种方法可以解决这个问题?