How to use and manage memory with my FPGA?

Recommended Posts

Hi @GalD101

My mistake, they are indeed identical.

Indeed, a combinatorial circuit only depends on its input. Once the input becomes stable, a bit later (usually in the ns range), the output becomes stable, too.

Sequential circuits is when you add flipflops, which are clocked; on each rising clock-edge, they sample their input. The input section to the flip flop(s) itself can be considered a combinatorial (sub)circuit, the inputs of which are output of the flipflops themselves (and also, the input of flip flops in other sequential circuits that share the same clock signal).

The trick with a sequential circuit is to pick your clock frequency low enough that the inputs to the flip-flops have all become fully stable once a new rising clock edge comes along. If there's a lot of combinatorial logic in front of the flip-flop input (implying a longer stabilization time), the clock frequency needs to go down to accommodate that.

In a very real way, the trick to design circuits that can run at high clock frequencies is to make sure that the combinatorial logic sitting in front of all the flip-flops is as simple as possible. Even a single deep combinatorial circuit in your system can cost a lot of performance since it forces the clock frequency to go down for all the flip-flops using the same clock.

Vivado won't help you to do that type of design, but it will do all the calculations to verify that your design can accommodate the clock frequency you're trying to run it at.

So,

• combinatorial: a stateless (no flip-flops) feed-forward network of pure logic functions (like AND, OR, NOT, NAND, XOR), that will eventually stabilize;
• sequential: clocked flip-flops, the input of which is the output of a combinatorial sub-circuit, that, in turn, has flip-flops outputs as inputs.

