Strange behavior of Mux grammar in Verilog

C

Candida Ferreira

Guest
Hello Everyone,

I'm building a 3-mux grammar in Verilog and just realized that it is not
giving the expeted results. For instance, the code below generated using
only AND, OR, and NOT, is a solution to the Majority(x,y,z) function.

---

module gepModel (d, result);
input [0:2] d;
output result;
reg result;

reg [0:1] gene;

initial begin

d[0] = 1'b1;
d[1] = 1'b0;
d[2] = 1'b1;

fork : geneEvaluation

gene[0] = ((d[2] & d[1]) | (d[0] & d[2]));
gene[1] = (d[0] & d[1]);

join

result = (gene[0] | gene[1]);

end

endmodule

---

The following code is a straightforward translation of this code to a Mux
grammar, but curiously it is no longer a solution to the majority function:

---

module gepModel (d, result);
input [0:2] d;
output result;
reg result;

reg [0:1] gene;

initial begin

d[0] = 1'b1;
d[1] = 1'b0;
d[2] = 1'b1;

fork : geneEvaluation

gene[0] =
gepMux(gepMux(d[2],d[2],d[1]),gepMux(d[0],d[0],d[2]),gepMux(d[2],d[2],d[1]));
gene[1] = gepMux(d[0],d[0],d[1]);

join

result = gepMux(gene[0],gene[1],gene[0]);

end

function gepMux;
input x, y, z;
begin
gepMux = (((~(x)) & y) | (x & z));
end
endfunction

endmodule

---

The most interesting is that a similar Mux grammar in VHDL behaves exactly
as expected and gives the correct answer:



library IEEE;
use IEEE.std_logic_1164.all;

entity gepModel is
port (d: in bit_vector (0 to 2);
result: out bit);
end gepModel;

architecture gepGeneratedCode of gepModel is

function gepMux(x, y, z: bit) return bit is
begin
return (((not(x)) and y) or (x and z));
end gepMux;

signal gene: bit_vector (0 to 1);

begin

gene(0) <=
gepMux(gepMux(d(2),d(2),d(1)),gepMux(d(0),d(0),d(2)),gepMux(d(2),d(2),d(1)));
gene(1) <= gepMux(d(0),d(0),d(1));

result <= gepMux(gene(0),gene(1),gene(0));

end architecture gepGeneratedCode;

---

Any ideas why this is happening in Verilog? Am I doing something wrong? This
happens fairly frequently and so far I've been unable to understand the
reason for this.

Many thanks.

Candida

---
Candida Ferreira, Ph.D.
Chief Scientist, Gepsoft
http://www.gene-expression-programming.com/author.asp

GEP: Mathematical Modeling by an Artificial Intelligence
(Springer Verlag edition 2006)
http://www.gene-expression-programming.com/Books/index.asp
Online Version:
http://www.gene-expression-programming.com/GepBook/Introduction.htm

Modeling Software:
http://www.gepsoft.com/
 
I only glanced at your example, but have a guess about a possible
problem.

Your Verilog simulator may have a bug when you call a function and one
or more of the actual argument expressions calls the same function.
Some simulators apparently don't do the evaluations in the right order
and overwrite the arguments for one call with the arguments for
another.

If this is your problem, and you can't get your simulator fixed, there
are some possible workarounds. Simply declaring the function automatic
might work. Or you can force correct ordering by evaluating each
function call into an intermediate temporary, and passing that to the
later call.
 
Sorry, but there were some bits used for testing that went into the code
examples. The correct versions follow:

Solution to the majority function using AND and OR gates:

module gepModel (d, result);
input [0:2] d;
output result;
reg result;

reg [0:1] gene;

initial begin

fork : geneEvaluation

gene[0] = ((d[2] & d[1]) | (d[0] & d[2]));
gene[1] = (d[0] & d[1]);

join

result = (gene[0] | gene[1]);

end

endmodule

---

The same code automatically translated using a 3-mux grammar that should
produce tha same output but does not:

module gepModel (d, result);
input [0:2] d;
output result;
reg result;

reg [0:1] gene;

initial begin

fork : geneEvaluation

gene[0] =
gepMux(gepMux(d[2],d[2],d[1]),gepMux(d[0],d[0],d[2]),gepMux(d[2],d[2],d[1]));
gene[1] = gepMux(d[0],d[0],d[1]);

join

result = gepMux(gene[0],gene[1],gene[0]);

end

function gepMux;
input x, y, z;
begin
gepMux = (((~(x)) & y) | (x & z));
end
endfunction

endmodule

---

And the similar VHDL version that behaves exactly as expected and gives the
correct output:

library IEEE;
use IEEE.std_logic_1164.all;

entity gepModel is
port (d: in bit_vector (0 to 2);
result: out bit);
end gepModel;

architecture gepGeneratedCode of gepModel is

function gepMux(x, y, z: bit) return bit is
begin
return (((not(x)) and y) or (x and z));
end gepMux;

signal gene: bit_vector (0 to 1);

begin

