Reply by Kevin Simonson September 28, 20202020-09-28
Gtwrek (Mark): "Like another poster indicated - you're coding at a very low level. Instatiating 'xor2' primitives and the like is quite low level. Just inline the expression using the verilog '^', '|', '&', etc operators." What's wrong with writing Verilog at a low level? If someone has a feel for how her/his design should work at a low level, is there something wrong with coding it at that level? If so, what is wrong with it?

"Change your generate case() to a procedural case()." What exactly is a procedural case, and how can I find out about it?
Reply by gtwrek September 25, 20202020-09-25
In article <071797c0-bfc0-4df1-b23e-f1519230330en@googlegroups.com>,
Kevin Simonson  <kvnsmnsn@hotmail.com> wrote:
>module neilson > #( parameter nmBits = 1) > ( output lssThn > , input [ nmBits-1:0] leftOp > , input [ nmBits-1:0] rightOp); > >typedef enum { CORNER, E_LEAF, N_LEAF, SIDE, E_INTERIOR, N_INTERIOR } nodeType; > >localparam integer nmNodes = 2 * nmBits - 1; >localparam integer nmLevels = $clog2( nmBits) + 1; >localparam integer nmRships = 2 * nmNodes - nmLevels; > >nodeType ndTypes [ nmNodes:1]; >integer inLows [ nmNodes:1]; >integer inHighs [ nmBits-1:1]; >integer outs [ nmNodes:1]; >integer bases [ nmLevels:0]; >wire rships [ nmRships:1]; >wire ntRght; >genvar ix; > >function automatic integer fillSubtree ( input integer vrtcl > , input integer hrzntl > , input bit equal); > integer rsltLw; > integer rsltHh; > integer ndIx; > integer rlIx; > integer vr; > integer hz; > integer twice; > integer nxVr; > bit nxEq; > begin > ndIx = (1 << vrtcl) + (hrzntl << vrtcl + 1); > vr = vrtcl; > hz = hrzntl; > while (nmNodes < ndIx) > begin > vr = vr - 1; > hz <<= 1; > ndIx = (1 << vr) + (hz << vr + 1); > end > rlIx = bases[ vr] + (hz << 1); > fillSubtree = rlIx; > if (0 < vr) > begin > twice = hz << 1; > nxEq = 0 == hz || ! equal; > nxVr = vr - 1; > rsltLw = fillSubtree( nxVr, twice , nxEq); > rsltHh = fillSubtree( nxVr, twice + 1, nxEq); > ndTypes[ ndIx] = hz == 0 ? SIDE : equal ? E_INTERIOR : N_INTERIOR; > inLows[ ndIx] = rsltLw; > inHighs[ ndIx >> 1] = rsltHh; > outs[ ndIx] = rlIx; > end > else > begin > ndTypes[ ndIx] = hz == 0 ? CORNER : equal ? E_LEAF : N_LEAF; > inLows[ ndIx] = hz; > outs[ ndIx] = rlIx; > end > end >endfunction > >initial >begin > integer lvl; > bases[ 0] = 1; > for (lvl = 1; lvl <= nmLevels; lvl = lvl + 1) > begin > bases[ lvl] = bases[ lvl - 1] + ((nmNodes + (1 << lvl - 1) >> lvl << 1) - 1); > end > fillSubtree( nmLevels - 1, 0, true); >end > >generate > for (ix = 1; ix <= nmNodes; ix = ix + 1) > begin > integer inLow = inLows[ ix]; > integer inHigh = inHighs[ ix >> 1]; > integer out = outs[ ix]; > case (ndTypes[ ix]) > E_INTERIOR > : begin > nor2 pio( rships[ out - 1], rships[ inLow - 1], rships[ inHigh - 1]); > mplex pim( rships[ out], rships[ inHigh - 1], rships[ inHigh], rships[ inLow]); > end > N_INTERIOR > : begin > nand2 mia( rships[ out - 1], rships[ inLow - 1], rships[ inHigh - 1]); > mplex mim( rships[ out], rships[ inHigh - 1], rships[ inLow], rships[ inHigh]); > end > SIDE > : mplex sm( rships[ out], rships[ inHigh - 1], rships[ inLow], rships[ inHigh]); > E_LEAF > : begin > equ2 ple( rships[ out], leftOp[ inLow], rightOp[ inLow]); > assign rships[ out - 1] = rightOp[ inLow]; > end > N_LEAF > : begin > xor2 mlx( rships[ out], leftOp[ inLow], rightOp[ inLow]); > assign rships[ out - 1] = rightOp[ inLow]; > end > CORNER > : begin > nt1 cn( ntRght, rightOp[ inLow]); > nor2 co( rships[ out], leftOp[ inLow], ntRght); > end > endcase > end >endgenerate >assign lssThn = rships[ bases[ nmLevels - 1]]; > >endmodule
Your problem now is the generate case() statements. Generate case() statements agruments DO need to be parameters. (I know I told you to change it from a localparm to a variable - but I missed the generate case() usage) However, I still don't think you should make these parameters. Like another poster indicated - you're coding at a very low level. Instatiating "xor2" primitives and the like is quite low level. Just inline the expression using the verilog "^", "|", "&", etc operators. Change your generate case() to a procedural case(). Another comment on style. Your function should really not be both sampling, and manipulating non-local variables. Write your function with a stable API that passes in the neccesary arguments, and returns the neccesary outputs. Manipulating global variables, makes the function call pretty purposeless. There's no reason at all for it to be a function if it's just manipulating global variables. Just move it down to the procedural block if you don't want to solidify the API. Or put it in it's own procedural block. Change the function to: always @* begin //function contents that manipulate ndTypes[]; end Regards, Mark
Reply by Kevin Simonson September 25, 20202020-09-25
D:\Hf\Verilog\Unpacked\Src\Common>\Icarus\bin\iverilog -g2009 -o neilson.vvp neilson.sv
neilson.sv:84: error: Unable to bind parameter `ndTypes[ix]' in `neilson.$gen1[1]'
neilson.sv:84: error: Cannot evaluate genvar case expression: ndTypes[ix]
2 error(s) during elaboration.

