Author Topic: What HDL to start with  (Read 16166 times)

0 Members and 1 Guest are viewing this topic.

Offline james_s

  • Super Contributor
  • ***
  • Posts: 21611
  • Country: us
Re: What HDL to start with
« Reply #25 on: March 09, 2020, 05:53:55 pm »
VHDL is going the way of dodo, just like Basic and Pascal are. No reason to bother with it.


VHDL is hugely popular in the hobbyist/open source circles, that right there is a reason to bother with it. Ultimately though the choice of language is virtually irrelevant, they all have the same capabilities, hardware that can be defined with one can be defined with another.


To the OP:
Regarding software, you are stuck with the software provided by the vendor for the part you are using.

Your question is a bit like asking a group of people what religion to choose though, and you will also find that there are a handful of professional developers who do this for a living and cannot comprehend that the needs of a hobbyist are different than their own. Most of us who dabble in FPGAs are never going to be doing it as a real job so their adamant advice on what you "have" to do is irrelevant.
 

Offline tggzzz

  • Super Contributor
  • ***
  • Posts: 20355
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: What HDL to start with
« Reply #26 on: March 09, 2020, 09:09:05 pm »
You can write it in somewhat behavioral way and still take advantage of DSP pipeline registers because Vivado synthesizer is smart enough to do that for you if you white the code in certain way.

I'll be heretical and ask...

What's the advantage if you have to write the code in a certain way to make it fit onto one specific hardware block?
Why not just instantiate the block directly?

That would, arguably, very explicitly indicate the intention.
It would, arguably, not lose any portability or reusability - if the specific hardware block is not available then the specially crafted code would probably have to be rewritten anyway.
There are lies, damned lies, statistics - and ADC/DAC specs.
Glider pilot's aphorism: "there is no substitute for span". Retort: "There is a substitute: skill+imagination. But you can buy span".
Having fun doing more, with less
 

Online asmi

  • Super Contributor
  • ***
  • Posts: 2778
  • Country: ca
Re: What HDL to start with
« Reply #27 on: March 09, 2020, 09:19:18 pm »
I'll be heretical and ask...

What's the advantage if you have to write the code in a certain way to make it fit onto one specific hardware block?
Why not just instantiate the block directly?

That would, arguably, very explicitly indicate the intention.
It would, arguably, not lose any portability or reusability - if the specific hardware block is not available then the specially crafted code would probably have to be rewritten anyway.
1. It will still work on different architectures, even though at much lower Fmax.
2. It allows using sims which don't know what DSP48E1 is (for example Verilator) for behavioral simulations.
3. It is much more clear in what it does, while DSP can do many things, and figuring out what exactly it's set to do at specific instantiation is not trivial unless you specialize on DSP and so memorized all opcodes and config options.
3. It's much less code and so it's easier to read. Code is read much more often than it is written, so maintaining readability is very important.

Offline tggzzz

  • Super Contributor
  • ***
  • Posts: 20355
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: What HDL to start with
« Reply #28 on: March 09, 2020, 09:52:44 pm »
I'll be heretical and ask...

What's the advantage if you have to write the code in a certain way to make it fit onto one specific hardware block?
Why not just instantiate the block directly?

That would, arguably, very explicitly indicate the intention.
It would, arguably, not lose any portability or reusability - if the specific hardware block is not available then the specially crafted code would probably have to be rewritten anyway.
1. It will still work on different architectures, even though at much lower Fmax.
2. It allows using sims which don't know what DSP48E1 is (for example Verilator) for behavioral simulations.
3. It is much more clear in what it does, while DSP can do many things, and figuring out what exactly it's set to do at specific instantiation is not trivial unless you specialize on DSP and so memorized all opcodes and config options.
3. It's much less code and so it's easier to read. Code is read much more often than it is written, so maintaining readability is very important.

1: accepted, but ugh!
2: not clear that is a benefit
3: unconvinced. Crafting C code to get a specific assembler output has always struck me as inelegant, somewhat obfuscatory, and subject to change when a compiler changes. The analogies with HDLs and synthesisers are clear.
4: readability is very important, but it is arguable whether it is more readable. N.B. it = crafted code plus synthesiser  plus logic family blocks.
There are lies, damned lies, statistics - and ADC/DAC specs.
Glider pilot's aphorism: "there is no substitute for span". Retort: "There is a substitute: skill+imagination. But you can buy span".
Having fun doing more, with less
 

Offline jmelson

  • Super Contributor
  • ***
  • Posts: 2816
  • Country: us
Re: What HDL to start with
« Reply #29 on: March 09, 2020, 10:24:49 pm »
NO!!! If you go this route you'll be writing a lot of very bad and poorly maintainable code and achieve very little. I've seen this over and over. The trick is to understand how your code is translated into FPGA primitives. But other than that the most time efficient way is to treat writing FPGA exactly like you are writing software.
This approach only works if your goal is to design something that runs at 1 MHz. It will fail badly if you need your design to run at any decent frequency.
That is your opinion but I have been following the exact principle for almost 2 decades very succesfully.
Right, some years ago I did a project where almost all of the FPGA was running at 150 MHz on a Spartan 3A, and it could have gone faster.  All pretty simple VHDL.

