blob: 66fa39eaf36098147cefec20a2512217c9cecf68 [file] [log] [blame]
module fpga #(
parameter MX = 7,
parameter MY = 8,
parameter NUM_CONFIG_REGIONS = 2,
// There are 38 IO pins in Caravel, so we distribute them around the chip.
parameter IO_NORTH = 10, // Actually 9
parameter IO_SOUTH = 8, // Actually 0
parameter IO_EAST = 10, // Actually 15
parameter IO_WEST = 10, // Actually 14
// SRAM
// MAC
parameter MAC_CONF_WIDTH = 4,
parameter MAC_MIN_WIDTH = 8,
parameter MAC_MULT_WIDTH = 2*MAC_MIN_WIDTH,
parameter MAC_ACC_WIDTH = 2*MAC_MULT_WIDTH,
parameter MAC_INT_WIDTH = 5*MAC_MIN_WIDTH,
parameter DCB_NS_W = 192,
parameter IX_IN_OUT_W = DCB_NS_W+2,
parameter DCB_DATAIN = 8,
parameter DCB_DATAOUT = 8,
// CLBs
parameter S_XX_BASE = 4,
parameter NUM_LUTS = 4,
parameter WS = 4,
parameter WD = 8,
parameter WG = 0,
parameter CLBIN = 10,
parameter CLBIN_EACH_SIDE = 10,
parameter CLBOUT = 5,
parameter CLBOUT_EACH_SIDE = 5,
parameter CLBOS = 4,
parameter CLBOD = 4,
parameter CLBX = 1
)(
inout [IO_NORTH-1:0] gpio_north,
inout [IO_SOUTH-1:0] gpio_south,
inout [IO_WEST-1:0] gpio_west,
inout [IO_EAST-1:0] gpio_east,
// Global signals
input wb_clk_i,
input wb_rst_i,
// Wishbone signals
input wbs_stb_i,
input wbs_cyc_i,
input wbs_we_i,
// Write mask
input [3:0] wbs_sel_i,
input [31:0] wbs_data_i,
input [31:0] wbs_addr_i,
output wbs_ack_o,
output [31:0] wbs_data_o
);
wire clk;
wire rst;
wire en;
/* We take the wishbone clock to be our fabric clock, I guess.
* rst is the first GPIO pin.
* en is the second GPIO pin.
*/
assign clk = wb_clk_i;
assign rst = gpio_north[9];
assign en = gpio_north[8];
/* This FPGA lays out tiles in the following fixed configuration (not to
* scale).
*
* +-----------++-----------++-----------+
* 5 | clb_tile || clb_tile || clb_tile |
* +-----------++-----------++-----------+
* +-----------++-----------++-----------+
* 4 | clb_tile || clb_tile || clb_tile |
* +-----------++-----------++-----------+
* ^ +-----------++-----------++-----------+
* | 3 | clb_tile || clb_tile || clb_tile |
* MY +-----------++-----------++-----------+
* | +-----------++-----------++-----------+
* v 2 | clb_tile || clb_tile || clb_tile |
* +-----------++-----------++-----------+
* +-----------++-----------++-----------+
* 1 | clb_tile || clb_tile || clb_tile |
* +-----------++-----------++-----------+
* +-----------++-----------++-----------+
* 0 | clb_tile || clb_tile || clb_tile |
* +-----------++-----------++-----------+
* 0 1 2
* <--- MX --->
*
*/
// Interconnect wires go between switch boxes and connection boxes.
wire [WS-1:0] ix_single_ns[MY :0][MX-1:0];
wire [WS-1:0] ix_single_ew[MY-1:0][MX :0];
wire [WD-1:0] ix_double_ns[MY :0][MX-1:0];
wire [WD-1:0] ix_double_ew[MY-1:0][MX :0];
// Direct connection wires go between connection boxes and CLBs.
wire [CLBOUT_EACH_SIDE-1:0] dc_ns[MY:0][MX-1:0];
wire [CLBIN_EACH_SIDE-1:0] dc_sn[MY:0][MX-1:0];
wire [CLBOUT_EACH_SIDE-1:0] dc_ew[MY-1:0][MX:0];
wire [CLBIN_EACH_SIDE-1:0] dc_we[MY-1:0][MX:0];
// Configuration enable signals, one per column.
wire [MX-1:0] col_cen;
wire [MX-1:0] col_set[MY:0];
wire [MX-1:0] col_shift[MY:0];
wire [MX-1:0] carry[MY:0];
genvar x;
genvar y;
generate
for (x = 0; x < MX; x = x + 1) begin:X
for (y = 0; y < MY; y = y + 1) begin:Y
clb_tile #(
.S_XX_BASE(S_XX_BASE),
.NUM_LUTS(NUM_LUTS),
.WS(WS),
.WD(WD),
.WG(WG),
.CLBIN(CLBIN),
.CLBIN_EACH_SIDE(CLBIN_EACH_SIDE),
.CLBOUT(CLBOUT),
.CLBOUT_EACH_SIDE(CLBOUT_EACH_SIDE),
.CLBOS(CLBOS),
.CLBOD(CLBOD),
.CLBX(CLBX)
) clb (
.clk(clk),
.rst(rst),
.cen(col_cen[x]),
.north_single(ix_single_ns[y+1][ x]),
.east_single( ix_single_ew[ y][x+1]),
.south_single(ix_single_ns[ y][ x]),
.west_single( ix_single_ew[ y][ x]),
.north_double(ix_double_ns[y+1][ x]),
.east_double( ix_double_ew[ y][x+1]),
.south_double(ix_double_ns[ y][ x]),
.west_double( ix_double_ew[ y][ x]),
// The names are made up and the points don't matter!
.cb_north_in( dc_ns[y+1][ x]),
.clb_south_out(dc_ns[ y][ x]),
.clb_south_in( dc_sn[ y][ x]),
.cb_north_out( dc_sn[y+1][ x]),
.clb_west_in( dc_we[ y][ x]),
.cb_east_out( dc_we[ y][x+1]),
.cb_east_in( dc_ew[ y][x+1]),
.clb_west_out( dc_ew[ y][ x]),
.carry_in( carry[y ][ x]),
.carry_out( carry[y+1][ x]),
.shift_in_hard(col_shift[ y][ x]),
.set_in_hard( col_set [ y][ x]),
.shift_out_hard( col_shift[y+1][ x]),
.set_out_hard( col_set [y+1][ x])
);
end
end
endgenerate
//mac_tile #(
// .MAC_CONF_WIDTH(MAC_CONF_WIDTH),
// .MAC_MIN_WIDTH(MAC_MIN_WIDTH),
// .MAC_MULT_WIDTH(MAC_MULT_WIDTH),
// .MAC_ACC_WIDTH(MAC_ACC_WIDTH),
// .MAC_INT_WIDTH(MAC_INT_WIDTH),
// .DCB_NS_W(DCB_NS_W),
// .IX_IN_OUT_W(IX_IN_OUT_W),
// .DCB_DATAIN(DCB_DATAIN),
// .DCB_DATAOUT(DCB_DATAOUT)
//) mac (
// .north(),
// .south(),
// .east(),
// .west()
//);
wire [3:0] wb_set_out[NUM_CONFIG_REGIONS-1:0];
wire [3:0] wb_shift_out[NUM_CONFIG_REGIONS-1:0];
wire wb_cen_out[NUM_CONFIG_REGIONS-1:0];
wire [31:0] wbs_data_o_internal[NUM_CONFIG_REGIONS-1:0];
wire wbs_ack_o_internal[NUM_CONFIG_REGIONS-1:0];
assign wbs_data_o = wbs_data_o_internal[0] | wbs_data_o_internal[1];
assign wbs_ack_o = wbs_ack_o_internal[0] | wbs_ack_o_internal[1];
wishbone_configuratorinator_00 wishbonatron_00 (
.wb_clk_i(wb_clk_i),
.wb_rst_i(wb_rst_i),
.wbs_cyc_i(wbs_cyc_i),
.wbs_stb_i(wbs_stb_i),
.wbs_we_i(wbs_we_i),
.wbs_sel_i(wbs_sel_i),
.wbs_data_i(wbs_data_i),
.wbs_addr_i(wbs_addr_i),
.wbs_ack_o(wbs_ack_o_internal[0]),
.wbs_data_o(wbs_data_o_internal[0]),
.cen(wb_cen_out[0]),
.set_out(wb_set_out[0]),
.shift_out(wb_shift_out[0])
);
wishbone_configuratorinator_10 wishbonatron_10 (
.wb_clk_i(wb_clk_i),
.wb_rst_i(wb_rst_i),
.wbs_cyc_i(wbs_cyc_i),
.wbs_stb_i(wbs_stb_i),
.wbs_we_i(wbs_we_i),
.wbs_sel_i(wbs_sel_i),
.wbs_data_i(wbs_data_i),
.wbs_addr_i(wbs_addr_i),
.wbs_ack_o(wbs_ack_o_internal[1]),
.wbs_data_o(wbs_data_o_internal[1]),
.cen(wb_cen_out[1]),
.set_out(wb_set_out[1]),
.shift_out(wb_shift_out[1])
);
genvar i;
generate
for (i = 0; i < NUM_CONFIG_REGIONS; i = i + 1) begin:wb
assign col_set[0][4*i +: 4] = wb_set_out[i][3:0];
assign col_shift[0][4*i +: 4] = wb_shift_out[i][3:0];
assign col_cen[4*i +: 4] = {wb_cen_out[i], wb_cen_out[i], wb_cen_out[i], wb_cen_out[i]};
end
endgenerate
generate
for (x = 0; x < MX; x = x + 1) begin
assign gpio_north[x] = ix_single_ns[MY][x][0];
assign gpio_south[x] = ix_single_ns[0][x][0];
end
for (y = 0; y < MY; y = y + 1) begin
assign gpio_east[y] = ix_single_ew[y][MX][0];
assign gpio_west[y] = ix_single_ew[y][ 0][0];
end
endgenerate
endmodule