fpga: Add initial Verilog build Also applied Verilog auto-formatting with: verible-verilog-format --inplace fpga/*.v Change-Id: I3520775fbca49519d8e20d934a7503110a70ff3f Reviewed-on: https://pigweed-review.googlesource.com/c/gonk/+/185470 Pigweed-Auto-Submit: Anthony DiGirolamo <tonymd@google.com> Reviewed-by: Umang Shah <umangshah@google.com> Commit-Queue: Auto-Submit <auto-submit@pigweed-service-accounts.iam.gserviceaccount.com>
diff --git a/fpga/BUILD.gn b/fpga/BUILD.gn index 6958491..7210567 100644 --- a/fpga/BUILD.gn +++ b/fpga/BUILD.gn
@@ -17,4 +17,29 @@ import("//fpga/fpga_image.gni") group("fpga") { + deps = [ ":toplevel" ] +} + +# Build an FPGA bitstream. Outputs are placed in: +# +# out/gn/obj/fpga/toplevel/ +# toplevel.asc +# toplevel.bin +# toplevel.json +# toplevel_timing_report.json +# toplevel_timing_report.txt +# +fpga_image("toplevel") { + sources = [ + "gonk/csa_ctl_top.v", + "gonk/pll.v", + "gonk/rst_sync.v", + "gonk/sig_sync.v", + "gonk/spi_m_core.v", + "gonk/spi_m_core_ctl.v", + "gonk/spi_s_core.v", + "gonk/top.v", + ] + + pcf = "gonk/top.pcf" }
diff --git a/fpga/gonk/csa_ctl_top.v b/fpga/gonk/csa_ctl_top.v new file mode 100644 index 0000000..81ce617 --- /dev/null +++ b/fpga/gonk/csa_ctl_top.v
@@ -0,0 +1,746 @@ +// Copyright 2023 The Pigweed Authors +// +// 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 +// +// https://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. + +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// +////////////////////////////////////////////////////////////////////////////////// + + +module csa_ctl_top ( + input mclk_i, + input rst_i, + input r_w_en_i, + input en_i, + input mode_i, + input [10:0] adc_sel_i, + input [5:0] rwaddr_i, + input [15:0] wdata_i, + output reg dn_o, + output reg [39:0] rdata_o, + // spi interfaces + input miso_i_1, + input alertl_i_1, + output sclk_o_1, + output mosi_o_1, + output cs_o_1, + // + input miso_i_2, + input alertl_i_2, + output sclk_o_2, + output mosi_o_2, + output cs_o_2, + // spi interface + input miso_i_3, + input alertl_i_3, + output sclk_o_3, + output mosi_o_3, + output cs_o_3, + // + input miso_i_4, + input alertl_i_4, + output sclk_o_4, + output mosi_o_4, + output cs_o_4, + // + input miso_i_5, + input alertl_i_5, + output sclk_o_5, + output mosi_o_5, + output cs_o_5, + // + input miso_i_6, + input alertl_i_6, + output sclk_o_6, + output mosi_o_6, + output cs_o_6, + // + input miso_i_7, + input alertl_i_7, + output sclk_o_7, + output mosi_o_7, + output cs_o_7, + // + input miso_i_8, + input alertl_i_8, + output sclk_o_8, + output mosi_o_8, + output cs_o_8, + // + input miso_i_9, + input alertl_i_9, + output sclk_o_9, + output mosi_o_9, + output cs_o_9, + // + input miso_i_10, + input alertl_i_10, + output sclk_o_10, + output mosi_o_10, + output cs_o_10, + // + input miso_i_11, + input alertl_i_11, + output sclk_o_11, + output mosi_o_11, + output cs_o_11, + // + input dn_clr_i, + output reg poll_dn_o, + // output [11:0] poll_dn, + output [23:0] vbus_1, + output [23:0] vshunt_1, + output [23:0] vbus_2, + output [23:0] vshunt_2, + output [23:0] vbus_3, + output [23:0] vshunt_3, + output [23:0] vbus_4, + output [23:0] vshunt_4, + output [23:0] vbus_5, + output [23:0] vshunt_5, + output [23:0] vbus_6, + output [23:0] vshunt_6, + output [23:0] vbus_7, + output [23:0] vshunt_7, + output [23:0] vbus_8, + output [23:0] vshunt_8, + output [23:0] vbus_9, + output [23:0] vshunt_9, + output [23:0] vbus_10, + output [23:0] vshunt_10, + output [23:0] vbus_11, + output [23:0] vshunt_11 + // +); + // + reg + dn_latch_r1, + dn_latch_r2, + dn_latch_r3, + dn_latch_r4, + dn_latch_r5, + dn_latch_r6, + dn_latch_r7, + dn_latch_r8, + dn_latch_r9, + dn_latch_r10, + dn_latch_r11, + rst_i_r; + reg + poll_dn_latch_r1, + poll_dn_latch_r2, + poll_dn_latch_r3, + poll_dn_latch_r4, + poll_dn_latch_r5, + poll_dn_latch_r6, + poll_dn_latch_r7, + poll_dn_latch_r8, + poll_dn_latch_r9, + poll_dn_latch_r10, + poll_dn_latch_r11; + reg en_r1, en_r2, en_r3, en_r4, en_r5, en_r6, en_r7, en_r8, en_r9, en_r10, en_r11; + reg dn_r, poll_dn_r; + reg + r_w_en_r1, + r_w_en_r2, + r_w_en_r3, + r_w_en_r4, + r_w_en_r5, + r_w_en_r6, + r_w_en_r7, + r_w_en_r8, + r_w_en_r9, + r_w_en_r10, + r_w_en_r11; + reg en_r, r_w_en_r; + reg [ 5:0] rwaddr_r; + reg [10:0] adc_sel_r; + reg [15:0] wdata_r; + // + wire poll_dn_r1,poll_dn_r2,poll_dn_r3,poll_dn_r4,poll_dn_r5,poll_dn_r6,poll_dn_r7,poll_dn_r8,poll_dn_r9,poll_dn_r10,poll_dn_r11; + wire dn_r1, dn_r2, dn_r3, dn_r4, dn_r5, dn_r6, dn_r7, dn_r8, dn_r9, dn_r10, dn_r11; + wire [39:0] rdata_w1,rdata_w2,rdata_w3,rdata_w4,rdata_w5,rdata_w6,rdata_w7,rdata_w8,rdata_w9,rdata_w10,rdata_w11; + // + + always @(posedge mclk_i) begin + rst_i_r <= rst_i; + end + + spi_m_core_ctl csa_1 ( + .mclk_i(mclk_i), + .rst_i(rst_i_r), + .r_w_en_i(r_w_en_r1), + .en_i(en_r1), + .mode_i(mode_i), + .rwaddr_i(rwaddr_r), + .wdata_i(wdata_r), + .dn_o(dn_r1), + .rdata_o(rdata_w1), + .vbus_o(vbus_1), + .vshunt_o(vshunt_1), + .poll_dn_o(poll_dn_r1), + .miso_i(miso_i_1), + .alert_n_i(alertl_i_1), + .sclk_o(sclk_o_1), + .mosi_o(mosi_o_1), + .cs_o(cs_o_1) + ); + + spi_m_core_ctl csa_2 ( + .mclk_i(mclk_i), + .rst_i(rst_i_r), + .r_w_en_i(r_w_en_r2), + .en_i(en_r2), + .mode_i(mode_i), + .rwaddr_i(rwaddr_r), + .wdata_i(wdata_r), + .dn_o(dn_r2), + .rdata_o(rdata_w2), + .vbus_o(vbus_2), + .vshunt_o(vshunt_2), + .poll_dn_o(poll_dn_r2), + .miso_i(miso_i_2), + .alert_n_i(alertl_i_2), + .sclk_o(sclk_o_2), + .mosi_o(mosi_o_2), + .cs_o(cs_o_2) + ); + + spi_m_core_ctl csa_3 ( + .mclk_i(mclk_i), + .rst_i(rst_i_r), + .r_w_en_i(r_w_en_r3), + .en_i(en_r3), + .mode_i(mode_i), + .rwaddr_i(rwaddr_r), + .wdata_i(wdata_r), + .dn_o(dn_r3), + .rdata_o(rdata_w3), + .vbus_o(vbus_3), + .vshunt_o(vshunt_3), + .poll_dn_o(poll_dn_r3), + .miso_i(miso_i_3), + .alert_n_i(alertl_i_3), + .sclk_o(sclk_o_3), + .mosi_o(mosi_o_3), + .cs_o(cs_o_3) + ); + + spi_m_core_ctl csa_4 ( + .mclk_i(mclk_i), + .rst_i(rst_i_r), + .r_w_en_i(r_w_en_r4), + .en_i(en_r4), + .mode_i(mode_i), + .rwaddr_i(rwaddr_r), + .wdata_i(wdata_r), + .dn_o(dn_r4), + .rdata_o(rdata_w4), + .vbus_o(vbus_4), + .vshunt_o(vshunt_4), + .poll_dn_o(poll_dn_r4), + .miso_i(miso_i_4), + .alert_n_i(alertl_i_4), + .sclk_o(sclk_o_4), + .mosi_o(mosi_o_4), + .cs_o(cs_o_4) + ); + + spi_m_core_ctl csa_5 ( + .mclk_i(mclk_i), + .rst_i(rst_i_r), + .r_w_en_i(r_w_en_r5), + .en_i(en_r5), + .mode_i(mode_i), + .rwaddr_i(rwaddr_r), + .wdata_i(wdata_r), + .dn_o(dn_r5), + .rdata_o(rdata_w5), + .vbus_o(vbus_5), + .vshunt_o(vshunt_5), + .poll_dn_o(poll_dn_r5), + .miso_i(miso_i_5), + .alert_n_i(alertl_i_5), + .sclk_o(sclk_o_5), + .mosi_o(mosi_o_5), + .cs_o(cs_o_5) + ); + + + spi_m_core_ctl csa_6 ( + .mclk_i(mclk_i), + .rst_i(rst_i_r), + .r_w_en_i(r_w_en_r6), + .en_i(en_r6), + .mode_i(mode_i), + .rwaddr_i(rwaddr_r), + .wdata_i(wdata_r), + .dn_o(dn_r6), + .rdata_o(rdata_w6), + .vbus_o(vbus_6), + .vshunt_o(vshunt_6), + .poll_dn_o(poll_dn_r6), + .miso_i(miso_i_6), + .alert_n_i(alertl_i_6), + .sclk_o(sclk_o_6), + .mosi_o(mosi_o_6), + .cs_o(cs_o_6) + ); + + spi_m_core_ctl csa_7 ( + .mclk_i(mclk_i), + .rst_i(rst_i_r), + .r_w_en_i(r_w_en_r7), + .en_i(en_r7), + .mode_i(mode_i), + .rwaddr_i(rwaddr_r), + .wdata_i(wdata_r), + .dn_o(dn_r7), + .rdata_o(rdata_w7), + .vbus_o(vbus_7), + .vshunt_o(vshunt_7), + .poll_dn_o(poll_dn_r7), + .miso_i(miso_i_7), + .alert_n_i(alertl_i_7), + .sclk_o(sclk_o_7), + .mosi_o(mosi_o_7), + .cs_o(cs_o_7) + ); + + spi_m_core_ctl csa_8 ( + .mclk_i(mclk_i), + .rst_i(rst_i_r), + .r_w_en_i(r_w_en_r8), + .en_i(en_r8), + .mode_i(mode_i), + .rwaddr_i(rwaddr_r), + .wdata_i(wdata_r), + .dn_o(dn_r8), + .rdata_o(rdata_w8), + .vbus_o(vbus_8), + .vshunt_o(vshunt_8), + .poll_dn_o(poll_dn_r8), + .miso_i(miso_i_8), + .alert_n_i(alertl_i_8), + .sclk_o(sclk_o_8), + .mosi_o(mosi_o_8), + .cs_o(cs_o_8) + ); + + spi_m_core_ctl csa_9 ( + .mclk_i(mclk_i), + .rst_i(rst_i_r), + .r_w_en_i(r_w_en_r9), + .en_i(en_r9), + .mode_i(mode_i), + .rwaddr_i(rwaddr_r), + .wdata_i(wdata_r), + .dn_o(dn_r9), + .rdata_o(rdata_w9), + .vbus_o(vbus_9), + .vshunt_o(vshunt_9), + .poll_dn_o(poll_dn_r9), + .miso_i(miso_i_9), + .alert_n_i(alertl_i_9), + .sclk_o(sclk_o_9), + .mosi_o(mosi_o_9), + .cs_o(cs_o_9) + ); + + spi_m_core_ctl csa_10 ( + .mclk_i(mclk_i), + .rst_i(rst_i_r), + .r_w_en_i(r_w_en_r10), + .en_i(en_r10), + .mode_i(mode_i), + .rwaddr_i(rwaddr_r), + .wdata_i(wdata_r), + .dn_o(dn_r10), + .rdata_o(rdata_w10), + .vbus_o(vbus_10), + .vshunt_o(vshunt_10), + .poll_dn_o(poll_dn_r10), + .miso_i(miso_i_10), + .alert_n_i(alertl_i_10), + .sclk_o(sclk_o_10), + .mosi_o(mosi_o_10), + .cs_o(cs_o_10) + ); + + spi_m_core_ctl csa_11 ( + .mclk_i(mclk_i), + .rst_i(rst_i_r), + .r_w_en_i(r_w_en_r11), + .en_i(en_r11), + .mode_i(mode_i), + .rwaddr_i(rwaddr_r), + .wdata_i(wdata_r), + .dn_o(dn_r11), + .rdata_o(rdata_w11), + .vbus_o(vbus_11), + .vshunt_o(vshunt_11), + .poll_dn_o(poll_dn_r11), + .miso_i(miso_i_11), + .alert_n_i(alertl_i_11), + .sclk_o(sclk_o_11), + .mosi_o(mosi_o_11), + .cs_o(cs_o_11) + ); + + always @(posedge mclk_i) begin + if (rst_i_r) begin + poll_dn_o <= 0; + dn_o <= 0; + en_r <= 0; + end else begin + poll_dn_o <= poll_dn_r; + dn_o <= dn_r; + en_r <= en_i; //(en_i & !mode_i) ; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r) begin + wdata_r <= 0; + rwaddr_r <= 0; + r_w_en_r <= 0; + end else begin + if (en_i) begin + wdata_r <= wdata_i; + rwaddr_r <= rwaddr_i[5:0]; + r_w_en_r <= r_w_en_i; + adc_sel_r <= adc_sel_i; + end + end + end + + always @(posedge mclk_i) begin + if (r_w_en_r) begin + r_w_en_r1 <= 1; + r_w_en_r2 <= 1; + r_w_en_r3 <= 1; + r_w_en_r4 <= 1; + r_w_en_r5 <= 1; + r_w_en_r6 <= 1; + r_w_en_r7 <= 1; + r_w_en_r8 <= 1; + r_w_en_r9 <= 1; + r_w_en_r10 <= 1; + r_w_en_r11 <= 1; + end else begin + r_w_en_r1 <= 0; + r_w_en_r2 <= 0; + r_w_en_r3 <= 0; + r_w_en_r4 <= 0; + r_w_en_r5 <= 0; + r_w_en_r6 <= 0; + r_w_en_r7 <= 0; + r_w_en_r8 <= 0; + r_w_en_r9 <= 0; + r_w_en_r10 <= 0; + r_w_en_r11 <= 0; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r) begin + en_r1 <= 0; + en_r2 <= 0; + en_r3 <= 0; + en_r4 <= 0; + en_r5 <= 0; + en_r6 <= 0; + en_r7 <= 0; + en_r8 <= 0; + en_r9 <= 0; + en_r10 <= 0; + en_r11 <= 0; + end else begin + if (en_r) begin + en_r1 <= adc_sel_r[0]; + en_r2 <= adc_sel_r[1]; + en_r3 <= adc_sel_r[2]; + en_r4 <= adc_sel_r[3]; + en_r5 <= adc_sel_r[4]; + en_r6 <= adc_sel_r[5]; + en_r7 <= adc_sel_r[6]; + en_r8 <= adc_sel_r[7]; + en_r9 <= adc_sel_r[8]; + en_r10 <= adc_sel_r[9]; + en_r11 <= adc_sel_r[10]; + end else begin + en_r1 <= 0; + en_r2 <= 0; + en_r3 <= 0; + en_r4 <= 0; + en_r5 <= 0; + en_r6 <= 0; + en_r7 <= 0; + en_r8 <= 0; + en_r9 <= 0; + en_r10 <= 0; + en_r11 <= 0; + end + end + end + + always @(posedge mclk_i) begin + // priority. + if (adc_sel_r < 64) begin + if (adc_sel_r[0]) rdata_o <= rdata_w1; + else if (adc_sel_r[1]) rdata_o <= rdata_w2; + else if (adc_sel_r[2]) rdata_o <= rdata_w3; + else if (adc_sel_r[3]) rdata_o <= rdata_w4; + else if (adc_sel_r[4]) rdata_o <= rdata_w5; + else if (adc_sel_r[5]) rdata_o <= rdata_w6; + end else begin + if (adc_sel_r[6]) rdata_o <= rdata_w7; + else if (adc_sel_r[7]) rdata_o <= rdata_w8; + else if (adc_sel_r[8]) rdata_o <= rdata_w9; + else if (adc_sel_r[9]) rdata_o <= rdata_w10; + else if (adc_sel_r[10]) rdata_o <= rdata_w11; + else rdata_o <= 0; + end + end + + reg dn_latch_0_r, dn_latch_1_r, dn_latch_2_r, dn_latch_3_r; + wire dn_latch_0, dn_latch_1, dn_latch_2, dn_latch_3, dn_w; + + // Change to AND to sync after bring-up + assign dn_latch_0 = (dn_latch_r7 | dn_latch_r9 | dn_latch_r10); // bank0 + assign dn_latch_1 = (dn_latch_r5 | dn_latch_r8 | dn_latch_r1); + assign dn_latch_2 = (dn_latch_r4 | dn_latch_r6 | dn_latch_r3); + assign dn_latch_3 = (dn_latch_r2 | dn_latch_r11); + assign dn_w = (dn_latch_0_r | dn_latch_1_r | dn_latch_2_r | dn_latch_3_r); + + always @(posedge mclk_i) begin + if (rst_i_r) begin + dn_r <= 0; + dn_latch_0_r <= 0; + dn_latch_1_r <= 0; + dn_latch_2_r <= 0; + dn_latch_3_r <= 0; + end else begin + dn_latch_0_r <= dn_latch_0; + dn_latch_1_r <= dn_latch_1; + dn_latch_2_r <= dn_latch_2; + dn_latch_3_r <= dn_latch_3; + dn_r <= dn_w; + end + end + + /// + + reg poll_dn_latch_0_r, poll_dn_latch_1_r, poll_dn_latch_2_r, poll_dn_latch_3_r; + wire poll_dn_latch_0, poll_dn_latch_1, poll_dn_latch_2, poll_dn_latch_3, poll_dn_w; + + assign poll_dn_latch_0 = (poll_dn_latch_r7 | poll_dn_latch_r9 | poll_dn_latch_r10); // bank0 + assign poll_dn_latch_1 = (poll_dn_latch_r5 | poll_dn_latch_r8 | poll_dn_latch_r1); + assign poll_dn_latch_2 = (poll_dn_latch_r4 | poll_dn_latch_r6 | poll_dn_latch_r3); + assign poll_dn_latch_3 = (poll_dn_latch_r2 | poll_dn_latch_r11); + assign poll_dn_w = (poll_dn_latch_0_r | poll_dn_latch_1_r | poll_dn_latch_2_r | poll_dn_latch_3_r); + + always @(posedge mclk_i) begin + if (rst_i_r) begin + poll_dn_r <= 0; + poll_dn_latch_0_r <= 0; + poll_dn_latch_1_r <= 0; + poll_dn_latch_2_r <= 0; + poll_dn_latch_3_r <= 0; + end else begin + poll_dn_latch_0_r <= poll_dn_latch_0; + poll_dn_latch_1_r <= poll_dn_latch_1; + poll_dn_latch_2_r <= poll_dn_latch_2; + poll_dn_latch_3_r <= poll_dn_latch_3; + poll_dn_r <= poll_dn_w; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r | dn_clr_i) begin + dn_latch_r1 <= 0; + end else begin + if (dn_r1) dn_latch_r1 <= 1; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r | dn_clr_i) begin + dn_latch_r2 <= 0; + end else begin + if (dn_r2) dn_latch_r2 <= 1; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r | dn_clr_i) begin + dn_latch_r3 <= 0; + end else begin + if (dn_r3) dn_latch_r3 <= 1; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r | dn_clr_i) begin + dn_latch_r4 <= 0; + end else begin + if (dn_r4) dn_latch_r4 <= 1; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r | dn_clr_i) begin + dn_latch_r5 <= 0; + end else begin + if (dn_r5) dn_latch_r5 <= 1; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r | dn_clr_i) begin + dn_latch_r6 <= 0; + end else begin + if (dn_r6) dn_latch_r6 <= 1; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r | dn_clr_i) begin + dn_latch_r7 <= 0; + end else begin + if (dn_r7) dn_latch_r7 <= 1; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r | dn_clr_i) begin + dn_latch_r8 <= 0; + end else begin + if (dn_r8) dn_latch_r8 <= 1; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r | dn_clr_i) begin + dn_latch_r9 <= 0; + end else begin + if (dn_r9) dn_latch_r9 <= 1; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r | dn_clr_i) begin + dn_latch_r10 <= 0; + end else begin + if (dn_r10) dn_latch_r10 <= 1; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r | dn_clr_i) begin + dn_latch_r11 <= 0; + end else begin + if (dn_r11) dn_latch_r11 <= 1; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r | dn_clr_i) begin + poll_dn_latch_r1 <= 0; + end else begin + if (poll_dn_r1) poll_dn_latch_r1 <= 1; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r | dn_clr_i) begin + poll_dn_latch_r2 <= 0; + end else begin + if (poll_dn_r2) poll_dn_latch_r2 <= 1; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r | dn_clr_i) begin + poll_dn_latch_r3 <= 0; + end else begin + if (poll_dn_r3) poll_dn_latch_r3 <= 1; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r | dn_clr_i) begin + poll_dn_latch_r4 <= 0; + end else begin + if (poll_dn_r4) poll_dn_latch_r4 <= 1; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r | dn_clr_i) begin + poll_dn_latch_r5 <= 0; + end else begin + if (poll_dn_r5) poll_dn_latch_r5 <= 1; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r | dn_clr_i) begin + poll_dn_latch_r6 <= 0; + end else begin + if (poll_dn_r6) poll_dn_latch_r6 <= 1; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r | dn_clr_i) begin + poll_dn_latch_r7 <= 0; + end else begin + if (poll_dn_r7) poll_dn_latch_r7 <= 1; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r | dn_clr_i) begin + poll_dn_latch_r8 <= 0; + end else begin + if (poll_dn_r8) poll_dn_latch_r8 <= 1; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r | dn_clr_i) begin + poll_dn_latch_r9 <= 0; + end else begin + if (poll_dn_r9) poll_dn_latch_r9 <= 1; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r | dn_clr_i) begin + poll_dn_latch_r10 <= 0; + end else begin + if (poll_dn_r10) poll_dn_latch_r10 <= 1; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r | dn_clr_i) begin + poll_dn_latch_r11 <= 0; + end else begin + if (poll_dn_r11) poll_dn_latch_r11 <= 1; + end + end + +endmodule
diff --git a/fpga/gonk/pll.v b/fpga/gonk/pll.v new file mode 100644 index 0000000..0196621 --- /dev/null +++ b/fpga/gonk/pll.v
@@ -0,0 +1,41 @@ +// Copyright 2023 The Pigweed Authors +// +// 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 +// +// https://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. + +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// +////////////////////////////////////////////////////////////////////////////////// + + +module pll ( + input clock_in, + output clock_out + // output locked +); + // assign clock_out=clock_in; + SB_PLL40_CORE #( + .FEEDBACK_PATH("SIMPLE"), + .PLLOUT_SELECT("GENCLK"), + .DIVR(4'b0000), + .DIVF(7'b0010111), + .DIVQ(3'b011), + .FILTER_RANGE(3'b001) + ) uut ( + .RESETB(1'b1), + .BYPASS(1'b0), + .REFERENCECLK(clock_in), + .PLLOUTCORE(clock_out) + ); + +endmodule
diff --git a/fpga/gonk/rst_sync.v b/fpga/gonk/rst_sync.v new file mode 100644 index 0000000..f2fe98d --- /dev/null +++ b/fpga/gonk/rst_sync.v
@@ -0,0 +1,66 @@ +// Copyright 2023 The Pigweed Authors +// +// 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 +// +// https://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. + +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// +// +////////////////////////////////////////////////////////////////////////////////// + + +module rst_sync ( + input clk_i, + input rst_i, + output rst_o +); + + reg rst_i_r0, rst_i_r1, rst_i_r2; + assign rst_o = rst_i_r2; + + reg [2:0] rst_state; + reg [3:0] count; + + always @(posedge clk_i) begin + case (rst_state) + 0: begin + rst_i_r0 <= 1; + rst_state <= 1; + count <= 0; + end + 1: begin + rst_i_r0 <= 1; + count <= count + 1; + if (count >= 4'd9) rst_state <= 2; + end + 2: begin + rst_i_r0 <= 0; + count <= 0; + end + default: rst_state <= 0; + endcase + end + + always @(posedge clk_i or posedge rst_i) begin + if (rst_i) begin + // rst_i_r0<=1; + rst_i_r1 <= 1; + rst_i_r2 <= 1; + end else begin + // rst_i_r0<=rst_i; + rst_i_r1 <= rst_i_r0; + rst_i_r2 <= rst_i_r1; + end + end + +endmodule
diff --git a/fpga/gonk/sig_sync.v b/fpga/gonk/sig_sync.v new file mode 100644 index 0000000..6946427 --- /dev/null +++ b/fpga/gonk/sig_sync.v
@@ -0,0 +1,45 @@ +// Copyright 2023 The Pigweed Authors +// +// 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 +// +// https://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. + +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// +// +////////////////////////////////////////////////////////////////////////////////// + + +module sig_sync ( + input clk_i, + input rst_i, + input sig_i, + output sig_o +); + + reg sig_i_r0, sig_i_r1, sig_i_r2; + assign sig_o = sig_i_r2; + + always @(posedge clk_i) begin + if (rst_i) begin + sig_i_r0 <= 0; + sig_i_r1 <= 0; + sig_i_r2 <= 0; + end else begin + sig_i_r0 <= sig_i; + sig_i_r1 <= sig_i_r0; + sig_i_r2 <= sig_i_r1; + + end + end + +endmodule
diff --git a/fpga/gonk/spi_m_core.v b/fpga/gonk/spi_m_core.v new file mode 100644 index 0000000..c3f37c2 --- /dev/null +++ b/fpga/gonk/spi_m_core.v
@@ -0,0 +1,296 @@ +// Copyright 2023 The Pigweed Authors +// +// 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 +// +// https://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. + +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// SPI for INA229 +// Refer Spec: https://www.ti.com/lit/ds/symlink/ina229.pdf?ts=1692387535714&ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FINA229 +////////////////////////////////////////////////////////////////////////////////// + +module spi_m_core #( + parameter SCK_DIVISOR = 10, + parameter MCLK_CYCLE_TIME = 10 +) ( + input mclk_i, + input rst_i, + input r_w_en_i, + input en_i, + input [5:0] rwaddr_i, + input [15:0] wdata_i, + output reg dn_o, + output reg [39:0] rdata_o, + // spi interface + input miso_i, + output reg sclk_o, + output reg mosi_o, + output reg cs_o +); + + + reg + miso_r0, + miso_r1, + miso_r2, + rising_edge_det, + falling_edge_det, + rising_edge_det_r0, + rising_edge_det_r1, + rising_edge_det_r2, + en_r, + sck_div_ctr_clr, + sclk_clr; + reg + wr_done_r, + rd_en_r, + rd_done_r, + dat_out_ctr_en_r, + r_w_en_r, + falling_edge_det_r2, + falling_edge_det_r1, + falling_edge_det_r0, + wait_ctr_en_r, + spi_en_r, + dn_r, + wait_dn_r; + reg [3:0] sck_div_ctr_r, wait_ctr_r; + reg [2:0] spi_m_state; + reg [5:0] rwaddr_latch_r; + reg [6:0] rwaddr_r, max_bit_count_r, dat_out_ctr_r, dat_in_ctr; + reg [15:0] wdata_r; + reg [23:0] dat_out_r; + reg [39:0] dat_in_r; + + localparam IDLE = 0; // Power On State + localparam EN = 1; // Transfer Enabled. Waiting for Transfer Done. + localparam DN = 2; // Transfer Done State. Drive dn_o high. + localparam WAIT = 3; // State to Add the min. wait time required b/w CS assertion/de-assertion and CLK Enable/Disable. + + localparam CLK_DIV = SCK_DIVISOR - 1; // Clock Divisor wrt 100MHz mclk. + localparam CLK_DIV_2 = CLK_DIV >> 1; // CLK_DIV/2 + localparam t_SCLK_CS_WAIT = 0; // # no. of mclk cycle wait for t_SCLK_CS + + // SPI State Machine. Mealy, 3 States. Control Signals = en_r, dn_r. + + always @(posedge mclk_i) begin + if (rst_i) spi_m_state <= IDLE; + else begin + case (spi_m_state) + IDLE: begin + if (en_r) spi_m_state <= EN; + else spi_m_state <= IDLE; + end + EN: begin + if (dn_r) spi_m_state <= DN; + else spi_m_state <= EN; + end + DN: begin + // if (dn_r) + // spi_m_state<=DN; + // else + spi_m_state <= IDLE; + end + default: begin + spi_m_state <= IDLE; + end + endcase + end + end + + // State Machine O/Ps. + + always @(posedge mclk_i) begin + if (rst_i) begin + cs_o <= 1; + dat_out_ctr_en_r <= 0; + spi_en_r <= 0; + wait_ctr_en_r <= 0; + dn_o <= 0; + end else begin + case (spi_m_state) + IDLE: begin + spi_en_r <= 0; + dat_out_ctr_en_r <= 0; + wait_ctr_en_r <= 0; + dn_o <= 0; + if (en_r) cs_o <= 0; + else cs_o <= 1; + end + EN: begin + cs_o <= 0; + wait_ctr_en_r <= 0; + dn_o <= 0; + if (dn_r) begin + spi_en_r <= 0; + dat_out_ctr_en_r <= 0; + end else begin + dat_out_ctr_en_r <= 1; + spi_en_r <= 1; + end + end + DN: begin + cs_o <= 0; + dat_out_ctr_en_r <= 0; + spi_en_r <= 0; + wait_ctr_en_r <= 0; + dn_o <= 1; + end + endcase + end + end + + // SCK Logic begin + always @(posedge mclk_i) begin + if (spi_en_r) begin + if (sck_div_ctr_clr) sck_div_ctr_r <= 0; + else sck_div_ctr_r <= sck_div_ctr_r + 1; + end else sck_div_ctr_r <= 0; + end + + always @(posedge mclk_i) begin + if (rst_i) begin + sclk_o <= 0; + end else begin + sclk_o <= (spi_en_r && (sck_div_ctr_r > CLK_DIV_2)); // default state = 0 + end + end + // SCK Logic End + + + // Data Transmit and Receive Logic Begin + // Pulses to sync transmit and capture with respective clock edges. + always @(posedge mclk_i) begin + rising_edge_det <= (sck_div_ctr_r == CLK_DIV_2); + falling_edge_det <= (sck_div_ctr_r == CLK_DIV); + end + + always @(posedge mclk_i) begin + if (dat_out_ctr_en_r) begin + if (falling_edge_det) dat_out_ctr_r <= dat_out_ctr_r + 1; + end else dat_out_ctr_r <= 0; + end + + always @(posedge mclk_i) begin + if (rst_i) en_r <= 0; + else begin + if (dn_r) en_r <= 0; + else if (en_i) en_r <= 1; + end + end + + always @(posedge mclk_i) begin + if (rst_i) begin + rwaddr_r <= 0; + rwaddr_latch_r <= 0; + wdata_r <= 0; + r_w_en_r <= 0; + dat_out_r <= 0; + end else begin + if (en_i) begin + dat_out_r <= {rwaddr_i, 1'b0, r_w_en_i, wdata_i}; + rwaddr_r <= {rwaddr_i, 1'b0}; + rwaddr_latch_r <= rwaddr_i; + wdata_r <= wdata_i; + r_w_en_r <= r_w_en_i; + end + end + end + + always @(posedge mclk_i) begin + if (r_w_en_r) begin + if (rwaddr_latch_r== 6'd4 || rwaddr_latch_r== 6'd5 || rwaddr_latch_r== 6'd7 || rwaddr_latch_r== 6'd8) + max_bit_count_r <= 24; + else if (rwaddr_latch_r == 6'd9 || rwaddr_latch_r == 6'd10) max_bit_count_r <= 40; + else max_bit_count_r <= 16; + end else begin + max_bit_count_r <= 16; + end + end + + always @(posedge mclk_i) begin + wr_done_r<=((!r_w_en_r) & (dat_out_ctr_r==24));// && falling_edge_det_r1); // added sync with falling_edge_det_r2 + rd_en_r <= ((dat_out_ctr_r > 8) && r_w_en_r); // changed from (dat_out_ctr_r>=8) + rd_done_r <= (dat_in_ctr == (max_bit_count_r - 1)); + wait_dn_r <= (wait_ctr_r == t_SCLK_CS_WAIT); + sck_div_ctr_clr <= (sck_div_ctr_r == (CLK_DIV - 1)); + end + + always @(posedge mclk_i) begin + if (rst_i) begin + mosi_o <= 1; + end else begin + if (spi_en_r) begin + if (rising_edge_det) begin + if (rd_en_r) mosi_o <= 0; + else mosi_o <= dat_out_r[23-dat_out_ctr_r]; + end + end else + mosi_o <= 1; // if (cs_o) mosi_o<=1; // change-might create a crit path b/w cs_o and mosi + end + end + + always @(posedge mclk_i) begin + if (rd_en_r) begin + if (falling_edge_det_r0) begin + dat_in_ctr <= dat_in_ctr + 1; + end + end else begin + dat_in_ctr <= 0; + end + end + + always @(posedge mclk_i) begin + if (rd_en_r) begin + if (falling_edge_det_r1) begin + dat_in_r <= {dat_in_r, miso_r1}; + end + end else begin + dat_in_r <= 0; + end + end + + always @(posedge mclk_i) begin + if (rst_i) // Rst not required. + rdata_o <= 0; + else if (rd_done_r & rising_edge_det) rdata_o <= dat_in_r; + end + + always @(posedge mclk_i) begin + if (wait_ctr_en_r) wait_ctr_r <= wait_ctr_r + 1; + else wait_ctr_r <= 0; + end + + + // Using shift reg. pattern. Unsure of ASYNC_REG placement on icestorm. + always @(posedge mclk_i) begin + if (rst_i) begin + {miso_r0, miso_r1, miso_r2} <= 0; + {rising_edge_det_r0, rising_edge_det_r1, rising_edge_det_r2} <= 0; + {falling_edge_det_r0, falling_edge_det_r1, falling_edge_det_r2} <= 0; + end else begin + {miso_r2, miso_r1, miso_r0} <= {miso_r1, miso_r0, miso_i}; + {rising_edge_det_r2, rising_edge_det_r1, rising_edge_det_r0} <= { + rising_edge_det_r1, rising_edge_det_r0, rising_edge_det + }; + {falling_edge_det_r2, falling_edge_det_r1, falling_edge_det_r0} <= { + falling_edge_det_r1, falling_edge_det_r0, falling_edge_det + }; + end + end + + always @(posedge mclk_i) begin + dn_r <= (wr_done_r | (rd_done_r)); + end + + // Data Transmit and Receive Logic End +endmodule
diff --git a/fpga/gonk/spi_m_core_ctl.v b/fpga/gonk/spi_m_core_ctl.v new file mode 100644 index 0000000..e1b0377 --- /dev/null +++ b/fpga/gonk/spi_m_core_ctl.v
@@ -0,0 +1,228 @@ +// Copyright 2023 The Pigweed Authors +// +// 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 +// +// https://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. + +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// SPI m Controller +// +////////////////////////////////////////////////////////////////////////////////// + + + +module spi_m_core_ctl ( + input mclk_i, + input rst_i, + input r_w_en_i, + input en_i, + input mode_i, + input [5:0] rwaddr_i, + input [15:0] wdata_i, + output reg dn_o, + output reg poll_dn_o, + output reg [39:0] rdata_o, + output reg [23:0] vbus_o, + output reg [23:0] vshunt_o, + // spi interface + input miso_i, + input alert_n_i, + output sclk_o, + output mosi_o, + output cs_o +); + + reg + r_w_en_r, + alert_n_r2, + alert_n_r1, + alert_n_r0, + spi_poll_en_r, + spi_core_en_r, + spi_m_en_r, + rst_i_r, + wait_ctr_en_r; + reg dn_r; + reg [1:0] poll_addr_select; + reg [2:0] wait_ctr_r; + reg [2:0] poll_state; + reg [5:0] poll_rwaddr_r; + reg [5:0] rwaddr_r; + reg [15:0] wdata_r; + reg [39:0] spi_rdata_r; + wire [39:0] spi_rdata_w; + wire dn_w; + + localparam S0 = 0; + localparam S1 = 1; + localparam S2 = 2; + localparam S3 = 3; + localparam S4 = 4; + localparam poll_r_w_en = 1; // Continous read. + localparam poll_addr0 = 6'b000100; // 04h = V-shunt Register + localparam poll_addr1 = 6'b000101; // 05h = V-bus Register + localparam poll_addr2 = 6'b001011; // 0Bh = Diag Alert Reg. to clear Alert. + + spi_m_core spi_m_inst ( + .mclk_i(mclk_i), + .rst_i(rst_i_r), + .r_w_en_i(r_w_en_r), + .en_i(spi_m_en_r), + .rwaddr_i(rwaddr_r), + .wdata_i(wdata_r), + .dn_o(dn_w), + .rdata_o(spi_rdata_w), + // spi + .miso_i(miso_i), + .sclk_o(sclk_o), + .mosi_o(mosi_o), + .cs_o(cs_o) + ); + + always @(posedge mclk_i) begin + rst_i_r <= rst_i; + end + + always @(posedge mclk_i) begin + if (rst_i_r) spi_m_en_r <= 0; + else spi_m_en_r <= (en_i | spi_poll_en_r); + end + + always @(posedge mclk_i) begin + if (rst_i_r) begin + dn_o <= 0; + rdata_o <= 0; + end else begin + if (!mode_i) begin + dn_o <= dn_w; + if (dn_w) rdata_o <= spi_rdata_w; + end + end + end + + always @(posedge mclk_i) begin + if (rst_i_r) begin + {alert_n_r0, alert_n_r1, alert_n_r2} <= 3'b111; + end else begin + {alert_n_r2, alert_n_r1, alert_n_r0} <= {alert_n_r1, alert_n_r0, alert_n_i}; + end + end + + always @(posedge mclk_i) begin + if (mode_i) begin // if mode=0 R/W Mode. // if mode=1 Continous Mode + rwaddr_r <= poll_rwaddr_r; + wdata_r <= 0; + r_w_en_r <= poll_r_w_en; + end else begin + rwaddr_r <= rwaddr_i; + wdata_r <= wdata_i; + r_w_en_r <= r_w_en_i; + end + end + + // Shunt reg.s Polling state machine + + always @(posedge mclk_i) begin + if (rst_i_r) poll_state <= S0; + else begin + if (mode_i) begin + case (poll_state) + S0: begin + if (alert_n_r2) poll_state <= S0; + else poll_state <= S1; + end + S1: begin + poll_state <= S2; + end + S2: begin + if (dn_w) poll_state <= S3; + else poll_state <= S2; + end + S3: begin + if (poll_addr_select[1]) // Change to "poll_addr_select<=2" if alert doesn't clear after reading the vbus and vshunt registers. + poll_state <= S4; + else begin + if (wait_ctr_r[2]) //(wait_ctr_r>=5) // Changed to one bit comparator. + poll_state <= S1; + else poll_state <= S3; + end + end + S4: begin + if (alert_n_r2) poll_state <= S0; + else poll_state <= S4; + end + default: poll_state <= S0; + endcase + end else poll_state <= S0; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r) begin + spi_poll_en_r <= 0; + wait_ctr_en_r <= 0; + poll_dn_o <= 0; + end else begin + case (poll_state) + S0: begin + poll_dn_o <= 0; + wait_ctr_en_r <= 0; + spi_poll_en_r <= 0; + end + S1: begin + poll_dn_o <= 0; + spi_poll_en_r <= 1; + wait_ctr_en_r <= 0; + end + S2: begin + spi_poll_en_r <= 0; + poll_dn_o <= 0; + wait_ctr_en_r <= 0; + end + S3: begin // min wait time b/w 2 transaction + poll_dn_o <= 0; + spi_poll_en_r <= 0; + wait_ctr_en_r <= 1; + end + S4: begin + spi_poll_en_r <= 0; + poll_dn_o <= 1; + wait_ctr_en_r <= 0; + end + endcase + end + end + + always @(posedge mclk_i) begin + if (rst_i_r | poll_dn_o) poll_addr_select <= 0; + if (spi_m_en_r & mode_i) poll_addr_select <= poll_addr_select + 1; + end + + always @(posedge mclk_i) begin + if (poll_addr_select == 0) poll_rwaddr_r <= poll_addr0; + else if (poll_addr_select == 1) poll_rwaddr_r <= poll_addr1; + else poll_rwaddr_r <= poll_addr2; + end + + always @(posedge mclk_i) begin + if (dn_w & mode_i) begin + if (poll_addr_select == 2'b01) vshunt_o <= spi_rdata_w; + else if (poll_addr_select == 2'b10) vbus_o <= spi_rdata_w; + end + end + + always @(posedge mclk_i) begin + if (wait_ctr_en_r) wait_ctr_r <= wait_ctr_r + 1; + else wait_ctr_r <= 0; + end + +endmodule
diff --git a/fpga/gonk/spi_s_core.v b/fpga/gonk/spi_s_core.v new file mode 100644 index 0000000..349f5a8 --- /dev/null +++ b/fpga/gonk/spi_s_core.v
@@ -0,0 +1,351 @@ +// Copyright 2023 The Pigweed Authors +// +// 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 +// +// https://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. + +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// +////////////////////////////////////////////////////////////////////////////////// + +module spi_s_core ( + // + input [23:0] vbus_1, + input [23:0] vshunt_1, + input [23:0] vbus_2, + input [23:0] vshunt_2, + input [23:0] vbus_3, + input [23:0] vshunt_3, + input [23:0] vbus_4, + input [23:0] vshunt_4, + input [23:0] vbus_5, + input [23:0] vshunt_5, + input [23:0] vbus_6, + input [23:0] vshunt_6, + input [23:0] vbus_7, + input [23:0] vshunt_7, + input [23:0] vbus_8, + input [23:0] vshunt_8, + input [23:0] vbus_9, + input [23:0] vshunt_9, + input [23:0] vbus_10, + input [23:0] vshunt_10, + input [23:0] vbus_11, + input [23:0] vshunt_11, + // + input dn_i, + input poll_dn_i, + input [39:0] rdata_i, + output reg dn_clr_o, + output reg en_o, + output reg r_w_en_o, + output reg [5:0] rwaddr_o, + output reg [15:0] wdata_o, + output reg [10:0] adc_sel_o, + // sys + input mclk_i, + input rst_i, + input mode_i, + output data_valid_o, + // spi + input sclk_i, + input mosi_i, + input cs_i, + output reg miso_o +); + + localparam IDLE = 1; + localparam WT = 2; + localparam DN = 4; + + reg + sclk_i_r0, + sclk_i_r1, + sclk_i_r2, + cs_i_r0, + cs_i_r1, + cs_i_r2, + mosi_i_r0, + mosi_i_r1, + mosi_i_r2, + dat_out_dn_r, + rst_i_r, + wr_dn_valid_r; + reg + spi_rdy_r, + dat_out_dn_latch, + dat_out_en_r, + dat_out_ctr_clr, + poll_dat_ctr_clr, + addr_rdy_r, + wdata_rdy_r, + dat_out_ctr_clr_r, + poll_ctr_en_r, + poll_ctr_en_r1; + reg [2:0] spi_s_state; + reg [5:0] rwaddr_latch_r, poll_dat_ctr_r; + reg [6:0] dat_in_ctr_r, data_count_max_r, dat_out_ctr; + reg [15:0] rwaddr_r, wdata_r, wdata_latch_r; + reg [23:0] poll_dat_r; + reg [39:0] dat_in_r, dat_out_r, dat_in_r1; + + wire pos_edge, neg_edge, poll_ctr_en_w; + + assign pos_edge = (sclk_i_r1 & !sclk_i_r2); + assign neg_edge = (!sclk_i_r1 & sclk_i_r2); + assign poll_ctr_en_w = dat_out_ctr_clr_r & dat_out_ctr_clr; + assign data_valid_o = (dat_out_en_r | wr_dn_valid_r); + + wire [10:0] test; + assign test = (data_count_max_r - 1) - dat_out_ctr; + + always @(posedge mclk_i) begin + rst_i_r <= rst_i; + end + + always @(posedge mclk_i) begin + if (rst_i_r) begin + {sclk_i_r0, sclk_i_r1, sclk_i_r2} <= 0; + {cs_i_r0, cs_i_r1, cs_i_r2} <= 3'b111; + {mosi_i_r0, mosi_i_r1, mosi_i_r2} <= 0; + + end else begin + {sclk_i_r2, sclk_i_r1, sclk_i_r0} <= {sclk_i_r1, sclk_i_r0, sclk_i}; + {cs_i_r0, cs_i_r1, cs_i_r2} <= {cs_i, cs_i_r0, cs_i_r1}; + {mosi_i_r0, mosi_i_r1, mosi_i_r2} <= {mosi_i, mosi_i_r0, mosi_i_r1}; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r) begin + dat_in_r <= 0; + dat_in_ctr_r <= 0; + end else begin + if (!cs_i_r2 & spi_rdy_r) begin + if (neg_edge) begin + dat_in_r <= {dat_in_r, mosi_i_r2}; + dat_in_ctr_r <= dat_in_ctr_r + 1; + end + end else begin + dat_in_r <= 0; + dat_in_ctr_r <= 0; + end + end + end + + always @(posedge mclk_i) begin + if (rst_i_r | mode_i) spi_rdy_r <= 0; + else begin + spi_rdy_r <= (spi_s_state == IDLE); + end + end + + always @(posedge mclk_i) begin + if (rst_i_r) begin + addr_rdy_r <= 0; + end else begin + if (dat_in_ctr_r == 24) // changed from 16. + addr_rdy_r <= 1; + else addr_rdy_r <= 0; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r) begin + wdata_rdy_r <= 0; + end else begin + if (dat_in_ctr_r == 40) wdata_rdy_r <= 1; + else wdata_rdy_r <= 0; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r) begin + rwaddr_o <= 0; + r_w_en_o <= 0; + adc_sel_o <= 0; + end else begin + if (addr_rdy_r) begin + adc_sel_o <= dat_in_r1[17:7]; + rwaddr_o <= dat_in_r1[6:1]; + r_w_en_o <= dat_in_r1[0]; + end + end + end + + always @(posedge mclk_i) begin + if (rst_i_r) begin + dat_in_r1 <= 0; + end else begin + dat_in_r1 <= dat_in_r; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r) wdata_o <= 0; + else begin + if (wdata_rdy_r) wdata_o <= dat_in_r1; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r) en_o <= 0; + else begin + en_o <= (|adc_sel_o) & (wdata_rdy_r | (r_w_en_o & addr_rdy_r)); + end + end + + always @(posedge mclk_i) begin + if (rst_i_r | mode_i) spi_s_state <= IDLE; + else begin + case (spi_s_state) + IDLE: begin + if (en_o) spi_s_state <= WT; + else spi_s_state <= IDLE; + // spi_s_state<=en_o?r_w_en_o?RD:WR:IDLE; + end + WT: begin + if (r_w_en_o) begin + if (dat_out_dn_latch) spi_s_state <= DN; + else spi_s_state <= WT; + end else begin + if (dn_i) spi_s_state <= DN; + else spi_s_state <= WT; + end + end + DN: begin + spi_s_state <= IDLE; //(pos_edge)?IDLE:DN; + end + default: spi_s_state <= IDLE; + endcase + end + end + + always @(posedge mclk_i) begin + wr_dn_valid_r <= dn_i & ((~mode_i) & (~r_w_en_o)); + poll_ctr_en_r <= poll_ctr_en_w; + poll_ctr_en_r1 <= poll_ctr_en_r; + end + + always @(posedge mclk_i) begin + if (rst_i_r | dat_out_dn_latch) begin + dat_out_en_r <= 0; + end else begin + if ((mode_i & poll_dn_i) | ((!mode_i) & r_w_en_o & dn_i)) dat_out_en_r <= 1; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r) miso_o <= 1; + else begin + if (dat_out_en_r) begin + if (pos_edge) miso_o <= dat_out_r[((data_count_max_r-1)-dat_out_ctr)]; + end else miso_o <= 1; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r | dat_out_ctr_clr) dat_out_ctr <= 0; + else begin + if (dat_out_en_r) begin + if (neg_edge) dat_out_ctr <= dat_out_ctr + 1; + end else dat_out_ctr <= 0; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r) dat_out_r <= 0; + else begin + if (mode_i) begin + dat_out_r <= poll_dat_r; + end else begin + if (dn_i) dat_out_r <= rdata_i; + end + end + end + + always @(posedge mclk_i) begin + case (poll_dat_ctr_r) + 0: poll_dat_r <= vshunt_1; + 1: poll_dat_r <= vbus_1; + 2: poll_dat_r <= vshunt_2; + 3: poll_dat_r <= vbus_2; + 4: poll_dat_r <= vshunt_3; + 5: poll_dat_r <= vbus_3; + 6: poll_dat_r <= vshunt_4; + 7: poll_dat_r <= vbus_4; + 8: poll_dat_r <= vshunt_5; + 9: poll_dat_r <= vbus_5; + 10: poll_dat_r <= vshunt_6; + 11: poll_dat_r <= vbus_6; + 12: poll_dat_r <= vshunt_7; + 13: poll_dat_r <= vbus_7; + 14: poll_dat_r <= vshunt_8; + 15: poll_dat_r <= vbus_8; + 16: poll_dat_r <= vshunt_9; + 17: poll_dat_r <= vbus_9; + 18: poll_dat_r <= vshunt_10; + 19: poll_dat_r <= vbus_10; + 20: poll_dat_r <= vshunt_11; + 21: poll_dat_r <= vbus_11; + default: poll_dat_r <= 0; + endcase + end + + always @(posedge mclk_i) begin + dat_out_ctr_clr <= (dat_out_ctr == data_count_max_r); + dat_out_ctr_clr_r <= dat_out_ctr_clr; + poll_dat_ctr_clr <= (poll_dat_ctr_r == 22); + end + + always @(posedge mclk_i) begin + if (rst_i_r) dat_out_dn_r <= 0; + else + dat_out_dn_r <= (((!mode_i) & dat_out_ctr_clr) | (mode_i & poll_dat_ctr_clr)); // pos_edge & + end + + always @(posedge mclk_i) begin + if (rst_i_r | neg_edge) dat_out_dn_latch <= 0; + else if (dat_out_dn_r) dat_out_dn_latch <= 1; + end + + always @(posedge mclk_i) begin + if (rst_i_r | poll_dat_ctr_clr) poll_dat_ctr_r <= 0; + else begin + if (poll_ctr_en_w & mode_i) poll_dat_ctr_r <= poll_dat_ctr_r + 1; + end + end + + always @(posedge mclk_i) begin + if (rst_i_r) dn_clr_o <= 0; + else begin + dn_clr_o <= ((!mode_i & dn_i) | (mode_i & poll_dn_i)); + end + end + + always @(posedge mclk_i) begin + if (rst_i_r) begin + data_count_max_r <= 16; + end else begin + if (mode_i) data_count_max_r <= 24; + else begin + if (r_w_en_o) begin + if (rwaddr_o == 4 || rwaddr_o == 5 || rwaddr_o == 7 || rwaddr_o == 8) + data_count_max_r <= 24; + else if (rwaddr_o == 9 || rwaddr_o == 10) data_count_max_r <= 40; + else data_count_max_r <= 16; + end else data_count_max_r <= 16; + end + end + end + +endmodule
diff --git a/fpga/gonk/top.pcf b/fpga/gonk/top.pcf new file mode 100644 index 0000000..40a43c3 --- /dev/null +++ b/fpga/gonk/top.pcf
@@ -0,0 +1,79 @@ +# Copyright 2023 The Pigweed Authors +# +# 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 +# +# https://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. + +###IOSet List 63 +set_io led 56 +set_io rst_i 135 +set_io data_valid_o 136 +set_io op_mode_i 137 +set_io sl_cs_i_0 75 +set_io sl_mosi_i_0 74 +set_io sl_miso_o_0 73 +set_io sl_sclk_i_0 76 +set_io cs_o_3 19 +set_io miso_i_4 2 +set_io alertl_i_6 10 +set_io miso_i_3 16 +set_io mosi_o_6 11 +set_io sclk_o_7 139 +set_io alertl_i_1 104 +set_io cs_o_1 106 +set_io mosi_o_9 114 +set_io sclk_o_8 87 +set_io alertl_i_10 118 +set_io alertl_i_8 90 +set_io cs_o_8 93 +set_io miso_i_1 98 +set_io sclk_o_1 97 +set_io mosi_o_1 105 +set_io alertl_i_3 17 +set_io cs_o_10 120 +set_io cs_o_7 144 +set_io miso_i_10 117 +set_io miso_i_8 88 +set_io sclk_o_11 32 +set_io miso_i_7 141 +set_io mosi_o_2 24 +set_io sclk_o_3 15 +set_io alertl_i_5 83 +set_io cs_o_5 85 +set_io mosi_o_10 119 +set_io mosi_o_5 84 +set_io sclk_o_4 1 +set_io miso_i_5 82 +set_io alertl_i_7 142 +set_io mosi_o_7 143 +set_io sclk_o_6 8 +set_io clk_i 129 +set_io cs_o_2 25 +set_io alertl_i_9 113 +set_io cs_o_9 115 +set_io miso_i_2 22 +set_io miso_i_9 112 +set_io mosi_o_8 91 +set_io sclk_o_9 110 +set_io alertl_i_11 34 +set_io mosi_o_3 18 +set_io sclk_o_2 21 +set_io alertl_i_2 23 +set_io cs_o_11 38 +set_io cs_o_6 12 +set_io miso_i_11 33 +set_io sclk_o_10 116 +set_io miso_i_6 9 +set_io alertl_i_4 7 +set_io cs_o_4 4 +set_io mosi_o_11 37 +set_io mosi_o_4 3 +set_io sclk_o_5 81
diff --git a/fpga/gonk/top.v b/fpga/gonk/top.v new file mode 100644 index 0000000..e1773ec --- /dev/null +++ b/fpga/gonk/top.v
@@ -0,0 +1,296 @@ +// Copyright 2023 The Pigweed Authors +// +// 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 +// +// https://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. + +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// +////////////////////////////////////////////////////////////////////////////////// +module top ( + input clk_i, + input rst_i, + input op_mode_i, + output data_valid_o, + output led, + // spi secondary interface + input sl_sclk_i_0, + input sl_mosi_i_0, + input sl_cs_i_0, + output sl_miso_o_0, + // spi interfaces + // + input miso_i_1, + input alertl_i_1, + output sclk_o_1, + output mosi_o_1, + output cs_o_1, + // + input miso_i_2, + input alertl_i_2, + output sclk_o_2, + output mosi_o_2, + output cs_o_2, + // + input miso_i_3, + input alertl_i_3, + output sclk_o_3, + output mosi_o_3, + output cs_o_3, + // + input miso_i_4, + input alertl_i_4, + output sclk_o_4, + output mosi_o_4, + output cs_o_4, + // + input miso_i_5, + input alertl_i_5, + output sclk_o_5, + output mosi_o_5, + output cs_o_5, + // + input miso_i_6, + input alertl_i_6, + output sclk_o_6, + output mosi_o_6, + output cs_o_6, + // + input miso_i_7, + input alertl_i_7, + output sclk_o_7, + output mosi_o_7, + output cs_o_7, + // + input miso_i_8, + input alertl_i_8, + output sclk_o_8, + output mosi_o_8, + output cs_o_8, + // + input miso_i_9, + input alertl_i_9, + output sclk_o_9, + output mosi_o_9, + output cs_o_9, + // + input miso_i_10, + input alertl_i_10, + output sclk_o_10, + output mosi_o_10, + output cs_o_10, + // + input miso_i_11, + input alertl_i_11, + output sclk_o_11, + output mosi_o_11, + output cs_o_11 +); + + wire rst_i_sync, poll_dn_w, mclk, en_w, r_w_en_w, mode_i_sync, trf_dn_w, dn_clr; + wire [ 5:0] rwaddr_w; + wire [10:0] adc_select_w; + wire [11:0] poll_dn_bus_w; + wire [15:0] wdata_w; + wire [23:0] vbus_1,vshunt_1,vbus_2,vshunt_2 ,vbus_3 ,vshunt_3 ,vbus_4 ,vshunt_4 ,vbus_5 ,vshunt_5 ,vbus_6 ,vshunt_6 ; + wire [23:0] vbus_7 ,vshunt_7,vbus_8 ,vshunt_8 ,vbus_9 ,vshunt_9 ,vbus_10 ,vshunt_10 ,vbus_11 ,vshunt_11; + wire [39:0] rdata_w; + + pll pll_inst ( + .clock_in (clk_i), + .clock_out(mclk) + ); + + assign led = count[25]; + reg [25:0] count; + initial count = 0; + always @(posedge mclk) begin + count <= count + 1; + end + + spi_s_core spi_s_core_inst ( + .sclk_i(sl_sclk_i_0), + .mosi_i(sl_mosi_i_0), + .cs_i(sl_cs_i_0), + .miso_o(sl_miso_o_0), + // + .mclk_i(mclk), + .rst_i(rst_i_sync), + .en_o(en_w), + .rwaddr_o(rwaddr_w), + .adc_sel_o(adc_select_w), + .wdata_o(wdata_w), + .r_w_en_o(r_w_en_w), + .data_valid_o(data_valid_o), + .mode_i(mode_i_sync), + .rdata_i(rdata_w), + .poll_dn_i(poll_dn_w), + .dn_i(trf_dn_w), + .dn_clr_o(dn_clr), + .vbus_1(vbus_1), + .vshunt_1(vshunt_1), + .vbus_2(vbus_2), + .vshunt_2(vshunt_2), + .vbus_3(vbus_3), + .vshunt_3(vshunt_3), + .vbus_4(vbus_4), + .vshunt_4(vshunt_4), + .vbus_5(vbus_5), + .vshunt_5(vshunt_5), + .vbus_6(vbus_6), + .vshunt_6(vshunt_6), + .vbus_7(vbus_7), + .vshunt_7(vshunt_7), + .vbus_8(vbus_8), + .vshunt_8(vshunt_8), + .vbus_9(vbus_9), + .vshunt_9(vshunt_9), + .vbus_10(vbus_10), + .vshunt_10(vshunt_10), + .vbus_11(vbus_11), + .vshunt_11(vshunt_11) + ); + // + // .vbus_1(1),// vbus_1), + // .vshunt_1(2), + // .vbus_2(3), + // .vshunt_2(4), + // .vbus_3(5), + // .vshunt_3(6), + // .vbus_4(7), + // .vshunt_4(8), + // .vbus_5(9), + // .vshunt_5(10), + // .vbus_6(11), + // .vshunt_6(12), + // .vbus_7(13), + // .vshunt_7(14), + // .vbus_8(15), + // .vshunt_8(16), + // .vbus_9(17), + // .vshunt_9(19), + // .vbus_10(20), + // .vshunt_10(21), + // .vbus_11(22), + // .vshunt_11(23)); + + + rst_sync rst_sync_inst ( + .clk_i(mclk), + .rst_i(rst_i), + .rst_o(rst_i_sync) + ); + + sig_sync op_mode_sync ( + .clk_i(mclk), + .rst_i(rst_i_sync), + .sig_i(op_mode_i), + .sig_o(mode_i_sync) + ); + + csa_ctl_top csa_ctl_top_inst ( + .mclk_i(mclk), + .rst_i(rst_i_sync), + .r_w_en_i(r_w_en_w), + .en_i(en_w), + .mode_i(mode_i_sync), + .rwaddr_i(rwaddr_w), + .adc_sel_i(adc_select_w), + .wdata_i(wdata_w), + .dn_o(trf_dn_w), + .rdata_o(rdata_w), + // + .dn_clr_i(dn_clr), // Use to clear data-valid. Short to trf_dn_o of spi core. + .poll_dn_o(poll_dn_w), + // .poll_dn(),// NC. Only for bringup + // spi + .miso_i_1(miso_i_1), + .alertl_i_1(alertl_i_1), + .sclk_o_1(sclk_o_1), + .mosi_o_1(mosi_o_1), + .cs_o_1(cs_o_1), + .miso_i_2(miso_i_2), + .alertl_i_2(alertl_i_2), + .sclk_o_2(sclk_o_2), + .mosi_o_2(mosi_o_2), + .cs_o_2(cs_o_2), + .miso_i_3(miso_i_3), + .alertl_i_3(alertl_i_3), + .sclk_o_3(sclk_o_3), + .mosi_o_3(mosi_o_3), + .cs_o_3(cs_o_3), + .miso_i_4(miso_i_4), + .alertl_i_4(alertl_i_4), + .sclk_o_4(sclk_o_4), + .mosi_o_4(mosi_o_4), + .cs_o_4(cs_o_4), + .miso_i_5(miso_i_5), + .alertl_i_5(alertl_i_5), + .sclk_o_5(sclk_o_5), + .mosi_o_5(mosi_o_5), + .cs_o_5(cs_o_5), + .miso_i_6(miso_i_6), + .alertl_i_6(alertl_i_6), + .sclk_o_6(sclk_o_6), + .mosi_o_6(mosi_o_6), + .cs_o_6(cs_o_6), + .miso_i_7(miso_i_7), + .alertl_i_7(alertl_i_7), + .sclk_o_7(sclk_o_7), + .mosi_o_7(mosi_o_7), + .cs_o_7(cs_o_7), + .miso_i_8(miso_i_8), + .alertl_i_8(alertl_i_8), + .sclk_o_8(sclk_o_8), + .mosi_o_8(mosi_o_8), + .cs_o_8(cs_o_8), + .miso_i_9(miso_i_9), + .alertl_i_9(alertl_i_9), + .sclk_o_9(sclk_o_9), + .mosi_o_9(mosi_o_9), + .cs_o_9(cs_o_9), + .miso_i_10(miso_i_10), + .alertl_i_10(alertl_i_10), + .sclk_o_10(sclk_o_10), + .mosi_o_10(mosi_o_10), + .cs_o_10(cs_o_10), + .miso_i_11(miso_i_11), + .alertl_i_11(alertl_i_11), + .sclk_o_11(sclk_o_11), + .mosi_o_11(mosi_o_11), + .cs_o_11(cs_o_11), + // + .vbus_1(vbus_1), + .vshunt_1(vshunt_1), + .vbus_2(vbus_2), + .vshunt_2(vshunt_2), + .vbus_3(vbus_3), + .vshunt_3(vshunt_3), + .vbus_4(vbus_4), + .vshunt_4(vshunt_4), + .vbus_5(vbus_5), + .vshunt_5(vshunt_5), + .vbus_6(vbus_6), + .vshunt_6(vshunt_6), + .vbus_7(vbus_7), + .vshunt_7(vshunt_7), + .vbus_8(vbus_8), + .vshunt_8(vshunt_8), + .vbus_9(vbus_9), + .vshunt_9(vshunt_9), + .vbus_10(vbus_10), + .vshunt_10(vshunt_10), + .vbus_11(vbus_11), + .vshunt_11(vshunt_11) + ); + +endmodule