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

0 Members and 1 Guest are viewing this topic.

Offline free_electron

  • Super Contributor
  • ***
  • Posts: 8550
  • Country: us
    • SiliconValleyGarage
Re: What HDL to start with
« Reply #50 on: March 10, 2020, 06:10:16 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 ADC data bits are undefined.
you were too fast. i was writing up more info. Lut's don't work the way you think they work. it does not cost logic in terms of 'silicon space' for the decoder, nor 'propagation delay' if you have more control signals.
and yes you do need to do a sign extention by stuffing the unused bits with '1'

as for undefined in nxp : i wouldn't touch those with a 10 mile long pole. so how do they handle signed values if they have undefined bits ? i guess their devices are so poor they can't even do signed a/d.

this kind of sloppyness leads to extremely difficult to debug issues. Lock down stuff that is unused. There should be no 'mystery states' in a design. People will get killed.

Go read up about the people that were radiated to death by a cancer treatment machine because of sloppy coding int he control logic. the Therac-25 incident.. Caused by 'undefined states' in the control logic that allowed the machine to radiate patient with max dose . (anything that was not defined yielded 'max dosage' )

it's the same concept as in writing code: initialize your variables. you do not know what that memory location was used for, before.
« Last Edit: March 10, 2020, 06:18:04 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: ralphrmartin, coldfiremc

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 27881
  • Country: nl
    • NCT Developments
Re: What HDL to start with
« Reply #51 on: March 10, 2020, 06:30:57 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.

you were too fast. i was writing up more info. Lut's don't work the way you think they work. it does not cost logic in terms of 'silicon space' for the decoder, nor 'propagation delay' if you have more control signals.
Ofcourse it does! If you have 7 input signals then you'll need to cascade two 4 or 5 input LUTs to get the result. This will cost extra logic, routing resources and adds delay to the path. There is no magic way around that.
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline free_electron

  • Super Contributor
  • ***
  • Posts: 8550
  • Country: us
    • SiliconValleyGarage
Re: What HDL to start with
« Reply #52 on: March 10, 2020, 07:22:43 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.

you were too fast. i was writing up more info. Lut's don't work the way you think they work. it does not cost logic in terms of 'silicon space' for the decoder, nor 'propagation delay' if you have more control signals.
Ofcourse it does! If you have 7 input signals then you'll need to cascade two 4 or 5 input LUTs to get the result. This will cost extra logic, routing resources and adds delay to the path. There is no magic way around that.
Yes, you will be consuming one additional lut. So what ? You will be consuming that LUT whether it is initialized or not.  The interconnect is already part of the raceways in the fpga fabric , so that doesn't cost anything , nor does it add delay (like i said : switching and decoding in an FPGA , of which the raceways are part, is delayless between in and out. There is a setup time , but once the connection is made there is no delay as it is simply the drain-source channel) . A wider lut does not add setup delay as the delay is purely based on transistor switching time , which is a constant in a lut, irrespective of what combination. you have one inverter to pass and one selector gate so two transistor switch delays. Doesn't matter if it is one lut , two chained luts (wider inputs). it is only important for cascaded ( more outputs) as there you need subswitching and need to put luts behind luts, but even then you incur virtually nothing as the synthesizer use one lut to do a global enable on the cascaded ones. So you get the first one for free. You only get hit by 2 more transistor delays.
And again, it doesn't matter if you hard lock the states or 'don;t care'. the cells are there anyway. it's not like you can erase them. if a lut is half used it is spent. you may as well use it completely by stuffing it.



in short : lock down the states !. Just like you initialize variables in a program. If you can't be bothered to do initialization you are an idiot and should take up a different job , like painting the lines for parking spaces.
Professional Electron Wrangler.
Any comments, or points of view expressed, are my own and not endorsed , induced or compensated by my employer(s).
 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 27881
  • Country: nl
    • NCT Developments
Re: What HDL to start with
« Reply #53 on: March 10, 2020, 07:37:00 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.

