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

Data retrieving using HPS in DE10-Nano

JorgeA
Novice
131 Views

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.

Labels (2)
0 Kudos
2 Replies
Jeet14
Employee
55 Views

Hi,


Please allow sometime to go through this query.

Will get back to you soon.


Regards

Tiwari


0 Kudos
Jeet14
Employee
13 Views

Hi,


I assume you have already made changes to the device tree files i.e. all bridges should be enabled.


Since, you are referring this https://github.com/zangman/de10-nano?tab=readme-ov-file, I recommend you to post your query on the githib discussion. This page author might help you.


Regards

Tiwari




0 Kudos
Reply