(Note that this neat and tidy model has a big practical limitation, in that it doesn't say anything about external inputs, that have no relation with the clock that all the flip-flops share. This is a serious challenge; it touches also on question (d)).

An FPGA is little more than a big sea of flip-flops and combinatorial logic blocks to prepare the input for those flip-flops, and a bunch of dedicated hardware blocks that perform often-needed functions that could in principle be implemented using just the flip-flops and combinatorial logic blocks, but that are so useful that dedicated high-performance blocks are prepared (for example: RAM memory, and digital multipliers). And, last but not least: dedicated logic to handle input to and output from the FPGA logic, with a lot of cool tricks built-in.

As a last thought: flip-flops and their input logic that share the same clock are called a "clock domain".  It is sometimes useful to have multiple clock domains in your FPGA running at different frequencies. This opens the interesting question: how do you reliably transfer data from one clock domain to another? This is the clock domain crossing problem that was mentioned before, and there are tricks to do this reliably. Fortunately, for your FPGA-based photon correlator, this won't be necessary.

Edited by reddish
Share on other sites

7 hours ago, reddish said:

Sequential circuits is when you add flipflops, which are clocked

Sequential circuits do not have to be clocked. Flip-flops don't have to be clocked. It's quite possible to have sequential logic ( depends on the state of previous output ) with memory that depends on a previous state. An example is an asynchronous RS flip-flop built using 2 2-input nor gates. Essentially, this is combinatorial logic with memory. This distinction is important because your HDL description of your design can cause synthesis to infer a latch (memory) which may not be what you intend to do.

In the old days of MSI and LSI logic devices, or even PAL devices, logic was built from discrete basic boolean gates. A clock wasn't necessary.

In FPGA devices, logic is implemented in LUTs not and/or/not gates. The problem of delay through levels of combinatorial logic as implemented in LUTs is still a problem, as it was in the old days. The way to manage the problem of delay is by using clocked registers ( also has memory ) to control timing between parts of a design.

I've personally never attempted to implement a complete design in an FPGA that didn't use clocked registers. I suppose that it's possible. Most, if not all, FPGA designs use at least one clock to control their logic. It might be an external clock source or a number of clocks that are derived from an external clock source. When a design has multiple external clock sources that are unrelated ( not derived or synchronized ) to each other, or has inputs that can change state and violate setup or hold times, then your design starts getting complicated.

Trying to simplify and condense a digital design course into a couple of posts to a thread like this is difficult because it's easy to miss, or confuse,  really important concepts. Concepts like delay, clock setup time and clock hold time, meta-stability, etc. Can one turn on and off an LED on an FPGA board without understanding these concepts? Sure.

Edited by zygot
Share on other sites

7 hours ago, reddish said:

Even a single deep combinatorial circuit in your system can cost a lot of performance since it forces the clock frequency to go down for all the flip-flops using the same clock.

Wow that was confusing to read. I think that what you intended to say was that if the delay in your combinatorial logic approaches or exceeds the period of your register clock then your design will exhibit errors. Synthesis doesn't change clock frequencies for your design based on logic delays. In the case of an FPGA device external clocks and derived internal clocks generated by MMCM or PLL hardware are (mostly) fixed. Where your logic gets placed is fixed. If post-implementation timing analysis determines that logic path delays are excessive, based on clock periods, IO timing constraints, how the logic is synthesized, where it's placed, etc, etc, then your design won't work or, worse yest, will be unreliable. If your external input signals change in a way that is different than your timing constraints for those pins, then even a design that has no timing issues can fail. For outputs, even if you provide perfectly good timing constraints, there's no guarantee that the tools will meet those constraints. In that case you need to provide placement constraints for sections of your logic. It's all fairly complicated and not perfectly controllable.

I don't know what "single deep combinatorial circuit" is supposed to mean. Combinatorial logic structures may require many levels of delays between parts of the structure. Even if there's one output of the structure the delay may not be the same depending how the inputs change. This is easier to conceptualize if you think of your logic structure in terms of and, or, not type boolean logic gates and draw a schematic of it. When you describe your logic in VHDL or Verilog code thinking about levels and delays is a lot harder to do. Tools like Vivado will create a schematic view of your logic ( well actually of what it is after synthesis has finished with it ) , and that might help you understand it better. Personally, I have had a design appear to work until one of my logic structures encountered a combination inputs and previous last state that cause excessive delay, and hence failure on running hardware. There was no timing warning, so the post implementation timing analysis was not as complete as it should have been. We make a lot of assumptions about how the tools work and what the reports mean.

The reason why I'm bothering to post this is because of the nature of your project. It's pretty much the worst case use of an FPGA device.The analysis starts with a good practical understanding of digital design theory of your input signals before they even get past input buffers in your FPGA devices' input pins.

Commercial use of FPGA devices rarely use off-the shelf third party FPGA boards; usually it's a board custom designed for a specific application. In general this means that often signals going into an FPGA are conditioned by some external circuit so that what the FPGA application sees meets dc and ac specifications.

Edited by zygot
Share on other sites

On 8/25/2023 at 1:09 PM, reddish said:

what a "signal assignment" does. Specifically, what is the value of a signal inside a clocked code block right after the assignment statement?

I’m not sure if I understood you correctly, but if you talk about the assign statement, I think it just makes sure that whenever the value on the right hand side is changing, it changes the state of the value on the left hand side. For example, if I write something like: assign led_b = ~led_g

then whenever the value of led_g is 0 then led_b will be 1 and when led_g is 1, then led_b will be 0

Share on other sites

On 8/25/2023 at 1:09 PM, reddish said:

constraints file

I’m not sure if I really understood what a constrains file is yet, but I think it’s like some sort of a dictionary, I looked here and here and I just used it as a mapping tool between the names of the “variables” in my code to the physical hardware that is on the FPGA. other than that, I’m not sure what else can it be used for. I did see the “create_clock” keyword and I think what you are asking is in reference to this but so far, I just used this file as a dictionary. Is it something that I’m supposed to change or is it supposed to stay like this for the specific device I’m using?

Share on other sites

On 8/25/2023 at 1:09 PM, reddish said:

why registering externally generated signals that are asynchronous relative to your clock is always a good idea (even if your HDL allows you to not do that).

ok, so I think that by registering you mean saving as a register (that opposite to a 'wire', it remembers - acts like a memory block) and it is important in order for the timing to be accurate, since the asynchronous signals are not connected to the clock and therefore, if I won't save it in a register (if I won't register the signals), it wouldn't be accurate enough. I'm not sure if that's true, but I think you should also register your output for good practice but it is not as important.

