From 0484ad666d765c84d7a06a97ee9c7f6280733ed8 Mon Sep 17 00:00:00 2001
From: Andrew Zonenberg <azonenberg@drawersteak.com>
Date: Wed, 13 Sep 2017 15:32:20 -0700
Subject: Added support for inferring counters with active-low reset

---
 passes/techmap/extract_counter.cc | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

(limited to 'passes')

diff --git a/passes/techmap/extract_counter.cc b/passes/techmap/extract_counter.cc
index ec34d9cd1..3746a3cb6 100644
--- a/passes/techmap/extract_counter.cc
+++ b/passes/techmap/extract_counter.cc
@@ -94,6 +94,7 @@ struct CounterExtraction
 	bool has_reset;					//true if we have a reset
 	bool has_ce;					//true if we have a clock enable
 	RTLIL::SigSpec rst;				//reset pin
+	bool rst_inverted;				//true if reset is active low
 	int count_value;				//value we count from
 	RTLIL::SigSpec ce;				//clock signal
 	RTLIL::SigSpec clk;				//clock enable, if any
@@ -236,10 +237,9 @@ int counter_tryextract(
 	{
 		extract.has_reset = true;
 
-		//Verify ARST_VALUE is zero and ARST_POLARITY is 1
-		//TODO: infer an inverter to make it 1 if necessary, so we can support negative level resets?
-		if(count_reg->getParam("\\ARST_POLARITY").as_int() != 1)
-			return 22;
+		//Verify ARST_VALUE is zero.
+		//Detect polarity inversions on reset.
+		extract.rst_inverted = (count_reg->getParam("\\ARST_POLARITY").as_int() != 1);
 		if(count_reg->getParam("\\ARST_VALUE").as_int() != 0)
 			return 23;
 
@@ -418,7 +418,7 @@ void counter_worker(
 			"Register output is not full bus",				//19
 			"No init value found",							//20
 			"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
 			"Clock enable configuration is unsupported"		//24
 		};
@@ -458,7 +458,16 @@ void counter_worker(
 	{
 		//TODO: support other kinds of reset
 		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
 	{
-- 
cgit v1.2.3