From 5090294a12d2a3fde0e8e0e208dfaa67859788eb Mon Sep 17 00:00:00 2001 From: RuigeLee Date: Thu, 27 Jun 2024 18:47:46 +0800 Subject: [PATCH] =?UTF-8?q?spi=20=E5=8A=9F=E8=83=BD=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E9=80=9A=E8=BF=87=EF=BC=8C=E8=B5=84=E6=BA=90=E4=B8=8D=E8=B6=B3?= =?UTF-8?q?=20qei=20=E9=98=B2=E8=B7=B3=E5=8F=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 1 + src/main/scala/backBoard/Qei.scala | 19 +- src/main/scala/backBoard/SpiSlv.scala | 113 ++++++++ src/main/scala/backBoard/SpiSlv.scala.bk | 35 --- src/main/verilog/spi_top.v | 322 +++++++++++++++++++++++ src/test/scala/gcd/test.scala | 8 +- 6 files changed, 454 insertions(+), 44 deletions(-) create mode 100644 src/main/scala/backBoard/SpiSlv.scala delete mode 100644 src/main/scala/backBoard/SpiSlv.scala.bk create mode 100644 src/main/verilog/spi_top.v diff --git a/Makefile b/Makefile index 48ce82c..7417f48 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,7 @@ back: cp ./src/main/verilog/di16_top.v ./generated/back/ cp ./src/main/verilog/do16_top.v ./generated/back/ cp ./src/main/verilog/qei_top.v ./generated/back/ + cp ./src/main/verilog/spi_top.v ./generated/back/ cp ./src/main/verilog/defineParam.v ./generated/back/ diff --git a/src/main/scala/backBoard/Qei.scala b/src/main/scala/backBoard/Qei.scala index faae8b3..4b6c611 100644 --- a/src/main/scala/backBoard/Qei.scala +++ b/src/main/scala/backBoard/Qei.scala @@ -136,21 +136,24 @@ class Qei extends BackBoardSlvLocal with BackBoardSlvStatusPR with BackBoardSlvQ } + val cntLatch = for( i <- 0 until 2 ) yield { RegEnable(counter(i), ~RegNext(io.lvdsSlv.upstream_tx_data_ready, false.B) & io.lvdsSlv.upstream_tx_data_ready ) } + + when( statusPage === 0.U ){ upReg(2) := Cat( isSign(0), invDirect(0), mode(0), isSetVal(0), is2Phase(0), isZPhaseEnable(0), isEnable(0) ) upReg(3) := 0.U upReg(4) := Cat( isSign(1), invDirect(1), mode(1), isSetVal(1), is2Phase(1), isZPhaseEnable(1), isEnable(1) ) upReg(5) := 0.U - upReg(6) := counter(0)(7,0) - upReg(7) := counter(0)(15,8) - upReg(8) := counter(0)(23,16) - upReg(9) := counter(0)(31,24) + upReg(6) := cntLatch(0)(7,0) + upReg(7) := cntLatch(0)(15,8) + upReg(8) := cntLatch(0)(23,16) + upReg(9) := cntLatch(0)(31,24) - upReg(10) := counter(1)(7,0) - upReg(11) := counter(1)(15,8) - upReg(12) := counter(1)(23,16) - upReg(13) := counter(1)(31,24) + upReg(10) := cntLatch(1)(7,0) + upReg(11) := cntLatch(1)(15,8) + upReg(12) := cntLatch(1)(23,16) + upReg(13) := cntLatch(1)(31,24) } } diff --git a/src/main/scala/backBoard/SpiSlv.scala b/src/main/scala/backBoard/SpiSlv.scala new file mode 100644 index 0000000..217ad51 --- /dev/null +++ b/src/main/scala/backBoard/SpiSlv.scala @@ -0,0 +1,113 @@ +package BACK + +import chisel3._ +import chisel3.util._ + + +trait BackBoardSpiSlv{ this: BackBoardSlvLocal => + + def page: Int + + val sck = Wire(Bool()) + val mosi = Wire(Bool()) + val csn = Wire(Bool()) + val clk100M = Wire(Bool()) + + val localReg = for( i <- 0 until page ) yield {Reg(Vec(31, UInt(8.W)))} + val localUpdate = RegInit(0.U(16.W)) + + + + val shiftSCK = withClockAndReset( clk100M.asClock, reset ){ ShiftRegisters(sck, 3, false.B, true.B) } + val shiftCSn = withClockAndReset( clk100M.asClock, reset ){ ShiftRegisters(csn, 3, true.B, true.B) } + val shiftMOSI = withClockAndReset( clk100M.asClock, reset ){ ShiftRegisters(mosi, 3) } + + + val isSckPosedge = ~shiftSCK(2) & shiftSCK(1) + val isSckNegedge = shiftSCK(2) & ~shiftSCK(1) + + + val exReg_100M = withClockAndReset( clk100M.asClock, reset ){ Reg(UInt((8*31).W)) } + val cmd_100M = withClockAndReset( clk100M.asClock, reset ){ Reg(UInt(8.W)) } + val pageSel = cmd_100M(7,4) + val spiCmd = cmd_100M(3,0) + val localPage = PriorityMux( ( 0 until page ).map{ i => ( i.U === pageSel ) -> localReg(i) } ) + + val cnt_100M = withClockAndReset( clk100M.asClock, reset ){ Reg(UInt(4.W)) } + + // val misoReg = withClockAndReset( clk100M.asClock, reset ){ Reg(Bool()) } + + + withClockAndReset( clk100M.asClock, reset ){//100M + + when( shiftCSn(2) & ~shiftCSn(1) ){ + cnt_100M := 0.U + // misoReg := false.B + } .elsewhen( isSckPosedge & ~shiftCSn(1) & cnt_100M < 8.U ){ + cmd_100M := Cat( cmd_100M(6,0), shiftMOSI(1) ) + cnt_100M := cnt_100M + 1.U + } .elsewhen( isSckNegedge & ~shiftCSn(1) & cnt_100M === 8.U ){ + exReg_100M := Mux( spiCmd.extract(1), Cat( localUpdate, 0.U((8*29).W) ), Cat( localPage.reverse) ) + cnt_100M := cnt_100M + 1.U + } .elsewhen( isSckPosedge & ~shiftCSn(1) & cnt_100M === 9.U ){ + // misoReg := exReg_100M.extract(exReg_100M.getWidth-1) + exReg_100M := Cat( exReg_100M(exReg_100M.getWidth-2 ,0), shiftMOSI(1) ) + } + } +} + + +class SpiSlv extends BackBoardSlvLocal +with BackBoardSlvStatusPR +with BackBoardSpiSlv{ + + def page: Int = 1 + + val spi = IO(new Bundle{ + val sck = Input(Bool()) + val mosi = Input(Bool()) + val miso = Output(Bool()) + val csn = Input(Bool()) + }) + val clk100MIO = IO(Input(Bool())) + + sck := spi.sck + mosi := spi.mosi + csn := spi.csn + spi.miso := exReg_100M.extract(exReg_100M.getWidth-1) + clk100M := clk100MIO + + val shiftCSn_10M = ShiftRegisters(csn, 3, true.B, true.B) + + for( i <- 0 until page ){ + + when( isCrcPass ){ + when( downRegTemp(0)(3,0) === i.U ){ + localUpdate := localUpdate & ~( 1.U << i ) + for( j <- 1 until 32 ) { + localReg(i)(j-1) := downRegTemp(j) + } + } + } .elsewhen( ~shiftCSn_10M(2) & shiftCSn_10M(1) & spiCmd === 1.U ){ + when( i.U === pageSel ){ + for( j <- 0 until 31 ) { + localReg(i)(30-j) := exReg_100M(8*j+7,8*j) + } + } + } .elsewhen( ~shiftCSn_10M(2) & shiftCSn_10M(1) & spiCmd === 3.U ){ + localUpdate := localUpdate & (~exReg_100M(15,0)) + } + + when( statusPage === i.U ){ + for( j <- 1 until 32 ) { + upReg(j) := localReg(i)(j-1) + } + } + } + + + +} + + + diff --git a/src/main/scala/backBoard/SpiSlv.scala.bk b/src/main/scala/backBoard/SpiSlv.scala.bk deleted file mode 100644 index 914af9e..0000000 --- a/src/main/scala/backBoard/SpiSlv.scala.bk +++ /dev/null @@ -1,35 +0,0 @@ -package BACK - -import chisel3._ -import chisel3.util._ - - -trait BackBoardSpiSlv{ this: BackBoardSlvLocal => - val sck = Wire(Bool()) - val mosi = Wire(Bool()) - val csn = Wire(Bool()) - val clk100M = Wire(Bool()) - - val shiftSCK = withClockAndReset( clk100M.asClock, reset ){ ShiftRegisters(sck, 3, false.B, true.B) } - val shiftCSn = withClockAndReset( clk100M.asClock, reset ){ ShiftRegisters(csn, 3, true.B, true.B) } - val shiftMOSI = withClockAndReset( clk100M.asClock, reset ){ ShiftRegisters(mosi, 3) } - - val isSckPosedge = ~shiftSCK(2) & shiftSCK(1) - val isSckNegedge = shiftSCK(2) & ~shiftSCK(1) - - - val downReg_100M = withClockAndReset( clk100M.asClock, reset ){ Reg(UInt(8*8.W)) } - val upReg_100M = withClockAndReset( clk100M.asClock, reset ){ Reg(UInt(8*8.W)) } - val misoReg = withClockAndReset( clk100M.asClock, reset ){ Reg(Bool()) } - - - withClockAndReset( clk100M.asClock, reset ){//100M - when( isSckPosedge & shiftCSn(2) ){ - misoReg := downReg_100M.extract(0) - downReg_100M := downReg_100M >> 1 - upReg_100M := Cat( upReg_100M(8*8-1,1), shiftMOSI(2) ) - } - } - -} - diff --git a/src/main/verilog/spi_top.v b/src/main/verilog/spi_top.v new file mode 100644 index 0000000..bf15e40 --- /dev/null +++ b/src/main/verilog/spi_top.v @@ -0,0 +1,322 @@ + + +module spi_top( + + input clock, + + + input lvds_up_din_p, + input lvds_up_din_n, + output lvds_up_dout_p, + output lvds_up_dout_n, + + input lvds_down_din_p, + input lvds_down_din_n, + output lvds_down_dout_p, + output lvds_down_dout_n, + + output isOnline, + input isLast, + + input DCIn, + output LED_PR, + + input sck, + input mosi, + output miso, + input csn + +); + + + +wire clk_400m; +wire clk_400m_a; +wire clk_100m_a; +wire clk_50m_a; +wire clk_10m_a; + +wire lock_o; +wire reset_stop; +wire reset_calib; + +reg rst_n; +reg rstn_d; + +wire resetn; +reg resetn1=1'b1; +wire timeout_rst; +reg timeout_rst_d1; +reg timeout_rst_d2; +reg timeout_rst_d3; +reg timeout_rst_d4; +reg timeout_rst_d5; +reg timeout_rst_d6; +reg timeout_rst_d7; +reg timeout_rst_d8; + +reg [3:0] resetCnt = 4'd0; +always @( posedge clock ) begin + if( resetCnt != 4'd15 ) begin + resetCnt <= resetCnt + 4'd1; + end +end + +assign resetn = resetCnt == 4'd15; + +always@(posedge clock or negedge resetn) begin + if(!resetn) begin + timeout_rst_d1 <= 0; + timeout_rst_d2 <= 0; + timeout_rst_d3 <= 0; + timeout_rst_d4 <= 0; + timeout_rst_d5 <= 0; + timeout_rst_d6 <= 0; + timeout_rst_d7 <= 0; + timeout_rst_d8 <= 0; + end + else begin + timeout_rst_d1 <= timeout_rst; + timeout_rst_d2 <= timeout_rst_d1; + timeout_rst_d3 <= timeout_rst_d2; + timeout_rst_d4 <= timeout_rst_d3; + timeout_rst_d5 <= timeout_rst_d4; + timeout_rst_d6 <= timeout_rst_d5; + timeout_rst_d7 <= timeout_rst_d6; + timeout_rst_d8 <= timeout_rst_d7; + end +end + +always @(posedge clock or negedge resetn) begin + if(!resetn) begin + resetn1 <= 1'b1; + end else if((timeout_rst_d3 == 1'b0) && (timeout_rst_d2 == 1'b1)) begin + resetn1 <= 1'b0; + end else if((timeout_rst_d4 == 1'b0) && (timeout_rst_d3 == 1'b1)) begin + resetn1 <= 1'b0; + end else if((timeout_rst_d5 == 1'b0) && (timeout_rst_d4 == 1'b1)) begin + resetn1 <= 1'b0; + end else if((timeout_rst_d6 == 1'b0) && (timeout_rst_d5 == 1'b1)) begin + resetn1 <= 1'b0; + end else if((timeout_rst_d7 == 1'b0) && (timeout_rst_d6 == 1'b1)) begin + resetn1 <= 1'b0; + end else if((timeout_rst_d8 == 1'b0) && (timeout_rst_d7 == 1'b1)) begin + resetn1 <= 1'b0; + end else begin + resetn1 <= 1'b1; + end +end + + +reg [5:0] delay_io_last=6'b111111; +reg [15:0] counter0=0; +reg clk_en0; +wire isLast_temp; +wire isLast_temp1; + +always @(posedge clk_10m_a or negedge resetn) begin + if(!resetn) begin + counter0 <= 16'd0; + clk_en0 <= 1'b0; + end else if(counter0 == 16'd9999) begin + counter0 <= 16'd0; + clk_en0 <= 1'b1; + end else begin + counter0 <= counter0 + 1; + clk_en0 <= 1'b0; + end +end + + +always @(posedge clk_10m_a or negedge resetn) begin + if(!resetn) begin + delay_io_last <= 6'b111111; + end else if(clk_en0 == 1'b1) begin + delay_io_last[5:1] <= delay_io_last[4:0]; + delay_io_last[0] <= isLast; + end +end + + +assign isLast_temp = &{!delay_io_last[5],!delay_io_last[4],!delay_io_last[3],!delay_io_last[2],!delay_io_last[1]}; +assign isLast_temp1 = ~isLast_temp; + +Gowin_PLLO Gowin_PLLO( + .lock(lock_o), + .clkouta(clk_400m), + .clkin(clock) +); + + + +TLVDS_OBUF lvds_downstream_out( + .O(lvds_down_dout_p), + .OB(lvds_down_dout_n), + .I(lvds_down_dout) +); + + +TLVDS_IBUF lvds_downstream_in( + .O(lvds_down_din), + .I(lvds_down_din_p), + .IB(lvds_down_din_n) +); + + +TLVDS_OBUF lvds_upstream_out( + .O(lvds_up_dout_p), + .OB(lvds_up_dout_n), + .I(lvds_up_dout) +); + + +TLVDS_IBUF lvds_upstream_in( + .O(lvds_up_din), + .I(lvds_up_din_p), + .IB(lvds_up_din_n) +); + + +DHCEN dhcen_inst2 ( + .CLKIN(clk_400m), + .CE(reset_stop), + .CLKOUT(clk_400m_a) +); + + +//reset sync module, all the IDES/OSER and related CLKDIV MUST be reset by this module +oser_rst u_oser_rst( + .clk_in(clock), // or any other speed comparble with fabric, DO NOT use HCLK as fabric cannot work at so high speed. + .rst_n(resetn && resetn1), + .pll_lock(lock_o), // trigged by PLL Lock + .reset_stop(reset_stop), // for DHCEN CE + .reset_calib(reset_calib), // for IDES and CLKDIV reset + .set_calib(), + .ready() +); + + +defparam Inst4_CLKDIVC.DIV_MODE="4"; +defparam Inst4_CLKDIVC.GSREN="false"; +CLKDIV Inst4_CLKDIVC( + .RESETN (~reset_calib), + .HCLKIN (clk_400m_a), + .CALIB (1'b0 ), + .CLKOUT (clk_100m_a) +); + + +defparam Inst2_CLKDIVC.DIV_MODE="2"; +defparam Inst2_CLKDIVC.GSREN="false"; +CLKDIV Inst2_CLKDIVC( + .RESETN (~reset_calib), + .HCLKIN (clk_100m_a), + .CALIB (1'b0 ), + .CLKOUT (clk_50m_a) +); + + +defparam Inst5_CLKDIVC.DIV_MODE="5"; +defparam Inst5_CLKDIVC.GSREN="false"; +CLKDIV Inst5_CLKDIVC( + .RESETN (~reset_calib), + .HCLKIN (clk_50m_a), + .CALIB (1'b0 ), + .CLKOUT (clk_10m_a) +); + +wire [7:0] downstream_rx_data_out; +wire downstream_rx_data_valid; +wire downstream_rx_crc_valid; +wire downstream_rx_crc_err; +wire upstream_tx_data_ready; +wire [7:0] upstream_tx_data_in; + +wire downstream_rx_cdr_err; +wire upstream_rx_cdr_err; + +lvds_bus_slave_top i_lvds_bus_slave( + .rst_n(resetn && resetn1), + .reset_calib(reset_calib), + .oser_pclk(clk_10m_a), + .oser_fclk(clk_50m_a), + .ides_pclk(clk_100m_a), + .ides_fclk(clk_400m_a), + .timeout_rst(timeout_rst), //add 240523 + + .lvds_down_din(lvds_down_din), + .lvds_down_dout(lvds_down_dout), + .lvds_up_din(lvds_up_din), + .lvds_up_dout(lvds_up_dout), + + .downstream_rx_data_valid(downstream_rx_data_valid), + .downstream_rx_unicast_pkg_valid(), + .downstream_rx_data_out(downstream_rx_data_out), + .downstream_rx_crc_valid(downstream_rx_crc_valid), + .downstream_rx_crc_err(downstream_rx_crc_err), + .downstream_rx_crc_err_counter(), + .downstream_rx_cdr_err(downstream_rx_cdr_err), + .downstream_sync(), + .upstream_tx_data_ready(upstream_tx_data_ready), + .upstream_tx_unicast_pkg_ready(), + .upstream_tx_data_in(upstream_tx_data_in), + .upstream_rx_crc_valid(), + .upstream_rx_crc_err(), + .upstream_rx_crc_err_counter(), + .upstream_rx_cdr_err(upstream_rx_cdr_err), + + .local_slave_id(), + .test_downstream_rx_10b_data(), + .test_downstream_rx_8b_data(), + .test_downstream_rx_state_machine(), + .test_downstream_tx_en(), + .test_downstream_tx_8b_data(), + .test_downstream_tx_10b_data(), + .test_upstream_rx_10b_data(), + .test_upstream_rx_8b_data(), + .test_upstream_rx_state_machine(), + .test_upstream_tx_en(), + .test_upstream_tx_8b_data(), + .test_upstream_tx_10b_data() + ); + + +SpiSlv i_spiSlv( + .reset(~resetn), + .clock(clk_10m_a), + + .io_isOnline(isOnline), + .io_isLast(isLast_temp1), + .io_DCIn(DCIn), + + .param_vendorID(`VENDORID), + .param_moduleID(`MODULEID), + .param_hwVersion(`HWVERSION), + .param_swVersion(`SWVERSION), + .param_serial(`SERIAL), + + .io_lvdsSlv_downstream_rx_data_out(downstream_rx_data_out), + .io_lvdsSlv_downstream_rx_data_valid(downstream_rx_data_valid), + .io_lvdsSlv_downstream_rx_crc_valid(downstream_rx_crc_valid), + .io_lvdsSlv_downstream_rx_crc_err(downstream_rx_crc_err), + .io_lvdsSlv_upstream_tx_data_ready(upstream_tx_data_ready), + .io_lvdsSlv_upstream_tx_data_in(upstream_tx_data_in), + .io_lvdsSlv_downstream_rx_cdr_err(downstream_rx_cdr_err), + .io_lvdsSlv_upstream_rx_cdr_err(upstream_rx_cdr_err), + + .LED_PR(LED_PR), + .spi_sck(sck), + .spi_mosi(mosi), + .spi_miso(miso), + .spi_csn(csn), + .clk100MIO(clk_100m_a) +); + + + + +endmodule + + + + diff --git a/src/test/scala/gcd/test.scala b/src/test/scala/gcd/test.scala index 847ab22..90d7832 100644 --- a/src/test/scala/gcd/test.scala +++ b/src/test/scala/gcd/test.scala @@ -32,7 +32,13 @@ object testModule extends App { (new chisel3.stage.ChiselStage).execute( Array("--target-dir", "generated/back/", "-E", "verilog" ) ++ args, Seq( ChiselGeneratorAnnotation(() => { new Qei }) )) - + + (new chisel3.stage.ChiselStage).execute( Array("--target-dir", "generated/back/", "-E", "verilog" ) ++ args, Seq( + ChiselGeneratorAnnotation(() => { new SpiSlv }) + )) + + + // (new chisel3.stage.ChiselStage).execute( Array("--target-dir", "generated/", "-E", "verilog" ) ++ args, Seq( // ChiselGeneratorAnnotation(() => { new BackPlaneChainTest }) // ))