With the rising complexity of digital designs and the deep sub-micron era right ahead, the specification and the design of embedded systems has to move to higher levels of abstraction. Co-design, the design of systems involving both hardware and software parts, consists of a set of refinement tasks that map an abstract specification of the design onto the intended system architecture. This article describes a generic co-design methodology including specification of the design at a high level of abstraction and step-wise refinement.