you were too fast. i was writing up more info. Lut's don't work the way you think they work. it does not cost logic in terms of 'silicon space' for the decoder, nor 'propagation delay' if you have more control signals.
Ofcourse it does! If you have 7 input signals then you'll need to cascade two 4 or 5 input LUTs to get the result. This will cost extra logic, routing resources and adds delay to the path. There is no magic way around that.
Yes, you will be consuming one additional lut. So what ? You will be consuming that LUT whether it is initialized or not. 
The whole point is to avoid needing 7 input signals if possible. If you avoid needing that extra LUT by not having a default you'll need less FPGA resources, have shorter delays and thus have a better chance on meeting timing / fitting the design in an FPGA. Whether you need initialised values or not is a functional design decision. Sometimes it will matter, sometimes not and sometimes you'll have to compromise in order to meet timing requirements. There is no general rule (whether you like it or not). This also circles back to code style in general. If you have a whole flurry of nested ifs (which is poor coding style because the purpose is lost quickly) then it is very likely a case / state machine approach is better suited to have better code clarity. A case / statemachine approach will also allow the synthesizer to choose between various encodings (number or one-hot) in order to get to the most optimal result. In the end the resulting hardware implementation may even be better compared to the nested if statements.

Also in most (digital) semiconductor devices you'll see that unused bits have undefined values. So appearantly your statement that default values come for free is false.

But this is getting wildly off-topic.
« Last Edit: March 10, 2020, 09:28:22 pm by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline mrflibble

  • Super Contributor
  • ***
  • Posts: 2051
  • Country: nl
Re: What HDL to start with
« Reply #54 on: March 10, 2020, 11:48:53 pm »
I'll just quote it in full so we don't get any of that quoted-out-of-context nonsense...
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.

you were too fast. i was writing up more info. Lut's don't work the way you think they work. it does not cost logic in terms of 'silicon space' for the decoder, nor 'propagation delay' if you have more control signals.
Ofcourse it does! If you have 7 input signals then you'll need to cascade two 4 or 5 input LUTs to get the result. This will cost extra logic, routing resources and adds delay to the path. There is no magic way around that.
Yes, you will be consuming one additional lut. So what ? You will be consuming that LUT whether it is initialized or not. 
The whole point is to avoid needing 7 input signals if possible. If you avoid needing that extra LUT by not having a default you'll need less FPGA resources, have shorter delays and thus have a better chance on meeting timing / fitting the design in an FPGA. Whether you need initialised values or not is a functional design decision. Sometimes it will matter, sometimes not and sometimes you'll have to compromise in order to meet timing requirements. There is no general rule (whether you like it or not). This also circles back to code style in general. If you have a whole flurry of nested ifs (which is poor coding style because the purpose is lost quickly) then it is very likely a case / state machine approach is better suited to have better code clarity. A case / statemachine approach will also allow the synthesizer to choose between various encodings (number or one-hot) in order to get to the most optimal result. In the end the resulting hardware implementation may even be better compared to the nested if statements.

Also in most (digital) semiconductor devices you'll see that unused bits have undefined values. So appearantly your statement that default values come for free is false.

But this is getting wildly off-topic.

*edit*

Okay, before I write waay too much based something that could be a misunderstanding... Lets just verify that what you mean is what I think you mean. Because, that which I think you mean is ... uhm, "not entirely accurate" would be the polite way of putting it. Less subtle would be "that is a load of shit, and it can be mathematically proven that it is a load of shit". It is in fact such a load of shit, that I honestly think that I must have misunderstood, because how the fuck can someone come to that conclusion. But then again ... three posts all of which are consistent with "that which is meant" is just not true. And these same three posts are not consistent with "that which is actually happening in real actual synthesizers made by real actual companies selling real actual FPGAs".

What I think you mean is:

blackbox/module/whatever with 7 inputs. As per discussion one of the inputs is a default value. The other 6 signals are truly variable, could be anything.

