Add Xilinx System Generator and XSG core config blocks
Add a System generator block from the Xilinx library by locating the Xilinx Blockset library’s Basic Elements subsection and dragging a System Generator token onto your new file.
Do not configure it directly, but rather add a platform block representing the system you care compiling for. These can be found in the CASPER XPS System Blockset library. For ROACH2, you need an XPS_core_config block.
Double click on the platform block that you just added. The Hardware Platform parameter should match the platform you are compiling for. For ROACH2 you have to set this from a drop-down list, for newer platforms it should automatically be set to the correct board type. Once you have selected a board, you need to choose where it will get its clock. In designs including ADCs you probably want the FPGA clock to be derived from the sampling clock, but for this simple design (which doesn’t include an ADC) you should use the platform’s on-board clock. To do this, set the User IP Clock Source to sys_clk. The sys_clk rate is 100 MHz, so you should set this for User IP Clock Rate in the block.
The configuration yellow block knows what FPGA corresponds to which platform, and so it will automatically configure the System Generator block which you previously added.
The System Generator and XPS Config blocks are required by all CASPER designs
To demonstrate the basic use of hardware interfaces, we will make an LED flash. With the FPGA running at ~100MHz (or greater), the most significant bit (MSB) of a 27 bit counter will toggle approximately every 0.67 seconds. We can output this bit to an LED on your board. Most (all?) CASPER platforms have at least four LEDs, with the exact configuration depending on the board. We will make a small circuit connecting the top bit of a 27 bit counter to one of these LEDs. When compiled this will make the LED flash with a 50% duty cycle approximately once a second.
Add a counter
Add a counter to your design by navigating to Xilinx Blockset -> Basic Elements -> Counter and dragging it onto your model.
Double-click it and set it for free running, 27 bits, unsigned. This means it will count from 0 to 2^27 - 1, and will then wrap back to zero and continue.
Add a slice block to select the MSB
We now need to select the most significant bit (MSB) of the counter. We do this using a slice block, which Xilinx provides. Xilinx Blockset -> Basic Elements -> Slice.
Double-click on the newly-added slice block. There are multiple ways to select which bit(s) you want. In this case, it is simplest to index from the upper end and select the first bit. If you wanted the least significant bit (LSB), you can also index from that position. You can either select the width and offset, or two bit locations.
Set it for 1 bit wide with offset from top bit at zero. As you might guess, this will take the 27-bit input signal, and output just the top bit.
Add a GPIO block
From: CASPER XPS library -> gpio.
In order to send the 1-bit signal you have sliced off to an LED, you need to connect it to the right FPGA output pin. To do this you can use a GPIO (general-purpose input/output) block from the XPS library, this allows you to route a signal from Simulink to a selection of FPGA pins, which are addressed with user-friendly names. Set it to use ROACH2’s LED bank as output. Once you’ve chosen the LED bank, you need to pick which LED you want to output to. Set the GPIO bit index to 0 (the first LED) and the data type to Boolean with bitwidth 1. This means your Simulink input is a 1 bit Boolean, and the output is LED0.
Add a terminator
To prevent warnings (from MATLAB & Simulink) about unconnected outputs, terminate all unused outputs using a Terminator:
From: Simulink -> Sinks -> Terminator
You can also use the Matlab function XlAddTerms, run in the MATLAB prompt, to automatically terminate your unused outputs.
Connect your design
It is a good idea to rename your blocks to something more sensible, like counter_led instead of just counter. Do this simply by double-clicking on the name of the block and editing the text appropriately.
To connect the blocks simply click and drag from the ‘output arrow’ on one block and drag it to the ‘input arrow’ of another block. Connect the blocks together: Counter -> Slice -> gpio as showing in digram below.
Remember to save your design often.
To demonstrate the use of software registers to control the FPGA from a computer, we will add registers so that the counter in our design can be started, stopped, and reset from software. We will also add a register so that we can monitor the counter’s current value too. By the end of this section you will create a system that looks like this:
Add the software registers
We need two software registers:
- To control the counter, and
- To read its current value.
From the CASPER XPS System Blockset library, drag two software registers into your design.
Set the I/O direction to From Processor on the first one (counter control) to enable a value to be set from software and sent to your FPGA design. Set it to To Processor on the second one (counter value) to enable a value to be sent from the FPGA to software. Set both registers to a bitwidth of 32 bits.
Rename the registers to something sensible, the names you give them here are the names you will use to access them from software. Do not use spaces, slashes and other special characters in these. Perhaps counter_ctrl and counter_value to represent the control and output registers respectively.
Also note that the software registers have sim_reg and sim_out ports. The input port provides a means of simulating this register’s value (as would be set by the runtime software) using the sim_reg line. The output port provides a means to simulate this register’s current FPGA-assigned value.
For now, set the sim_reg port to constant one using a Simulink-type constant. This can be found in Simulink -> Sources, and will enable the counter during simulations.
During simulation we can monitor the counter’s value using a scope (Simulink -> Sinks):
Here is a good point to note that all blocks from the Simulink library are usually white in colour, and will not be compiled into hardware. i.e. They are present for simulation only. Xilinx blocks are usually blue in colour with the Xilinx logo, and will be compiled to hardware.
You need to use gateway blocks whenever connecting a Simulink-provided block (like a scope or sine-wave generator) to and from a Xilinx block. This will sample and quantize the Simulink signals so that they are compatible with the Xilinx world. Some blocks (like the software register) provide a gateway internally, so you can feed the input of a software register with a Xilinx signal, and monitor its output with a Simulink scope. However, in general, you must manually insert these gateways where appropriate. Simulink will issue warnings for any direct connections between the Simulink and Xilinx domains.
Add the counter
You can do this either by copying your existing counter block (copy-paste, or ctrl-click-drag-drop) or by placing a new one from the library. Configure it with a reset and enable port as follows:
Add the slice blocks
Now we need some way to control the enable and reset ports of the counter. We could do this using two separate software registers, but this is wasteful since each register is 32 bits anyway.
So we’ll use a single register and slice out one bit for enabling the counter, and another bit for resetting it. Either copy your existing slice block (copy-paste it or hold ctrl while dragging/dropping it) or add two more from the library.
The enable and reset ports of the counter require boolean values (which Simulink interprets differently from ordinary 1-bit unsigned numbers). Configure the slices as follows:
Slice for enable:
Slice for reset:
Connect it all up
Now we need to connect all these blocks together. To neaten things up, consider resizing the slice blocks and hiding their names. Their function is clear enough from their icon without needing to see their names.
Do so by right-clicking and unchecking Format → Show Block Name. You could do this with the counter too, but it’s not a good idea with the software registers, because otherwise you wouldn’t know how to address them when looking at your diagram.
To demonstrate some simple mathematical operations, we will create an adder. It will add two numbers on demand and output the result to another software register. Almost all astronomy DSP is done using fixed-point (integer) notation, and this adder will be no different.
We will calculate a+b = sum_a_b.
Add the software registers
Add two more input software registers. These will allow us to specify the two numbers to add. Add another output register for the sum output.
Either copy your existing software register blocks (copy-paste or holding ctrl while dragging/dropping it) or add three more from the library. Set the I/O direction to From Processor on the first two and set it to To Processor on the third one.
Add the adder block
Locate the adder/subtractor block, Xilinx Blockset -> Math -> AddSub and drag one onto your design. This block can optionally perform addition or subtraction. Let’s leave it set at it’s default, for addition.
The output register is 32 bits. If we add two 32 bit numbers, we will have 33 bits.
There are a number of ways of fixing this:
- limit the input bitwidth(s) with slice blocks
- limit the output bitwidth with slice blocks
- create a 32 bit adder.
Since you have already seen slice blocks demonstrated, let’s try to set the AddSub block to
be a 32 bit saturating adder. On the second tab, set it for user-defined precision, unsigned 32 bits.
Also, under overflow, set it to saturate. Now if we add two very large numbers, it will simply return 2^32 -1.
Add the scope and simulation inputs
Either copy your existing scope and simulation constants (copy-paste or ctrl-drag) or place a new one from the library as before. Set the values of the simulation inputs to anything you like.
Connect it all together