Red Pitaya FPGA-board as a pulse counter

0

I want to get familiar with FPGA development and therefore tried to implement as a first project a FPGA-based pulse counter which simply counts all incoming pulses (e.g. just the rising edges) and makes them accessed via the GPIO/AXI interface as a 32-Bit integer.

I tried to combine the following two examples:

I used the stopwatch project as the base and adapted it so, that the Binary Counter will not be feed by the 125Mhz FPGA clock, but instead with the incoming pulses (that part is taken from the frequency counter project). I also changed the Verilog code of the FrequencyCounter that it just creates a 1-bit High/Low signal, so it can drive the Binary Counter:

module frequency_counter #
(
    parameter ADC_WIDTH = 14,
    parameter AXIS_TDATA_WIDTH = 32,
    parameter COUNT_WIDTH = 32,
    parameter HIGH_THRESHOLD = -100,
    parameter LOW_THRESHOLD = -150
)
(
    (* X_INTERFACE_PARAMETER = "FREQ_HZ 125000000" *)
    input [AXIS_TDATA_WIDTH-1:0]   S_AXIS_IN_tdata,
    input                          S_AXIS_IN_tvalid,
    input                          clk,
    input                          rst,
    input [COUNT_WIDTH-1:0]        Ncycles,
    output [AXIS_TDATA_WIDTH-1:0]  M_AXIS_OUT_tdata,
    output                         M_AXIS_OUT_tvalid,
    output [0:0]       counter_output
);

    wire signed [ADC_WIDTH-1:0]    data;
    reg                            state, state_next;
    reg [COUNT_WIDTH-1:0]          counter=0, counter_next=0;
    reg [COUNT_WIDTH-1:0]          counter_output_next=0;
    reg [0:0]                      counter_output=0;
    reg [COUNT_WIDTH-1:0]          cycle=0, cycle_next=0;


    // Wire AXIS IN to AXIS OUT
    assign  M_AXIS_OUT_tdata[ADC_WIDTH-1:0] = S_AXIS_IN_tdata[ADC_WIDTH-1:0];
    assign  M_AXIS_OUT_tvalid = S_AXIS_IN_tvalid;

    // Extract only the 14-bits of ADC data 
    assign  data = S_AXIS_IN_tdata[ADC_WIDTH-1:0];

    // Handling of the state buffer for finding signal transition at the threshold
    always @(posedge clk) 
    begin
        if (~rst) 
            state <= 1'b0;
        else
            state <= state_next;
    end

    always @*            // logic for state buffer
    begin
        if (data > HIGH_THRESHOLD)
            counter_output = 1;
        else if (data < LOW_THRESHOLD)
            counter_output = 0;
        else
            state_next = state;
    end

endmodule

It does work somehow, but not correctly:

If I send pulses on the IN1 input, the counter value (0x48000008) gets incremented, but too fast (I use a 1Hz signal and the counter gets incremented about 1000x faster):

// read counter value
root@rp-f0184d:~# monitor 0x42000008
0x00000000

// start counting pulses (by default stopped)
root@rp-f0184d:~# monitor 0x42000000 1

// read counter values
root@rp-f0184d:~# monitor 0x42000008
0x00000db5
root@rp-f0184d:~# monitor 0x42000008
0x00001404
root@rp-f0184d:~# monitor 0x42000008
0x000017ca
root@rp-f0184d:~# monitor 0x42000008
0x00001b86
root@rp-f0184d:~# monitor 0x42000008

Here is the block design:

enter image description here

Can someone please help me, how I can get this to work?

verilog
fpga
xilinx
zynq
redpitaya
asked on Stack Overflow Jul 18, 2018 by user9564464 • edited Jul 19, 2018 by user9564464

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0