| // 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 |