Added support for inferring counters with active-low reset

This commit is contained in:
Andrew Zonenberg 2017-09-13 15:32:20 -07:00
parent a84172b23b
commit 0484ad666d
1 changed files with 15 additions and 6 deletions

View File

@ -94,6 +94,7 @@ struct CounterExtraction
bool has_reset; //true if we have a reset bool has_reset; //true if we have a reset
bool has_ce; //true if we have a clock enable bool has_ce; //true if we have a clock enable
RTLIL::SigSpec rst; //reset pin RTLIL::SigSpec rst; //reset pin
bool rst_inverted; //true if reset is active low
int count_value; //value we count from int count_value; //value we count from
RTLIL::SigSpec ce; //clock signal RTLIL::SigSpec ce; //clock signal
RTLIL::SigSpec clk; //clock enable, if any RTLIL::SigSpec clk; //clock enable, if any
@ -236,10 +237,9 @@ int counter_tryextract(
{ {
extract.has_reset = true; extract.has_reset = true;
//Verify ARST_VALUE is zero and ARST_POLARITY is 1 //Verify ARST_VALUE is zero.
//TODO: infer an inverter to make it 1 if necessary, so we can support negative level resets? //Detect polarity inversions on reset.
if(count_reg->getParam("\\ARST_POLARITY").as_int() != 1) extract.rst_inverted = (count_reg->getParam("\\ARST_POLARITY").as_int() != 1);
return 22;
if(count_reg->getParam("\\ARST_VALUE").as_int() != 0) if(count_reg->getParam("\\ARST_VALUE").as_int() != 0)
return 23; return 23;
@ -418,7 +418,7 @@ void counter_worker(
"Register output is not full bus", //19 "Register output is not full bus", //19
"No init value found", //20 "No init value found", //20
"Underflow value is not equal to init value", //21 "Underflow value is not equal to init value", //21
"Reset polarity is not positive", //22 "RESERVED, not implemented", //22, kept for compatibility but not used anymore
"Reset is not to zero", //23 "Reset is not to zero", //23
"Clock enable configuration is unsupported" //24 "Clock enable configuration is unsupported" //24
}; };
@ -458,7 +458,16 @@ void counter_worker(
{ {
//TODO: support other kinds of reset //TODO: support other kinds of reset
cell->setParam("\\RESET_MODE", RTLIL::Const("LEVEL")); cell->setParam("\\RESET_MODE", RTLIL::Const("LEVEL"));
cell->setPort("\\RST", extract.rst);
//If the reset is active low, infer an inverter ($__COUNT_ cells always have active high reset)
if(extract.rst_inverted)
{
auto realreset = cell->module->addWire(NEW_ID);
cell->module->addNot(NEW_ID, extract.rst, RTLIL::SigSpec(realreset));
cell->setPort("\\RST", realreset);
}
else
cell->setPort("\\RST", extract.rst);
} }
else else
{ {