Share on other sites

On 8/24/2023 at 5:58 PM, reddish said:

On the hardware side, this involves making sure that the voltage level output by the SPD is compatible with the voltage input of the FPGA. If you want to do it properly, it would be necessary to make sure that the impedance of the receiving end matches the impedance of the cable coming out of the SPD (usually 50 Ohms), to make sure you don't get reflections of the detection pulses. This is more-or-less optional if the SPD has an output impedance of 50 Ohms, as it will absorb any reflections in that case.

How can I check this? I have this schematic file and I'm not sure how to read it. Also, how can I figure out the impedance of the cable coming out of the SPD?

Share on other sites

according to the details of my SPD here, it says: "TTL output pulse amplitude (into 50 Ohm) is typically 3 Volts". Does it mean I need to make sure the corresponding input on my FPGA is "ok" with 3 volts?

Share on other sites

Hi @GalD101

A lot of good questions, excellent. I will tackle them one by one tomorrow because today is a bit busy.

Share on other sites

for the time being, I can use a function generator instead of a photon detector

Edited by GalD101
Share on other sites

Ok, I will first tackle the hardware questions.

Your question is, how can you check the compatibility of the SPD output with the CMOD input.

This requires some electronics knowledge, and the ability to read both the datasheet of the SPD, the electronic schematic of the CMOD module, and a good practical understanding of what impedance is and how to handle it. The best thing will be to consult a more experienced person locally at your lab who can help you with that.

A cable has an impedance, which is essentially a quantity that determines how an electromagnetic wave propagates in the cable. It has the same unit as resistance (Ohms), and it is related to that, but it is something else. If you connect different cables with different impedances, or you connect a cable with a certain impedance to an input with a different impedance (outputs and inputs have impedances, too), you have what's called an impedance mismatch; the electromagnetic wave will start to misbehave: part of its energy will reflect at the point where the mismatch happens. This can introduce nasty effects like local high voltages (more than you put in!), standing waves, etc, which at worst can destroy equipment, and (slightly less bad) can muck up your signal, which is pretty terrible if you try to do what you're doing, i.e., precise timing.

The good news is that your SPD, and the SMA cable that comes out of it (I presume it has an SMA connector?) have 50 Ohm impedances, which are thus matched (equal), and thanks to the 50 Ohm source impedance, any reflected signals get absorbed by the source (so you won't get reflections-of-reflections). This 50 Ohm source impedance is quite standard on digital outputs nowadays, but it's always good to check the datasheet. The cool thing about a 50 Ohm source impedance is that at the receiving side, you don't have to worry too much about reflections. They will happen, but they will reflect back to the source, and they will be absorbed there and vanish.

Problem is, the SPD output is still 5V TTL, and your destination (the FPGA) will see 5V if you're not careful. 5V in itself can potentially destroy the inputs on your Spartan FPGA.

There are several solutions to this problem. What I would do is shown below: at the side of your FPGA where the SMA cable from the SPD comes in, tie a 50 Ohm resistor between the signal and GND. This should make it so you will halve the voltage of the SPD signal, which (A) is safe for the FPGA, and (B) will actually be detected.

(Recommended reading: The Art of Electronics, Chapter 12 Logic Interfacing, section "Driving Cables").

Note that I am not an electronics expert, and there are certainly cleaner solutions, but this will work, and it will be enough to protect your FPGA. However: forget the 50 Ohm resistor, and you will (probably) blow up the FPGA.

It may be easier to do it like this, which is equivalent:

Here, too: forget the terminator == destroy your FPGA (possibly).

The cool thing is (if you dare): you are already in a position to test all of this. Write a simple Verilog program that replicates an input pin to an output pin (just "assign PIN_OUT = SPD_IN"), hook up and enable the SPD as shown above, and check with a scope the voltages you see at the FPGA input pin and the output pins. Ideally, the output pin should show a (slightly delayed and differently shaped) replica of the input pin.

(Note that this also requires you to explain to Vivado at which pins PIN_OUT and SPD_IN are connected; this is done using the constraints file that was mentioned before.)

To address a specific question you have:

> Also, how can I figure out the impedance of the cable coming out of the SPD?

Most BNC and SMA cables you will find in the lab will be 50 Ohms; if you insist you should find the precise cable type ID and look it up on the vendor website. (Cables with different impedances exist but they are quite rare, except perhaps cables used in video; video people use 75 Ohm impedance cables for some applications).

Share on other sites

The constraints file is a place where you provide information to Vivado that it needs to make a working "program" (more accurately: the bit-file that contains the full FPGA configuration), but which cannot (easily) be expressed in your HDL program.

The two most prominent examples of what you put in a constraints file are:

* Physical pin numbers and their logic standard (for example, "3.3V CMOS") corresponding to the top-level port name you use in your HDL code.
* The fact that there is an externally provided clock signal on some external pin. This allows Vivado to analyze and check the timing of your design.

Especially without the first type of constraint, Vivado wouldn't know, for example, that the "CLK" input of your top-level Verilog module corresponds to physical pin M9 of your FPGA.

Share on other sites

9 hours ago, GalD101 said:

for the time being, I can use, instead of a photon detector, a function generator

It will also have 50 Ohm output impedance, like your SPD. And you can generate a well-known signal (if it's a 2-channel generator) with known inter-channel delay, which can help to check if you recover the same delay from the FPGA correlator, later on. Also, you will save a bit of usage time on your SPD, which is a limited-lifetime item, and quite expensive.

Overall, an excellent idea. One caveat:

Function generators often allow you to specify a "load resistance", and then they will conveniently scale the voltage output to be the value as seen by the load, rather than what they put out, conveniently blowing up your load in the process, if you didn't anticipate that.

So if you (faithfully) put load = 50 Ohm, and set the function generator to generate 5V pulses, it will ACTUALLY output 10 Volt pulses which are seen as 5 Volt by the load. Boom says the FPGA.

So be very very careful with that, one silly mistake can cost you hardware.

After blowing up three or four devices in this way, I have disciplined myself to always look at the output of my function generator on a scope, before hooking it up to the device-under-test. Scopes can take quite a beating; digital inputs, not so much.

More tomorrow.

Edited by reddish
Share on other sites

Hi @GalD101,

First, the need to register asynchronous input signals.

> [...] if I won't save it in a register (if I won't register the signals), it wouldn't be accurate enough.

It goes a bit beyond that. If you use asynchronous inputs directly in a sequential (clocked) design, you are violating a major condition for the sequential design to work properly, which is that all inputs to flip-flops should be well-defined and stable as the clock goes through a rising edge.

Most often, the observable consequence of violating this condition is that your design will work most of the time, but it will sometimes fail. Mysteriously. In fact, it can do things that (according to just reading your HDL code) should seemingly be impossible.

Consider the figure below:

Here, the idea is to sample an incoming asynchronous signal with two flip-flops; the first flip-flop should sample the inverted value, and the second flip-flop should sample the non-inverted value when the clock goes through a rising edge.

In Verilog this would be something like this:

```always @ (posedge CLK)
begin
flipflop_1 <= ~ASYNC_IN; // sample inverted ASYNC_IN
flipflop_2 <=  ASYNC_IN; // sample non-inverted ASYNC_IN
end```

That seems obvious and innocuous enough; and it seems to guarantee that flipflop_1 and flipflop_2 are always each other's inverses, right?

Nope.

Vivado will happily compile this (it may emit a warning along the way, but it will probably get lost in the sea of messages it produces while processing a design).

But if you run this, and would use the values of flipflop_1 and flipflop_2, you will sometimes see that flipflop_1 and flipflop_2 end up with identical values.

Please think a bit about why this could happen, and explain it in your own words. Better yet: make a small Verilog program that does this, and put the outputs of both flipflops on a scope, with a shared asynchronous input from your function generator, to see it happen in real life. This is a problem that bites almost all beginning FPGA users, and it is vital that you understand why this happens, and how to prevent it from happening.

Quote

I'm not sure if that's true, but I think you should also register your output for good practice but it is not as important.

It is certainly good practice, yes.

Here's the issue: Verilog and VHDL allow you to write stuff down that is legal in those languages, but will lead to bad behavior once put in a simulator or on a real FPGA. (It's not unlike what you can do in more "normal" programming languages: they all allow you to write buggy code that will happily compile and/or run but doesn't do what you want.)

The way to deal with this in HDLs is to force yourself to write code in a very structured way and follow rules that are not demanded by the languages and enforced by the tools, but rather rules that you choose to follow voluntarily, to minimize the chances of silly bugs, to maintain the ability to reason about the code, and also the keep open the possibility that other people may understand your code.

One such rule: put all asynchronous inputs in a register (flip-flop), and only use the registered value in your design. Resist any and all temptation to use the asynchronous input directly. That rule is pretty hard.

Another rule of good design: divide your sequential HDL design into modules, each of which has a very clear function, inputs, and outputs. This is just good engineering practice, not different from the idea in normal programming, or in any design. A car's motor and gearbox are separate subsystems, even though it would theoretically be possible to design an integrated motor/gearbox. This allows different designers to work on different modules and keeps the complexity per subsystem manageable.

The register-your-outputs rule you mention is also such a rule: all outputs of sequential logic modules should be the outputs of registers in the module. This rule is a bit difficult as there are exceptions, where you break it. But once you reach the level where you want to break this rule, you'll be confident enough to understand why you should break it. For now, just consider it a hard rule. One important reason to adhere to this rule, is that it prevents very long chains of combinatorial logic from happening by accident. This can easily be seen by considering the model presented below.

Here is how I like to think about sequential FPGA design:

This design has three sequential-logic modules, sharing the same clock (together, they form a "clock domain"). The state of each module is kept in the registers (the green boxes, at the "output" side of each module). Some state is purely for internal use; other state is intended as output to other modules or the external world; for example, an LED.

The blue stuff is combinatorial logic: ANDs, ORs, adders, NOTs, etcetera, and all combinations thereof. The function of the combinatorial logic within a module is simply this: determine the input to the registers (in green), which will become the content of the registers on the next rising clock edge.

The purple lines are register outputs that are inputs to other modules, and also to the module itself.

I could understand that all this is quite abstract to you at this point. if you don't fully understand why I think this is a big deal: don't worry, this will come as your FPGA journey continues. The cool thing is, once you get to the point where you see that this is indeed a good way to think about FPGA design, you can make small miracles happen. This way of thinking about FPGA/HDL design is sufficient to make pretty serious designs, with microprocessors, memories, filter banks, .... It's even good enough for making a photon correlator ... :-)

There is another "rule" for FPGA design which concerns the way that these modules interact. Sometimes a module wants information from an "upstream" module, but it has to wait until it is available. I have standardized on a good way to deal with that situation. We'll discuss it once we need that.

Edited by reddish
Share on other sites

For now, the last open issue, concerns my question about what a signal assignment does. This is a complicated and quite technical topic.

It's also a topic where Verilog and VHDL are different. Since we're trying to do Verilog here, I'm on somewhat shaky ground.

The first thing to realize is that Verilog has two different assignment operators:

```// Non-blocking assignment:

a <= b;

// Blocking assignment:

a = b;```

What I want you to realize first and foremost is that a non-blocking assignment says that the assignment should not be executed right now, but later. When you run a Verilog program in a simulator, this means that such an assignment is not executed immediately, but rather it is put in a queue of things-to-do-later, and the things-to-do-later are executed only at the end of the currently executed always block.

To drive this point home, I would like you to study (and perhaps run in your hardware), two Verilog programs.

Program 1

```module non_blocking_assignment_1(CLK, LED);

input CLK;
output LED;

reg flipflop = 1'b0;

always @ (posedge CLK)
begin
flipflop <= ~flipflop;
end

assign LED = flipflop;

endmodule```

This first program toggles a flip-flop on each clock cycle. The output of the flipflop is sent to an LED, which will blink (fast). The visible effect will be that the LED seems to be less bright than what it normally does, if enabled 100% of the time.

This is easy, right?

Now consider the following very similar program:

Program 2

```module non_blocking_assignment_2(CLK, LED);

input CLK;
output LED;

reg flipflop = 1'b0;

always @ (posedge CLK)
begin
flipflop <= ~flipflop;
flipflop <= ~flipflop;
end

assign LED = flipflop;

endmodule```

Here, on every clock-cycle, the flip-flop is seemingly inverted twice, right? Which suggests that the flipflop always stays at 0, and the LED will be off all the time.

Run this program on your little Spartan 7, and be amazed. The behavior will be exactly identical to program 1: your LED will appear "on" at ~half the normal brightness.

Please read up on blocking and non-blocking assignments, to the point where you can explain in your own words why program #2 acts the same as program #1.

Be wary that there's a lot of bad info on the internet about HDLs, so at this point I'd suggest that you get a good book about the language. The only problem is that I can't recommend such a good Verilog book, because I haven't read any. Perhaps others can chime in.

Why are we discussing all these esoteric corner cases?

At this point you may be wondering why we're going off on all these tangents and topics that seemingly have so little to do with what you're trying to accomplish -- your little photon coincidence counter.

In essence, we're building a foundation here. All this is FPGA 101, just to make sure that we have a common vocabulary, and we can discuss more practical stuff later on at a much higher tempo. We're also building good habits ("register your inputs!") and explaining why it is important. If we skip those kinds of things and try to shoot for your end goal more directly, you WILL run into those things, but you will do so in a much more complicated context of a semi-finished, probably somewhat badly written buggy photon coincidence counter. Digging yourself out of that will be essentially impossible. To a large extent, the learning curve of FPGA/HDL work is bumping into a lot of problems, and once you understand what's going wrong, you learn to recognize the symptoms, and the next time you encounter it you'll have a handle on how to fix it. What I'm trying to do now is point out these bumps before you run into them yourself. The payout will come later.

Edited by reddish
Share on other sites

On 8/28/2023 at 10:45 AM, reddish said:

Isn't this is what's called a "Race Condition"?
Here, since the two flipflops receive asynchronous input (the input is foreign to their clock),
a race condition occurs and in the small time difference that is in between the input signal for each ff, the values of flipflop_1 and flipflop_2 are seemingly the same sometimes but in reality, it's just because they sort of like have 2 different inputs that have a "clock" that isn't exactly the same all the time
by the way, what software/program are you using to draw those images? I saw it before but never bothered to look for it.

Share on other sites

Hi @GalD101

Indeed, you can view this as a sort of race condition! If the input signal changes fast enough to reach flipflop_2 at the clock edge but is still making it through the inverter, you can get the situation that both flip flops sample ("register") the same value. The time window where this would happen is small, but not empty.

Registering the value in a single flip-flop is in principle not even enough. In fact, the problem is super fundamental (google "metastability" if you want your mind blown) ... The standard solution is to lead asynchronous incoming signals through multiple levels of flip-flops, that way you can make the chance that this is a problem in your design arbitrarily small. For many practical purposes (your photon counter included) a single flip-flop will probably suffice in practice.

The problems this can cause are really quite nasty. Suppose for example that you have an asynchronous RESET input in your design, that resets all modules. If this kind of thing happens you could end up with half your modules in reset, while the other half are already running. Yikes.

The drawings are made on the fly in MS Paint, how about that :)

Edited by reddish
Share on other sites

Hey @reddish

so in order to accomplish step 1, I need to connect the function generator to the FPGA (and making sure I never give it more than 3 volts), and then to check if it works?
What should I do now?

Share on other sites

Oh, I also happen to have a PmodDA4 that communicates via the SPI protocol. Is it something I can use?

Share on other sites

On 8/24/2023 at 5:58 PM, reddish said:

On the software (HDL) side, this is already a lot more involved. The most challenging part will be to write a bit of VHDL or Verilog to transfer information from the FPGA to the computer. The only feasible way to do that (given your expertise) is via a serial interface. You will write bytes from inside your FPGA to an FPGA output pin that is connected to an FTDI chip on your development board. This FTDI chip will send this data to the PC via USB, where you can receive it using a serial port reading program, for further analysis.

can you help me with this part? where should I start? I will google some information about it

Share on other sites

Hi @GalD101

Your SPI PMOD is not useful for what you are trying to do.

I indicated useful things you can do here and there in my comments. From where you are now, the next logical steps are:

1. Make an image of what your SPD does on a scope and post it here. Also, post the type/model of your SPD.

2. Safely (as explained before, with a 50 Ohm terminator) connect the SPD to the FPGA, and program the FPGA to replicate the SPD signal it receives to an output pin (directly, without a clock). Put both signals on a scope. Verify that your FPGA actually detects the SPD signals (this confirms that the signal levels are usable).

