diff --git a/src/Convert.hs b/src/Convert.hs
index 83ab3ed..333cd2c 100644
--- a/src/Convert.hs
+++ b/src/Convert.hs
@@ -21,6 +21,7 @@ import qualified Convert.ForDecl
 import qualified Convert.Foreach
 import qualified Convert.FuncRet
 import qualified Convert.FuncRoutine
+import qualified Convert.ImplicitNet
 import qualified Convert.Inside
 import qualified Convert.Interface
 import qualified Convert.IntTypes
@@ -63,6 +64,7 @@ phases excludes =
     , Convert.FuncRet.convert
     , Convert.FuncRoutine.convert
     , Convert.EmptyArgs.convert
+    , Convert.ImplicitNet.convert
     , Convert.Inside.convert
     , Convert.IntTypes.convert
     , Convert.KWArgs.convert
diff --git a/src/Convert/ImplicitNet.hs b/src/Convert/ImplicitNet.hs
new file mode 100644
index 0000000..c71c250
--- /dev/null
+++ b/src/Convert/ImplicitNet.hs
@@ -0,0 +1,107 @@
+{-# LANGUAGE PatternSynonyms #-}
+{- sv2v
+ - Author: Zachary Snow <zach@zachjs.com>
+ -
+ - Create declarations for implicit nets
+ -}
+
+module Convert.ImplicitNet (convert) where
+
+import Control.Monad (when)
+import Data.List (isPrefixOf, mapAccumL)
+
+import Convert.Scoper
+import Language.SystemVerilog.AST
+
+type DefaultNetType = Maybe NetType
+
+convert :: [AST] -> [AST]
+convert =
+    snd . mapAccumL
+        (mapAccumL traverseDescription)
+        (Just TWire)
+
+traverseDescription :: DefaultNetType -> Description
+    -> (DefaultNetType, Description)
+traverseDescription defaultNetType (PackageItem (Directive str)) =
+    (defaultNetType', PackageItem $ Directive str)
+    where
+        prefix = "`default_nettype "
+        defaultNetType' =
+            if isPrefixOf prefix str
+                then parseDefaultNetType $ drop (length prefix) str
+                else defaultNetType
+traverseDescription defaultNetType (part @ Part{}) =
+    (defaultNetType, partScoper traverseDeclM
+        (traverseModuleItemM defaultNetType)
+        return return part)
+traverseDescription defaultNetType other = (defaultNetType, other)
+
+traverseDeclM :: Decl -> Scoper () Decl
+traverseDeclM decl = do
+    case decl of
+        Variable _ t x _ _ -> when (t /= unknownType) $ insertElem x ()
+        Param _ _ x _ -> insertElem x ()
+        ParamType{} -> return ()
+        CommentDecl{} -> return ()
+    return decl
+    where unknownType = Implicit Unspecified []
+
+traverseModuleItemM :: DefaultNetType -> ModuleItem -> Scoper () ModuleItem
+traverseModuleItemM _ (Genvar x) =
+    insertElem x () >> return (Genvar x)
+traverseModuleItemM defaultNetType (orig @ (Assign _ x _)) = do
+    needsLHS defaultNetType x
+    return orig
+traverseModuleItemM defaultNetType (orig @ (NInputGate _ _ x lhs exprs)) = do
+    insertElem x ()
+    needsLHS defaultNetType lhs
+    _ <- mapM (needsExpr defaultNetType) exprs
+    return orig
+traverseModuleItemM defaultNetType (orig @ (NOutputGate _ _ x lhss expr)) = do
+    insertElem x ()
+    _ <- mapM (needsLHS defaultNetType) lhss
+    needsExpr defaultNetType expr
+    return orig
+traverseModuleItemM defaultNetType (orig @ (Instance _ _ _ _ ports)) = do
+    _ <- mapM (needsExpr defaultNetType . snd) ports
+    return orig
+traverseModuleItemM _ item = return item
+
+needsExpr :: DefaultNetType -> Expr -> Scoper () ()
+needsExpr defaultNetType (Ident x) = needsIdent defaultNetType x
+needsExpr _ _ = return ()
+
+needsLHS :: DefaultNetType -> LHS -> Scoper () ()
+needsLHS defaultNetType (LHSIdent x) = needsIdent defaultNetType x
+needsLHS _ _ = return ()
+
+needsIdent :: DefaultNetType -> Identifier -> Scoper () ()
+needsIdent defaultNetType x = do
+    details <- lookupElemM x
+    when (details == Nothing) $ do
+        insertElem x ()
+        injectItem decl
+    where
+        t = impliedNetType x defaultNetType Unspecified []
+        decl = MIPackageItem $ Decl $ Variable Local t x [] Nil
+
+impliedNetType :: String -> DefaultNetType -> Signing -> [Range] -> Type
+impliedNetType var Nothing =
+    error $ "implicit declaration of " ++
+        show var ++ " but default_nettype is none"
+impliedNetType _ (Just netType) = Net (NetType netType)
+
+parseDefaultNetType :: String -> DefaultNetType
+parseDefaultNetType "tri"    = Just TTri
+parseDefaultNetType "triand" = Just TTriand
+parseDefaultNetType "trior"  = Just TTrior
+parseDefaultNetType "trireg" = Just TTrireg
+parseDefaultNetType "tri0"   = Just TTri0
+parseDefaultNetType "tri1"   = Just TTri1
+parseDefaultNetType "uwire"  = Just TUwire
+parseDefaultNetType "wire"   = Just TWire
+parseDefaultNetType "wand"   = Just TWand
+parseDefaultNetType "wor"    = Just TWor
+parseDefaultNetType "none"   = Nothing
+parseDefaultNetType str      = error $ "bad default_nettype: " ++ show str
diff --git a/sv2v.cabal b/sv2v.cabal
index 24dbc5f..d7df4ce 100644
--- a/sv2v.cabal
+++ b/sv2v.cabal
@@ -70,6 +70,7 @@ executable sv2v
     Convert.Foreach
     Convert.FuncRet
     Convert.FuncRoutine
+    Convert.ImplicitNet
     Convert.Inside
     Convert.Interface
     Convert.IntTypes
diff --git a/test/basic/implicit_net.sv b/test/basic/implicit_net.sv
new file mode 100644
index 0000000..c8cdef9
--- /dev/null
+++ b/test/basic/implicit_net.sv
@@ -0,0 +1,39 @@
+`define DISPLAY(expr) \
+    $display(`"expr = %b; $bits(expr) = %0d`", expr, $bits(expr));
+
+`default_nettype wor
+
+module Example(a, b, c);
+    input a, b, c;
+    initial begin
+        `DISPLAY(a)
+        `DISPLAY(b)
+        `DISPLAY(c)
+    end
+endmodule
+
+module top;
+    assign foo = 0;
+    type(foo) bar;
+    assign bar = 1;
+
+    and (o1, foo, bar);
+    not (o2, o3, foo);
+    not (u1, u2, u3);
+
+    Example e (a, b, c);
+
+    initial begin
+        `DISPLAY(foo)
+        `DISPLAY(bar)
+        `DISPLAY(o1)
+        `DISPLAY(o2)
+        `DISPLAY(o3)
+        `DISPLAY(u1)
+        `DISPLAY(u2)
+        `DISPLAY(u3)
+        `DISPLAY(a)
+        `DISPLAY(b)
+        `DISPLAY(c)
+    end
+endmodule
diff --git a/test/basic/implicit_net.v b/test/basic/implicit_net.v
new file mode 100644
index 0000000..e0590b0
--- /dev/null
+++ b/test/basic/implicit_net.v
@@ -0,0 +1,43 @@
+`define DISPLAY(expr) \
+    $display(`"expr = %b; $bits(expr) = %0d`", expr, $bits(expr));
+
+`default_nettype wor
+
+module Example(a, b, c);
+    input a, b, c;
+    initial begin
+        `DISPLAY(a)
+        `DISPLAY(b)
+        `DISPLAY(c)
+    end
+endmodule
+
+module top;
+    wor foo;
+    assign foo = 0;
+    wor bar;
+    assign bar = 1;
+
+    wor o1, o2, o3;
+    wor u1, u2, u3;
+    and (o1, foo, bar);
+    not (o2, o3, foo);
+    not (u1, u2, u3);
+
+    wor a, b, c;
+    Example e (a, b, c);
+
+    initial begin
+        `DISPLAY(foo)
+        `DISPLAY(bar)
+        `DISPLAY(o1)
+        `DISPLAY(o2)
+        `DISPLAY(o3)
+        `DISPLAY(u1)
+        `DISPLAY(u2)
+        `DISPLAY(u3)
+        `DISPLAY(a)
+        `DISPLAY(b)
+        `DISPLAY(c)
+    end
+endmodule