So 7 input lines, one of those is always the exact same boring value always always always. And the other 6 could be anything. You (as in ntcnico you) are free to choose any random input sequence for those 6 variable input to fuck up my example. For now I'll just keep it as follows: those 6 inputs are the 6 outputs of another module, they are nice and registered, boring old flip-flops, clocked with positive clock edge. Lets say they are the output of some random generator, so I make no assumptions about those 6 input bits. And about that 7th default value input we agree that it is always 1. Or always 0. I don't care, as long as it is static, you are free to pick which one in order to fuck up my example.

The output of our blackbox is some function that depends on ALL of the input bits, so no assumptions about that on my part. We could make it the bit reduction XOR operation for all I care. Again, you are free to pick something else to fuck up my example. So our blackbox module has 7 bits of input, it takes the bit reduce xor of those, and voila, that is the output. And we register it for good measure.

What you seem to be saying is that in that sort of situation the synthesizer will need more than 1 LUT6 to get the job done? Do understand that correctly? Because I think I know for a fact that that is: rubbish, not true, false, how the hell can you even think that, take your pick. But as said, that is just so ... wrong that I have a hard time believing that this is what you mean. In which case, could you clarify?

PS: Damnit, too long anyways. ;)
 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 27881
  • Country: nl
    • NCT Developments
Re: What HDL to start with
« Reply #55 on: March 11, 2020, 12:13:59 am »
No; you misunderstood.
Say you have 10 inputs in total feeding a complex piece of logic. If you create a default value you need 7 out of those 10 inputs to create an output (single bit). If you don't have a default value you only need 4 inputs to create the output value (*).In the latter case one typical LUT would suffice to create the output instead of two. 

Think about the good old Karnaugh diagrams: the more 'don't cares' you have the less inputs and/or logic are needed to generate the output. Having a default means less 'don't cares' in the Karnaugh diagram and thus possibly needing more inputs and/or logic. I'm not saying you'll always be able save resources but in order to reduce the amount of logic you will want to optimise your code to make outputs depend on the least amount of inputs. So you have to consider the benefits of having a default value versus the extra amount of logic it may create.

* Don't wonder about the how and why you get from needing 7 inputs or 4; it is not important. These are just numbers to show that in an FPGA you work with LUTs (building blocks) which have a particular size and that you need extra LUTs if you exceed the capacity of one LUT.
« Last Edit: March 11, 2020, 12:27:37 am by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline mrflibble

  • Super Contributor
  • ***
  • Posts: 2051
  • Country: nl
Re: What HDL to start with
« Reply #56 on: March 11, 2020, 03:25:33 am »
Had a longer post here, but on reflection I deleted it. The synthesizer will optimize what it will optimize, regardless of what we write about it. :)
« Last Edit: March 11, 2020, 04:38:03 am by mrflibble »
 
The following users thanked this post: Sal Ammoniac, Bassman59, coldfiremc

Offline coldfiremc

  • Regular Contributor
  • *
  • Posts: 75
  • Country: cl
Re: What HDL to start with
« Reply #57 on: March 11, 2020, 05:39:57 am »
Had a longer post here, but on reflection I deleted it. The synthesizer will optimize what it will optimize, regardless of what we write about it. :)
And that's very important. How inference will work in our description and how much time the analyzer will compile our simulations. RTFM is the best advice here. I think, despite not always generates the most "economical" circuit, to wrap any IP or explicit reference to internal blocks into separate entities or files. That probably will make the design a little more portable.
 
The following users thanked this post: rstofer

Offline james_s

  • Super Contributor
  • ***
  • Posts: 21611
  • Country: us
Re: What HDL to start with
« Reply #58 on: March 11, 2020, 05:59:34 am »
I think this is all getting a little out of hand. The OP asked what HDL to start with, IMHO they're a LONG way from needing to worry about the nuances and optimizations.
 