Jon
 

Online asmi

  • Super Contributor
  • ***
  • Posts: 2778
  • Country: ca
Re: What HDL to start with
« Reply #30 on: March 09, 2020, 11:59:57 pm »
3: unconvinced. Crafting C code to get a specific assembler output has always struck me as inelegant, somewhat obfuscatory, and subject to change when a compiler changes. The analogies with HDLs and synthesisers are clear.
What's so unclear in this code? It shows exactly what's happening inside DSP tile (the only simplification is about pipeline register right after multiplication). You can't possibly claim it's "assembly code" vs "C code" situation.
4: readability is very important, but it is arguable whether it is more readable. N.B. it = crafted code plus synthesiser  plus logic family blocks.
To me there is no argument as I tried both approaches before settled on one I use today. But you can prove me wrong and show me a better way of doing the same, that works as good as my code (meaning still hits Fmax).

Online nctnico

  • Super Contributor
  • ***
  • Posts: 27694
  • Country: nl
    • NCT Developments
Re: What HDL to start with
« Reply #31 on: March 10, 2020, 12:13:25 am »
3: unconvinced. Crafting C code to get a specific assembler output has always struck me as inelegant, somewhat obfuscatory, and subject to change when a compiler changes. The analogies with HDLs and synthesisers are clear.
Well, at some point you need to be aware of the limitations of the underlying hardware. However the patterns to be used are well explained in Xilinx' documentation (synthesizer manual). Ofcourse the more hardware specific your code gets, the more difficult it will be to make the code portable. Still writing a=b*c +d (for example) is much cleaner compared to instantiating a primitve (which usually requires reading how it works to instantiate it correctly).
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Online rstofer

  • Super Contributor
  • ***
  • Posts: 9929
  • Country: us
Re: What HDL to start with
« Reply #32 on: March 10, 2020, 03:30:19 am »
You can write it in somewhat behavioral way and still take advantage of DSP pipeline registers because Vivado synthesizer is smart enough to do that for you if you white the code in certain way. I've already showed this example in the past here, so below code is mapped fully onto DSP tile, takes advantage of all pipeline registers and runs at Fmax for DSP tile (550 MHz for speed grade 2 Artix/Spartan-7):
Code: [Select]
module mul_dsp #(
    parameter WIDTH = 17
) (
    input clk,
    input [WIDTH-1:0] arg0,
    input [WIDTH-1:0] arg1,
    output logic [2*WIDTH-1:0] result
);

bit [WIDTH-1:0] a0, a1;

bit [2*WIDTH-1:0] res_pipe[0:1], res;
   
always_ff @(posedge clk) begin
    a0 <= arg0;
    a1 <= arg1;
   
    res_pipe[0] <= a0 * a1;
    res_pipe[1] <= res_pipe[0];
   
    res <= res_pipe[1];
   
    result <= res;
end
endmodule
As you can see, it's easy to read and understand what's going on, and it perfectly maps to the hardware. Note there is an extra pipeline stage at the end to close IO timing (I did actually run it through P&R to confirm it works), in regular "internal" case it is not needed.

I haven't had occasion to write code like that, I'm not even sure I would think of it.  It's elegant!
 

Offline tggzzz

  • Super Contributor
  • ***
  • Posts: 20355
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: What HDL to start with
« Reply #33 on: March 10, 2020, 06:45:50 am »
3: unconvinced. Crafting C code to get a specific assembler output has always struck me as inelegant, somewhat obfuscatory, and subject to change when a compiler changes. The analogies with HDLs and synthesisers are clear.
What's so unclear in this code? It shows exactly what's happening inside DSP tile (the only simplification is about pipeline register right after multiplication). You can't possibly claim it's "assembly code" vs "C code" situation.
4: readability is very important, but it is arguable whether it is more readable. N.B. it = crafted code plus synthesiser  plus logic family blocks.
To me there is no argument as I tried both approaches before settled on one I use today. But you can prove me wrong and show me a better way of doing the same, that works as good as my code (meaning still hits Fmax).

It was a general observation applicable to the general approach, not specific to one example.

It is always possible to choose an example to justify any contention.

I'll restate a point I made in an earlier post: "But non-dogmatic good taste trumps all of those [earlier points]".
There are lies, damned lies, statistics - and ADC/DAC specs.
Glider pilot's aphorism: "there is no substitute for span". Retort: "There is a substitute: skill+imagination. But you can buy span".
Having fun doing more, with less
 

Offline tggzzz

  • Super Contributor
  • ***
  • Posts: 20355
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: What HDL to start with
« Reply #34 on: March 10, 2020, 06:48:58 am »
3: unconvinced. Crafting C code to get a specific assembler output has always struck me as inelegant, somewhat obfuscatory, and subject to change when a compiler changes. The analogies with HDLs and synthesisers are clear.
Well, at some point you need to be aware of the limitations of the underlying hardware. However the patterns to be used are well explained in Xilinx' documentation (synthesizer manual). Ofcourse the more hardware specific your code gets, the more difficult it will be to make the code portable. Still writing a=b*c +d (for example) is much cleaner compared to instantiating a primitve (which usually requires reading how it works to instantiate it correctly).