3. Replace the SPD by the function generator programmed to generate a similar but regular signal (similar voltage level, similar pulse length). if that works, you can do most of the remaining development using the function generator rather than with the SPD.

4. Learn how to control your FPGA's timing. I proposed earlier that you generate a 30% duty cycle, 10 MHz signal; I still want to see a scope image of that. For this you will need to instantiate an MMCM block inside the FPGA that can synthesize a 100 MHz frequency from the 12 MHz input. If you're at a loss on how to accomplish this, let me know, I can chop this up it in smaller chunks.

5. If you did all that, we can start thinking about step 1. You need to read about the standard serial (UART) protocol: start bits, data bits, and stop bits. We will first try to push 'U' characters from the FPGA to your PC, since that involves nothing more than generating a square wave with the right frequency. If you can do that, we'll turn that into a proper UART transmitter. And if you did that, we'll start making a VHDL design that can transmit a counter.

If you manage to get step 5 done, you will be about halfway there towards the coincidence counter.

You've been pretty quiet over the last week. Realize there is still ~ 80-200 hours of intensive work for you to do until you get your coincidence counter working, and that's just getting the FPGA part of your experiment working. I assume you also need to do other work.

I need to hear from you if you are firmly committed to spend this time. Because this is taking a lot of my time as well, which I'm willing to do, but only.if you're serious about getting the project done. You cannot half-ass this; you need to put in the hours.

