【问题标题】:How to write the verilog to force yosys / nextpnr to output a manually designed logic tiles如何编写verilog强制yosys/nextpnr输出手动设计的逻辑块
【发布时间】:2019-12-03 10:24:29
【问题描述】:

我想创建一个非常紧凑的并行到串行移位寄存器。

我已经手动设计了一个逻辑图块。

我希望 yosys/nextpnr 只做这个 tile 和 io 引脚之间的路由。

我已将代码设计为使用 yosys 原语,但 nextpnr 无法将 LUT 与进位融合。

代码如下:


module top (
    output PIN_21, PIN_22, PIN_23, PIN_24, USBPU,
    input CLK, PIN_1, PIN_2, PIN_3, PIN_4, PIN_5, PIN_6, PIN_7, PIN_8, PIN_9, PIN_10, PIN_11, PIN_12, PIN_13
);

    wire[12:0] loop;
    wire[12:0] carry;

    MyCell #(.LUT_INIT('h0F0F)) sRegBorder(loop[0], carry[0], 0, loop[0], PIN_13, 0, 0, CLK);
    MyCell #(.LUT_INIT('hFAFA)) sRegA(loop[1], carry[1], loop[0], loop[1], PIN_13, PIN_1, carry[0], CLK);
    MyCell #(.LUT_INIT('hFAFA)) sRegB(loop[2], carry[2], loop[1], loop[2], PIN_13, PIN_2, carry[1], CLK);
    MyCell #(.LUT_INIT('hFAFA)) sRegC(loop[3], carry[3], loop[2], loop[3], PIN_13, PIN_3, carry[2], CLK);
    MyCell #(.LUT_INIT('hFAFA)) sRegD(loop[4], carry[4], loop[3], loop[4], PIN_13, PIN_4, carry[3], CLK);
    MyCell #(.LUT_INIT('hFAFA)) sRegE(PIN_24, carry[5], loop[4], PIN_24, PIN_13, PIN_5, carry[4], CLK);
    SB_LUT4 #(.LUT_INIT('hFFFF)) sRegFin (PIN_22,0,0,0,carry[5]);

endmodule

module MyCell(output O, CO, input I0, I1, I2, I3, CI, CLK);
    parameter [15:0] LUT_INIT = 0;
    wire lo;
    SB_LUT4 #(.LUT_INIT(LUT_INIT)) lut (lo, I0, I1, I2, I3);
    SB_CARRY cr (CO, I1, I2, CI);
    SB_DFF dff (O, CLK, lo);
endmodule

预期的结果是只有一个带有 7 个 LUT 堆栈的图块。

* PIN_13 should be connected to I2 of the first 6 LUTS.

* PIN_[1-6] should be connected to I3 of the first 6 LUTS, respectivelly.

* every output of the first 6 LUTs should be buffered (DFF) and the buffered output should loop to the I1 of the same LUT.

* every output of the first 5 LUTs shoud also be routed to the I0 of the next LUT in sequence.

* the carry logic should be enabled and flow through the first 6 LUTs and at LUT7 should be captured as an output.

我从 yosys 得到的结果看起来还不错,但是 nextpnr 将 LUT 到处杀掉,并为进位分配了单独的 LUT,使使用的 LUT 数量增加了一倍。

所以基本上,如果我知道我想要的输出,至少到特定的磁贴配置,我应该写什么作为输入?

我尝试在 TinyFPGA.BX 上编译代码。

【问题讨论】:

  • PIN_22 将始终为 1'b1,因为 sRegFin 的 LUT 值为 16'hFFFF。这可能不是你想要的。 (另外,PIN_21、PIN_23 和 USBPU 没有连接到任何东西)。我是否正确假设您希望 PIN_22 显示移位寄存器是否为 6'h0?
  • yes sRegFin 是 16'hFF00,它用于捕获进位并将其暴露为输出。
  • PIN_1 到 PIN_5 连接到 SB_LUT4 I3 对电路没有输入,因为 LUT 值为 16'hfafa,这可能不是您想要的。所描述的PIN_6不参与代码?
  • 所以FAFA想给出这个语义,也许我做错了。 O=I2?I3:I0 。即使 I1 不用于 lut,但它实际上用于进位功能,lut 也会忽略该输入。

标签: verilog fpga yosys


【解决方案1】:

我相信答案是您尝试做的事情可能目前无法完成。我很抱歉这个否定的答案,我也需要打包,所以我希望有人能证明我错了。

我做了一些调查,下载了最新的yosys 和nextpnr(和arachne-pnr),或多或少地复制了你的设计。虽然 ICECube2 给出了我预期的结果,但 yosys/arachne-pnr 和 yosys/nextpnr-ice40 都没有管理。

