write_verilog: handle the $shift cell.
authorwhitequark <whitequark@whitequark.org>
Sun, 16 Dec 2018 18:46:32 +0000 (18:46 +0000)
committerwhitequark <whitequark@whitequark.org>
Sun, 16 Dec 2018 18:46:32 +0000 (18:46 +0000)
The implementation corresponds to the following Verilog, which is
lifted straight from simlib.v:

    module \\$shift (A, B, Y);

    parameter A_SIGNED = 0;
    parameter B_SIGNED = 0;
    parameter A_WIDTH = 0;
    parameter B_WIDTH = 0;
    parameter Y_WIDTH = 0;

    input [A_WIDTH-1:0] A;
    input [B_WIDTH-1:0] B;
    output [Y_WIDTH-1:0] Y;

    generate
        if (B_SIGNED) begin:BLOCK1
            assign Y = $signed(B) < 0 ? A << -B : A >> B;
        end else begin:BLOCK2
            assign Y = A >> B;
        end
    endgenerate

    endmodule

backends/verilog/verilog_backend.cc

index 3a47b478f3dc147cbad51cef9199a4552e57df3a..71db25f989728cc8e3732e5a28912652b8afd214 100644 (file)
@@ -678,6 +678,35 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
 #undef HANDLE_UNIOP
 #undef HANDLE_BINOP
 
+       if (cell->type == "$shift")
+       {
+               f << stringf("%s" "assign ", indent.c_str());
+               dump_sigspec(f, cell->getPort("\\Y"));
+               f << stringf(" = ");
+               if (cell->getParam("\\B_SIGNED").as_bool())
+               {
+                       f << stringf("$signed(");
+                       dump_sigspec(f, cell->getPort("\\B"));
+                       f << stringf(")");
+                       f << stringf(" < 0 ? ");
+                       dump_sigspec(f, cell->getPort("\\A"));
+                       f << stringf(" << - ");
+                       dump_sigspec(f, cell->getPort("\\B"));
+                       f << stringf(" : ");
+                       dump_sigspec(f, cell->getPort("\\A"));
+                       f << stringf(" >> ");
+                       dump_sigspec(f, cell->getPort("\\B"));
+               }
+               else
+               {
+                       dump_sigspec(f, cell->getPort("\\A"));
+                       f << stringf(" >> ");
+                       dump_sigspec(f, cell->getPort("\\B"));
+               }
+               f << stringf(";\n");
+               return true;
+       }
+
        if (cell->type == "$shiftx")
        {
                f << stringf("%s" "assign ", indent.c_str());