- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have a verilog module designed to process an encoder signal, I have been having problems so have cut it down to a minimum that demonstrates the kind of problem. File is attached (and cited below).
The code receives a clk signal (25MHz output of a PLL), and a time (now, count of a 1MHz clock). enc is an input from an encoder on a motor (provides pulses approximately 20kHz).
The if block is activated on a negative edge of the encoder. For the majority of pulses the code behaves correctly and all code in the block is executed. Occasionally, some or none of the code is executed. I do not understand how this can be the case.
This image shows a signal tap of most of the block's signals. At just after t=-1280, there is a negative edge, the enc_pulse is taken high, but the count is not incremented, the enc_prev_time and enc_time are not updated.
The image also shows a 'well-behaving' edge just after t=-2560.
Could someone explain how this can be?
module encoder (
input clk,
input enc,
input [31:0] now,
output reg [15:0] count,
output reg enc_pulse,
output missed_enc
);
reg enc_prev;
reg marker_prev;
reg new_marker;
reg [31:0] enc_time;
reg [31:0] enc_prev_time;
initial begin
count <= 16'd512; // Start count mid rev. First rev will be invalid.
enc_pulse <= 0;
end
assign missed_enc = (enc_time - enc_prev_time) > 64;
always @ (posedge clk) begin
if (enc == 0 && enc_prev == 1) begin // trigger on encoder falling edge
enc_pulse = 1;
count = count + 16'd1;
enc_prev_time = enc_time;
enc_time = now;
end
else begin
enc_pulse = 0;
end
enc_prev = enc;
end
endmodule
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It's hard to tell without zooming in, but it looks like enc and enc_prev are going low simultaneously, so they wouldn't trigger the if statement at all. You might be seeing glitches because enc is not registered. It looks like a truly asynchronous input, so there's no guarantees with that if statement. I'd register enc and then do the if check.
If you do, you might also think about doing negedge enc in the sensitivity list.
#iwork4intel
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It's hard to tell without zooming in, but it looks like enc and enc_prev are going low simultaneously, so they wouldn't trigger the if statement at all. You might be seeing glitches because enc is not registered. It looks like a truly asynchronous input, so there's no guarantees with that if statement. I'd register enc and then do the if check.
If you do, you might also think about doing negedge enc in the sensitivity list.
#iwork4intel
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for the reply.
The enc and enc_prev are not quite simultaneous, since enc_prev is enc clocked at the next clock edge.
I have zoomed in to show it more clearly.
What is truly confusing me is if block has 4 lines.
- enc_pulse is taken high.
- count is incremented.
- enc_prev_time becomes enc_time.
- enc_time becomes now.
As you can see from the diagram (1) is being run, but (2-4) are not. How can this be?
n.b. I am currently using blocking assignments. I originally used non-blocking, but changed during my investigation. It made no difference.
if (enc == 0 && enc_prev == 1) begin // trigger on encoder falling edge
enc_pulse = 1;
count = count + 16'd1;
enc_prev_time = enc_time;
enc_time = now;
end
I'm relatively new to verilog. What do you mean exactly by "registering enc"?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I've worked out what you mean by "registering" by giving it more thought.
The code below does what I think you suggested. The 'missing_enc' line is my error detector that I trigger from in Signal Tap. This never triggers, so I think this is fixed. The alternative is that I have broken my error detector.
module encoder (
input clk,
input enc,
input [31:0] now,
output reg [15:0] count,
output enc_pulse,
output missed_enc
);
reg enc_reg;
reg enc_prev;
reg [31:0] enc_time;
reg [31:0] enc_prev_time;
assign enc_pulse = enc_prev & !enc_reg;
assign missed_enc = (enc_time - enc_prev_time) > 64;
// No initial block. First rev will always be invalid anyway.
// System has no interest until up to speed.
always @ (posedge clk) begin
enc_prev <= enc_reg;
enc_reg <= enc;
end
always @ (negedge enc_reg) begin
count <= count + 16'd1;
enc_prev_time <= enc_time;
enc_time <= now;
end
endmodule
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes, this is what I was talking about. Glad it's working correctly now.
#iwork4intel

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page