# Instantiating module inside for loop

I'm trying to write verilog code for converting any digit decimal number to BCD number. My logic: when i read decimal number, i'll extract decimal number digit by digit and I have written module to convert decimal digit (0 to 9) to BCD. But I'm getting error in the line "dec_to_bcd_0_to_9 a(temp2, bcd_num [(3*i)+(i-1):4*(i-1)]);" it is showing syntax error in icarus verilog simulator. what is wrong in my code?

module dec_to_bcd_0_to_9(dec,bcd);
input integer dec;
output reg [3:0] bcd;

always@*
begin

case(dec)
1'd0:bcd=4'b0000;

1'd1:bcd=4'b0001;

1'd2:bcd=4'b0010;

1'd3:bcd=4'b0011;

1'd4:bcd=4'b0100;

1'd5:bcd=4'b0101;

1'd6:bcd=4'b0110;

1'd7:bcd=4'b0111;

1'd8:bcd=4'b1000;

default:bcd=4'b1001;
endcase

end

endmodule

module dec_to_bcd_any_number(dec_width,dec_num,bcd_num);
input integer  dec_width,dec_num;
output [4*dec_width-1:0] bcd_num;

reg integer temp1,temp2;

assign temp1=dec_num/10;
assign temp2=dec_num%10;

generate
genvar i;

for(i=1;i<=dec_width;i=i+1)
begin
dec_to_bcd_0_to_9 a(temp2, bcd_num [(3*i)+(i-1):4*(i-1)]);
assign temp2=temp1%10;
assign temp1=temp1/10;
end

endgenerate

endmodule

• Beware that the / and % operator are not support by all synthesis tools for values which are not a power of two. – Oldfart Oct 2 '19 at 12:44
• then what is the solution for this problem if we want to synthesize? – Ajay vishwanath Oct 2 '19 at 13:34
• There is no easy solution, that is why I pointed this out. Ultimately you might have to implement a divider. Multiplication is easy so you can make "% 10" by using the division result, multiply it by 10 and then subtraction from the original. – Oldfart Oct 2 '19 at 14:49

There are two problems.

• First, you can't use integer as the type of an input port. In fact, iverilog seems to treat it as equivalent to reg, which means you can't use it in assign statements either. You need to replace it with a wire with an explicit width.

• Second, the limits of a for loop need to be known at compile time, so you can't base it on an input port. dec_width must be a module parameter instead.

• Also, there was a minor problem with declaring an explicit width of 1 bit for your case values.

Here's a version of your code that compiles cleanly with iverilog -tnull ...:

module dec_to_bcd_0_to_9 (dec, bcd);
input [31:0] dec;
output reg [3:0] bcd;

always @* begin
case (dec)
'd0:     bcd = 4'b0000;
'd1:     bcd = 4'b0001;
'd2:     bcd = 4'b0010;
'd3:     bcd = 4'b0011;
'd4:     bcd = 4'b0100;
'd5:     bcd = 4'b0101;
'd6:     bcd = 4'b0110;
'd7:     bcd = 4'b0111;
'd8:     bcd = 4'b1000;
default: bcd = 4'b1001;
endcase
end
endmodule

module dec_to_bcd_any_number (dec_num, bcd_num);
parameter dec_width = 5;
input [31:0] dec_num;
output [4*dec_width-1:0] bcd_num;

wire [31:0] temp1, temp2;

assign temp1 = dec_num/10;
assign temp2 = dec_num%10;

generate
genvar i;

for (i = 1; i <= dec_width; i = i+1) begin
dec_to_bcd_0_to_9 a (temp2, bcd_num [(3*i)+(i-1):4*(i-1)]);
assign temp2 = temp1%10;
assign temp1 = temp1/10;
end
endgenerate
endmodule

• Thank you. but I am getting "xxxxxxxxxxxxxxxxxxxx" for every decimal value that I am giving from test bench. is it beacuse my logic incorrect? – Ajay vishwanath Oct 2 '19 at 13:21
• Yes. What you do next is called "debugging". Look at each of the variables in the order in which they are assigned, and verify that they have the expected values. As soon as you find a discrepancy, stop and figure out why. – Dave Tweed Oct 2 '19 at 14:22