I was trying to create a module for using the sensors that I recently bought. My module works well in simulation , synthesis and implementation. but when I used my module inside the top leveled module, I saw that while synthesizing it, it creates some registers outside it's module. With trial and error I found out that the problem is from a sequence of arithmetic operations.
module Sensor_handle_dev1(
input logic i_clk , i_reset , i_echo,
output logic o_trg,
output logic[7:0] o_distance , sensorNum
);
assign sensorNum = 8'b1;
logic[1:0] IdleState , CatchEchoState , CountState , PackUpState;
assign IdleState = 2'b00;
assign CatchEchoState = 2'b01;
assign CountState = 2'b10;
assign PackUpState = 2'b11;
logic next_trg;
logic[1:0] curState , next_state;
logic[31:0] l_count , next_count;
logic[7:0] next_distance;
always @( posedge i_clk )
begin
if ( i_reset == 1'b1 )
begin
curState <= IdleState;
o_trg <= 0;
o_distance <= 0;
l_count <= 0;
end
else
begin
curState <= next_state;
l_count <= next_count;
o_distance <= next_distance;
o_trg <= next_trg;
end
end
always_comb
begin
next_trg = o_trg; // <-- default value is flopped value
next_distance = o_distance; // <-- default value is flopped value
next_count = l_count;
case(curState)
IdleState:
begin
next_count = 0;
next_trg = 1;
next_count = 0;
next_distance = 0;
//# trig wait
next_state = CatchEchoState;
end
CatchEchoState:
begin
next_trg = 0;
if ( i_echo == 1 )
begin
if( l_count < 32'b101101110001101100000000 )
begin
next_count = l_count + 1;
next_state = CatchEchoState;
end
else
begin
next_state = IdleState;
end
end
else
begin
next_state = CountState;
end
end
CountState:
begin
// here is the problem
//next_distance = ((l_count * 68) / 100000) + 1;
next_state = IdleState;
end
default:
next_state = IdleState;
endcase
end
endmodule
and the schematic looks like this
how can I implement to evade this situation ?
Best Answer
My guess is it requires more than one clock to calculate
((l_count * 68) / 100000) + 1
. There should be a warning about this in the synthesis/timing report.First thing that can be done is reduce the 68/100000 to 17/25000. The synthesizer should have done the same optimization.
Then split the calculation across multiple clocks. Notice in the
CatchEchoState
state whennext_state = CountState;
,next_count
is not being updated. Some of the distance calculation can be move to this condition.In the example below I moved the multiplication to the
CatchEchoState
and kept the division in theCountState
. Check the timing report. If the timing can be meet for partial calc and not the final calc, then include a division of factor of 25000 (ex 40 is a factor of 25000, which then becomesnext_count = (l_count * 17) / 40;
...next_distance = (l_count / 625) + 1;
). If timing still cannot be meet, consider to incrementnext_count
by 17 instead of 1, thereby eliminating the dedicated multiplication logic.If there is still an issue, then it likely has to do with your top level module or your synthesis configurations.
FYI:
o_distance
andnext_distance
need to be at least 24-bits wide to store the maximum unsigned value (assuming maxl_count
value is 11,999,999). Looks like this is what is going on in the screenshot, but it is 8-bits in the provided RTL.