For a project, I have to determine the RPM of a turning resolver. I can correctly read the angular position of the resolver as as a hex number via an RDC. This number is then converted into a 14-bit decimal number and then sent to a 7-segment display. To give an idea how this works, when the resolver is at 180 degrees, the RDC will return 0x8000, when it is at 359 degrees, the RDC will return 0xFFFF, and at 0 degrees, the RDC will return 0x0000. The separate module then converts the 16-bit values to a 14-bit value.
I am calculating the RPM in its own Verilog module called RPM_calc. The angular position of the resolver is being read at 1000Hz. Inside RPM_calc, I have clock that samples the position 4 times a second every posedge. Every time this posedge hits, it reads the position data being fed in and moves the previous position into a different register. These two registers are subtracted, and the position difference over time (0.25s) is then used to calculate the RPM. The RPM direction is not displayed, and if the direction results in a negative number, it is converted from 2s complement to a regular number. The res input just determines whether I want a 10 or 12-bit resolution from the RDC. My verilog code is shown below.
module RPM_calc( input clk_i, //1000Hz sample clock input res, input [13:0] position_i, output [13:0] RPM_o, output sample_o ); reg [8:0] clk_4hz_counter = 0; reg clk_4hz = 0; reg [13:0] position_reg; reg [13:0] prev_position_reg = 0; always@(posedge clk_i) begin //4Hz clock generator clk_4hz_counter <= clk_4hz_counter + 1; if(clk_4hz_counter == 125) begin clk_4hz_counter <= 0; clk_4hz = ~clk_4hz; end end always@(posedge clk_4hz) begin position_reg <= position_i; prev_position_reg <= position_reg; end //2s complement wires wire [13:0] deltaP; wire [13:0] abs_deltaP; assign deltaP = position_reg-prev_position_reg; assign abs_deltaP = (deltaP)?(~deltaP+1):(deltaP); //if res is 0, divide by 2^12, else divide by 2^10. 240 = 60*(4Hz) assign RPM_o = res? 240*(abs_deltaP)/1024: 240*(abs_deltaP)/4096; assign sample_o = clk_i; endmodule
The problem I ran into is when the RDC rolls over at 360 degrees. For example, if I sample at 350 degrees, and 0.25s later, I sample at 10 degrees when travelling clockwise, my module thinks I traveled 340 degrees in 0.25s, which is incorrect. I need a way of determining what the correct RPM is when two samples happen with a rollover in between. Does anyone have an idea of how to do this?