Yes, and per the other comment this is a huge limitation of them - you don't have Javascript authors saying "you need to work out what you want in this other paradigm and then translate it". You occasionally see people writing C this way though, by working out what they want from the assembly and working backwards, which tends to get wrecked by UB or the optimizer at some security-critical point.
If the main point of the language is to generate flops, flops should be an explicit primitive!
> Verilog is an early object oriented language - modules are objects
Maybe, but IMO a more useful place to apply object orientation would be interfaces, which are nets not modules. I should be able to instantiate "AXI bus" somewhere and connect things to it.
Well, firstly it isn't, as others have explained. It's broader - describe a digital logic circuit - efficiently.
Secondly, it's trivially possible to explicitly generate flip-flops and other hardware primitives using a more "structural" approach:
DFF mydff(
.clk (clk100),
.rst, // means .rst(rst)
.d (in),
.q (out)
);
Thirdly, the whole reason that we have "synthesis" is to allow a much higher-level description that is not so explicitly "structural". It gets really unwieldy otherwise: reg [127:0]out;
always_ff @(posedge clk)
out <= in;
There - I just made 128 of those flip-flops. Also, told you it was a "128 bit register that was clocked on the positive edge". One can at once describe the meaning of the circuit, describe the circuit, and make a event-driven-simulator of the circuit. For really large numbers of elements in a terse but understandable format.It ain't perfect, but it's doing a lot more than I think a lot of people realize and a lot more than a lot of similar looking procedural languages do.
Senior JavaScript developers will. They'll be thinking in terms of types and allocations, even if the language doesn't enforce them. Even junior javascript developers will usually have some concept of async IO execution.
Well, React with the hooks API has basically become that. You need to imagine your code first as computational effects triggered by state dependencies in an implicit stack, and then you translate that into a language where all of that must be represented as either calling functions or passing functions around.
As to the second point, you can do exactly what you said, instantiate a SystemVerilog “AXI bus” interface and connect things to it. With the interface being a single line item in the port map. This comes with its own set of headaches and I’m not always sure it’s worth it.
I disagree. A HDL, which verilog is an instance of, provides a precise description of a digital machine.
Once you have that description, many things can be done with it. For example you can simulate the machine which is to be produced.
The problem is HDL looks like an algorithm, because it is. But it’s not a precise description of a computation, it’s a description of an object.
Most people who I’ve observed program verilog badly do so because they confuse the two. Kinda like confusing giving directions with giving instructions to make a map. Directions and maps are highly related, but they’re not the same thing.
> I should be able to instantiate "AXI bus" somewhere and connect things to it
There's a powerful concept called Interfaces which is pretty exactly what you just invented. You can create (and I have) an AXI Interface, even parameterized by address or data widths, etc. You can create these interfaces and connect them to modules very efficiently.
SystemVerilog/Verilog has grown to a very excessive bulky language, but unless you are doing exclusively validation/simulation and want things like UVM, the "synthesizable subset" is pretty sensible and one can very productively stick to that.
Not really. You wouldn't expect good programs from someone who has no idea how a computer works. The language is the knobs and dials. You need to know what the knobs and dials do in the machine.
I wouldn't expect them to write a good operating system, but for the vast majority of code that is being written you can get pretty far with "your cpu is faster than your memory" as the only bit of knowledge about how computers work.
I think this is actually not right. There's not any kind of loop that is running, it's triggered by signal edges. That's the fundamental difference between hardware and software that makes hardware difficult for software people. Everything happens simultaneously.
always @(posedge clk) begin
do some stuff
if (condition) begin
@(posedge clk);
do some more stuff
end else begin
@(posedge clk);
do some different stuff
end
......
end
Synopsis will happily synthesise this, generating the implied state variable. There really is a loop in there. In fact 'always' is exactly 'initial #0 forever'In simulation this is easy to implement, but in synthesis the synthesis tool needs to rewrite it as some hidden flops for state and a top level case statement
always #half_period areg = ~areg;
always c = #5 ~c;
the @() portion is not intrinsically part of the always - it's just usually used there for synthesisable codeIf not, where in this shift register[1], when synthesized to an FPGA, is the loop waiting for posedge clk or posedge reset?
[1]: https://asic4u.wordpress.com/2016/03/28/verilog-1-delay-in-r...
always begin
@(posedge clk) v <= a+1;
@(posedge clk) v <= a-1;
end
is identical to: always @(posedge clk) begin
v <= a+1;
@(posedge clk)
v <= a-1;
end
both can be synthesised and make the same logicOk, then we agree. Of course a simulator will have an implicit loop, that's not contentious.
However you did not mention this in your initial statement, and I've read and been told explicitly not to think of it like this because there's no loop in hardware.
It’s like programming a machine to make a watch. At the end you have a watch. Would you say the gears execute in parallel while it measures time?
In some sense it’s right, but in another it’s missing the point.
Yes, there are two kinds of boxes (flip-flops and latches) and how the clock works varies (and there are often multiple clocks, and the clocks may be driven by logic).
More to the point, I'd argue that the hardware designers job is to manage state and logic so a language which makes them explicit is a good thing.
It's possible to design a language that works exactly like that. The simulator is easy to make very fast and is easily parallelizable. (The logic clouds are acyclic. Moreover, everything that needs to be evaluated at a given clock event or combination thereof can be determined AND partitioned statically.)
The synthesis is also easy.
Note that SystemC is NOT such a language.
I learnt C then Verilog, I am fluent in Verilog. The mindset for designing digital logic is completely different to programming computers, it literally is a completely different skill. The problem is, people think just because they can type a (procedural) programming language they can program anything that is programmed with a code which is where peoples initial distaste for Verilog and VHDL comes from. When you learn how to do it, I think designing logic is refreshing compared to writing software, there's so much baggage with software.
Procedure to make brick wall:
For brick in wheel-barrow do
To brick, apply mortar, place it, pound it with trowel
(Apologies to all masons. I think you can tell my training is electrical engineering.)I've thought for some time that the main problem with Verilog is that it looks really close, visually, to C and that gives people the wrong impression.
My go-to example for this is the Carry-skip Adder. (https://en.wikipedia.org/wiki/Carry-skip_adder)
Things are happening simultaneously in time and space. The ripples are happening while the skips are happening. The skips go stable because the ripple goes stable or the carry will skip so the ripple has "extra time" to go stable.
This is the simplest add faster than naive ripple carry. Note that it has no clocks. This is a purely combinatoric problem. And most "digital designers" will get it wrong.
Hardware design is NOT software design. Good digital designers are always thinking about how to interleave things in time and space like this.
For example, the current big advance in "modern" languages is "async". Which "just" instantiates an implicit state machine that you can't control.
Is there an option for bothedge clk?
As the parent's-parent comment said in other words, think circuit first.
Initially you really need a strong understanding of digital logic (not a language), in particular pipelines.
Once you have that stuff in your head you can turn to verilog (or vhdl or whatever) and learn how to map these ideas into the language
In System Verilog it's easy this is the only way to reliably make synthesisable flops:
And you can make combinatorial logic 2 ways: They'll make the same gates, notice the use of = vs <=, you typically use the always when you want something more complex"always X" just means loop waiting for X, '*' means "anything important changes"
That's it, the most important concepts you have to get your head around, everything else is just this at scale - also please ignore the async reset in the "Verilog is Weird" example - they tend to be timing nightmares in the real world, use a synchronous reset instead.
One more thing - Verilog is an early object oriented language - modules are objects - but they are static, the entire design can be elaborated at compile (or synthesis) time - why? because you can't new or malloc more gates on the fly on a real chip - almost everything in verilog is static by design (it does support local variables in functions but anything that's vaguely recursive wont make gates in synthesis)