FPGA, SoC, And CPLD Boards And Kits
FPGA Evaluation and Development Kits
6231 Discussions

How to obtain the counting of TTL pulses from an FPGA?

JorgeA
Novice
1,703 Views

I'm currently working on a project in which I need to program an FPGA in order to connect it to a photon detector, that generates a TTL pulse when detecting a photon; I need to count this pulses, meaning, I need to count the photons being detected. The duration of each pulse according to the detector documentation is 20 ns.

I'm completely new to hardware programming, but I've been trying to keep up. So far, I was able to create the PulseCounter module and its testbench. The functionality I want is to set intervals in the scale of microseconds and then count the pulses from the detector during that time, up until a total time is completed, so I'm using frames of 100 μs during 1 second. Based on a paper I have, the number of photons is between 0 and 14 (it follows a Poisson distribution with a mean of 3.6) for a 254 μs time frame. Right now the pulse signal in the testbench is running continously. The counting seems to be working fine.

This is the module PulseCounter.v:

module PulseCounter (
    input wire clk,
    input wire reset,
    input wire photon_pulse,
    output reg [31:0] count,
    output reg interval_done
);

reg photon_pulse_dly; // Delayed version of photon_pulse
reg [31:0] timer;
reg [31:0] total_timer;

parameter INTERVAL = 5000; // 100 us = 0.0001 s @ 50MHz clock
parameter TOTAL_TIME = 50000000; // 1 s @ 50MHz clock

always @(posedge clk or posedge reset) begin
    if (reset) begin
        count <= 32'b0;
        timer <= 32'b0;
        total_timer <= 32'b0;
        photon_pulse_dly <= 0;
        interval_done <= 0;
    end else begin
        photon_pulse_dly <= photon_pulse;
        if (photon_pulse && !photon_pulse_dly) begin // Rising edge detected
            count <= count + 1;
        end
        if (timer == INTERVAL) begin
            timer <= 32'b0;
            interval_done <= 1;
            if (total_timer != TOTAL_TIME) begin
                total_timer <= total_timer + INTERVAL;
                count <= 32'b0; // Reset count for next interval
            end
        end else begin
            timer <= timer + 1;
            interval_done <= 0;
        end
    end
end

endmodule

And this is the testbench PulseCounter_tb.v:

`timescale 1ns / 1ps

module PulseCounter_tb;

    reg clk;
    reg reset;
    reg photon_pulse;
    wire [31:0] count;
    wire interval_done;

    // Instantiate the PulseCounter module
    PulseCounter uut (
        .clk(clk), 
        .reset(reset), 
        .photon_pulse(photon_pulse), 
        .count(count), 
        .interval_done(interval_done)
    );

    initial begin
        // Initialize inputs
        clk = 0;
        reset = 0;
        photon_pulse = 0;

        // Apply reset
        reset = 1;
        #10;
        reset = 0;        
    end
     
     initial begin
        // Generate a certain number of pulses
        repeat (5000) begin
            #20; photon_pulse = 1; // Pulse starts
            #20; photon_pulse = 0; // Pulse ends
        end
     
        // Stop the simulation after all pulses are generated
        #10000;
      $finish;
     end

    // Clock generator
    always #10 clk = ~clk;

endmodule


The FPGA I'm using is a DE10-Nano and I'm using Quartus. The next step would be retrieving this information and sending it to my PC. This is what I need help with. I've been looking and I found an alternative which is USB-to-UART connection. I don't know how to do this, and what would be the appropiate way to do it (whether the counting of each interval should be send altogether or at the end of the interval). I'm more familiar with high level programming languages, so the way I visualize it is to have a .txt with the counting for each interval, but then again, I'm lost here. I would appreciate a lot anyone's help.

Labels (2)
0 Kudos
1 Solution
ShengN_Intel
Employee
1,650 Views

Hi,

 

If you want to retrieve the RTL count data in a .txt file, you can use PIO IP to pass the RTL count data to embedded system to be written in .txt file.

PIO IP reference link - https://www.macnica.co.jp/en/business/semiconductor/articles/intel/113961/

TXT file mounting video link - https://www.youtube.com/watch?v=kbIcXwtfBiY&t=414s

To mount the text file in embedded system (eclipse), will need to debug the software Debug As -> Nios II Hardware.

 

For USB-to-UART, you may refer to this video link https://www.youtube.com/watch?v=7xJ9dhVDCwU&t=271s and reference design https://www.intel.com/content/www/us/en/design-example/715139/cyclone-v-uart-rs-232-maximum-baud-rate-reference-design.html. For the USB part putty (HPS), may be you need to open a new thread in https://community.intel.com/t5/Intel-SoC-FPGA-Embedded/bd-p/soc-fpga-embedded-development-suite to get more details.

 

If want to send the count data at end of interval, may be can do something like below in RTL:

assign count = (timer == 32'd4999) ? count_reg : 32'b0;

 

Btw, I had create a design uart_putty.zip attached below for demonstration. The ./software/usbuart/output_end_interval.txt record the count data at end interval while the ./software/usbuart/output_whole_interval.txt record the count data for whole interval.

 

Let me know if you have any further update or concern.

 

Thanks,

Best Regards,

Sheng

 

View solution in original post

6 Replies
ShengN_Intel
Employee
1,651 Views

Hi,

 

If you want to retrieve the RTL count data in a .txt file, you can use PIO IP to pass the RTL count data to embedded system to be written in .txt file.

PIO IP reference link - https://www.macnica.co.jp/en/business/semiconductor/articles/intel/113961/

TXT file mounting video link - https://www.youtube.com/watch?v=kbIcXwtfBiY&t=414s

To mount the text file in embedded system (eclipse), will need to debug the software Debug As -> Nios II Hardware.

 

For USB-to-UART, you may refer to this video link https://www.youtube.com/watch?v=7xJ9dhVDCwU&t=271s and reference design https://www.intel.com/content/www/us/en/design-example/715139/cyclone-v-uart-rs-232-maximum-baud-rate-reference-design.html. For the USB part putty (HPS), may be you need to open a new thread in https://community.intel.com/t5/Intel-SoC-FPGA-Embedded/bd-p/soc-fpga-embedded-development-suite to get more details.

 

If want to send the count data at end of interval, may be can do something like below in RTL:

assign count = (timer == 32'd4999) ? count_reg : 32'b0;

 

Btw, I had create a design uart_putty.zip attached below for demonstration. The ./software/usbuart/output_end_interval.txt record the count data at end interval while the ./software/usbuart/output_whole_interval.txt record the count data for whole interval.

 

Let me know if you have any further update or concern.

 

Thanks,

Best Regards,

Sheng

 

ShengN_Intel
Employee
1,629 Views

Hi,


Any further update or concern on this thread?


Thanks,

Best Regards,

Sheng


JorgeA
Novice
1,600 Views

Hello,

 

Thank's a lot for your help. I'm currently trying to understand the example design you provided. As I mentioned, I'm completely new to hardware programming in general (not only FPGA's), so It's being a little difficult to understand the design. I have also checked the resources you provided  for context, but it's still challenging. If you can provide a general description of this it would be really helpful. Finally, would this design be ready for the FPGA programming? I'm sorry for the inconvenience.

0 Kudos
JorgeA
Novice
1,602 Views

Hello,

 

Thank's a lot for your help. I'm currently trying to understand the example design you provided. As I mentioned, I'm completely new to hardware programming in general (not only FPGA's), so It's being a little difficult to understand the design. I have also checked the resources you provided  for context, but it's still challenging. If you can provide a general description of this it would be really helpful. Finally, would this design be ready for the FPGA programming? I'm sorry for the inconvenience.

0 Kudos
ShengN_Intel
Employee
1,582 Views

Hi,


The 32-bits RTL count data obtained is passed to the embedded system through the PIO IP.

In <path>/uart_putty/software/uabuart/main.c:

FILE* - specify a file name.


fopen - open the .txt file


reg_bb[0] = *(volatile unsigned char *) PIO_3_BASE;

reg_bb[1] = *(volatile unsigned char *) PIO_2_BASE;

reg_bb[2] = *(volatile unsigned char *) PIO_1_BASE;

reg_bb[3] = *(volatile unsigned char *) PIO_0_BASE;

int combinedValue = (reg_bb[0] << 24) | (reg_bb[1] << 16) | (reg_bb[2] << | reg_bb[3];

Retrieve the PIO value (RTL count data) 8-bits each and then combine to 32-bits.


sprintf - convert the combined value to string


strcpy - copy the string to buffer


fputs - write the buffer value to the .txt file and fclose


PutUart1() and GetUart1() are for uart transmit and receive respectively. For the uart transmit to the putty (usb-to-uart), this probably will need help from another forum because will require some board configuration.


Yes, this design is ready for the FPGA programming. Have to program the .sof and .elf files. If you use other boards, try to regenerate all the things.


Thanks,

Regards,

Sheng


0 Kudos
JorgeA
Novice
1,573 Views
0 Kudos
Reply