Altera firmware
From ExtraTerrestrik
Contents[hide] |
Altera Cyclone 3
The FPGA is documeted in the Altera Cyclone 3 Handbook. We chose the biggest Cyclone 3 that comes in a 144 pin package, an EP3C25. It features:
- 24624 locic elements,
- 66 M9K memeory blocks, i.e., about 66 kByte,
- 66 18x18 multipliers,
- 4 PLLs,
- 20 global clock networks,
- 82 user IO pins,
- 6 LVDS IO, and 8 LVDS clk inputs
The logic is compiled into a raw binary file, which is uncompressed 5,800,000 bits. The compressed files are about ΒΌ Mbyte.
Tools
The logic in the FPGA is programmed in a Hardware Description Language (HDL). We use Verilog. Other options are VHDL or Alteras own HDL, or even schematic entry, We use Verilog.
Synthesis
To compile the logic we need to use the Quartus II software from Altera. The Makefile includes commands to compile the design without running the GUI. The output format is compressed raw binary file.
Some Megafunction Wizards do not work properly in Linux, but when those are done, Windows is not required. Megafunctions are needed to use the PLLs, memory block, and multipliers.
Simulation
Our designs are entered in Verilog and simulated with Icarus Verilog, the simulation results are viewed with GTKWave.
The frontend module
This is somewhat backwards. From the FPGA point of view it is the backend module. The module provides the interface to the ARM and some infrastructure for the core.
mclk
The core logic must run on a PLL derived clock with a frequency well
higher than the SPI interface clock from the ARM, i.e., 30MHz. A
megafunction module called pll96
is provided to generate
a set of clock freuencies: 8, 12, 24, 48, and 96 MHz. Any other
frequency well above 30 MHz will do. For lower core frequencies, we
either need to run the SPI on the ARM at a lower bit rate, or run the
frontend module on a different clock than the core.
spi_slave
This module receives SPI frames from the ARM and translates then into
commands. A command is issued synchronous to the the core clock. The
responses are captured synchronous to the core clock into a 2k word
spififo
. The spi_slave module performs the clock domain
transitions.
command format
A command is issued on four outputs from the module:
-
we
: is high for one cycle -
wp
: is high when the command has a parameter -
wa[13:0]
: command address -
wd[15:0]
: command parameter.
wp
, wa
, and wd
can be sampled
when we
is high, but stay valid for a good part of half a
microsecond.
Typically, commands with a parameter are considered write commands, while commands without parameter are read commands.
responses
Data that shall be returned to the ARM is pusched into the spififo at any time, via two module inputs:
-
re
: high for one cycle for each word. -
rd[15:0]
: data, sampled whenre
is high.
Typically we do not do any resonse arbitration. All data sources just
send data whenever they are triggered to do so. All re
and
rd[15:0]
sources are just or-ed. Collisions are
considered a user error.
The frontend provides three fifos for asynchronous data.
registers
The frontend module instantiates a set of register modules, for it's own use and as a service to the core. These registers are accessed by commands from the spi_slave and provide input and outputs to the user.
Core code can instantiate these modules for internal use.
stat_reg module
The stat_reg
module is read-only. It is basically a
command to return the state of some signal levels.
master_stat
The master_stat instance in the frontend is used to return some frontend status, unused bits can be provided by the core, via the stats module input.
- address 'h0005: master_stat
- bits 'h0001: error summary
- bits 'h00f0: fifos full, f3/f2/f1/hk
- bits 'h0f00: fifos empty, f3/f2/f1/hk
- bits 'hf000: fifos have a packet, f3/f2/f1/hk
conf_reg module
The stat_reg
module is read/write. It provides 16 bits
of output, that can be written and read via SPI. It occupies a single
command address. When a parameter is provided, it is written to the
conf register. In all cases, the (previous) register status is
returned.
spide_reg
This frontend conf_reg defines the data values that shall be returned in SPI frames, when no response data is available.
- address 'h0002: spide_reg
hksizereg, hkmaskreg, hkhdrvreg
These registers define the properties of packets in the housekeeping fifo.
- address 'h0018: hksize
- address 'h0019: hkmask
- address 'h001A: hkhdrv
cntl_reg module
A cntl_reg
module occupies four command addresses, read
and write. Read commands all return the state of the control
registers. Write commands depend on two address bits. Register bits
are set high only with writes when address bit 1 is set. To clear bits
in the register, address bit 0 must be set. When both bits are set,
all bits in the register are written. When no address bit is set, the
command is essentially a read, the parameter is ignored.
master_conf
The master_conf instance in the frontend controls some frontend functions, the (other) bits can be used by the core, through module output confs.
- address 'h0008: master_conf read
- address 'h0009: master_conf clear bits
- address 'h000a: master_conf set bits
- address 'h000b: master_conf write
- bits 'h0008: clock enable
- bits 'h00f0: fifos enable, f3/f2/f1/hk
- bits 'h0100: fifos to ssp disable (clear for streaming)
- bits 'h0200: frontend to ssp disable (set for streaming)
- bits 'h0400: core to ssp disable (set for streaming)
error_reg module
The error_reg
module reads or resets the status of
latches. When an input bit is high, the corresponding bit in the
error register is set. It stays set until a 1 is written to the
register bit.
master_errc
The master_errc instance has a few unused bits that can be used by the core through the errors module input.
- address 'h0006: master_errc
- bits 'h0001: spi_overflow
- bits 'h00f0: fifos were full, f3/f2/f1/hk
- bits 'h0f00: fifos were empty, f3/f2/f1/hk
- bits 'hf000: fifos had a packet, f3/f2/f1/hk
cntr_reg module
A cntr_reg module implements a 32-bit counter. It occupies four command addresses. The address bits control which half of the counter is accessed, and if the access latches.
- read 00: copy counter to latch, read low word of latch
- read 01: copy counter to latch, read high word of latch
- read 10: read low word of the latch
- read 11: read high word of the latch
- write 00: write low word of latch
- write 01: write high word of latch
- write 10: write low word of latch, copy latch to counter
- write 11: write high word of latch, copy latch to counter
master_clock
The master_clock instance counts ticks provided by the core, gated by the clock_enable bit in the master_conf register. The core may tie tick high, to count mclk cycles. The core can read the clock through the clock module output.
- address 'h000c: master_clock low, little endian
- address 'h000d: master_clock high, big endian
- address 'h000e: master_clock low, big endian
- address 'h000f: master_clock high, little endian
packetfifo module
The frontend module provides four packetfifo instances. The housekeeping fifo is fed by commands via SPI. The other three fifos are fed by the core. Each packetfifo can store 2k words. (It is based on an spi_fifo module instance.)
A fifo_read command (address 'h8000) triggers the transfer of a data packet from a packet fifo to the spi_fifo. The packet fifos are checked in priority order. The first one that is enabled by the master_conf register and (thinks) it has a complete packet inside will dump the whole packet to the SPI. Fifo responses must not be disabled in the master_conf register bit 8, else the data will drop into the bitbucket.
packet size
Each packetfifo has a packet size assigned to it. This can be a constand, hardwired by the core, or some register or logic. The packet size is one word more than the number on the psize module input. As soon as that many word are stored in the fifo, the packet is considered complete. Header syncing may invalidate this assumption.
packet header
To provide some limited synchronization of the packet bouindaries, a packet fifo will scan for a packet header word. Words preceding a valid header word are not counted towards the packet size while a packet is sent to SPI. The fifo may run out of words before the packet is complete, since it volunteered to send a complete packet before checking the header.
The header specification consists of a mask and a value word. The masked data word must match the value. If the mask and value are zero, effectivle not header checking is performed. All words match.
If any value bit is set while the corresponding mask bit is not, no header matches, and the fifo is completely drained, possibly overflowing the spi fifo.
Housekeeping fifo
The highest priority fifo is not available to the core, but shall be used by ARM software to inject (housekeeping) packets into the telemetry stream. Registers define packet size and header.
Core fifos
The core must provide packet size and header parameters for three fifos, and write 16-bit wide data into the fifo inputs.
fifo_full outputs are provided to the core, that flag when less that a packet of free space remains in the fifo. fifo_full shall decide if a packet is started, but not prevent the completion of a partially submitted packet.