Welcome to this Cortex-M3 Design Start Eval video that provides an overview of the RTL. This video shows the structure and the main
components of the RTL, and demonstrates how you can evaluate a design using the RTL simulator graphic user interface and the processor instruction
log file. By the end of this video you will have a better understanding of the RTL and will have learned how to use the methods shown to evaluate
and troubleshoot a program. You will then be able to apply this to your own designs
Before following the instructions in this video, you will need to have the Cortex-M3 DesignStart Cycle model installed, as well as the additional tools that
are required. Also, you must be able to successfully compile the RTL and run the included integration tests. Information and instructions on how to do all
of this can be found in the ARM Cortex-M3 DesignStart RTL and FPGA QuickStart guide. In this video, we will begin by compiling the RTL and
navigating through the structure of the Testbench in the simulation GUI. In order to observe the activity in the first few cycles of some of the main signals
and the ARM architectural registers in a program, we will run the hello test. This will help us to ensure that the test runs as expected. Visualising the
processor activity can also help you understand the transactions in the signal flow. This is a useful exercise to do to highlight the location of any
anomalies in the activity. As well as visualising the waves of the signals, we will also look at the activity in the first few cycles in the tarmac log file. This file
indicates the instructions that are being executed as well as any exceptions that are taken, and the memory, bus, and register accesses. This file is
also useful for tracing software as it runs, and can helpful when troubleshooting design issues.
Before we can open the simulator interface, we need to compile the RTL from inside the execution testbench directory. To do this, enter make compile
and then specify compiling the cycle model by adding DSM=yes. When this is successful, enter command make run TESTNAME=hello DSM=yes
GUI=yes. This opens the testbench interface
so that you can run the hello test using the cycle model from there. In this video we are using the QuestaSim simulator, but you are free to use any of
the supported simulators.
In this view, we have the left-hand Sim window showing the hierarchy of the contents of the testbench, and the Objects window showing the
signals contained in the testbench modules When we run the hello test from the command line, the compiled test image is copied into the run
directory, but not loaded into the simulation until we instruct the simulator to start running. So before we run the test, let us take a look through the contents
of the testbench to locate the Cortex-M3 example system and identify some useful signals. We are going to add these signals to the wave viewer so
that we can observe their activity during the test.
When you scroll down through the contents in the Sim window, you will find the uart capture model. This is used to connect things in the testbench
together, as well as to display messages from printf using the receive data signal, RXD. Let us add this signal to the visualisation by first
selecting the
model then right-clicking on the RXD object and selecting Add wave. Our selection is confirmed here in the transcript window.
Also at the top level of the testbench is the module fpga_top.
Fpga_top is the top level of the design and includes pin muxing logic, and oscillators. Within the design is the system level and then a user
partition that
contains the example system. In here, we can see the SPI-AHB, used for code download, the Timestamp counter for ETM trace, the simple
wrapper for the flash system, which is implemented using SRAM, the normal SRAM subsystem that goes along with the iot_subsystem, a set of
peripherals, that are mostly specific to the FPGA but has a block of APB peripherals, and a default slave.
This user partition is of particular use to us as it is the iot_top subsystem that contains the interconnect, some tightly coupled peripherals, the
AHB to SRAM interfaces and Cortex-M3 integration level. In here is the system C model that is used to represent the internal workings of the
processor. u_DSM has signals that are routed out so that you can observe the internal state as well as the normal IO. In the IO, let us begin to add some
signals to the wave viewer that allow us to visualise the activity that occurs when we run a test.
We will start here by selecting the three HADDR signals for instruction, data, and system – labelled HADDR I, D and S. These busses specify the
addresses for transfers. Again, we will add the waves by right-clicking them and selecting Add wave. Then do the same to add the signals that can
be specifically taken by the instruction bus, HRDATAI – the read data bus, HRTANSI – which indicates whether the bus is idle or non-sequential,
and HREADYI - which, when high, indicates whether a transfer has completed on the bus, and is driven low to extend a transfer. To see the internal
state, let us add the program counter, PC. And to see the internal ARM architectural registers, we will add R0 – R14. Finally, so that the timing is
clear, select the power-on reset signal PoRESETn.
Now we have added the signals that we want to see to the wave viewer we can run the test. Just to check that the correct signals were added, the
transcript window shows a list of all of the signals that we have chosen. Before we run the test, let us log all of the signals so that we can view them later
in the waveform viewer. To do this, enter the command log –r /* . Now we are ready to run the test. To do this, enter the command run –all, and we
can see here that the hello test has passed.
If the test is successful, go to the wave window and you can zoom out to see the activity that occurs throughout the test. The fact that only the first few
registers are used more than the others shows us that this is a simple test. By zooming and scrolling across to the beginning of the test, we can see
that where the reset signal switches to HIGH the processor is able to start running – as indicated by all of the activity that happens after it is set to its
active state.
If you later experience problems with your designs, it can be useful to look closely at the first few cycles to check the activity is as you expect. So let
us do that now. In the test, we can see that the first thing that the processor does is it reads from address 0.
It then gets this response, which has not changed as address 0 has always been in the simulation.
This is used for the initial stack pointer, and we can see here that R13 gets updated with this initial stack pointer value.
We can also see that the only other activity in the ARM architectural registers prior to R13 being updated is R14 being initialised to all f’s . And we’ll
see this again later on.
Then the processor reads from address 4 to get the reset vector.
And the value that is returned is 219. Since 9 is odd, we can infer that bit 0 is set, indicating thumb state, and the address is 218.
These next two cycles are not doing any transfers, as shown here by the idle HTRANSI signal, with a value of 2’h0.
Then we can see an instruction read from address 218, here.
And then reads from addresses 21c and 220 as the core is fetching instructions on the assumption that they are probably going to be useful.
If we look at the activity of the program counter, we can see where we would expect it to change to 218 here, but it is actually greater by 4.
We can also see that instruction fetches occur without the PC changing, then the next instruction shows a PC value of 21E as this data read
occurs. This is an artefact of the ARM architecture, which is important to be aware of as it can be confusing to try and cross-reference the detail of the
waves with the instructions that you think that you are executing. This is clearer to determine in the TARMAC log file, which we will look at soon.
However, it is useful to see the register changes in the waveform viewer. So, if we scroll forward we can see that a little bit further along R0 gets updated
which we can infer is used for the branch to 208, here.
Before we check the log file though, let us quickly confirm what we are seeing in the hello listing file, which was created by the compiler. This is in the
testbench/testcodes/hello/ folder, here. If we scroll down to look at the assembly code, we can see that the reset handler starts here, on this line, with
a branch to SystemInit - and again we see that R0 is updated to 209.
The tarmac log file is located here.To help avoid confusion when trying to understand the meaning of the waveforms, you can open the tarmac log file that
is generated by the test. If you use the obfuscated RTL, then you cannot generate this file. The tarmac log file indicates all of the exceptions, the memory,
bus, and register accesses, and the instructions that are being executed.
Here, we can analyse the same early activity of the test that we have just observed in the wave viewer, and we can trace the software as it runs, seeing the
activity at every cycle. Towards the start of the file, we can see that the processor comes out of reset here and starts to run. It is worth noting that the
tarmac log reports the run transition as an exception, although it is not an architectural exception.
Next, as we also observed in the wave viewer, we can see where R14 is initialised to all f’s and the initial stack pointer is read from address 0.
and written to R13.
Then, again as we saw in the wave viewer, the reset vector is read from address 4 and then we read from the address that we received to get the first
instruction here. This instruction that executes is a 16-bit thumb instruction and loads R0 from an offset address from the program counter, PC.
So R0 is loaded, but there are some instruction fetches in the background that occur just before R0 is loaded and the memory transaction that goes
along with it. Since the pipeline is very short, it can produce an unexpected result where the side-effect is shown before the memory access
that causes it. If we look here, we can see that writing a new value to R0 – the side effect – is shown on the line before the
memory read access is reported, here. However, if we look closely we can see that all of these events occur at the same time – at cycle 444,
and there is no ordering implied here.
Just after this, we can see more of the instructions being executed, and the final thing that we are going to look at is this branch to the address in R0 that if
you recall back to when we were looking at the same activity in the wave viewer, we inferred that this might have happened.
To summarise, in this video we have looked at the structure of the RTL in the testbench, and identified some of the main components. We have selected
some useful signals to observe and analysed their activity across the first few cycles of the hello test. When observed in the wave viewer, we've seen how
the activity of the program counter is not always as we expect and this is an artefact of the ARM architecture. But we have learnt that the tarmac log
file is useful for seeing instructions clearer with more detail. It is also important to remember that the tarmac log file does not always show the exact
order of instructions within each cycle, as we have seen, but this is to be expected and is not indicative of any faults. You can now apply the methods
covered in this video when you inspect and analyse the activity of your own designs to check for the expected signal behaviour. For further information on
the RTL, see the DesignStart documentation - in particular the DesignStart RTL and testbench User Guide, and finally, to share your experience or
ideas, or to access further technical information about designing on Cortex-M3, visit the DesignStart section of the ARM Community .