FPGAs provide a flexible hardware platform for prototyping and developing custom digital circuits and systems. The Cortex-M0 DesignStart FPGA from ARM offers an affordable option for exploring Cortex-M0 CPU designs by allowing you to compile and load your own custom bitstreams.
Overview of Cortex-M0 DesignStart FPGA
The Cortex-M0 DesignStart FPGA features a low-cost Spartan-6 LX9 FPGA from Xilinx coupled with a pre-integrated Cortex-M0 CPU. This allows you to quickly build a custom hardware system around the Cortex-M0 by utilizing the FPGA fabric. Some key features of the DesignStart FPGA include:
- Xilinx Spartan-6 LX9 FPGA with 7200 logic cells
- 50MHz clock frequency
- Pre-integrated Cortex-M0 CPU running at 50 MHz
- 128KB of RAM
- 16MB of Flash memory
- UART, I2C, SPI, Ethernet, USB 2.0, and other interfaces
By providing an affordable development platform with a Cortex-M0 CPU, the DesignStart FPGA allows developers to prototype and test Cortex-M0 designs before manufacturing a custom ASIC or embedding a Cortex-M0 in a larger design.
Design Flow Overview
To build your own custom bitstream for the DesignStart FPGA involves the following general steps:
- Create your design in a hardware description language like VHDL or Verilog
- Synthesize your design using Xilinx ISE tools
- Add pin constraints for the DesignStart FPGA board
- Run placement and routing to generate a bitstream file
- Load the bitstream onto the DesignStart FPGA to configure the FPGA fabric
This gives you an overview of the process – you design your circuit, synthesize it into gates, map it to the actual FPGA resources, generate a bitstream file, and load that file to program the FPGA with your custom logic and interconnect.
Designing with HDL
The first step is to create your digital hardware design using a hardware description language (HDL) like VHDL or Verilog. This describes the behavior and structure of your system at the register transfer level (RTL). For example, you can design a simple accumulator module in VHDL: library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity accumulator is port ( clk : in std_logic; input : in std_logic_vector(7 downto 0); load : in std_logic; rst : in std_logic; output: out std_logic_vector(15 downto 0) ); end accumulator; architecture Behavioral of accumulator is signal acc_reg: unsigned(15 downto 0) := X”0000″; begin process(clk) begin if(rising_edge(clk)) then if(rst = ‘1’) then acc_reg <= (others => ‘0’); elsif (load = ‘1’) then acc_reg <= unsigned(input); else acc_reg <= acc_reg + unsigned(input); end if; end if; end process; output <= std_logic_vector(acc_reg); end Behavioral;
This describes an 8-bit accumulator circuit that can be instantiated in a larger design. The HDL allows you to architect the digital logic before mapping it to hardware resources.
FPGA Synthesis
The next step is synthesize your HDL design using the Xilinx ISE tools. This takes your HDL code and converts it into an actual gate-level implementation by inferring hardware resource like look-up tables (LUTs), flip-flops, block memories, DSP slices, etc. The synthesis tools will analyze and optimize your design to best map it to the FPGA.
For example, the accumulator module would infer registers, operators, and connections which map nicely to slice logic resources in the FPGA. The synthesis tools take care of this translation from HDL to gates/resources. After synthesis, the design can be simulated to verify functionality before placement and routing.
Pin Constraints
To target the Cortex-M0 DesignStart FPGA board, you need to apply pin constraints which map signals in your HDL design to the actual physical pins of the FPGA package. This is done using a UCF (user constraints file) which provides location constraints. For example: NET “clk” LOC = “E3”; NET “rst” LOC = “C12”; NET “input[7]” LOC = “D11”; # etc…
This maps the clk, rst, and input signals from your HDL to the pin locations printed on the FPGA board. Applying these pin constraints is crucial for getting your design to work on the actual hardware.
Placement and Routing
After synthesis and pin constraints, the next step is placement and routing. This takes your gate-level netlist and maps it to the actual FPGA resources – specific logic cells, block RAMs, DSPs, IO blocks, etc. The placer figures out where each logic element should go and the router connects them with wire segments.
This can be a time-consuming process as the tools try to optimize delay, routability, and resource utilization. Timing constraints are also applied during this stage to meet clock frequency requirements. The output of placement and routing is a binary bitstream file that can program the FPGA fabric.
Loading the Bitstream
Once you have your bitstream file, you can load it onto the DesignStart FPGA board to actually configure the Spartan-6 FPGA. This uses the Xilinx Platform Cable USB port to essentially “rewrite” the SRAM cells in the FPGA to implement your custom logic design.
There are a few ways to load the bitstream:
- Use the iMPACT tool included with ISE – click on the FPGA device and select Program to download the bitfile.
- Use the bootloader that comes with the board – just copy the bitfile to the BOOT partition.
- Drag-and-drop the bitfile to the Xilinx Platform Cable USB drive.
Once programmed, the FPGA will execute your loaded design each time it powers up. You can iterate by making logic changes and rebuilding the bitstream to reprogram the device.
Demo Design Overview
To help illustrate the full compile and load process, here is an overview of a demo design you can implement on the Cortex-M0 DesignStart FPGA:
- top.v – Top-level module
- Instantiates ADC, accumulator, and UART modules
- Interconnects blocks with wires
- adc.v – 8-channel Analog-to-Digital Converter
- Takes analog inputs and digitizes
- Streams out 8-bit samples
- accumulator.v – Configurable accumulator
- Adds incoming samples
- Width/latency configurable via regs
- uart_tx.v – UART transmitter
- Takes 16-bit data and serializes
- Sends over UART pins
This demo system takes analog inputs, digitizes with the ADC, accumulates samples in the accumulator block, and transmits the accumulated value over UART. The top-level ties together the different blocks.
After writing the RTL code, we synthesize with Xilinx ISE targeting the Spartan-6 device on the board. Pin constraints are applied to map ADC inputs and UART pins from the top-level ports to the right package pins.
After placement and routing, we generate the bitstream file and load it to the DesignStart FPGA using iMPACT or the bootloader. The programmed FPGA will run our demo design taking real analog inputs and transmitting data over the serial port.
Conclusion
The Cortex-M0 DesignStart FPGA provides an affordable way to prototype Cortex-M0 designs by allowing you to compile your own custom bitstreams. This involves coding in HDL, synthesizing with Xilinx ISE, applying pin constraints, placing and routing, and loading the bitstream to configure the FPGA fabric.
With the techniques covered here, you can take advantage of the flexibility of FPGAs to build your own digital systems around the Cortex-M0 CPU on the DesignStart board for learning and experimentation.