Agreed. There is a balance to be struck, and good taste is important.

I'll note the comment I made in an earlier post: "Where designing a datapath, especially involving arithmetic, I'll adopt a programming language approach, giving the toolset as much information as possible about my use of the data in the datapath, e.g. signed/unsigned, width etc."

There are lies, damned lies, statistics - and ADC/DAC specs.
Glider pilot's aphorism: "there is no substitute for span". Retort: "There is a substitute: skill+imagination. But you can buy span".
Having fun doing more, with less
 

Online nctnico

  • Super Contributor
  • ***
  • Posts: 27694
  • Country: nl
    • NCT Developments
Re: What HDL to start with
« Reply #35 on: March 10, 2020, 11:16:24 am »
3: unconvinced. Crafting C code to get a specific assembler output has always struck me as inelegant, somewhat obfuscatory, and subject to change when a compiler changes. The analogies with HDLs and synthesisers are clear.
Well, at some point you need to be aware of the limitations of the underlying hardware. However the patterns to be used are well explained in Xilinx' documentation (synthesizer manual). Ofcourse the more hardware specific your code gets, the more difficult it will be to make the code portable. Still writing a=b*c +d (for example) is much cleaner compared to instantiating a primitve (which usually requires reading how it works to instantiate it correctly).

Agreed. There is a balance to be struck, and good taste is important.

I'll note the comment I made in an earlier post: "Where designing a datapath, especially involving arithmetic, I'll adopt a programming language approach, giving the toolset as much information as possible about my use of the data in the datapath, e.g. signed/unsigned, width etc."
That is a good comment. It is also an area where you can get stuck if you take the wrong exit when using VHDL. In a lot of VHDL code you see std_logic_vector being used for signals which are a number. Once you want to use a std_logic_vector as a number you have to do a horrific amount of casting and the strong typing of VHDL gets in the way. But the problem isn't VHDL, the problem is the person who is writing the code.
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline tggzzz

  • Super Contributor
  • ***
  • Posts: 20355
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: What HDL to start with
« Reply #36 on: March 10, 2020, 11:59:14 am »
3: unconvinced. Crafting C code to get a specific assembler output has always struck me as inelegant, somewhat obfuscatory, and subject to change when a compiler changes. The analogies with HDLs and synthesisers are clear.
Well, at some point you need to be aware of the limitations of the underlying hardware. However the patterns to be used are well explained in Xilinx' documentation (synthesizer manual). Ofcourse the more hardware specific your code gets, the more difficult it will be to make the code portable. Still writing a=b*c +d (for example) is much cleaner compared to instantiating a primitve (which usually requires reading how it works to instantiate it correctly).

Agreed. There is a balance to be struck, and good taste is important.

I'll note the comment I made in an earlier post: "Where designing a datapath, especially involving arithmetic, I'll adopt a programming language approach, giving the toolset as much information as possible about my use of the data in the datapath, e.g. signed/unsigned, width etc."
That is a good comment. It is also an area where you can get stuck if you take the wrong exit when using VHDL. In a lot of VHDL code you see std_logic_vector being used for signals which are a number. Once you want to use a std_logic_vector as a number you have to do a horrific amount of casting and the strong typing of VHDL gets in the way. But the problem isn't VHDL, the problem is the person who is writing the code.

Agreed.

Except in standard well-understood use-cases, casting is an orange flag that something is wrong.

It is usually beneficial to occasionally examine a compiler's/synthesiser's output to see that you haven't missed something significant. But needing to do that frequently is an orange flag.
There are lies, damned lies, statistics - and ADC/DAC specs.
Glider pilot's aphorism: "there is no substitute for span". Retort: "There is a substitute: skill+imagination. But you can buy span".
Having fun doing more, with less
 

Offline free_electron

  • Super Contributor
  • ***
  • Posts: 8549
  • Country: us
    • SiliconValleyGarage
Re: What HDL to start with
« Reply #37 on: March 10, 2020, 01:30:01 pm »
Verilog was designed from the getgo to produce digital logic.
VHDL is a generic hardware description language. You could even describe a nut and bolt or screwdriver with it. For logic you use the logic libraries

systemverilog solves a number of 'perceived issues' ( like latch inferrence ) by providing constructs like always_ff and always_comb , but overall makes coding simpler.

The big thing is : learn how a logic synthesizer works and use it ! There is a very good book by Bhasker : https://www.amazon.com/Verilog-HDL-Synthesis-Practical-Primer/dp/0965039153
There is a difference between writing verilog ( or vhdl) and verilog (or vhdl) for SYNTHESIS ( fpga/ asic). Sure you can model things very high level , but the generated output will be horrible in terms of performance and logic size.

One of the least known, or least understood, (verilog/systemverilog) synthesis rules is this one : logic shall be executed IN THE ORDER IT IS WRITTEN. And most people ( non-asic designers, or software-approach people ) never use this.
It solves many problems , and it tells you EXACTLY what the synthesizer is going to build. I've written multimillion gate logic designs that were first-time right. No need to simulate it even. Synthesize and go ( this involved bus arbiters between two cpu's , memory and a whole bunch of accelerator logic. Some of that system sits in every harddisk produced.

