2
votes

I am looking to replace some generic synchroniser code in a Verilog module (for this reason). The code a standard 2-flop synchroniser.

always @ (posedge clk_i or posedge rst)
begin
  if (rst)
    begin
      rx_sync_tmp <= 1'b1;
      rx_sync     <= 1'b1;
    end
  else
    begin
      rx_sync_tmp <= rx_i;
      rx_sync     <= rx_sync_tmp;
    end
end

The entity declaration in VHDL is also straightforward:

entity synchroniser_d_flip_flop_n is

    generic(
        NUM_STAGES          : natural   := 2;
        RESET_ACTIVE_STATE  : std_logic := '1';
        DEFAULT_AFTER_RESET : std_logic := '0'
    );

    port(
        clk_i       : in  std_logic;
        reset_i     : in  std_logic; 
      d_i           : in  std_logic;
        q_o         : out std_logic
    );

end synchroniser_d_flip_flop_n;

But if I attempt to instantiate this in verilog the obvious way:

synchroniser_d_flip_flop_n #(2, 1, 1) rx_sync_block(
    clk_i,
    rst, 
    rx_i,
    rx_sync
    );

Altera Quartus-II 15.0.2 gives the following error (target is MAX10):

Error (10517): VHDL type mismatch error at synchroniser_d_flip_flop.vhd(9): std_logic type does not match integer literal
Error (10517): VHDL type mismatch error at synchroniser_d_flip_flop.vhd(10): std_logic type does not match integer literal

That is, it appears not to accept 1 as std_logic.

Xilinx seems to suggest that VHDL generics containing std_logic are not possible to instantiate in Verilog:

Generics (Parameters) Mapping Following VHDL generic types (and their Verilog equivalents) are supported.

 integer
 real
 string
 boolean

Note Any other generic type found on mixed language boundary is considered an error.


tl;dr

Is there a standard way to instantiate VHDL generics containing std_logic in a Verilog file? If not, what might be suggested as a workaround?

2
Try creating your Verilog with boolean instead of integer where you have a single bit signal. It's likely that your tools can convert boolean to std_logic and back, but I'm not surprised it rejects integer. - user_1818839
Can't you do it with 1'b1 or 1'b0 rather than using 1, which represents an integer? - Russell
@Rusell comment makes it work for me. I have accepted the more complete answer as it discusses standaridsation. - Damien

2 Answers

1
votes

There's no standard - you'll have to check your simulator docs. The Cadence docs say that "The LSB of the Verilog integer parameter is mapped to a single-bit std_logic generic". The relevant table rather unhelpfully refers to SV, but I'm pretty sure that this will also work for plain Verilog.

The MoldelSim/QuestaSim docs say that you can instantiate a VHDL design unit in Verilog or SV if "The generics are of type bit, bit_vector, integer, real, std_logic, std_logic_vector, vl_logic, vl_logic_vector, time, physical, enumeration, or string".

isim has always been a bit of a train wreck - are they still using it in Vivado? I'd rewrite the VHDL to take an integer generic if you're stuck with it.

0
votes

Try this:

synchroniser_d_flip_flop_n #(2, 4'd3, 4'd3) rx_sync_block(
    clk_i,
    rst, 
    rx_i,
    rx_sync
    );

std_logic can take any one of 9 enumerated values: {U,X,0,1,Z,W,L,H,-} so with 4'd3, you're specifying the 3rd value in this list. For logic 0, you'd pick 4'd2.