SURF  1.0
SpiSlave.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : SpiSlave.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2014-01-27
5 -- Last update: 2014-03-14
6 -------------------------------------------------------------------------------
7 -- Description: Generic SPI Slave Module
8 -------------------------------------------------------------------------------
9 -- This file is part of 'SLAC Firmware Standard Library'.
10 -- It is subject to the license terms in the LICENSE.txt file found in the
11 -- top-level directory of this distribution and at:
12 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html.
13 -- No part of 'SLAC Firmware Standard Library', including this file,
14 -- may be copied, modified, propagated, or distributed except according to
15 -- the terms contained in the LICENSE.txt file.
16 -------------------------------------------------------------------------------
17 
18 library ieee;
19 use ieee.std_logic_1164.all;
20 use ieee.std_logic_arith.all;
21 use ieee.std_logic_unsigned.all;
22 use work.StdRtlPkg.all;
23 
24 --! @see entity
25  --! @ingroup protocols_spi
26 entity SpiSlave is
27  generic (
28  TPD_G : time := 1 ns;
29  CPOL_G : sl := '0';
30  CPHA_G : sl := '1';
31  WORD_SIZE_G : positive := 16);
32  port (
33  clk : in sl;
34  rst : in sl;
35 
36  sclk : in sl;
37  mosi : in sl;
38  miso : out sl;
39  selL : in sl;
40 
41  rdData : in slv(WORD_SIZE_G-1 downto 0);
42  rdStb : in sl;
43 
44  wrData : out slv(WORD_SIZE_G-1 downto 0);
45  wrStb : out sl);
46 
47 end entity SpiSlave;
48 
49 architecture rtl of SpiSlave is
50 
51  constant MAX_COUNT_C : integer := WORD_SIZE_G-1;
52 
53  type RegType is
54  record
55  -- Input sync and edge detection regs
56  mosiLast : sl;
57  sclkLast : sl;
58  selLLast : sl;
59 
60  --Internal Shift regs and counters
61  shiftReg : slv(WORD_SIZE_G downto 0);
62  shiftCnt : slv(log2(WORD_SIZE_G)-1 downto 0);
63  gotSclk : sl;
64 
65  -- Outputs
66  wrStb : sl;
67  end record;
68 
69  constant REG_INIT_C : RegType := (
70  mosiLast => '0',
71  sclkLast => '0',
72  selLLast => '1',
73  shiftReg => (others => '0'),
74  shiftCnt => toSlv(MAX_COUNT_C, log2(WORD_SIZE_G)),
75  gotSclk => '0',
76  wrStb => '0');
77 
78  signal r : RegType := REG_INIT_C;
79  signal rin : RegType;
80 
81  signal mosiSync : sl;
82  signal sclkSync : sl;
83  signal selLSync : sl;
84 
85 begin
86 
87  SEL_SYNCHRONIZER : entity work.Synchronizer
88  generic map (
89  TPD_G => TPD_G,
90  STAGES_G => 3,
91  INIT_G => "111")
92  port map (
93  clk => clk,
94  rst => rst,
95  dataIn => selL,
96  dataOut => selLSync);
97 
98  SCLK_SYNCHRONIZER : entity work.Synchronizer
99  generic map (
100  TPD_G => TPD_G)
101  port map (
102  clk => clk,
103  rst => rst,
104  dataIn => sclk,
105  dataOut => sclkSync);
106 
107  MOSI_SYNCHRONIZER : entity work.Synchronizer
108  generic map (
109  TPD_G => TPD_G)
110  port map (
111  clk => clk,
112  rst => rst,
113  dataIn => mosi,
114  dataOut => mosiSync);
115 
116  seq : process (clk) is
117  begin
118  if (rising_edge(clk)) then
119  r <= rin after TPD_G;
120  end if;
121 
122  end process seq;
123 
124 
125  comb : process (mosiSync, r, rdData, rdStb, rst, sclkSync, selLSync) is
126  variable v : RegType;
127 
128  impure function isLeadingEdge
129  return boolean is
130  begin
131  return selLSync = '0' and r.sclkLast = CPOL_G and sclkSync = not CPOL_G;
132  end function;
133 
134  impure function isTrailingEdge
135  return boolean is
136  begin
137  return selLSync = '0' and r.sclkLast = not CPOL_G and sclkSync = CPOL_G;
138  end function;
139 
140  -- Shift a new bit out
141  procedure shift is
142  begin
143  v.shiftReg := r.shiftReg(WORD_SIZE_G-1 downto 0) & '0';
144  end procedure;
145 
146  -- Clock in the current mosi bit and increment counter
147  procedure sample is
148  begin
149  v.shiftReg(0) := mosiSync;
150 
151  v.shiftCnt := r.shiftCnt + 1;
152  if (r.shiftCnt = MAX_COUNT_C) then
153  v.shiftCnt := (others => '0');
154  end if;
155  end procedure;
156 
157  begin
158  v := r;
159 
160  v.sclkLast := sclkSync;
161  v.mosiLast := mosiSync;
162  v.selLLast := selLSync;
163 
164  -- CPHA_G = 0 is a special case
165  -- Do a shift on falling edge of selL
166  if (CPHA_G = '0' and r.selLLast = '1' and selLSync = '0') then
167  shift;
168  end if;
169 
170  if (isLeadingEdge) then
171  v.gotSclk := '1';
172  if (CPHA_G = '1') then
173  shift;
174  elsif (CPHA_G = '0') then
175  sample;
176  end if;
177  end if;
178 
179  if (isTrailingEdge) then
180  if (CPHA_G = '1') then
181  sample;
182  elsif (CPHA_G = '0' and r.shiftCnt /= MAX_COUNT_C) then
183  shift;
184  end if;
185  end if;
186 
187  -- Assert wrStb when max count reached
188  if (r.shiftCnt = MAX_COUNT_C and isTrailingEdge and r.gotSclk = '1') then
189  v.wrStb := '1';
190  end if;
191 
192  -- Read strobe only allowed when Write strobe is high
193  if (r.wrStb = '1' and (rdStb = '1' or isLeadingEdge)) then
194  v.wrStb := '0';
195  v.shiftReg(WORD_SIZE_G-1 downto 0) := rdData;
196  end if;
197 
198  if (rst = '1') then
199  v := REG_INIT_C;
200  end if;
201 
202  rin <= v;
203 
204  -- Outputs
205  miso <= 'Z';
206  if (selLSync = '0') then
207  miso <= r.shiftReg(WORD_SIZE_G);
208  end if;
209 
210  wrData <= r.shiftReg(WORD_SIZE_G-1 downto 0);
211  wrStb <= r.wrStb;
212 
213  end process;
214 
215 end architecture rtl;
INIT_Gslv := "0"
in clksl
Definition: SpiSlave.vhd:33
in rstsl
Definition: SpiSlave.vhd:34
in rdStbsl
Definition: SpiSlave.vhd:42
std_logic sl
Definition: StdRtlPkg.vhd:28
in rstsl :=not RST_POLARITY_G
TPD_Gtime := 1 ns
Definition: SpiSlave.vhd:28
STAGES_Gpositive := 2
_library_ ieeeieee
Definition: SpiMaster.vhd:18
out dataOutsl
WORD_SIZE_Gpositive := 16
Definition: SpiSlave.vhd:31
in mosisl
Definition: SpiSlave.vhd:37
CPHA_Gsl := '1'
Definition: SpiSlave.vhd:30
out wrDataslv( WORD_SIZE_G- 1 downto 0)
Definition: SpiSlave.vhd:44
TPD_Gtime := 1 ns
in rdDataslv( WORD_SIZE_G- 1 downto 0)
Definition: SpiSlave.vhd:41
out misosl
Definition: SpiSlave.vhd:38
in sclksl
Definition: SpiSlave.vhd:36
CPOL_Gsl := '0'
Definition: SpiSlave.vhd:29
out wrStbsl
Definition: SpiSlave.vhd:45
std_logic_vector slv
Definition: StdRtlPkg.vhd:29
in selLsl
Definition: SpiSlave.vhd:39