From a577ee447b51b80894d9951b5fb325854b356a7e Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Wed, 13 Aug 2008 17:03:03 +0100 Subject: [PATCH] Generate process for sequential UDPs --- tgt-vhdl/logic.cc | 46 ++++++++++++++++++++++++++++++++++++++++- tgt-vhdl/vhdl_syntax.cc | 2 +- tgt-vhdl/vhdl_syntax.hh | 2 +- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/tgt-vhdl/logic.cc b/tgt-vhdl/logic.cc index a5bc92fb5..97acb9a16 100644 --- a/tgt-vhdl/logic.cc +++ b/tgt-vhdl/logic.cc @@ -161,7 +161,51 @@ static void comb_udp_logic(vhdl_arch *arch, ivl_net_logic_t log) static void seq_udp_logic(vhdl_arch *arch, ivl_net_logic_t log) { - error("Sequential UDP devices not supported yet"); + ivl_udp_t udp = ivl_logic_udp(log); + + // These will be translated to a process with a single + // case statement + + vhdl_process *proc = new vhdl_process(ivl_logic_basename(log)); + + ostringstream ss; + ss << "Generated from UDP " << ivl_udp_name(udp); + proc->set_comment(ss.str().c_str()); + + // Create a variable to hold the concatenation of the inputs + int msb = ivl_udp_nin(udp) - 1; + vhdl_type *tmp_type = vhdl_type::std_logic_vector(msb, 0); + proc->get_scope()->add_decl(new vhdl_var_decl("UDP_Inputs", tmp_type)); + + // Concatenate the inputs into a single expression that can be + // used as the test in a case statement (this can't be inserted + // directly into the case statement due to the requirement that + // the test expression be "locally static") + int nin = ivl_udp_nin(udp); + vhdl_expr *tmp_rhs = NULL; + if (nin == 1) { + vhdl_var_ref *ref = + nexus_to_var_ref(arch->get_scope(), ivl_logic_pin(log, 1)); + tmp_rhs = ref->cast(tmp_type); + proc->add_sensitivity(ref->get_name()); + } + else { + vhdl_binop_expr *concat = new vhdl_binop_expr(VHDL_BINOP_CONCAT, NULL); + + for (int i = 1; i < nin; i++) { + vhdl_var_ref *ref = + nexus_to_var_ref(arch->get_scope(), ivl_logic_pin(log, i)); + concat->add_expr(ref); + proc->add_sensitivity(ref->get_name()); + } + + tmp_rhs = concat; + } + + proc->get_container()->add_stmt + (new vhdl_assign_stmt(new vhdl_var_ref("UDP_Inputs", NULL), tmp_rhs)); + + arch->add_stmt(proc); } static void udp_logic(vhdl_arch *arch, ivl_net_logic_t log) diff --git a/tgt-vhdl/vhdl_syntax.cc b/tgt-vhdl/vhdl_syntax.cc index e8dce1629..6bb246e4d 100644 --- a/tgt-vhdl/vhdl_syntax.cc +++ b/tgt-vhdl/vhdl_syntax.cc @@ -156,7 +156,7 @@ void vhdl_arch::emit(std::ostream &of, int level) const blank_line(of, level); // Extra blank line after architectures; } -void vhdl_process::add_sensitivity(const char *name) +void vhdl_process::add_sensitivity(const std::string &name) { sens_.push_back(name); } diff --git a/tgt-vhdl/vhdl_syntax.hh b/tgt-vhdl/vhdl_syntax.hh index 7180f4453..c1c63bd25 100644 --- a/tgt-vhdl/vhdl_syntax.hh +++ b/tgt-vhdl/vhdl_syntax.hh @@ -724,7 +724,7 @@ public: vhdl_process(const char *name = "") : name_(name) {} void emit(std::ostream &of, int level) const; - void add_sensitivity(const char *name); + void add_sensitivity(const std::string &name); private: std::string name_; string_list_t sens_;