SURF  1.0
AxiMicronN25QReg.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : AxiMicronN25QReg.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2014-04-25
5 -- Last update: 2017-06-14
6 -------------------------------------------------------------------------------
7 -- Description: MicronN25Q AXI-Lite Register Access
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_unsigned.all;
21 use ieee.std_logic_arith.all;
22 
23 use work.StdRtlPkg.all;
24 use work.AxiLitePkg.all;
25 
26 --! @see entity
27  --! @ingroup devices_Micron_n25q
29  generic (
30  TPD_G : time := 1 ns;
31  MEM_ADDR_MASK_G : slv(31 downto 0) := x"00000000";
32  AXI_CLK_FREQ_G : real := 200.0E+6; -- units of Hz
33  SPI_CLK_FREQ_G : real := 25.0E+6; -- units of Hz
35  port (
36  -- FLASH Memory Ports
37  csL : out sl;
38  sck : out sl;
39  mosi : out sl;
40  miso : in sl;
41  -- AXI-Lite Register Interface
46  -- Global Signals
47  axiClk : in sl;
48  axiRst : in sl);
49 end AxiMicronN25QReg;
50 
51 architecture rtl of AxiMicronN25QReg is
52 
53  constant DOUBLE_SCK_FREQ_C : real := SPI_CLK_FREQ_G * 2.0;
54  constant SCK_HALF_PERIOD_C : natural := (getTimeRatio(AXI_CLK_FREQ_G, DOUBLE_SCK_FREQ_C))-1;
55  constant MIN_CS_WIDTH_C : natural := (getTimeRatio(AXI_CLK_FREQ_G, 2.0E+7));
56  constant MAX_SCK_CNT_C : natural := ite((SCK_HALF_PERIOD_C > MIN_CS_WIDTH_C), SCK_HALF_PERIOD_C, MIN_CS_WIDTH_C);
57 
58  constant PRESET_32BIT_ADDR_C : slv(8 downto 0) := "111111011";
59  constant PRESET_24BIT_ADDR_C : slv(8 downto 0) := "111111100";
60 
61  type StateType is (
62  IDLE_S,
63  WORD_WRITE_S,
64  WORD_READ_S,
65  WORD_READ_HOLD_S,
66  SCK_LOW_S,
67  SCK_HIGH_S,
68  MIN_CS_WIDTH_S);
69 
70  type RegType is record
71  test : slv(31 downto 0);
72  wrData : slv(31 downto 0);
73  addr : slv(31 downto 0);
74  addr32BitMode : sl;
75  cmd : slv(7 downto 0);
76  status : slv(7 downto 0);
77  -- RAM Signals
78  RnW : sl;
79  we : sl;
80  rd : slv(1 downto 0);
81  cnt : slv(8 downto 0);
82  waddr : slv(8 downto 0);
83  raddr : slv(8 downto 0);
84  xferSize : slv(8 downto 0);
85  ramDin : slv(7 downto 0);
86  -- SPI Signals
87  csL : sl;
88  sck : sl;
89  mosi : sl;
90  sckCnt : natural range 0 to MAX_SCK_CNT_C;
91  bitPntr : natural range 0 to 7;
92  -- AXI-Lite Signals
95  -- Status Machine
96  state : StateType;
97  end record RegType;
98 
99  constant REG_INIT_C : RegType := (
100  test => (others => '0'),
101  wrData => (others => '0'),
102  addr => (others => '0'),
103  addr32BitMode => '0',
104  cmd => (others => '0'),
105  status => (others => '0'),
106  -- RAM Signals
107  RnW => '1',
108  we => '0',
109  rd => "00",
110  cnt => (others => '0'),
111  waddr => (others => '0'),
112  raddr => (others => '0'),
113  xferSize => (others => '0'),
114  ramDin => (others => '0'),
115  -- SPI Signals
116  csL => '1',
117  sck => '0',
118  mosi => '0',
119  sckCnt => 0,
120  bitPntr => 0,
121  -- AXI-Lite Signals
124  -- Status Machine
125  state => IDLE_S);
126 
127  signal r : RegType := REG_INIT_C;
128  signal rin : RegType;
129 
130  signal ramDout : slv(7 downto 0);
131 
132  -- attribute dont_touch : string;
133  -- attribute dont_touch of r : signal is "true";
134 
135 begin
136 
137  -------------------------------
138  -- Configuration Register
139  -------------------------------
140  comb : process (axiReadMaster, axiRst, axiWriteMaster, miso, r, ramDout) is
141  variable v : RegType;
142  variable axiStatus : AxiLiteStatusType;
143  variable axiWriteResp : slv(1 downto 0);
144  variable axiReadResp : slv(1 downto 0);
145  begin
146  -- Latch the current value
147  v := r;
148 
149  -- Reset the strobing signals
150  axiWriteResp := AXI_RESP_OK_C;
151  axiReadResp := AXI_RESP_OK_C;
152  v.we := '0';
153 
154  -- Shift register
155  v.rd(1) := r.rd(0);
156  v.rd(0) := '0';
157 
158  -- Determine the transaction type
160 
161  -- State Machine
162  case (r.state) is
163  ----------------------------------------------------------------------
164  when IDLE_S =>
165  -- Reset the signals in IDLE state
166  v.csL := '1';
167  v.sck := '0';
168  v.cnt := (others => '0');
169  v.waddr := (others => '0');
170  v.raddr := (others => '0');
171  -- Check for a write request
172  if (axiStatus.writeEnable = '1') then
173  if axiWriteMaster.awaddr(9) = '1' then
174  -- Latch the write data and write address
175  v.waddr := axiWriteMaster.awaddr(8 downto 0);
176  v.raddr := axiWriteMaster.awaddr(8 downto 0);
177  v.wrData := axiWriteMaster.wdata;
178  -- Next state
179  v.state := WORD_WRITE_S;
180  else
181  -- Decode address and perform write
182  case (axiWriteMaster.awaddr(7 downto 0)) is
183  when x"00" =>
184  v.test := axiWriteMaster.wdata;
185  when x"04" =>
186  v.addr32BitMode := axiWriteMaster.wdata(0);
187  when x"08" =>
188  v.addr := axiWriteMaster.wdata;
189  when x"0C" =>
190  v.RnW := axiWriteMaster.wdata(31);
191  v.cmd := axiWriteMaster.wdata(23 downto 16);
192  v.xferSize := axiWriteMaster.wdata(8 downto 0);
193  -- Check address mode
194  if r.addr32BitMode = '1' then
195  -- 32-bit Address Mode
196  v.raddr := PRESET_32BIT_ADDR_C;
197  else
198  -- 24-bit Address Mode
199  v.raddr := PRESET_24BIT_ADDR_C;
200  end if;
201  -- Next state
202  v.state := SCK_LOW_S;
203  when others =>
204  axiWriteResp := AXI_ERROR_RESP_G;
205  end case;
206  end if;
207  -- Send AXI-Lite response
208  axiSlaveWriteResponse(v.axiWriteSlave, axiWriteResp);
209  -- Check for a read request
210  elsif (axiStatus.readEnable = '1') then
211  if axiReadMaster.araddr(9) = '1' then
212  -- Set the read address
213  v.raddr := axiReadMaster.araddr(8 downto 0);
214  -- Set the flag
215  v.rd(0) := '1';
216  -- Next state
217  v.state := WORD_READ_S;
218  else
219  -- Reset the register
220  v.axiReadSlave.rdata := (others => '0');
221  -- Decode address and assign read data
222  case (axiReadMaster.araddr(7 downto 0)) is
223  when x"00" =>
224  v.axiReadSlave.rdata := r.test;
225  when x"04" =>
226  v.axiReadSlave.rdata(0) := r.addr32BitMode;
227  when x"08" =>
228  v.axiReadSlave.rdata := r.addr;
229  when x"0C" =>
230  v.axiReadSlave.rdata(7 downto 0) := r.status;
231  when others =>
232  axiReadResp := AXI_ERROR_RESP_G;
233  end case;
234  -- Send AXI-Lite Response
235  axiSlaveReadResponse(v.axiReadSlave, axiReadResp);
236  end if;
237  end if;
238  ----------------------------------------------------------------------
239  when WORD_WRITE_S =>
240  -- Write a byte to the RAM
241  v.we := '1';
242  v.waddr := r.raddr;
243  v.ramDin := r.wrData(31 downto 24);
244  -- Shift the data
245  v.wrData(31 downto 8) := r.wrData(23 downto 0);
246  v.wrData(7 downto 0) := x"00";
247  -- Increment the counters
248  v.raddr := r.raddr + 1;
249  v.cnt := r.cnt + 1;
250  -- Check the counter size
251  if r.cnt = 3 then
252  -- Reset the counter
253  v.cnt := (others => '0');
254  -- Next state
255  v.state := IDLE_S;
256  end if;
257  ----------------------------------------------------------------------
258  when WORD_READ_S =>
259  -- Check if the RAM data is updated
260  if r.rd = "00" then
261  -- Set the flag
262  v.rd(0) := '1';
263  -- Shift the data
264  v.axiReadSlave.rdata(31 downto 8) := v.axiReadSlave.rdata(23 downto 0);
265  v.axiReadSlave.rdata(7 downto 0) := ramDout;
266  -- Increment the counters
267  v.raddr := r.raddr + 1;
268  v.cnt := r.cnt + 1;
269  -- Check the counter size
270  if r.cnt = 3 then
271  -- Reset the counter
272  v.cnt := (others => '0');
273  -- Next state
274  v.state := WORD_READ_HOLD_S;
275  end if;
276  end if;
277  ----------------------------------------------------------------------
278  when WORD_READ_HOLD_S =>
279  -- Send AXI-Lite Response
280  axiSlaveReadResponse(v.axiReadSlave);
281  -- Wait for read request to complete
282  if (axiStatus.readEnable = '0') then
283  -- Reset the counters
284  v.waddr := (others => '0');
285  v.raddr := (others => '0');
286  -- Next state
287  v.state := IDLE_S;
288  end if;
289  ----------------------------------------------------------------------
290  when SCK_LOW_S =>
291  -- Assert the chip select
292  v.csL := '0';
293  -- Serial Clock low phase
294  v.sck := '0';
295  -- Check if the RAM data is updated
296  if r.rd = "00" then
297  -- 32-bit Address Mode
298  if r.addr32BitMode = '1' then
299  if r.cnt = 0 then
300  v.mosi := r.cmd(7-r.bitPntr);
301  elsif r.cnt = 1 then
302  v.mosi := MEM_ADDR_MASK_G(31-r.bitPntr) or r.addr(31-r.bitPntr);
303  elsif r.cnt = 2 then
304  v.mosi := MEM_ADDR_MASK_G(23-r.bitPntr) or r.addr(23-r.bitPntr);
305  elsif r.cnt = 3 then
306  v.mosi := MEM_ADDR_MASK_G(15-r.bitPntr) or r.addr(15-r.bitPntr);
307  elsif r.cnt = 4 then
308  v.mosi := MEM_ADDR_MASK_G(7-r.bitPntr) or r.addr(7-r.bitPntr);
309  else
310  v.mosi := ramDout(7-r.bitPntr);
311  end if;
312  -- 24-bit Address Mode
313  else
314  if r.cnt = 0 then
315  v.mosi := r.cmd(7-r.bitPntr);
316  elsif r.cnt = 1 then
317  v.mosi := MEM_ADDR_MASK_G(23-r.bitPntr) or r.addr(23-r.bitPntr);
318  elsif r.cnt = 2 then
319  v.mosi := MEM_ADDR_MASK_G(15-r.bitPntr) or r.addr(15-r.bitPntr);
320  elsif r.cnt = 3 then
321  v.mosi := MEM_ADDR_MASK_G(7-r.bitPntr) or r.addr(7-r.bitPntr);
322  else
323  v.mosi := ramDout(7-r.bitPntr);
324  end if;
325  end if;
326  -- Increment the counter
327  v.sckCnt := r.sckCnt + 1;
328  -- Check the counter value
329  if r.sckCnt = SCK_HALF_PERIOD_C then
330  -- Reset the counter
331  v.sckCnt := 0;
332  -- Next state
333  v.state := SCK_HIGH_S;
334  end if;
335  end if;
336  ----------------------------------------------------------------------
337  when SCK_HIGH_S =>
338  -- Serial Clock high phase
339  v.sck := '1';
340  -- Increment the counter
341  v.sckCnt := r.sckCnt + 1;
342  -- Check the counter value
343  if r.sckCnt = SCK_HALF_PERIOD_C then
344  -- Set the default state
345  v.state := SCK_LOW_S;
346  -- Reset the counter
347  v.sckCnt := 0;
348  -- Update the ram data bus
349  v.ramDin(7 downto 1) := r.ramDin(6 downto 0);
350  v.ramDin(0) := miso;
351  -- Increment the counter
352  v.bitPntr := r.bitPntr + 1;
353  -- Check the counter value
354  if r.bitPntr = 7 then
355  -- Reset the counter
356  v.bitPntr := 0;
357  -- Write to RAM
358  v.we := not(r.RnW);
359  v.waddr := r.raddr;
360  -- Increment the counters
361  v.raddr := r.raddr + 1;
362  v.cnt := r.cnt + 1;
363  -- Set the flag
364  v.rd(0) := '1';
365  -- Check the xfer size
366  if r.cnt = r.xferSize then
367  -- Reset the counter
368  v.cnt := (others => '0');
369  -- Next state
370  v.state := MIN_CS_WIDTH_S;
371  end if;
372  end if;
373  end if;
374  ----------------------------------------------------------------------
375  when MIN_CS_WIDTH_S =>
376  -- De-assert the chip select
377  v.csL := '1';
378  -- Serial Clock low phase
379  v.sck := '0';
380  -- Increment the counter
381  v.sckCnt := r.sckCnt + 1;
382  -- Check counter
383  if r.sckCnt = MIN_CS_WIDTH_C then
384  -- Latch the last write value
385  v.status := r.ramDin;
386  -- Reset the counter
387  v.sckCnt := 0;
388  -- Next State
389  v.state := IDLE_S;
390  end if;
391  ----------------------------------------------------------------------
392  end case;
393 
394  -- Synchronous Reset
395  if axiRst = '1' then
396  v := REG_INIT_C;
397  end if;
398 
399  -- Register the variable for next clock cycle
400  rin <= v;
401 
402  -- Outputs
405 
406  csL <= r.csL;
407  sck <= r.sck;
408  mosi <= r.mosi;
409 
410  end process comb;
411 
412  seq : process (axiClk) is
413  begin
414  if rising_edge(axiClk) then
415  r <= rin after TPD_G;
416  end if;
417  end process seq;
418 
419  U_Ram : entity work.SimpleDualPortRam
420  generic map(
421  BRAM_EN_G => true,
422  DATA_WIDTH_G => 8,
423  ADDR_WIDTH_G => 9)
424  port map (
425  -- Port A
426  clka => axiClk,
427  wea => r.we,
428  addra => r.waddr,
429  dina => r.ramDin,
430  -- Port B
431  clkb => axiClk,
432  addrb => r.raddr,
433  doutb => ramDout);
434 
435 end rtl;
in addrbslv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0')
BRAM_EN_Gboolean := true
out doutbslv( DATA_WIDTH_G- 1 downto 0)
DATA_WIDTH_Ginteger range 1 to ( 2** 24):= 16
AxiLiteWriteMasterType
Definition: AxiLitePkg.vhd:111
std_logic sl
Definition: StdRtlPkg.vhd:28
slv( 31 downto 0) rdata
Definition: AxiLitePkg.vhd:89
out axiWriteSlaveAxiLiteWriteSlaveType
slv( 31 downto 0) wdata
Definition: AxiLitePkg.vhd:117
AxiLiteStatusType axiStatus
Definition: AxiLitePkg.vhd:183
SPI_CLK_FREQ_Greal := 25.0E+6
AXI_CLK_FREQ_Greal := 200.0E+6
slv( 1 downto 0) := "10" AXI_RESP_SLVERR_C
Definition: AxiLitePkg.vhd:36
in axiReadMasterAxiLiteReadMasterType
ADDR_WIDTH_Ginteger range 1 to ( 2** 24):= 4
in axiWriteMasterAxiLiteWriteMasterType
in addraslv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0')
AxiLiteReadMasterType
Definition: AxiLitePkg.vhd:59
slv( 31 downto 0) awaddr
Definition: AxiLitePkg.vhd:113
AxiLiteReadSlaveType :=(arready => '0',rdata =>( others => '0'),rresp =>( others => '0'),rvalid => '0') AXI_LITE_READ_SLAVE_INIT_C
Definition: AxiLitePkg.vhd:95
out axiReadSlaveAxiLiteReadSlaveType
AxiLiteReadSlaveType
Definition: AxiLitePkg.vhd:85
slv( 1 downto 0) := "00" AXI_RESP_OK_C
Definition: AxiLitePkg.vhd:31
slv( 31 downto 0) araddr
Definition: AxiLitePkg.vhd:61
AXI_ERROR_RESP_Gslv( 1 downto 0) := AXI_RESP_SLVERR_C
AxiLiteWriteSlaveType :=(awready => '0',wready => '0',bresp =>( others => '0'),bvalid => '0') AXI_LITE_WRITE_SLAVE_INIT_C
Definition: AxiLitePkg.vhd:156
MEM_ADDR_MASK_Gslv( 31 downto 0) := x"00000000"
std_logic_vector slv
Definition: StdRtlPkg.vhd:29
in dinaslv( DATA_WIDTH_G- 1 downto 0) :=( others => '0')