I see so much code with if-then else constructions that are unneeded, unterminated (missing cases) , do not cover all possible pathways and create 'unwanted states'. That all could be solved if you just learn how a synthesizer works.

Here goes a short description:

To convert your list of instructions  (which are sequential in nature ) to logic the synthesizer needs to build a 'cloud' of , let's call it 'command logic'. You tell it what you want a block to do and the synthesizer converts that in a bunch of combinatorial logic that will control a register. Doesn't matter what you are building. A counter, a memory , a shifter , a lookup table, a comparator, or even if this block is registered (flipflops) or combinatorial (and/or/not)

The synthesizer builds logic on-the-fly. It reads a line of code and drops down a bunch of gates/flipflops , then it evaluates the next line and does this again. At the end of the command list it runs a logic minimization algorithm that compresses the combinatorial stuff to the least amount of gates. This is NOT necessarily the final output. Depending on your target architecture (fpga or asic) the gates may or may not exist and logic may need to be 'expanded' again to fit what is available. ( your selected device may not have a 8 input AND gate and one will have to be built using two 4 input and gates and one 2 input and gate, the device compiler takes care of that, none of your worries, except timing wise )

let's look at an example:

build me a 4 bit counter.
- it needs a system_reset, reset , a preset , a parallel load , a count up/down control, an enable 4 inputs and 4 outputs. And a clk of course.
- the system_reset should work always, irrespective of any other control line.
- the reset,preset,load,up/down are tied to the 'enable' signal. if the counter is not enabled nothing is to happen.
- reset takes priority ,followed by preset , and load (meaning if more than one signal is active , reset has the highest 'weight'. if both reset and load commands arrive at the same time : reset wins.)
- updown zero means count down, if one : count up

Code: [Select]
always_ff(@ posedge clk) begin       
  if (enable) begin
     count <= count-1;
     if (updown) count <= count+1;
     if (load) count <=data_in;
     if (preset) count <=4'd9;
     if (reset) count <=0;
  end;
  if(system_reset) count <=0;
end;

Let's analyse this a bit:

always_ff : i need flipflops here. Don't muck around with other constructs. You tell the compiler explicitly that it must create register logic, so there is no wiggle room for interpretation.
@ posedge clk : and we will perform operations based on the rising edge of a clock signal. 
if(enable) : look at the enable signal : if it is high, process the attached list of commands
count <=count-1 : wait, what ? why do you do this. well here is the thing, i am using the synthesizer to my advantage here by writing so called 'scheduled' logic ( this comes down to the statement that 'statements will be executed in the order they are given' )

I Tell the synthesizer : schedule (prepare) to count down.

The next statement says "if updown count <= count +1". so now i tell the synthesizer : if updown is active : count up .

What is going on here ? ( and this is the KEY difference between software languages and hardware languages. once you grasp this , you can do anything you want. )
You will no doubt have had people tell you 'everything happens in parallel in an fpga . Well, it does , but that does not mean there is no 'order' ! there is : the order in which the statements are written !

in software this would happen :
count <=count -1    // we subtract one
if(enable) count <= count+1  ' if enabled we add one

