Take the 2-minute tour ×
Electrical Engineering Stack Exchange is a question and answer site for electronics and electrical engineering professionals, students, and enthusiasts. It's 100% free, no registration required.

I'm trying to generate a multi-input gate for which the inputs can be selected when the design is elaborated.

Let me give an example to (hopefully) make this more clear:

module selectable_xor(input [7:0] in, output out);

parameter [7:0] SELECT = 8'b10010100;

// this should be generated for the default value of SELECT:
assign out = in[7] ^ in[4] ^ in[2]

endmodule

So, out should be the output of a XOR gate which has those bits of in as input for which the corresponding bit in SELECT is set.

I'm attempting something like the following:

generate
  genvar gen_i;
  assign out = 1'b0;

  for (gen_i = 0; gen_i < 8; gen_i = gen_i + 1)
    if (SELECT[gen_i])
      assign out = out ^ in[gen_i];
endgenerate

But this produces undefined values for the out signal.

Is there any good way to generate a gate with a variable number of inputs in Verilog?

PS: About the use case: I'm trying to implement a LFSR for which the polynomial is a parameter.

Edit: The consensus seems to be that I should use the following equivalent expression and trust the synthesizer to optimize it to the circuit I want:

assign out = ^(in & SELECT);

Although I do trust that any decent synthesizer will be able to do this, I still would like to know if there is a way in Verilog to actually code this circuit myself.

Consider that, instead of the XOR-gate above, I wanted to code an OR-gate. The equivalent expression is:

assign out = |(in & SELECT);

Ok, that's practically the same as for the XOR-gate. For an AND-gate, however, the expression is different:

assign out = &(in | ~SELECT);

My point is that for every type of gate, I might have to come up with a different equivalent expression. I'd rather have a general way to code a gate for which the inputs can be parametrized because then I can use the same technique for any type of gate.

Edit 2: Since my bounty expires tomorrow, I will edit this question one more time to bump it. This is a comment I left to explain what I want which I hope will be more visible in the question's body:

What I want has nothing to do with physical resources. When I talk about "gates" I mean the Verilog concept. I want to be able to define a gate with inputs depending on some parameter. More specifically, I want this gate to have in[i] as an input iff SELECT[i] is set. I do not want an equivalent expression that might be optimized to the gate I want. As I've said before, this equivalent expression might as well be implemented as 8 AND-gates and an 8-input XOR-gate because that's what's actually coded. I hope this clarifies things :-)

share|improve this question
    
You still haven't added any new information that explains exactly what result you're hoping to get from this, which is what would make it possible to answer this question. It sounds like you want to explicitly control the allocation of physical resources on the chip, but that's a process that's very dependent on the chip technology you're targeting. As @pjc50 has already pointed out, there are no "gates" on most FPGAs, just LUTs (look-up tables). While there may be a way to instantiate and define the contents of a LUT in Verilog, that would be specific to the toolchain provided by the vendor. –  Dave Tweed Jan 14 '13 at 2:50
    
@DaveTweed: What I want has nothing to do with physical resources. When I talk about "gates" I mean the Verilog concept. I want to be able to define a gate with inputs depending on some parameter. More specifically, I want this gate to have in[i] as an input iff SELECT[i] is set. I do not want an equivalent expression that might be optimized to the gate I want. As I've said before, this equivalent expression might as well be implemented as 8 AND-gates and an 8-input XOR-gate because that's what's actually coded. I hope this clarifies things :-) –  Job Jan 15 '13 at 9:01
add comment

3 Answers

up vote 1 down vote accepted
+100

If I understood your question correctly, I think the following module does what you want. You can very simply specify the gate by its operator (^,&,|, etc) and nothing else. Plus only the desired assignments are generated (which is I think what you are looking for).

