In article <c8f86dc5-fccc-4ec0-bd93-c7bd38809bccn@googlegroups.com>, Kevin Simonson <kvnsmnsn@hotmail.com> wrote:>Gtwrek (Mark): "All of the above looks reasonable. Recursive functions are synthesizable as long as the terminating conditions are static (in software speak, the >loop can be unrolled during elaboration)". > >Mark, can I post my Verilog so you can take a look at it, and then post the error messages Icarus is giving me when I try to simulate it? Or e-mail them to you?If it's a minimal example, I'll give it a shot. Post here. --Mark
How powerful is Verilog at using parameters to specify designs?
Started by ●September 21, 2020
Reply by ●September 23, 20202020-09-23
Reply by ●September 23, 20202020-09-23
Gtwrek (Mark): "If it's a minimal example, I'll give it a shot. Post here." It's kind of complicated, but it's not huge. I'll post it and you can decide whether it's too big or not. It will be my next post, and the post after that will be the error messages Icarus gave me.
Reply by ●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
Reply by ●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 ●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 > endmoduleI 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 ●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 ●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 ●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 ●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 ●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>