📜 ⬆️ ⬇️

Why language Verilog microcontroller programmer

image

I started writing this article several times and threw it. I threw it because the topic, I think, is somewhat controversial. The bicycle I have invented may seem ridiculous and absurd to someone and is not entirely correct at all. However…

In general, it seems to me that in the field of the development of electronic devices there exist, as it were, several little overlapping worlds. For example, there is the development of devices based on microcontrollers and in parallel there is the development of devices based on FPGAs. The principles of operation of these microcircuits are fundamentally different and in the same way the principles and methods of development, the programming and debugging languages ​​used differ. Of course, the choice of the element base strongly depends on the task. However, it is clear that these worlds, the world of microcontrollers and the world of FPGAs almost do not overlap. Maybe there is something at the junction of technology?
')
I myself, in general, prefer FPGAs and even participate in the FPGA blog , however, our company recently took up the development of a device based on the STM32 microcontroller. Actually, the main problems that we encountered were not entirely technical, but rather organizational.

The fact is that despite the agreement on the development of the device, and despite the presence of more or less agreed TK for the device, it so happened that every week the customer came with new ideas, requirements, thoughts and wishes. Of course, it would have been possible to send them to hell, but we decided that we would try to be patient and still carry out the project.

The most important organizational problem was that there were a lot of requests for a change in the control algorithm of the controller and they were often very contradictory. And the customer himself was not sure how it should work and did not even really understand how he would check all this. It would be more accurate to say so. There are managers who want to have a controller in their unit. What specific functions the managers and the aggregate should have the managers themselves do not know exactly and the requirements should have been formed by a single engineer who should have checked the operability of the device. The engineer doesn’t have his own methodology for testing the controller’s performance, since he has no experience with electronic devices.

Here is an example. In the standby mode, when the controller just waits for the “Start” button to be pressed, our controller should turn on the pump that pumps the liquid for 10 seconds once a day. This type of protection against souring pump seals. When I ask; “How will you check this function?” - they answer that “no way”. Personally, I'm in shock. We, of course, try to write programs “without mistakes”, but I think the receiving party should somehow share responsibility, conduct its tests, etc ...

Next, go to the actual technical side of things.

We decided that we need some kind of microcontroller software tests.

Usually in the software world there is such a concept unit testing. And in principle, this technique is in some measure suitable for microcontroller programs. Currently, programs for microcontrollers are often written in ordinary C language, so with unit tests, in general, there should be no problems. Although ... not everything can be easily checked by unit tests in the microcontroller.

Everything related to programming internal hardware devices like timers, DMA channels, serial ports, interrupts, and so on - there are problems with this. Here, for debugging, it is time to take an oscilloscope and watch what microcontroller signals are received at the inputs-outputs. And in general, to measure how much time the interrupt is being processed is not a big deal. And it is right.

There is another nuance with unit tests. As it seems to me, the usual unit testing of software is data oriented. Well, that is, usually the unit-test program delivers various expected data to the input of the function being tested and then verifies that the processed output meets the requirements. Everything.

For an electronic device that acts as an input processor, the concept of “flow of time” is crucial. Well, that is, the requirements are usually the following: if an emergency situation occurs and the emergency sensor A is triggered, switch off actuators B , C at intervals of N1 seconds and turn off device D no later than N2 seconds but not earlier than N3 seconds, Something like this.

It is clear that to test the software control algorithm it would be good to use some kind of signal simulator taking into account the passage of time. And there are such tools in the arsenal ... among developers of systems on the FPGA.

The developer of FPGA-based electronic devices typically uses the Verilog hardware description language or VHDL. At the same time, besides the code for the FPGA, the so-called testbench is written - this is something like a unit-test for an ordinary C programmer.

I use Verilog HDL.
The programmer writes the testbench program and at the same time tries to simulate all possible input effects on the FPGA chip. The output signals are analyzed by the testbench and checked in accordance with the expected.
In this case, the simulator Verilog itself monitors the passage of time in the system.

Consider a simple and completely abstract example of what the FPGA programmer does.
For example, here is a module that describes a simple binary counter with asynchronous reset (sample.v):

module sample( input wire reset, input wire clk, output reg [3:0]cnt ); always @(posedge clk or posedge reset) if(reset) cnt <= 0; else cnt <= cnt + 1; endmodule 


I think this code will be understood by any programmer who does not even know the Verilog HDL language. There are two input signals, reset and clk . And there is a four-bit output signal [3: 0] cnt. Always on the clock edge, the value in the counter increases. And always when the unit appears on reset, the counter is reset.

This module is synthesized, that is, it is planned to be compiled and stitched into the FPGA.