so, if count was 3, we end up with either 2 (enable=0) or 3 (enable=1, we subtracted 1 (3-1=2), then added one 2+1 = 3

In logic that does NOT happen. You end up with 2 or 4 why ? Because of how a synthesizer works. And now i need to switch to a graphic representation of how a synthesizer 'builds' logic. Take a look at the attached picture.
The synthesizer starts reading your instruction list. The first thing it encounters is always_ff (posedge clk)
So, it drops down a register and attaches the clock to CLK. Since the synthesizer does not know what comes next , it attaches the output (count) to the input. We don't want any dangling lines ...
So whenever a CLK happens the register simply stores its own output. No data is corrupted.

Now it sees 'if(enable) {list of instructions}  (second image down)
So the synthesizer injects a multiplexer ( the trapezoid thingie) under control of ENABLE. If ENABLE =0 then COUNT is connected to the data input of the flipflops, if ENABLE =1 then the list {} is connected to the data input of the flipflops.
A multiplexer is nothing but a switch under control of a signal. Such a switch in Boolean logic is a very simple equation : out = (in0 and not(enable)) or (in1 and enable) : two and gates, an inverter and an or gate.

Note : the list is represented by the yellow box.

Now the synthesizer sees : count <= count -1, so it drops a logic subtractor circuit in place.
The next statement says : if (updown) count up. So it injects another multiplexer , under control of UPDOWN , that switches between what it already had (count down) , and the new command (count up).

The next statement says if LOAD then we need to take in DATA_IN , so we drop another multiplexer that switches between everything that came before , and the now operation.
This is the key thing to remember: you switch between WHAT CAME BEFORE and the NEW statement. The ORDER IN WHICH INSTRUCTIONS ARE GIVEN.
Yes, all that stuff happens in parallel, the adding, subtracting , loading , but it happens IN THE ORDER IT IS GIVEN. So the LOAD has a higher priority than anything that came before. It doesn't matter what state up-down is in, or what the count value is incremented or decremented , if LOAD is active then we will take in DATA_IN.

The synthesizer keeps on reading statements and dropping multiplexers : one for preset , one for reset. Every new statement has a HIGHER priority than what came before. So you will never get a conflict of interest. We have two signals active.. how do we decide ? We need if then else ... no you don't it follows the order given. If you write if-then-else statements there is a risk you forget to specify certain conditions. As we cannot have 'floating' lines ,the synthesizer will tie those 'forgotten' pathways' to something ( and that is not always what you might think it is ... ) and then you end up with logic that does weird things if a state is encountered that was not covered.

By using scheduling as i describe it here there are no  undefined states in the logic. You know exactly what is described and in what order of priority.

now, we have come to the end of the begin..end block so the synthesizer considers this block as 'closed and it goes back to the if(enable) multiplexer if build the very first.

The next statement says if system_reset ... so we get another multiplexer under control of that signal. If this signal is active, it doesn't matter what came before as instructions: that entire block is cut off by the multiplexer.

So now the synthesizer has a chunk of logic built form multiplexers, input signals and operators such as + and - . This entire 'cloud' of logic is nothing but and,or and not gates. So one huge boolean expression that can be minimized very quickly and efficiently.
The truth table is complete, there are no undefined states in the table because if the scheduling principle.

If you tried to build the table using if-then elseif or switch case statements , there is a risk you have undefined states. in a switch case you can specify a DEFAULT state that enures the undefined states fall back to this state. With if-then,elseif,else statements you have to be careful to cover all possible combinations. Also ,when someone comes back and say : we want preset to take priority over reset you have carefully alter a complex if-then else cluster. with scheduled logic : move that statement one line below so it gets higher priority.

Now, there are going to be people that will tell you ' this is nonsense' , this is not 'how it is done', or 'how can you be sure the compiler works that way' and many other things. Don't listen to them.

The compiler ? there is such a thing as a STANDARD (vhdl, verilog,systemverilog). And this scheduling is PART of all these standards. All the synthesizers work this way ( there really is only one way to translate a list of statements into a cloud of logic and that is the way i described it : inject multiplexers under control of signals, that switches the datapath around. Then minimize that logic into a truth table. This gives the fastest and smallest implementation. All the synthesizers i know (alteray, xilinx, lattice, cypress, Synopsys ) all respect the standard.

As for this 'is nonsense' or this is 'not how it is done': i've worked with silicon for 23 years and did many complex designs, some of which sit in ADSL/VDSL modems and central office equipment , some of which sit in almost any harddisk that was produced in the last 15 years and controls the motors and positions the heads. And that logic was built exactly the way i described it above. Using scheduling.

Learn this principle, and use it to your advantage. You will write more concise code, without undefined states, that is easier to maintain/modify when priorities change.

Block level simulation ? Virtually not needed.
High level (system level), yes.
Timing , yes.
Functionally (does it do what i intend it to do) , no. There is no 'wiggle room' or undefined path.
« Last Edit: March 10, 2020, 01:32:16 pm by free_electron »
Professional Electron Wrangler.
Any comments, or points of view expressed, are my own and not endorsed , induced or compensated by my employer(s).
 
The following users thanked this post: Sal Ammoniac, rstofer

Offline laugensalm

  • Regular Contributor
  • *
  • Posts: 129
  • Country: ch
Re: What HDL to start with
« Reply #38 on: March 10, 2020, 01:33:31 pm »
VHDL is going the way of dodo, just like Basic and Pascal are. No reason to bother with it.

VHDL is hugely popular in the hobbyist/open source circles, that right there is a reason to bother with it. Ultimately though the choice of language is virtually irrelevant, they all have the same capabilities, hardware that can be defined with one can be defined with another.

It's not just popular, it will never disappear in a certain (not just niche) market, where safety and proper functionality coverage is relevant and lazy hacking not an option. And choice of language is not irrelevant when aiming at functional safety or portability, Im afraid.

For the beginner, I would summarize my experiences with HDL as follows:
  • Verilog: Less to write, more 'main stream', but: implicit effects can be a real pain (and things can go seriously wrong in silicon, too). Can encourage a lot of 'lazy coding'
  • VHDL: a lot to write/copy paste, very verbose, strict and picky, but always explicit (unless you use std_logic_arith or other broken libraries)
  • Python/MyHDL: Very nice concept, little code to write, converts to Verilog/VHDL nicely. Has a few sticky bugs, and may appear orphaned and little maintained but in fact has my best 'reusability score'.
  • Python/nmigen: Quite a hack, but 'main stream' on the Python HDL side. Pros: Big IP core library, integration with opensource synthesis advanced

Unfortunately, none of these is a true description language, although some people will keep repeating that to you and point at that 'D' in VHDL. They are all programming languages, trying to describe hardware. That's what makes them problematic with respect to early design rules, so, as mentioned, you might spend a lot of time trying to find out what is synthesizeable into primitives, and how.
And unfortunately, many concepts are broken by design, so let's not go further into niche languages.

If you just want to focus on developing logic and functional testing, you can become very effective using the Python approaches, but you still should be able to read Verilog/VHDL for debugging purposes, like the situation C++ <-> Assembly. You can never trust the tools, but at least some of them are free/open tools. And for synthesis, you can learn a lot with yosys and obtain usable results on various FPGAs, while being able to verify the innards with proven simulation tools.
 

Online nctnico

  • Super Contributor
  • ***
  • Posts: 27694
  • Country: nl
    • NCT Developments
Re: What HDL to start with
« Reply #39 on: March 10, 2020, 01:45:48 pm »
One of the least known, or least understood, (verilog/systemverilog) synthesis rules is this one : logic shall be executed IN THE ORDER IT IS WRITTEN. And most people ( non-asic designers, or software-approach people ) never use this.
And for a good reason. Logic is supposed to be parallel and now suddenly the order of statements starts to matter  :wtf: . Sure the standard has to define what to do in such a case but it doesn't make it a good practise (similar to many obscure & obfusticated things you can do in C). There are so many ways to shoot yourself in the foot with your proposed way of working that people aren't using it. When writing code always make sure someone fresh from school can understand it and make modifications without tearing the whole thing down by introducing subtle errors. Code needs to be as self-explainatory as possible.
« Last Edit: March 10, 2020, 01:57:48 pm by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 15180
  • Country: fr
Re: What HDL to start with
« Reply #40 on: March 10, 2020, 02:13:23 pm »
One of the least known, or least understood, (verilog/systemverilog) synthesis rules is this one : logic shall be executed IN THE ORDER IT IS WRITTEN. And most people ( non-asic designers, or software-approach people ) never use this.
And for a good reason. Logic is supposed to be parallel and now suddenly the order of statements starts to matter  :wtf: .

The order matters when you are re-assigning the same signals in several statements. If not, it doesn't matter.
It also does if you're using variables.

Some people never write code like this - because they think it looks sloppy - and some will make use of this to write more compact code. Your call.
Such as:
Code: [Select]
a <= (others => '0');
(...)
if xxx then
    a <= b;
end if;

In this trivial piece of code, obviously the equivalent would be:
Code: [Select]
if xxx then
    a <= b;
else
    a <= (others => '0');
end if;

In less trivial examples, the savings in terms of code can be substantial. Again it's up to you and/or the rules you have to comply with.
« Last Edit: March 10, 2020, 02:15:35 pm by SiliconWizard »
 

Offline free_electron

  • Super Contributor
  • ***
  • Posts: 8549
  • Country: us
    • SiliconValleyGarage
Re: What HDL to start with
« Reply #41 on: March 10, 2020, 02:15:04 pm »
One of the least known, or least understood, (verilog/systemverilog) synthesis rules is this one : logic shall be executed IN THE ORDER IT IS WRITTEN. And most people ( non-asic designers, or software-approach people ) never use this.
And for a good reason. Logic is supposed to be parallel and now suddenly the order of statements starts to matter  :wtf: . Sure the standard has to define what to do in such a case but it doesn't make it a good practise (similar to many obscure & obfusticated things you can do in C). There are so many ways to shoot yourself in the foot with your proposed way of working that people aren't using it. When writing code always make sure someone fresh from school can understand it and make modifications without tearing the whole thing down by introducing subtle errors. Code needs to be as self-explainatory as possible.
You haven't understood is at all.

Logic IS parallel but there is still an ORDER in which it executes. That is imperative due to the nature of the synthesis process.
One way to create order is by using case and if-then-else clauses. But there is a risk you do not cover all possible cases.

By using the built in order mechanism (scheduling) you avoid all this. Do not treat logic design as code design ! Logic is building truth tables to drive operations. And your truth tables need to be complete or they become 'maybe' and 'sometimes' tables... with unpredictable results. Use the scheduling that is built in the standard and you avoid all these issues. your logic becomes fully deterministic and without unintentional pathways. There is also no endless nesting of if-then-else clauses that becomes unmanageable

Professional Electron Wrangler.
Any comments, or points of view expressed, are my own and not endorsed , induced or compensated by my employer(s).
 

Online nctnico

  • Super Contributor
  • ***
  • Posts: 27694
  • Country: nl
    • NCT Developments
Re: What HDL to start with
« Reply #42 on: March 10, 2020, 02:21:13 pm »
One of the least known, or least understood, (verilog/systemverilog) synthesis rules is this one : logic shall be executed IN THE ORDER IT IS WRITTEN. And most people ( non-asic designers, or software-approach people ) never use this.
And for a good reason. Logic is supposed to be parallel and now suddenly the order of statements starts to matter  :wtf: . Sure the standard has to define what to do in such a case but it doesn't make it a good practise (similar to many obscure & obfusticated things you can do in C). There are so many ways to shoot yourself in the foot with your proposed way of working that people aren't using it. When writing code always make sure someone fresh from school can understand it and make modifications without tearing the whole thing down by introducing subtle errors. Code needs to be as self-explainatory as possible.
You haven't understood is at all.

I understand it perfectly but it results in code which does something else than it suggests at first sight. That is a big problem to get less experienced people to work on a project in a productive way. The problem is not the code but the logistics of keeping code maintainable by as many people as possible. Unless ofcourse you want to maintain your own code until the end of time. And what if you look at your own code after having not used HDL for a long time? Or switched to an HDL which works differently? You'll be in trouble for sure!
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Online nctnico

  • Super Contributor
  • ***
  • Posts: 27694
  • Country: nl
    • NCT Developments
Re: What HDL to start with
« Reply #43 on: March 10, 2020, 02:29:11 pm »
In this trivial piece of code, obviously the equivalent would be:
Code: [Select]
if xxx then
    a <= b;
else
    a <= (others => '0');
end if;

In less trivial examples, the savings in terms of code can be substantial.
I always use the way from the snippet because it shows exactly what is supposed to happen and keeps the places where (in this case) a is modified in well defined areas. Aks yourself what happens if you merge the code and a line gets shuffled around by the version management system? Or someone shuffles a few lines around? And sure in more complex logic it may require a bit more thinking on how to organise your code. At some point a case statement may be better suited compared to a whole bunch of nested ifs. Maybe use a state variable instead of several seperate signals. Or create a function. IOW: the typical trade-offs when writing software in any programming language to create simple code and improve readability.
« Last Edit: March 10, 2020, 02:31:57 pm by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 15180
  • Country: fr
Re: What HDL to start with
« Reply #44 on: March 10, 2020, 02:34:46 pm »
In this trivial piece of code, obviously the equivalent would be:
Code: [Select]
if xxx then
    a <= b;
else
    a <= (others => '0');
end if;

In less trivial examples, the savings in terms of code can be substantial.
I always use the way from the snippet because it shows exactly what is supposed to happen and keeps the places where (in this case) a is modified in well defined areas. Aks yourself what happens if you merge the code and a line gets shuffled around by the version management system? Or someone shuffles a few lines around? And sure in more complex logic it may require a bit more thinking on how to organise your code. At some point a case statement may be better suited compared to a whole bunch of nested ifs. Maybe use a state variable instead of several seperate signals. Or create a function.

There could be counter-examples where the first version would actually lead to less bugs in case of code modification: you have an explicit "default" value for the signal (all zeroes), and only assign it to something else in specific cases... so that doesn't necessarily introduce more bugs than the second, and could in some cases introduce potentially fewer.

As I said, some people will make it a rule not to do this - you seem to be part of them - and it's fine.

But knowing the language rules is still an important thing, and I think you should know them perfectly even when you choose not to use some constructs.

As to variables, they should essentially be seen as placeholders, and not at all as variables in the software programming sense. Once you grasp that, they become trivial to use, and are handy to avoid unncessary code duplication.
« Last Edit: March 10, 2020, 02:38:07 pm by SiliconWizard »
 

Offline OwO

  • Super Contributor
  • ***
  • Posts: 1250
  • Country: cn
  • RF Engineer.
Re: What HDL to start with
« Reply #45 on: March 10, 2020, 03:09:40 pm »
My way would be:
Code: [Select]
a <= b when xxx else
        (others=>'0');

The only complaint I have is that VHDL doesn't have a mux construct like:
Quote
out <= mux sel begin
         a+b when "00" else
         a-b when "01" else
         a;
and would error out if not all cases are covered.

I *really* do not like the concept of conditionals (if/else) in hardware because it is completely unphysical; you can not swap hardware in and out depending on a condition; the hardware is always there. You can only use a mux to select which output to use, so I'd like this to be explicit.

I think the overall structure of the hardware is something that must be explicitly spelled out; for example, an adder that supports dynamic add/subtract selection is not the same as one adder and one subtractor with a mux to select between the two. Although VHDL and verilog do not allow you to distinguish the two, the synthesizer generally does the right thing if the add/subtract selection is by itself (res <= a+b when sub='0' else a-b;). In my experience vivado will generate suboptimal logic if you have it as part of a longer conditional with more cases.
« Last Edit: March 10, 2020, 03:18:33 pm by OwO »
Email: OwOwOwOwO123@outlook.com
 
The following users thanked this post: nctnico

Online asmi

  • Super Contributor
  • ***
  • Posts: 2778
  • Country: ca
Re: What HDL to start with
« Reply #46 on: March 10, 2020, 03:22:29 pm »
There could be counter-examples where the first version would actually lead to less bugs in case of code modification: you have an explicit "default" value for the signal (all zeroes), and only assign it to something else in specific cases... so that doesn't necessarily introduce more bugs than the second, and could in some cases introduce potentially fewer.
I actually prefer this way because this way it is guaranteed to be a default option, while in complex control structures what may seem like a default branch may not actually be that. Good news is at least Vivado synthesis issues a warning each time you have not covered all possible cases. Using SV's modifiers (priority/unique if/case, always_ff/_comb/_latch) helps to convey your intent to synthesizer so that it can check if assumptions you make are actually valid and again will issue a warning is something isn't right.

As to variables, they should essentially be seen as placeholders, and not at all as variables in the software programming sense. Once you grasp that, they become trivial to use, and are handy to avoid unncessary code duplication.
In my experience, the hardest concept of HDL to grasp is a wire. It's somewhat similar to pointer or reference in high-level programming languages, but it's more powerful in a sense that it can "point" to different places depending on some conditions. To those who understand wires it's all very obvious, but it's kind of hard to explain to someone who doesn't understand it yet. I had my own share of issues in code because I didn't fully understand this concept.

Online nctnico

  • Super Contributor
  • ***
  • Posts: 27694
  • Country: nl
    • NCT Developments
Re: What HDL to start with
« Reply #47 on: March 10, 2020, 04:38:18 pm »
Just some quick food for thought on defaults: on the upside the value is always defined (likely 0) but the downside is that it limits the logic optimisation and this can result in needing a larger amount of logic than strictly necessary.

Take a register in a peripheral for example. Does it matter if you read back 0 in unused bits or can they be an unspecified value?
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline free_electron

  • Super Contributor
  • ***
  • Posts: 8549
  • Country: us
    • SiliconValleyGarage
Re: What HDL to start with
« Reply #48 on: March 10, 2020, 05:36:00 pm »
Just some quick food for thought on defaults: on the upside the value is always defined (likely 0) but the downside is that it limits the logic optimisation and this can result in needing a larger amount of logic than strictly necessary.

Take a register in a peripheral for example. Does it matter if you read back 0 in unused bits or can they be an unspecified value?

They should be hard set to 0 or 1, not left with 'garbage' depending on which way the wind blows.

Why ? let's assume the 'other guy' that has to read that register (the programmer writing some C code on the cpu that will access this register) has cast this variable as an INT.
If that MSB randomly flips to 1 you just read a NEGATIVE number from the register ... Let's say this is an ADC with 10 bits mapped into a 16 bit register . You are going to create massive issues down the line. Especially if this ADC is signed ! ( you would have to map bit 10 onto bit 15 and the other would contain 'garbage' .. good luck filtering that in software. you now have to dick around with a bunch of data sanitizing because the logic designer was too lazy to lock those bits.  If i were to encounter a chip that does shit like that i would fire the engineer on the spot !

There is no such thing as 'undefined' bits. It does not cost additional logic to return zeroes (or ones) for unused bits. That is a misconception ! logic is not generated out of clouds of and,or,not gates. It is generated out of LUT's : look-up-tables. Basically roms. Whether you use them or not : it consumes the same amount of LUTS. So have a 'Default' statement. It populates all undefined states with whatever you specified , as opposed to leave it random. It is only a bit more work for the synthesizer to fill the table.

During minimisation, the flipflops that never alter state ( yes, the synthesiser can spot that ) are not even instantiated. They are replaced with a hard zero or hard one.

The reason for using LUT's and not random cloud logic is that , for a given size of LUT the propagation time is a constant. It does not matter what line in the rom you select. the time from change to output is a constant. With random clouds of logic , depending on the state, the chain may be shorter or longer. this leads to race conditions and immense trouble doing timing analysis and timing closure. A rom based lut does not have this issue. But,but,but having such a decoder takes up silicon space too. All those and/or/gates to make a 4 to 16 decoder to select the table... wrong ! in reality such decoders are not made using 'logic' gates , they are made using selectors ( basically one transistor  ).

two to 4 decoder using selectors (SEE IMAGE)

for every additional input you need 1 inverter and a set of p-mos (or PNP's). the outputs of the selectors are used to 'power' the mosfets in the rom. they drive (for zero) , or do not drive (for 1) the gate of the selected rows. so every rom cell is also a single transistor. in an fpga this cell is loadable by precharging the gate during loading of the bitmap. In an asic this stuff becomes a diode matrix.

See where this is headed ? For many things on silicon you have to let go of this notion of and,or,not and stuff. it's all selectors and diode matrixes. It is much faster, much smaller, and timing deterministic. the speed of selection is purely given by how fast you can turn on that transistor ( or switch it off ). the only true Delay is the switch delay of the selector + the delay in the inverter ( which you have one per control line ) so this entire hoopla , no matter how many inputs, has a propagation delay of maximum two transistor delays.

you can chain hundreds of mosfets if you want.

Same way many flipflops are actually a chain of inverters. They simply dope the channel of the mosfets in the second inverter to be very weak (relatively high-ohmic) so it can be 'overdriven'. need a clock ? that's a pass transistor cutting off the input.
a multiplexer ? that's an n-p pair.
« Last Edit: March 10, 2020, 06:02:09 pm by free_electron »
Professional Electron Wrangler.
Any comments, or points of view expressed, are my own and not endorsed , induced or compensated by my employer(s).
 

Online nctnico

  • Super Contributor
  • ***
  • Posts: 27694
  • Country: nl
    • NCT Developments
Re: What HDL to start with
« Reply #49 on: March 10, 2020, 05:43:32 pm »
But did it occur to you that having a default may need to use more inputs than a LUT has and therefore can introduce extra logic? In the end the default condition is based on a combination of inputs and the relevant output states depend on a combination of inputs. Together this can result in the output depending on more inputs than strictly necessary. And LUTs have a limited amount of inputs so the less inputs an output relies on, the less LUTs need to be cascaded.

But as I wrote: having defaults is a situation specific trade-off.

Regarding your ADC example: in such a case (2's complement data out) you'd left align the result and leave the bottom bits undefined. Otherwise it won't even work because you have to extend the sign bit to the unused bits to get the right result. BTW... just checked an NXP datasheet for an LPC1700 microcontroller: unused (bottom) ADC data bits are undefined.
« Last Edit: March 10, 2020, 06:13:21 pm by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf