add latch primitive for vlog95
This commit is contained in:
parent
99afea6946
commit
89333fa3a5
|
|
@ -364,6 +364,7 @@ static ivl_nexus_t get_lpm_output(ivl_scope_t scope, ivl_lpm_t lpm)
|
||||||
case IVL_LPM_CONCATZ:
|
case IVL_LPM_CONCATZ:
|
||||||
case IVL_LPM_DIVIDE:
|
case IVL_LPM_DIVIDE:
|
||||||
case IVL_LPM_FF:
|
case IVL_LPM_FF:
|
||||||
|
case IVL_LPM_LATCH:
|
||||||
case IVL_LPM_MOD:
|
case IVL_LPM_MOD:
|
||||||
case IVL_LPM_MULT:
|
case IVL_LPM_MULT:
|
||||||
case IVL_LPM_MUX:
|
case IVL_LPM_MUX:
|
||||||
|
|
@ -1437,8 +1438,27 @@ static void emit_negedge_dff_prim(void)
|
||||||
fprintf(vlog_out, "endprimitive\n");
|
fprintf(vlog_out, "endprimitive\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void emit_latch_prim(void)
|
||||||
|
{
|
||||||
|
fprintf(vlog_out, "\n");
|
||||||
|
fprintf(vlog_out, "/* Icarus generated UDP to represent a synthesized "
|
||||||
|
"LATCH. */\n");
|
||||||
|
fprintf(vlog_out, "primitive IVL_LATCH "
|
||||||
|
"(q, en, d);\n");
|
||||||
|
fprintf(vlog_out, "%*coutput q;\n", indent_incr, ' ');
|
||||||
|
fprintf(vlog_out, "%*cinput en, d;\n", indent_incr, ' ');
|
||||||
|
fprintf(vlog_out, "%*creg q;\n", indent_incr, ' ');
|
||||||
|
fprintf(vlog_out, "%*ctable\n", indent_incr, ' ');
|
||||||
|
fprintf(vlog_out, "%*c 1 0 : ? : 0 ;\n", 2*indent_incr, ' ');
|
||||||
|
fprintf(vlog_out, "%*c 1 1 : ? : 1 ;\n", 2*indent_incr, ' ');
|
||||||
|
fprintf(vlog_out, "%*c 0 ? : ? : - ;\n", 2*indent_incr, ' ');
|
||||||
|
fprintf(vlog_out, "%*cendtable\n", indent_incr, ' ');
|
||||||
|
fprintf(vlog_out, "endprimitive\n");
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned need_posedge_dff_prim = 0;
|
static unsigned need_posedge_dff_prim = 0;
|
||||||
static unsigned need_negedge_dff_prim = 0;
|
static unsigned need_negedge_dff_prim = 0;
|
||||||
|
static unsigned need_latch_prim = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Synthesis creates a D-FF LPM object. To allow this to be simulated as
|
* Synthesis creates a D-FF LPM object. To allow this to be simulated as
|
||||||
|
|
@ -1456,7 +1476,7 @@ void emit_icarus_generated_udps()
|
||||||
{
|
{
|
||||||
/* Emit the copyright information and LGPL note and then emit any
|
/* Emit the copyright information and LGPL note and then emit any
|
||||||
* needed primitives. */
|
* needed primitives. */
|
||||||
if (need_posedge_dff_prim || need_negedge_dff_prim) {
|
if (need_posedge_dff_prim || need_negedge_dff_prim || need_latch_prim) {
|
||||||
fprintf(vlog_out,
|
fprintf(vlog_out,
|
||||||
"\n"
|
"\n"
|
||||||
"/*\n"
|
"/*\n"
|
||||||
|
|
@ -1484,6 +1504,7 @@ void emit_icarus_generated_udps()
|
||||||
}
|
}
|
||||||
if (need_posedge_dff_prim) emit_posedge_dff_prim();
|
if (need_posedge_dff_prim) emit_posedge_dff_prim();
|
||||||
if (need_negedge_dff_prim) emit_negedge_dff_prim();
|
if (need_negedge_dff_prim) emit_negedge_dff_prim();
|
||||||
|
if (need_latch_prim) emit_latch_prim();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emit_lpm_ff(ivl_scope_t scope, ivl_lpm_t lpm)
|
static void emit_lpm_ff(ivl_scope_t scope, ivl_lpm_t lpm)
|
||||||
|
|
@ -1606,6 +1627,41 @@ static void emit_lpm_ff(ivl_scope_t scope, ivl_lpm_t lpm)
|
||||||
need_posedge_dff_prim = 1;
|
need_posedge_dff_prim = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void emit_lpm_latch(ivl_scope_t scope, ivl_lpm_t lpm)
|
||||||
|
{
|
||||||
|
ivl_nexus_t nex;
|
||||||
|
unsigned emitted;
|
||||||
|
|
||||||
|
fprintf(vlog_out, "%*c", indent, ' ');
|
||||||
|
fprintf(vlog_out, "IVL_LATCH");
|
||||||
|
emit_lpm_strength(lpm);
|
||||||
|
/* The lpm LATCH does not support any delays. */
|
||||||
|
/* The LATCH name is a temporary so we don't bother to print it unless
|
||||||
|
* we have a range. Then we need to use a made up name. */
|
||||||
|
if (ivl_lpm_width(lpm) > 1) {
|
||||||
|
fprintf(vlog_out, " synth_%p [%u:0]", lpm, ivl_lpm_width(lpm)-1U);
|
||||||
|
}
|
||||||
|
fprintf(vlog_out, " (");
|
||||||
|
/* Emit the q pin. */
|
||||||
|
emit_name_of_nexus(scope, ivl_lpm_q(lpm), 0);
|
||||||
|
fprintf(vlog_out, ", ");
|
||||||
|
/* Emit the enable pin expression(s) if needed. */
|
||||||
|
emitted = 0;
|
||||||
|
nex = ivl_lpm_enable(lpm);
|
||||||
|
if (nex) {
|
||||||
|
emit_nexus_as_ca(scope, nex, 0, 0);
|
||||||
|
emitted = 1;
|
||||||
|
}
|
||||||
|
if (!emitted) fprintf(vlog_out, "1'b1");
|
||||||
|
fprintf(vlog_out, ", ");
|
||||||
|
/* Emit the data pin expression(s). */
|
||||||
|
nex = ivl_lpm_data(lpm, 0);
|
||||||
|
assert (nex);
|
||||||
|
emit_nexus_as_ca(scope, nex, 0, 0);
|
||||||
|
fprintf(vlog_out, ");\n");
|
||||||
|
need_latch_prim = 1;
|
||||||
|
}
|
||||||
|
|
||||||
static ivl_signal_t get_output_from_nexus(ivl_scope_t scope, ivl_nexus_t nex,
|
static ivl_signal_t get_output_from_nexus(ivl_scope_t scope, ivl_nexus_t nex,
|
||||||
int64_t*array_idx)
|
int64_t*array_idx)
|
||||||
{
|
{
|
||||||
|
|
@ -1729,6 +1785,10 @@ void emit_lpm(ivl_scope_t scope, ivl_lpm_t lpm)
|
||||||
emit_lpm_ff(scope, lpm);
|
emit_lpm_ff(scope, lpm);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (type == IVL_LPM_LATCH) {
|
||||||
|
emit_lpm_latch(scope, lpm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// HERE: Look for a select passed to a pull device (pr2019553).
|
// HERE: Look for a select passed to a pull device (pr2019553).
|
||||||
/* Skip assignments to a module instantiation input. */
|
/* Skip assignments to a module instantiation input. */
|
||||||
if (output_is_module_instantiation_input(scope, output)) return;
|
if (output_is_module_instantiation_input(scope, output)) return;
|
||||||
|
|
@ -2199,6 +2259,7 @@ void dump_nexus_information(ivl_scope_t scope, ivl_nexus_t nex)
|
||||||
case IVL_LPM_CMP_NEE: fprintf(stderr, "nee"); break;
|
case IVL_LPM_CMP_NEE: fprintf(stderr, "nee"); break;
|
||||||
case IVL_LPM_DIVIDE: fprintf(stderr, "divide"); break;
|
case IVL_LPM_DIVIDE: fprintf(stderr, "divide"); break;
|
||||||
case IVL_LPM_FF: fprintf(stderr, "dff"); break;
|
case IVL_LPM_FF: fprintf(stderr, "dff"); break;
|
||||||
|
case IVL_LPM_LATCH: fprintf(stderr, "latch"); break;
|
||||||
case IVL_LPM_MOD: fprintf(stderr, "mod"); break;
|
case IVL_LPM_MOD: fprintf(stderr, "mod"); break;
|
||||||
case IVL_LPM_MULT: fprintf(stderr, "mult"); break;
|
case IVL_LPM_MULT: fprintf(stderr, "mult"); break;
|
||||||
case IVL_LPM_MUX: fprintf(stderr, "mux"); break;
|
case IVL_LPM_MUX: fprintf(stderr, "mux"); break;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue