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; library ieee;
use ieee.std_logic_1164.all; use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity SpiMasterE is entity SpiMasterE is
generic ( generic (
G_DATA_WIDTH : positive := 8; --* data bus width 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_CPOL : natural range 0 to 1 := 0; --* SPI clock polarity
G_SPI_CPHA : natural range 0 to 1 := 0; --* SPI clock phase 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 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); 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 begin
@ -96,7 +101,7 @@ begin
begin begin
if (Reset_n_i = '0') then if (Reset_n_i = '0') then
s_recv_register <= (others => '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-1; v_sclk_counter := G_SCLK_DIVIDER-1;
s_transfer_valid <= false; s_transfer_valid <= false;
s_ste <= '1'; s_ste <= '1';
@ -111,7 +116,7 @@ begin
s_sclk <= std_logic'val(G_SPI_CPOL+2); s_sclk <= std_logic'val(G_SPI_CPOL+2);
s_mosi <= '0'; s_mosi <= '0';
s_recv_register <= (others => '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; v_sclk_counter := G_SCLK_DIVIDER/2-1;
s_transfer_valid <= false; s_transfer_valid <= false;
if(DataValid_i = '1' and s_data_accept = '1') then if(DataValid_i = '1' and s_data_accept = '1') then
@ -120,7 +125,7 @@ begin
end if; end if;
when WRITE => 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_mosi <= s_send_register(v_bit_counter);
s_spi_state <= READ; s_spi_state <= READ;
else else
@ -139,14 +144,18 @@ begin
s_sclk <= not(s_sclk); s_sclk <= not(s_sclk);
s_recv_register(v_bit_counter) <= a_miso; s_recv_register(v_bit_counter) <= a_miso;
v_sclk_counter := G_SCLK_DIVIDER/2-1; 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 if (G_SPI_CPHA = 0) then
s_spi_state <= CYCLE; s_spi_state <= CYCLE;
else else
s_spi_state <= STORE; s_spi_state <= STORE;
end if; end if;
else 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; s_spi_state <= WRITE;
end if; end if;
else else


+ 13
- 4
syn/SpiSlaveE.vhd View File

@ -1,11 +1,13 @@
library ieee; library ieee;
use ieee.std_logic_1164.all; use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity SpiSlaveE is entity SpiSlaveE is
generic ( generic (
G_DATA_WIDTH : positive := 8; --* data bus width 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_CPOL : natural range 0 to 1 := 0; --* SPI clock polarity
G_SPI_CPHA : natural range 0 to 1 := 0 --* SPI clock phase 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_ste : std_logic is s_ste_d(s_ste_d'left);
alias a_mosi : std_logic is s_mosi_d(s_mosi_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 begin
@ -114,7 +119,7 @@ begin
if (Reset_n_i = '0') then if (Reset_n_i = '0') then
s_miso <= '0'; s_miso <= '0';
s_recv_register <= (others => '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_transfer_valid <= false;
s_spi_state <= IDLE; s_spi_state <= IDLE;
elsif rising_edge(Clk_i) then elsif rising_edge(Clk_i) then
@ -123,7 +128,7 @@ begin
when IDLE => when IDLE =>
s_miso <= '0'; s_miso <= '0';
s_recv_register <= (others => '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_transfer_valid <= false;
if (a_ste = '0') then if (a_ste = '0') then
if (G_SPI_CPHA = 0) then if (G_SPI_CPHA = 0) then
@ -135,10 +140,14 @@ begin
when TRANSFER => when TRANSFER =>
if s_read_edge then if s_read_edge then
s_recv_register(v_bit_counter) <= a_mosi; 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; s_spi_state <= STORE;
else 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; end if;
elsif s_write_edge then elsif s_write_edge then
s_miso <= s_send_register(v_bit_counter); 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 component SpiMasterE is
generic ( generic (
G_DATA_WIDTH : positive := 8; 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_CPOL : natural range 0 to 1 := 0;
G_SPI_CPHA : 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 G_SCLK_DIVIDER : positive range 6 to positive'high := 10
@ -58,6 +59,7 @@ architecture sim of SpiT is
component SpiSlaveE is component SpiSlaveE is
generic ( generic (
G_DATA_WIDTH : positive := 8; 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_CPOL : natural range 0 to 1 := 0;
G_SPI_CPHA : natural range 0 to 1 := 0 G_SPI_CPHA : natural range 0 to 1 := 0
); );
@ -130,6 +132,15 @@ begin
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 SpiMasterStimP : process is
variable v_random : RandomPType; variable v_random : RandomPType;
begin begin
@ -149,9 +160,11 @@ begin
end process SpiMasterStimP; end process SpiMasterStimP;
--* DUT: SpiMasterE component
i_SpiMasterE : SpiMasterE i_SpiMasterE : SpiMasterE
generic map ( generic map (
G_DATA_WIDTH => C_DATA_WIDTH, G_DATA_WIDTH => C_DATA_WIDTH,
G_DATA_DIR => 1,
G_SPI_CPOL => mode / 2, G_SPI_CPOL => mode / 2,
G_SPI_CPHA => mode mod 2, G_SPI_CPHA => mode mod 2,
G_SCLK_DIVIDER => 10 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 SpiMasterCheckP : process is
variable v_queue_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0'); variable v_queue_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0');
begin begin
@ -194,8 +214,20 @@ begin
end process SpiMasterCheckP; 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 SpiSlaveP : process is
variable v_send_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0'); 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'); variable v_receive_data : std_logic_vector(C_DATA_WIDTH-1 downto 0) := (others => '0');
@ -307,6 +339,7 @@ begin
i_SpiSlaveE : SpiSlaveE i_SpiSlaveE : SpiSlaveE
generic map ( generic map (
G_DATA_WIDTH => C_DATA_WIDTH, G_DATA_WIDTH => C_DATA_WIDTH,
G_DATA_DIR => 1,
G_SPI_CPOL => mode / 2, G_SPI_CPOL => mode / 2,
G_SPI_CPHA => mode mod 2 G_SPI_CPHA => mode mod 2
) )


Loading…
Cancel
Save