Skip to content

Commit

Permalink
DEVEL:spi_tri_o port added to spi_master for 3-wires SPI IF (#62)
Browse files Browse the repository at this point in the history
  • Loading branch information
FD82 authored Sep 16, 2024
1 parent bf3c80b commit bbed262
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 7 deletions.
8 changes: 6 additions & 2 deletions doc/files/psi_common_spi_master.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ applied on the first edge (red). For CPHA = 0 it is the opposite way.
| slave_cnt_g | positive | Number of slaves to support (number of *Cs\_n* lines)
| lsb_first_g | boolean | **False** = MSB first transmission, **True** = LSB first transmission
| mosi_idle_state_g | std_logic | Idle state of the MOSI line
| rst_pol_g | std_logic | reset polarity |
| rst_pol_g | std_logic | Reset polarity
| read_bit_pol_g | std_logic | Polarity of Read operation in RW bit in MOSI word (needed in 3-Wires SPI)
| tri_state_pol_g | std_logic | Polarity of tristate signal in case of a 3-Wires SPI
| spi_data_pos_g | positive | Starting bit position of Data in MOSI word (needed in 3-Wires SPI)

### Interfaces
| Name | In/Out | Length | Description |
Expand All @@ -49,7 +52,8 @@ applied on the first edge (red). For CPHA = 0 it is the opposite way.
| dat_o | o | trans_width_g | Data received from slave. Must be sampled during *Done = '1'* or *Busy = '0'*.
| spi_sck_o | o | 1 | SPI clock
| spi_mosi_o | o | 1 | SPI master to slave data signal
| spi_miso_i | i | 1 | SPI slave to master data signal
| spi_miso_i | i | 1 | SPI slave to master data signal
| spi_tri_o | o | 1 | SPI tri-state buffer select if 3-wires SPI is used
| spi_cs_n_o | o | slave_cnt_g | SPI slave select signal (low active)
| spi_le_o | o | slave_cnt_g | SPI slave latch enable (high active)

Expand Down
30 changes: 26 additions & 4 deletions hdl/psi_common_spi_master.vhd
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
------------------------------------------------------------------------------
-- Copyright (c) 2018 by Paul Scherrer Institute, Switzerland
-- All rights reserved.
-- Copyright (c) 2018 by Paul Scherrer Institute, Switzerland
-- All rights reserved.
-- Authors: Oliver Bruendler
------------------------------------------------------------------------------

Expand All @@ -27,8 +27,11 @@ entity psi_common_spi_master is
slave_cnt_g : positive := 1; -- Number if slaves to support
lsb_first_g : boolean := false; -- False = MSB first trasnmission and True LSB
mosi_idle_state_g : std_logic := '0'; -- Idle state of the MOSI line
rst_pol_g : std_logic:= '1'); -- reset polarity
port( -- Control Signals
rst_pol_g : std_logic:= '1'; -- Reset polarity
read_bit_pol_g : std_logic := '1'; -- Polarity of Read operation in RW bit in MOSI word (needed in 3-Wires SPI)
tri_state_pol_g : std_logic := '1'; -- Polarity of tristate signal in case of a 3-Wires SPI
spi_data_pos_g : positive := 3); -- Starting bit position of Data in MOSI word (needed in 3-Wires SPI)
port( -- Control Signals
clk_i : in std_logic; -- system clock
rst_i : in std_logic; -- system reset (sync)
-- Parallel Interface
Expand All @@ -42,6 +45,7 @@ entity psi_common_spi_master is
spi_sck_o : out std_logic; -- SPI clock
spi_mosi_o : out std_logic; -- SPI master to slave data signal
spi_miso_i : in std_logic; -- SPI slave to master data signal
spi_tri_o : out std_logic; -- SPI tri-state buffer select if 3-wires SPI is used
spi_cs_n_o : out std_logic_vector(slave_cnt_g - 1 downto 0); -- SPI slave select signal (low active)
spi_le_o : out std_logic_vector(slave_cnt_g - 1 downto 0)); -- SPI slave latch enable (high active)
end entity;
Expand All @@ -54,17 +58,20 @@ architecture rtl of psi_common_spi_master is

-- *** Constants ***
constant ClkDivThres_c : natural := clk_div_g / 2 - 1;
constant BitCntDataPos_c : natural := trans_width_g - spi_data_pos_g;

