diff options
23 files changed, 1490 insertions, 45 deletions
diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index fd7f20cc6..40d05a036 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -306,17 +306,8 @@ struct FirrtlWorker // If this is a parameterized module, its parent module is encoded in the cell type if (cell->type.begins_with("$paramod")) { - std::string::iterator it; - for (it = cell_type.begin(); it < cell_type.end(); it++) - { - switch (*it) { - case '\\': /* FALL_THROUGH */ - case '=': /* FALL_THROUGH */ - case '\'': /* FALL_THROUGH */ - case '$': instanceOf.append("_"); break; - default: instanceOf.append(1, *it); break; - } - } + log_assert(cell->has_attribute(ID::hdlname)); + instanceOf = cell->get_string_attribute(ID::hdlname); } else { diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 245a53611..9ddd538b5 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -218,6 +218,7 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch realvalue = 0; id2ast = NULL; basic_prep = false; + lookahead = false; if (child1) children.push_back(child1); @@ -310,6 +311,10 @@ void AstNode::dumpAst(FILE *f, std::string indent) const fprintf(f, " reg"); if (is_signed) fprintf(f, " signed"); + if (basic_prep) + fprintf(f, " basic_prep"); + if (lookahead) + fprintf(f, " lookahead"); if (port_id > 0) fprintf(f, " port=%d", port_id); if (range_valid || range_left != -1 || range_right != 0) @@ -1565,6 +1570,9 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::Id rewritten.reserve(GetSize(parameters)); AstNode *new_ast = ast->clone(); + if (!new_ast->attributes.count(ID::hdlname)) + new_ast->attributes[ID::hdlname] = AstNode::mkconst_str(stripped_name); + para_counter = 0; for (auto child : new_ast->children) { if (child->type != AST_PARAMETER) diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 3dd40238f..3f6329112 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -202,6 +202,9 @@ namespace AST // this is used by simplify to detect if basic analysis has been performed already on the node bool basic_prep; + // this is used for ID references in RHS expressions that should use the "new" value for non-blocking assignments + bool lookahead; + // this is the original sourcecode location that resulted in this AST node // it is automatically set by the constructor using AST::current_filename and // the AST::get_line_num() callback function. @@ -352,6 +355,7 @@ namespace AST_INTERNAL extern AST::AstNode *current_always, *current_top_block, *current_block, *current_block_child; extern AST::AstModule *current_module; extern bool current_always_clocked; + struct LookaheadRewriter; struct ProcessGenerator; } diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index ab368fdb0..ff3f5b84c 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -157,6 +157,126 @@ static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const return wire; } +// helper class for rewriting simple lookahead references in AST always blocks +struct AST_INTERNAL::LookaheadRewriter +{ + dict<IdString, pair<AstNode*, AstNode*>> lookaheadids; + + void collect_lookaheadids(AstNode *node) + { + if (node->lookahead) { + log_assert(node->type == AST_IDENTIFIER); + if (!lookaheadids.count(node->str)) { + AstNode *wire = new AstNode(AST_WIRE); + for (auto c : node->id2ast->children) + wire->children.push_back(c->clone()); + wire->str = stringf("$lookahead%s$%d", node->str.c_str(), autoidx++); + wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false); + wire->is_logic = true; + while (wire->simplify(true, false, false, 1, -1, false, false)) { } + current_ast_mod->children.push_back(wire); + lookaheadids[node->str] = make_pair(node->id2ast, wire); + wire->genRTLIL(); + } + } + + for (auto child : node->children) + collect_lookaheadids(child); + } + + bool has_lookaheadids(AstNode *node) + { + if (node->type == AST_IDENTIFIER && lookaheadids.count(node->str) != 0) + return true; + + for (auto child : node->children) + if (has_lookaheadids(child)) + return true; + + return false; + } + + bool has_nonlookaheadids(AstNode *node) + { + if (node->type == AST_IDENTIFIER && lookaheadids.count(node->str) == 0) + return true; + + for (auto child : node->children) + if (has_nonlookaheadids(child)) + return true; + + return false; + } + + void rewrite_lookaheadids(AstNode *node, bool lhs = false) + { + if (node->type == AST_ASSIGN_LE) + { + if (has_lookaheadids(node->children[0])) + { + if (has_nonlookaheadids(node->children[0])) + log_error("incompatible mix of lookahead and non-lookahead IDs in LHS expression.\n"); + + rewrite_lookaheadids(node->children[0], true); + node->type = AST_ASSIGN_EQ; + } + + rewrite_lookaheadids(node->children[1], lhs); + return; + } + + if (node->type == AST_IDENTIFIER && (node->lookahead || lhs)) { + AstNode *newwire = lookaheadids.at(node->str).second; + node->str = newwire->str; + node->id2ast = newwire; + lhs = false; + } + + for (auto child : node->children) + rewrite_lookaheadids(child, lhs); + } + + LookaheadRewriter(AstNode *top) + { + // top->dumpAst(NULL, "REWRITE-BEFORE> "); + // top->dumpVlog(NULL, "REWRITE-BEFORE> "); + + AstNode *block = nullptr; + + for (auto c : top->children) + if (c->type == AST_BLOCK) { + log_assert(block == nullptr); + block = c; + } + log_assert(block != nullptr); + + collect_lookaheadids(block); + rewrite_lookaheadids(block); + + for (auto it : lookaheadids) + { + AstNode *ref_orig = new AstNode(AST_IDENTIFIER); + ref_orig->str = it.second.first->str; + ref_orig->id2ast = it.second.first; + ref_orig->was_checked = true; + + AstNode *ref_temp = new AstNode(AST_IDENTIFIER); + ref_temp->str = it.second.second->str; + ref_temp->id2ast = it.second.second; + ref_temp->was_checked = true; + + AstNode *init_assign = new AstNode(AST_ASSIGN_EQ, ref_temp->clone(), ref_orig->clone()); + AstNode *final_assign = new AstNode(AST_ASSIGN_LE, ref_orig, ref_temp); + + block->children.insert(block->children.begin(), init_assign); + block->children.push_back(final_assign); + } + + // top->dumpAst(NULL, "REWRITE-AFTER> "); + // top->dumpVlog(NULL, "REWRITE-AFTER> "); + } +}; + // helper class for converting AST always nodes to RTLIL processes struct AST_INTERNAL::ProcessGenerator { @@ -191,6 +311,9 @@ struct AST_INTERNAL::ProcessGenerator ProcessGenerator(AstNode *always, RTLIL::SigSpec initSyncSignalsArg = RTLIL::SigSpec()) : always(always), initSyncSignals(initSyncSignalsArg) { + // rewrite lookahead references + LookaheadRewriter la_rewriter(always); + // generate process and simple root case proc = new RTLIL::Process; proc->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", always->filename.c_str(), always->location.first_line, always->location.first_column, always->location.last_line, always->location.last_column); @@ -338,7 +461,7 @@ struct AST_INTERNAL::ProcessGenerator return chunks; } - // recursively traverse the AST an collect all assigned signals + // recursively traverse the AST and collect all assigned signals void collect_lvalues(RTLIL::SigSpec ®, AstNode *ast, bool type_eq, bool type_le, bool run_sort_and_unify = true) { switch (ast->type) @@ -1010,7 +1133,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) int add_undef_bits_msb = 0; int add_undef_bits_lsb = 0; - if (id2ast && id2ast->type == AST_AUTOWIRE && current_module->wires_.count(str) == 0) { + log_assert(id2ast != nullptr); + + if (id2ast->type == AST_AUTOWIRE && current_module->wires_.count(str) == 0) { RTLIL::Wire *wire = current_module->addWire(str); wire->attributes[ID::src] = stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column); wire->name = str; @@ -1025,7 +1150,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) chunk = RTLIL::Const(id2ast->children[0]->bits); goto use_const_chunk; } - else if (id2ast && (id2ast->type == AST_WIRE || id2ast->type == AST_AUTOWIRE || id2ast->type == AST_MEMORY) && current_module->wires_.count(str) != 0) { + else if ((id2ast->type == AST_WIRE || id2ast->type == AST_AUTOWIRE || id2ast->type == AST_MEMORY) && current_module->wires_.count(str) != 0) { RTLIL::Wire *current_wire = current_module->wire(str); if (current_wire->get_bool_attribute(ID::is_interface)) is_interface = true; diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 467afdd87..837c14ad7 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1754,8 +1754,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } // replace dynamic ranges in left-hand side expressions (e.g. "foo[bar] <= 1'b1;") with - // a big case block that selects the correct single-bit assignment. - if (type == AST_ASSIGN_EQ || type == AST_ASSIGN_LE) { + // either a big case block that selects the correct single-bit assignment, or mask and + // shift operations. + if (type == AST_ASSIGN_EQ || type == AST_ASSIGN_LE) + { if (children[0]->type != AST_IDENTIFIER || children[0]->children.size() == 0) goto skip_dynamic_range_lvalue_expansion; if (children[0]->children[0]->range_valid || did_something) @@ -1764,10 +1766,13 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, goto skip_dynamic_range_lvalue_expansion; if (!children[0]->id2ast->range_valid) goto skip_dynamic_range_lvalue_expansion; + int source_width = children[0]->id2ast->range_left - children[0]->id2ast->range_right + 1; int result_width = 1; + AstNode *shift_expr = NULL; AstNode *range = children[0]->children[0]; + if (range->children.size() == 1) { shift_expr = range->children[0]->clone(); } else { @@ -1780,19 +1785,72 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, log_file_error(filename, location.first_line, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); result_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1; } - did_something = true; - newNode = new AstNode(AST_CASE, shift_expr); - for (int i = 0; i < source_width; i++) { - int start_bit = children[0]->id2ast->range_right + i; - AstNode *cond = new AstNode(AST_COND, mkconst_int(start_bit, true)); + + if (0) + { + // big case block + + did_something = true; + newNode = new AstNode(AST_CASE, shift_expr); + for (int i = 0; i < source_width; i++) { + int start_bit = children[0]->id2ast->range_right + i; + AstNode *cond = new AstNode(AST_COND, mkconst_int(start_bit, true)); + AstNode *lvalue = children[0]->clone(); + lvalue->delete_children(); + int end_bit = std::min(start_bit+result_width,source_width) - 1; + lvalue->children.push_back(new AstNode(AST_RANGE, + mkconst_int(end_bit, true), mkconst_int(start_bit, true))); + cond->children.push_back(new AstNode(AST_BLOCK, new AstNode(type, lvalue, children[1]->clone()))); + newNode->children.push_back(cond); + } + } + else + { + // mask and shift operations, disabled for now + + AstNode *wire_mask = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(source_width-1, true), mkconst_int(0, true))); + wire_mask->str = stringf("$bitselwrite$mask$%s:%d$%d", filename.c_str(), location.first_line, autoidx++); + wire_mask->attributes["\\nosync"] = AstNode::mkconst_int(1, false); + wire_mask->is_logic = true; + while (wire_mask->simplify(true, false, false, 1, -1, false, false)) { } + current_ast_mod->children.push_back(wire_mask); + + AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(source_width-1, true), mkconst_int(0, true))); + wire_data->str = stringf("$bitselwrite$data$%s:%d$%d", filename.c_str(), location.first_line, autoidx++); + wire_data->attributes["\\nosync"] = AstNode::mkconst_int(1, false); + wire_data->is_logic = true; + while (wire_data->simplify(true, false, false, 1, -1, false, false)) { } + current_ast_mod->children.push_back(wire_data); + + did_something = true; + newNode = new AstNode(AST_BLOCK); + AstNode *lvalue = children[0]->clone(); lvalue->delete_children(); - int end_bit = std::min(start_bit+result_width,source_width) - 1; - lvalue->children.push_back(new AstNode(AST_RANGE, - mkconst_int(end_bit, true), mkconst_int(start_bit, true))); - cond->children.push_back(new AstNode(AST_BLOCK, new AstNode(type, lvalue, children[1]->clone()))); - newNode->children.push_back(cond); + + AstNode *ref_mask = new AstNode(AST_IDENTIFIER); + ref_mask->str = wire_mask->str; + ref_mask->id2ast = wire_mask; + ref_mask->was_checked = true; + + AstNode *ref_data = new AstNode(AST_IDENTIFIER); + ref_data->str = wire_data->str; + ref_data->id2ast = wire_data; + ref_data->was_checked = true; + + AstNode *old_data = lvalue->clone(); + if (type == AST_ASSIGN_LE) + old_data->lookahead = true; + + AstNode *shamt = shift_expr; + + newNode->children.push_back(new AstNode(AST_ASSIGN_EQ, ref_mask->clone(), + new AstNode(AST_SHIFT_LEFT, mkconst_bits(std::vector<RTLIL::State>(result_width, State::S1), false), shamt->clone()))); + newNode->children.push_back(new AstNode(AST_ASSIGN_EQ, ref_data->clone(), + new AstNode(AST_SHIFT_LEFT, new AstNode(AST_BIT_AND, mkconst_bits(std::vector<RTLIL::State>(result_width, State::S1), false), children[1]->clone()), shamt))); + newNode->children.push_back(new AstNode(type, lvalue, new AstNode(AST_BIT_OR, new AstNode(AST_BIT_AND, old_data, new AstNode(AST_BIT_NOT, ref_mask)), ref_data))); } + goto apply_newNode; } skip_dynamic_range_lvalue_expansion:; diff --git a/frontends/rpc/rpc_frontend.cc b/frontends/rpc/rpc_frontend.cc index a23f7548e..46ee6a733 100644 --- a/frontends/rpc/rpc_frontend.cc +++ b/frontends/rpc/rpc_frontend.cc @@ -217,6 +217,8 @@ struct RpcModule : RTLIL::Module { module.second->name = mangled_name; module.second->design = design; module.second->attributes.erase(ID::top); + if (!module.second->has_attribute(ID::hdlname)) + module.second->set_string_attribute(ID::hdlname, module.first.str()); design->modules_[mangled_name] = module.second; derived_design->modules_.erase(module.first); } diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 8ae1b51ff..78c902866 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -467,7 +467,12 @@ void prep_lut(RTLIL::Design *design, int maxlut) { TimingInfo timing; - std::vector<std::tuple<int, IdString, int, std::vector<int>>> table; + struct t_lut { + IdString name; + int area; + std::vector<int> delays; + }; + std::map<int,t_lut> table; for (auto module : design->modules()) { auto it = module->attributes.find(ID::abc9_lut); if (it == module->attributes.end()) @@ -476,40 +481,52 @@ void prep_lut(RTLIL::Design *design, int maxlut) auto &t = timing.setup_module(module); TimingInfo::NameBit o; - std::vector<int> specify; + std::vector<int> delays; for (const auto &i : t.comb) { auto &d = i.first.second; if (o == TimingInfo::NameBit()) o = d; else if (o != d) - log_error("(* abc9_lut *) module '%s' with has more than one output.\n", log_id(module)); - specify.push_back(i.second); + log_error("Module '%s' with (* abc9_lut *) has more than one output.\n", log_id(module)); + delays.push_back(i.second); } - if (maxlut && GetSize(specify) > maxlut) + if (GetSize(delays) == 0) + log_error("Module '%s' with (* abc9_lut *) has no specify entries.\n", log_id(module)); + if (maxlut && GetSize(delays) > maxlut) continue; // ABC requires non-decreasing LUT input delays - std::sort(specify.begin(), specify.end()); - table.emplace_back(GetSize(specify), module->name, it->second.as_int(), std::move(specify)); + std::sort(delays.begin(), delays.end()); + + int K = GetSize(delays); + auto entry = t_lut{module->name, it->second.as_int(), std::move(delays)}; + auto r = table.emplace(K, entry); + if (!r.second) { + if (r.first->second.area != entry.area) + log_error("Modules '%s' and '%s' have conflicting (* abc9_lut *) values.\n", log_id(module), log_id(r.first->second.name)); + if (r.first->second.delays != entry.delays) + log_error("Modules '%s' and '%s' have conflicting specify entries.\n", log_id(module), log_id(r.first->second.name)); + } } - // ABC requires ascending size - std::sort(table.begin(), table.end()); + + if (table.empty()) + log_error("Design does not contain any modules with (* abc9_lut *).\n"); std::stringstream ss; - const auto &first = table.front(); + const auto &front = *table.begin(); // If the first entry does not start from a 1-input LUT, // (as ABC requires) crop the first entry to do so - for (int i = 1; i < std::get<0>(first); i++) { + for (int i = 1; i < front.first; i++) { ss << "# $__ABC9_LUT" << i << std::endl; - ss << i << " " << std::get<2>(first); + ss << i << " " << front.second.area; for (int j = 0; j < i; j++) - ss << " " << std::get<3>(first)[j]; + ss << " " << front.second.delays[j]; ss << std::endl; } for (const auto &i : table) { - ss << "# " << log_id(std::get<1>(i)) << std::endl; - ss << std::get<0>(i) << " " << std::get<2>(i); - for (const auto &j : std::get<3>(i)) + ss << "# " << log_id(i.second.name) << std::endl; + ss << i.first << " " << i.second.area; + for (const auto &j : i.second.delays) ss << " " << j; ss << std::endl; } diff --git a/tests/arch/ecp5/memories.ys b/tests/arch/ecp5/memories.ys index e1f748e26..f55bf01d2 100644 --- a/tests/arch/ecp5/memories.ys +++ b/tests/arch/ecp5/memories.ys @@ -208,7 +208,6 @@ select -assert-count 1 t:PDPW16KD design -reset; read_verilog ../common/blockrom.v chparam -set ADDRESS_WIDTH 3 -set DATA_WIDTH 36 sync_rom -write_ilang synth_ecp5 -top sync_rom; cd sync_rom select -assert-count 0 t:PDPW16KD # too inefficient select -assert-min 18 t:LUT4 @@ -274,7 +273,6 @@ select -assert-count 1 t:DP16KD design -reset; read_verilog ../common/blockrom.v chparam -set ADDRESS_WIDTH 3 -set DATA_WIDTH 18 sync_rom -write_ilang synth_ecp5 -top sync_rom; cd sync_rom select -assert-count 0 t:DP16KD # too inefficient select -assert-min 9 t:LUT4 diff --git a/tests/arch/ice40/memories.ys b/tests/arch/ice40/memories.ys index 571edec1d..c32f12315 100644 --- a/tests/arch/ice40/memories.ys +++ b/tests/arch/ice40/memories.ys @@ -112,7 +112,6 @@ select -assert-count 1 t:SB_RAM40_4K design -reset; read_verilog ../common/blockrom.v chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom -write_ilang synth_ice40 -top sync_rom; cd sync_rom select -assert-count 0 t:SB_RAM40_4K # too inefficient select -assert-min 1 t:SB_LUT4 diff --git a/tests/various/abc9.ys b/tests/various/abc9.ys index 0c7695089..6e2415ad7 100644 --- a/tests/various/abc9.ys +++ b/tests/various/abc9.ys @@ -53,3 +53,22 @@ assign q = w; endmodule EOT abc9 -lut 4 -dff + + +design -reset +read_verilog -icells -specify <<EOT +(* abc9_lut=1, blackbox *) +module LUT2(input [1:0] i, output o); +parameter [3:0] mask = 0; +assign o = i[0] ? (i[1] ? mask[3] : mask[2]) + : (i[1] ? mask[1] : mask[0]); +specify + (i *> o) = 1; +endspecify +endmodule + +module top(input [1:0] i, output o); +LUT2 #(.mask(4'b0)) lut (.i(i), .o(o)); +endmodule +EOT +abc9 diff --git a/tests/various/dynamic_part_select.ys b/tests/various/dynamic_part_select.ys new file mode 100644 index 000000000..abc1daad6 --- /dev/null +++ b/tests/various/dynamic_part_select.ys @@ -0,0 +1,106 @@ +### Original testcase ### +read_verilog ./dynamic_part_select/original.v +proc +rename -top gold +design -stash gold + +read_verilog ./dynamic_part_select/original_gate.v +proc +rename -top gate +design -stash gate + +design -copy-from gold -as gold gold +design -copy-from gate -as gate gate + +miter -equiv -make_assert -make_outcmp -flatten gold gate equiv +sat -prove-asserts -seq 10 -show-public -verify -set-init-zero equiv + +### Multiple blocking assingments ### +design -reset +read_verilog ./dynamic_part_select/multiple_blocking.v +proc +rename -top gold +design -stash gold + +read_verilog ./dynamic_part_select/multiple_blocking_gate.v +proc +rename -top gate +design -stash gate + +design -copy-from gold -as gold gold +design -copy-from gate -as gate gate + +miter -equiv -make_assert -make_outcmp -flatten gold gate equiv +sat -prove-asserts -seq 10 -show-public -verify -set-init-zero equiv + +### Non-blocking to the same output register ### +design -reset +read_verilog ./dynamic_part_select/nonblocking.v +proc +rename -top gold +design -stash gold + +read_verilog ./dynamic_part_select/nonblocking_gate.v +proc +rename -top gate +design -stash gate + +design -copy-from gold -as gold gold +design -copy-from gate -as gate gate + +miter -equiv -make_assert -make_outcmp -flatten gold gate equiv +sat -prove-asserts -seq 10 -show-public -verify -set-init-zero equiv + +### For-loop select, one dynamic input +design -reset +read_verilog ./dynamic_part_select/forloop_select.v +proc +rename -top gold +design -stash gold + +read_verilog ./dynamic_part_select/forloop_select_gate.v +proc +rename -top gate +design -stash gate + +design -copy-from gold -as gold gold +design -copy-from gate -as gate gate + +miter -equiv -make_assert -make_outcmp -flatten gold gate equiv +sat -prove-asserts -seq 10 -show-public -verify -set-init-zero equiv + +#### Double loop (part-select, reset) ### +design -reset +read_verilog ./dynamic_part_select/reset_test.v +proc +rename -top gold +design -stash gold + +read_verilog ./dynamic_part_select/reset_test_gate.v +proc +rename -top gate +design -stash gate + +design -copy-from gold -as gold gold +design -copy-from gate -as gate gate + +miter -equiv -make_assert -make_outcmp -flatten gold gate equiv +sat -prove-asserts -seq 10 -show-public -verify -set-init-zero equiv + +### Reversed part-select case ### +design -reset +read_verilog ./dynamic_part_select/reversed.v +proc +rename -top gold +design -stash gold + +read_verilog ./dynamic_part_select/reversed_gate.v +proc +rename -top gate +design -stash gate + +design -copy-from gold -as gold gold +design -copy-from gate -as gate gate + +miter -equiv -make_assert -make_outcmp -flatten gold gate equiv +sat -prove-asserts -seq 10 -show-public -verify -set-init-zero equiv diff --git a/tests/various/dynamic_part_select/forloop_select.v b/tests/various/dynamic_part_select/forloop_select.v new file mode 100644 index 000000000..8260f3186 --- /dev/null +++ b/tests/various/dynamic_part_select/forloop_select.v @@ -0,0 +1,19 @@ +module forloop_select #(parameter WIDTH=16, SELW=4, CTRLW=$clog2(WIDTH), DINW=2**SELW) + (input clk, + input [CTRLW-1:0] ctrl, + input [DINW-1:0] din, + input en, + output reg [WIDTH-1:0] dout); + + reg [SELW:0] sel; + localparam SLICE = WIDTH/(SELW**2); + + always @(posedge clk) + begin + if (en) begin + for (sel = 0; sel <= 4'hf; sel=sel+1'b1) + dout[(ctrl*sel)+:SLICE] <= din; + end + end +endmodule + diff --git a/tests/various/dynamic_part_select/forloop_select_gate.v b/tests/various/dynamic_part_select/forloop_select_gate.v new file mode 100644 index 000000000..71ae88537 --- /dev/null +++ b/tests/various/dynamic_part_select/forloop_select_gate.v @@ -0,0 +1,559 @@ +module forloop_select_gate (clk, ctrl, din, en, dout); + input clk; + input [3:0] ctrl; + input [15:0] din; + input en; + output reg [15:0] dout; + reg [4:0] sel; + always @(posedge clk) + case (|(en)) + 1'b 1: + begin + case (({(ctrl)*(0)})+(0)) + 0: + dout[0:0] <= din; + 1: + dout[1:1] <= din; + 2: + dout[2:2] <= din; + 3: + dout[3:3] <= din; + 4: + dout[4:4] <= din; + 5: + dout[5:5] <= din; + 6: + dout[6:6] <= din; + 7: + dout[7:7] <= din; + 8: + dout[8:8] <= din; + 9: + dout[9:9] <= din; + 10: + dout[10:10] <= din; + 11: + dout[11:11] <= din; + 12: + dout[12:12] <= din; + 13: + dout[13:13] <= din; + 14: + dout[14:14] <= din; + 15: + dout[15:15] <= din; + endcase + case (({(ctrl)*(5'b 00001)})+(0)) + 0: + dout[0:0] <= din; + 1: + dout[1:1] <= din; + 2: + dout[2:2] <= din; + 3: + dout[3:3] <= din; + 4: + dout[4:4] <= din; + 5: + dout[5:5] <= din; + 6: + dout[6:6] <= din; + 7: + dout[7:7] <= din; + 8: + dout[8:8] <= din; + 9: + dout[9:9] <= din; + 10: + dout[10:10] <= din; + 11: + dout[11:11] <= din; + 12: + dout[12:12] <= din; + 13: + dout[13:13] <= din; + 14: + dout[14:14] <= din; + 15: + dout[15:15] <= din; + endcase + case (({(ctrl)*(5'b 00010)})+(0)) + 0: + dout[0:0] <= din; + 1: + dout[1:1] <= din; + 2: + dout[2:2] <= din; + 3: + dout[3:3] <= din; + 4: + dout[4:4] <= din; + 5: + dout[5:5] <= din; + 6: + dout[6:6] <= din; + 7: + dout[7:7] <= din; + 8: + dout[8:8] <= din; + 9: + dout[9:9] <= din; + 10: + dout[10:10] <= din; + 11: + dout[11:11] <= din; + 12: + dout[12:12] <= din; + 13: + dout[13:13] <= din; + 14: + dout[14:14] <= din; + 15: + dout[15:15] <= din; + endcase + case (({(ctrl)*(5'b 00011)})+(0)) + 0: + dout[0:0] <= din; + 1: + dout[1:1] <= din; + 2: + dout[2:2] <= din; + 3: + dout[3:3] <= din; + 4: + dout[4:4] <= din; + 5: + dout[5:5] <= din; + 6: + dout[6:6] <= din; + 7: + dout[7:7] <= din; + 8: + dout[8:8] <= din; + 9: + dout[9:9] <= din; + 10: + dout[10:10] <= din; + 11: + dout[11:11] <= din; + 12: + dout[12:12] <= din; + 13: + dout[13:13] <= din; + 14: + dout[14:14] <= din; + 15: + dout[15:15] <= din; + endcase + case (({(ctrl)*(5'b 00100)})+(0)) + 0: + dout[0:0] <= din; + 1: + dout[1:1] <= din; + 2: + dout[2:2] <= din; + 3: + dout[3:3] <= din; + 4: + dout[4:4] <= din; + 5: + dout[5:5] <= din; + 6: + dout[6:6] <= din; + 7: + dout[7:7] <= din; + 8: + dout[8:8] <= din; + 9: + dout[9:9] <= din; + 10: + dout[10:10] <= din; + 11: + dout[11:11] <= din; + 12: + dout[12:12] <= din; + 13: + dout[13:13] <= din; + 14: + dout[14:14] <= din; + 15: + dout[15:15] <= din; + endcase + case (({(ctrl)*(5'b 00101)})+(0)) + 0: + dout[0:0] <= din; + 1: + dout[1:1] <= din; + 2: + dout[2:2] <= din; + 3: + dout[3:3] <= din; + 4: + dout[4:4] <= din; + 5: + dout[5:5] <= din; + 6: + dout[6:6] <= din; + 7: + dout[7:7] <= din; + 8: + dout[8:8] <= din; + 9: + dout[9:9] <= din; + 10: + dout[10:10] <= din; + 11: + dout[11:11] <= din; + 12: + dout[12:12] <= din; + 13: + dout[13:13] <= din; + 14: + dout[14:14] <= din; + 15: + dout[15:15] <= din; + endcase + case (({(ctrl)*(5'b 00110)})+(0)) + 0: + dout[0:0] <= din; + 1: + dout[1:1] <= din; + 2: + dout[2:2] <= din; + 3: + dout[3:3] <= din; + 4: + dout[4:4] <= din; + 5: + dout[5:5] <= din; + 6: + dout[6:6] <= din; + 7: + dout[7:7] <= din; + 8: + dout[8:8] <= din; + 9: + dout[9:9] <= din; + 10: + dout[10:10] <= din; + 11: + dout[11:11] <= din; + 12: + dout[12:12] <= din; + 13: + dout[13:13] <= din; + 14: + dout[14:14] <= din; + 15: + dout[15:15] <= din; + endcase + case (({(ctrl)*(5'b 00111)})+(0)) + 0: + dout[0:0] <= din; + 1: + dout[1:1] <= din; + 2: + dout[2:2] <= din; + 3: + dout[3:3] <= din; + 4: + dout[4:4] <= din; + 5: + dout[5:5] <= din; + 6: + dout[6:6] <= din; + 7: + dout[7:7] <= din; + 8: + dout[8:8] <= din; + 9: + dout[9:9] <= din; + 10: + dout[10:10] <= din; + 11: + dout[11:11] <= din; + 12: + dout[12:12] <= din; + 13: + dout[13:13] <= din; + 14: + dout[14:14] <= din; + 15: + dout[15:15] <= din; + endcase + case (({(ctrl)*(5'b 01000)})+(0)) + 0: + dout[0:0] <= din; + 1: + dout[1:1] <= din; + 2: + dout[2:2] <= din; + 3: + dout[3:3] <= din; + 4: + dout[4:4] <= din; + 5: + dout[5:5] <= din; + 6: + dout[6:6] <= din; + 7: + dout[7:7] <= din; + 8: + dout[8:8] <= din; + 9: + dout[9:9] <= din; + 10: + dout[10:10] <= din; + 11: + dout[11:11] <= din; + 12: + dout[12:12] <= din; + 13: + dout[13:13] <= din; + 14: + dout[14:14] <= din; + 15: + dout[15:15] <= din; + endcase + case (({(ctrl)*(5'b 01001)})+(0)) + 0: + dout[0:0] <= din; + 1: + dout[1:1] <= din; + 2: + dout[2:2] <= din; + 3: + dout[3:3] <= din; + 4: + dout[4:4] <= din; + 5: + dout[5:5] <= din; + 6: + dout[6:6] <= din; + 7: + dout[7:7] <= din; + 8: + dout[8:8] <= din; + 9: + dout[9:9] <= din; + 10: + dout[10:10] <= din; + 11: + dout[11:11] <= din; + 12: + dout[12:12] <= din; + 13: + dout[13:13] <= din; + 14: + dout[14:14] <= din; + 15: + dout[15:15] <= din; + endcase + case (({(ctrl)*(5'b 01010)})+(0)) + 0: + dout[0:0] <= din; + 1: + dout[1:1] <= din; + 2: + dout[2:2] <= din; + 3: + dout[3:3] <= din; + 4: + dout[4:4] <= din; + 5: + dout[5:5] <= din; + 6: + dout[6:6] <= din; + 7: + dout[7:7] <= din; + 8: + dout[8:8] <= din; + 9: + dout[9:9] <= din; + 10: + dout[10:10] <= din; + 11: + dout[11:11] <= din; + 12: + dout[12:12] <= din; + 13: + dout[13:13] <= din; + 14: + dout[14:14] <= din; + 15: + dout[15:15] <= din; + endcase + case (({(ctrl)*(5'b 01011)})+(0)) + 0: + dout[0:0] <= din; + 1: + dout[1:1] <= din; + 2: + dout[2:2] <= din; + 3: + dout[3:3] <= din; + 4: + dout[4:4] <= din; + 5: + dout[5:5] <= din; + 6: + dout[6:6] <= din; + 7: + dout[7:7] <= din; + 8: + dout[8:8] <= din; + 9: + dout[9:9] <= din; + 10: + dout[10:10] <= din; + 11: + dout[11:11] <= din; + 12: + dout[12:12] <= din; + 13: + dout[13:13] <= din; + 14: + dout[14:14] <= din; + 15: + dout[15:15] <= din; + endcase + case (({(ctrl)*(5'b 01100)})+(0)) + 0: + dout[0:0] <= din; + 1: + dout[1:1] <= din; + 2: + dout[2:2] <= din; + 3: + dout[3:3] <= din; + 4: + dout[4:4] <= din; + 5: + dout[5:5] <= din; + 6: + dout[6:6] <= din; + 7: + dout[7:7] <= din; + 8: + dout[8:8] <= din; + 9: + dout[9:9] <= din; + 10: + dout[10:10] <= din; + 11: + dout[11:11] <= din; + 12: + dout[12:12] <= din; + 13: + dout[13:13] <= din; + 14: + dout[14:14] <= din; + 15: + dout[15:15] <= din; + endcase + case (({(ctrl)*(5'b 01101)})+(0)) + 0: + dout[0:0] <= din; + 1: + dout[1:1] <= din; + 2: + dout[2:2] <= din; + 3: + dout[3:3] <= din; + 4: + dout[4:4] <= din; + 5: + dout[5:5] <= din; + 6: + dout[6:6] <= din; + 7: + dout[7:7] <= din; + 8: + dout[8:8] <= din; + 9: + dout[9:9] <= din; + 10: + dout[10:10] <= din; + 11: + dout[11:11] <= din; + 12: + dout[12:12] <= din; + 13: + dout[13:13] <= din; + 14: + dout[14:14] <= din; + 15: + dout[15:15] <= din; + endcase + case (({(ctrl)*(5'b 01110)})+(0)) + 0: + dout[0:0] <= din; + 1: + dout[1:1] <= din; + 2: + dout[2:2] <= din; + 3: + dout[3:3] <= din; + 4: + dout[4:4] <= din; + 5: + dout[5:5] <= din; + 6: + dout[6:6] <= din; + 7: + dout[7:7] <= din; + 8: + dout[8:8] <= din; + 9: + dout[9:9] <= din; + 10: + dout[10:10] <= din; + 11: + dout[11:11] <= din; + 12: + dout[12:12] <= din; + 13: + dout[13:13] <= din; + 14: + dout[14:14] <= din; + 15: + dout[15:15] <= din; + endcase + case (({(ctrl)*(5'b 01111)})+(0)) + 0: + dout[0:0] <= din; + 1: + dout[1:1] <= din; + 2: + dout[2:2] <= din; + 3: + dout[3:3] <= din; + 4: + dout[4:4] <= din; + 5: + dout[5:5] <= din; + 6: + dout[6:6] <= din; + 7: + dout[7:7] <= din; + 8: + dout[8:8] <= din; + 9: + dout[9:9] <= din; + 10: + dout[10:10] <= din; + 11: + dout[11:11] <= din; + 12: + dout[12:12] <= din; + 13: + dout[13:13] <= din; + 14: + dout[14:14] <= din; + 15: + dout[15:15] <= din; + endcase + sel = 5'b 10000; + end + endcase + endmodule diff --git a/tests/various/dynamic_part_select/multiple_blocking.v b/tests/various/dynamic_part_select/multiple_blocking.v new file mode 100644 index 000000000..2858f7741 --- /dev/null +++ b/tests/various/dynamic_part_select/multiple_blocking.v @@ -0,0 +1,19 @@ +module multiple_blocking #(parameter WIDTH=32, SELW=1, CTRLW=$clog2(WIDTH), DINW=2**SELW) + (input clk, + input [CTRLW-1:0] ctrl, + input [DINW-1:0] din, + input [SELW-1:0] sel, + output reg [WIDTH-1:0] dout); + + localparam SLICE = WIDTH/(SELW**2); + reg [CTRLW:0] a; + reg [SELW-1:0] b; + reg [DINW:0] c; + always @(posedge clk) begin + a = ctrl + 1; + b = sel - 1; + c = ~din; + dout = dout + 1; + dout[a*b+:SLICE] = c; + end +endmodule diff --git a/tests/various/dynamic_part_select/multiple_blocking_gate.v b/tests/various/dynamic_part_select/multiple_blocking_gate.v new file mode 100644 index 000000000..073b559dc --- /dev/null +++ b/tests/various/dynamic_part_select/multiple_blocking_gate.v @@ -0,0 +1,83 @@ +module multiple_blocking_gate (clk, ctrl, din, sel, dout); + input clk; + input [4:0] ctrl; + input [1:0] din; + input [0:0] sel; + output reg [31:0] dout; + reg [5:0] a; + reg [0:0] b; + reg [2:0] c; + always @(posedge clk) + begin + a = (ctrl)+(1); + b = (sel)-(1); + c = ~(din); + dout = (dout)+(1); + case (({(a)*(b)})+(0)) + 0: + dout[31:0] = c; + 1: + dout[31:1] = c; + 2: + dout[31:2] = c; + 3: + dout[31:3] = c; + 4: + dout[31:4] = c; + 5: + dout[31:5] = c; + 6: + dout[31:6] = c; + 7: + dout[31:7] = c; + 8: + dout[31:8] = c; + 9: + dout[31:9] = c; + 10: + dout[31:10] = c; + 11: + dout[31:11] = c; + 12: + dout[31:12] = c; + 13: + dout[31:13] = c; + 14: + dout[31:14] = c; + 15: + dout[31:15] = c; + 16: + dout[31:16] = c; + 17: + dout[31:17] = c; + 18: + dout[31:18] = c; + 19: + dout[31:19] = c; + 20: + dout[31:20] = c; + 21: + dout[31:21] = c; + 22: + dout[31:22] = c; + 23: + dout[31:23] = c; + 24: + dout[31:24] = c; + 25: + dout[31:25] = c; + 26: + dout[31:26] = c; + 27: + dout[31:27] = c; + 28: + dout[31:28] = c; + 29: + dout[31:29] = c; + 30: + dout[31:30] = c; + 31: + dout[31:31] = c; + endcase + end +endmodule diff --git a/tests/various/dynamic_part_select/nonblocking.v b/tests/various/dynamic_part_select/nonblocking.v new file mode 100644 index 000000000..0949b31a9 --- /dev/null +++ b/tests/various/dynamic_part_select/nonblocking.v @@ -0,0 +1,14 @@ +module nonblocking #(parameter WIDTH=32, SELW=1, CTRLW=$clog2(WIDTH), DINW=2**SELW) + (input clk, + input [CTRLW-1:0] ctrl, + input [DINW-1:0] din, + input [SELW-1:0] sel, + output reg [WIDTH-1:0] dout); + + localparam SLICE = WIDTH/(SELW**2); + always @(posedge clk) begin + dout <= dout + 1; + dout[ctrl*sel+:SLICE] <= din ; + end + +endmodule diff --git a/tests/various/dynamic_part_select/nonblocking_gate.v b/tests/various/dynamic_part_select/nonblocking_gate.v new file mode 100644 index 000000000..ed1ee2776 --- /dev/null +++ b/tests/various/dynamic_part_select/nonblocking_gate.v @@ -0,0 +1,77 @@ +module nonblocking_gate (clk, ctrl, din, sel, dout); + input clk; + input [4:0] ctrl; + input [1:0] din; + input [0:0] sel; + output reg [31:0] dout; + always @(posedge clk) + begin + dout <= (dout)+(1); + case (({(ctrl)*(sel)})+(0)) + 0: + dout[31:0] <= din; + 1: + dout[31:1] <= din; + 2: + dout[31:2] <= din; + 3: + dout[31:3] <= din; + 4: + dout[31:4] <= din; + 5: + dout[31:5] <= din; + 6: + dout[31:6] <= din; + 7: + dout[31:7] <= din; + 8: + dout[31:8] <= din; + 9: + dout[31:9] <= din; + 10: + dout[31:10] <= din; + 11: + dout[31:11] <= din; + 12: + dout[31:12] <= din; + 13: + dout[31:13] <= din; + 14: + dout[31:14] <= din; + 15: + dout[31:15] <= din; + 16: + dout[31:16] <= din; + 17: + dout[31:17] <= din; + 18: + dout[31:18] <= din; + 19: + dout[31:19] <= din; + 20: + dout[31:20] <= din; + 21: + dout[31:21] <= din; + 22: + dout[31:22] <= din; + 23: + dout[31:23] <= din; + 24: + dout[31:24] <= din; + 25: + dout[31:25] <= din; + 26: + dout[31:26] <= din; + 27: + dout[31:27] <= din; + 28: + dout[31:28] <= din; + 29: + dout[31:29] <= din; + 30: + dout[31:30] <= din; + 31: + dout[31:31] <= din; + endcase + end +endmodule diff --git a/tests/various/dynamic_part_select/original.v b/tests/various/dynamic_part_select/original.v new file mode 100644 index 000000000..f7dfed1a1 --- /dev/null +++ b/tests/various/dynamic_part_select/original.v @@ -0,0 +1,12 @@ +module original #(parameter WIDTH=32, SELW=1, CTRLW=$clog2(WIDTH), DINW=2**SELW) + (input clk, + input [CTRLW-1:0] ctrl, + input [DINW-1:0] din, + input [SELW-1:0] sel, + output reg [WIDTH-1:0] dout); + localparam SLICE = WIDTH/(SELW**2); + always @(posedge clk) + begin + dout[ctrl*sel+:SLICE] <= din ; + end +endmodule diff --git a/tests/various/dynamic_part_select/original_gate.v b/tests/various/dynamic_part_select/original_gate.v new file mode 100644 index 000000000..22093bf63 --- /dev/null +++ b/tests/various/dynamic_part_select/original_gate.v @@ -0,0 +1,74 @@ +module original_gate (clk, ctrl, din, sel, dout); + input clk; + input [4:0] ctrl; + input [1:0] din; + input [0:0] sel; + output reg [31:0] dout; + always @(posedge clk) + case (({(ctrl)*(sel)})+(0)) + 0: + dout[31:0] <= din; + 1: + dout[31:1] <= din; + 2: + dout[31:2] <= din; + 3: + dout[31:3] <= din; + 4: + dout[31:4] <= din; + 5: + dout[31:5] <= din; + 6: + dout[31:6] <= din; + 7: + dout[31:7] <= din; + 8: + dout[31:8] <= din; + 9: + dout[31:9] <= din; + 10: + dout[31:10] <= din; + 11: + dout[31:11] <= din; + 12: + dout[31:12] <= din; + 13: + dout[31:13] <= din; + 14: + dout[31:14] <= din; + 15: + dout[31:15] <= din; + 16: + dout[31:16] <= din; + 17: + dout[31:17] <= din; + 18: + dout[31:18] <= din; + 19: + dout[31:19] <= din; + 20: + dout[31:20] <= din; + 21: + dout[31:21] <= din; + 22: + dout[31:22] <= din; + 23: + dout[31:23] <= din; + 24: + dout[31:24] <= din; + 25: + dout[31:25] <= din; + 26: + dout[31:26] <= din; + 27: + dout[31:27] <= din; + 28: + dout[31:28] <= din; + 29: + dout[31:29] <= din; + 30: + dout[31:30] <= din; + 31: + dout[31:31] <= din; + endcase +endmodule diff --git a/tests/various/dynamic_part_select/reset_test.v b/tests/various/dynamic_part_select/reset_test.v new file mode 100644 index 000000000..29355aafb --- /dev/null +++ b/tests/various/dynamic_part_select/reset_test.v @@ -0,0 +1,23 @@ +module reset_test #(parameter WIDTH=32, SELW=1, CTRLW=$clog2(WIDTH), DINW=2**SELW) + (input clk, + input [CTRLW-1:0] ctrl, + input [DINW-1:0] din, + input [SELW-1:0] sel, + output reg [WIDTH-1:0] dout); + + reg [SELW:0] i; + wire [SELW-1:0] rval = {reset, {SELW-1{1'b0}}}; + localparam SLICE = WIDTH/(SELW**2); + // Doing exotic reset. masking 2 LSB bits to 0, 6 MSB bits to 1 for + // whatever reason. + always @(posedge clk) begin + if (reset) begin: reset_mask + for (i = 0; i < {SELW{1'b1}}; i=i+1) begin + dout[i*rval+:SLICE] <= 32'hDEAD; + end + end + //else begin + dout[ctrl*sel+:SLICE] <= din; + //end + end +endmodule diff --git a/tests/various/dynamic_part_select/reset_test_gate.v b/tests/various/dynamic_part_select/reset_test_gate.v new file mode 100644 index 000000000..96dff4135 --- /dev/null +++ b/tests/various/dynamic_part_select/reset_test_gate.v @@ -0,0 +1,151 @@ +module reset_test_gate (clk, ctrl, din, sel, dout); + input clk; + input [4:0] ctrl; + input [1:0] din; + input [0:0] sel; + output reg [31:0] dout; + reg [1:0] i; + wire [0:0] rval; + assign rval = {reset, 1'b0 }; + always @(posedge clk) + begin + case (|(reset)) + 1'b 1: + begin + case (({(0)*(rval)})+(0)) + 0: + dout[31:0] <= 57005; + 1: + dout[31:1] <= 57005; + 2: + dout[31:2] <= 57005; + 3: + dout[31:3] <= 57005; + 4: + dout[31:4] <= 57005; + 5: + dout[31:5] <= 57005; + 6: + dout[31:6] <= 57005; + 7: + dout[31:7] <= 57005; + 8: + dout[31:8] <= 57005; + 9: + dout[31:9] <= 57005; + 10: + dout[31:10] <= 57005; + 11: + dout[31:11] <= 57005; + 12: + dout[31:12] <= 57005; + 13: + dout[31:13] <= 57005; + 14: + dout[31:14] <= 57005; + 15: + dout[31:15] <= 57005; + 16: + dout[31:16] <= 57005; + 17: + dout[31:17] <= 57005; + 18: + dout[31:18] <= 57005; + 19: + dout[31:19] <= 57005; + 20: + dout[31:20] <= 57005; + 21: + dout[31:21] <= 57005; + 22: + dout[31:22] <= 57005; + 23: + dout[31:23] <= 57005; + 24: + dout[31:24] <= 57005; + 25: + dout[31:25] <= 57005; + 26: + dout[31:26] <= 57005; + 27: + dout[31:27] <= 57005; + 28: + dout[31:28] <= 57005; + 29: + dout[31:29] <= 57005; + 30: + dout[31:30] <= 57005; + 31: + dout[31:31] <= 57005; + endcase + i = 1; + end + endcase + case (({(ctrl)*(sel)})+(0)) + 0: + dout[31:0] <= din; + 1: + dout[31:1] <= din; + 2: + dout[31:2] <= din; + 3: + dout[31:3] <= din; + 4: + dout[31:4] <= din; + 5: + dout[31:5] <= din; + 6: + dout[31:6] <= din; + 7: + dout[31:7] <= din; + 8: + dout[31:8] <= din; + 9: + dout[31:9] <= din; + 10: + dout[31:10] <= din; + 11: + dout[31:11] <= din; + 12: + dout[31:12] <= din; + 13: + dout[31:13] <= din; + 14: + dout[31:14] <= din; + 15: + dout[31:15] <= din; + 16: + dout[31:16] <= din; + 17: + dout[31:17] <= din; + 18: + dout[31:18] <= din; + 19: + dout[31:19] <= din; + 20: + dout[31:20] <= din; + 21: + dout[31:21] <= din; + 22: + dout[31:22] <= din; + 23: + dout[31:23] <= din; + 24: + dout[31:24] <= din; + 25: + dout[31:25] <= din; + 26: + dout[31:26] <= din; + 27: + dout[31:27] <= din; + 28: + dout[31:28] <= din; + 29: + dout[31:29] <= din; + 30: + dout[31:30] <= din; + 31: + dout[31:31] <= din; + endcase + end +endmodule diff --git a/tests/various/dynamic_part_select/reversed.v b/tests/various/dynamic_part_select/reversed.v new file mode 100644 index 000000000..8b114ac77 --- /dev/null +++ b/tests/various/dynamic_part_select/reversed.v @@ -0,0 +1,13 @@ +module reversed #(parameter WIDTH=32, SELW=4, CTRLW=$clog2(WIDTH), DINW=2**SELW) + (input clk, + input [CTRLW-1:0] ctrl, + input [DINW-1:0] din, + input [SELW-1:0] sel, + output reg [WIDTH-1:0] dout); + + localparam SLICE = WIDTH/(SELW**2); + always @(posedge clk) begin + dout[(WIDTH-ctrl*sel)-:SLICE] <= din; + end +endmodule + diff --git a/tests/various/dynamic_part_select/reversed_gate.v b/tests/various/dynamic_part_select/reversed_gate.v new file mode 100644 index 000000000..9349d45ee --- /dev/null +++ b/tests/various/dynamic_part_select/reversed_gate.v @@ -0,0 +1,74 @@ +module reversed_gate (clk, ctrl, din, sel, dout); + input clk; + input [4:0] ctrl; + input [15:0] din; + input [3:0] sel; + output reg [31:0] dout; + always @(posedge clk) + case ((({(32)-((ctrl)*(sel))})+(1))-(2)) + 0: + dout[1:0] <= din; + 1: + dout[2:1] <= din; + 2: + dout[3:2] <= din; + 3: + dout[4:3] <= din; + 4: + dout[5:4] <= din; + 5: + dout[6:5] <= din; + 6: + dout[7:6] <= din; + 7: + dout[8:7] <= din; + 8: + dout[9:8] <= din; + 9: + dout[10:9] <= din; + 10: + dout[11:10] <= din; + 11: + dout[12:11] <= din; + 12: + dout[13:12] <= din; + 13: + dout[14:13] <= din; + 14: + dout[15:14] <= din; + 15: + dout[16:15] <= din; + 16: + dout[17:16] <= din; + 17: + dout[18:17] <= din; + 18: + dout[19:18] <= din; + 19: + dout[20:19] <= din; + 20: + dout[21:20] <= din; + 21: + dout[22:21] <= din; + 22: + dout[23:22] <= din; + 23: + dout[24:23] <= din; + 24: + dout[25:24] <= din; + 25: + dout[26:25] <= din; + 26: + dout[27:26] <= din; + 27: + dout[28:27] <= din; + 28: + dout[29:28] <= din; + 29: + dout[30:29] <= din; + 30: + dout[31:30] <= din; + 31: + dout[31:31] <= din; + endcase +endmodule |