The following users thanked this post: nctnico, BrianHG

Offline emece67

  • Frequent Contributor
  • **
  • !
  • Posts: 614
  • Country: 00
Re: What HDL to start with
« Reply #59 on: March 11, 2020, 03:46:54 pm »
.
« Last Edit: August 19, 2022, 03:46:46 pm by emece67 »
 
The following users thanked this post: Bassman59, coldfiremc

Offline ale500

  • Frequent Contributor
  • **
  • Posts: 415
Re: What HDL to start with
« Reply #60 on: March 30, 2020, 10:01:17 am »
Quote
In fact this is not only a V/SV feature, but also a VHDL one. The process/always semantics state that the statements inside them are processed (or modeled, or executed, or simulated, if you prefer) sequentially (*) and that the signal assignments found take effect not when found, but when the end of the process/always block is reached. Not only that, but such semantics also state that, if during processing of the statements, there were various assignments to the same signal, only the last one found has significance, other assignments are ignored. Obviously, such semantics are quite different to that of software.

It builds a priority encoded logic sequence. It can be written explicitly too.
 

Offline Bassman59

  • Super Contributor
  • ***
  • Posts: 2501
  • Country: us
  • Yes, I do this for a living
Re: What HDL to start with
« Reply #61 on: March 30, 2020, 08:25:13 pm »
Quote
In fact this is not only a V/SV feature, but also a VHDL one. The process/always semantics state that the statements inside them are processed (or modeled, or executed, or simulated, if you prefer) sequentially (*) and that the signal assignments found take effect not when found, but when the end of the process/always block is reached. Not only that, but such semantics also state that, if during processing of the statements, there were various assignments to the same signal, only the last one found has significance, other assignments are ignored. Obviously, such semantics are quite different to that of software.

It builds a priority encoded logic sequence. It can be written explicitly too.

Indeed it does, and indeed it can. And in general I prefer to write explicit code and not make the future reader (including myself!) guess at what I was doing.

But in some recent designs I've used the following paradigm. One use is for a sensor readout sequencer, where my state machine has a bunch of defined states, but the time spent in each state is variable. I took advantage of the "last assignment wins" feature of our HDLs to make the code more readable. So a simple example.

Code: [Select]
architecture foobar of bletch is
    signal duration : natural range 0 to LONGEST; -- this counts time in each state
    type state_t is (
        S_INIT,   -- wait for "go"
        S_S1,      -- state 1
        S_S2,      -- state 2
        S_S3,      -- state 3
        S_S4);     -- state 4
    signal state : state_t;
begin
    Machine : process (clk, rst) is
        if rst = '1' then
            duration <= 0;
            state <= S_INIT;
        elsif rising_edge(clk) then

            -- Time spent in each state:
            StateTimer : if duration > 0 then
                duration <= duration - 1;
            end if StateTimer;

            Decoder : case state is
                when S_INIT =>
                    if go = '1' then
                         duration <= s1_duration;
                         state <= S_S1;
                    end if;

                 when S_S1 =>
                     if duration = 0 then
                         duration <= s2_duration;
                         state <= S_S2;
                     end if;

                 when S_S2 =>
                     if duration = 0 then
                         duration <= s3_duration;
                         state <= S_S3;
                     end if;

                 when S_S3 =>
                     if duration = 0 then
                         duration <= s3_duration;
                         state <= S_S4;
                     end if;

                 when S_S4 =>
                     if duration = 0 then
                         duration <= s4_duration;
                         state <= S_INIT;
                     end if;
            end case Decoder;

        end if;
    end process Machine;
end architecture foobar;

It's quite simple. The counter always counts down to zero and then idles.

A mux is built for the counter load. Each load happens for only one clock. When we are in one of the four loading states, the load happens only when the counter is zero.

What's neat about this is that the duration of each state can be stored in registers (which themselves have initializers which are stored in nonvolatile memory and fetched at startup) so you can tune the sequencer as needed.

This isn't a priority-encoded sequence in the usual sense (if this then that elsif this2 then that2 elsif this3 then that3 end if).

Is this "efficient?" I don't know. What matters is if it meets my actual timing constraints. And its operation is immediately apparent to the reader.

In each state we have the compare-to-zero for the duration. For long durations that comparison, as well as the timer itself, might require pipelining, so you might register the comparison:

Code: [Select]
            -- Time spent in each state:
            StateTimer : if duration > 0 then
                duration <= duration - 1;
            end if StateTimer;

            -- pipeline comparison for speed reasons.
            -- This could have been written with the same paradigm as above!
            if duration = 1 then
                durationIsZero <= '1';
            else
                durationIsZero <= '0';
            end if;

            -- and in each state we use the pipelined compare
                when S_S1 =>
                    if durationIsZero = '1' then
                        duration <= s2_duration;
                        state <= S_S2;
                    end if;

The pipelined-compare flag means that the state machine decoder looks at only two bits to determine when to update the timer and advance to the next state. Those bits are the one-hot state bit and the compare-true flag. It's "better" than doing, say, a 16-bit compare to zero in each state.

Your mileage may vary. Write your code for clarity first, then optimize only when necessary.
 

Offline free_electron

  • Super Contributor
  • ***
  • Posts: 8550
  • Country: us
    • SiliconValleyGarage
Re: What HDL to start with
« Reply #62 on: March 30, 2020, 11:04:53 pm »
to make such constructions more readable i typically define something like:
'define nextstate duration <= duration - 1

so i can write
`nextstate;

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

Offline Bassman59

  • Super Contributor
  • ***
  • Posts: 2501
  • Country: us
  • Yes, I do this for a living
Re: What HDL to start with
« Reply #63 on: March 30, 2020, 11:30:19 pm »
to make such constructions more readable i typically define something like:
'define nextstate duration <= duration - 1

so i can write
`nextstate;

That's supported only with Verilog, not VHDL.

