diff --git a/src/Makefile_obj.in b/src/Makefile_obj.in
index e667bf5..07e9d62 100644
--- a/src/Makefile_obj.in
+++ b/src/Makefile_obj.in
@@ -206,6 +206,7 @@ RAW_OBJS = \
 	V3Premit.o \
 	V3Scope.o \
 	V3Signed.o \
+	V3Slice.o \
 	V3Split.o \
 	V3SplitAs.o \
 	V3Stats.o \
diff --git a/src/V3Ast.h b/src/V3Ast.h
index d3e39b2..a2c8e9d 100644
--- a/src/V3Ast.h
+++ b/src/V3Ast.h
@@ -1229,7 +1229,9 @@ struct AstNodeSel : public AstNodeBiop {
 	:AstNodeBiop(fl, fromp, bitp) {}
     ASTNODE_BASE_FUNCS(NodeSel)
     AstNode* fromp()		const { return op1p()->castNode(); }	// op1 = Extracting what (NULL=TBD during parsing)
+    void fromp(AstNode* nodep)	      { setOp1p(nodep); }
     AstNode* bitp()		const { return op2p()->castNode(); }	// op2 = Msb selection expression
+    void bitp(AstNode* nodep)	      { setOp2p(nodep); }
     int	     bitConst()	const;
 };
 
diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp
index 7238326..db5ff0f 100644
--- a/src/V3AstNodes.cpp
+++ b/src/V3AstNodes.cpp
@@ -258,6 +258,23 @@ uint32_t AstVar::arrayElements() const {
     return entries;
 }
 
