-1

I have a 32-bit input port pins and a 32-bit input enable pin_en, and want to generate a 16-bit output selected by the enables. I wrote verilog like this, but seems there are some errors. How can I fix it or any other way to achive? Thanks!

ps: No more than 16 pins selected by en, but maybe less.

input [31:0] pins;
input [31:0] pin_en;
output [15:0] actual_pins;

generate
genvar i;
localparam cnt = 0;
    for(i = 0; (i < 'd32) & (cnt < 'd16); i = i + 'd1) begin : b1
        if(pin_en[i]) begin
            assign actual_pins[i] = pins[cnt];
            cnt = cnt + 'd1;
        end
    end
    if(cnt < 16)
        assign actual_pins[16 : cnt] = 'b0;
endgenerate
PX.Liu
  • 171
  • 1
  • 7
  • We can't do anything with a description like *"there are some errors*". By the way, you write HDL like it is an ordinary programming language. It is not! I suggest you have a look at existing Verilog code. – Oldfart Mar 03 '20 at 06:44
  • Thanks @Oldfart, I'm new in verilog and I'm learning. I googled after I asked the question and I know _cnt_ cannot be used in this way. I found a way to bypass this situation in my project. But I still have no idea about how to pick 16 bit (or less) form 32bit dynamically. – PX.Liu Mar 03 '20 at 07:53
  • Your question is unclear. How would you like to reduce the number of signals from 32 to 16 just by using enable? Typically, you would write just `actual_pins = pins & pin_en`, but the reduction part is confusing. As @Oldfart mentioned, you write code like it is a Python (?) code. But it won't work. – Qiu Mar 03 '20 at 09:22

1 Answers1

1

I think that there are several errors in you code:

  1. in generate blocks you cannot do any generation, based on the actual values of variables. The blocks are for the constant expressions only which could be resolved at compilation time, not at the run time. Also, you cannot modify anything in the generated blocks besides genvars. Paremeters (localparams) cannot be modified, so the cnt = cnt + 1 is just illegal there.

  2. you messed up actual_pins and pins. by logic there should be actual_pins[cnt];

  3. you use binary & operator, but you should have used logical && instead.

So, all your code should have been implemented in a run-time constructs, i.e., always blocks. You also need a trigger which will cause the always block to be evaluated. I created a small example where the always block is to be triggered by a clock.

module top (
  input clk,
  input [31:0] pins,
  input [31:0] pin_en,
  output reg [15:0] actual_pins
);

  always @(posedge clk) begin
    int cnt = 0;
    int i;
    for(i = 0; (i < 'd32) && (cnt < 'd16); i = i + 'd1) begin 
        if(pin_en[i]) begin
          actual_pins[cnt] = pins[i];
          cnt = cnt + 'd1;
        end
    end
    for(; cnt < 16; cnt = cnt + 1) 
         actual_pins[j] = 1'b0;
  end
endmodule
Serge
  • 11,616
  • 3
  • 18
  • 28