📜 ⬆️ ⬇️

Circuit design and programming language Verilog

I want to tell you about my impressions of the Verilog programming language. It is used to describe hardware. Even easier to say to describe the architecture of the chip. I started using it in my projects recently. However, it seems to me that I "felt its taste."

A small digression from the topic ...
To begin with, out of curiosity, let's see some Habrow statistics at the time of this writing. I do a search for java, c ++, python, verilog, vhdl keywords:

java: 1581 topic;
C ++: 598 topics;
python: 995 topics;

and
')
Verilog: 6 Topics
VHDL: 5 topics (and by the way, these are the same articles where Verilog is mentioned).

Visible disproportion in the interests of Habratopik writers. It seems that the most common in our country is still "pure" programming. Programming languages ​​for creating microcircuits are seen not at all in fashion.

Especially struck me by today's article on Habré “Independent study of circuitry. Basic concepts. Part 1 "(here habrahabr.ru/blogs/arbeit/91922 ). Honestly, I can’t imagine that people would study circuit engineering and at the same time not mention the modern languages ​​of circuit description ...

Why so? You can make two assumptions. Either the developers of the equipment in our immense country mostly do not read Habr (which I doubt), or microelectronics in us, unfortunately, died irrevocably.

Of course, you can go all out: “died, so died” ... And you can try to do something.
In fact, at present, the development of microcircuits can be carried out practically “on the knees” using CPLD and FPGA microcircuits. If the project "goes", it will be possible later to switch to eAsic or even (if there are investors) to a real ASIC ...
And even it is not at all necessary to have a factory - everyone knows the example of fabless from ARM. The successful design of the processor is patented, and replicated by third-party companies in their products.

All you need to start is to select a developer kit according to your needs and affordability. Fortunately, to get a developer fee in our country is not a problem. For example, the company EFO on the site www.altera.ru offers to purchase boards for experiments from several manufacturers: Altera, Terasic, LDM-Systems. There, of course, there are monsters of $ 7,000 in the list, but there are also inexpensive fees of $ 150. If this is expensive, for a start, it is possible to advise very simple motherboard-type motherboards ( http://www.marsohod.org — by the way, Russian open-source development) —this is about 1000 rubles.
The software development environment for initial surveys is completely free: for example, Altera QuartusII Web Edition.

Well, still come back to the topic.
Long gone are the days when the schemes were drawn in graphic editors. The time has come for real programming languages ​​that allow us to describe the logic of the electronic circuit.

Verilog language is very elegant, does not require extra scribbling, and is somewhat similar to C.
I want to show small examples and, most importantly, code associations and the resulting netlist schema. I think this is very important. Modern programmers are very “corrupted” by virtual memory and processor power. When programming for microcircuits, it is important to understand how it will actually turn out “inside the chip”. Each additional code in the program is wrapped in additional triggers and logic elements in the project. Ultimately, all this affects the speed, the size of the crystal and power consumption.

I will not describe here the syntax of the language - to whom it will be interesting and he will find books on Verilog himself. People here are literate, they have been trained in different languages. I hope for your associative perception. The only thing that must be noticed is that you need to clearly understand what combinatorial logic is, and what registers and synchronous processes are.

Combinatorial logic is simply a logical function of the input data, signals. If one of the input signals changes, the entire function changes (recalculated) immediately. In real terms, the response, of course, is a bit late in time.

Well, for example, the function of calculating the parity of the signal for 32-bit PCI bus. It is necessary to calculate the XOR from all 32 input lines of addresses / data AD [31: 0] and four more CBE signals [3: 0]. If you draw diagrams, then you just need to draw 35 two-input XOR logic elements and connect them with wires.

You can write a small module in Verilog to calculate the parity bit.
It will look like this:

module pci_parity (
input wire [31: 0] ad,
input wire [3: 0] cbe,
output reg parity
);

always @ *
begin
parity = ad [0] ^ ad [1] ^ ad [2] ^ ad [3] ^
ad [4] ^ ad [5] ^ ad [6] ^ ad [7] ^
ad [8] ^ ad [9] ^ ad [10] ^ ad [11] ^
ad [12] ^ ad [13] ^ ad [14] ^ ad [15] ^
ad [16] ^ ad [17] ^ ad [18] ^ ad [19] ^
ad [20] ^ ad [21] ^ ad [22] ^ ad [23] ^
ad [24] ^ ad [25] ^ ad [26] ^ ad [27] ^
ad [28] ^ ad [29] ^ ad [30] ^ ad [31] ^
cbe [0] ^ cbe [1] ^ cbe [2] ^ cbe [3];
end

endmodule

In this code, particular attention should be paid to the combination of always @ * - it just means that the output signal is always “recalculated” when changing any input signal.

Even more concisely the same can be written like this:

module pci_parity (
input wire [31: 0] ad,
input wire [3: 0] cbe,
output wire parity
);

assign parity = (^ ad) ^ (^ cbe);

endmodule

Here the unary operator "^" is used as reduction - that is, just the XOR between all the bits of the vector ad [31: 0].

How to see what we did after compiling in the chip? I use Altera QuartusII. After compiling, you can run the RTLViewer program (this is part of the QuartusII environment) and see the resulting “scheme” after optimization by the compiler.
For both pci_parity code examples, the result is the same:

image

Quite another thing is synchronous circuits and triggers. A trigger is a memory element that stores a cell. On the front (the edges are usually used) of the clock frequency signal, the value at the input of the trigger data is stored in it. A trigger may have additional inputs to enable memory (Enable) and reset.

Let's write a simple counter in Verilog:
module my_counter
(
input wire clk,
output reg [3: 0] counter
);

always @ (posedge clk)
begin
counter <= counter + 1;
end

endmodule

Pay attention to the line always @ (posedge clk) - this line just says that the process is synchronous, associated with the front of the signal clk. Again we compile with QuartusII and see in RTLViewer what we did:

image

We see that, in fact, we have the resulting circuit as if it consists of the combinatorial function of the adder and triggers, which store the counter value according to the clock frequency signal.

Let's change our module a bit like this:
module my_counter
(
input wire reset,
input wire clk,
output reg [3: 0] counter
);

always @ (posedge clk or posedge reset)
begin
if (reset)
counter <= 0;
else
counter <= counter + 1;
end

endmodule

I added an asynchronous reset input to the module and changed the "always @" rule.
Again, compile and watch the resulting RTL:

image

As I promised, the reset input is an asynchronous reset for triggers.

We continue our experiments. For example, let's make a decimal counter:
module my_counter
(
input wire reset,
input wire clk,
output reg [3: 0] counter
);

always @ (posedge clk or posedge reset)
begin
if (reset)
counter <= 0;
else
begin
if (counter == 9)
counter <= 0;
else
counter <= counter + 1;
end
end

endmodule

The second if in our program module will control the multiplexer to load into registers either zero or the next value of the counter.
We look that we have after compilation:

image

Indeed, if "turned" into a multiplexer.

Well, something like this.
On Verilog, just write, just model. Modern design tools make studying circuitry really affordable. Having a wide range of developer boards makes it quite easy to try a project in hardware.

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


All Articles