4

I am used to programming in VHDL and I want to know the "best" way to do some types of actions that I use in VHDL in Verilog. I suppose that each of these could be their own dedicated question, but I thought it would be nice to have a collection of these for people just to see a bunch of Verilog examples in one place rather than spread across 5 questions. Thanks.

Here are some examples that I would like to see best practices for:

Replacement for Others:

I know that for signal assignments in Verilog, you can do:

data <= 'b0;

This assigns all bits in data to zero, and if data changes its width it still works. Neat trick, but what about when instantiating a module and tying an input to zero? E.G.

   Data_Module UUT
      (
       .Data(8'h00),  //'b0 doesn't work here

Replacement for Attributes:

Writing flexible code is nice, so I like to define my port widths based on generics such that if the port widths change all it takes is a quick update of the generic and everything still works. I often have VHDL code like this:

signal some_data : std_logic_vector(g_DATA_WIDTH+g_GENERIC-1 downto 0);
signal some2     : std_logic_vector(some_data'length-1 downto 0);

-- OR I may have this:
left_bit <= some_data'left;

Long when/else chain:

This one gives me troubles. Is the best way to do this to set up a combinational always block and use a case-statement on index? That seems like a lot of code. Using the ? operator can lead to some illegible code, so I prefer not to do that for long when/else chains.

some_data <= X"01" when index = 0 else
             X"04" when index = 1 else
             X"02" when index = 2 else
             X"F0";

Assertions:

How can I trigger a modelsim assertion in Verilog? I often use these on my VHDL FIFOs to check for overflow/underflow conditions. E.G.

assert NOT_FIFO_OVERFLOW report "FIFO has overflowed, that's a bad thing" severity failure;

Generate Blocks:

In VHDL, it's nice to be able to generate a block of code based on a generic, or completely remove it if that generic is not present. E.G.

  g_LFSR_3 : if g_Num_Bits = 3 generate
    w_XNOR <= r_LFSR(3) xnor r_LFSR(2);
  end generate g_LFSR_3;

  g_LFSR_4 : if g_Num_Bits = 4 generate
    w_XNOR <= r_LFSR(4) xnor r_LFSR(3);
  end generate g_LFSR_4;

State Machine Enumeration:

In Verilog, do I really need to create parameters for each individual state? If that's the best way to do it, I'll do it, but it seems like a lot. I like that in VHDL you can create a type that just contains each state and then create a state machine signal of that type.

Creating Integers:

Often I have code like this:

signal Row_Count : integer range 0 to c_TOTAL_ROWS-1 := 0;

What's the best way to do this in Verilog? Do I need to take the log base 2 of c_TOTAL_ROWS to find the max width of it then define a reg based on this? That seems like a lot of work. I believe that Verilog creates 32-bit integers by default, but I do not want to generate extra logic if I do not need to. Also I like that if I exceed the expected range, my Modelsim simulation will crash.

1

1 Answer 1

5

Not everything can be directly translated into Verilog.

Replacement for Others:

Verilog

'b0 should work with port declinations. There should be compiling warnings, not errors. Some simulator try to be backward compatible to IEEE Std 1364-2005 where 'b0 is an inferred 32'b0. According to IEEE Std 1364-2005 &sect 3.5.1 this 32-bit max limitation seems to be removed. Simulators may be lagging behind the standard. It is a simulator limitation if the module port instantiation .Data('b0), results in a compiling error.

SystemVerilog

SystemVerilog added a fill constants '0, '1, 'x, & 'z. '0, 'x, & 'z are the same as IEEE Std 1364-2005 'b0, 'bx, & 'bz with one less character. 'b1 is {(N-1){1'b0},1'b1} where '1 is {N{1'b1}} with N being the width of the destination vector/packed-array.

Replacement for Attributes:

Verilog

Non that could be found.

SystemVerilog

logic [g_DATA_WIDTH+g_GENERIC-1:0] some_data;
logic [$size(some_data)-1:0] some2;
logic [$bits(some_data)-1:0] some3; // or with $bits for vector

// OR I may have this:
left_bit <= some_data[$left(ome_data)];

Long when/else chain:

Verilog/SystemVerilog (Same for both)

some_data <= (index == 0) ? 'h01 :
             (index == 1) ? 'h04 :
             (index == 2) ? 'h02 :
                            'hF0 ;

The works functionally but may not give the best timing and area when synthesized. When some synthesizers see ?: they will always generate a 2-to-1 mux; if they see a chain of nested ?: it will create a chain of 2-to-1 muxes even is a 4-to-1 mux (or other mux types) is available.

It a little more typing but this should give a better result (same functionality)

case(index)
  0 : some_data <= 'h01;
  1 : some_data <= 'h04;
  2 : some_data <= 'h02;
  default : some_data <= 'hF0;
endcase

Assertions:

Verilog

Verilog does not have assertions built into the language. Creating some for of checkers are not to challenging (for example non-overlaping concurrent check can be done with a always block), but flagging the error to the simulator may be a bit tricky. Usually a global error counter incremented of failures and the simulation will abort with $finish if a user defined error limit is reached. There might be a PLI/VPI solution or a something that simulator specific.

SystemVerilog

SystemVerilog has two main types of assertions; concurrent and immediate. Immediate exist inside of a procedural block (i.e. begin-end) such as:

optional_label : assert (NOT_FIFO_OVERFLOW) $error("FIFO has overflowed, that's a bad thing");

Concurrent assertions run in the module scope, out side of a procedural block. They use a clocking reference.

optional_label : assert property (@(posedge clk) !$stable(fifo_ptr) |->  fifo_pt < FIFO_DEPTH) $error("FIFO has overflowed, that's a bad thing");

Refer to IEEE Std 1800-2012 § 16. Assertions for further explinations and examples.

Note - if using UVM, use `uvm_error instead of $error

Generate Blocks:

Verilog/SystemVerilog

Generate blocks were added in Verilog's IEEE Std 1364-2001. The generate-endgenerate are actually optional, but make a good visual reference. See IEEE Std 1800-2012 § 27. Generate constructs for full detail

generate
  if (g_Num_Bits = 3) begin : g_LFSR_3
    xnor (w_XNOR, r_LFSR[3], r_LFSR[2]);
  end : g_LFSR_3
  if (g_Num_Bits = 4) begin : g_LFSR_4
    always @* begin
      w_XNOR = ~{r_LFSR[4] ^ r_LFSR[3]};
    end
  end
endgenerate

Note: In this particular example part-select addressing would also work in Verilog/System Verilog: w_XNOR = ~^r_LFSR[g_Num_Bits-:2]; IEEE Std 1800-2012 § 11.5.1

State Machine Enumeration:

Verilog

Got to use parameter here if it is desired to using names instead of memorizing indexes. It legal possible to define multiple parameter in a one statement, but identifier still needs to define its value.

SystemVerilog

Enumeration is supported. See IEEE Std 1800-2012 § 6.19 Enumerations

Example:

typedef enum logic [3:0] { IDLE=0, START, STAGE[4:6], BLAH, STAGE[3] } states_e;
states_e state, next_state;

Is the equivalent of writing:

parameter [3:0] IDLE   = 4'd0,
                START  = 4'd1,
                STAGE4 = 4'd2,
                STAGE5 = 4'd3,
                STAGE6 = 4'd4,
                BLAH   = 4'd5,
                STAGE0 = 4'd6,
                STAGE1 = 4'd7,
                STAGE2 = 4'd8;

Creating Integers:

Verilog/SystemVerilog

With IEEE Std 1364-2005 (Final version of Verilog) or IEEE Std 1800 (SystemVerilog) use reg [$clog2(c_TOTAL_ROWS)-1:0] Row_Count;

For older Verilog (IEEE Std 1364-1995 and IEEE Std 1364-2001) create a custom fuction to find the ceiling of a log base 2. Example:

function interger ceiling_log2(input integer value);
  interger local_copy;
  local_copy = value;
  ceiling_log2 = 0;
  while(local_copy!=0) begin
    ceiling_log2 = ceiling_log2 + 1;
    local_copy = local_copy >> 1;
  end
  return ceiling_log2;
endfunction
reg [ceiling_log2(c_TOTAL_ROWS)-1:0] Row_Count;

Note: Some synthesizer may have limitations

Sign up to request clarification or add additional context in comments.

2 Comments

Greg this the type of answer I was hoping to get. This is fantastic information, thank you for putting it all together. Does that case statement in your example exist within an always block?
Yes, the case statement should be in an always block.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.