Share on other sites

Hi @reddish

As of now, I'm only limited to using just the function generator. I was able to connect it and make the led blink according to it.

7 hours ago, reddish said:

I still want to see a scope image of that

How can I achieve this? Do you want me to connect the function generator to an oscilloscope?

7 hours ago, reddish said:

Make an image of what your SPD does on a scope and post it here. Also, post the type/model of your SPD.

I will try to ask my professor for that since I'm not sure what to do (do I need to connect the spd to an oscilloscope? For now I'm only limited to using the function generator)

7 hours ago, reddish said:

Safely (as explained before, with a 50 Ohm terminator) connect the SPD to the FPGA, and program the FPGA to replicate the SPD signal it receives to an output pin (directly, without a clock). Put both signals on a scope. Verify that your FPGA actually detects the SPD signals (this confirms that the signal levels are usable).

As I said for now I'm limited to using just the function generator instead

7 hours ago, reddish said:

Replace the SPD by the function generator programmed to generate a similar but regular signal (similar voltage level, similar pulse length). if that works, you can do most of the remaining development using the function generator rather than with the SPD.

The function generator is connected to one of the pins in the fpga and it works

7 hours ago, reddish said:

Learn how to control your FPGA's timing. I proposed earlier that you generate a 30% duty cycle, 10 MHz signal; I still want to see a scope image of that. For this you will need to instantiate an MMCM block inside the FPGA that can synthesize a 100 MHz frequency from the 12 MHz input. If you're at a loss on how to accomplish this, let me know, I can chop this up it in smaller chunks.

