I have some Verilog code as follows:

module bus_fifo #(
    parameter DEPTH_WIDTH = 0,
    parameter DATA_WIDTH = 0
) (
    input  wire                    clk,
    input  wire                    rst,

    input  wire [DATA_WIDTH-1:0]       wr_data_i,
    input  wire                wr_en_i,

    output wire [DATA_WIDTH-1:0]       rd_data_o,
    input  wire                        rd_en_i,

    output wire                full_o,
    output wire                        empty_o

localparam DW = (DATA_WIDTH  == 10) ? 4 : DATA_WIDTH;
localparam AW = DEPTH_WIDTH>>2;


I want syntactically valid VHDL that does the same thing:

library ieee;
use ieee.std_logic_1164.all;

entity bus_fifo is
        DEPTH_WIDTH               : integer := 0;
        DATA_WIDTH                : integer := 0
        clk                       : in    std_logic;
        rst                       : in    std_logic;
        wr_data_i                 : in    std_logic_vector(DATA_WIDTH-1 downto 0);
        wr_en_i                   : in    std_logic;
        rd_data_o                 : out   std_logic_vector(DATA_WIDTH-1 downto 0);
        rd_en_i                   : in    std_logic;
        full_o                    : out   std_logic;
        empty_o                   : out   std_logic        
end entity;

architecture bus_fifo of bus_fifo is
    constant   DW         : integer := (DATA_WIDTH  == 10) ? 4 : DATA_WIDTH;
    constant   AW         : integer := DEPTH_WIDTH>>2;
    signal     write_pointer;            : std_logic_vector(AW downto 0);
    signal     read_pointer;             : std_logic_vector(AW downto 0);
    signal     empty_int                 : std_logic;
    signal     full_or_empty             : std_logic;

end architecture;

The problem i'm having is that VHDL does't support ternary operator and generates and ERROR message. I'm wondering if there's a VHDL solution to do something similar to what i'm doing in Verilog?

3 Answers

dave_59 On

You can create a function and call the function in the evaluation of the generic.

damage On

I usually use a function (named "If Then Else" = ite) to work around the lack of a ternary operator in VHDL.

function ite(b: boolean; x, y: integer) return integer is begin
    if (b) then
        return x;
        return y;
    end if;
end function ite;

Usage like this:

constant foo : integer := ite(SOME_INTEGER = 42, 1337, 4711);

You can overload this function for different return types. Note that the boolean expression must be constant at evaluation time when used to initialize a constant.
A more realistic example, a recipe I often use:

entity foo is
  generic (
    DEBUG_LVL : integer := 0
attribute MARK_DEBUG : string;
signal my_signal : std_logic;
attribute MARK_DEBUG of my_signal : signal is ite(DEBUG_LVL >= 1, "TRUE", "FALSE");

This last example of course requires a "ite function" with the signature

function ite(b: boolean; x, y: string) return string;
Tricky On

VHDL 2019 adds conditional assignment of initial values:

constant DW : integer := 4 when (DATA_WIDTH = 10) else DATA_WIDTH;

Expect vendor support (especially Xilinx) by the year 2029.