openlane/chaos_automaton/runs/22_08_08_12_04/results/final/gds/chaos_automaton.gds
diff --git a/gds/chaos_subarray.gds b/gds/chaos_subarray.gds
index 80ca597..4fc82e1 100644
--- a/gds/chaos_subarray.gds
+++ b/gds/chaos_subarray.gds
Binary files differ
diff --git a/mag/chaos_subarray.mag b/mag/chaos_subarray.mag
index a8aa589..cc47162 100644
--- a/mag/chaos_subarray.mag
+++ b/mag/chaos_subarray.mag
@@ -1,7 +1,7 @@
magic
tech sky130B
magscale 1 2
-timestamp 1659731836
+timestamp 1659988397
<< viali >>
rect 1869 117249 1903 117283
rect 5549 117249 5583 117283
diff --git a/maglef/chaos_subarray.mag b/maglef/chaos_subarray.mag
index ee689b4..00d3aba 100644
--- a/maglef/chaos_subarray.mag
+++ b/maglef/chaos_subarray.mag
@@ -1,7 +1,7 @@
magic
tech sky130B
magscale 1 2
-timestamp 1659731860
+timestamp 1659988421
<< obsli1 >>
rect 1104 2159 178848 117521
<< obsm1 >>
@@ -440,7 +440,7 @@
string LEFclass BLOCK
string LEFview TRUE
string GDS_END 36487724
-string GDS_FILE /home/alex/chaos_automaton_Summer_2022/openlane/chaos_subarray/runs/22_08_05_16_33/results/signoff/chaos_subarray.magic.gds
+string GDS_FILE /home/alex/chaos_automaton_Summer_2022/openlane/chaos_subarray/runs/22_08_08_15_49/results/signoff/chaos_subarray.magic.gds
string GDS_START 141920
<< end >>
diff --git a/openlane/chaos_subarray/common_pdn.tcl b/openlane/chaos_subarray/common_pdn.tcl
new file mode 100644
index 0000000..586bd4a
--- /dev/null
+++ b/openlane/chaos_subarray/common_pdn.tcl
@@ -0,0 +1,2 @@
+set ::env(DESIGN_IS_CORE) 1
+set ::env(FP_PDN_CORE_RING) 1
\ No newline at end of file
diff --git a/sdc/chaos_subarray.sdc b/sdc/chaos_subarray.sdc
index 54240c6..817fe4e 100644
--- a/sdc/chaos_subarray.sdc
+++ b/sdc/chaos_subarray.sdc
@@ -1,6 +1,6 @@
###############################################################################
# Created by write_sdc
-# Fri Aug 5 20:34:37 2022
+# Mon Aug 8 19:50:43 2022
###############################################################################
current_design chaos_subarray
###############################################################################
diff --git a/sdf/chaos_subarray.sdf b/sdf/chaos_subarray.sdf
index e39241a..305fe02 100644
--- a/sdf/chaos_subarray.sdf
+++ b/sdf/chaos_subarray.sdf
@@ -1,7 +1,7 @@
(DELAYFILE
(SDFVERSION "3.0")
(DESIGN "chaos_subarray")
- (DATE "Fri Aug 5 20:36:50 2022")
+ (DATE "Mon Aug 8 19:52:52 2022")
(VENDOR "Parallax")
(PROGRAM "STA")
(VERSION "2.3.1")
diff --git a/signoff/chaos_subarray/metrics.csv b/signoff/chaos_subarray/metrics.csv
index 16e5677..82f79f9 100644
--- a/signoff/chaos_subarray/metrics.csv
+++ b/signoff/chaos_subarray/metrics.csv
@@ -1,2 +1,2 @@
design,design_name,config,flow_status,total_runtime,routed_runtime,(Cell/mm^2)/Core_Util,DIEAREA_mm^2,CellPer_mm^2,OpenDP_Util,Peak_Memory_Usage_MB,cell_count,tritonRoute_violations,Short_violations,MetSpc_violations,OffGrid_violations,MinHole_violations,Other_violations,Magic_violations,antenna_violations,lvs_total_errors,cvc_total_errors,klayout_violations,wire_length,vias,wns,pl_wns,optimized_wns,fastroute_wns,spef_wns,tns,pl_tns,optimized_tns,fastroute_tns,spef_tns,HPWL,routing_layer1_pct,routing_layer2_pct,routing_layer3_pct,routing_layer4_pct,routing_layer5_pct,routing_layer6_pct,wires_count,wire_bits,public_wires_count,public_wire_bits,memories_count,memory_bits,processes_count,cells_pre_abc,AND,DFF,NAND,NOR,OR,XOR,XNOR,MUX,inputs,outputs,level,EndCaps,TapCells,Diodes,Total_Physical_Cells,CoreArea_um^2,power_slowest_internal_uW,power_slowest_switching_uW,power_slowest_leakage_uW,power_typical_internal_uW,power_typical_switching_uW,power_typical_leakage_uW,power_fastest_internal_uW,power_fastest_switching_uW,power_fastest_leakage_uW,critical_path_ns,suggested_clock_period,suggested_clock_frequency,CLOCK_PERIOD,SYNTH_STRATEGY,SYNTH_MAX_FANOUT,FP_CORE_UTIL,FP_ASPECT_RATIO,FP_PDN_VPITCH,FP_PDN_HPITCH,PL_TARGET_DENSITY,GLB_RT_ADJUSTMENT,STD_CELL_LIBRARY,CELL_PAD,DIODE_INSERTION_STRATEGY
-/home/alex/chaos_automaton_Summer_2022/openlane/chaos_subarray,chaos_subarray,22_08_05_16_33,flow completed,0h9m55s0ms,0h2m47s0ms,-2.0,0.54,-1,39.46,3550.07,-1,0,0,0,0,0,0,0,6,0,-1,-1,339198,103321,-26.09,-26.09,0.0,0.0,-1,-26.09,-26.09,0.0,0.0,-1,132918716.0,0.0,31.47,19.28,0.8,0.26,-1,1040,7346,1040,7346,0,0,0,6500,0,100,0,0,0,0,0,0,2,6600,5,424,7276,0,7700,514032.2304,0.012,0.00293,0.000174,0.0154,0.00382,2.02e-07,0.0179,0.00456,3.87e-07,1.9400000000000004,26.0,38.46153846153846,25,AREA 0,12,50,1,153.6,153.18,0.48,0.3,sky130_fd_sc_hd,4,4
+/home/alex/chaos_automaton_Summer_2022/openlane/chaos_subarray,chaos_subarray,22_08_08_15_49,flow completed,0h9m51s0ms,0h2m40s0ms,-2.0,0.54,-1,39.46,3576.88,-1,0,0,0,0,0,0,0,6,0,-1,-1,339198,103321,-26.09,-26.09,0.0,0.0,-1,-26.09,-26.09,0.0,0.0,-1,132918716.0,0.0,31.47,19.28,0.8,0.26,-1,1040,7346,1040,7346,0,0,0,6500,0,100,0,0,0,0,0,0,2,6600,5,424,7276,0,7700,514032.2304,0.012,0.00293,0.000174,0.0154,0.00382,2.02e-07,0.0179,0.00456,3.87e-07,1.9400000000000004,26.0,38.46153846153846,25,AREA 0,12,50,1,153.6,153.18,0.48,0.3,sky130_fd_sc_hd,4,4
diff --git a/verilog/dv/verify.log b/verilog/dv/verify.log
deleted file mode 100644
index e69de29..0000000
--- a/verilog/dv/verify.log
+++ /dev/null
diff --git a/verilog/rtl/chaos_automaton.v b/verilog/rtl/chaos_automaton.v
index a37ac10..afe54ae 100644
--- a/verilog/rtl/chaos_automaton.v
+++ b/verilog/rtl/chaos_automaton.v
@@ -13,9 +13,6 @@
// limitations under the License.
// SPDX-License-Identifier: Apache-2.0
-// NOTE: Remove the following line before synthesizing
-// `define MPRJ_IO_PADS 38
-
`default_nettype none
/*
*-------------------------------------------------------------
@@ -52,17 +49,35 @@
* in addition to the 64 flops so that the scan chain can be cycled
* without affecting ongoing operation of the automaton.
*
+ * Version v2: The logic analyzer is replaced by a local version that
+ * has the same number of bits as periphery I/O. There are two registers
+ * per signal, one for output, and one for input. All registers update
+ * simultaneously. Every periphery input is connected to three sources,
+ * XOR'd together: A periphery output, a GPIO input, and a register.
+ * Every periphery output is connected to three sinks: A periphery
+ * input, a GPIO output, and a register. The periphery output-to-input
+ * connections can be a loop-back or neighbor loop-back.
+ *
* Memory mapped address space:
*
- * BASE_ADR + 7 to BASE_ADR + 0: Data to read or write
- * BASE_ADR + 15 to BASE_ADR + 8: Core cell address for read/write
- * BASE_ADR + 16: Triggers
+ * BASE_ADR + 7 to BASE_ADR + 0: Configuration data to read or write
+ * BASE_ADR + 11 to BASE_ADR + 8: Core cell address for read/write
+ * BASE_ADR + 12: Triggers
+ * BASE_ADR + 17 to BASE_ADR + 16: Per-side input configuration
+ * BASE_ADR + 18: GPIO input and output slice selection
+ * BASE_ADR + 19: GPIO direction
+ * BASE_ADR + ?? to BASE_ADR + 20: Operational data
+ * (BASE_ADR + 39 for 50x30 array)
*
* Trigger bits:
* bit 0: Shift by (address) cells (64 bits).
* bit 1: Finish cycle. Return shift register to run state, toggle "hold"
*
- * Both trigger bits are self-resetting. The trigger bit (as read) remains
+ * (to be done:)
+ * bit 2: Capture data
+ * bit 3: Apply data
+ *
+ * All trigger bits are self-resetting. The trigger bit (as read) remains
* high until the transfer has completed. The trigger bit can be polled to
* determine when the cycle has completed.
*
@@ -90,7 +105,9 @@
*-------------------------------------------------------------
*/
-//`include "chaos_subarray.v"
+// NOTE: Uncomment the following lines for syntax checking
+// `define MPRJ_IO_PADS 38
+// `include "chaos_subarray.v"
/*
*-----------------------------------------------------------------
@@ -103,7 +120,7 @@
parameter YSIZE = 50, // Total number of cells top to bottom
parameter XTOP = 3, // Number of sub-arrays left to right
parameter YTOP = 5, // Number of sub-arrays top to bottom
- parameter ASIZE = 10, // Enough bits to count XSIZE * YSIZE
+ parameter ASIZE = 11, // Enough bits to count XSIZE * YSIZE
parameter BASE_ADR = 32'h 3000_0000 // Wishbone base address
)(
`ifdef USE_POWER_PINS
@@ -129,7 +146,7 @@
output wbs_ack_o,
output [31:0] wbs_dat_o,
- // Logic Analyzer Signals
+ // Logic Analyzer Signals (unused)
input [127:0] la_data_in,
output [127:0] la_data_out,
input [127:0] la_oenb,
@@ -151,17 +168,20 @@
`define LOAD 3'b101
`define CONFIGL 8'h00 /* Address offset of configuration data low word */
-`define CONFIGH 8'h04 /* Address offset of configuration data high word */
-`define ADDRESS 8'h08 /* Address offset of cell address value */
-`define XFER 8'h0c /* Address offset of transfer bits */
+`define CONFIGH 8'h01 /* Address offset of configuration data high word */
+`define ADDRESS 8'h02 /* Address offset of cell address value */
+`define XFER 8'h03 /* Address offset of transfer bits */
+`define DIRECT 8'h04 /* Address offset of GPIO directions */
+`define SOURCE 8'h04 /* Address offset of GPIO source selection */
+`define DATATOP 8'h05 /* Address offset of start of data section */
`define MAXADDR (XSIZE * YSIZE) /* Highest cell address plus one */
reg clk; /* serial clock to transfer data */
reg hold; /* trigger to hold transferred data */
reg [2:0] xfer_state; /* state of the data transfer */
- reg [1:0] xfer_ctrl; /* Transfer trigger bits */
- reg [63:0] config_data; /* 64 bits to read or write */
+ reg [1:0] xfer_ctrl; /* Configuration transfer trigger bits */
+ reg [63:0] config_data; /* 64 bits to read or write configuration */
reg [ASIZE - 1:0] cell_addr; /* Core cell to address */
reg [ASIZE - 1:0] cell_offset; /* Current offset of shift register */
@@ -174,6 +194,15 @@
wire [1:0] config_sel;
wire address_sel;
wire xfer_sel;
+ wire direct_sel;
+ wire source_sel;
+
+ // NOTE: This should be parameterized.
+ // For the 50x30 array, there are 50+50+30+30 = 160 periphery bits =
+ // 5 words of 32 bits. This is hard-coded for convenience. If the
+ // array size changes, this needs to be changed as well. Needs to be
+ // converted to a "generate" block.
+ wire [4:0] data_sel;
wire valid;
reg ready;
@@ -186,30 +215,83 @@
reg [63:0] wdata;
reg write;
- wire [2*XSIZE + 2*YSIZE - 1: 0] data_in;
+ // Direction for each GPIO (32 used)
+ reg [31:0] gpio_oeb;
+
+ // Data to and from array periphery I/O
+ wire [YSIZE-1: 0] data_in_east;
+ wire [YSIZE-1: 0] data_in_west;
+ wire [XSIZE-1: 0] data_in_north;
+ wire [XSIZE-1: 0] data_in_south;
+
+ wire [YSIZE-1: 0] data_out_east;
+ wire [YSIZE-1: 0] data_out_west;
+ wire [XSIZE-1: 0] data_out_north;
+ wire [XSIZE-1: 0] data_out_south;
+
+ // Latched output for wishbone read-back (to be done)
+ // TBD
+
+ // Latched input from wishbone (to do: Make shadow register)
+ wire [YSIZE-1: 0] latched_in_east;
+ wire [YSIZE-1: 0] latched_in_west;
+ wire [XSIZE-1: 0] latched_in_north;
+ wire [XSIZE-1: 0] latched_in_south;
+
+ // Shadow registers for wishbone input (to be done)
+ // TBD
+
+ // Register array mapping latched data to 32-bit sections for data
+ // transfer through the wishbone
+ reg [XSIZE*2 + YSIZE*2 - 1:0] latched_in;
+
+ // Wire array mapping output data to 32-bit sections for data
+ // transfer through the wishbone
+ wire [XSIZE*2 + YSIZE*2 - 1:0] data_out;
+
+ // Periphery output-to-input loop-back selection
+ reg [2:0] north_loopback;
+ reg [2:0] east_loopback;
+ reg [2:0] south_loopback;
+ reg [2:0] west_loopback;
+
+// Loopback value definitions
+
+`define INPUT_LOW 3'b000
+`define INPUT_HIGH 3'b001
+`define LOOPBACK 3'b010
+`define NEIGHBOR_LEFT 3'b011
+`define NEIGHBOR_RIGHT 3'b100
+
+ // GPIO slicing (because there are many fewer GPIO than array outputs)
+ // GPIOs can be clustered on either end or in the center of the array
+ // side, or distributed along the side (1 GPIO per 5 array cells)
+ reg [1:0] gpio_output_slice;
+ reg [1:0] gpio_input_slice;
+
+ // Registered GPIO directions go directly to io_oeb[37:6]. Leave the
+ // lower 6 GPIO to the management processor.
+ assign io_oeb = {gpio_oeb, 6'b1};
// Wishbone address select indicators
- assign config_sel[0] = (wbs_adr_i[7:0] == `CONFIGL);
- assign config_sel[1] = (wbs_adr_i[7:0] == `CONFIGH);
- assign address_sel = (wbs_adr_i[7:0] == `ADDRESS);
- assign xfer_sel = (wbs_adr_i[7:0] == `XFER);
+ assign config_sel[0] = (wbs_adr_i[7:2] == `CONFIGL);
+ assign config_sel[1] = (wbs_adr_i[7:2] == `CONFIGH);
+ assign address_sel = (wbs_adr_i[7:2] == `ADDRESS);
+ assign xfer_sel = (wbs_adr_i[7:2] == `XFER);
+ assign direct_sel = (wbs_adr_i[7:2] == `DIRECT);
+ assign source_sel = (wbs_adr_i[7:2] == `SOURCE);
- assign selected = config_sel[1] || config_sel[0] || address_sel || xfer_sel;
-
+ // Hard-coded to 5 words; see note above
+ assign data_sel[0] = (wbs_adr_i[7:2] == (`DATATOP + 0));
+ assign data_sel[1] = (wbs_adr_i[7:2] == (`DATATOP + 1));
+ assign data_sel[2] = (wbs_adr_i[7:2] == (`DATATOP + 2));
+ assign data_sel[3] = (wbs_adr_i[7:2] == (`DATATOP + 3));
+ assign data_sel[4] = (wbs_adr_i[7:2] == (`DATATOP + 4));
+
assign valid = wbs_cyc_i && wbs_stb_i;
assign wbs_ack_o = ready;
assign iomem_we = wbs_sel_i & {4{wbs_we_i}};
- // Chip pin output (Connects to a subset of la_data_in;
- // 9 signals each N and S, 10 signals each W and E)
- assign io_out = {la_data_out[2*YSIZE + XSIZE + 8: 2*YSIZE + XSIZE], // north
- la_data_out[2*YSIZE + 8: 2*YSIZE], // south
- la_data_out[YSIZE + 9: YSIZE], // east
- la_data_out[9:0]}; // west
-
- // Chip pin direction is assigned to la_data sub-array
- assign io_oeb = la_data_in[127:127-38] & ~la_oenb[127:127-38];
-
// IRQ
assign irq = 3'b000; // Unused
@@ -232,44 +314,298 @@
.rdata(rdata),
.wdata(wdata),
.write(write),
- .data_in(data_in),
- .data_out(la_data_out[2*XSIZE + 2*YSIZE - 1: 0])
+ .data_in_east(data_in_east),
+ .data_in_west(data_in_west),
+ .data_in_north(data_in_north),
+ .data_in_south(data_in_south),
+ .data_out_east(data_out_east),
+ .data_out_west(data_out_west),
+ .data_out_north(data_out_north),
+ .data_out_south(data_out_south)
);
- /* Hook up io_in (multiplexed with la_data_int based on value of la_oenb,
- * using the same subsets as used for io_out). The expressions are more
- * complicated because the signals that are connected to the GPIO pins
- * have to be multiplexed with the logic analyzer inputs.
- */
+ // Wire definitions mapping the GPIO to the array periphery
+ wire [YSIZE-1:0] gpio_east, gpio_west;
+ wire [XSIZE-1:0] gpio_north, gpio_south;
- genvar i;
+ // Wire definitions mapping the array periphery loop-back connections
+ wire [YSIZE-1:0] data_muxed_east, data_muxed_west;
+ wire [XSIZE-1:0] data_muxed_north, data_muxed_south;
- generate
- for (i = 2*YSIZE + XSIZE + 9; i < 2*YSIZE + 2*XSIZE; i=i+1) begin
- assign data_in[i] = la_data_in[i];
- end
- for (i = 2 * YSIZE + XSIZE; i < 2*YSIZE + XSIZE + 9; i=i+1) begin
- assign data_in[i] = la_oenb[i] ? io_in[i - 2*YSIZE + XSIZE + 29] : la_data_in[i];
- end
- for (i = 2 * YSIZE + 9; i < 2 * YSIZE + XSIZE; i=i+1) begin
- assign data_in[i] = la_data_in[i];
- end
- for (i = 2 * YSIZE; i < 2 * YSIZE + 9; i=i+1) begin
- assign data_in[i] = la_oenb[i] ? io_in[i - 2*YSIZE + 20] : la_data_in[i];
- end
- for (i = YSIZE + 10; i < 2 * YSIZE; i=i+1) begin
- assign data_in[i] = la_data_in[i];
- end
- for (i = YSIZE; i < YSIZE + 10; i=i+1) begin
- assign data_in[i] = la_oenb[i] ? io_in[i - YSIZE + 10] : la_data_in[i];
- end
- for (i = 10; i < YSIZE; i=i+1) begin
- assign data_in[i] = la_data_in[i];
- end
- for (i = 0; i < 10; i=i+1) begin
- assign data_in[i] = la_oenb[i] ? io_in[i]: la_data_in[i];
- end
- endgenerate
+ // Hook up array inputs (data_in_*) to an XOR'd combination of
+ // (1) array outputs (data_out_*, muxed into data_muxed_*),
+ // (2) the GPIO pads (muxed into gpio_*), and
+ // (3) data from the wishbone bus (latched_in_*).
+
+ assign data_in_west = latched_in_west ^ gpio_west ^ data_muxed_west;
+ assign data_in_east = latched_in_east ^ gpio_east ^ data_muxed_east;
+ assign data_in_south = latched_in_south ^ gpio_south ^ data_muxed_south;
+ assign data_in_north = latched_in_north ^ gpio_north ^ data_muxed_north;
+
+`define INPUT_LOW 3'b000
+`define INPUT_HIGH 3'b001
+`define LOOPBACK 3'b010
+`define NEIGHBOR_LEFT 3'b011
+`define NEIGHBOR_RIGHT 3'b100
+
+ // Define loop-back inputs
+ assign data_muxed_west =
+ (west_loopback == `NEIGHBOR_LEFT) ? {data_out_west[YSIZE-2:0], 1'b0} :
+ (west_loopback == `NEIGHBOR_RIGHT) ? {1'b0, data_out_west[YSIZE-1:1]} :
+ (west_loopback == `LOOPBACK) ? data_out_west :
+ (west_loopback == `INPUT_HIGH) ? 'b1 : 'b0;
+
+ assign data_muxed_east =
+ (east_loopback == `NEIGHBOR_LEFT) ? {data_out_east[YSIZE-2:0], 1'b0} :
+ (east_loopback == `NEIGHBOR_RIGHT) ? {1'b0, data_out_east[YSIZE-1:1]} :
+ (east_loopback == `LOOPBACK) ? data_out_east :
+ (east_loopback == `INPUT_HIGH) ? 'b1 : 'b0;
+
+ assign data_muxed_south =
+ (south_loopback == `NEIGHBOR_LEFT) ? {data_out_south[XSIZE-2:0], 1'b0} :
+ (south_loopback == `NEIGHBOR_RIGHT) ? {1'b0, data_out_south[XSIZE-1:1]} :
+ (south_loopback == `LOOPBACK) ? data_out_south :
+ (south_loopback == `INPUT_HIGH) ? 'b1 : 'b0;
+
+ assign data_muxed_north =
+ (north_loopback == `NEIGHBOR_LEFT) ? {data_out_north[XSIZE-2:0], 1'b0} :
+ (north_loopback == `NEIGHBOR_RIGHT) ? {1'b0, data_out_north[XSIZE-1:1]} :
+ (north_loopback == `LOOPBACK) ? data_out_north :
+ (south_loopback == `INPUT_HIGH) ? 'b1 : 'b0;
+
+ // Define I/O input slices
+ // NOTE: This is hard-coded. There are 38 GPIOs. Assigning 32 of them
+ // (GPIO 37 to 6) to array inputs and outputs. These are arranged as
+ // 10 on the sides and 6 on the top and bottom. These are further sub-
+ // divided into 5 inputs and 5 outputs on the sides, and 3 inputs and
+ // 3 outputs on top and bottom. Depending on the selection, these
+ // can be injected into various places around the array.
+
+ // Another note: It probably makes more sense to define vectors for
+ // io_in_east, io_in_north, etc., and align them in the direction of
+ // the arrays (high to low index is top to bottom, or right to left).
+
+ assign gpio_east = // I/O 15 to 6
+ (gpio_input_slice == 0) ? // Distributed
+ {2'b0, io_in[15], 4'b0, io_in[14], 4'b0, io_in[13],
+ 4'b0, io_in[12], 4'b0, io_in[11], 4'b0, io_in[10],
+ 4'b0, io_in[9], 4'b0, io_in[8], 4'b0, io_in[7],
+ 4'b0, io_in[6], 2'b0} :
+ (gpio_input_slice == 1) ? {40'b0, io_in[15:6]} : // Bottom shifted
+ (gpio_input_slice == 2) ? {20'b0, io_in[15:6], 20'b0} : // Centered
+ {io_in[15:6], 40'b0}; // Top shifted
+
+ assign gpio_north = // I/O 21 to 16
+ (gpio_input_slice == 0) ? // Distributed
+ {2'b0, io_in[16], 4'b0, io_in[17], 4'b0, io_in[18],
+ 4'b0, io_in[19], 4'b0, io_in[20], 4'b0, io_in[21], 2'b0} :
+ (gpio_input_slice == 1) ? // Right shifted
+ {14'b0, io_in[16], io_in[17], io_in[18], io_in[19],
+ io_in[20], io_in[21]} :
+ (gpio_input_slice == 2) ? // Centered
+ {7'b0, io_in[16], io_in[17], io_in[18], io_in[19],
+ io_in[20], io_in[21], 7'b0} :
+ {io_in[16], io_in[17], io_in[18], io_in[19], io_in[20],
+ io_in[21], 4'b0}; // Left shifted
+
+ assign gpio_west = // I/O 22 to 31
+ (gpio_input_slice == 0) ? // Distributed
+ {2'b0, io_in[22], 4'b0, io_in[23], 4'b0, io_in[24],
+ 4'b0, io_in[25], 4'b0, io_in[26], 4'b0, io_in[27],
+ 4'b0, io_in[28], 4'b0, io_in[29], 4'b0, io_in[30],
+ 4'b0, io_in[31], 2'b0} :
+ (gpio_input_slice == 1) ? // Bottom shifted
+ {40'b0, io_in[22], io_in[23], io_in[24], io_in[25],
+ io_in[26], io_in[27], io_in[28], io_in[29], io_in[31],
+ io_in[31]} :
+ (gpio_input_slice == 2) ? // Centered
+ {20'b0, io_in[22], io_in[23], io_in[24], io_in[25],
+ io_in[26], io_in[27], io_in[28], io_in[29], io_in[31],
+ io_in[31], 20'b0} :
+ {io_in[22], io_in[23], io_in[24], io_in[25], io_in[26],
+ io_in[27], io_in[28], io_in[29], io_in[31], io_in[31],
+ 40'b0}; // Top shifted
+
+ assign gpio_south = // I/O 32 to 37
+ (gpio_input_slice == 0) ? // Distributed
+ {2'b0, io_in[37], 4'b0, io_in[36], 4'b0, io_in[35],
+ 4'b0, io_in[34], 4'b0, io_in[33], 4'b0, io_in[32], 2'b0} :
+ (gpio_input_slice == 1) ? {14'b0, io_in[37:32]} : // Right shifted
+ (gpio_input_slice == 2) ? {7'b0, io_in[37:32], 7'b0} : // Centered
+ {io_in[37:32], 14'b0}; // Left shifted
+
+ // East side
+ assign io_out[6] =
+ (gpio_output_slice == 0) ? data_out_east[2] : // Distributed
+ (gpio_output_slice == 1) ? data_out_east[20] : // Center
+ (gpio_output_slice == 2) ? data_out_east[40] : // Top
+ data_out_east[0]; // Bottom
+ assign io_out[7] =
+ (gpio_output_slice == 0) ? data_out_east[7] : // Distributed
+ (gpio_output_slice == 1) ? data_out_east[21] : // Center
+ (gpio_output_slice == 2) ? data_out_east[41] : // Top
+ data_out_east[1]; // Bottom
+ assign io_out[8] =
+ (gpio_output_slice == 0) ? data_out_east[12] : // Distributed
+ (gpio_output_slice == 1) ? data_out_east[22] : // Center
+ (gpio_output_slice == 2) ? data_out_east[42] : // Top
+ data_out_east[2]; // Bottom
+ assign io_out[9] =
+ (gpio_output_slice == 0) ? data_out_east[17] : // Distributed
+ (gpio_output_slice == 1) ? data_out_east[23] : // Center
+ (gpio_output_slice == 2) ? data_out_east[43] : // Top
+ data_out_east[3]; // Bottom
+ assign io_out[10] =
+ (gpio_output_slice == 0) ? data_out_east[22] : // Distributed
+ (gpio_output_slice == 1) ? data_out_east[24] : // Center
+ (gpio_output_slice == 2) ? data_out_east[44] : // Top
+ data_out_east[4]; // Bottom
+ assign io_out[11] =
+ (gpio_output_slice == 0) ? data_out_east[27] : // Distributed
+ (gpio_output_slice == 1) ? data_out_east[25] : // Center
+ (gpio_output_slice == 2) ? data_out_east[45] : // Top
+ data_out_east[5]; // Bottom
+ assign io_out[12] =
+ (gpio_output_slice == 0) ? data_out_east[32] : // Distributed
+ (gpio_output_slice == 1) ? data_out_east[26] : // Center
+ (gpio_output_slice == 2) ? data_out_east[46] : // Top
+ data_out_east[6]; // Bottom
+ assign io_out[13] =
+ (gpio_output_slice == 0) ? data_out_east[37] : // Distributed
+ (gpio_output_slice == 1) ? data_out_east[27] : // Center
+ (gpio_output_slice == 2) ? data_out_east[47] : // Top
+ data_out_east[7]; // Bottom
+ assign io_out[14] =
+ (gpio_output_slice == 0) ? data_out_east[42] : // Distributed
+ (gpio_output_slice == 1) ? data_out_east[28] : // Center
+ (gpio_output_slice == 2) ? data_out_east[48] : // Top
+ data_out_east[8]; // Bottom
+ assign io_out[15] =
+ (gpio_output_slice == 0) ? data_out_east[47] : // Distributed
+ (gpio_output_slice == 1) ? data_out_east[29] : // Center
+ (gpio_output_slice == 2) ? data_out_east[49] : // Top
+ data_out_east[9]; // Bottom
+
+ // North side
+ assign io_out[16] =
+ (gpio_output_slice == 0) ? data_out_north[27] : // Distributed
+ (gpio_output_slice == 1) ? data_out_north[16] : // Center
+ (gpio_output_slice == 2) ? data_out_north[29] : // Right
+ data_out_north[5]; // Left
+ assign io_out[17] =
+ (gpio_output_slice == 0) ? data_out_north[22] : // Distributed
+ (gpio_output_slice == 1) ? data_out_north[15] : // Center
+ (gpio_output_slice == 2) ? data_out_north[28] : // Right
+ data_out_north[4]; // Left
+ assign io_out[18] =
+ (gpio_output_slice == 0) ? data_out_north[17] : // Distributed
+ (gpio_output_slice == 1) ? data_out_north[14] : // Center
+ (gpio_output_slice == 2) ? data_out_north[27] : // Right
+ data_out_north[3]; // Left
+ assign io_out[19] =
+ (gpio_output_slice == 0) ? data_out_north[12] : // Distributed
+ (gpio_output_slice == 1) ? data_out_north[13] : // Center
+ (gpio_output_slice == 2) ? data_out_north[26] : // Right
+ data_out_north[2]; // Left
+ assign io_out[20] =
+ (gpio_output_slice == 0) ? data_out_north[7] : // Distributed
+ (gpio_output_slice == 1) ? data_out_north[12] : // Center
+ (gpio_output_slice == 2) ? data_out_north[25] : // Right
+ data_out_north[1]; // Left
+ assign io_out[21] =
+ (gpio_output_slice == 0) ? data_out_north[2] : // Distributed
+ (gpio_output_slice == 1) ? data_out_north[11] : // Center
+ (gpio_output_slice == 2) ? data_out_north[24] : // Right
+ data_out_north[0]; // Left
+
+ // West side
+ assign io_out[22] =
+ (gpio_output_slice == 0) ? data_out_west[47] : // Distributed
+ (gpio_output_slice == 1) ? data_out_west[29] : // Center
+ (gpio_output_slice == 2) ? data_out_west[49] : // Top
+ data_out_east[9]; // Bottom
+ assign io_out[23] =
+ (gpio_output_slice == 0) ? data_out_west[42] : // Distributed
+ (gpio_output_slice == 1) ? data_out_west[28] : // Center
+ (gpio_output_slice == 2) ? data_out_west[48] : // Top
+ data_out_east[8]; // Bottom
+ assign io_out[24] =
+ (gpio_output_slice == 0) ? data_out_west[37] : // Distributed
+ (gpio_output_slice == 1) ? data_out_west[27] : // Center
+ (gpio_output_slice == 2) ? data_out_west[47] : // Top
+ data_out_east[7]; // Bottom
+ assign io_out[25] =
+ (gpio_output_slice == 0) ? data_out_west[32] : // Distributed
+ (gpio_output_slice == 1) ? data_out_west[26] : // Center
+ (gpio_output_slice == 2) ? data_out_west[46] : // Top
+ data_out_east[6]; // Bottom
+ assign io_out[26] =
+ (gpio_output_slice == 0) ? data_out_west[27] : // Distributed
+ (gpio_output_slice == 1) ? data_out_west[25] : // Center
+ (gpio_output_slice == 2) ? data_out_west[45] : // Top
+ data_out_east[5]; // Bottom
+ assign io_out[27] =
+ (gpio_output_slice == 0) ? data_out_west[22] : // Distributed
+ (gpio_output_slice == 1) ? data_out_west[24] : // Center
+ (gpio_output_slice == 2) ? data_out_west[44] : // Top
+ data_out_east[4]; // Bottom
+ assign io_out[28] =
+ (gpio_output_slice == 0) ? data_out_west[17] : // Distributed
+ (gpio_output_slice == 1) ? data_out_west[23] : // Center
+ (gpio_output_slice == 2) ? data_out_west[43] : // Top
+ data_out_east[3]; // Bottom
+ assign io_out[29] =
+ (gpio_output_slice == 0) ? data_out_west[12] : // Distributed
+ (gpio_output_slice == 1) ? data_out_west[22] : // Center
+ (gpio_output_slice == 2) ? data_out_west[42] : // Top
+ data_out_east[2]; // Bottom
+ assign io_out[30] =
+ (gpio_output_slice == 0) ? data_out_west[7] : // Distributed
+ (gpio_output_slice == 1) ? data_out_west[21] : // Center
+ (gpio_output_slice == 2) ? data_out_west[41] : // Top
+ data_out_east[1]; // Bottom
+ assign io_out[31] =
+ (gpio_output_slice == 0) ? data_out_west[2] : // Distributed
+ (gpio_output_slice == 1) ? data_out_west[20] : // Center
+ (gpio_output_slice == 2) ? data_out_west[40] : // Top
+ data_out_east[0]; // Bottom
+
+ // South side
+ assign io_out[32] =
+ (gpio_output_slice == 0) ? data_out_south[2] : // Distributed
+ (gpio_output_slice == 1) ? data_out_south[11] : // Center
+ (gpio_output_slice == 2) ? data_out_south[24] : // Right
+ data_out_north[0]; // Left
+ assign io_out[33] =
+ (gpio_output_slice == 0) ? data_out_south[7] : // Distributed
+ (gpio_output_slice == 1) ? data_out_south[12] : // Center
+ (gpio_output_slice == 2) ? data_out_south[25] : // Right
+ data_out_north[1]; // Left
+ assign io_out[34] =
+ (gpio_output_slice == 0) ? data_out_south[12] : // Distributed
+ (gpio_output_slice == 1) ? data_out_south[13] : // Center
+ (gpio_output_slice == 2) ? data_out_south[26] : // Right
+ data_out_north[2]; // Left
+ assign io_out[35] =
+ (gpio_output_slice == 0) ? data_out_south[17] : // Distributed
+ (gpio_output_slice == 1) ? data_out_south[14] : // Center
+ (gpio_output_slice == 2) ? data_out_south[27] : // Right
+ data_out_north[3]; // Left
+ assign io_out[36] =
+ (gpio_output_slice == 0) ? data_out_south[22] : // Distributed
+ (gpio_output_slice == 1) ? data_out_south[15] : // Center
+ (gpio_output_slice == 2) ? data_out_south[28] : // Right
+ data_out_north[4]; // Left
+ assign io_out[37] =
+ (gpio_output_slice == 0) ? data_out_south[27] : // Distributed
+ (gpio_output_slice == 1) ? data_out_south[16] : // Center
+ (gpio_output_slice == 2) ? data_out_south[29] : // Right
+ data_out_north[5]; // Left
+
+ // Map the output data from the sides to a single array that can be
+ // broken up into 32 bit segments for data transfer.
+
+ assign data_out = {data_out_north, data_out_east, data_out_south, data_out_west};
/* Read data (only rdata is something that was not written by the processor) */
@@ -285,6 +621,22 @@
/* When ADDRESS is selected, pass back the existing cell */
/* count rather than what was written into cell_addr. */
rdata_pre = bit_count[ASIZE + 6: 7];
+ end else if (direct_sel) begin
+ rdata_pre = gpio_oeb;
+ end else if (source_sel) begin
+ rdata_pre = {10'b0, gpio_output_slice, 2'b0, gpio_input_slice,
+ 1'b0, north_loopback, 1'b0, east_loopback,
+ 1'b0, south_loopback, 1'b0, west_loopback};
+ end else if (data_sel[0]) begin
+ rdata_pre = data_out[31:0];
+ end else if (data_sel[1]) begin
+ rdata_pre = data_out[63:32];
+ end else if (data_sel[2]) begin
+ rdata_pre = data_out[95:64];
+ end else if (data_sel[3]) begin
+ rdata_pre = data_out[127:96];
+ end else if (data_sel[4]) begin
+ rdata_pre = data_out[159:128];
end
end
@@ -298,13 +650,19 @@
ready <= 0;
if (valid && !ready && wbs_adr_i[31:8] == BASE_ADR[31:8]) begin
ready <= 1'b1;
- if (selected) begin
- wbs_dat_o <= rdata_pre;
- end
+ wbs_dat_o <= rdata_pre;
end
end
end
+ // Map the latched data from the sides to a single array that can be
+ // broken up into 32 bit segments for data transfer.
+
+ assign latched_in_north = latched_in[2*XSIZE+2*YSIZE-1:2*XSIZE+YSIZE];
+ assign latched_in_east = latched_in[2*YSIZE+XSIZE-1:YSIZE+XSIZE];
+ assign latched_in_south = latched_in[YSIZE+XSIZE-1:YSIZE];
+ assign latched_in_west = latched_in[YSIZE-1:0];
+
/* Write data */
always @(posedge wb_clk_i or posedge wb_rst_i) begin
@@ -332,6 +690,49 @@
end else if (address_sel) begin
/* NOTE: If XSIZE * YSIZE > 256, this must be adjusted */
if (iomem_we[0]) cell_addr <= wbs_dat_i[7:0];
+ end else if (direct_sel) begin
+ if (iomem_we[0]) gpio_oeb[7:0] <= wbs_dat_i[7:0];
+ if (iomem_we[1]) gpio_oeb[15:8] <= wbs_dat_i[15:8];
+ if (iomem_we[2]) gpio_oeb[23:16] <= wbs_dat_i[23:16];
+ if (iomem_we[3]) gpio_oeb[31:24] <= wbs_dat_i[31:24];
+ end else if (source_sel) begin
+ if (iomem_we[0]) begin
+ west_loopback <= wbs_dat_i[2:0];
+ south_loopback <= wbs_dat_i[6:4];
+ end
+ if (iomem_we[1]) begin
+ east_loopback <= wbs_dat_i[2:0];
+ north_loopback <= wbs_dat_i[6:4];
+ end
+ if (iomem_we[2]) begin
+ gpio_input_slice <= wbs_dat_i[1:0];
+ gpio_output_slice <= wbs_dat_i[5:4];
+ end
+ end else if (data_sel[0]) begin
+ if (iomem_we[0]) latched_in[7:0] <= wbs_dat_i[7:0];
+ if (iomem_we[1]) latched_in[15:8] <= wbs_dat_i[15:8];
+ if (iomem_we[2]) latched_in[23:16] <= wbs_dat_i[23:16];
+ if (iomem_we[3]) latched_in[31:24] <= wbs_dat_i[31:24];
+ end else if (data_sel[1]) begin
+ if (iomem_we[0]) latched_in[39:32] <= wbs_dat_i[7:0];
+ if (iomem_we[1]) latched_in[47:40] <= wbs_dat_i[15:8];
+ if (iomem_we[2]) latched_in[55:48] <= wbs_dat_i[23:16];
+ if (iomem_we[3]) latched_in[63:56] <= wbs_dat_i[31:24];
+ end else if (data_sel[2]) begin
+ if (iomem_we[0]) latched_in[71:64] <= wbs_dat_i[7:0];
+ if (iomem_we[1]) latched_in[79:72] <= wbs_dat_i[15:8];
+ if (iomem_we[2]) latched_in[87:80] <= wbs_dat_i[23:16];
+ if (iomem_we[3]) latched_in[95:88] <= wbs_dat_i[31:24];
+ end else if (data_sel[3]) begin
+ if (iomem_we[0]) latched_in[103:96] <= wbs_dat_i[7:0];
+ if (iomem_we[1]) latched_in[111:104] <= wbs_dat_i[15:8];
+ if (iomem_we[2]) latched_in[119:112] <= wbs_dat_i[23:16];
+ if (iomem_we[3]) latched_in[127:120] <= wbs_dat_i[31:24];
+ end else if (data_sel[4]) begin
+ if (iomem_we[0]) latched_in[135:128] <= wbs_dat_i[7:0];
+ if (iomem_we[1]) latched_in[143:136] <= wbs_dat_i[15:8];
+ if (iomem_we[2]) latched_in[151:144] <= wbs_dat_i[23:16];
+ if (iomem_we[3]) latched_in[159:152] <= wbs_dat_i[31:24];
end
end else begin
xfer_ctrl <= 0; // Immediately self-resetting
@@ -426,8 +827,14 @@
input write,
input [63:0] wdata,
output [63:0] rdata,
- input [2*XSIZE + 2*YSIZE - 1:0] data_in, // Perimeter I/O
- output [2*XSIZE + 2*YSIZE - 1:0] data_out // Perimeter I/O
+ input [YSIZE-1:0] data_in_east, // Perimeter input
+ input [YSIZE-1:0] data_in_west,
+ input [XSIZE-1:0] data_in_north,
+ input [XSIZE-1:0] data_in_south,
+ output [YSIZE-1:0] data_out_east, // Perimeter output
+ output [YSIZE-1:0] data_out_west,
+ output [XSIZE-1:0] data_out_north,
+ output [XSIZE-1:0] data_out_south
);
wire [XSIZE - 1: 0] uconn [YTOP: 0];
wire [XSIZE - 1: 0] dconn [YTOP: 0];
@@ -481,16 +888,21 @@
// some 2D arrays may need to be copied into 1D arrays.
// See the original verilog for examples.
- /* The perimeter inputs and outputs connect to the logic analyzer */
- /* (To do: multiplex inputs between the chip I/O and logic analyzer */
+ /* The perimeter inputs and outputs connect the array to the
+ * parent module. Note that this hides all the interior data,
+ * which could be an issue with understanding how the circuit
+ * works.
+ */
- assign data_out = {uconn[YTOP][XSIZE - 1:0], dconn[0][XSIZE - 1:0],
- rconn[XTOP][YSIZE - 1:0], lconn[0][YSIZE - 1:0]};
+ assign data_out_north = uconn[YTOP][XSIZE - 1:0];
+ assign data_out_south = dconn[0][XSIZE - 1:0];
+ assign data_out_east = rconn[XTOP][YSIZE - 1:0];
+ assign data_out_west = lconn[0][YSIZE - 1:0];
- assign dconn[YTOP][XSIZE - 1:0] = data_in[2*XSIZE+2*YSIZE - 1: 2*YSIZE + XSIZE];
- assign uconn[0][XSIZE - 1:0] = data_in[2*YSIZE + XSIZE - 1:2*YSIZE];
- assign rconn[0][YSIZE - 1:0] = data_in[2*YSIZE-1:YSIZE];
- assign lconn[XTOP][YSIZE - 1:0] = data_in[YSIZE-1:0];
+ assign dconn[YTOP][XSIZE - 1:0] = data_in_south;
+ assign uconn[0][XSIZE - 1:0] = data_in_north;
+ assign rconn[0][YSIZE - 1:0] = data_in_east;
+ assign lconn[XTOP][YSIZE - 1:0] = data_in_west;
genvar i, j;
diff --git a/verilog/rtl/chaos_automaton.v:Zone.Identifier b/verilog/rtl/chaos_automaton.v:Zone.Identifier
index cfea768..bb947fc 100644
--- a/verilog/rtl/chaos_automaton.v:Zone.Identifier
+++ b/verilog/rtl/chaos_automaton.v:Zone.Identifier
@@ -1,3 +1,3 @@
[ZoneTransfer]
ZoneId=3
-HostUrl=https://files.slack.com/files-pri/T0156RWKTRA-F03SKB0CMK5/download/chaos_automaton.v?origin_team=T0156RWKTRA
+HostUrl=https://files.slack.com/files-pri/T0156RWKTRA-F03SG99NPGE/download/chaos_automaton.v?origin_team=T0156RWKTRA