-- Copyright (c) 2014 - 2022 by Torsten Meissner
|
|
--
|
|
-- Licensed under the Apache License, Version 2.0 (the "License");
|
|
-- you may not use this file except in compliance with the License.
|
|
-- You may obtain a copy of the License at
|
|
--
|
|
-- https://www.apache.org/licenses/LICENSE-2.0
|
|
--
|
|
-- Unless required by applicable law or agreed to in writing, software
|
|
-- distributed under the License is distributed on an "AS IS" BASIS,
|
|
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
-- See the License for the specific language governing permissions and
|
|
-- limitations under the License.
|
|
|
|
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
|
|
--+ including vhdl 2008 libraries
|
|
--+ These lines can be commented out when using
|
|
--+ a simulator with built-in VHDL 2008 support
|
|
--library ieee_proposed;
|
|
-- use ieee_proposed.standard_additions.all;
|
|
-- use ieee_proposed.std_logic_1164_additions.all;
|
|
|
|
library libvhdl;
|
|
use libvhdl.AssertP.all;
|
|
|
|
|
|
|
|
|
|
package SimP is
|
|
|
|
|
|
procedure wait_cycles (signal clk : in std_logic; n : in natural);
|
|
|
|
procedure spi_master ( data_in : in std_logic_vector; data_out : out std_logic_vector;
|
|
signal sclk : inout std_logic; signal ste : out std_logic;
|
|
signal mosi : out std_logic; signal miso : in std_logic;
|
|
dir : in natural range 0 to 1; cpol : in natural range 0 to 1;
|
|
cpha : in natural range 0 to 1; period : in time);
|
|
|
|
procedure spi_slave ( data_in : in std_logic_vector; data_out : out std_logic_vector;
|
|
signal sclk : in std_logic; signal ste : in std_logic;
|
|
signal mosi : in std_logic; signal miso : out std_logic;
|
|
dir : in natural range 0 to 1; cpol : in natural range 0 to 1;
|
|
cpha : in natural range 0 to 1);
|
|
|
|
|
|
end package SimP;
|
|
|
|
|
|
|
|
package body SimP is
|
|
|
|
|
|
-- wait for n rising edges on clk
|
|
procedure wait_cycles (signal clk : in std_logic; n : in natural) is
|
|
begin
|
|
for i in 1 to n loop
|
|
wait until rising_edge(clk);
|
|
end loop;
|
|
end procedure wait_cycles;
|
|
|
|
|
|
-- configurable spi master which supports all combinations of cpol & cpha
|
|
procedure spi_master ( data_in : in std_logic_vector; data_out : out std_logic_vector;
|
|
signal sclk : inout std_logic; signal ste : out std_logic;
|
|
signal mosi : out std_logic; signal miso : in std_logic;
|
|
dir : in natural range 0 to 1; cpol : in natural range 0 to 1;
|
|
cpha : in natural range 0 to 1; period : in time) is
|
|
begin
|
|
assert_equal(data_in'length, data_out'length, spi_master'simple_name & ": data_in & data_out must have same length!");
|
|
sclk <= std_logic'val(cpol+2);
|
|
ste <= '0';
|
|
if (cpha = 0) then
|
|
for i in data_in'range loop
|
|
if (dir = 0) then
|
|
mosi <= data_in(data_in'high - i);
|
|
else
|
|
mosi <= data_in(i);
|
|
end if;
|
|
wait for period/2;
|
|
sclk <= not(sclk);
|
|
if (dir = 0) then
|
|
data_out(data_out'high - i) := miso;
|
|
else
|
|
data_out(i) := miso;
|
|
end if;
|
|
wait for period/2;
|
|
sclk <= not(sclk);
|
|
end loop;
|
|
wait for period/2;
|
|
else
|
|
mosi <= '1';
|
|
wait for period/2;
|
|
for i in data_in'range loop
|
|
sclk <= not(sclk);
|
|
if (dir = 0) then
|
|
mosi <= data_in(data_in'high - i);
|
|
else
|
|
mosi <= data_in(i);
|
|
end if;
|
|
wait for period/2;
|
|
sclk <= not(sclk);
|
|
if (dir = 0) then
|
|
data_out(data_out'high - i) := miso;
|
|
else
|
|
data_out(i) := miso;
|
|
end if;
|
|
wait for period/2;
|
|
end loop;
|
|
end if;
|
|
ste <= '1';
|
|
mosi <= '1';
|
|
wait for period/2;
|
|
end procedure spi_master;
|
|
|
|
|
|
-- configurable spi slave which supports all combinations of cpol & cpha
|
|
procedure spi_slave ( data_in : in std_logic_vector; data_out : out std_logic_vector;
|
|
signal sclk : in std_logic; signal ste : in std_logic;
|
|
signal mosi : in std_logic; signal miso : out std_logic;
|
|
dir : in natural range 0 to 1; cpol : in natural range 0 to 1;
|
|
cpha : in natural range 0 to 1) is
|
|
variable v_cpol : std_logic := std_logic'val(cpol+2);
|
|
begin
|
|
assert_equal(data_in'length, data_out'length, spi_slave'simple_name & ": data_in & data_out must have same length!");
|
|
miso <= 'Z';
|
|
wait until ste = '0';
|
|
if (cpha = 0) then
|
|
for i in data_in'range loop
|
|
if (dir = 0) then
|
|
miso <= data_in(data_in'high - i);
|
|
else
|
|
miso <= data_in(i);
|
|
end if;
|
|
wait until sclk'event and sclk = not(v_cpol);
|
|
if (dir = 0) then
|
|
data_out(data_out'high - i) := mosi;
|
|
else
|
|
data_out(i) := mosi;
|
|
end if;
|
|
wait until sclk'event and sclk = v_cpol;
|
|
end loop;
|
|
else
|
|
for i in data_in'range loop
|
|
wait until sclk'event and sclk = not(v_cpol);
|
|
if (dir = 0) then
|
|
miso <= data_in(data_in'high - i);
|
|
else
|
|
miso <= data_in(i);
|
|
end if;
|
|
wait until sclk'event and sclk = v_cpol;
|
|
if (dir = 0) then
|
|
data_out(data_out'high - i) := mosi;
|
|
else
|
|
data_out(i) := mosi;
|
|
end if;
|
|
end loop;
|
|
end if;
|
|
wait until ste = '1';
|
|
miso <= 'Z';
|
|
end procedure spi_slave;
|
|
|
|
|
|
end package body SimP;
|