surfer113
surfer113

Reputation: 55

How can write code in verilog shorter using case sentence

I am new in Verilog and I still have some problems with basics. The following code is one of the modules and works the way I want, but I wonder if it can be written more efficient and shorter and how could it be done. Thank you for your help!

`timescale 1ns / 1ps


module COUNTER
  (
    input A_i,
    input B_i,
    input ENABLE_i,
    input CLK,
    input RESET,
    input R_i,
    input UP_DOWN_i, // za realno stanje se UP_DOWN_o prepisuje v UP_DOWN_i
    output reg signed [7:0] VALUE_o,
    output reg UP_DOWN_o  
  );



  reg A;
  reg B;
  reg signed [7:0] VALUE_cmp;
  wire [1:0] A_B={A,B};

  initial VALUE_o = 8'b00000000;
  initial VALUE_cmp = 8'b00000000;
  initial A = 1'b0;
  initial B = 1'b0;
  initial UP_DOWN_o = 1'b1;


  always@ (posedge CLK or posedge RESET)
  begin
    A <= A_i;
    B <= B_i;
    VALUE_cmp <= VALUE_o; 

    if (RESET || R_i)
    begin
      VALUE_o<= 8'b0;
      VALUE_cmp <=8'b0;  
    end

    else if (ENABLE_i)
    begin

//up or down
      if (UP_DOWN_i)
      begin 
//up
        if ((A == 1'b0) && (A_i == 1'b0) && (B == 1'b0) && (B_i == 1'b1))
          VALUE_o <= VALUE_o+1;  
        else if ((A == 1'b0) && (A_i == 1'b1) && (B == 1'b1) && (B_i == 1'b1))
          VALUE_o <= VALUE_o+1;  
        else if ((A == 1'b1) && (A_i == 1'b1) && (B == 1'b1) && (B_i == 1'b0))
          VALUE_o <= VALUE_o+1;  
        else if ((A == 1'b1) && (A_i == 1'b0) && (B == 1'b0) && (B_i == 1'b0))
          VALUE_o <= VALUE_o+1;
// change
        if ((A == 1'b0) && (A_i == 1'b1) && (B == 1'b0) && (B_i == 1'b0))
            VALUE_o <= VALUE_o+1;
        else if ((A == 1'b1) && (A_i == 1'b1) && (B == 1'b0) && (B_i == 1'b1))
            VALUE_o <= VALUE_o+1;  
        else if ((A == 1'b1) && (A_i == 1'b0) && (B == 1'b1) && (B_i == 1'b1))
            VALUE_o <= VALUE_o+1;
        else if ((A == 1'b0) && (A_i == 1'b0) && (B == 1'b1) && (B_i == 1'b0))
            VALUE_o <= VALUE_o+1;
// after  
        else if (A == A_i ==B == B_i )
            VALUE_o <= VALUE_o+1;              
      end

      else
      begin
 //down  
        if ((A == 1'b0) && (A_i == 1'b1) && (B == 1'b0) && (B_i == 1'b0))
            VALUE_o <= VALUE_o-1;
        else if ((A == 1'b1) && (A_i == 1'b1) && (B == 1'b0) && (B_i == 1'b1))
            VALUE_o <= VALUE_o-1;  
        else if ((A == 1'b1) && (A_i == 1'b0) && (B == 1'b1) && (B_i == 1'b1))
            VALUE_o <= VALUE_o-1;
        else if ((A == 1'b0) && (A_i == 1'b0) && (B == 1'b1) && (B_i == 1'b0))
            VALUE_o <= VALUE_o-1;         
//change     
        else if ((A == 1'b1) && (A_i == 1'b1) && (B == 1'b1) && (B_i == 1'b0))
                VALUE_o <= VALUE_o-1;
        else if ((A == 1'b0) && (A_i == 1'b1) && (B == 1'b1) && (B_i == 1'b1))
                VALUE_o <= VALUE_o-1;
        else if ((A == 1'b0) && (A_i == 1'b0) && (B == 1'b0) && (B_i == 1'b1))
                        VALUE_o <= VALUE_o-1;
        else if ((A == 1'b1) && (A_i == 1'b0) && (B == 1'b0) && (B_i == 1'b0))
                                VALUE_o <= VALUE_o-1;
// after  
        else if (A == A_i ==B == B_i )
            VALUE_o <= VALUE_o-1;     
       end
      end
  end

  always@ (posedge CLK) // kasneje potrebo vezat za UP_DOWN_o
  begin      
       //steje dol
      if (VALUE_cmp > VALUE_o)
        UP_DOWN_o <= 0;

      //steje gor
      else if (VALUE_cmp < VALUE_o)
          UP_DOWN_o <= 1;        
  end        
endmodule

Upvotes: 1

Views: 397

Answers (1)

GurstTavo
GurstTavo

Reputation: 334

It can be shortened by replacing the if-else chains with the a case as you suggest. Here is the dense implementation. Also in this kind of problems you can use Look up tables (LUT).

  always@ (posedge CLK or posedge RESET)
  begin
    A <= A_i;
    B <= B_i;
    VALUE_cmp <= VALUE_o; 

    if (RESET || R_i)
    begin
      VALUE_o<= 8'b0;
      VALUE_cmp <=8'b0;  
    end

    else if (ENABLE_i)
    begin

//up or down
      if (UP_DOWN_i)
      begin 

        case({A,A_i,B,B_i})
            //up
            4'b0001, 4'b0111,
            4'b1110, 4'b1000,
            // change
            4'b0100, 4'b1101,
            4'b1011, 4'b0010:
                VALUE_o <= VALUE_o+1;
        endcase
        if (A == A_i ==B == B_i )
            VALUE_o <= VALUE_o+1; 
        end

      else
      begin

        case({A,A_i,B,B_i})
        //down 
        4'b0100, 4'b1101,
        4'b1011, 4'b0010,
        //change  
        4'b1110, 4'b0111,
        4'b0001, 4'b1000:
            VALUE_o <= VALUE_o-1;
        endcase
// after  
        else if (A == A_i ==B == B_i )
            VALUE_o <= VALUE_o-1;     
       end
      end
  end

Here is a reference for LUT implementations: https://www.csee.umbc.edu/~tinoosh/cmpe415/slides/Rom-LUT-verilog.pdf

Upvotes: 1

Related Questions