/* Just a toy implementation of a shift register, in itself unusable. Written 
 * to explore how arachne-pnr and nextpnr-ice40 handles SB_CARRY. The design is
 * not simulated, hence wrong.
 * 
 * Main results: Neither arachne-pnr nor nextpnr-ice40 are particularly intelligent
 * when it comes to SB_CARRY packing.
 * 
 * Details:
 * 
 * When SHOULD_WORK == 1
 * =====================
 * (a) yosys/arachne-pnr uses too many LUTs: 12
 * (b) yosys/next uses too many LUTs:        10 
 * (c) Lattice ICECube2:                      8 (as was expected)
 * 
 * Not satisfied, I tried to use an internal cell definition, ICESTORM_LC.
 * Worse and worse...
 * 
 * When SHOULD_WORK == 0
 * ======================
 * (d) yosys/arachne-pnr uses too many LUTs: 12
 * (e) yosys/next uses too many LUTs:        14
 *   
 * Commands used to produce (a) and (d):
 * yosys -p "synth_ice40 -blif hardware.blif" -q other.v
 * arachne-pnr -d 1k -P vq100 -p other.pcf -o hardware.asc  hardware.blif
 *
 * Commands used to produce (b) and (e):
 * yosys -p 'synth_ice40 -top top -json other.json' other.v  
 * nextpnr-ice40 -v --hx1k --json other.json --pcf other.pcf --asc other.asc
 *
 * Versions of programs used:
 * nextpnr-ice40 -- Next Generation Place and Route (git sha1 b863690).  (I pulled the 
 *     code today, 2019.12.05)
 * arachne-pnr 0.1+328+0 (git sha1 c40fb22, g++ 5.4.0-6ubuntu1~16.04.12 -O2)
 * Yosys 0.9+932 (git sha1 fcce940, clang 3.8.0-2ubuntu4 -fPIC -Os)
 * 
 */
module top 
  (
   output      PIN_22, // Combinatorical, high if shiftreg busy
   output      PIN_24, // Shift register output. 
   input       CLK,
   input       PIN_13, // Load
   input [5:1] PIN
   );
   wire [5:0] loop, cy;

   assign cy[0] = 1'b0;

`define SHOULD_WORK 1
`ifdef SHOULD_WORK 
   wire [5:0] cmb_loop;
   SB_LUT4 #(.LUT_INIT(16'haaaa)) l_border   ( .O(cmb_loop[0]),   .I3(1'b0),  .I2(1'b0), .I1(1'b0     ), .I0(PIN_13) );   
   SB_LUT4 #(.LUT_INIT(16'hcaca)) l_sh [4:0] ( .O(cmb_loop[5:1]), .I3(PIN_13),  .I2(1'b1), .I1(loop[4:0]), .I0(PIN) );
   SB_CARRY                       l_cy [4:0] ( .CO(cy[5:1]),    .CI(cy[4:0]), .I1(1'b1), .I0(loop[4:0])           );
   SB_DFF                         r_sh [5:0] ( .Q(loop), .C(CLK), .D(cmb_loop) );
`else
   wire       cmbloop0;
   SB_LUT4 #(.LUT_INIT(16'haaaa)) l_border ( .O(cmbloop0), .I3(1'b0), .I2(1'b0), .I1(1'b0 ), .I0(PIN_13) );
   SB_DFF r_border( .Q(loop[0]), .C(CLK), .D(cmbloop0) );
   ICESTORM_LC #(.LUT_INIT(16'hcaca),
                 .CARRY_ENABLE(1),
                 .DFF_ENABLE(1))
   l_shcyreg [4:0] ( .I0(PIN),  
                     .I1(loop[4:0]),
                     .I2(1'b1),
                     .I3(PIN_13),
                     .CIN(cy[4:0]),
                     .CLK(CLK),
                     .O(loop[5:1]),
                     .COUT(cy[5:1]));   
`endif

   SB_LUT4 #(.LUT_INIT(16'hff00)) l_empty    ( .O(PIN_22), .I3(cy[5]), .I2(1'b0), .I1(1'b0), .I0(1'b0));

   assign PIN_24 = loop[5];
endmodule

/* What I hope the code above describe. Should be a total of 7 SB_LUTs, 
 * and 1 SB_LUT to generate 1'b1
 *                    ___
 *                   |I0 |
 *                   |I1 |---------------------- PIN_22
 *                   |I2 |
 *                +--|I3_|
 *                |  FF00
 *                | cy[5]         
 *               /y\              
 *               |||  ___         
 *        PIN_5 -(((-|I0 |     _  
 *      +--------+((-|I1 |----| |--- loop[5] --- PIN_24  
 *      |     1 --(+-|I2 |    >_|  
 * +----(---------(--|I3_|         
 * |    |         |  AACC          
 * |    +---------(---------------+
 * |PIN_13        | cy[4]         |  loop[4]
 * 
 *            ::::::::::::::
 * 
 * |    |         |
 * |    +---------(---------------+
 * |              | cy[1]         |
 * |             /y\              |
 * |             |||  ___         |
 * |      PIN_1 -(((-|I0 |     _  |
 * |    +--------+((-|I1 |----| |-+  loop[1]
 * |    |     1 --(+-|I2 |    >_|  
 * +----(---------(--|I3_|         
 * |    |         |  AACC
 * |    |         0 cy[0]
 * |    |
 * |    +-------------------------+
 * |                  ___         |
 * +-----------------|I0 |     _  |
 * |                 |I1 |----| |-+  loop[0]
 * |                 |I2 |    >_|  
 * |                 |I3_|         
 * |                 AAAA   
 * | PIN_13         
 */

这是一个非常令人头疼的问题,它似乎位于 nextpnr/ice40/pack.cc 的第 192 行附近。很抱歉我帮不上忙,但也许这个输入可以用来改进 nextpnr-ice40 中的打包。

【讨论】:

  • 爱你的 asciiart。是的 ICESTORM_LC 将是一个答案。唉:github.com/YosysHQ/nextpnr/issues/364ICESTORM_LC 目前被认为是一个内部结构。所以……也许在这个假期里,我可以花一些时间在 pack.cc 上
  • 希望能抽空做点正经的事;并参与其中(增强pack.cc)。还需要考虑级联 LUT 的问题。这并不容易解决。无论发生什么,我们一定会看到pack.cc 的变化。 PS。我还针对这个特定问题尝试了(* BEL .. *) placement 约束 - 它对 SB_DFF 有影响,而不是对 SB_LUT4 或 SB_CARRY。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多