Forum Discussion

Nikolai's avatar
Nikolai
Icon for New Contributor rankNew Contributor
4 years ago
Solved

verilog register gets corrupted

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

5 Replies

  • sstrell's avatar
    sstrell
    Icon for Super Contributor rankSuper Contributor

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

    • Nikolai's avatar
      Nikolai
      Icon for New Contributor rankNew Contributor

      fail.jpg transition 146

      fail2.jpg transition 316

      fail3.jpg transition 1026

  • sstrell's avatar
    sstrell
    Icon for Super Contributor rankSuper Contributor

    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?

  • GLees's avatar
    GLees
    Icon for Contributor rankContributor

    Are all your inputs registered to the clock?

    • Nikolai's avatar
      Nikolai
      Icon for New Contributor rankNew Contributor

      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;