Now, for example, a programmer wants to test the performance of his module. He writes a program on Verilog, a testbench that will simulate the input signals for a chip (testbench.v):

 `timescale 1ms / 1 ms module testbench(); reg tb_rst, tb_clk; wire [3:0]value; always #5 tb_clk = ~tb_clk; initial begin $dumpfile("waves.vcd"); $dumpvars(0,testbench); $display("starting testbench!!!!"); tb_rst = 1; tb_clk = 0; #10; tb_rst = 0; #73; tb_rst = 1; #11; tb_rst = 0; #134; tb_rst = 1; #57; tb_rst = 0; #200; $display("finished OK!"); $finish; end sample my_sample_inst( .reset(tb_rst), .clk(tb_clk), .cnt( value ) ); wire fail; assign fail = (tb_rst & value!=0 ); endmodule 


This module is not synthesized, it can not be compiled and stitched in FPGA, but it is needed to simulate the project. Notice the lines

 sample my_sample_inst( .reset(tb_rst), .clk(tb_clk), .cnt( value ) ); 


It is the test sample of the sample module that is inserted into the testbench. It turns out like this:

image

It is very possible that we have a project performance criterion. We need the output signals of the counter to always be zero during the reset signal. That is, we can determine the error signal in the test bench:

 wire fail; assign fail = (tb_rst & value!=0 ); 


This signal can be monitored programmatically or simply viewed with the eyes on the output time diagrams.

I often use a simple free simulator VerilogHDL IcarusVerilog. Its easy to install and work with. I compile and run the simulator:

image

My testbench thanks to the $ dumpfile ("waves.vcd") program lines; and $ dumpvars (0, testbench); creates a wave.vcd timeline file. And these time diagrams can be viewed with another great free tool GtkWave:

image

Thus, the simplest thing a FPGA programmer can do is write testbenches to the module under test and generate the resulting time diagrams and examine them, see whether the correct response comes from the FPGA.

Now I will tell how you can apply a similar testing technology to microcontrollers.

If you pay attention to Verilog testbench again, you will notice there are some system functions like $ display (..).

So here. It turns out that for the Verilog HDL simulator, you can add the necessary system functions in the C language. And once there is a place for the C language, then there is a place where the Verilog testbench code can interact with the Sichny code for the microcontroller.

In general, the Verilog interface to the C language is called the Verilog Procedural Interface (VPI). You can talk about it for a long time, this is a big separate topic. You can read more, for example, here .

I just want to schematically illustrate how this can be used.
A project for a microcontroller can consist of many files. Our task is to separate the actual control algorithm from the hardware features of a particular microcontroller.

Suppose a project for a microcontroller consists of files:

 Main.c Dma.c Serial.c Interrupts.c …. Algorithm.c 


Interrupt handlers from the input lines of the microcontroller are described in the file Interrupts.c. They are something like this:

 void EXTI9_5_IRQHandler(void) { Int val; disableGlobalInterrupts(); EXTI_ClearITPendingBit(EXTI_Line6); val = GPIO_ReadInputDataBit(MY_PORT, MY_SIGNAL); Algo_set_value( val ); enableGlobalInterrupts(); } 


When the signal on the input line of the microcontroller changes, an interrupt occurs, it reads the value on the line and this value is passed to the processing algorithm by the Algo_set_val () function. The entire control algorithm is described in the Algorithm.c file.

The file Algorithm.c simultaneously participates in the project for the microcontroller and in the project for the VPI module Verilog.

image

Thus, developing a “control algorithm”, we basically compile the VPI module together with Algorithm.c for the Verilog simulator. Calling a certain new system function $ int () in Verbog's testbench, we simulate the occurrence of a microcontroller interrupt at some point in time. In the same way, the internal variables of the algorithm can be read and passed to the Verilog testbench with the help of a new system function $ getpin (..). It turns out that our Verilog testbench can simulate the input effects and the flow of time for the microcontroller control algorithm.

It is noteworthy that we have at our disposal timing diagrams of input actions and responses. They can be shown to the customer for the purpose of familiarization - the GtkWave program is used to view them. The customer will be able to see with his own eyes how the input effects from various sensors will respond to his control algorithm. The customer must see all possible combinations of effects from the input signals and all the “black box” responses called the microcontroller.

At least in the time diagrams, you can see how the pump is virtually turned on for 10 seconds every day ...

The last stage - we stop compiling the VPI module for the Verilog simulator (purple block) and begin to compile the microcontroller project (orange block).

Now, the algorithm functions will not be called from the virtual effects of the Verilog simulator, but from physical interrupts from input lines and timers.

Just in case, I note once again that with the help of our Verilog testbench, we certainly don’t verify the correctness of programming peripheral registers like DMA or timers or GPIO. We test only the “control algorithm”. In my opinion, this is very, very important.

Somehow like this.

Source: https://habr.com/ru/post/212507/


All Articles