Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
250 lines (244 sloc) 7.68 KB
################################################################################
##
## Filename: flash.txt
##
## Project: AutoFPGA, a utility for composing FPGA designs from peripherals
##
## Purpose: Describes the flash in our new data format.
##
## Creator: Dan Gisselquist, Ph.D.
## Gisselquist Technology, LLC
##
################################################################################
##
## Copyright (C) 2017, Gisselquist Technology, LLC
##
## This program is free software (firmware): you can redistribute it and/or
## modify it under the terms of the GNU General Public License as published
## by the Free Software Foundation, either version 3 of the License, or (at
## your option) any later version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
## for more details.
##
## You should have received a copy of the GNU General Public License along
## with this program. (It's in the $(ROOT)/doc directory. Run make with no
## target there if the PDF file isn't present.) If not, see
## <http://www.gnu.org/licenses/> for a copy.
##
## License: GPL, v3, as defined and found on www.gnu.org,
## http://www.gnu.org/licenses/gpl.html
##
##
################################################################################
##
##
@PREFIX= flash
@$LGFLASHSZ.EXPR=24
@$NADDR=(1<<(@$LGFLASHSZ-2))
@$NBYTES=(1<<@$LGFLASHSZ)
@NBYTES.FORMAT=0x%08x
@ACCESS= FLASH_ACCESS
@SLAVE.TYPE=MEMORY
@SLAVE.BUS=wb
@LD.PERM=rx
@INT.FLASH.WIRE= flash_interrupt
@INT.FLASH.PIC= buspic
@$ISPIF_EN.EXPR=@$ISPIF_DIS|0x80000000
@ISPIF_EN.FORMAT=0x%08x
@$ISPIF_DIS.EXPR=(@$ISPIF_CLR)|((@$ISPIF_CLR)<<16)
@ISPIF_DIS.FORMAT=0x%08x
@$ISPIF_CLR.EXPR=(1<<(@$INT.FLASH.buspic.ID))
@ISPIF_CLR.FORMAT=0x%08x
@TOP.PORTLIST=
// Top level Quad-SPI I/O ports
o_qspi_cs_n, io_qspi_dat
@TOP.IODECL=
// Quad SPI flash
output wire o_qspi_cs_n;
inout wire [3:0] io_qspi_dat;
@TOP.DEFNS=
wire w_qspi_sck, w_qspi_cs_n;
wire [1:0] qspi_bmod;
wire [3:0] qspi_dat;
@TOP.MAIN=
// Quad SPI flash
w_qspi_cs_n, w_qspi_sck, qspi_dat, io_qspi_dat, qspi_bmod
@TOP.INSERT=
//
//
// Wires for setting up the QSPI flash wishbone peripheral
//
//
// QSPI)BMOD, Quad SPI bus mode, Bus modes are:
// 0? Normal serial mode, one bit in one bit out
// 10 Quad SPI mode, going out
// 11 Quad SPI mode coming from the device (read mode)
assign io_qspi_dat = (~qspi_bmod[1])?({2'b11,1'bz,qspi_dat[0]})
:((qspi_bmod[0])?(4'bzzzz):(qspi_dat[3:0]));
assign o_qspi_cs_n = w_qspi_cs_n;
// The following primitive is necessary in many designs order to gain
// access to the o_qspi_sck pin. It's not necessary on the Arty,
// simply because they provide two pins that can drive the QSPI
// clock pin.
wire [3:0] su_nc; // Startup primitive, no connect
STARTUPE2 #(
// Leave PROG_USR false to avoid activating the program
// event security feature. Notes state that such a feature
// requires encrypted bitstreams.
.PROG_USR("FALSE"),
// Sets the configuration clock frequency (in ns) for
// simulation.
.SIM_CCLK_FREQ(0.0)
) STARTUPE2_inst (
// CFGCLK, 1'b output: Configuration main clock output -- no connect
.CFGCLK(su_nc[0]),
// CFGMCLK, 1'b output: Configuration internal oscillator clock output
.CFGMCLK(su_nc[1]),
// EOS, 1'b output: Active high output indicating the End Of Startup.
.EOS(su_nc[2]),
// PREQ, 1'b output: PROGRAM request to fabric output
// Only enabled if PROG_USR is set. This lets the fabric know
// that a request has been made (either JTAG or pin pulled low)
// to program the device
.PREQ(su_nc[3]),
// CLK, 1'b input: User start-up clock input
.CLK(1'b0),
// GSR, 1'b input: Global Set/Reset input
.GSR(1'b0),
// GTS, 1'b input: Global 3-state input
.GTS(1'b0),
// KEYCLEARB, 1'b input: Clear AES Decrypter Key input from BBRAM
.KEYCLEARB(1'b0),
// PACK, 1-bit input: PROGRAM acknowledge input
// This pin is only enabled if PROG_USR is set. This allows the
// FPGA to acknowledge a request for reprogram to allow the FPGA
// to get itself into a reprogrammable state first.
.PACK(1'b0),
// USRCLKO, 1-bit input: User CCLK input -- This is why I am using this
// module at all.
.USRCCLKO(w_qspi_sck),
// USRCCLKTS, 1'b input: User CCLK 3-state enable input
// An active high here places the clock into a high impedence
// state. Since we wish to use the clock as an active output
// always, we drive this pin low.
.USRCCLKTS(1'b0),
// USRDONEO, 1'b input: User DONE pin output control
// Set this to "high" to make sure that the DONE LED pin is
// high.
.USRDONEO(1'b1),
// USRDONETS, 1'b input: User DONE 3-state enable output
// This enables the FPGA DONE pin to be active. Setting this
// active high sets the DONE pin to high impedence, setting it
// low allows the output of this pin to be as stated above.
.USRDONETS(1'b1)
);
@MAIN.PORTLIST=
// The QSPI Flash
o_qspi_cs_n, o_qspi_sck, o_qspi_dat, i_qspi_dat, o_qspi_mod
@MAIN.IODECL=
// The QSPI flash
output wire o_qspi_cs_n, o_qspi_sck;
output wire [3:0] o_qspi_dat;
input wire [3:0] i_qspi_dat;
output wire [1:0] o_qspi_mod;
@MAIN.INSERT=
wbqspiflash #(@$LGFLASHSZ)
flashmem(i_clk,
(wb_cyc), (wb_stb)&&(flash_sel), (wb_stb)&&(flctl_sel),wb_we,
wb_addr[(@$LGFLASHSZ-3):0], wb_data,
flash_ack, flash_stall, flash_data,
o_qspi_sck, o_qspi_cs_n, o_qspi_mod, o_qspi_dat, i_qspi_dat,
flash_interrupt);
@MAIN.ALT=
assign o_qspi_sck = 1'b1;
assign o_qspi_cs_n = 1'b1;
assign o_qspi_mod = 2'b01;
assign o_qspi_dat = 4'b1111;
@MEM.NAME= flash
@MEM.ACCESS = rx
@REGS.N= 1
@DEVID=FLASH
@REGDEFS.H.DEFNS=
#define @$(DEVID)BASE @$[0x%08x](REGBASE)
#define @$(DEVID)LEN @$NBYTES
#define @$(DEVID)LGLEN @$LGFLASHSZ
@REGS.0= 0 R_@$(DEVID) FLASH
@BDEF.OSDEF=_BOARD_HAS_FLASH
@BDEF.OSVAL=extern char _flash[@$NBYTES];
@LDSCRIPT.PSTR= rx
@LDSCRIPT.PTR= flash
@LDSCRIPT.DEF=
_flash=ORIGIN(flash);
@REGDEFS.H.INSERT=
#define R_ICONTROL R_PIC
#define ISPIF_EN @$ISPIF_EN
#define ISPIF_DIS @$ISPIF_DIS
#define ISPIF_CLR @$ISPIF_CLR
@SIM.INCLUDE+=
#include "qspiflashsim.h"
@SIM.DEFNS+=
#ifdef @$(ACCESS)
QSPIFLASHSIM *m_@$(MEM.NAME);
#endif
@SIM.INIT+=
#ifdef @$(ACCESS)
m_@$(MEM.NAME) = new QSPIFLASHSIM(FLASHLGLEN);
#endif
@SIM.TICK +=
#ifdef @$(ACCESS)
m_core->i_qspi_dat = (*m_@$(MEM.NAME))(m_core->o_qspi_cs_n,
m_core->o_qspi_sck, m_core->o_qspi_dat);
#endif
@SIM.LOAD +=
m_@$(MEM.NAME)->load(start, &buf[offset], wlen);
#
#
#
#
#
# Now, the control interface
@PREFIX= flctl
@NADDR= 4
@ACCESS= FLASH_ACCESS
# This cannot be a DOUBLE peripheral type, since our response may take more than
# two clock cycles.
@SLAVE.TYPE=OTHER
@SLAVE.BUS=wb
@MAIN.INSERT=
// The Flash control interface result comes back together with the
// flash interface itself. Hence, we always return zero here.
assign flctl_ack = 1'b0;
assign flctl_stall = 1'b0;
assign flctl_data = 0;
@REGS.NOTE= // FLASH erase/program configuration registers
@REGS.N= 4
@REGS.0= 0 R_QSPI_EREG QSPIE
@REGS.1= 1 R_QSPI_CREG QSPIC
@REGS.2= 2 R_QSPI_SREG QSPIS
@REGS.3= 3 R_QSPI_IDREG QSPII
@BDEF.DEFN=
typedef struct FLASHCTL_S {
unsigned f_ereg, f_config, f_status, f_id;
} FLASHCTL;
@REGDEFS.H.INSERT=
// Flash control constants
#define ERASEFLAG 0x80000000
#define DISABLEWP 0x10000000
#define ENABLEWP 0x00000000
#define SZPAGEB 256
#define PGLENB 256
#define SZPAGEW 64
#define PGLENW 64
#define NPAGES 256
#define SECTORSZB (NPAGES * SZPAGEB) // In bytes, not words!!
#define SECTORSZW (NPAGES * SZPAGEW) // In words
#define NSECTORS 64
#define SECTOROF(A) ((A) & (-1<<16))
#define SUBSECTOROF(A) ((A) & (-1<<12))
#define PAGEOF(A) ((A) & (-1<<8))
@BDEF.IONAME= io_flctl
@RTL.MAKE.GROUP= FLASH
@RTL.MAKE.FILES= wbqspiflash.v llqspi.v flashconfig.v