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:
Stopwatch: http://antonpotocnik.com/?p=489265
Frequency Counter: http://antonpotocnik.com/?p=519284
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:
Can someone please help me, how I can get this to work?
User contributions licensed under CC BY-SA 3.0