diff --git a/tgt-vhdl/expr.cc b/tgt-vhdl/expr.cc index 2b8322683..555a50f43 100644 --- a/tgt-vhdl/expr.cc +++ b/tgt-vhdl/expr.cc @@ -320,6 +320,19 @@ static vhdl_expr *translate_binary(ivl_expr_t e) int rwidth = rhs->get_type()->get_width(); int result_width = ivl_expr_width(e); + // There's a funny corner-case where both the LHS and RHS are constant + // single bit numbers and the VHDL compiler can't decide between the + // std_ulogic and bit overloads of various operators + const bool lnumber = ivl_expr_type(ivl_expr_oper1(e)) == IVL_EX_NUMBER; + const bool rnumber = ivl_expr_type(ivl_expr_oper2(e)) == IVL_EX_NUMBER; + if (lwidth == 1 && rwidth == 1 && lnumber && rnumber) { + // It's sufficient to qualify only one side + vhdl_fcall *lqual = new vhdl_fcall("std_logic'", lhs->get_type()); + lqual->add_expr(lhs); + + lhs = lqual; + } + // For === and !== we need to compare std_logic_vectors // rather than signeds vhdl_type std_logic_vector(VHDL_TYPE_STD_LOGIC_VECTOR, result_width-1, 0); diff --git a/tgt-vhdl/lpm.cc b/tgt-vhdl/lpm.cc index 3c7c5bca4..7153ec06b 100644 --- a/tgt-vhdl/lpm.cc +++ b/tgt-vhdl/lpm.cc @@ -271,7 +271,7 @@ static vhdl_expr *lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm) case IVL_LPM_RE_XOR: return reduction_lpm_to_expr(scope, lpm, SF_REDUCE_XOR, false); case IVL_LPM_RE_XNOR: - return reduction_lpm_to_expr(scope, lpm, SF_REDUCE_XOR, true); + return reduction_lpm_to_expr(scope, lpm, SF_REDUCE_XNOR, true); case IVL_LPM_SIGN_EXT: return sign_extend_lpm_to_expr(scope, lpm); case IVL_LPM_ARRAY: diff --git a/tgt-vhdl/support.cc b/tgt-vhdl/support.cc index 6f16ba762..3a06efea7 100644 --- a/tgt-vhdl/support.cc +++ b/tgt-vhdl/support.cc @@ -144,7 +144,7 @@ void support_function::emit(std::ostream &of, int level) const emit_reduction(of, level, "and", '1'); break; case SF_REDUCE_XOR: - emit_reduction(of, level, "xnor", '0'); + emit_reduction(of, level, "xor", '0'); break; case SF_REDUCE_XNOR: emit_reduction(of, level, "xnor", '0');