Author Topic: My first FPGA code  (Read 24077 times)

0 Members and 1 Guest are viewing this topic.

Offline lawrence11Topic starter

  • Frequent Contributor
  • **
  • !
  • Posts: 322
  • Country: ca
Re: My first FPGA code
« Reply #125 on: November 27, 2019, 07:20:25 pm »
Quote

One of the best things a newcomer can do is model different blocks, synthesize and review the hardware schematic.  What code results in what hardware?  I have a book on HDL design that spends a lot of time on the different ways to model various blocks.  It's very interesting stuff.

I don't know what anyone would expect from PC <= PC + 1; but it isn't some kind of counter.  No, Vivado will use a full-adder in the feedback path and just add 1.  Now, among the hundreds of options, I suppose there is a way to change that but, by default, Vivado uses an adder.  Somehow I think it is important to know that.  Later on I'll figure out why it's important...

It looks pretty much like Garbage IMHO.
« Last Edit: November 27, 2019, 07:22:58 pm by lawrence11 »
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9921
  • Country: us
Re: My first FPGA code
« Reply #126 on: November 27, 2019, 07:43:07 pm »

One of the best things a newcomer can do is model different blocks, synthesize and review the hardware schematic.  What code results in what hardware?  I have a book on HDL design that spends a lot of time on the different ways to model various blocks.  It's very interesting stuff.

The book from Airiau, Bergé & Olive maybe?

"HDL Chip Design" by Douglas J Smith
 
The following users thanked this post: emece67

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9921
  • Country: us
Re: My first FPGA code
« Reply #127 on: November 27, 2019, 07:45:57 pm »
Quote

One of the best things a newcomer can do is model different blocks, synthesize and review the hardware schematic.  What code results in what hardware?  I have a book on HDL design that spends a lot of time on the different ways to model various blocks.  It's very interesting stuff.

I don't know what anyone would expect from PC <= PC + 1; but it isn't some kind of counter.  No, Vivado will use a full-adder in the feedback path and just add 1.  Now, among the hundreds of options, I suppose there is a way to change that but, by default, Vivado uses an adder.  Somehow I think it is important to know that.  Later on I'll figure out why it's important...

It looks pretty much like Garbage IMHO.

What you have is 3 inputs going to IBUFs and 2 outputs going through OBUFs on the way to pins.  No logic is included and I'm not sure why.  All you have is 3 inputs and 2 outputs connecting to nothing.  Sometimes the schematic 'summarizes' what is below and if you double-click on a block, you can drill down.  I don't know if that is the case here.

I think that some folks liken using an HDL to using a programming language and clearly that is not the case.  It would seem to me that a designer using HDL to model a circuit would first need to be proficient with hardware.  Can the designer, given a warehouse full of every 74xxx gate ever invented, actually fabricate their design in real hardware?  If not, there's a really steep learning curve ahead.  My personal limit for wire-wrapping is around 100 chips.  Beyond that, I lose patience and focus.  100 Medium Scale Integration (MSI) chips like the 7474 Dual-D Flop is only 200 flops.  Not very many when compared to nearly a  million in the FPGAs I use.  The XC7A100T has 101,440 slices with 8 flops each so around 811,520 flops.  I can't even imagine what a similarly sized TTL implementation would look like.

https://www.xilinx.com/support/documentation/data_sheets/ds180_7Series_Overview.pdf  Page 3
« Last Edit: November 27, 2019, 08:00:26 pm by rstofer »
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9921
  • Country: us
Re: My first FPGA code
« Reply #128 on: November 27, 2019, 08:08:08 pm »

It looks pretty much like Garbage IMHO.

Look back at Reply 73 where I gave you a simplified version of your 'parallel' code (except I just tested a single bit for simplicity) and look at the resulting hardware.  It is pretty easy to get from the HDL to the hardware and the hardware makes sense.
 

Offline lawrence11Topic starter

  • Frequent Contributor
  • **
  • !
  • Posts: 322
  • Country: ca
Re: My first FPGA code
« Reply #129 on: November 27, 2019, 08:22:12 pm »
I started with 74HC,C4000 and now 74LVC.

Then I was hesitant to move into uC's tarted with microchip, and from uC's I was hesitant to go into FPGA's.

I already drew the circuit, its a flip flop chain connected in parallel woth comparator modules, wich now get the parallel value from an initial block, but in the real circuit it will be real synchronous parallel data.

Probably it is lost as to what it should.

In any case, I cant babysit some interpretation algorithm in order to get sone sensical data out of it, I prefer extracting the circuit by observing the result, from the simulator.

« Last Edit: November 27, 2019, 08:34:27 pm by lawrence11 »
 

Offline Bassman59

  • Super Contributor
  • ***
  • Posts: 2501
  • Country: us
  • Yes, I do this for a living
Re: My first FPGA code
« Reply #130 on: November 29, 2019, 11:13:46 pm »
I don't know what anyone would expect from PC <= PC + 1; but it isn't some kind of counter.  No, Vivado will use a full-adder in the feedback path and just add 1.  Now, among the hundreds of options, I suppose there is a way to change that but, by default, Vivado uses an adder.  Somehow I think it is important to know that.  Later on I'll figure out why it's important...

A counter is a special case of an adder. :)

A full adder allows you to specify the all of the inputs. A counter doesn't, as it uses the output fed back as one of the inputs, and the increment value (in this case, 1) as the other. My guess is that the logic is the same.

Also consider that your Xilinx device has hard-core adders (math blocks). The synthesizer knows how many exist and may preferentially fit long counters into one. A 16-bit counter implemented with a hard adder should be faster than one built from slices.
 

Offline Bassman59

  • Super Contributor
  • ***
  • Posts: 2501
  • Country: us
  • Yes, I do this for a living
Re: My first FPGA code
« Reply #131 on: November 29, 2019, 11:17:07 pm »
The usual advice here is "don't write two-process state machines (unless you have a really good reason to do so, and even then think about it some more)." Forgetting to assign to each left-hand-side in each state results in latches. The process(all) construct lets you not worry about the sensitivity list but you still have to make sure that you assign everything in every state.

Same caveat here: use such registered-Mealy FSM. But for 2-process ones, the "default values" trick described by rstofer is a safeguard I've used sometimes.

To be honest, the notion of Mealy vs Moore machines is an academic one. I can't remember which one does what, and it honestly doesn't matter. Write the state machine in the manner which makes the most sense for the design.

Quote
Speaking of crutches, what about the VHDL dereference operator (.all, I suppose it is inherited from ADA)?

There are no pointers in VHDL so no need to deference one.
 

Offline Bassman59

  • Super Contributor
  • ***
  • Posts: 2501
  • Country: us
  • Yes, I do this for a living
Re: My first FPGA code
« Reply #132 on: November 29, 2019, 11:18:37 pm »
Verilog:  When in doubt, instantiate everything like a headless chicken.

Even tho its completly unnecessary for the tb instantiation to know what is important since it is defined as wire and testbench has no direct write authority.

Its none of its business whats important is, what it should be doing is concentrating on pin_1 like I asked it to.

Verilog makes assumptions about signals which are not connected. VHDL throws errors at compile time. Which do you think is more helpful for the designer?
 

Offline Bassman59

  • Super Contributor
  • ***
  • Posts: 2501
  • Country: us
  • Yes, I do this for a living
Re: My first FPGA code
« Reply #133 on: November 29, 2019, 11:41:08 pm »
I wasn't thinking about the 'initial' value but rather a default value assigned inside the process, just ahead of the case statement, that provided a value for the named signal in every state unless over-ridden in the state.  Given, say, 50 output signals from the FSM, it would be silly to define them in each of 100 states yet all signals must be defined in all states, one way or another.  Missing one of these signals results in a latch, something to be avoided.

Ah, OK, this distinction between an initializer and a "default" is important.

As for "default" assignments in a combinatorial process to avoid latch inference, exactly what is the default? For example, say you have a four-state machine and you assign to signal foo in two of those states. How do you maintain the signal value in the other two states? This is one reason why I avoid the two-process FSM.

Yes, the single-process FSM has its one clock of latency. But for most cases this latency is easily handled. Yes, there are exceptions.

I do use a clever trick to set the time (in clocks) spent in some states. Remember this is all in a clocked process. I create a signal called duration. Outside of the state machine I have an assignment:

Code: [Select]
if duration > 0 then
    duration <= duration - 1;
end if;

and then in the machine itself I'll have code like:

Code: [Select]
when STATEX =>
    duration <= 50;
    foo <= '1';
    state <= STATEY;
when STATEY =>
    if duration = 0 then
        foo <= '0';
        state <= STATEZ;
    end if;

Perhaps there's a way to do this in a two-process machine but I don't want to think about it.

But whatever works for you.

Quote
I didn't know that initializers weren't universal.  After all, it is just a configuration bit among millions of other bits configuring the fabric.
It should be but it isn't.

Quote
The asynchronous versus synchronous reset issue has been debated since the first FPGA project.  I have used mostly asynchronous but if Xilinx says to use synchronous, that's fine.  I have done it wrong for a long time but there's still time to learn to do it right.  I guess the asynchronous approach came from the 7474 which has asynchronous set and reset.

The Xilinx reason for the async reset is that it gets put on a slow global net (GSR) and there's no way to ensure that all flip-flops come out of reset at the same time, especially on the larger chips running fast. And since the flip-flops have resets which are configurable as either async or sync with no penalty for the sync reset (my guess is that the sync reset/preset is nothing more than a mux selected by the reset signal that drives the D input) then it works well. If the flip-flops in the fabric don't have a sync reset capability then it must be implemented outside of the flip-flop (in the CLB or wherever).
 

Offline emece67

  • Frequent Contributor
  • **
  • !
  • Posts: 614
  • Country: 00
Re: My first FPGA code
« Reply #134 on: November 30, 2019, 12:21:51 am »
.
« Last Edit: August 19, 2022, 02:45:33 pm by emece67 »
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3237
  • Country: ca
Re: My first FPGA code
« Reply #135 on: November 30, 2019, 12:57:36 am »
Also consider that your Xilinx device has hard-core adders (math blocks). The synthesizer knows how many exist and may preferentially fit long counters into one. A 16-bit counter implemented with a hard adder should be faster than one built from slices.

Xilinx has carry-chain hardware in every slice, so just feeding '1' as a carry to it will generate a counter of decent speed. This is what Vivado uses most of the time.

This is not as fast as DSP, which can count faster than carry chain, but DSP's clock speed is limited.

Since the state of the counter is fully known as far to the future as you want, you can always pipeline the counter and make it go as fast (or nearly as fast) as the logic can be clocked, which is much faster than DSP. Although it'll take a lot of logic for a long counter.
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9921
  • Country: us
Re: My first FPGA code
« Reply #136 on: November 30, 2019, 01:01:17 am »
I wasn't thinking about the 'initial' value but rather a default value assigned inside the process, just ahead of the case statement, that provided a value for the named signal in every state unless over-ridden in the state.  Given, say, 50 output signals from the FSM, it would be silly to define them in each of 100 states yet all signals must be defined in all states, one way or another.  Missing one of these signals results in a latch, something to be avoided.

Ah, OK, this distinction between an initializer and a "default" is important.

As for "default" assignments in a combinatorial process to avoid latch inference, exactly what is the default? For example, say you have a four-state machine and you assign to signal foo in two of those states. How do you maintain the signal value in the other two states? This is one reason why I avoid the two-process FSM.

Suppose I implement the program counter as described above and in the combinatorial process of the FSM, I only actually interact with the PC when I want to load or increment which occurs in just a very few of a hundred or so states in the FSM.  The default value IAR_NOP is sent to the PC unless otherwise specified.  This is the only way, short of defining the output in every state, that will eliminate latches.

Here is a simple process for the Instruction Address Register on my IBM1130
Code: [Select]
[font=courier]- IAR control

process(Reset, Clk, IAR_Ctrl)
begin
if Reset = '1' then
IAR <= (others => '0');
elsif Clk'event and Clk = '1' then
case IAR_Ctrl is
when IAR_NOP => null;
when IAR_LOAD => IAR <= A_BUS;
when IAR_INCR => IAR <= IAR + 1;
when others => null;
end case;
end if;
end process;[/font]

