Browse Source

add generic G_DATA_DIR to set if we want transfer from LSB to MSB ore vice versa

pull/1/head
T. Meissner 10 years ago
parent
commit
5c06158fac
3 changed files with 62 additions and 11 deletions
  1. +14
    -5
      syn/SpiMasterE.vhd
  2. +13
    -4
      syn/SpiSlaveE.vhd
  3. +35
    -2
      test/SpiT.vhd

+ 14
- 5
syn/SpiMasterE.vhd View File

@ -1,11 +1,13 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity SpiMasterE is
generic (
G_DATA_WIDTH : positive := 8; --* data bus width
G_DATA_DIR : natural range 0 to 1 := 0; --* start from lsb/msb 0/1
G_SPI_CPOL : natural range 0 to 1 := 0; --* SPI clock polarity
G_SPI_CPHA : natural range 0 to 1 := 0; --* SPI clock phase
G_SCLK_DIVIDER : positive range 6 to positive'high := 10 --* SCLK divider related to system clock
@ -57,6 +59,9 @@ architecture rtl of SpiMasterE is
alias a_miso : std_logic is s_miso_d(s_miso_d'left);
constant C_BIT_COUNTER_START : natural := (G_DATA_WIDTH-1) * G_DATA_DIR;
constant C_BIT_COUNTER_END : natural := (G_DATA_WIDTH-1) * to_integer(not(to_unsigned(G_DATA_DIR, 1)));
begin
@ -96,7 +101,7 @@ begin
begin
if (Reset_n_i = '0') then
s_recv_register <= (others => '0');
v_bit_counter := G_DATA_WIDTH-1;
v_bit_counter := C_BIT_COUNTER_START;
v_sclk_counter := G_SCLK_DIVIDER-1;
s_transfer_valid <= false;
s_ste <= '1';
@ -111,7 +116,7 @@ begin
s_sclk <= std_logic'val(G_SPI_CPOL+2);
s_mosi <= '0';
s_recv_register <= (others => '0');
v_bit_counter := G_DATA_WIDTH-1;
v_bit_counter := C_BIT_COUNTER_START;
v_sclk_counter := G_SCLK_DIVIDER/2-1;
s_transfer_valid <= false;
if(DataValid_i = '1' and s_data_accept = '1') then
@ -120,7 +125,7 @@ begin
end if;
when WRITE =>
if (G_SPI_CPHA = 0 and v_bit_counter = G_DATA_WIDTH-1) then
if (G_SPI_CPHA = 0 and v_bit_counter = C_BIT_COUNTER_START) then
s_mosi <= s_send_register(v_bit_counter);
s_spi_state <= READ;
else
@ -139,14 +144,18 @@ begin
s_sclk <= not(s_sclk);
s_recv_register(v_bit_counter) <= a_miso;
v_sclk_counter := G_SCLK_DIVIDER/2-1;
if (v_bit_counter = 0) then
if (v_bit_counter = C_BIT_COUNTER_END) then
if (G_SPI_CPHA = 0) then
s_spi_state <= CYCLE;
else
s_spi_state <= STORE;
end if;
else
v_bit_counter := v_bit_counter - 1;
if (G_DATA_DIR = 0) then
v_bit_counter := v_bit_counter + 1;
else
v_bit_counter := v_bit_counter - 1;
end if;
s_spi_state <= WRITE;
end if;
else


+ 13
- 4
syn/SpiSlaveE.vhd View File

@ -1,11 +1,13 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity SpiSlaveE is
generic (
G_DATA_WIDTH : positive := 8; --* data bus width
G_DATA_DIR : natural range 0 to 1 := 0; --* start from lsb/msb 0/1
G_SPI_CPOL : natural range 0 to 1 := 0; --* SPI clock polarity
G_SPI_CPHA : natural range 0 to 1 := 0 --* SPI clock phase
);
@ -56,6 +58,9 @@ architecture rtl of SpiSlaveE is
alias a_ste : std_logic is s_ste_d(s_ste_d'left);
alias a_mosi : std_logic is s_mosi_d(s_mosi_d'left);
constant C_BIT_COUNTER_START : natural := (G_DATA_WIDTH-1) * G_DATA_DIR;
constant C_BIT_COUNTER_END : natural := (G_DATA_WIDTH-1) * to_integer(not(to_unsigned(G_DATA_DIR, 1)));
begin
@ -114,7 +119,7 @@ begin
if (Reset_n_i = '0') then
s_miso <= '0';
s_recv_register <= (others => '0');
v_bit_counter := G_DATA_WIDTH-1;
v_bit_counter := C_BIT_COUNTER_START;
s_transfer_valid <= false;
s_spi_state <= IDLE;
elsif rising_edge(Clk_i) then
@ -123,7 +128,7 @@ begin
when IDLE =>
s_miso <= '0';
s_recv_register <= (others => '0');
v_bit_counter := G_DATA_WIDTH-1;
v_bit_counter := C_BIT_COUNTER_START;
s_transfer_valid <= false;
if (a_ste = '0') then
if (G_SPI_CPHA = 0) then
@ -135,10 +140,14 @@ begin
when TRANSFER =>
if s_read_edge then
s_recv_register(v_bit_counter) <= a_mosi;
if (v_bit_counter = 0) then
if (v_bit_counter = C_BIT_COUNTER_END) then
s_spi_state <= STORE;
else
v_bit_counter := v_bit_counter - 1;
if (G_DATA_DIR = 0) then
v_bit_counter := v_bit_counter + 1;
else
v_bit_counter := v_bit_counter - 1;
end if;
end if;
elsif s_write_edge then
s_miso <= s_send_register(v_bit_counter);


+ 35
- 2
test/SpiT.vhd View File

@ -31,6 +31,7 @@ architecture sim of SpiT is
component SpiMasterE is
generic (
G_DATA_WIDTH : positive := 8;
G_DATA_DIR : natural range 0 to 1 := 0;
G_SPI_CPOL : natural range 0 to 1 := 0;
G_SPI_CPHA : natural range 0 to 1 := 0;
G_SCLK_DIVIDER : positive range 6 to positive'high := 10
@ -58,6 +59,7 @@ architecture sim of SpiT is
component SpiSlaveE is
generic (
G_DATA_WIDTH : positive := 8;
G_DATA_DIR : natural range 0 to 1 := 0;
G_SPI_CPOL : natural range 0 to 1 := 0;
G_SPI_CPHA : natural range 0 to 1 := 0
);
@ -130,6 +132,15 @@ begin
begin
--* Stimuli generator and BFM for the valid-accept interface
--* on the local data input of the DUT
--*
--* Generates random stimuli and serves it to the
--* valid-accept interface at the input of the DUT
--*
--* The stimuli data is also pushed into the mosi queue
--* which serves as simple abstract reference model
--* of the SPI transmit (master -> slave) channel
SpiMasterStimP : process is
variable v_random : RandomPType;
begin
@ -149,9 +160,11 @@ begin
end process SpiMasterStimP;
--* DUT: SpiMasterE component
i_SpiMasterE : SpiMasterE
generic map (
G_DATA_WIDTH => C_DATA_WIDTH,
G_DATA_DIR => 1,
G_SPI_CPOL => mode / 2,
G_SPI_CPHA => mode mod 2,
G_SCLK_DIVIDER => 10
@ -175,6 +188,13 @@ begin
);
--* Checker and BFM for the valid-accept interface
--* on the local data output of the DUT
--*
--* Reads the output of the DUT and compares it to
--* data popped from the miso queue which serves as
--* simple abstract reference model of the SPI receive
--* (slave -> master) channel
SpiMasterCheckP : process is
variable v_queue_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0');
begin
@ -194,8 +214,20 @@ begin
end process SpiMasterCheckP;
-- Unit test of spi slave procedure, checks all combinations
-- of cpol & cpha against spi master procedure
--* Stimuli generator and BFM for the SPI slave
--* interface on the SPI miso input of the DUT
--*
--* Generates random stimuli and serves it to the
--* SPI interface at the input of the DUT
--*
--* The stimuli data is also pushed into the miso queue
--* which serves as simple abstract reference model
--* of the SPI receive (slave -> master) channel
--*
--* Furthermore the data received by the SPI slave BFM
--* is checked against data popped from the mosi queue
--* which serves as simple abstract reference model of
--* the SPI receive (master -> slave) channel
SpiSlaveP : process is
variable v_send_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0');
variable v_receive_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0');
@ -307,6 +339,7 @@ begin
i_SpiSlaveE : SpiSlaveE
generic map (
G_DATA_WIDTH => C_DATA_WIDTH,
G_DATA_DIR => 1,
G_SPI_CPOL => mode / 2,
G_SPI_CPHA => mode mod 2
)


Loading…
Cancel
Save