`timescale 1 ns / 1 ps

module selectable_gate(input [7:0] in, output out);

parameter [7:0] SELECT = 8'b10010100;

function integer count_ones;
  input [7:0] v;
  integer ret;
  integer i;
  begin
    ret = 0;
    for(i=0;i<8;i=i+1) begin
      if (v[i]) begin
        ret = ret+1;
      end
    end
    count_ones = ret;
  end
endfunction

function integer nth_one;
  input integer n;
  input [7:0] v;
  integer i,ret,cnt;
  begin
    ret = -1;
    cnt = 0;
    for(i=0;i<8;i=i+1) begin
      if (v[i]) begin
        if (cnt == n) begin
          ret = i;
        end
        cnt = cnt+1;
      end
    end    
    nth_one = ret;
  end
endfunction

localparam integer w = count_ones(SELECT);
wire [w-1:0] y;

generate
  genvar i;
  for(i=0 ; i<w ; i=i+1) begin
    assign y[i] = in[nth_one(i,SELECT)];
  end
endgenerate

assign out = ^y; // specify gate here (e.g. ^y, &y, |y, etc)

endmodule;  

The above module for the default SELECT = 8'b10010100 should end up generated as:

assign y[0] = in[2];
assign y[1] = in[4];
assign y[2] = in[7];
assign out  = ^y;

Which is the same as xor(in[2],in[4],in[7]).

Since genvars are always unrolled as constants inside the generates, the trick was to find constants that allow the proper conditions for the generate, and use functions for any temporary variable manipulation necessary to calculate them.

share|improve this answer
    
Great solution! This is the thing I was looking for. Just one comment, and I'm nitpicking now, but this seems to create the XOR-gates in series. The created circuit is XOR(in[7], XOR(in[4], in[2])) instead of XOR(in[2], in[4], in[7]). That is, two 2-input XOR-gates instead of one 3-input XOR-gate. I think the latter may be generated by assigning y[i] to in[nth_one(i,SELECT)] and then just doing assign out = ^y. Anyway, like I said this is nitpicking. Thanks for the great answer! –  Job Jan 17 '13 at 7:23
    
@Job Ah, yes. I've updated the answer to describe the gate as a single operation on a vector containing only the selected inputs, instead of multiple 2-input gates. –  apalopohapa Jan 17 '13 at 8:34
    
I think I just spotted a small bug in your code: in function nth_one, the statement ret = cnt should be ret = i. –  Job Jan 17 '13 at 8:44
    
@Job True. Fixed. –  apalopohapa Jan 17 '13 at 9:29
    
Great! Enjoy your bounty :-) –  Job Jan 17 '13 at 10:00
add comment

Try

assign out = ^(in & parameter);

The & selects those bits which are 1 in parameter, and then ^ will XOR them all together. Those bits which are 0 in parameter will be ignored.

share|improve this answer
    
Hehe we posted the exact same answer at the same time. Please see the concerns I added to my answer. –  Job Jan 8 '13 at 10:57
add comment

The following is equivalent to what I want:

assign out = ^(in & SELECT);

And I noticed that Xilinx ISE synthesizes this into a 3-input XOR-gate for the default value of SELECT which is exactly what I want.

However, since this might just as well be synthesized into 8 AND-gates and one 8-input XOR-gate, I'm still very much interested in other answers. I would like to have a way to code this in Verilog instead of having to rely on the synthesis tool.

share|improve this answer
    
Your issue is essentially that you don't trust the synthesis tool to do logic minimisation? Note that if you're targetting an FPGA, it's all lookup tables rather than actual gates.. –  pjc50 Jan 8 '13 at 11:24
    
You did just code it in Verilog. I don't understand what your concern is. –  Dave Tweed Jan 8 '13 at 13:00
    
@DaveTweed: My concern is that I did not code the use of a small number of XOR-gates. I coded the use of 8 AND-gates and one big XOR-gate. Although I assume any decent synthesizer will infer what I want, I'm still interested in coding this in Verilog. –  Job Jan 8 '13 at 14:50
1  
Parameters are fixed value for synthesis, so the synthesizer is doing the proper thing and optimizing for SELECT=8'b10010100. If you want the full logic, change SELECT to an input instead of a parameter. If SELECT can take on any value, the synthesizer will not be able to make that optimization. –  dwikle Jan 8 '13 at 15:02
    
@dwikle: I updated my answer to give some rationale as to why I want to do this in another way. –  Job Jan 9 '13 at 8:00
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.