It is controlled by the main FSM by something like this in state s49:
Code: [Select]
[font=courier]
when s49 IAR_Ctrl <= IAR_INCR;
NextState <= MemRd;
[/font]

The default value set up at the beginning of the combinatorial process does:
Code: [Select]
[font=courier]
process (state, FullEA, FetchOpnd, F, TAG, IA, CO, OFL, OVFLInd, COtemp, CSET, VSET, ...
begin
IAR_Ctrl <= IAR_NOP;
<gigantic snip>
case state is
when s0 => NextState <= s0a; -- use this to IPL
when s0a => if DiskReady = '0' then -- wait for disk to go not ready
  NextState <= s0b;
      else
  NextState <= s0a;
     end if;
<gigantic snip>
[/font]
IAR_Ctrl is of type IAR_CtrlType which is:
Code: [Select]
[font=courier]
type IAR_CtrlType is (IAR_NOP, IAR_LOAD, IAR_INCR);
[/font]
« Last Edit: November 30, 2019, 01:08:58 am by rstofer »
 

Offline asmi

  • Super Contributor
  • ***
  • Posts: 2772
  • Country: ca
Re: My first FPGA code
« Reply #137 on: November 30, 2019, 02:54:19 am »
Verilog makes assumptions about signals which are not connected. VHDL throws errors at compile time. Which do you think is more helpful for the designer?
:bullshit: again. :(
« Last Edit: November 30, 2019, 03:05:53 am by asmi »
 

Offline lawrence11Topic starter

  • Frequent Contributor
  • **
  • !
  • Posts: 322
  • Country: ca
Re: My first FPGA code
« Reply #138 on: November 30, 2019, 04:29:56 am »
Is this legit?. This should be 2 clocks connected to a or gate, but each clock line is enabled by their respective conditon.

always @ ((posedge data_clk and !silence_inv) or (posedge mcu_clk and silence_inv))
« Last Edit: November 30, 2019, 04:59:20 am by lawrence11 »
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3237
  • Country: ca
Re: My first FPGA code
« Reply #139 on: November 30, 2019, 05:01:44 am »
Is this legit?. This should be 2 clocks connected to and or gate, but each clock line is enabled by their respective conditon.

always @ ((posedge data_clk and !silence_inv) or (posedge mcu_clk and silence_inv))

I don't use Verilog, so I don't know if this is correct.

Clock muxes are certainly real. However, switching clocks may produce a short clock which will cause unpredictable results across the fabric. Therefore, you need to be careful with clock switches.
 

Offline lawrence11Topic starter

  • Frequent Contributor
  • **
  • !
  • Posts: 322
  • Country: ca
Re: My first FPGA code
« Reply #140 on: November 30, 2019, 05:18:24 am »
I thought this was going to be more simple since I can draw it on a paper quite easily.

https://forums.intel.com/s/question/0D50P00003yyG9DSAU/max-10-alternate-between-two-clock-sources-without-reseting-ios-values-?language=en_US

BrianHG? You knowledge would surely be useful right now.
 

Offline asmi

  • Super Contributor
  • ***
  • Posts: 2772
  • Country: ca
Re: My first FPGA code
« Reply #141 on: November 30, 2019, 05:20:04 am »
Is this legit?. This should be 2 clocks connected to a or gate, but each clock line is enabled by their respective conditon.

always @ ((posedge data_clk and !silence_inv) or (posedge mcu_clk and silence_inv))
I will have to repeat my advice to take a step back and learn basics. If you would think for a second what kind of gates this code would create, you'd immediately understand that this code makes no sense. I don't even understand what is it you're trying to accomplish here.

Offline asmi

  • Super Contributor
  • ***
  • Posts: 2772
  • Country: ca
Re: My first FPGA code
« Reply #142 on: November 30, 2019, 05:21:43 am »
I thought this was going to be more simple since I can draw it on a paper quite easily.
Xilinx FPGAs have BUFGMUX primitive exactly for that purpose. As you hopefully understand, this is a HW-specific primitive.

Offline asmi

  • Super Contributor
  • ***
  • Posts: 2772
  • Country: ca
Re: My first FPGA code
« Reply #143 on: November 30, 2019, 05:25:10 am »
Clock muxes are certainly real.
They are not created through LUTs. Using LUT output as a clock is a disaster in the making.

However, switching clocks may produce a short clock which will cause unpredictable results across the fabric. Therefore, you need to be careful with clock switches.
Xilinx provides special hardware modules to ensure glitch-less switch, which are located next to global clock buffers. I'm sure other vendors do similar things.
« Last Edit: November 30, 2019, 05:37:01 am by asmi »
 

Offline lawrence11Topic starter

  • Frequent Contributor
  • **
  • !
  • Posts: 322
  • Country: ca
Re: My first FPGA code
« Reply #144 on: November 30, 2019, 05:26:50 am »
Clock muxes are certainly real.
They are not created through LUTs. Using LUT output as a clock is a disaster in the making.

However, switching clocks may produce a short clock which will cause unpredictable results across the fabric. Therefore, you need to be careful with clock switches.
Xilinx provides special hardware to ensure glitch-less switch, which is located next to global clock buffers. I'm sure other vendors do similar things.

Is there a max10 equivalent primitive?

I have yet to play around with "primitives".

As yu know, I can be a a bit "primitive" sometimes, so this shouldnt be too hard right?
 

Offline asmi

  • Super Contributor
  • ***
  • Posts: 2772
  • Country: ca
Re: My first FPGA code
« Reply #145 on: November 30, 2019, 05:27:57 am »
Is there a max10 equivalent primitive?

I have yet to play around with "primitives".
I don't know - read documentation and find out  :-//
As yu know, I can be a a bit "primitive" sometimes, so this shouldnt be too hard right?
Primitive is a built-in module (in terms of HDL) - meaning you don't need to create an implementation of it. They usually reflect hardware modules found inside FPGA (things like block RAM, DSP, various clock buffers, PCIE IP block, etc.). For Xilinx 7 series, they are all documented in document UG953.
« Last Edit: November 30, 2019, 05:31:16 am by asmi »
 

Offline lawrence11Topic starter

  • Frequent Contributor
  • **
  • !
  • Posts: 322
  • Country: ca
Re: My first FPGA code
« Reply #146 on: November 30, 2019, 05:44:31 am »
« Last Edit: November 30, 2019, 06:32:12 am by lawrence11 »
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2812
  • Country: nz
Re: My first FPGA code
« Reply #147 on: November 30, 2019, 05:57:53 am »
Is this legit?. This should be 2 clocks connected to a or gate, but each clock line is enabled by their respective conditon.

always @ ((posedge data_clk and !silence_inv) or (posedge mcu_clk and silence_inv))

Not legit. You need to use some FPGA specific resources, that can be discovered by reading this manual:

https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/hb/max-10/ug_m10_clkpll.pdf

It is very important to note the caveats over when clocks can switch over - in some use-cases both clocks must be ticking to allow the switchover to occur.
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Offline emece67

  • Frequent Contributor
  • **
  • !
  • Posts: 614
  • Country: 00
Re: My first FPGA code
« Reply #148 on: November 30, 2019, 11:27:56 am »
.
« Last Edit: August 19, 2022, 02:45:25 pm by emece67 »
 

Offline lawrence11Topic starter

  • Frequent Contributor
  • **
  • !
  • Posts: 322
  • Country: ca
Re: My first FPGA code
« Reply #149 on: November 30, 2019, 04:59:01 pm »
Ok well, this looks like debate over system synchronous vs source synchronous.

https://www.reddit.com/r/FPGA/comments/bkxyd2/systemsynchronous_vs_sourcesynchronous_interface/?ref=readnext

The data the FPGA receives comes from outside, on 1 pin the clock is external 108mhz, and on another pin its 150 mhz. The data pins are the same they dont move.

Both these clock pins are clk_p pins.

Calculations done dont need to be deterministic and do not need to be synchronized with other data sets, an output is generated to an external interrupt pin on the mcu.

Wich strategy would you take?

And, in any case, I still would need to perform the clock switch-over manoeuver, with clkena primitive, correct?
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf