Data retrieving using HPS in DE10-Nano
Hello,
I've been working on a project that consists in program a DE10-Nano to use it as a photon counter. The idea is to count TTL pulses fired by a photon detector. I previously asked here for help, because I'm completely new to hardware programming, but I couldn't make the help I got to work. I searched some more and I found a useful repo dedicated to the DE10-Nano. https://github.com/zangman/de10-nano In there, I was able to use a different approach, which uses the HPS (with an Embedded Linux System based on Debian) to control the FPGA. I ended up making progress using this, an I got the following design:
/// PHOTON COUNTER /// wire photon_pulse; reg photon_pulse_delay; reg interval_done; reg [31:0] interval_timer; reg [31:0] total_timer; reg [63:0] count; reg [63:0] final_count; always @(posedge fpga_clk_50 or negedge hps_fpga_reset_n) begin if (~hps_fpga_reset_n) begin interval_timer <= 0; total_timer <= 0; count <= 0; final_count <= 0; interval_done <= 0; photon_pulse_delay <= 0; end else begin photon_pulse_delay <= photon_pulse; if (photon_pulse && !photon_pulse_delay) begin count <= count + 1; end if (interval_timer == time_interval_export) begin interval_done <= 1; interval_timer <= 0; final_count <= count; count <= 0; if (total_timer < total_time_interval_export) begin total_timer <= total_timer + time_interval_export; end end else begin interval_timer <= interval_timer + 1; interval_done <= 0; end end end assign interval_counting_export = interval_done ? final_count : total_timer == total_time_interval_export ? 6969 : 0; assign photon_pulse = PHOTON_PULSE_GPIO;
Since I'm more familiar with Programming Languages instead of HDL (or anything related to hardware), I found this useful because I can interact with the FPGA using a C code. The C code (provided by the repo) is this:
#include <error.h> #include <fcntl.h> #include <inttypes.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <sys/mman.h> #include <unistd.h> #define BRIDGE 0xC0000000 #define BRIDGE_SPAN 0x18 #define TIME_INTERVAL 0x00 #define TOTAL_TIME_INTERVAL 0x08 #define INTERVAL_COUNTING 0x10 int main(int argc, char **argv) { uint64_t time_interval = 0; uint64_t total_time_interval = 0; uint64_t interval_counting = 0; uint8_t *time_interval_map = NULL; uint8_t *total_time_interval_map = NULL; uint8_t *interval_counting_map = NULL; uint8_t *bridge_map = NULL; int fd = 0; int result = 0; if (argc != 3) { perror("Only 2 numbers should be passed."); return -1; } time_interval = strtoll(argv[1], NULL, 10); // time_interval in clock cycles (100 us @ 50 MHz = 5000 Clock Cycles) total_time_interval = strtoll(argv[2], NULL, 10); // total_time_interval in clock cycles (1 s @ 50 MHz = 50'000.000 Clock Cycles) fd = open("/dev/mem", O_RDWR | O_SYNC); if (fd < 0) { perror("Couldn't open /dev/mem\n"); return -2; } bridge_map = (uint8_t *)mmap(NULL, BRIDGE_SPAN, PROT_READ | PROT_WRITE, MAP_SHARED, fd, BRIDGE); if (bridge_map == MAP_FAILED) { perror("mmap failed."); close(fd); return -3; } time_interval_map = bridge_map + TIME_INTERVAL; total_time_interval_map = bridge_map + TOTAL_TIME_INTERVAL; interval_counting_map = bridge_map + INTERVAL_COUNTING; *((uint64_t *)time_interval_map) = time_interval; *((uint64_t *)total_time_interval_map) = total_time_interval; while (1) { interval_counting = *((uint64_t *)interval_counting_map); if (interval_counting != 0) { printf("%" PRIu64 "\n", interval_counting); } if (interval_counting == 6969) break; } result = munmap(bridge_map, BRIDGE_SPAN); if (result < 0) { perror("Couldnt unmap bridge."); close(fd); return -4; } close(fd); return 0; }
I modified it so it matches my project. My main goal is to provide two parameters (time_interval and total_time_interval) and to obtain the counting data from each interval made by the FPGA, and in this case I do so by accessing the interva_counting (defined as an export in Platform Designer in Quartus). However I'm facing some issues: The first one, is that the counting is different from what is suppossed to be at certain intervals, giving the fact that I'm using a waveform generator of known frequency. The second error is that I'm not getting all the intervals I should be getting (total_time_interval_export/time_interval_export). I'm not sure what can be causing this errors, so I would really appreciate the help. Do I need a different approach?
Thanks a lot.