D:\Hf\Verilog\Unpacked\Src\Common>
Reply by Kevin Simonson September 25, 20202020-09-25
module neilson
  #( parameter nmBits = 1)
  ( output              lssThn
  , input [ nmBits-1:0] leftOp
  , input [ nmBits-1:0] rightOp);

typedef enum { CORNER, E_LEAF, N_LEAF, SIDE, E_INTERIOR, N_INTERIOR } nodeType;

localparam integer nmNodes  = 2 * nmBits - 1;
localparam integer nmLevels = $clog2( nmBits) + 1;
localparam integer nmRships = 2 * nmNodes - nmLevels;

nodeType ndTypes [  nmNodes:1];
integer  inLows  [  nmNodes:1];
integer  inHighs [ nmBits-1:1];
integer  outs    [  nmNodes:1];
integer  bases   [ nmLevels:0];
wire     rships  [ nmRships:1];
wire     ntRght;
genvar   ix;

function automatic integer fillSubtree ( input integer vrtcl
                                       , input integer hrzntl
                                       , input     bit equal);
    integer rsltLw;
    integer rsltHh;
    integer ndIx;
    integer rlIx;
    integer vr;
    integer hz;
    integer twice;
    integer nxVr;
    bit nxEq;
  begin
    ndIx = (1 << vrtcl) + (hrzntl << vrtcl + 1);
    vr   = vrtcl;
    hz   = hrzntl;
    while (nmNodes < ndIx)
    begin
      vr   = vr - 1;
      hz <<= 1;
      ndIx = (1 << vr) + (hz << vr + 1);
    end
    rlIx        = bases[ vr] + (hz << 1);
    fillSubtree = rlIx;
    if (0 < vr)
    begin
      twice               = hz << 1;
      nxEq                = 0 == hz || ! equal;
      nxVr                = vr - 1;
      rsltLw              = fillSubtree( nxVr, twice    , nxEq);
      rsltHh              = fillSubtree( nxVr, twice + 1, nxEq);
      ndTypes[ ndIx]      = hz == 0 ? SIDE : equal ? E_INTERIOR : N_INTERIOR;
      inLows[ ndIx]       = rsltLw;
      inHighs[ ndIx >> 1] = rsltHh;
      outs[ ndIx]         = rlIx;
    end
    else
    begin
      ndTypes[ ndIx] = hz == 0 ? CORNER : equal ? E_LEAF : N_LEAF;
      inLows[ ndIx]  = hz;
      outs[ ndIx]    = rlIx;
    end
  end
