Add support for iCE40 global buffers (currently only for 1k devices)

Signed-off-by: Clifford Wolf <clifford@clifford.at>
This commit is contained in:
Clifford Wolf 2018-06-10 16:31:06 +02:00
parent 02b83d6db6
commit 602e6fab1e
8 changed files with 198 additions and 124 deletions

View File

@ -192,6 +192,8 @@ void write_asc(const Design &design, std::ostream &out)
set_config(ti, config.at(iey).at(iex), set_config(ti, config.at(iey).at(iex),
"IoCtrl.REN_" + std::to_string(iez), !pullup); "IoCtrl.REN_" + std::to_string(iez), !pullup);
} }
} else if (cell.second->type == "SB_GB") {
// no cell config bits
} else { } else {
assert(false); assert(false);
} }
@ -216,18 +218,41 @@ void write_asc(const Design &design, std::ostream &out)
} }
} }
// Set other config bits - currently just disable RAM to stop icebox_vlog // Set other config bits
// crashing
// TODO: ColBufCtrl
for (int y = 0; y < ci.height; y++) { for (int y = 0; y < ci.height; y++) {
for (int x = 0; x < ci.width; x++) { for (int x = 0; x < ci.width; x++) {
TileType tile = tile_at(chip, x, y); TileType tile = tile_at(chip, x, y);
TileInfoPOD &ti = bi.tiles_nonrouting[tile]; TileInfoPOD &ti = bi.tiles_nonrouting[tile];
// disable RAM to stop icebox_vlog crashing (FIXME)
if ((tile == TILE_RAMB) && (chip.args.type == ChipArgs::LP1K || chip.args.type == ChipArgs::HX1K)) { if ((tile == TILE_RAMB) && (chip.args.type == ChipArgs::LP1K || chip.args.type == ChipArgs::HX1K)) {
set_config(ti, config.at(y).at(x), "RamConfig.PowerUp", true); set_config(ti, config.at(y).at(x), "RamConfig.PowerUp", true);
} }
// set all ColBufCtrl bits (FIXME)
bool setColBufCtrl = true;
if (chip.args.type == ChipArgs::LP1K || chip.args.type == ChipArgs::HX1K) {
if (tile == TILE_RAMB || tile == TILE_RAMT) {
setColBufCtrl = (y == 3 || y == 5 || y == 11 || y == 13);
} else {
setColBufCtrl = (y == 4 || y == 5 || y == 12 || y == 13);
}
} else if (chip.args.type == ChipArgs::LP8K || chip.args.type == ChipArgs::HX8K) {
setColBufCtrl = (y == 8 || y == 9 || y == 24 || y == 25);
}
if (setColBufCtrl) {
set_config(ti, config.at(y).at(x), "ColBufCtrl.glb_netwk_0", true);
set_config(ti, config.at(y).at(x), "ColBufCtrl.glb_netwk_1", true);
set_config(ti, config.at(y).at(x), "ColBufCtrl.glb_netwk_2", true);
set_config(ti, config.at(y).at(x), "ColBufCtrl.glb_netwk_3", true);
set_config(ti, config.at(y).at(x), "ColBufCtrl.glb_netwk_4", true);
set_config(ti, config.at(y).at(x), "ColBufCtrl.glb_netwk_5", true);
set_config(ti, config.at(y).at(x), "ColBufCtrl.glb_netwk_6", true);
set_config(ti, config.at(y).at(x), "ColBufCtrl.glb_netwk_7", true);
}
} }
} }
// Write config out // Write config out
for (int y = 0; y < ci.height; y++) { for (int y = 0; y < ci.height; y++) {
for (int x = 0; x < ci.width; x++) { for (int x = 0; x < ci.width; x++) {

View File

@ -2,6 +2,7 @@
set -ex set -ex
yosys blinky.ys yosys blinky.ys
../nextpnr-ice40 --json blinky.json --asc blinky.asc ../nextpnr-ice40 --json blinky.json --asc blinky.asc
icepack blinky.asc blinky.bin
icebox_vlog blinky.asc > blinky_chip.v icebox_vlog blinky.asc > blinky_chip.v
iverilog -o blinky_tb blinky_chip.v blinky_tb.v iverilog -o blinky_tb blinky_chip.v blinky_tb.v
./blinky_tb vvp -N ./blinky_tb

View File

@ -1,131 +1,144 @@
module blinky ( module blinky (
input clk_pin, input clk_pin,
output led1_pin, output led1_pin,
output led2_pin, output led2_pin,
output led3_pin, output led3_pin,
output led4_pin, output led4_pin,
output led5_pin output led5_pin
); );
wire clk, led1, led2, led3, led4, led5; wire clk, clki;
(* BEL="13_12_io1" *) SB_GB clk_gb (
SB_IO #( .USER_SIGNAL_TO_GLOBAL_BUFFER(clki),
.PIN_TYPE(6'b 0110_01), .GLOBAL_BUFFER_OUTPUT(clk)
.PULLUP(1'b0), );
.NEG_TRIGGER(1'b0)
) led1_iob (
.PACKAGE_PIN(led1_pin),
.LATCH_INPUT_VALUE(),
.CLOCK_ENABLE(),
.INPUT_CLK(),
.OUTPUT_CLK(),
.OUTPUT_ENABLE(),
.D_OUT_0(led1),
.D_OUT_1(),
.D_IN_0(),
.D_IN_1()
);
(* BEL="13_12_io0" *) wire led1, led2, led3, led4, led5;
SB_IO #(
.PIN_TYPE(6'b 0110_01),
.PULLUP(1'b0),
.NEG_TRIGGER(1'b0)
) led2_iob (
.PACKAGE_PIN(led2_pin),
.LATCH_INPUT_VALUE(),
.CLOCK_ENABLE(),
.INPUT_CLK(),
.OUTPUT_CLK(),
.OUTPUT_ENABLE(),
.D_OUT_0(led2),
.D_OUT_1(),
.D_IN_0(),
.D_IN_1()
);
(* BEL="13_11_io1" *) (* BEL="13_12_io1" *)
SB_IO #( SB_IO #(
.PIN_TYPE(6'b 0110_01), .PIN_TYPE(6'b 0110_01),
.PULLUP(1'b0), .PULLUP(1'b0),
.NEG_TRIGGER(1'b0) .NEG_TRIGGER(1'b0)
) led3_iob ( ) led1_iob (
.PACKAGE_PIN(led3_pin), .PACKAGE_PIN(led1_pin),
.LATCH_INPUT_VALUE(), .LATCH_INPUT_VALUE(),
.CLOCK_ENABLE(), .CLOCK_ENABLE(),
.INPUT_CLK(), .INPUT_CLK(),
.OUTPUT_CLK(), .OUTPUT_CLK(),
.OUTPUT_ENABLE(), .OUTPUT_ENABLE(),
.D_OUT_0(led3), .D_OUT_0(led1),
.D_OUT_1(), .D_OUT_1(),
.D_IN_0(), .D_IN_0(),
.D_IN_1() .D_IN_1()
); );
(* BEL="13_11_io0" *) (* BEL="13_12_io0" *)
SB_IO #( SB_IO #(
.PIN_TYPE(6'b 0110_01), .PIN_TYPE(6'b 0110_01),
.PULLUP(1'b0), .PULLUP(1'b0),
.NEG_TRIGGER(1'b0) .NEG_TRIGGER(1'b0)
) led4_iob ( ) led2_iob (
.PACKAGE_PIN(led4_pin), .PACKAGE_PIN(led2_pin),
.LATCH_INPUT_VALUE(), .LATCH_INPUT_VALUE(),
.CLOCK_ENABLE(), .CLOCK_ENABLE(),
.INPUT_CLK(), .INPUT_CLK(),
.OUTPUT_CLK(), .OUTPUT_CLK(),
.OUTPUT_ENABLE(), .OUTPUT_ENABLE(),
.D_OUT_0(led4), .D_OUT_0(led2),
.D_OUT_1(), .D_OUT_1(),
.D_IN_0(), .D_IN_0(),
.D_IN_1() .D_IN_1()
); );
(* BEL="13_9_io1" *) (* BEL="13_11_io1" *)
SB_IO #( SB_IO #(
.PIN_TYPE(6'b 0110_01), .PIN_TYPE(6'b 0110_01),
.PULLUP(1'b0), .PULLUP(1'b0),
.NEG_TRIGGER(1'b0) .NEG_TRIGGER(1'b0)
) led5_iob ( ) led3_iob (
.PACKAGE_PIN(led5_pin), .PACKAGE_PIN(led3_pin),
.LATCH_INPUT_VALUE(), .LATCH_INPUT_VALUE(),
.CLOCK_ENABLE(), .CLOCK_ENABLE(),
.INPUT_CLK(), .INPUT_CLK(),
.OUTPUT_CLK(), .OUTPUT_CLK(),
.OUTPUT_ENABLE(), .OUTPUT_ENABLE(),
.D_OUT_0(led5), .D_OUT_0(led3),
.D_OUT_1(), .D_OUT_1(),
.D_IN_0(), .D_IN_0(),
.D_IN_1() .D_IN_1()
); );
(* BEL="0_8_io1" *) (* BEL="13_11_io0" *)
SB_IO #( SB_IO #(
.PIN_TYPE(6'b 0000_01), .PIN_TYPE(6'b 0110_01),
.PULLUP(1'b0), .PULLUP(1'b0),
.NEG_TRIGGER(1'b0) .NEG_TRIGGER(1'b0)
) clk_iob ( ) led4_iob (
.PACKAGE_PIN(clk_pin), .PACKAGE_PIN(led4_pin),
.LATCH_INPUT_VALUE(), .LATCH_INPUT_VALUE(),
.CLOCK_ENABLE(), .CLOCK_ENABLE(),
.INPUT_CLK(), .INPUT_CLK(),
.OUTPUT_CLK(), .OUTPUT_CLK(),
.OUTPUT_ENABLE(), .OUTPUT_ENABLE(),
.D_OUT_0(), .D_OUT_0(led4),
.D_OUT_1(), .D_OUT_1(),
.D_IN_0(clk), .D_IN_0(),
.D_IN_1() .D_IN_1()
); );
localparam BITS = 5; (* BEL="13_9_io1" *)
localparam LOG2DELAY = 22; SB_IO #(
.PIN_TYPE(6'b 0110_01),
.PULLUP(1'b0),
.NEG_TRIGGER(1'b0)
) led5_iob (
.PACKAGE_PIN(led5_pin),
.LATCH_INPUT_VALUE(),
.CLOCK_ENABLE(),
.INPUT_CLK(),
.OUTPUT_CLK(),
.OUTPUT_ENABLE(),
.D_OUT_0(led5),
.D_OUT_1(),
.D_IN_0(),
.D_IN_1()
);
reg [BITS+LOG2DELAY-1:0] counter = 0; (* BEL="0_8_io1" *)
reg [BITS-1:0] outcnt; SB_IO #(
.PIN_TYPE(6'b 0000_01),
.PULLUP(1'b0),
.NEG_TRIGGER(1'b0)
) clk_iob (
.PACKAGE_PIN(clk_pin),
.LATCH_INPUT_VALUE(),
.CLOCK_ENABLE(),
.INPUT_CLK(),
.OUTPUT_CLK(),
.OUTPUT_ENABLE(),
.D_OUT_0(),
.D_OUT_1(),
.D_IN_0(clki),
.D_IN_1()
);
always @(posedge clk) begin `ifdef ALT_BLINKY
counter <= counter + 1; reg ff = 0;
outcnt <= counter >> LOG2DELAY; always @(posedge clk) ff <= !ff;
end assign led1 = clki, led2 = !clki, led3 = !clk, led4 = !clk, led5 = ff;
`else
localparam BITS = 5;
localparam LOG2DELAY = 22;
assign {led1, led2, led3, led4, led5} = outcnt ^ (outcnt >> 1); reg [BITS+LOG2DELAY-1:0] counter = 0;
reg [BITS-1:0] outcnt;
always @(posedge clk) begin
counter <= counter + 1;
outcnt <= counter >> LOG2DELAY;
end
assign {led1, led2, led3, led4, led5} = outcnt ^ (outcnt >> 1);
`endif
endmodule endmodule

View File

@ -2,8 +2,15 @@ module blinky_tb;
reg clk; reg clk;
always #5 clk = (clk === 1'b0); always #5 clk = (clk === 1'b0);
wire led1, led2, led3, led4, led5;
chip uut ( chip uut (
.io_0_8_1(clk) .io_0_8_1(clk),
.io_13_12_1(led1),
.io_13_12_0(led2),
.io_13_11_1(led3),
.io_13_11_0(led4),
.io_13_9_1(led5)
); );
initial begin initial begin

View File

@ -30,6 +30,8 @@ IdString belTypeToId(BelType type)
return "ICESTORM_RAM"; return "ICESTORM_RAM";
if (type == TYPE_SB_IO) if (type == TYPE_SB_IO)
return "SB_IO"; return "SB_IO";
if (type == TYPE_SB_GB)
return "SB_GB";
return IdString(); return IdString();
} }
@ -41,6 +43,8 @@ BelType belTypeFromId(IdString id)
return TYPE_ICESTORM_RAM; return TYPE_ICESTORM_RAM;
if (id == "SB_IO") if (id == "SB_IO")
return TYPE_SB_IO; return TYPE_SB_IO;
if (id == "SB_GB")
return TYPE_SB_GB;
return TYPE_NONE; return TYPE_NONE;
} }

View File

@ -45,7 +45,8 @@ enum BelType
TYPE_NONE, TYPE_NONE,
TYPE_ICESTORM_LC, TYPE_ICESTORM_LC,
TYPE_ICESTORM_RAM, TYPE_ICESTORM_RAM,
TYPE_SB_IO TYPE_SB_IO,
TYPE_SB_GB
}; };
IdString belTypeToId(BelType type); IdString belTypeToId(BelType type);

View File

@ -293,6 +293,16 @@ def add_bel_ram(x, y):
add_bel_input(bel, wire_names[(x, y1, "ram/RCLKE")], "RCLKE") add_bel_input(bel, wire_names[(x, y1, "ram/RCLKE")], "RCLKE")
add_bel_input(bel, wire_names[(x, y1, "ram/RE")], "RE") add_bel_input(bel, wire_names[(x, y1, "ram/RE")], "RE")
def add_bel_gb(x, y, g):
bel = len(bel_name)
bel_name.append("%d_%d_gb" % (x, y))
bel_type.append("SB_GB")
bel_pos.append((x, y, 0))
bel_wires.append(list())
add_bel_input(bel, wire_names[(x, y, "fabout")], "USER_SIGNAL_TO_GLOBAL_BUFFER")
add_bel_output(bel, wire_names[(x, y, "glb_netwk_%d" % g)], "GLOBAL_BUFFER_OUTPUT")
for tile_xy, tile_type in sorted(tiles.items()): for tile_xy, tile_type in sorted(tiles.items()):
if tile_type == "logic": if tile_type == "logic":
for i in range(8): for i in range(8):
@ -303,6 +313,16 @@ for tile_xy, tile_type in sorted(tiles.items()):
if tile_type == "ramb": if tile_type == "ramb":
add_bel_ram(tile_xy[0], tile_xy[1]) add_bel_ram(tile_xy[0], tile_xy[1])
if dev_name == "1k":
add_bel_gb( 7, 0, 0)
add_bel_gb( 7, 17, 1)
add_bel_gb(13, 9, 2)
add_bel_gb( 0, 9, 3)
add_bel_gb( 6, 17, 4)
add_bel_gb( 6, 0, 5)
add_bel_gb( 0, 8, 6)
add_bel_gb(13, 8, 7)
print('#include "chip.h"') print('#include "chip.h"')
for bel in range(len(bel_name)): for bel in range(len(bel_name)):

View File

@ -103,3 +103,6 @@ X(D_OUT_0)
X(D_OUT_1) X(D_OUT_1)
X(D_IN_0) X(D_IN_0)
X(D_IN_1) X(D_IN_1)
X(USER_SIGNAL_TO_GLOBAL_BUFFER)
X(GLOBAL_BUFFER_OUTPUT)