如何编写verilog以强制yosys/nextpnr输出手动设计的逻辑块

如何编写verilog以强制yosys/nextpnr输出手动设计的逻辑块,verilog,fpga,yosys,Verilog,Fpga,Yosys,我想创建一个非常紧凑的并行到串行移位寄存器 我已经手动设计了一个逻辑图块 我希望yosys/nextpnr只在这个磁贴和io引脚之间进行布线 我已经设计了使用yosys原语的代码,但是nextpnr无法将LUT与Carrys融合 代码如下: 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, P

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

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

我希望yosys/nextpnr只在这个磁贴和io引脚之间进行布线

我已经设计了使用yosys原语的代码,但是nextpnr无法将LUT与Carrys融合

代码如下:


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进行了屠宰,并为Carry分配了单独的LUT,使用的LUT数量增加了一倍

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


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

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

我做了一些调查,下载了最新的
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         
 */

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

PIN_22
中的打包,因为
sRegFin
的LUT值为16'hFFFF。这可能不是你想要的。(另外,
PIN_21
PIN_23
USBPU
未连接到任何东西)。我假设您想要
PIN_22
显示移位寄存器是否为6'h0,是否正确?是的,sRegFin为16'hFF00,它用于捕获进位并将其作为输出显示。
PIN_1
通过
PIN_5
连接到SB_LUT4 I3,不向电路提供输入,因为LUT值为16'hfafa,这可能不是您想要的。所描述的
PIN_6
不参与代码?因此FAFA想给出这个语义,也许我做得不对。O=I2?I3:I0。即使它不用于lut,但实际上用于进位功能,lut也会忽略该输入。热爱你的asciiart。是的,冰暴将是一个答案。唉:目前,暴风雪被认为是一个内部结构。所以也许在这个假期里,我可以花点时间整理一下行李。ccI希望能抽出时间做些体面的事情;并参与其中(增强
pack.cc
)。也有考虑级联LUTS的问题。这是不容易解决的。无论发生什么,我们都会在
pack.cc
中看到变化。另外,我还尝试了
(*BEL..*)
针对这个特殊问题的放置约束-它对SB_DFF有影响,而不是对SB_LUT4或SB_CARRY有影响。