endfunction

initial
begin
  integer lvl;
  bases[ 0]   = 1;
  for (lvl = 1; lvl <= nmLevels; lvl = lvl + 1)
  begin
    bases[ lvl] = bases[ lvl - 1] + ((nmNodes + (1 << lvl - 1) >> lvl << 1) - 1);
  end
  fillSubtree( nmLevels - 1, 0, true);
end

generate
  for (ix = 1; ix <= nmNodes; ix = ix + 1)
  begin
    integer inLow  = inLows[ ix];
    integer inHigh = inHighs[ ix >> 1];
    integer out    = outs[ ix];
    case (ndTypes[ ix])
      E_INTERIOR
    : begin
        nor2 pio( rships[ out - 1], rships[ inLow - 1], rships[ inHigh - 1]);
        mplex pim( rships[ out], rships[ inHigh - 1], rships[ inHigh], rships[ inLow]);
      end
      N_INTERIOR
    : begin
        nand2 mia( rships[ out - 1], rships[ inLow - 1], rships[ inHigh - 1]);
        mplex mim( rships[ out], rships[ inHigh - 1], rships[ inLow], rships[ inHigh]);
      end
      SIDE
    : mplex sm( rships[ out], rships[ inHigh - 1], rships[ inLow], rships[ inHigh]);
      E_LEAF
    : begin
        equ2 ple( rships[ out], leftOp[ inLow], rightOp[ inLow]);
        assign rships[ out - 1] = rightOp[ inLow];
      end
      N_LEAF
    : begin
        xor2 mlx( rships[ out], leftOp[ inLow], rightOp[ inLow]);
        assign rships[ out - 1] = rightOp[ inLow];
      end
      CORNER
    : begin
        nt1 cn( ntRght, rightOp[ inLow]);
        nor2 co( rships[ out], leftOp[ inLow], ntRght);
      end
    endcase
  end
endgenerate
assign lssThn = rships[ bases[ nmLevels - 1]];