+uint32_t AstVar::dimensions() const {
+    // How many array dimensions does this Var have?
+    uint32_t dim = 0;
+    for (AstNodeDType* dtypep=this->dtypep(); dtypep; ) {
+	dtypep = dtypep->skipRefp();  // Skip AstRefDType/AstTypedef, or return same node
+	if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
+	    dim += 1;
+	    dtypep = adtypep->dtypep();
+	}
+	else {
+	    // AstBasicDType - nothing below, 1
+	    break;
+	}
+    }
+    return dim;
+}
+
 // Special operators
 int AstArraySel::dimension(AstNode* nodep) {
     // How many dimensions is this reference from the base variable?
@@ -445,6 +462,10 @@ void AstNode::dump(ostream& os) {
     if (name()!="") os<<"  "<<AstNode::quoteName(name());
 }
 
+void AstArraySel::dump(ostream& str) {
+    this->AstNode::dump(str);
+    str<<" [start:"<<start()<<"] [length:"<<length()<<"]";
+}
 void AstAttrOf::dump(ostream& str) {
     this->AstNode::dump(str);
     str<<" ["<<attrType().ascii()<<"]";
diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h
index aff2260..370e75c 100644
--- a/src/V3AstNodes.h
+++ b/src/V3AstNodes.h
@@ -401,12 +401,16 @@ struct AstEnumDType : public AstNodeDType {
 struct AstArraySel : public AstNodeSel {
     // Parents: math|stmt
     // Children: varref|arraysel, math
+private:
+    unsigned m_start;
+    unsigned m_length;
+public:
     AstArraySel(FileLine* fl, AstNode* fromp, AstNode* bitp)
-	:AstNodeSel(fl, fromp, bitp) {
+	:AstNodeSel(fl, fromp, bitp), m_start(0), m_length(1) {
 	if (fromp) widthSignedFrom(fromp);
     }
     AstArraySel(FileLine* fl, AstNode* fromp, int bit)
-	:AstNodeSel(fl, fromp, new AstConst(fl,bit)) {
+	:AstNodeSel(fl, fromp, new AstConst(fl,bit)), m_start(0), m_length(1) {
 	if (fromp) widthSignedFrom(fromp);
     }
     ASTNODE_NODE_FUNCS(ArraySel, ARRAYSEL)
@@ -422,9 +426,14 @@ struct AstArraySel : public AstNodeSel {
     virtual V3Hash sameHash() const { return V3Hash(); }
     virtual bool same(AstNode* samep) const { return true; }
     virtual int instrCount() const { return widthInstrs(); }
+    unsigned length()                { return m_length; }
+    void     length(unsigned length) { m_length = length; }
+    void     start(unsigned start) { m_start = start; }
+    unsigned start(void)           { return m_start; }
     // Special operators
     static int dimension(AstNode* nodep); ///< How many dimensions is this reference from the base variable?
     static AstNode* baseFromp(AstNode* nodep);	///< What is the base variable (or const) this dereferences?
+    virtual void dump(ostream& str);
 };
 
 struct AstWordSel : public AstNodeSel {
@@ -603,6 +612,7 @@ public:
     AstNodeDType* dtypeSkipRefp() const { return dtypep()->skipRefp(); }	// op1 = Range of variable (Note don't need virtual - AstVar isn't a NodeDType)
     AstBasicDType* basicp() const { return dtypep()->basicp(); }  // (Slow) recurse down to find basic data type (Note don't need virtual - AstVar isn't a NodeDType)
     AstNodeDType* dtypeDimensionp(int depth) const;
+    uint32_t	dimensions() const;
     AstNode* 	initp()		const { return op3p()->castNode(); }	// op3 = Initial value that never changes (static const)
     void	initp(AstNode* nodep) { setOp3p(nodep); }
     void	addAttrsp(AstNode* nodep) { addNOp4p(nodep); }
diff --git a/src/V3Delayed.cpp b/src/V3Delayed.cpp
index eae03ad..28bd5ad 100644
--- a/src/V3Delayed.cpp
+++ b/src/V3Delayed.cpp
@@ -158,6 +158,7 @@ private:
 	    arrayselp = lhsp->castArraySel();
 	}
 	if (!arrayselp) nodep->v3fatalSrc("No arraysel under bitsel?");
+	UASSERT(arrayselp->length() == 1, "ArraySel with length!=1 should have been removed in V3Slice");
 
 	UINFO(4,"AssignDlyArray: "<<nodep<<endl);
 	//
diff --git a/src/V3Expand.cpp b/src/V3Expand.cpp
index 764438f..f708183 100644
--- a/src/V3Expand.cpp
+++ b/src/V3Expand.cpp
@@ -239,6 +239,7 @@ private:
 	return true;
     }
     bool expandWide (AstNodeAssign* nodep, AstArraySel* rhsp) {
+	UASSERT(rhsp->length() == 1, "ArraySel with length!=1 should have been removed in V3Slice");
 	UINFO(8,"    Wordize ASSIGN(ARRAYSEL) "<<nodep<<endl);
 	for (int w=0; w<nodep->widthWords(); w++) {
 	    addWordAssign(nodep, w, newAstWordSelClone (rhsp, w));
diff --git a/src/V3Slice.cpp b/src/V3Slice.cpp
new file mode 100644
index 0000000..9ad2232
--- /dev/null
+++ b/src/V3Slice.cpp
@@ -0,0 +1,348 @@
+//*************************************************************************
+// DESCRIPTION: Verilator: Parse module/signal name references
+//
+// Code available from: http://www.veripool.org/verilator
+//
+// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
+//
+//*************************************************************************
+//
+// Copyright 2003-2010 by Wilson Snyder.  This program is free software; you can
+// redistribute it and/or modify it under the terms of either the GNU
+// Lesser General Public License Version 3 or the Perl Artistic License
+// Version 2.0.
+//
+// Verilator is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+//*************************************************************************
+// Slice TRANSFORMATIONS:
+//	Top-down traversal (SliceVisitor):
+//	  NODEASSIGN
+//	    ARRAYSEL
+//	      Compare the dimensions to the Var to check for implicit slices.
+//	      Using ->length() calculate the number of clones needed.
+//	    VARREF
+//	      Check the dimensions of the Var for an implicit slice.
+//	      Replace with ArraySel nodes if needed.
+//	    SEL, EXTEND
+//	      We might be assigning a 1-D packed array to a 2-D packed array,
+//	      this is unsupported.
+//	    SliceCloneVisitor (called if this node is a slice):
+//	      NODEASSIGN
+//	        Clone and iterate the clone:
+//		  ARRAYSEL
+//		    Modify bitp() for the new value and set ->length(1)
+//*************************************************************************
+
+#include "config_build.h"
+#include "verilatedos.h"
+#include <cstdio>
+#include <cstdarg>
+#include <unistd.h>
+
+#include "V3Global.h"
+#include "V3Slice.h"
+#include "V3Ast.h"
+#include <vector>
+
+class SliceCloneVisitor : public AstNVisitor {
+private:
+    // NODE STATE
+    // Inputs:
+    //  AstArraySel::user1p()	    -> AstVarRef. The VarRef that the final ArraySel points to
+    //  AstNodeAssign::user2()	    -> int. The number of clones needed for this assign
+
+    // STATE
+    std::vector<std::vector<unsigned> >	    m_selBits;	    // Indexes of the ArraySel we are expanding
+    int					    m_vecIdx;	    // Current vector index
+    unsigned				    m_depth;	    // Number of ArraySel's from the VarRef
+    AstVarRef*				    m_refp;	    // The VarRef under this ArraySel
+
+    // METHODS
+    virtual void visit(AstArraySel* nodep, AstNUser*) {
+	if (!nodep->backp()->castArraySel()) {
+	    // This is the top of an ArraySel, setup
+	    m_refp = nodep->user1p()->castNode()->castVarRef();
+	    m_vecIdx += 1;
+	    if (m_vecIdx == m_selBits.size()) {
+		m_selBits.push_back(std::vector<unsigned>());
+		AstVar* varp = m_refp->varp();
+		int dimensions = varp->dimensions();
+		for (int i = 0; i < dimensions; ++i) {
+		    m_selBits[m_vecIdx].push_back(0);
+		}
+	    }
+	}
+	nodep->iterateChildren(*this);
+	if (nodep->fromp()->castVarRef()) {
+	    m_depth = 0;
+	} else {
+	    ++m_depth;
+	}
+	// Check if m_selBits has overflowed
+	if (m_selBits[m_vecIdx][m_depth] >= nodep->length()) {
+	    m_selBits[m_vecIdx][m_depth] = 0;
+	    if (m_depth + 1 < m_selBits[m_vecIdx].size())
+		m_selBits[m_vecIdx][m_depth+1] += 1;
+	}
+	// Reassign the bitp()
+	if (nodep->length() > 1) {
+	    if (AstConst* bitp = nodep->bitp()->castConst()) {
+		unsigned idx = nodep->start() + m_selBits[m_vecIdx][m_depth];
+		AstNode* constp = new AstConst(bitp->fileline(), V3Number(bitp->fileline(), bitp->castConst()->num().width(), idx));
+		bitp->replaceWith(constp);
+	    } else {
+		nodep->v3error("Unsupported: Only constants supported in slices");
+	    }
+	}
+	if (!nodep->backp()->castArraySel()) {
+	    // Top ArraySel, increment m_selBits
+	    m_selBits[m_vecIdx][0] += 1;
+	}
+	nodep->length(1);
+    }
+
+    virtual void visit(AstNodeAssign* nodep, AstNUser*) {
+	m_selBits.clear();
+	UINFO(4, "Cloning "<<nodep->user2()<<" times: "<<nodep<<endl);
+	for (int i = 0; i < nodep->user2(); ++i) {
+	    // Clone the node and iterate over the clone
+	    m_vecIdx = -1;
+	    AstNodeAssign* clonep = nodep->cloneTree(false)->castNodeAssign();
+	    clonep->iterateChildren(*this);
+	    nodep->addNextHere(clonep);
+	}
+	nodep->unlinkFrBack(false)->deleteTree(); nodep = NULL;
+    }
+
+    virtual void visit(AstNode* nodep, AstNUser*) {
+	// Default: Just iterate
+	nodep->iterateChildren(*this);
+    }
+public:
+    // CONSTUCTORS
+    SliceCloneVisitor(AstNodeAssign* assignp) {
+	assignp->accept(*this);
+    }
+    virtual ~SliceCloneVisitor() {}
+};
+
+class SliceVisitor : public AstNVisitor {
+private:
+    // NODE STATE
+    // Cleared on netlist
+    //  AstNodeAssign::user1()	    -> bool.  True if find is complete
+    //  AstNodeAssign::user2()	    -> int. The number of clones needed for this assign
+    //  AstArraySel::user1p()	    -> AstVarRef. The VarRef that the final ArraySel points to
+    AstUser1InUse	m_inuser1;
+    AstUser2InUse	m_inuser2;
+
+    // STATE
+    AstNode*		    m_assign;	    // The assignment we are under
+    AstNodeVarRef*	    m_lhspVarRef;   // Var on the LHS
+    bool		    m_extend;	    // True if we have found an extend node
+
+    // METHODS
+    virtual void visit(AstVarRef* nodep, AstNUser*) {
+	// The LHS/RHS of an Assign may be to a Var that is an array. In this
+	// case we need to create a slice accross the entire Var
+	if (m_assign && !nodep->backp()->castArraySel()) {
+	    uint32_t dimensions = nodep->varp()->dimensions();
+	    if (dimensions > 0) {
+		AstNode* newp = insertImplicit(nodep->cloneTree(false), 1, dimensions);
+		nodep->replaceWith(newp); nodep = NULL;
+		newp->iterateChildren(*this);
+	    }
+	}
+    }
+
+    // Find out how many explicit dimensions are in a given ArraySel.
+    unsigned explicitDimensions(AstArraySel* nodep) {
+	unsigned dim = 0;
+	AstNode* fromp = nodep;
+	AstArraySel* selp;
+	do {
+	    selp = fromp->castArraySel();
+	    if (!selp) {
+		nodep->user1p(fromp->castVarRef());
+		selp = NULL;
+	    } else {
+		fromp = selp->fromp();
+		if (fromp)
+		    ++dim;
+	    }
+	} while (fromp && selp);
+	UASSERT(m_assign->user1p(), "Couldn't find VarRef under the ArraySel");
+	return dim;
+    }
+
+    AstNode* insertImplicit(AstVarRef* nodep, unsigned start, unsigned count) {
+	// Insert any implicit slices as explicit slices (ArraySel nodes).
+	// Return a new pointer to replace fromp() in the ArraySel.
+	AstVarRef* fromp = nodep;
+	UASSERT(fromp, "NULL VarRef passed to insertImplicit");
+	AstVar* varp = fromp->varp();
+	// Get the DType and insert a new ArraySel
+	AstArraySel* topp = NULL;
+	AstArraySel* bottomp = NULL;
+	for (unsigned i = start; i < start + count; ++i) {
+	    AstNodeDType* dtypep = varp->dtypeDimensionp(i-1);
+	    AstArrayDType* adtypep = dtypep->castArrayDType();
+	    UASSERT(adtypep, "insertImplicit tried to expand an array without an ArrayDType");
+	    vlsint32_t msb = adtypep->msb();
+	    vlsint32_t lsb = adtypep->lsb();
+	    if (lsb > msb) {
+		// Below code assumes big bit endian; just works out if we swap
+		int x = msb; msb = lsb; lsb = x;
+	    }
+	    AstArraySel* newp = new AstArraySel(nodep->fileline(), fromp, new AstConst(nodep->fileline(),lsb));
+	    newp->start(lsb);
+	    newp->length(msb - lsb + 1);
+	    if (!topp)
+		topp = newp;
+	    fromp = newp->fromp()->unlinkFrBack()->castVarRef();
+
+	    if (bottomp)
+		bottomp->fromp(newp);
+	    bottomp = newp;
+	}
+	bottomp->fromp(fromp);
+	return topp;
+    }
+
+    int countClones(AstArraySel* nodep) {
+	// Count how many clones we need to make from this ArraySel
+	int clones = 1;
+	AstNode* fromp = nodep;
+	AstArraySel* selp;
+	do {
+	    selp = fromp->castArraySel();
+	    fromp = (selp) ? selp->fromp() : NULL;
+	    if (fromp && selp)
+		clones *= selp->length();
+	} while (fromp && selp);
+	return clones;
+    }
+
+    virtual void visit(AstExtend* nodep, AstNUser*) {
+	m_extend = true;
+	if (m_assign && m_assign->user2() > 1) {
+	    m_assign->v3error("Unsupported: Assignment between packed arrays of different dimensions");
+	}
+	nodep->iterateChildren(*this);
+    }
+
+    virtual void visit(AstArraySel* nodep, AstNUser*) {
+	if (!m_assign)
+	    return;
+	unsigned dim = explicitDimensions(nodep);
+	AstVarRef* refp = nodep->user1p()->castNode()->castVarRef();
+	unsigned implicit = refp->varp()->dimensions() - dim;
+	if (implicit > 0) {
+	    AstNode* backp = refp->backp();
+	    AstNode* newp = insertImplicit(refp->cloneTree(false), dim+1, implicit);
+	    backp->castArraySel()->fromp()->replaceWith(newp);
+	}
+	int clones = countClones(nodep);
+	if (m_assign->user2() > 0 && m_assign->user2() != clones) {
+	    m_assign->v3error("Slices of arrays in assignments must have the same unpacked dimensions");
+	} else if (m_assign->user2() == 0) {
+	    if (m_extend && clones > 1) {
+		m_assign->v3error("Unsupported: Assignment between packed arrays of different dimensions");
+	    }
+	    if (clones > 1 && !refp->lvalue() && refp->varp() == m_lhspVarRef->varp() && !m_assign->castAssignDly()) {
+	        // LHS Var != RHS Var for a non-delayed assignment
+		m_assign->v3error("Unsupported: Slices in a non-delayed assignment with the same Var on both sides");
+	    }
+	    m_assign->user2(clones);
+	}
+    }
+
+    virtual void visit(AstSel* nodep, AstNUser*) {
+	m_extend = true;
+	if (m_assign && m_assign->user2() > 1) {
+	    m_assign->v3error("Unsupported: Assignment between packed arrays of different dimensions");
+	}
+	nodep->iterateChildren(*this);
+    }
+
+    // Return the first AstVarRef under the node
+    AstVarRef* findVarRefRecurse(AstNode* nodep)
+    {
+	AstVarRef* refp;
+	if (refp = nodep->castVarRef())
+	    return refp;
+	if (nodep->op1p()) {
+	    refp = findVarRefRecurse(nodep->op1p());
+	    if (refp) return refp;
+	}
+	if (nodep->op2p()) {
+	    refp = findVarRefRecurse(nodep->op2p());
+	    if (refp) return refp;
+	}
+	if (nodep->op3p()) {
+	    refp = findVarRefRecurse(nodep->op3p());
+	    if (refp) return refp;
+	}
+	if (nodep->op3p()) {
+	    refp = findVarRefRecurse(nodep->op3p());
+	    if (refp) return refp;
+	}
+	if (nodep->nextp()) {
+	    refp = findVarRefRecurse(nodep->nextp());
+	    if (refp) return refp;
+	}
+	return NULL;
+    }
+
+    void findImplicit(AstNodeAssign* nodep) {
+	UASSERT(!m_assign, "Found a NodeAssign under another NodeAssign");
+	m_assign = nodep;
+	m_extend = false;
+	nodep->user1(true);
+	// Record the LHS Var so we can check if the Var on the RHS is the same
+	m_lhspVarRef = findVarRefRecurse(nodep->lhsp());
+	UASSERT(m_lhspVarRef, "Couldn't find a VarRef on the LHSP of an Assign");
+	// Iterate children looking for ArraySel nodes. From that we get the number of elements
+	// in the array so we know how many times we need to clone this assignment.
+	nodep->iterateChildren(*this);
+	if (nodep->user2() > 1) {
+	    SliceCloneVisitor scv(nodep);
+	}
+	m_assign = NULL;
+    }
+
+    virtual void visit(AstNodeAssign* nodep, AstNUser*) {
+	if (!nodep->user1()) {
+	    // Hasn't been searched for implicit slices yet
+	    findImplicit(nodep);
+	}
+    }
+
+    virtual void visit(AstNode* nodep, AstNUser*) {
+	// Default: Just iterate
+	nodep->iterateChildren(*this);
+    }
+
+public:
+    // CONSTUCTORS
+    SliceVisitor(AstNetlist* rootp) {
+	m_assign = NULL;
+	m_lhspVarRef = NULL;
+	AstNode::user1ClearTree();
+	AstNode::user2ClearTree();
+	rootp->accept(*this);
+    }
+    virtual ~SliceVisitor() {}
+};
+
+//######################################################################
+// Link class functions
+
+void V3Slice::expandAll(AstNetlist* rootp) {
+    UINFO(4,__FUNCTION__<<": "<<endl);
+    SliceVisitor visitor(rootp);
+}
diff --git a/src/V3Slice.h b/src/V3Slice.h
new file mode 100644
index 0000000..c8001bf
--- /dev/null
+++ b/src/V3Slice.h
@@ -0,0 +1,37 @@
+// -*- C++ -*-
+//*************************************************************************
+// DESCRIPTION: Verilator: Link modules/signals together
+//
+// Code available from: http://www.veripool.org/verilator
+//
+// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
+//
+//*************************************************************************
+//
+// Copyright 2003-2009 by Wilson Snyder.  This program is free software; you can
+// redistribute it and/or modify it under the terms of either the GNU
+// Lesser General Public License Version 3 or the Perl Artistic License
+// Version 2.0.
+//
+// Verilator is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+//*************************************************************************
+
+#ifndef _V3LINKSLICE_H_
+#define _V3LINKSLICE_H_ 1
+#include "config_build.h"
+#include "verilatedos.h"
+#include "V3Error.h"
+#include "V3Ast.h"
+
+//============================================================================
+
+class V3Slice {
+public:
+    static void expandAll(AstNetlist* nodep);
+};
+
+#endif // Guard
diff --git a/src/V3WidthSel.cpp b/src/V3WidthSel.cpp
index a7b6670..fedf175 100644
--- a/src/V3WidthSel.cpp
+++ b/src/V3WidthSel.cpp
@@ -80,10 +80,6 @@ private:
 	//UINFO(9,"SCD\n"); if (debug()>=9) nodep->backp()->dumpTree(cout,"-selcheck: ");
 	AstNodeDType* ddtypep = varp->dtypeDimensionp(dimension);
 	if (AstArrayDType* adtypep = ddtypep->castArrayDType()) {
-	    if (rangedSelect) {
-		nodep->v3error("Illegal bit select; can't bit extract from arrayed dimension: "<<varp->prettyName());
-		return NULL;
-	    }
 	    return adtypep;
 	}
 	else if (AstBasicDType* adtypep = ddtypep->castBasicDType()) {
@@ -247,7 +243,17 @@ private:
 	vlsint32_t msb = msbp->castConst()->toSInt();
 	vlsint32_t lsb = lsbp->castConst()->toSInt();
 	AstNodeDType* ddtypep = dtypeForExtractp(nodep, basefromp, dimension, msb!=lsb);
-	if (AstBasicDType* adtypep = ddtypep->castBasicDType()) {
+	if (AstArrayDType* adtypep = ddtypep->castArrayDType()) {
+	    if (msb!=lsb) {
+		AstArraySel* newp = new AstArraySel	(nodep->fileline(),
+						     fromp, lsbp);
+		newp->start(lsb);
+		newp->length((msb - lsb) + 1);
+		nodep->replaceWith(newp); pushDeletep(nodep); nodep=NULL;
+	    } else {
+		nodep->v3error("Illegal bit select; can't bit extract from arrayed dimension: "<<varp->prettyName());
+	    }
+	} else if (AstBasicDType* adtypep = ddtypep->castBasicDType()) {
 	    if (adtypep) {} // Unused
 	    if (varp->basicp()->rangep() && varp->basicp()->rangep()->littleEndian()) {
 		// Below code assumes big bit endian; just works out if we swap
diff --git a/src/Verilator.cpp b/src/Verilator.cpp
index 867385f..555345b 100644
--- a/src/Verilator.cpp
+++ b/src/Verilator.cpp
@@ -74,6 +74,7 @@
 #include "V3Premit.h"
 #include "V3Scope.h"
 #include "V3Signed.h"
+#include "V3Slice.h"
 #include "V3Split.h"
 #include "V3SplitAs.h"
 #include "V3Stats.h"
@@ -280,6 +281,10 @@ void process () {
     V3Unroll::unrollAll(v3Global.rootp());
     v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("unroll.tree"));
 
+    // Expand slices of arrays
+    V3Slice::expandAll(v3Global.rootp());
+    v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("slices.tree"));
+
     // Convert case statements to if() blocks.  Must be after V3Unknown
     V3Case::caseAll(v3Global.rootp());
     v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("case.tree"));
diff --git a/test_regress/t/t_mem_multi_ref_bad.pl b/test_regress/t/t_mem_multi_ref_bad.pl
index 1e005cf..d3bf5be 100755
--- a/test_regress/t/t_mem_multi_ref_bad.pl
+++ b/test_regress/t/t_mem_multi_ref_bad.pl
@@ -12,15 +12,16 @@ compile (
 	 nc=>0,  # Need to get it not to give the prompt
 	 expect=>
 q{%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension: dimn
+.*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal range select; variable already selected, or bad dimension
 .*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension: dim0
+.*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension
 .*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension: dim1
-.*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit select; can't bit extract from arrayed dimension: dim2
-.*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit select; can't bit extract from arrayed dimension: dim2
-.*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit select; can't bit extract from arrayed dimension: dim0nv
+.*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension
+.*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal \+: or -: select; variable already selected, or bad dimension
 .*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension: dim0nv
+.*%Error: t/t_mem_multi_ref_bad.v:\d+: Illegal bit or array select; variable already selected, or bad dimension
 .*%Error: Exiting due to.*},
 	 );
 
 ok(1);
 1;
-
diff --git a/test_regress/t/t_mem_packed_assign.pl b/test_regress/t/t_mem_packed_assign.pl
new file mode 100755
index 0000000..bc60bff
--- /dev/null
+++ b/test_regress/t/t_mem_packed_assign.pl
@@ -0,0 +1,20 @@
+#!/usr/bin/perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2003 by Wilson Snyder. This program is free software; you can
+# redistribute it and/or modify it under the terms of either the GNU
+# Lesser General Public License Version 3 or the Perl Artistic License
+# Version 2.0.
+
+compile (
+         v_flags => ["--lint-only"],
+	 fails=>1,
+	 expect=>
+'%Error: t/t_mem_packed_assign.v:\d+: Unsupported: Assignment between packed arrays of different dimensions
+%Error: t/t_mem_packed_assign.v:\d+: Unsupported: Assignment between packed arrays of different dimensions
+%Error: Exiting due to.*',
+	 );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_mem_packed_assign.v b/test_regress/t/t_mem_packed_assign.v
new file mode 100644
index 0000000..dfec487
--- /dev/null
+++ b/test_regress/t/t_mem_packed_assign.v
@@ -0,0 +1,36 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed into the Public Domain, for any use,
+// without warranty, 2009 by Wilson Snyder.
+
+module t (/*AUTOARG*/
+   // Inputs
+   clk
+   );
+
+   /* verilator lint_off WIDTH */
+
+   input clk;
+
+   integer cyc; initial cyc = 0;
+   logic [31:0] arr_c; initial arr_c = 0;
+   logic [7:0] [3:0] arr;
+
+   logic [31:0] arr2_c; initial arr2_c = 0;
+   logic [7:0] [3:0] arr2;
+   assign arr2_c = arr2;
+
+   always @ (posedge clk) begin
+      cyc <= cyc + 1;
+      arr_c <= arr_c + 1;
+      arr2 <= arr2 + 1;
+      $write("cyc%0d c:%0x a0:%0x a1:%0x a2:%0x a3:%0x\n", cyc, arr_c, arr[0], arr[1], arr[2], arr[3]);
+      if (cyc==99) begin
+	 $write("*-* All Finished *-*\n");
+	 $finish;
+      end
+   end
+
+   /* verilator lint_on WIDTH */
+
+endmodule
diff --git a/test_regress/t/t_mem_slice.pl b/test_regress/t/t_mem_slice.pl
new file mode 100755
index 0000000..639bb98
--- /dev/null
+++ b/test_regress/t/t_mem_slice.pl
@@ -0,0 +1,19 @@
+#!/usr/bin/perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2003 by Wilson Snyder. This program is free software; you can
+# redistribute it and/or modify it under the terms of either the GNU
+# Lesser General Public License Version 3 or the Perl Artistic License
+# Version 2.0.
+
+compile (
+	 v_flags => [],
+	 );
+
+execute (
+	 check_finished=>1,
+     );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_mem_slice.v b/test_regress/t/t_mem_slice.v
new file mode 100644
index 0000000..a87d6a0
--- /dev/null
+++ b/test_regress/t/t_mem_slice.v
@@ -0,0 +1,117 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed into the Public Domain, for any use,
+// without warranty, 2009 by Wilson Snyder.
+
+module t (/*AUTOARG*/
+   // Inputs
+   clk
+   );
+
+   input clk;
+
+   logic       use_AnB;
+   logic [1:0] active_command [8:0];
+   logic [1:0] command_A      [8:0];
+   logic [1:0] command_B      [8:0];
+
+   logic [1:0] active_command2 [8:0];
+   logic [1:0] command_A2      [8:0];
+   logic [1:0] command_B2      [8:0];
+
+   logic [1:0] active_command3 [1:0][2:0][3:0];
+   logic [1:0] command_A3      [1:0][2:0][3:0];
+   logic [1:0] command_B3      [1:0][2:0][3:0];
+
+   logic [8:0] pipe1	      [7:0];
+   logic [8:0] pipe1_input;
+
+   integer cyc;
+
+   assign active_command[8:0] = (use_AnB) ? command_A[8:0] : command_B[8:0];
+   assign active_command2 = (use_AnB) ? command_A2 : command_B2;
+   assign active_command3[1:0][2:0][3:0] = (use_AnB) ?  command_A3[1:0][2:0][3:0] : command_B3[1:0][2:0][3:0];
+
+   always @ (posedge clk) begin
+      pipe1_input <= pipe1_input + 1;
+      pipe1[0]    <= pipe1_input;
+      pipe1[7:1]  <= pipe1[6:0];
+   end
+
+   logic [3:0][13:0] iq_read_data [15:0];
+   logic [3:0][13:0] iq_data;
+   logic [3:0]       sel;
+
+   assign iq_data = iq_read_data[sel];
+
+   always @ (posedge clk) begin
+      sel = sel + 1;
+   end
+
+   initial begin
+      cyc = 0;
+      use_AnB = 0;
+      for (int i = 0; i < 7; ++i) begin
+	 command_A[i] = 2'b00;
+	 command_B[i] = 2'b11;
+	 command_A2[i] = 2'b00;
+	 command_B2[i] = 2'b11;
+	 pipe1_input = 9'b0;
+      end
+      for (int i = 0; i < 2; ++i) begin
+	 for (int j = 0; j < 3; ++j) begin
+	    for (int k = 0; k < 4; ++k) begin
+	       command_A3[i][j][k] = 2'b00;
+	       command_B3[i][j][k] = 2'b11;
+	    end
+	 end
+      end
+   end
+
+   always @ (posedge clk) begin
+      use_AnB <= ~use_AnB;
+      cyc <= cyc + 1;
+      if (use_AnB) begin
+	 if (active_command[3] != 2'b00) begin
+	    $stop;
+	 end
+	 if (active_command2[3] != 2'b00) begin
+	    $stop;
+	 end
+	 if (active_command3[0][1][2] != 2'b00) begin
+	    $stop;
+	 end
+      end
+      if (!use_AnB) begin
+	 if (active_command[3] != 2'b11) begin
+	    $stop;
+	 end
+	 if (active_command2[3] != 2'b11) begin
+	    $stop;
+	 end
+	 if (active_command3[3][1][2] != 2'b11) begin
+	    $stop;
+	 end
+      end
+   end
+
+   logic [8:0] last_pipe;
+   always @(posedge clk) begin
+      if (cyc < 3) begin
+	 last_pipe <= pipe1[0];
+      end
+      else begin
+	 if (last_pipe + 1 != pipe1[0]) begin
+	    $stop;
+	 end
+	 else begin
+	    last_pipe <= pipe1[0];
+	 end
+      end
+      if (cyc > 10) begin
+	 $write("*-* All Finished *-*\n");
+	 $finish;
+      end
+   end
+
+endmodule : t
diff --git a/test_regress/t/t_mem_slice_bad.pl b/test_regress/t/t_mem_slice_bad.pl
new file mode 100755
index 0000000..820350f
--- /dev/null
+++ b/test_regress/t/t_mem_slice_bad.pl
@@ -0,0 +1,25 @@
+#!/usr/bin/perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2008 by Wilson Snyder. This program is free software; you can
+# redistribute it and/or modify it under the terms of either the GNU
+# Lesser General Public License Version 3 or the Perl Artistic License
+# Version 2.0.
+
+compile (
+	 v_flags2 => ["--lint-only"],
+	 fails=>1,
+	 expect=>
+'%Error: t/t_mem_slice_bad.v:\d+: Slices of arrays in assignments must have the same unpacked dimensions
+%Error: t/t_mem_slice_bad.v:\d+: Slices of arrays in assignments must have the same unpacked dimensions
+%Error: t/t_mem_slice_bad.v:\d+: Slices of arrays in assignments must have the same unpacked dimensions
+%Error: t/t_mem_slice_bad.v:\d+: Slices of arrays in assignments must have the same unpacked dimensions
+%Error: t/t_mem_slice_bad.v:\d+: Unsupported: Slices in a non-delayed assignment with the same Var on both sides
+%Error: t/t_mem_slice_bad.v:\d+: Slices of arrays in assignments must have the same unpacked dimensions
+%Error: t/t_mem_slice_bad.v:\d+: Slices of arrays in assignments must have the same unpacked dimensions
+%Error: Exiting due to.*',
+	 ) if $Self->{v3};
+
+ok(1);
+1;
diff --git a/test_regress/t/t_mem_slice_bad.v b/test_regress/t/t_mem_slice_bad.v
new file mode 100644
index 0000000..f14bc22
--- /dev/null
+++ b/test_regress/t/t_mem_slice_bad.v
@@ -0,0 +1,58 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed into the Public Domain, for any use,
+// without warranty, 2009 by Wilson Snyder.
+
+module t (/*AUTOARG*/
+   // Inputs
+   clk
+   );
+
+   input clk;
+
+   logic       use_AnB;
+
+   logic [1:0] active_command  [8:0];
+   logic [1:0] command_A       [8:0];
+   logic [1:0] command_B       [8:0];
+
+   logic [1:0] active_command2 [8:0];
+   logic [1:0] command_A2      [7:0];
+   logic [1:0] command_B2      [8:0];
+
+   logic [1:0] active_command3 [1:0][2:0][3:0];
+   logic [1:0] command_A3      [1:0][2:0][3:0];
+   logic [1:0] command_B3      [1:0][2:0][3:0];
+
+   logic [1:0] active_command4 [8:0];
+   logic [1:0] command_A4      [7:0];
+
+   logic [1:0] active_command5 [8:0];
+   logic [1:0] command_A5      [7:0];
+
+   // Single dimension assign
+   assign active_command[3:0] = (use_AnB) ? command_A[7:0] : command_B[7:0];
+   // Assignment of entire arrays
+   assign active_command2 = (use_AnB) ? command_A2 : command_B2;
+   // Multi-dimension assign
+   assign active_command3[1:0][2:0][3:0] = (use_AnB) ?  command_A3[1:0][2:0][3:0] : command_B3[1:0][1:0][3:0];
+
+   // Supported: Delayed assigment with RHS Var == LHS Var
+   logic [7:0] arrd [7:0];
+   always_ff @(posedge clk) arrd[7:4] <= arrd[3:0];
+
+   // Unsupported: Non-delayed assigment with RHS Var == LHS Var
+   logic [7:0] arr [7:0];
+   assign arr[7:4] = arr[3:0];
+
+   // Delayed assign
+   always @(posedge clk) begin
+      active_command4[7:0] <= command_A4[8:0];
+   end
+
+   // Combinational assign
+   always_comb begin
+      active_command5[8:0] = command_A5[7:0];
+   end
+
+endmodule : t

