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