endmodule
Reply by Kevin Simonson September 25, 20202020-09-25
Okay, I got rid of (struct) type (node) and now just have four arrays, (ndTypes), (inLows), (inHighs), and (outs). Then I used Icarus to simulate it, and only got one error message. Any idea how to get rid of that one error message? As before, the next post I make will be of my "neilson.sv" Verilog file, and the post after that will be the results of my attempt to simulate it.
Reply by gtwrek September 24, 20202020-09-24
In article <rkibc5$jl0$1@dont-email.me>, gtwrek <gtwrek@sonic.net> wrote:
>In article <949f0dc7-6333-4b8e-b631-c4c82b825b04n@googlegroups.com>, >Kevin Simonson <kvnsmnsn@hotmail.com> wrote: >>localparam node nodes [ nmNodes:1]; >>localparam integer bases [ nmLevels:0]; > >Going to break feedback down into parts... > >A localparam without an assignment makes no sense, and is likely a >syntax error. Did you mean for these to be variables instead of >localparams?
Briefly reading through the rest of the code, and how you're using/manipulating "nodes" and "bases" - I think this is the root cause of your troubles. Just try and make these variables instead of localparams. I don't think there's any reason why they must be localparams. Regards, Mark
Reply by gtwrek September 24, 20202020-09-24
In article <949f0dc7-6333-4b8e-b631-c4c82b825b04n@googlegroups.com>,
Kevin Simonson  <kvnsmnsn@hotmail.com> wrote:
>localparam node nodes [ nmNodes:1]; >localparam integer bases [ nmLevels:0];
Going to break feedback down into parts... A localparam without an assignment makes no sense, and is likely a syntax error. Did you mean for these to be variables instead of localparams? Regards, Mark
Reply by Kevin Neilson September 23, 20202020-09-23
On Wednesday, September 23, 2020 at 4:45:55 PM UTC-6, Kevin Simonson wrote:
> module forMark=20 > #( parameter nmBits =3D 1)=20 > ( output lssThn=20 > , input [ nmBits-1:0] leftOp=20 > , input [ nmBits-1:0] rightOp); > typedef enum { CORNER, E_LEAF, N_LEAF, SIDE, E_INTERIOR, N_INTERIOR } nod=
eType;=20
> typedef struct packed=20 > { nodeType ndType;=20 > integer inLow;=20 > integer inHigh;=20 > integer out;=20 > } node; > localparam integer nmNodes =3D 2 * nmBits - 1;=20 > localparam integer nmLevels =3D $clog2( nmBits) + 1;=20 > localparam integer nmRships =3D 2 * nmNodes - nmLevels; > localparam node nodes [ nmNodes:1];=20 > localparam integer bases [ nmLevels:0];=20 > wire rships [ nmRships:1]; > wire ntRght;=20 > genvar ix; > function automatic integer fillSubtree ( input integer vrtcl=20 > , input integer hrzntl=20 > , input bit equal); > integer rsltLw;=20 > integer rsltHh;=20 > integer ndIx;=20 > integer rlIx;=20 > integer vr;=20 > integer hz;=20 > integer twice;=20 > integer nxVr;=20 > bit nxPs;=20 > begin=20 > ndIx =3D (1 << vrtcl) + (hrzntl << vrtcl + 1);=20 > vr =3D vrtcl;=20 > hz =3D hrzntl;=20 > while (nmNodes < ndIx)=20 > begin=20 > vr =3D vr - 1;=20 > hz <<=3D 1;=20 > ndIx =3D (1 << vr) + (hz << vr + 1);=20 > end=20 > rlIx =3D bases[ vr] + (hz << 1);=20 > fillSubtree =3D rlIx;=20 > if (0 < vr)=20 > begin=20 > twice =3D hz << 1;=20 > nxPs =3D 0 =3D=3D hz || ! equal;=20 > nxVr =3D vr - 1;=20 > rsltLw =3D fillSubtree( nxVr, twice , nxPs);=20 > rsltHh =3D fillSubtree( nxVr, twice + 1, nxPs);=20 > nodes[ ndIx].ndType =3D hz =3D=3D 0 ? SIDE : equal ? E_INTERIOR : N_INTER=
IOR;=20
> nodes[ ndIx].inLow =3D rsltLw;=20 > nodes[ ndIx].inHigh =3D rsltHh;=20 > nodes[ ndIx].out =3D rlIx;=20 > end=20 > else=20 > begin=20 > nodes[ ndIx].ndType =3D hz =3D=3D 0 ? CORNER : equal ? E_LEAF : N_LEAF;=
=20
> nodes[ ndIx].inLow =3D hz;=20 > nodes[ ndIx].out =3D rlIx;=20 > end=20 > end=20 > endfunction=20 >=20 > initial=20 > begin=20 > integer lvl;=20 > bases[ 0] =3D 1;=20 > for (lvl =3D 1; lvl <=3D nmLevels; lvl =3D lvl + 1)=20 > begin=20 > bases[ lvl] =3D bases[ lvl - 1] + ((nmNodes + (1 << lvl - 1) >> lvl << 1)=
- 1);=20
> end=20 > fillSubtree( nmLevels - 1, 0, true);=20 > end=20 >=20 > for (ix =3D 1; ix <=3D nmNodes; ix =3D ix + 1)=20 > begin=20 > localparam node nd =3D nodes[ ix];=20 > localparam integer highEq =3D nd.inHigh - 1;=20 > localparam integer inLow =3D nd.inLow;=20 > case (nd.ndType)=20 > E_INTERIOR=20 > : begin=20 > nor2 pio( rships[ nd.out - 1], rships[ inLow - 1], rships[ highEq]);=20 > mplex pim( rships[ nd.out], rships[ highEq], rships[ nd.inHigh], rships[ =
inLow]);=20
> end=20 > N_INTERIOR=20 > : begin=20 > nand2 mia( rships[ nd.out - 1], rships[ inLow - 1], rships[ highEq]);=20 > mplex mim( rships[ nd.out], rships[ highEq], rships[ inLow], rships[ nd.i=
nHigh]);=20
> end=20 > SIDE=20 > : mplex sm( rships[ nd.out], rships[ highEq], rships[ inLow], rships[ nd.=
inHigh]);=20
> E_LEAF=20 > : begin=20 > equ2 ple( rships[ nd.out], leftOp[ inLow], rightOp[ inLow]);=20 > assign rships[ nd.out - 1] =3D rightOp[ inLow];=20 > end=20 > N_LEAF=20 > : begin=20 > xor2 mlx( rships[ nd.out], leftOp[ inLow], rightOp[ inLow]);=20 > assign rships[ nd.out - 1] =3D rightOp[ inLow];=20 > end=20 > CORNER=20 > : begin=20 > nt1 cn( ntRght, rightOp[ inLow]);=20 > nor2 co( rships[ nd.out], leftOp[ inLow], ntRght);=20 > end=20 > endcase=20 > end=20 > assign lssThn =3D rships[ bases[ nmLevels - 1]];=20 >=20 > endmodule
I have a few comments: - You probably don't want to instantiate primitives like xor2. Maybe this = is some idea you got from the Palnitkar book. The old books are more geare= d toward circuit modeling, not circuit synthesis. You want "RTL" code, not= "structural" code (in which you instantiate gates instead of inferring the= m). To xor something, use the xor operator: result =3D a ^ b; To NAND so= mething: result =3D ~(a & b); - You are using a lot of "tricky" code, like structures, which are from Ver= ilog-2009 (aka SystemVerilog). Many synthesizers aren't going to like this= . I don't know about Icarus, but since it's free, I'd be wary. Synthesis = tools are not great. It's not like a C compiler, where as long as your C i= s legal, it's going to compile. Your "initial" blocks, functions, and stru= ctures might not synthesize. - You don't have the "generate" keyword before "for (ix ...". That might w= ork in some tools, but I think it might be required by a strict interpretat= ion. But you really shouldn't have a generate block anyway, because you re= ally want RTL code and no gate primitives.
Reply by Kevin Simonson September 23, 20202020-09-23
D:\Hf\Verilog\Unpacked\Src\Common>\Icarus\bin\iverilog -g2009 -o forMark.vvp forMark.sv
forMark.sv:19: sorry: cannot currently create a parameter of type 'node' which was defined at: forMark.sv:8.
forMark.sv:19: syntax error
forMark.sv:19: error: syntax error localparam list.
forMark.sv:20: syntax error
forMark.sv:20: error: syntax error localparam list.
forMark.sv:83: sorry: cannot currently create a parameter of type 'node' which was defined at: forMark.sv:8.

