 (defmethod to-vhdl :entity [[type name ports defs & architecture]]
   (apply str (interpose "\n" (indent-lines
   (list
-    (spaces "entity" name "is")
-    "port("
+    (spaces "ENTITY" name "is")
+    "PORT("
     (commaify (map to-vhdl (map (partial cons :port) ports)))
     ");"
-    (str "end " name ";")
+    (str "END " name ";")
 
-    (str "architecture arch_" name " of " name " is")
+    (str "ARCHITECTURE arch_" name " OF " name " IS")
     (map to-vhdl defs)
-    "begin"
+    "BEGIN"
     (with-meta (map to-vhdl architecture) {:noindent true})
-    (str "end arch_" name ";"))))))
+    (str "END arch_" name ";"))))))
 
 ; does not generate lines like block-level methods do
 (defmethod to-vhdl :port [[type id direction type]]

  (:use clojure.contrib.str-utils))


(def std-logic "std_logic")

(defn std-logic-vector [start end]
  (str "std_logic_vector(" start " downto " end ")"))


(defn indented-lines [strings] (map (partial str "  ") strings))


(defmethod to-vhdl :process [[type ports & definition]]
  (list
    (str "PROCESS(" (str-join "," (map keyword-to-str ports)) ")")
    "BEGIN"
    (with-meta (map to-vhdl definition) {:noindent true})
    "END PROCESS;"))

(defmethod to-vhdl :case [[type target & cases]]
  (list
    (spaces "CASE" (keyword-to-str target) "IS")
    (map #(str (spaces "WHEN" (quoted-str (first %)) "=>" (to-vhdl (second %))) \;)
         (partition 2 cases))
    "END CASE;"))

; does not generate lines like block-level methods do
(defmethod to-vhdl :<= [[type target expression]]
  (spaces (keyword-to-str target) "<=" (keyword-to-str expression)))

(defmethod to-vhdl :signal [[type sig type]]
  (str "SIGNAL " (name sig) " : " type ";"))

(defmethod to-vhdl :deftype [[type name values]]
  (let [valuelist (str-join ", " values)]
    (spaces "TYPE" name "IS" "(" valuelist ");")))

(defmethod to-vhdl :if [[type condition & body]]
  (list
    (spaces "IF" (to-vhdl condition) "THEN")
    (with-meta (map to-vhdl body) {:noindent true})
    "END IF;"))

(defmethod to-vhdl :and [[type condA condB]]
  (spaces (to-vhdl condA) "AND" (to-vhdl condB)))

(defmethod to-vhdl :event [[type target]]
  (str (keyword-to-str target) "'EVENT"))