I think I will need some help with that. Are there any good sources for this?

7 hours ago, reddish said:

I need to hear from you if you are firmly committed to spend this time. Because this is taking a lot of my time as well, which I'm willing to do, but only.if you're serious about getting the project done. You cannot half-ass this; you need to put in the hours.

Yes, I am committed I just take a data structures course at the same time but no worries, I have until 17.10 to work on this

Share on other sites

Hi @GalD101

> How can I achieve this? Do you want me to connect the function generator to an oscilloscope?

No. This is done purely using your little Spartan-7 board and a scope.

The idea is this. Your Spartan-7 board has a 12 MHz external clock connected to one of its input pins. So far (eg for your blinking LED) you have ran your design using this 12 MHz clock, since it's all you have. But for the photon coincidence counter, you will need a much faster clock.

A cool feature of these FPGAs is that they have pretty advanced on-chip facilities to generate clocks with frequencies that are not available by default. In your case, you will use a block called an "MMCM" to generate an intermediate frequency of 600 MHz in a so-called voltage-controlled oscillator, then divide this clock by 6, to arrive at a frequency of 100 MHz.

The details of this functionality are documented here: https://docs.xilinx.com/v/u/en-US/ug472_7Series_Clocking, in chapter 3.

However, this document is quite an information overload, and may be rather intimidating (Xilinx documentation is generally quite overwhelming to a beginner). In practice, what you will be doing is insert a piece of Verilog code in your code that will tell Vivado that you want to use an MMCM; you will provide a bunch of parameters to it (specifying that you want to generate a 100 MHz clock from a 12 MHz clock), and Vivado will do the rest.

Then, using this 100 MHz clock, you will implement a little state machine (not unlike your original blinking LED, but slightly more complicated) that will output a repeating sequence with a period of 10 clock cycles, with values 1-1-1-0-0-0-0-0-0-0, and put that on a pin. Hook up a scope to that, and you will see the desired 10 MHz, 30% duty cycle output.

I will write a more detailed post later about the generation of the 100 MHz clock using the MMCM facility.

> I will try to ask my professor for that since I'm not sure what to do (do I need to connect the spd to an oscilloscope?

Yes, and you will put your scope at 50 Ohm input impedance, or terminate its output manually with a 50 Ohm terminator, because that's what you will be doing later on with the FPGA as well. (As I said before, you really need to get an idea what impedance is and how it affects your work in the lab. Find a local person who can explain it to you).

The reason for doing this is to verify your SPD's output signal behavior: voltage level, pulse length, and dead time. These are important things to know, and the way to know them is read the devices datasheet (good) and verify it by looking at an actual picture on a scope (better).

> As I said for now I'm limited to using just the function generator instead.

Ok. If you're really don't have access to the SPD now, set your function generator to generate 2.5 Volts into a 50 Ohm load, and generate pulses of 5 ns length (or however short you van get them) at 1 kHz. Then get an image using a scope terminated at 50 Ohms (which is then a "50 Ohm load").

> The function generator is connected to one of the pins in the fpga and it works

Good. Please describe to me how you connected it. Please describe how you verified that it works.

> I think I will need some help with that. Are there any good sources for this?

This will require the MMCM that I talked about above. You can try to read the Xilinx docs, but it's heavy reading. I'll post a more accessible intro later.

> Yes, I am committed

Good! Let's proceed. The direct problem in front of is getting the 100 MHz clock from the 12 MHz clock. There's quite a road ahead; dividing it up into small, manageable steps is necessary.

As some auxiliary info: can you find out the model/make of your equipment (SPD, function generator, oscilloscope)? That will tell me what kind of things we can and cannot do with them.

Share on other sites

8 minutes ago, reddish said:

Good. Please describe to me how you connected it. Please describe how you verified that it works.

I made a simple program that assigned the led to the value of the corresponding pin.

Share on other sites

This is the spd we have. I will get info about the function generator as well as the oscilloscope later.

This is the oscilloscope:

This is the function generator:

Edited by GalD101
Added function generator and oscilloscope details