D:\Hf\Verilog\Unpacked\Src\Common>
Reply by Kevin Simonson September 23, 20202020-09-23
module forMark
  #( parameter nmBits = 1)
  ( output              lssThn
  , input [ nmBits-1:0] leftOp
  , input [ nmBits-1:0] rightOp);

typedef enum { CORNER, E_LEAF, N_LEAF, SIDE, E_INTERIOR, N_INTERIOR } nodeType;
typedef struct packed
{ nodeType ndType;
   integer inLow;
   integer inHigh;
   integer out;
} node;

localparam integer nmNodes  = 2 * nmBits - 1;
localparam integer nmLevels = $clog2( nmBits) + 1;
localparam integer nmRships = 2 * nmNodes - nmLevels;

localparam node    nodes  [  nmNodes:1];
localparam integer bases  [ nmLevels:0];
wire               rships [ nmRships:1];
wire               ntRght;
genvar             ix;

function automatic integer fillSubtree ( input integer vrtcl
                                       , input integer hrzntl
                                       , input     bit equal);
    integer rsltLw;
    integer rsltHh;
    integer ndIx;
    integer rlIx;
    integer vr;
    integer hz;
    integer twice;
    integer nxVr;
    bit nxPs;
  begin
    ndIx = (1 << vrtcl) + (hrzntl << vrtcl + 1);
    vr   = vrtcl;
    hz   = hrzntl;
    while (nmNodes < ndIx)
    begin
      vr   = vr - 1;
      hz <<= 1;
      ndIx = (1 << vr) + (hz << vr + 1);
    end
    rlIx        = bases[ vr] + (hz << 1);
    fillSubtree = rlIx;
    if (0 < vr)
    begin
      twice  = hz << 1;
      nxPs   = 0 == hz || ! equal;
      nxVr   = vr - 1;
      rsltLw = fillSubtree( nxVr, twice    , nxPs);
      rsltHh = fillSubtree( nxVr, twice + 1, nxPs);
      nodes[ ndIx].ndType = hz == 0 ? SIDE : equal ? E_INTERIOR : N_INTERIOR;
      nodes[ ndIx].inLow  = rsltLw;
      nodes[ ndIx].inHigh = rsltHh;
      nodes[ ndIx].out    = rlIx;
    end
    else
    begin
      nodes[ ndIx].ndType = hz == 0 ? CORNER : equal ? E_LEAF : N_LEAF;
      nodes[ ndIx].inLow  = hz;
      nodes[ ndIx].out    = rlIx;
    end
  end
