Verilog Coding Tips and Tricks: generic codes
Showing posts with label generic codes. Show all posts
Showing posts with label generic codes. Show all posts

Sunday, December 13, 2020

Generic Verilog Code for Binary to Gray and Gray to Binary converter

     Few years back I had written a 4 bit converter for conversion between Gray and Binary codes. After receiving much positive response I decided to write a generic version of the same.

Let me share the codes...

Binary to Gray Code Converter:



//Binary to Gray code Converter
//The 'parameter' keyword below is how we give the inputs/outputs a generic size.
module bin2gray #(parameter N = 4)
        ( input [N-1:0] bin,    //binary input
        output [N-1:0] G);      //Gray output

assign G[N-1] = bin[N-1];

//generate xor gates.
//the loop index need to be declared as 'genvar' and it can be done
//as you can see inside the 'for' loop.
//The instantiation is labelled as 'xor_gates_b2g'. 
//Always put a label when you generate instantiations.
//The 'generate' keyword need not be explicitly written.
for(genvar i=N-2;i>=0;i=i-1begin : xor_gates_b2g
    xor(G[i],bin[i+1],bin[i]);
end

endmodule


Gray Code to Binary Converter:



//Gray code to Binary Converter
module gray2bin #(parameter N = 4)
        ( input [N-1:0] G,    //Gray input
        output [N-1:0] bin);      //Binary output

assign bin[N-1] = G[N-1];

for(genvar i=N-2;i>=0;i=i-1begin : xor_gates_g2b
    xor(bin[i],G[i],bin[i+1]);
end

endmodule


Testbench:



//Testbench which connects both the converters back to back.
module tb;  //testbench module is always empty.

parameter N = 16;   //Change this to control the number of bits in the input/output.
reg [N-1:0] bin;
wire [N-1:0] G,bin_out;
reg [N:0] i;
integer error;  //this counts the number of errors during simulation.

    //Both the converters are connected back to back to see the binary input going to the
    //first module is the same as the output coming out of the second module.
    bin2gray #(.N(N)) uut1
        (
          .bin(bin),
          .G(G)
        );
 
    gray2bin #(.N(N)) uut2
        (
          .G(G),  
          .bin(bin_out)
        );
          
    initial 
    begin
        error = 0;  //initialize the error as zero.
        for(i=0;i<2**N;i=i+1begin     //loop through all the  available inputs 
            bin = i[N-1:0];
            #5;
            //Count the number of errors.It should be zero at the end of simulation.
            if(bin != bin_out)  
                error = error + 1;
            #5;
        end
        #10;
        $stop;  //All possible inputs are tested. So stop the simulation.
    end          

endmodule


    The codes were tested using Modelsim 10.4a version. Simply change the value of the parameter 'N' in the testbench to test for different sized converters.

A screenshot of the simulation waveform is shown below:





Tuesday, November 17, 2015

Synthesisable Verilog code for Division of two binary numbers

For doing division, Verilog has an operator, '/' defined. But this operator has some limitation when it comes to certain synthesis tools such as Xilinx XST. The '/' operator is synthesisable only when the second operand is a power of 2. 

For division of generic numbers Xilinx returns the following error message during synthesis:
Can not simplify operator DIV
 Few year back, I wrote a VHDL function for implementing division which was synthesisable. The design was based on Restoring Division algorithmIn this article, I have converted the same design into Verilog.

Division code:

The size of operands to the division module are defined through a parameter named WIDTH. This way you can use the same code for implementing 8 or 16 or 32 or any sized division. Note that, both the input operands and output have the same size.

module division(A,B,Res);

    //the size of input and output ports of the division module is generic.
    parameter WIDTH = 8;
    //input and output ports.
    input [WIDTH-1:0] A;
    input [WIDTH-1:0] B;
    output [WIDTH-1:0] Res;
    //internal variables    
    reg [WIDTH-1:0] Res = 0;
    reg [WIDTH-1:0] a1,b1;
    reg [WIDTH:0] p1;   
    integer i;

    always@ (or B)
    begin
        //initialize the variables.
        a1 = A;
        b1 = B;
        p1= 0;
        for(i=0;< WIDTH;i=i+1)    begin //start the for loop
            p1 = {p1[WIDTH-2:0],a1[WIDTH-1]};
            a1[WIDTH-1:1] = a1[WIDTH-2:0];
            p1 = p1-b1;
            if(p1[WIDTH-1] == 1)    begin
                a1[0] = 0;
                p1 = p1 + b1;   end
            else
                a1[0] = 1;
        end
        Res = a1;   
    end 

endmodule

Testbench code:

module tb_division;
    parameter WIDTH = 8;
    // Inputs
    reg [WIDTH-1:0] A;
    reg [WIDTH-1:0] B;
    // Outputs
    wire [WIDTH-1:0] Res;

    // Instantiate the division module (UUT)
    division #(WIDTH) uut (
        .A(A), 
        .B(B), 
        .Res(Res)
    );

    initial begin
        // Initialize Inputs and wait for 100 ns
        A = 0;  B = 0;  #100;  //Undefined inputs
        //Apply each set of inputs and wait for 100 ns.
        A = 100;    B = 10; #100;
        A = 200;    B = 40; #100;
        A = 90; B = 9;  #100;
        A = 70; B = 10; #100;
        A = 16; B = 3;  #100;
        A = 255;    B = 5;  #100;
    end
      
endmodule

Simulation Waveform:

The codes were simulated in Xilinx ISE 13.1 to get the following waveform.



Synthesis Results:

The design was synthesised for Virtex 4 fpga and a maximum combinational path delay of 20 ns was obtained for 8 bit division.