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
endmoduleAnd 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.
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