Browse Source

integrate VHDL-08 libraries

pull/1/head
T. Meissner 10 years ago
parent
commit
76f15e8c76
5 changed files with 235 additions and 89 deletions
  1. +18
    -14
      README.md
  2. +8
    -4
      sim/AssertP.vhd
  3. +8
    -0
      sim/SimP.vhd
  4. +6
    -8
      test/Makefile
  5. +195
    -63
      test/SpiT.vhd

+ 18
- 14
README.md View File

@ -25,12 +25,6 @@ Package with various components general useful for simulation
* `spi_master()` configurable master for SPI protocol, supports all cpol/cpha modes * `spi_master()` configurable master for SPI protocol, supports all cpol/cpha modes
* `spi_slave()` configurable slave for SPI protocol, supports all cpol/cpha modes * `spi_slave()` configurable slave for SPI protocol, supports all cpol/cpha modes
##### StringP
Package with various functions to convert to string
* `to_char(x)` returns string with binary value of std_logic x
* `to_string(x)` returns string with binary value of std_logic_vector x
##### QueueP ##### QueueP
Package with various implementations of queue types: Package with various implementations of queue types:
@ -41,12 +35,12 @@ Package with various implementations of queue types:
## syn ## syn
Synthesizable components for implementing in FPGA Synthesizable components for implementing in FPGA
##### SpiMasterE
Configurable SPI master with support modes 0-3 and simple VAI local backend.
##### SpiSlaveE ##### SpiSlaveE
Configurable SPI slave with support modes 0-3 and simple VAI local backend. Configurable SPI slave with support modes 0-3 and simple VAI local backend.
Implementation results:
* Microsemi SmartFusion2 (speed grade std): 49 logic elements, 397 MHz on
* Xilinx Kintex7 (speed grade -3): 24 slices, 649 MHz on
##test ##test
@ -61,16 +55,26 @@ Unit tests for components of SimP package
##### SpiT ##### SpiT
Unit tests for SpiSlave component Unit tests for SpiSlave component
##### StringT
Unit tests for components of SimP package
## Dependencies ## Dependencies
To run the tests, you have to install GHDL. You can get it from [http://sourceforge.net/projects/ghdl-updates/](http://sourceforge.net/projects/ghdl-updates/).
To run the tests, you have to install GHDL. You can get it from
[http://sourceforge.net/projects/ghdl-updates/](http://sourceforge.net/projects/ghdl-updates/).
Furthermore, you need the VHDL 2008 proposed packages because I'm using various VHDL 2008 features.
You can get the packages from [http://www.eda.org/fphdl/](http://www.eda.org/fphdl/).
Save the following files into the test folder:
* standard_additions_c.vhd
* standard_textio_additions_c.vhd
* std_logic_1164_additions.vhd
* numeric_std_additions.vhd
* numeric_std_unsigned_c.vhd
* env_c.vhd
Another useful tool is GTKWave, install it if you want to use the waveform files generated by some of the tests.
## Building ## Building
Type `make` and you should see the successfully running tests
Type `make` to do all tests. You should see the successfully running tests like this:
``` ```
$ make $ make


+ 8
- 4
sim/AssertP.vhd View File

@ -1,8 +1,12 @@
library ieee; library ieee;
use ieee.std_logic_1164.all; use ieee.std_logic_1164.all;
library libvhdl;
use libvhdl.StringP.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;
@ -77,7 +81,7 @@ package body AssertP is
begin begin
if (str'length = 0) then if (str'length = 0) then
assert a = b assert a = b
report integer'image(a) & " should be equal to " & integer'image(b)
report to_string(a) & " should be equal to " & integer'image(b)
severity level; severity level;
else else
assert a = b assert a = b
@ -125,7 +129,7 @@ package body AssertP is
begin begin
if (str'length = 0) then if (str'length = 0) then
assert a /= b assert a /= b
report integer'image(a) & " should not be equal to " & integer'image(b)
report to_string(a) & " should not be equal to " & integer'image(b)
severity level; severity level;
else else
assert a /= b assert a /= b


+ 8
- 0
sim/SimP.vhd View File

@ -1,11 +1,19 @@
library ieee; library ieee;
use ieee.std_logic_1164.all; 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; library libvhdl;
use libvhdl.AssertP.all; use libvhdl.AssertP.all;
package SimP is package SimP is


+ 6
- 8
test/Makefile View File

@ -3,7 +3,11 @@ SYN_SRC = ../syn
VHD_STD = 02 VHD_STD = 02
.PHONY: sim .PHONY: sim
sim: queuet stringt simt spit
sim: vhdl2008 queuet simt spit
.PHONY: vhdl2008
vhdl2008 : env_c.vhd numeric_std_additions.vhd numeric_std_unsigned_c.vhd standard_additions_c.vhd standard_textio_additions_c.vhd std_logic_1164_additions.vhd
ghdl -a --std=$(VHD_STD) --work=ieee_proposed standard_additions_c.vhd standard_textio_additions_c.vhd std_logic_1164_additions.vhd numeric_std_additions.vhd numeric_std_unsigned_c.vhd env_c.vhd
queuet : QueueT.vhd $(SIM_SRC)/QueueP.vhd $(SIM_SRC)/StringP.vhd $(SIM_SRC)/AssertP.vhd queuet : QueueT.vhd $(SIM_SRC)/QueueP.vhd $(SIM_SRC)/StringP.vhd $(SIM_SRC)/AssertP.vhd
ghdl -a --std=$(VHD_STD) --work=libvhdl $(SIM_SRC)/StringP.vhd $(SIM_SRC)/AssertP.vhd $(SIM_SRC)/QueueP.vhd ghdl -a --std=$(VHD_STD) --work=libvhdl $(SIM_SRC)/StringP.vhd $(SIM_SRC)/AssertP.vhd $(SIM_SRC)/QueueP.vhd
@ -11,13 +15,7 @@ queuet : QueueT.vhd $(SIM_SRC)/QueueP.vhd $(SIM_SRC)/StringP.vhd $(SIM_SRC)/Asse
ghdl -e --std=$(VHD_STD) QueueT ghdl -e --std=$(VHD_STD) QueueT
ghdl -r --std=$(VHD_STD) QueueT ghdl -r --std=$(VHD_STD) QueueT
stringt : StringT.vhd $(SIM_SRC)/StringP.vhd $(SIM_SRC)/AssertP.vhd
ghdl -a --std=$(VHD_STD) --work=libvhdl $(SIM_SRC)/StringP.vhd $(SIM_SRC)/AssertP.vhd
ghdl -a --std=$(VHD_STD) StringT.vhd
ghdl -e --std=$(VHD_STD) StringT
ghdl -r --std=$(VHD_STD) StringT
simt : SimT.vhd $(SIM_SRC)/StringP.vhd $(SIM_SRC)/AssertP.vhd $(SIM_SRC)/SimP.vhd
simt : vhdl2008 SimT.vhd $(SIM_SRC)/StringP.vhd $(SIM_SRC)/AssertP.vhd $(SIM_SRC)/SimP.vhd
ghdl -a --std=$(VHD_STD) --work=libvhdl $(SIM_SRC)/StringP.vhd $(SIM_SRC)/AssertP.vhd $(SIM_SRC)/SimP.vhd ghdl -a --std=$(VHD_STD) --work=libvhdl $(SIM_SRC)/StringP.vhd $(SIM_SRC)/AssertP.vhd $(SIM_SRC)/SimP.vhd
ghdl -a --std=$(VHD_STD) SimT.vhd ghdl -a --std=$(VHD_STD) SimT.vhd
ghdl -e --std=$(VHD_STD) SimT ghdl -e --std=$(VHD_STD) SimT


+ 195
- 63
test/SpiT.vhd View File

@ -3,10 +3,15 @@ library ieee;
use ieee.numeric_std.all; use ieee.numeric_std.all;
library libvhdl; library libvhdl;
use libvhdl.StringP.all;
use libvhdl.AssertP.all; use libvhdl.AssertP.all;
use libvhdl.SimP.all; use libvhdl.SimP.all;
--+ including vhdl 2008 libraries
library ieee_proposed;
use ieee_proposed.standard_additions.all;
use ieee_proposed.std_logic_1164_additions.all;
use ieee_proposed.numeric_std_additions.all;
entity SpiT is entity SpiT is
@ -17,6 +22,33 @@ end entity SpiT;
architecture sim of SpiT is architecture sim of SpiT is
component SpiMasterE is
generic (
G_DATA_WIDTH : positive := 8;
G_SPI_CPOL : natural range 0 to 1 := 0;
G_SPI_CPHA : natural range 0 to 1 := 0;
G_SCLK_DIVIDER : positive := 10
);
port (
--+ system if
Reset_n_i : in std_logic;
Clk_i : in std_logic;
--+ SPI slave if
SpiSclk_o : out std_logic;
SpiSte_o : out std_logic;
SpiMosi_o : out std_logic;
SpiMiso_i : in std_logic;
--+ local VAI if
Data_i : in std_logic_vector(G_DATA_WIDTH-1 downto 0);
DataValid_i : in std_logic;
DataAccept_o : out std_logic;
Data_o : out std_logic_vector(G_DATA_WIDTH-1 downto 0);
DataValid_o : out std_logic;
DataAccept_i : in std_logic
);
end component SpiMasterE;
component SpiSlaveE is component SpiSlaveE is
generic ( generic (
G_DATA_WIDTH : positive := 8; G_DATA_WIDTH : positive := 8;
@ -43,86 +75,185 @@ architecture sim of SpiT is
end component SpiSlaveE; end component SpiSlaveE;
--* testbench global clock period
constant C_PERIOD : time := 5 ns; constant C_PERIOD : time := 5 ns;
--* SPI data transfer data width
constant C_DATA_WIDTH : natural := 8; constant C_DATA_WIDTH : natural := 8;
signal s_done : boolean := false;
--* testbench global clock
signal s_clk : std_logic := '0'; signal s_clk : std_logic := '0';
--* testbench global reset
signal s_reset_n : std_logic := '0'; signal s_reset_n : std_logic := '0';
signal s_sclk : std_logic;
signal s_ste : std_logic;
signal s_mosi : std_logic;
signal s_miso : std_logic;
--* SPI mode range subtype
subtype t_spi_mode is natural range 0 to 3; subtype t_spi_mode is natural range 0 to 3;
signal s_spi_mode : t_spi_mode;
--+ test done array with entry for each test
signal s_test_done : boolean_vector(t_spi_mode'low to 2*t_spi_mode'high+1) := (others => false);
begin begin
s_clk <= not(s_clk) after C_PERIOD when not(s_done) else '0';
--* testbench global clock
s_clk <= not(s_clk) after C_PERIOD/2 when not(and_reduce(s_test_done)) else '0';
--* testbench global reset
s_reset_n <= '1' after 100 ns; s_reset_n <= '1' after 100 ns;
-- Unit test of spi master procedure, checks all combinations
-- of cpol & cpha against spi slave procedure
SpiMasterP : process is
variable v_slave_data : std_logic_vector(C_DATA_WIDTH-1 downto 0);
begin
s_sclk <= '1';
s_ste <= '1';
s_mosi <= '1';
s_spi_mode <= 0;
wait until s_reset_n = '1';
for mode in 0 to 3 loop
s_spi_mode <= mode;
for i in 0 to integer'(2**C_DATA_WIDTH-1) loop
spi_master (data_in => std_logic_vector(to_unsigned(i, C_DATA_WIDTH)),
data_out => v_slave_data,
sclk => s_sclk,
ste => s_ste,
mosi => s_mosi,
miso => s_miso,
cpol => mode / 2,
cpha => mode mod 2,
period => 1 us
);
assert_equal(v_slave_data, std_logic_vector(to_unsigned(i, C_DATA_WIDTH)));
end loop;
report "INFO: SPI mode " & integer'image(mode) & " test successfully";
end loop;
report "INFO: SpiSlaveE tests finished successfully";
s_done <= true;
wait;
end process SpiMasterP;
--+ spi ste demultiplexing
SpiMastersG : for mode in t_spi_mode'low to t_spi_mode'high generate
--+ spi ste demultiplexing
SpiSlavesG : for mode in t_spi_mode'low to t_spi_mode'high generate
signal s_sclk : std_logic;
signal s_ste : std_logic;
signal s_mosi : std_logic;
signal s_miso : std_logic;
subtype t_control_array is std_logic_vector(t_spi_mode'low to t_spi_mode'high);
signal s_spislave_ste : t_control_array;
signal s_din : std_logic_vector(C_DATA_WIDTH-1 downto 0);
signal s_din_valid : std_logic;
signal s_din_accept : std_logic;
signal s_dout : std_logic_vector(C_DATA_WIDTH-1 downto 0);
signal s_dout_valid : std_logic;
signal s_dout_accept : std_logic;
type t_data_array is array (t_spi_mode'low to t_spi_mode'high) of std_logic_vector(C_DATA_WIDTH-1 downto 0);
signal s_din : t_data_array;
signal s_dout : t_data_array;
signal s_dout_valid : t_control_array;
signal s_dout_accept : t_control_array;
begin
begin
SpiMasterStimP : process is
begin
wait until s_reset_n = '1';
for i in 0 to integer'(2**C_DATA_WIDTH-1) loop
s_din <= std_logic_vector(to_unsigned(i, C_DATA_WIDTH));
s_din_valid <= '1';
wait until rising_edge(s_clk) and s_din_accept = '1';
s_din_valid <= '0';
wait until rising_edge(s_clk);
end loop;
wait;
end process SpiMasterStimP;
s_din(mode) <= std_logic_vector(unsigned(s_dout(mode)) + 1);
i_SpiMasterE : SpiMasterE
generic map (
G_DATA_WIDTH => 8,
G_SPI_CPOL => mode / 2,
G_SPI_CPHA => mode mod 2,
G_SCLK_DIVIDER => 10
)
port map (
--+ system if
Reset_n_i => s_reset_n,
Clk_i => s_clk,
--+ SPI slave if
SpiSclk_o => s_sclk,
SpiSte_o => s_ste,
SpiMosi_o => s_mosi,
SpiMiso_i => s_miso,
--+ local VAI if
Data_i => s_din,
DataValid_i => s_din_valid,
DataAccept_o => s_din_accept,
Data_o => s_dout,
DataValid_o => s_dout_valid,
DataAccept_i => s_dout_accept
);
s_spislave_ste(mode) <= s_ste when s_spi_mode = mode else '1';
i0_SpiSlaveE : SpiSlaveE
SpiMasterCheckP : process is
begin
wait until s_reset_n = '1';
for i in 0 to integer'(2**C_DATA_WIDTH-1) loop
wait until rising_edge(s_clk) and s_dout_valid = '1';
s_dout_accept <= '1';
assert_equal(s_dout, std_logic_vector(to_unsigned(i, C_DATA_WIDTH)));
wait until rising_edge(s_clk);
s_dout_accept <= '0';
end loop;
report "INFO: SpiMaster (mode=" & to_string(mode) & ") test successfully";
s_test_done(mode) <= true;
wait;
end process SpiMasterCheckP;
-- Unit test of spi slave procedure, checks all combinations
-- of cpol & cpha against spi master procedure
SpiSlaveP : process is
variable v_master_data : std_logic_vector(7 downto 0) := (others => '0');
begin
for i in 0 to integer'(2**C_DATA_WIDTH-1) loop
spi_slave (data_in => v_master_data,
data_out => v_master_data,
sclk => s_sclk,
ste => s_ste,
mosi => s_mosi,
miso => s_miso,
cpol => mode / 2,
cpha => mode mod 2
);
assert_equal(v_master_data, std_logic_vector(to_unsigned(i, C_DATA_WIDTH)));
v_master_data := std_logic_vector(unsigned(v_master_data) + 1);
end loop;
wait;
end process SpiSlaveP;
end generate SpiMastersG;
--+ spi ste demultiplexing
SpiSlavesG : for mode in t_spi_mode'low to t_spi_mode'high generate
signal s_sclk : std_logic;
signal s_ste : std_logic;
signal s_mosi : std_logic;
signal s_miso : std_logic;
signal s_din : std_logic_vector(C_DATA_WIDTH-1 downto 0);
signal s_dout : std_logic_vector(C_DATA_WIDTH-1 downto 0);
signal s_dout_valid : std_logic;
signal s_dout_accept : std_logic;
begin
-- Unit test of spi master procedure, checks all combinations
-- of cpol & cpha against spi slave procedure
SpiMasterP : process is
variable v_slave_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0');
begin
s_sclk <= '1';
s_ste <= '1';
s_mosi <= '1';
wait until s_reset_n = '1';
for i in 0 to integer'(2**C_DATA_WIDTH-1) loop
spi_master (data_in => std_logic_vector(to_unsigned(i, C_DATA_WIDTH)),
data_out => v_slave_data,
sclk => s_sclk,
ste => s_ste,
mosi => s_mosi,
miso => s_miso,
cpol => mode / 2,
cpha => mode mod 2,
period => 100 ns
);
assert_equal(v_slave_data, std_logic_vector(to_unsigned(i, C_DATA_WIDTH)));
end loop;
report "INFO: SpiSlave (mode=" & to_string(mode) & ") test successfully";
s_test_done(mode+4) <= true;
wait;
end process SpiMasterP;
s_din <= std_logic_vector(unsigned(s_dout) + 1);
i_SpiSlaveE : SpiSlaveE
generic map ( generic map (
G_DATA_WIDTH => 8, G_DATA_WIDTH => 8,
G_SPI_CPOL => mode / 2, G_SPI_CPOL => mode / 2,
@ -134,20 +265,21 @@ begin
Clk_i => s_clk, Clk_i => s_clk,
--+ SPI slave if --+ SPI slave if
SpiSclk_i => s_sclk, SpiSclk_i => s_sclk,
SpiSte_i => s_spislave_ste(mode),
SpiSte_i => s_ste,
SpiMosi_i => s_mosi, SpiMosi_i => s_mosi,
SpiMiso_o => s_miso, SpiMiso_o => s_miso,
--+ local VAI if --+ local VAI if
Data_i => s_din(mode),
DataValid_i => s_dout_valid(mode),
DataAccept_o => s_dout_accept(mode),
Data_o => s_dout(mode),
DataValid_o => s_dout_valid(mode),
DataAccept_i => s_dout_accept(mode)
Data_i => s_din,
DataValid_i => s_dout_valid,
DataAccept_o => s_dout_accept,
Data_o => s_dout,
DataValid_o => s_dout_valid,
DataAccept_i => s_dout_accept
); );
end generate SpiSlavesG;
end generate SpiSlavesG;
end architecture sim; end architecture sim;

Loading…
Cancel
Save