SURF  1.0
AxiMicronP30Reg.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : AxiMicronP30Reg.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2014-10-21
5 -- Last update: 2017-07-11
6 -------------------------------------------------------------------------------
7 -- Description: This controller is designed around the Micron PC28F FLASH IC.
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 library unisim;
27 use unisim.vcomponents.all;
28 
29 --! @see entity
30  --! @ingroup devices_Micron_p30
31 entity AxiMicronP30Reg is
32  generic (
33  TPD_G : time := 1 ns;
34  MEM_ADDR_MASK_G : slv(31 downto 0) := x"00000000";
35  AXI_CLK_FREQ_G : real := 200.0E+6; -- units of Hz
37  port (
38  -- FLASH Interface
39  flashAddr : out slv(30 downto 0);
40  flashAdv : out sl;
41  flashClk : out sl;
42  flashRstL : out sl;
43  flashCeL : out sl;
44  flashOeL : out sl;
45  flashWeL : out sl;
46  flashTri : out sl;
47  flashDin : out slv(15 downto 0);
48  flashDout : in slv(15 downto 0);
49  -- AXI-Lite Register Interface
54  -- Clocks and Resets
55  axiClk : in sl;
56  axiRst : in sl);
57 end AxiMicronP30Reg;
58 
59 architecture rtl of AxiMicronP30Reg is
60 
61  constant HALF_CYCLE_PERIOD_C : real := 128.0E-9; -- units of seconds
62 
63  constant HALF_CYCLE_FREQ_C : real := (1.0 / HALF_CYCLE_PERIOD_C); -- units of Hz
64 
65  constant MAX_CNT_C : natural := getTimeRatio(AXI_CLK_FREQ_G, HALF_CYCLE_FREQ_C);
66 
67  type stateType is (
68  IDLE_S,
69  RAM_READ_S,
70  BLOCK_RD_S,
71  BLOCK_WR_S,
72  CMD_LOW_S,
73  CMD_HIGH_S,
74  WAIT_S,
75  DATA_LOW_S,
76  DATA_HIGH_S);
77 
78  type RegType is record
79  -- PROM Control Signals
80  tristate : sl;
81  ceL : sl;
82  oeL : sl;
83  RnW : sl;
84  weL : sl;
85  cnt : natural range 0 to (MAX_CNT_C+1);
86  din : slv(15 downto 0);
87  dataReg : slv(15 downto 0);
88  addr : slv(30 downto 0);
89  wrCmd : slv(15 downto 0);
90  wrData : slv(15 downto 0);
91  test : slv(31 downto 0);
92  -- Block Transfer signals
93  lockCmd : sl;
94  blockRd : sl;
95  blockWr : sl;
96  blockCnt : slv(7 downto 0);
97  xferSize : slv(7 downto 0);
98  -- RAM Buffer Signals
99  ramRd : slv(1 downto 0);
100  ramWe : sl;
101  ramDin : slv(15 downto 0);
102  waddr : slv(7 downto 0);
103  raddr : slv(7 downto 0);
104  -- AXI-Lite Signals
107  -- Status Machine
108  state : StateType;
109  end record RegType;
110 
111  constant REG_INIT_C : RegType := (
112  -- PROM Control Signals
113  tristate => '1',
114  ceL => '1',
115  oeL => '1',
116  RnW => '1',
117  weL => '1',
118  cnt => 0,
119  din => x"0000",
120  dataReg => x"0000",
121  addr => (others => '0'),
122  wrCmd => (others => '0'),
123  wrData => (others => '0'),
124  test => (others => '0'),
125  -- Block Transfer signals
126  lockCmd => '0',
127  blockRd => '0',
128  blockWr => '0',
129  blockCnt => (others => '0'),
130  xferSize => (others => '0'),
131  -- RAM Buffer Signals
132  ramRd => (others => '0'),
133  ramWe => '0',
134  ramDin => (others => '0'),
135  waddr => (others => '0'),
136  raddr => (others => '0'),
137  -- AXI-Lite Signals
140  -- Status Machine
141  state => IDLE_S);
142 
143  signal r : RegType := REG_INIT_C;
144  signal rin : RegType;
145 
146  signal ramDout : slv(15 downto 0);
147 
148  -- attribute dont_touch : string;
149  -- attribute dont_touch of r : signal is "true";
150  -- attribute dont_touch of ramDout : signal is "true";
151 
152 begin
153 
154  comb : process (axiReadMaster, axiRst, axiWriteMaster, flashDout, r,
155  ramDout) is
156  variable v : RegType;
157  variable axiStatus : AxiLiteStatusType;
158  variable axiWriteResp : slv(1 downto 0);
159  variable axiReadResp : slv(1 downto 0);
160  variable i : natural;
161  begin
162  -- Latch the current value
163  v := r;
164 
165  -- Reset the strobing signals
166  v.ceL := '1';
167  v.oeL := '1';
168  v.weL := '1';
169  v.tristate := '1';
170  axiWriteResp := AXI_RESP_OK_C;
171  axiReadResp := AXI_RESP_OK_C;
172  v.ramWe := '0';
173 
174  -- Shift register
175  v.ramRd(1) := r.ramRd(0);
176  v.ramRd(0) := '0';
177 
178  -- Determine the transaction type
180 
181  -- State Machine
182  case r.state is
183  ----------------------------------------------------------------------
184  when IDLE_S =>
185  -- Reset variables
186  v.lockCmd := '0';
187  v.blockRd := '0';
188  v.blockWr := '0';
189  v.blockCnt := x"00";
190  v.raddr := x"00";
191  -------------------------------------------------------------------
192  -- Check for a read request
193  -------------------------------------------------------------------
194  if (axiStatus.readEnable = '1') then
195  -- Reset the register
196  v.axiReadSlave.rdata := (others => '0');
197  -- Check for RAM access
198  if (axiReadMaster.araddr(10) = '1') then
199  -- Read the ram
200  v.ramRd(0) := '1';
201  v.raddr := axiReadMaster.araddr(9 downto 2);
202  -- Next state
203  v.state := RAM_READ_S;
204  else
205  case (axiReadMaster.araddr(7 downto 0)) is
206  -------------------------
207  -- Non-buffered Interface
208  -------------------------
209  when x"00" =>
210  -- Get the opCode bus
211  v.axiReadSlave.rdata(31 downto 16) := r.wrCmd;
212  -- Get the input data bus
213  v.axiReadSlave.rdata(15 downto 0) := r.wrData;
214  when x"04" =>
215  -- Get the RnW
216  v.axiReadSlave.rdata(31) := r.RnW;
217  -- Get the address bus
218  v.axiReadSlave.rdata(30 downto 0) := r.addr;
219  when x"08" =>
220  -- Get the output data bus
221  v.axiReadSlave.rdata(15 downto 0) := r.dataReg;
222  when x"0C" =>
223  v.axiReadSlave.rdata := r.test;
224  -------------------------
225  -- Buffered Interface
226  -------------------------
227  when x"80" =>
228  -- Get the address bus
229  v.axiReadSlave.rdata(7 downto 0) := r.xferSize;
230  when x"84" =>
231  -- Get the RnW
232  v.axiReadSlave.rdata(31) := r.RnW;
233  -- Get the address bus
234  v.axiReadSlave.rdata(30 downto 0) := r.addr;
235  when others =>
236  axiReadResp := AXI_ERROR_RESP_G;
237  end case;
238  -- Send AXI-Lite Response
239  axiSlaveReadResponse(v.axiReadSlave, axiReadResp);
240  end if;
241  -------------------------------------------------------------------
242  -- Check for a write request
243  -------------------------------------------------------------------
244  elsif (axiStatus.writeEnable = '1') then
245  -- Check for RAM access
246  if (axiWriteMaster.awaddr(10) = '1') then
247  -- Write the data to RAM
248  v.waddr := axiWriteMaster.awaddr(9 downto 2);
249  v.ramDin := axiWriteMaster.wdata(15 downto 0);
250  v.ramWe := '1';
251  else
252  case (axiWriteMaster.awaddr(7 downto 0)) is
253  -------------------------
254  -- Non-buffered Interface
255  -------------------------
256  when x"00" =>
257  -- Set the opCode bus
258  v.wrCmd := axiWriteMaster.wdata(31 downto 16);
259  -- Set the input data bus
260  v.wrData := axiWriteMaster.wdata(15 downto 0);
261  when x"04" =>
262  -- Set the RnW
263  v.RnW := axiWriteMaster.wdata(31);
264  -- Set the address bus
265  v.addr := axiWriteMaster.wdata(30 downto 0);
266  -- Next state
267  v.state := CMD_LOW_S;
268  when x"0C" =>
269  v.test := axiWriteMaster.wdata;
270  -------------------------
271  -- Buffered Interface
272  -------------------------
273  when x"80" =>
274  -- Set the block transfer size
275  v.xferSize := axiWriteMaster.wdata(7 downto 0);
276  when x"84" =>
277  -- Set the RnW
278  v.RnW := axiWriteMaster.wdata(31);
279  -- Set the address bus
280  v.addr := axiWriteMaster.wdata(30 downto 0);
281  -- Check the mode
282  if (axiWriteMaster.wdata(31) = '1') then
283  -- Set the flag
284  v.blockRd := '1';
285  -- Set the opCode bus
286  v.wrCmd := x"00FF";
287  -- Set the input data bus
288  v.wrData := x"00FF";
289  -- Next state
290  v.state := CMD_LOW_S;
291  else
292  -- Set the flag
293  v.blockWr := '1';
294  -- Next state
295  v.state := BLOCK_WR_S;
296  end if;
297  when others =>
298  axiWriteResp := AXI_ERROR_RESP_G;
299  end case;
300  end if;
301  -- Send AXI-Lite response
302  axiSlaveWriteResponse(v.axiWriteSlave, axiWriteResp);
303  end if;
304  ----------------------------------------------------------------------
305  when RAM_READ_S =>
306  -- Check if the RAM data is updated
307  if r.ramRd = "00" then
308  -- Set the data bus
309  v.axiReadSlave.rdata(15 downto 0) := ramDout;
310  -- Send AXI-Lite Response
311  axiSlaveReadResponse(v.axiReadSlave, axiReadResp);
312  -- Next state
313  v.state := IDLE_S;
314  end if;
315  ----------------------------------------------------------------------
316  when BLOCK_RD_S =>
317  -- Write the data to RAM
318  v.waddr := r.blockCnt;
319  v.ramDin := r.dataReg;
320  v.ramWe := '1';
321  -- Check the counter
322  if (r.blockCnt = r.xferSize) then
323  -- Next state
324  v.state := IDLE_S;
325  else
326  -- Increment the counters
327  v.blockCnt := r.blockCnt + 1;
328  v.addr := r.addr + 1;
329  -- Next state
330  v.state := CMD_LOW_S;
331  end if;
332  ----------------------------------------------------------------------
333  when BLOCK_WR_S =>
334  -- Increment the counter
335  v.blockCnt := r.blockCnt + 1;
336  -- Check the counter
337  case r.blockCnt is
338  when x"00" =>
339  -- Send the "unlock the block" command
340  v.RnW := '0';
341  v.wrCmd := x"0060";
342  v.wrData := x"00D0";
343  when x"01" =>
344  -- Send the "reset the status register" command
345  v.RnW := '0';
346  v.wrCmd := x"0050";
347  v.wrData := x"0050";
348  when x"02" =>
349  -- Send the "program" command
350  v.RnW := '0';
351  v.wrCmd := x"0040";
352  v.wrData := ramDout; -- Send the BRAM data
353  -- Get the status register
354  when x"03" =>
355  v.RnW := '1';
356  v.wrCmd := x"0070";
357  v.wrData := x"00FF";
358  when others =>
359  -- Check if FLASH is still busy
360  if r.dataReg(7) = '0' then
361  -- Set the counter
362  v.blockCnt := x"04";
363  -- Get the status register
364  v.RnW := '1';
365  v.wrCmd := x"0070";
366  v.wrData := x"00FF";
367  -- Check for programming failure
368  elsif r.dataReg(4) = '1' then
369  -- Set the counter
370  v.blockCnt := x"01";
371  -- Send the "unlock the block" command
372  v.RnW := '0';
373  v.wrCmd := x"0060";
374  v.wrData := x"00D0";
375  else
376  -- Send the "lock the block" command
377  v.RnW := '0';
378  v.wrCmd := x"0060";
379  v.wrData := x"0001";
380  v.lockCmd := '1';
381  -- Reset the counter
382  v.blockCnt := x"00";
383  -- Check the Block RAM address
384  if (r.raddr = r.xferSize) then
385  -- Reset the flag
386  v.blockWr := '0';
387  else
388  -- Increment the counter
389  v.raddr := r.raddr + 1;
390  end if;
391  end if;
392  end case;
393  -- Next state
394  v.state := CMD_LOW_S;
395  ----------------------------------------------------------------------
396  when CMD_LOW_S =>
397  v.ceL := '0';
398  v.oeL := '1';
399  v.weL := '0';
400  v.tristate := '0';
401  v.din := r.wrCmd;
402  -- Increment the counter
403  v.cnt := r.cnt + 1;
404  -- Check the counter
405  if (r.cnt = MAX_CNT_C) then
406  -- Reset the counter
407  v.cnt := 0;
408  -- Next state
409  v.state := CMD_HIGH_S;
410  end if;
411  ----------------------------------------------------------------------
412  when CMD_HIGH_S =>
413  v.ceL := '1';
414  v.oeL := '1';
415  v.weL := '1';
416  v.tristate := '0';
417  v.din := r.wrCmd;
418  -- Increment the counter
419  v.cnt := r.cnt + 1;
420  -- Check the counter
421  if (r.cnt = MAX_CNT_C) then
422  -- Reset the counter
423  v.cnt := 0;
424  -- Next state
425  v.state := WAIT_S;
426  end if;
427  ----------------------------------------------------------------------
428  when WAIT_S =>
429  v.ceL := '1';
430  v.oeL := '1';
431  v.weL := '1';
432  v.tristate := '1';
433  v.din := r.wrData;
434  -- Increment the counter
435  v.cnt := r.cnt + 1;
436  -- Check the counter
437  if (r.cnt = MAX_CNT_C) then
438  -- Reset the counter
439  v.cnt := 0;
440  -- Next state
441  v.state := DATA_LOW_S;
442  end if;
443  ----------------------------------------------------------------------
444  when DATA_LOW_S =>
445  v.ceL := '0';
446  v.oeL := not(r.RnW);
447  v.weL := r.RnW;
448  v.tristate := r.RnW;
449  v.din := r.wrData;
450  -- Increment the counter
451  v.cnt := r.cnt + 1;
452  -- Check the counter
453  if (r.cnt = MAX_CNT_C) then
454  -- Reset the counter
455  v.cnt := 0;
456  --latch the data bus value
457  v.dataReg := flashDout;
458  -- Next state
459  v.state := DATA_HIGH_S;
460  end if;
461  ----------------------------------------------------------------------
462  when DATA_HIGH_S =>
463  v.ceL := '1';
464  v.oeL := '1';
465  v.weL := '1';
466  v.tristate := r.RnW;
467  v.din := r.wrData;
468  -- Increment the counter
469  v.cnt := r.cnt + 1;
470  -- Check the counter
471  if (r.cnt = MAX_CNT_C) then
472  -- Reset the counter
473  v.cnt := 0;
474  -- Check for block read
475  if (r.blockRd = '1') then
476  -- Next state
477  v.state := BLOCK_RD_S;
478  -- Check for block write
479  elsif (r.blockWr = '1') then
480  -- Check for the lock CMD
481  if (r.lockCmd = '1') then
482  -- Reset the flag
483  v.lockCmd := '0';
484  -- Increment the counter
485  v.addr := r.addr + 1;
486  end if;
487  -- Next state
488  v.state := BLOCK_WR_S;
489  else
490  -- Next state
491  v.state := IDLE_S;
492  end if;
493  end if;
494  ----------------------------------------------------------------------
495  end case;
496 
497  -- Synchronous Reset
498  if (axiRst = '1') then
499  v := REG_INIT_C;
500  end if;
501 
502  -- Register the variable for next clock cycle
503  rin <= v;
504 
505  -- Outputs
506  for i in 0 to 30 loop
507  flashAddr(i) <= r.addr(i) or MEM_ADDR_MASK_G(i);
508  end loop;
509  flashAdv <= '0';
510  flashClk <= '1';
511  flashRstL <= not(axiRst);
512  flashCeL <= r.ceL;
513  flashOeL <= r.oeL;
514  flashWeL <= r.weL;
515  flashDin <= r.din;
516  flashTri <= r.tristate;
519 
520  end process comb;
521 
522  seq : process (axiClk) is
523  begin
524  if rising_edge(axiClk) then
525  r <= rin after TPD_G;
526  end if;
527  end process seq;
528 
529  U_Ram : entity work.SimpleDualPortRam
530  generic map(
531  BRAM_EN_G => true,
532  DATA_WIDTH_G => 16,
533  ADDR_WIDTH_G => 8)
534  port map (
535  -- Port A
536  clka => axiClk,
537  wea => r.ramWe,
538  addra => r.waddr,
539  dina => r.ramDin,
540  -- Port B
541  clkb => axiClk,
542  addrb => r.raddr,
543  doutb => ramDout);
544 
545 end rtl;
out flashDinslv( 15 downto 0)
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
MEM_ADDR_MASK_Gslv( 31 downto 0) := x"00000000"
slv( 31 downto 0) rdata
Definition: AxiLitePkg.vhd:89
in flashDoutslv( 15 downto 0)
slv( 31 downto 0) wdata
Definition: AxiLitePkg.vhd:117
AxiLiteStatusType axiStatus
Definition: AxiLitePkg.vhd:183
out flashAddrslv( 30 downto 0)
_library_ ieeeieee
AXI_CLK_FREQ_Greal := 200.0E+6
slv( 1 downto 0) := "10" AXI_RESP_SLVERR_C
Definition: AxiLitePkg.vhd:36
ADDR_WIDTH_Ginteger range 1 to ( 2** 24):= 4
in axiReadMasterAxiLiteReadMasterType
TPD_Gtime := 1 ns
in addraslv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0')
AxiLiteReadMasterType
Definition: AxiLitePkg.vhd:59
out axiReadSlaveAxiLiteReadSlaveType
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
AxiLiteReadSlaveType
Definition: AxiLitePkg.vhd:85
out axiWriteSlaveAxiLiteWriteSlaveType
slv( 1 downto 0) := "00" AXI_RESP_OK_C
Definition: AxiLitePkg.vhd:31
slv( 31 downto 0) araddr
Definition: AxiLitePkg.vhd:61
in axiWriteMasterAxiLiteWriteMasterType
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
std_logic_vector slv
Definition: StdRtlPkg.vhd:29
in dinaslv( DATA_WIDTH_G- 1 downto 0) :=( others => '0')