But I wonder -- if each state has its own timer, will the synthesizer be smart enough to optimize them into one, or will you end up with one counter per state that has that `define?
 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 27881
  • Country: nl
    • NCT Developments
Re: What HDL to start with
« Reply #64 on: March 31, 2020, 12:29:52 am »
Quote
In fact this is not only a V/SV feature, but also a VHDL one. The process/always semantics state that the statements inside them are processed (or modeled, or executed, or simulated, if you prefer) sequentially (*) and that the signal assignments found take effect not when found, but when the end of the process/always block is reached. Not only that, but such semantics also state that, if during processing of the statements, there were various assignments to the same signal, only the last one found has significance, other assignments are ignored. Obviously, such semantics are quite different to that of software.

It builds a priority encoded logic sequence. It can be written explicitly too.

Indeed it does, and indeed it can. And in general I prefer to write explicit code and not make the future reader (including myself!) guess at what I was doing.

But in some recent designs I've used the following paradigm. One use is for a sensor readout sequencer, where my state machine has a bunch of defined states, but the time spent in each state is variable. I took advantage of the "last assignment wins" feature of our HDLs to make the code more readable. So a simple example.
You can change this by putting the case / when in an else clause in the 'if  if duration > 0' (or the if durationIsZero) to make your examples unambiguous. However I get the feeling these are just small examples. Just like in any programming language a very long (nested) if or case statement is an indication a function may be better suited for the job.
« Last Edit: March 31, 2020, 12:35:01 am by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline Bassman59

  • Super Contributor
  • ***
  • Posts: 2501
  • Country: us
  • Yes, I do this for a living
Re: What HDL to start with
« Reply #65 on: March 31, 2020, 04:59:17 am »
Quote
In fact this is not only a V/SV feature, but also a VHDL one. The process/always semantics state that the statements inside them are processed (or modeled, or executed, or simulated, if you prefer) sequentially (*) and that the signal assignments found take effect not when found, but when the end of the process/always block is reached. Not only that, but such semantics also state that, if during processing of the statements, there were various assignments to the same signal, only the last one found has significance, other assignments are ignored. Obviously, such semantics are quite different to that of software.

It builds a priority encoded logic sequence. It can be written explicitly too.

Indeed it does, and indeed it can. And in general I prefer to write explicit code and not make the future reader (including myself!) guess at what I was doing.

But in some recent designs I've used the following paradigm. One use is for a sensor readout sequencer, where my state machine has a bunch of defined states, but the time spent in each state is variable. I took advantage of the "last assignment wins" feature of our HDLs to make the code more readable. So a simple example.
You can change this by putting the case / when in an else clause in the 'if  if duration > 0' (or the if durationIsZero) to make your examples unambiguous. However I get the feeling these are just small examples. Just like in any programming language a very long (nested) if or case statement is an indication a function may be better suited for the job.

If you have any ideas on how to reduce a parser that looks at an 8-bit command token and does, well, one of 256 disparate actions as a result, I'm all ears. In the current project, I have such a beast.

Now I suppose it could be made into a ROM lookup table, but then there's the questions of readability and maintainability.

For the sensor-controller/sequencer state-machine example, the number of states is small. And, in fact, the original idea was to use a ROM lookup table, sequenced by a state counter and embedded in the ROM are the duration of each state and branch control as well as machine outputs. Basically it was a 2901/2910 bit-slice processor without the ALU! Or the Apple ][ floppy-disc controller. (Those ancients, always stealing our ideas.) The ROM was a dual-port RAM, so the "program" could be changed at will. (The program would be fetched at startup from some nonvolatile memory.)

I don't really think that there's a "best" way to do this. Do it however it makes sense to you. Don't be clever; that's the synthesizer's job. Just make sure you can understand it in a few months. If it meets timing and area constraints, you're done.
 

Offline free_electron

  • Super Contributor
  • ***
  • Posts: 8550
  • Country: us
    • SiliconValleyGarage
Re: What HDL to start with
« Reply #66 on: March 31, 2020, 03:36:58 pm »
to make such constructions more readable i typically define something like:
'define nextstate duration <= duration - 1

so i can write
`nextstate;

That's supported only with Verilog, not VHDL.


