Forum Discussion

JorgeA's avatar
JorgeA
Icon for New Contributor rankNew Contributor
2 years ago
Solved

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

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.

6 Replies

  • ShengN_altera's avatar
    ShengN_altera
    Icon for Super Contributor rankSuper Contributor

    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_altera's avatar
    ShengN_altera
    Icon for Super Contributor rankSuper Contributor

    Hi,


    Any further update or concern on this thread?


    Thanks,

    Best Regards,

    Sheng


    • JorgeA's avatar
      JorgeA
      Icon for New Contributor rankNew Contributor

      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.

  • JorgeA's avatar
    JorgeA
    Icon for New Contributor rankNew Contributor

    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.

  • ShengN_altera's avatar
    ShengN_altera
    Icon for Super Contributor rankSuper Contributor

    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


    • JorgeA's avatar
      JorgeA
      Icon for New Contributor rankNew Contributor

      Thanks a lot for your help!