Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
20638 Discussions

verilog register gets corrupted

Nikolai
Beginner
849 Views

Im trying to interface quadrature encoder with Terasic SoM eval board but got strange behaviour.

All works fine for a short while, but after it registers holding position/rotation became corrupted. Depending on rearragning same code in verilog file and speed of rotation only rotation register or both became corrupted. I've spent a few days trying to figure out what's wrong but without any success. Is there something I've missed? Behaviour is exaclty the same on two boards.

Verilog file with interface, signal tap images and full project attached. 

 

 

 module cui_amt (
	clk,
	reset_n,
		
	sensor_A,
	sensor_B,
	sensor_X,
	
	// Avalon slave
	read,
	write,
	address,
	readdata,
	writedata
);

parameter PPR = 8192;

 
input clk;
input reset_n; 
input sensor_A;
input sensor_B;
input sensor_X;
 
reg [31:0] position = 0;
reg [31:0] rotation = 0;
reg sync_lost;
reg got_zero;

// Avalon slave
// 0 - posiion
// 1 - rotation
// 2 - status
//   0 - sync_lost
//   1 - got zero
// 3 - control
//   1 - reset
input read;
input write;
input [1:0] address;
output [31:0] readdata;
input [31:0] writedata;

reg prev_A;
reg prev_B;
reg prev_X;

 
always @(posedge clk)
begin
	if (reset_n)
	begin
		if (read)
		begin
			case (address)
				0: begin
					readdata <= position;
				end
				1: begin
					readdata <= rotation;
				end
				2: begin
					readdata[0] <= sync_lost;
					readdata[1] <= got_zero;
					readdata[31:2] <= 0;
				end
			endcase
		end
	
		if (write && writedata == 1) // Reset command
		begin
			position <= 0;
			rotation <= 0;
			sync_lost <= 0;
			got_zero <= 0;
		end
		else
		begin
			// Quadrature
			// A 110011
			// B 011001
		
			if (sensor_X)
			begin
				got_zero <= 1;
			end
			
			if (sensor_A != prev_A || sensor_B != prev_B)
			begin
				if (prev_A == sensor_A)
				begin
					if ((prev_A == 1 && prev_B == 0) || (prev_A == 0 && prev_B == 1))
					begin
						position <= position - 1;
						rotation <= rotation != 0 ? (rotation - 1) : (PPR - 1);
					end
					else
					begin
						position <= position + 1;
						rotation <= rotation != (PPR - 1) ? (rotation + 1) : 0;
						
					end
					
					prev_B <= sensor_B;
				end
				else if (prev_B == sensor_B)
				begin
					if ((prev_B == 1 && prev_A == 1) || (prev_B == 0 && prev_A == 0))
					begin
						position <= position - 1;
						rotation <= rotation != 0 ? (rotation - 1) : (PPR - 1);
					end
					else
					begin
						position <= position + 1;
						rotation <= rotation != (PPR - 1) ? (rotation + 1) : 0;
					end
					
					prev_A <= sensor_A;
				end
				else
				begin
					prev_A <= sensor_A;
					prev_B <= sensor_B;
					sync_lost <= 1;
				end
			end
		end
	end
	else
	begin
		position <= 0;
		rotation <= 0;
		sync_lost <= 0;
		got_zero <= 0;
		prev_A <= sensor_A;
		prev_B <= sensor_B;
	end
end
 
 
 
 
endmodule

 

0 Kudos
1 Solution
GLees
New Contributor II
815 Views

Are all your inputs registered to the clock?

View solution in original post

0 Kudos
5 Replies
sstrell
Honored Contributor III
830 Views

Can you indicate where on your Signal Tap pictures you are getting unexpected behavior?

0 Kudos
Nikolai
Beginner
826 Views

fail.jpg transition 146

fail2.jpg transition 316

fail3.jpg transition 1026

0 Kudos
sstrell
Honored Contributor III
819 Views

I don't see any issues in the code, so it must be something else.  Is your design meeting timing?  Do you have a complete .sdc file for the design?

0 Kudos
GLees
New Contributor II
816 Views

Are all your inputs registered to the clock?

0 Kudos
Nikolai
Beginner
807 Views

Inputs are input pins without any clock.

 

Assigning them to registers (with 1 clock period delay, but it does not matter as input is much slower than clock) solved the problem.

cur_A <= sensor_A;
cur_B <= sensor_B;
cur_X <= sensor_X;

 

0 Kudos
Reply