But I wonder -- if each state has its own timer, will the synthesizer be smart enough to optimize them into one, or will you end up with one counter per state that has that `define?

don't tell me vhdl does not have something like a 'define' or macro capability. One more reason not to use that sadomasochistic horrorshow of a language ...

For delays i create macros that would load a value on a counter

`define after system_ticks[15:0] <=
`define goto if (system_ticks==0) state <=
`define goto_next state <= state +1
`go (system_ticks ==0)
...

always@(posedge clk) begin

// note that this tick counter here needs to be ABOVE the state machine so we can override the counter value
if (tick) begin
     system_ticks <=system_ticks -1;
     if (system_ticks ==0) system_ticks <=0;
  end
end

select case state
    case 1
     if `go begin   // unrolls to if (system_ticks==0)  begin
        `after 1000;        // unrolls to:  system_ticks[15:0] <= 1000;
        `goto `some_state;  // unrolls to :  if (system_ticks==0) state <= `some_state;
               // or `goto_next;
     end
   case 2
      if `go begin
        ....
     end

keep in mind that the 'after' only executes once the state has transistioned. essentially you are telling the system : do this bunch of work , go state <x> , THEN wait for this time

you can play tricks : if you omit the 'go test you can chain states that are 'timerless'. to resynchronize a process you simply go back to a state that has a 'go statement.

Let's say you have a machine that needs to fire every 1000 system ticks. That means you have 1000 ticks to execute the machine. in that case you test for 'go only at the last state of the machine. the machine will execute and then halt until the counter has zeroed.

I had multiple such 'machines' when i was working on harddisks. When the platter passes index i would fire of the main machine and load the length of 1 revolution in the counter ( actually a little bit less , so i could end up in the state that checks for the index pulse to pulse and resynchronize the machine ). Depending on track i would load another machine with the length of a sector ( again a bit smaller so i would end up in the state that is responsible for checking sector transition )

This automatically gave me 'time slots' that were locked on sectors , irrespective of drive speed or sector size. i knew up front how many time slots were available and could do things nicely in lockstep with a spinning motor. during spinup or spindown the numbers would change (speed changes ) or when hopping from inner to outer tracks the sectors per track would change. all i needed to do was alter the time between a system 'tick' the machine would always have the correct number of 'subdivisions per sector, irrespective of motor speed or number of sectors per track. if i knew i needed 10 states per sector passing i could easily program that. the 'tick' was generated by a programmable divider from a master clock that was running much faster ( basically a fractional_n synthesizer)

i could have nested processes by using mulitple of such timer blocks. every process was attached to its own timer block and all were driven by the same master tick. I could have processes wait for their own 'tick' to expire' or wait until another process synced up.
Professional Electron Wrangler.
Any comments, or points of view expressed, are my own and not endorsed , induced or compensated by my employer(s).
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9932
  • Country: us
Re: What HDL to start with
« Reply #67 on: March 31, 2020, 04:15:00 pm »
don't tell me vhdl does not have something like a 'define' or macro capability. One more reason not to use that sadomasochistic horrorshow of a language ...

Fortunately, the designers of VHDL omitted the macro capability in favor of clean reading code.  Somehow, VHDL coders have been getting along without macros for a very long time.

VHDL does have procedures and functions and these can be defined in a package and used throughout a project.  'Generic' parameters also help create compile time configuration of procedures and functions.

 
The following users thanked this post: nctnico, Bassman59

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 15284
  • Country: fr
Re: What HDL to start with
« Reply #68 on: March 31, 2020, 04:27:27 pm »
don't tell me vhdl does not have something like a 'define' or macro capability. One more reason not to use that sadomasochistic horrorshow of a language ...

Fortunately, the designers of VHDL omitted the macro capability in favor of clean reading code.  Somehow, VHDL coders have been getting along without macros for a very long time.

VHDL does have procedures and functions and these can be defined in a package and used throughout a project.  'Generic' parameters also help create compile time configuration of procedures and functions.

Yep, functions and procedures in VHDL can do EVERYTHING a macro can do in Verilog, and much more.
 

Offline Bassman59

  • Super Contributor
  • ***
  • Posts: 2501
  • Country: us
  • Yes, I do this for a living
Re: What HDL to start with
« Reply #69 on: March 31, 2020, 06:08:55 pm »
don't tell me vhdl does not have something like a 'define' or macro capability. One more reason not to use that sadomasochistic horrorshow of a language ...

Fortunately, the designers of VHDL omitted the macro capability in favor of clean reading code.  Somehow, VHDL coders have been getting along without macros for a very long time.

VHDL does have procedures and functions and these can be defined in a package and used throughout a project.  'Generic' parameters also help create compile time configuration of procedures and functions.

Yep, functions and procedures in VHDL can do EVERYTHING a macro can do in Verilog, and much more.

To be fair, in the many years I've been designing with VHDL, not once have I needed a macro. When I did Verilog, I used ` macros for constant things like state names. (Oh, and the use of `define for state machine state definitions in Verilog is inferior to using an enumerated type in VHDL.)

Let's use the example provided.

Code: [Select]
if `go begin   // unrolls to if (system_ticks==0)  begin
        `after 1000;        // unrolls to:  system_ticks[15:0] <= 1000;
        `goto `some_state;  // unrolls to :  if (system_ticks==0) state <= `some_state;
               // or `goto_next;

The first thing I noticed is that you have comments to explain the function of the unrolled code.

Second, I don't see how if `go begin is better than simply writing if (system_ticks == 0) begin.

Third, if I am looking at simulation waveforms, I don't see the macros `go and such. I see the signal names. This means I have to remember the definition of the macro and translate it into what I see on my waveform display or in my simulation messages.

Macros, in this case, are obfuscators.
« Last Edit: March 31, 2020, 06:10:41 pm by Bassman59 »
 

Offline mrflibble

  • Super Contributor
  • ***
  • Posts: 2051
  • Country: nl
Re: What HDL to start with
« Reply #70 on: April 02, 2020, 05:47:35 pm »
Yep, functions and procedures in VHDL can do EVERYTHING a macro can do in Verilog, and much more.
Code: [Select]
typedef enum { Oh, IfOnly, SystemVerilog, Had, Some } SortOfEnumerationDataType;

SortOfEnumerationDataType oh_if_only;

;)
 