gene(0) <=
gepMux(gepMux(d(2),d(2),d(1)),gepMux(d(0),d(0),d(2)),gepMux(d(2),d(2),d(1)));
gene(1) <= gepMux(d(0),d(0),d(1));

result <= gepMux(gene(0),gene(1),gene(0));

end architecture gepGeneratedCode;


"Candida Ferreira" <cferreira@seehomepage.com> wrote in message
news:Wx09g.272429$8Q3.114789@fe1.news.blueyonder.co.uk...
Hello Everyone,

I'm building a 3-mux grammar in Verilog and just realized that it is not
giving the expeted results. For instance, the code below generated using
only AND, OR, and NOT, is a solution to the Majority(x,y,z) function.

---

module gepModel (d, result);
input [0:2] d;
output result;
reg result;

reg [0:1] gene;

initial begin

d[0] = 1'b1;
d[1] = 1'b0;
d[2] = 1'b1;

fork : geneEvaluation

gene[0] = ((d[2] & d[1]) | (d[0] & d[2]));
gene[1] = (d[0] & d[1]);

join

result = (gene[0] | gene[1]);

end

endmodule

---

The following code is a straightforward translation of this code to a Mux
grammar, but curiously it is no longer a solution to the majority
function:

---

module gepModel (d, result);
input [0:2] d;
output result;
reg result;

reg [0:1] gene;

initial begin

d[0] = 1'b1;
d[1] = 1'b0;
d[2] = 1'b1;

fork : geneEvaluation

gene[0] =
gepMux(gepMux(d[2],d[2],d[1]),gepMux(d[0],d[0],d[2]),gepMux(d[2],d[2],d[1]));
gene[1] = gepMux(d[0],d[0],d[1]);

join

result = gepMux(gene[0],gene[1],gene[0]);

end

function gepMux;
input x, y, z;
begin
gepMux = (((~(x)) & y) | (x & z));
end
endfunction

endmodule

---

The most interesting is that a similar Mux grammar in VHDL behaves exactly
as expected and gives the correct answer:



library IEEE;
use IEEE.std_logic_1164.all;

entity gepModel is
port (d: in bit_vector (0 to 2);
result: out bit);
end gepModel;

architecture gepGeneratedCode of gepModel is

function gepMux(x, y, z: bit) return bit is
begin
return (((not(x)) and y) or (x and z));
end gepMux;

signal gene: bit_vector (0 to 1);

begin

gene(0) <=
gepMux(gepMux(d(2),d(2),d(1)),gepMux(d(0),d(0),d(2)),gepMux(d(2),d(2),d(1)));
gene(1) <= gepMux(d(0),d(0),d(1));

result <= gepMux(gene(0),gene(1),gene(0));

end architecture gepGeneratedCode;

---

Any ideas why this is happening in Verilog? Am I doing something wrong?
This happens fairly frequently and so far I've been unable to understand
the reason for this.

Many thanks.

Candida

---
Candida Ferreira, Ph.D.
Chief Scientist, Gepsoft
http://www.gene-expression-programming.com/author.asp

GEP: Mathematical Modeling by an Artificial Intelligence
(Springer Verlag edition 2006)
http://www.gene-expression-programming.com/Books/index.asp
Online Version:
http://www.gene-expression-programming.com/GepBook/Introduction.htm

Modeling Software:
http://www.gepsoft.com/
 
Candida Ferreira wrote:

And the similar VHDL version that behaves exactly as expected and gives the
correct output:
I'm a VHDL guy, so let's start by converting your
vhdl code to a single process architecture like this:
_______________________________________
architecture one_process of gepmodel is
begin
one : process (d) is
variable gene : bit_vector (0 to 1);
function gepMux(x, y, z : bit) return bit is
begin
return (((not(x)) and y) or (x and z));
end gepMux;

begin
gene(0) := gepMux(gepMux(d(2), d(2), d(1)),
gepMux(d(0), d(0), d(2)),
gepMux(d(2), d(2), d(1))
);
gene(1) := gepMux(d(0), d(0), d(1));
result <= gepMux(gene(0), gene(1), gene(0));
end process one;
end architecture one_process;


So now I can translate that into a single block
verilog module like this:
___________________________
module gepmodel(d, result);

input [0:2] d;
output result;
reg result;

always @(d)
begin: local
reg [0:1] gene_v;
gene_v[0] =
gepMux(gepMux(d[2],d[2],d[1]),
gepMux(d[0],d[0],d[2]),
gepMux(d[2],d[2],d[1]));
gene_v[1] = gepMux(d[0],d[0],d[1]);
result = gepMux(gene_v[0],gene_v[1],gene_v[0]);
end

function gepMux;
input x, y, z;
begin
gepMux = (((~(x)) & y) | (x & z));
end
endfunction
endmodule

Which looks like this:

http://home.comcast.net/~mike_treseler/gepmodel_v.pdf

-- Mike Treseler
 
Thank you to everyone that contributed to this discussion; your suggestions
have been really helpful. I contacted the provider of the simulator I was
using and it is indeed a bug with multi-level nested function calls where
one of the inputs is the same function.

Best wishes,

Candida
 

Welcome to EDABoard.com

Sponsor

Back
Top