I'm trying to complete an assignment using Verilog, the details aren't too important, except that it must be a combinatorial design. Unfortunately I'm running into what I assume is the hardware getting stuck in an infinite loop: the following signal(s) form a combinatorial loop:
the following signal(s) form a combinatorial loop: _n0112, GND_2_o_GND_2_o_mux_66_OUT<1>, mode[2]_GND_2_o_equal_75_o, mode<1>, ran0, mode[2]_GND_2_o_equal_75_o_mmx_out.
Here's my code(I know its messy and can be done better, I'm working on it):
module seven_seg(
input [3:0] a,
input [3:0] b,
input [3:0] c,
input [3:0] d,
input [1:0] mux,
output [6:0] out,
output an0,
output an1,
output an2,
output an3
);
wire [6:0] x;
wire [6:0] y;
wire [6:0] i;
wire [6:0] j;
reg [2:0] mode = 3'b000;
reg ran0;
reg ran1;
reg ran2;
reg ran3;
parameter zero = 7'b1000000;
parameter one = 7'b1001111;
parameter two = 7'b0010010;
parameter three = 7'b0000110;
parameter four = 7'b1001100;
parameter five = 7'b0100100;
parameter six = 7'b0100000;
parameter seven = 7'b0011111;
parameter eight = 7'b0000000;
parameter nine = 7'b0000100;
parameter ten = 7'b0001000;
parameter eleven = 7'b0000000;
parameter twelve = 7'b0110001;
parameter thirteen= 7'b0000001;
parameter fourteen= 7'b0110000;
parameter fifteen = 7'b0111000;
assign c = 4'b0001;
assign d = 4'b0000;
assign x = (a == 4'b0000) ? zero :
(a == 4'b0001) ? one :
(a == 4'b0010) ? two :
(a == 4'b0011) ? three :
(a == 4'b0100) ? four :
(a == 4'b0101) ? five :
(a == 4'b0110) ? six :
(a == 4'b0111) ? seven :
(a == 4'b1000) ? eight :
(a == 4'b1001) ? nine :
(a == 4'b1010) ? ten :
(a == 4'b1011) ? eleven :
(a == 4'b1100) ? twelve :
(a == 4'b1101) ? thirteen :
(a == 4'b1111) ? fourteen : fifteen;
assign y = (b == 4'b0000) ? zero :
(b == 4'b0001) ? one :
(b == 4'b0010) ? two :
(b == 4'b0011) ? three :
(b == 4'b0100) ? four :
(b == 4'b0101) ? five :
(b == 4'b0110) ? six :
(b == 4'b0111) ? seven :
(b == 4'b1000) ? eight :
(b == 4'b1001) ? nine :
(b == 4'b1010) ? ten :
(b == 4'b1011) ? eleven :
(b == 4'b1100) ? twelve :
(b == 4'b1101) ? thirteen :
(b == 4'b1111) ? fourteen : fifteen;
always @(*)
begin
if(mux == 2'b00)
if(mode == 3'b000)
mode = 3'b001;
else if(mode == 3'b010)
mode = 3'b011;
else mode = 3'b000;
else if(mux == 2'b01)
mode = 3'b000;
else if(mux == 2'b10)
mode = 3'b010;
else //if(mux == 2'b11)
mode = 3'b100;
end
always @(*)
begin
if(mode == 3'b000)
begin
ran0 = 0;
ran1 = 1;
ran2 = 1;
ran3 = 1;
end
else if(mode == 3'b001)
begin
ran0 = 1;
ran1 = 0;
ran2 = 1;
ran3 = 1;
end
else if(mode == 3'b010)
begin
ran0 = 1;
ran1 = 1;
ran2 = 0;
ran3 = 1;
end
else if(mode == 3'b011)//011
begin
ran0 = 1;
ran1 = 1;
ran2 = 1;
ran3 = 0;
end
else
begin
ran0 = 0;
ran1 = 0;
ran2 = 0;
ran3 = 1;
end
end
assign an0 = ran0;
assign an1 = ran1;
assign an2 = ran2;
assign an3 = ran3;
assign out = x;
endmodule
So I think I understand the problem, it has to do with this block:
always @(mux)
begin
if(mux == 2'b00)
if(mode == 3'b000)
mode = 3'b001;
else if(mode == 3'b010)
mode = 3'b011;
else mode = 3'b000;
else if(mux == 2'b01)
mode = 3'b000;
else if(mux == 2'b10)
mode = 3'b010;
else //if(mux == 2'b11)
mode = 3'b100;
end
The synthesizer ends up putting 'mode' into the sensitivity list for some reason, and I believe that's why it ends up in a loop. I would appreciate some more insight as to what's going on here.
Thanks!
FSM
2 Answers 2
Whether you put it the sensitivity list or not, the mode variable depends on the mode variable. See where I point it out below.
Pretend you are trying to make that hardware. How do you make that work? Remember there is not clock here, so you would have to create a combinatorial loop, right?
always @(mux)
begin
if(mux == 2'b00)
if(mode == 3'b000) <---- HERE
mode = 3'b001;
else if(mode == 3'b010) <----- HERE
mode = 3'b011;
else mode = 3'b000;
else if(mux == 2'b01)
mode = 3'b000;
else if(mux == 2'b10)
mode = 3'b010;
else //if(mux == 2'b11)
mode = 3'b100;
end
Walk through the design to understand what does this do in the situation where mux is starting at 2'b01 then goes to 2'b00? When mux = 2'b01, mode = 3'b000. Then when mux goes to 2'b00, it looks to see that mode is 3'b000, and changes mode to be 3'b001. Then it immediately sees that mux is 2'b00 and mode is 3'b001 and changes mode to 3'b000, then it sees that mux is 2'b00 and mode is 3'b000 and changes mode to 3'b001. This is a combinatorial loop.
As an aside, let me explain what the sensitivity list is exactly. Originally, verilog was designed as a modelling language. The sensitivity list was a way to tell the simulator dependencies. This helped to reduce unneeded processing by letting the simulator not look into the code for each always block to determine if it needed to run it.
However, today verilog is mostly used to infer logic, so the sensitivity list is really not as useful as it was. The synthesis tool will look at the code and determine that you forgot something. You can't trick it by not putting it in the list. It is a dependency according to your logic and the synthesis tool will treat it as such. It probably even helpfully gave you a warning that you forgot it.
-
\$\begingroup\$ I tried adding a lastMode reg and using that in the stead of the 'if(mode == 3'b000)' -> if(lastMode == 3'b000), but it's still not working properly. I don't understand why. \$\endgroup\$user3474353– user34743532015年01月18日 05:45:57 +00:00Commented Jan 18, 2015 at 5:45
-
\$\begingroup\$ If last mode depends on mode without a clock delay, it is still a combinatorial loop. What do you want it to do when mux is 3'b000? \$\endgroup\$caveman– caveman2015年01月18日 06:05:39 +00:00Commented Jan 18, 2015 at 6:05
-
\$\begingroup\$ When mux is 2'b00, the next state depends on whether mux was 2'b01 or 2'b10. I'm just not sure of how to implement that without getting stuck in a loop. \$\endgroup\$user3474353– user34743532015年01月18日 21:59:23 +00:00Commented Jan 18, 2015 at 21:59
-
\$\begingroup\$ Seems like you need to implement a latch with combinatorial logic. Please update your original question to show the state machine. Without that, it is very difficult to help. \$\endgroup\$caveman– caveman2015年01月18日 22:47:50 +00:00Commented Jan 18, 2015 at 22:47
-
\$\begingroup\$ Added it, hope it's not too messy. \$\endgroup\$user3474353– user34743532015年01月18日 23:47:53 +00:00Commented Jan 18, 2015 at 23:47
Your code doesn't match your (incomplete) graph. Here is a table form that shows missing transitions explicitly.
Mode\Mux 2'b00 2'b01 2'b10 2'b11
3'b000 3'b001 3'b000 3'b010 3'b100
3'b001 3'b001 3'b000 3'b010 3'b100
3'b010 3'b011 3'b000 3'b010 3'b100
3'b011 3'b011 3'b000 3'b010 3'b100
3'b100 ? ? ? 3'b100
For example, you have Mode = 2'b00, Mux = 3'b011 going to 3'b000, which is where you have a combinatorial loop.
? :
construct often infers an explicit 2:1 mux in synthesize. Therefor your code infers a 15 deep chain of 2:1 muxes. It is recommended to usecase
statement, allowing the synthesizer can choose the mux configuration (ex: one 16:1, or two 8:1 + one 2:1, five 4:1, etc). Alsoreg
doesn't mean flop, if you declareoutput an0
asoutput reg an0
then you can assignan0
directly in your always block and omit theassign an0 = ran0
(which is just extra code, synthesis will not even treat the assign as a buffer). \$\endgroup\$