add wb_pio to project
This adds a simple wb_pio module to the project. It does not currently
pass placement.
Signed-off-by: Sean Cross <sean@xobs.io>
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..fa8fdda
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "verilog/rtl/fpga_pio"]
+ path = verilog/rtl/fpga_pio
+ url = https://github.com/lawrie/fpga_pio.git
diff --git a/README.md b/README.md
index 34b9a05..71d64d6 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,26 @@
-# Caravel User Project
+# PIO on GF180 (with Caravel)
[](https://opensource.org/licenses/Apache-2.0) [](https://github.com/efabless/caravel_project_example/actions/workflows/user_project_ci.yml) [](https://github.com/efabless/caravel_project_example/actions/workflows/caravel_build.yml)
-| :exclamation: Important Note |
-|-----------------------------------------|
-
-## Please fill in your project documentation in this README.md file
+A project designed to demonstrate Raspberry Pi PIO on GF180 using the Caravel harness.
Refer to [README](docs/source/index.rst#section-quickstart) for a quickstart of how to use caravel_user_project
Refer to [README](docs/source/index.rst) for this sample project documentation.
+
+## Building the Project
+
+You will need a Linux environment with Docker. Once you have that, you can set things up:
+
+```sh
+mkdir -p dependencies
+export OPENLANE_ROOT=$(pwd)/dependencies/openlane_src # you need to export this whenever you start a new shell
+export PDK_ROOT=$(pwd)/dependencies/pdks # you need to export this whenever you start a new shell
+export PDK=gf180mcuC
+```
+
+Next, do a one-time setup of the project.
+
+```sh
+make setup
+```
diff --git a/openlane/wb_pio/config.json b/openlane/wb_pio/config.json
new file mode 100644
index 0000000..2864ba8
--- /dev/null
+++ b/openlane/wb_pio/config.json
@@ -0,0 +1,47 @@
+{
+ "DESIGN_NAME": "wb_pio",
+ "DESIGN_IS_CORE": 0,
+ "VERILOG_FILES": ["dir::../../verilog/rtl/defines.v", "dir::../../verilog/rtl/wb_pio_top.v", "dir::../../verilog/rtl/fpga_pio/src/*.v"],
+ "CLOCK_PERIOD": 10,
+ "CLOCK_PORT": "wb_clk_i",
+ "CLOCK_NET": "counter.clk",
+ "FP_SIZING": "absolute",
+ "DIE_AREA": "0 0 900 600",
+ "FP_PIN_ORDER_CFG": "dir::pin_order.cfg",
+ "PL_BASIC_PLACEMENT": 1,
+ "PL_TARGET_DENSITY": 0.80,
+ "SYNTH_NO_FLAT": 0,
+ "VDD_NETS": ["vccd1"],
+ "GND_NETS": ["vssd1"],
+ "DIODE_INSERTION_STRATEGY": 4,
+ "RUN_CVC": 1,
+ "SYNTH_STRATEGY": "DELAY 4",
+ "pdk::sky130*": {
+ "FP_CORE_UTIL": 75,
+ "RT_MAX_LAYER": "met4",
+ "scl::sky130_fd_sc_hd": {
+ "CLOCK_PERIOD": 10
+ },
+ "scl::sky130_fd_sc_hdll": {
+ "CLOCK_PERIOD": 10
+ },
+ "scl::sky130_fd_sc_hs": {
+ "CLOCK_PERIOD": 8
+ },
+ "scl::sky130_fd_sc_ls": {
+ "CLOCK_PERIOD": 10,
+ "SYNTH_MAX_FANOUT": 5
+ },
+ "scl::sky130_fd_sc_ms": {
+ "CLOCK_PERIOD": 10
+ }
+ },
+ "pdk::gf180mcuC": {
+ "STD_CELL_LIBRARY": "gf180mcu_fd_sc_mcu7t5v0",
+ "CLOCK_PERIOD": 24.0,
+ "FP_CORE_UTIL": 80,
+ "RT_MAX_LAYER": "Metal4",
+ "SYNTH_MAX_FANOUT": 4,
+ "PL_TARGET_DENSITY": 0.85
+ }
+}
diff --git a/openlane/wb_pio/pin_order.cfg b/openlane/wb_pio/pin_order.cfg
new file mode 100644
index 0000000..2fda806
--- /dev/null
+++ b/openlane/wb_pio/pin_order.cfg
@@ -0,0 +1,10 @@
+#BUS_SORT
+
+#S
+wb_.*
+wbs_.*
+la_.*
+irq.*
+
+#N
+io_.*
diff --git a/verilog/rtl/fpga_pio b/verilog/rtl/fpga_pio
new file mode 160000
index 0000000..9ca929a
--- /dev/null
+++ b/verilog/rtl/fpga_pio
@@ -0,0 +1 @@
+Subproject commit 9ca929a930e46411fed482069a27c75905285b68
diff --git a/verilog/rtl/wb_pio_top.v b/verilog/rtl/wb_pio_top.v
new file mode 100644
index 0000000..ce5deb7
--- /dev/null
+++ b/verilog/rtl/wb_pio_top.v
@@ -0,0 +1,234 @@
+// SPDX-FileCopyrightText: 2020 Efabless Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// SPDX-License-Identifier: Apache-2.0
+
+`default_nettype none
+/*
+ *-------------------------------------------------------------
+ *
+ * user_proj_example
+ *
+ * This is an example of a (trivially simple) user project,
+ * showing how the user project can connect to the logic
+ * analyzer, the wishbone bus, and the I/O pads.
+ *
+ * This project generates an integer count, which is output
+ * on the user area GPIO pads (digital output only). The
+ * wishbone connection allows the project to be controlled
+ * (start and stop) from the management SoC program.
+ *
+ * See the testbenches in directory "mprj_counter" for the
+ * example programs that drive this user project. The three
+ * testbenches are "io_ports", "la_test1", and "la_test2".
+ *
+ *-------------------------------------------------------------
+ */
+
+module wb_pio #(
+ parameter BITS = 32
+)(
+`ifdef USE_POWER_PINS
+ inout vccd1, // User area 1 1.8V supply
+ inout vssd1, // User area 1 digital ground
+`endif
+
+ // Wishbone Slave ports (WB MI A)
+ input wb_clk_i,
+ input wb_rst_i,
+ input wbs_stb_i,
+ input wbs_cyc_i,
+ input wbs_we_i,
+ input [3:0] wbs_sel_i,
+ input [31:0] wbs_dat_i,
+ input [31:0] wbs_adr_i,
+ output wbs_ack_o,
+ output [31:0] wbs_dat_o,
+
+ // Logic Analyzer Signals
+ input [127:0] la_data_in,
+ output [127:0] la_data_out,
+ input [127:0] la_oenb,
+
+ // IOs
+ input [`MPRJ_IO_PADS-1:0] io_in,
+ output [`MPRJ_IO_PADS-1:0] io_out,
+ output [`MPRJ_IO_PADS-1:0] io_oeb,
+
+ // IRQ
+ output [2:0] irq
+);
+ wire clk;
+ wire rst;
+
+ wire [`MPRJ_IO_PADS-1:0] io_in;
+ wire [`MPRJ_IO_PADS-1:0] io_out;
+ wire [`MPRJ_IO_PADS-1:0] io_oeb;
+
+ wire [31:0] wdata;
+ wire [BITS-1:0] count;
+
+ wire valid;
+ wire [3:0] wstrb;
+ wire [31:0] la_write;
+
+ // WB MI A
+ assign valid = wbs_cyc_i && wbs_stb_i;
+ assign wstrb = wbs_sel_i & {4{wbs_we_i}};
+ assign wdata = wbs_dat_i;
+
+ // IO
+ assign io_out = count;
+ // assign io_oeb = {(`MPRJ_IO_PADS-1){rst}};
+
+ // IRQ
+ // assign irq = 3'b000; // Unused
+
+ // PIO registers and wires
+ reg [31:0] din; // Data sent to PIO
+ reg [4:0] index; // Instruction index
+ reg [1:0] mindex; // Machine index
+
+ reg [31:0] dout; // Output from PIO
+ wire [3:0] action; // Action to be done by PIO
+ wire irq0, irq1; // IRQ flags from PIO
+ wire [3:0] tx_full; // Set when TX fifo is full
+ wire [3:0] rx_empty; // Set when RX fifo is empty
+
+ // // LA
+ // assign la_data_out = {{(127-BITS){1'b0}}, count};
+ // // Assuming LA probes [63:32] are for controlling the count register
+ // assign la_write = ~la_oenb[63:32] & ~{BITS{valid}};
+ // // Assuming LA probes [65:64] are for controlling the count clk & reset
+ // assign clk = (~la_oenb[64]) ? la_data_in[64]: wb_clk_i;
+ // assign rst = (~la_oenb[65]) ? la_data_in[65]: wb_rst_i;
+
+ // counter #(
+ // .BITS(BITS)
+ // ) counter(
+ // .clk(clk),
+ // .reset(rst),
+ // .ready(wbs_ack_o),
+ // .valid(valid),
+ // .rdata(rdata),
+ // .wdata(wbs_dat_i),
+ // .wstrb(wstrb),
+ // .la_write(la_write),
+ // .la_input(la_data_in[63:32]),
+ // .count(count)
+ // );
+
+ assign irq[2] = 1'b0;
+
+ reg [3:0] actions[32];
+ reg [4:0] pc;
+ assign action = actions[pc];
+ // assign action = actions[0];
+ reg ack;
+ assign wbs_ack_o = ack;
+ assign wbs_dat_o = dout;
+
+ always @(posedge wb_clk_i) begin
+ if (wb_rst_i) begin
+ ack <= 1'b0;
+ pc <= 5'b00000;
+ end else begin
+ ack <= 1'b0;
+ pc <= pc + 1;
+ if (valid && !ack) begin
+ ack <= 1'b1;
+ if ((wbs_adr_i[3:0] == 0) && wbs_we_i) begin
+ if (wstrb[0]) din[7:0] <= wbs_dat_i[7:0];
+ if (wstrb[1]) din[15:8] <= wbs_dat_i[15:8];
+ if (wstrb[2]) din[23:16] <= wbs_dat_i[23:16];
+ if (wstrb[3]) din[31:24] <= wbs_dat_i[31:24];
+ end else if ((wbs_adr_i[3:0] == 4) && wbs_we_i) begin
+ if (wstrb[0]) mindex[1:0] <= wbs_dat_i[1:0];
+ end else if ((wbs_adr_i[3:0] == 8) && wbs_we_i) begin
+ if (wstrb[0]) index[4:0] <= wbs_dat_i[4:0];
+ end else if ((wbs_adr_i[3:0] == 12) && wbs_we_i) begin
+ if (wstrb[0]) actions[pc][3:0] <= wbs_dat_i[3:0];
+ // end else if ((wbs_adr_i[3:0] == 16) && !wbs_we_i) begin
+ // if (wstrb[0]) wbs_dat_o[7:0] <= dout[7:0];
+ // if (wstrb[1]) wbs_dat_o[15:8] <= dout[15:8];
+ // if (wstrb[2]) wbs_dat_o[23:16] <= dout[23:16];
+ // if (wstrb[3]) wbs_dat_o[31:24] <= dout[31:24];
+ end
+ end
+ end
+ end
+
+ // PIO instance 1
+ pio pio_1 (
+ .clk(wb_clk_i),
+ .reset(wb_rst_i),
+
+ .mindex(mindex),
+ .din(din),
+ .index(index),
+ .action(action),
+ .dout(dout),
+
+ .gpio_in(io_in),
+ .gpio_out(io_out),
+ .gpio_dir(io_oeb),
+ .irq0(irq[0]),
+ .irq1(irq[1]),
+
+ .tx_full(tx_full),
+ .rx_empty(rx_empty)
+ );
+endmodule
+
+// module counter #(
+// parameter BITS = 32
+// )(
+// input clk,
+// input reset,
+// input valid,
+// input [3:0] wstrb,
+// input [BITS-1:0] wdata,
+// input [BITS-1:0] la_write,
+// input [BITS-1:0] la_input,
+// output ready,
+// output [BITS-1:0] rdata,
+// output [BITS-1:0] count
+// );
+// reg ready;
+// reg [BITS-1:0] count;
+// reg [BITS-1:0] rdata;
+
+// always @(posedge clk) begin
+// if (reset) begin
+// count <= 0;
+// ready <= 0;
+// end else begin
+// ready <= 1'b0;
+// if (~|la_write) begin
+// count <= count + 1;
+// end
+// if (valid && !ready) begin
+// ready <= 1'b1;
+// rdata <= count;
+// if (wstrb[0]) count[7:0] <= wdata[7:0];
+// if (wstrb[1]) count[15:8] <= wdata[15:8];
+// if (wstrb[2]) count[23:16] <= wdata[23:16];
+// if (wstrb[3]) count[31:24] <= wdata[31:24];
+// end else if (|la_write) begin
+// count <= la_write & la_input;
+// end
+// end
+// end
+
+// endmodule
+`default_nettype wire