-- *** Two Process Method ***
type two_process_r is record
State : State_t;
StateLast : State_t;
IsRead : std_logic;
ShiftReg : std_logic_vector(trans_width_g - 1 downto 0);
dat_o : std_logic_vector(trans_width_g - 1 downto 0);
spi_cs_n_o : std_logic_vector(slave_cnt_g - 1 downto 0);
spi_le_o : std_logic_vector(slave_cnt_g - 1 downto 0);
spi_sck_o : std_logic;
spi_mosi_o : std_logic;
spi_tri_o : std_logic;
ClkDivCnt : integer range 0 to ClkDivThres_c;
BitCnt : integer range 0 to trans_width_g;
CsHighCnt : integer range 0 to cs_high_cycles_g - 1;
Expand Down Expand Up @@ -127,6 +134,7 @@ begin
-- Start of Transfer
if start_i = '1' then
v.ShiftReg := dat_i;
v.IsRead := dat_i (trans_width_g - 1);
v.spi_cs_n_o(to_integer(unsigned(slave_i))) := '0';
v.State := SftComp_s;
v.busy_o := '1';
Expand All @@ -148,6 +156,10 @@ begin
if r.ClkDivCnt = 0 then
if spi_cpha_g = 0 then
v.spi_mosi_o := r.MosiNext;
-- Only for 3-Wires SPI
if r.BitCnt = BitCntDataPos_c and r.IsRead = read_bit_pol_g then
v.spi_tri_o := tri_state_pol_g;
end if;
else
ShiftReg(r.ShiftReg, v.ShiftReg, spi_miso_i, v.MosiNext);
end if;
Expand All @@ -159,6 +171,7 @@ begin
v.spi_mosi_o := mosi_idle_state_g;
v.State := CsHigh_s;
v.spi_le_o := not r.spi_cs_n_o;
v.spi_tri_o := not tri_state_pol_g;
-- Otherwise contintue
else
v.State := ClkAct_s;
Expand All @@ -174,6 +187,10 @@ begin
if r.ClkDivCnt = 0 then
if spi_cpha_g = 1 then
v.spi_mosi_o := r.MosiNext;
-- Only for 3-Wires SPI
if r.BitCnt = BitCntDataPos_c and r.IsRead = read_bit_pol_g then
v.spi_tri_o := tri_state_pol_g;
end if;
else
ShiftReg(r.ShiftReg, v.ShiftReg, spi_miso_i, v.MosiNext);
end if;
Expand All @@ -190,6 +207,7 @@ begin
when CsHigh_s =>
v.spi_mosi_o := '0';
v.spi_cs_n_o := (others => '1');
v.spi_tri_o := not tri_state_pol_g;
if r.CsHighCnt = cs_high_cycles_g - 1 then
v.State := Idle_s;
v.busy_o := '0';
Expand All @@ -213,6 +231,7 @@ begin
spi_sck_o <= r.spi_sck_o;
spi_cs_n_o <= r.spi_cs_n_o;
spi_mosi_o <= r.spi_mosi_o;
spi_tri_o <= r.spi_tri_o;
spi_le_o <= r.spi_le_o;
p_seq : process(clk_i)
begin
Expand All @@ -226,9 +245,12 @@ begin
r.busy_o <= '0';
r.done_o <= '0';
r.spi_mosi_o <= mosi_idle_state_g;
r.spi_tri_o <= '0';
end if;
end if;
end process;

end architecture;



14 changes: 13 additions & 1 deletion testbench/psi_common_spi_master_tb/psi_common_spi_master_tb.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ architecture sim of psi_common_spi_master_tb is
constant trans_width_g : positive := 8;
constant cs_high_cycles_g : positive := 12;
constant slave_cnt_g : positive := 2;
constant rst_pol_g : std_logic:= '1';
constant mosi_idle_state_g : std_logic := '0';
constant read_bit_pol_g : std_logic := '1';
constant tri_state_pol_g : std_logic := '1';
constant spi_data_pos_g : positive := 3;

-- *** Not Assigned Generics (default values) ***

Expand All @@ -69,6 +74,7 @@ architecture sim of psi_common_spi_master_tb is
signal spi_sck_o : std_logic := '0';
signal spi_mosi_o : std_logic := '0';
signal spi_miso_i : std_logic := '0';
signal spi_tri_o : std_logic := '0';
signal spi_le_o : std_logic_vector(slave_cnt_g-1 downto 0) := (others => '0');
signal spi_cs_n_o : std_logic_vector(slave_cnt_g - 1 downto 0) := (others => '0');

Expand All @@ -92,7 +98,12 @@ begin
clk_div_g => clk_div_g,
trans_width_g => trans_width_g,
cs_high_cycles_g => cs_high_cycles_g,
slave_cnt_g => slave_cnt_g
slave_cnt_g => slave_cnt_g,
mosi_idle_state_g => mosi_idle_state_g,
rst_pol_g => rst_pol_g,
read_bit_pol_g => read_bit_pol_g,
tri_state_pol_g => tri_state_pol_g,
spi_data_pos_g => spi_data_pos_g
)
port map(
clk_i => clk_i,
Expand All @@ -106,6 +117,7 @@ begin
spi_sck_o => spi_sck_o,
spi_mosi_o => spi_mosi_o,
spi_miso_i => spi_miso_i,
spi_tri_o => spi_tri_o,
spi_cs_n_o => spi_cs_n_o,
spi_le_o => spi_le_o
);
Expand Down

0 comments on commit bbed262

Please sign in to comment.