The following users thanked this post: Sal Ammoniac

Offline Bassman59

  • Super Contributor
  • ***
  • Posts: 2501
  • Country: us
  • Yes, I do this for a living
Re: What HDL to start with
« Reply #71 on: April 02, 2020, 11:07:45 pm »
Yep, functions and procedures in VHDL can do EVERYTHING a macro can do in Verilog, and much more.
Code: [Select]
typedef enum { Oh, IfOnly, SystemVerilog, Had, Some } SortOfEnumerationDataType;

SortOfEnumerationDataType oh_if_only;

;)

As you note, enumerations are a SystemVerilog thing, so not applicable to regular Verilog users. Of course, VHDL has had enumerated types since, oh, forever.
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 15284
  • Country: fr
Re: What HDL to start with
« Reply #72 on: April 03, 2020, 12:01:28 am »
Yep, functions and procedures in VHDL can do EVERYTHING a macro can do in Verilog, and much more.
Code: [Select]
typedef enum { Oh, IfOnly, SystemVerilog, Had, Some } SortOfEnumerationDataType;

SortOfEnumerationDataType oh_if_only;

;)

As you note, enumerations are a SystemVerilog thing, so not applicable to regular Verilog users. Of course, VHDL has had enumerated types since, oh, forever.

Indeed! And enumerations are not macros either, so I wasn't even sure what the above post was meant to show anyway, and how they would relate with functions and procedures? ::)
 

Offline mrflibble

  • Super Contributor
  • ***
  • Posts: 2051
  • Country: nl
Re: What HDL to start with
« Reply #73 on: April 03, 2020, 12:59:29 am »
Yep, functions and procedures in VHDL can do EVERYTHING a macro can do in Verilog, and much more.
Code: [Select]
typedef enum { Oh, IfOnly, SystemVerilog, Had, Some } SortOfEnumerationDataType;

SortOfEnumerationDataType oh_if_only;

;)

As you note, enumerations are a SystemVerilog thing, so not applicable to regular Verilog users. Of course, VHDL has had enumerated types since, oh, forever.

Indeed! And enumerations are not macros either, so I wasn't even sure what the above post was meant to show anyway, and how they would relate with functions and procedures? ::)

What in the hell?  :wtf:

You know what, you are absolutely right! No idea how I managed to mangle those info tidbits together.  :palm: Best guess ... probably managed to grab the "enumeration vs macro"related bit from Basssman59's post, then read your post containing "yes X and Y can .* macro .*". Then called `BRAINFART . And of course forgot to terminate it with a ; , because that is what dodgy macro definitions are for!

 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 27881
  • Country: nl
    • NCT Developments
Re: What HDL to start with
« Reply #74 on: April 03, 2020, 10:54:58 am »
Indeed! And enumerations are not macros either, so I wasn't even sure what the above post was meant to show anyway, and how they would relate with functions and procedures? ::)
Macro's are somewhat related to enumerations especially if you want to use pre-defined 'values' with a name. There is more to it in VHDL because the synthesizer has some freedom as to what kind of value to assign to each member (think about a statemachine with one-hot encoding).
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