endfunction

initial
begin
  integer lvl;
  bases[ 0]   = 1;
  for (lvl = 1; lvl <= nmLevels; lvl = lvl + 1)
  begin
    bases[ lvl] = bases[ lvl - 1] + ((nmNodes + (1 << lvl - 1) >> lvl << 1) - 1);
  end
  fillSubtree( nmLevels - 1, 0, true);
end

for (ix = 1; ix <= nmNodes; ix = ix + 1)
begin
  localparam node     nd     = nodes[ ix];
  localparam integer  highEq = nd.inHigh - 1;
  localparam integer  inLow  = nd.inLow;
  case (nd.ndType)
    E_INTERIOR
  : begin
      nor2 pio( rships[ nd.out - 1], rships[ inLow - 1], rships[ highEq]);
      mplex pim( rships[ nd.out], rships[ highEq], rships[ nd.inHigh], rships[ inLow]);
    end
    N_INTERIOR
  : begin
      nand2 mia( rships[ nd.out - 1], rships[ inLow - 1], rships[ highEq]);
      mplex mim( rships[ nd.out], rships[ highEq], rships[ inLow], rships[ nd.inHigh]);
    end
    SIDE
  : mplex sm( rships[ nd.out], rships[ highEq], rships[ inLow], rships[ nd.inHigh]);
    E_LEAF
  : begin
      equ2 ple( rships[ nd.out], leftOp[ inLow], rightOp[ inLow]);
      assign rships[ nd.out - 1] = rightOp[ inLow];
    end
    N_LEAF
  : begin
      xor2 mlx( rships[ nd.out], leftOp[ inLow], rightOp[ inLow]);
      assign rships[ nd.out - 1] = rightOp[ inLow];
    end
    CORNER
  : begin
      nt1 cn( ntRght, rightOp[ inLow]);
      nor2 co( rships[ nd.out], leftOp[ inLow], ntRght);
    end
  endcase
end
assign lssThn = rships[ bases[ nmLevels - 1]];

endmodule