openlane generates the powered verilog file that's...
# openlane
m
openlane generates the powered verilog file that's then used for LVS. Is there a way to generate the verilog from the GDS? I can extract the spice netlist, but is there a way to convert that verilog?
m
Years ago I did something like that. Extracted compiled ROM modules to spice, converted that to verilog, and then simulated the verilog to verify that the layout was correct for each memory address. Some of the analog circuitry required tweaking. With openlane, it should be pretty straight forward.
@Matt Venn Here's a simple script I just wrote to convert the
user_project_wrapper
extracted spice to verilog. It doesn't handle the input/output/inout declarations but you could probably pull those from the gate level verilog. Also passing bus signals to instances isn't pretty.
spi2v.sh <spice_file>
(Disclaimer: haven't tested the verilog!)
Copy code
cat spi2v.sh
#! /bin/sh

awk '
/^.subckt/ {
	if ( $2 ~ /sky130/ ) {
		subckt = $2;
		module = 0;
	} else {
		subckt = $2;
		module = 1;
	}
	$1 = "";
	$2 = "";
	ports[subckt] = $0;
	getline;
	while ( /^+/ ) {
		$1 = "";
		ports[subckt] = ports[subckt] $0;
		getline;
	}
	if ( module == 1 ) {
		print "module", subckt, "(";
		expandedPortCount = split(ports[subckt], expandedPortList);
		lastPort = "";
		delete minBusIndex;
		delete maxBusIndex;
		portCount = 0;
		delete portList;
		for ( portIndex = 1; portIndex < expandedPortCount; portIndex++ ) {
			arrayCount = split(expandedPortList[portIndex], bus, /[\[\]]/);
			if ( ! (bus[1] in minBusIndex) ) {
				portCount += 1;
				portList[portCount] = bus[1];	
				minBusIndex[bus[1]] = bus[2];
				maxBusIndex[bus[1]] = bus[2];
			}
			if ( arrayCount > 1 ) {
				minBusIndex[bus[1]] = min(minBusIndex[bus[1]], bus[2]);
				maxBusIndex[bus[1]] = max(maxBusIndex[bus[1]], bus[2]);
			}
		}
		for ( portIndex = 1; portIndex < portCount; portIndex++ ) {
			print "	" portList[portIndex] ",";
		}
		print "	" portList[portCount] ");"
		for ( portIndex = 1; portIndex < portCount; portIndex++ ) {
			net = portList[portIndex];
			if ( minBusIndex[net] == "" ) {
				print "	input", net ";";
			} else {
				print "	input [" maxBusIndex[net] ":" minBusIndex[net] "]", net ";";
			}
		}
	}
}
module == 1 && /^X/ {
	while ( /^X/ ) {
		instance = $1;
		$1 = "";
		nets = $0;
		subckt = $NF;
		getline;
		while ( /^+/ ) {
			$1 = "";
			nets = nets $0;
			subckt = $NF;
			getline;
		}
		portCount = split(ports[subckt], portList);
		netCount = split(nets, netList) - 1;
		if ( portCount != netCount ) {
			print "ERROR: net count match subckt/instance", portCount "/" netCount;
		}
		print subckt, instance, "(";
		for ( netIndex = 1; netIndex < netCount; netIndex++ ) {
			print "	." portList[netIndex] "(" netList[netIndex] "),";
		}
		print "	." portList[netCount] "(" netList[netCount] "));";
	}
}
module == 1 && /^.ends/ {
	print "endmodule";
}
function min(a, b) {
	if ( a < b ) return a; else return b;
}
function max(a, b) {
	if ( a > b ) return a; else return b;
}
' $1
m
wow, shell script!