Pārlūkot izejas kodu

Новый модуль TempRead.

Mihail Zaytsev 1 gadu atpakaļ
vecāks
revīzija
fc31c35732

+ 366 - 0
src/src/TempRead/ExtI2cSlaveEmul.v

@@ -0,0 +1,366 @@
+/////////////////////////////////////////////////////////////////////
+////                                                             ////
+////  WISHBONE rev.B2 compliant synthesizable I2C Slave model    ////
+////                                                             ////
+////                                                             ////
+////  Authors: Richard Herveille (richard@asics.ws) www.asics.ws ////
+////           John Sheahan (jrsheahan@optushome.com.au)         ////
+////                                                             ////
+////  Downloaded from: http://www.opencores.org/projects/i2c/    ////
+////                                                             ////
+/////////////////////////////////////////////////////////////////////
+////                                                             ////
+//// Copyright (C) 2001,2002 Richard Herveille                   ////
+////                         richard@asics.ws                    ////
+////                                                             ////
+//// This source file may be used and distributed without        ////
+//// restriction provided that this copyright statement is not   ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer.////
+////                                                             ////
+////     THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     ////
+//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   ////
+//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   ////
+//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      ////
+//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         ////
+//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    ////
+//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   ////
+//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        ////
+//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  ////
+//// LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  ////
+//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  ////
+//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         ////
+//// POSSIBILITY OF SUCH DAMAGE.                                 ////
+////                                                             ////
+/////////////////////////////////////////////////////////////////////
+
+//  CVS Log
+//
+//  $Id: i2c_slave_model.v,v 1.7 2006-09-04 09:08:51 rherveille Exp $
+//
+//  $Date: 2006-09-04 09:08:51 $
+//  $Revision: 1.7 $
+//  $Author: rherveille $
+//  $Locker:  $
+//  $State: Exp $
+//
+// Change History:
+//               $Log: not supported by cvs2svn $
+//               Revision 1.6  2005/02/28 11:33:48  rherveille
+//               Fixed Tsu:sta timing check.
+//               Added Thd:sta timing check.
+//
+//               Revision 1.5  2003/12/05 11:05:19  rherveille
+//               Fixed slave address MSB='1' bug
+//
+//               Revision 1.4  2003/09/11 08:25:37  rherveille
+//               Fixed a bug in the timing section. Changed 'tst_scl' into 'tst_sto'.
+//
+//               Revision 1.3  2002/10/30 18:11:06  rherveille
+//               Added timing tests to i2c_model.
+//               Updated testbench.
+//
+//               Revision 1.2  2002/03/17 10:26:38  rherveille
+//               Fixed some race conditions in the i2c-slave model.
+//               Added debug information.
+//               Added headers.
+//
+
+//`include "timescale.v"
+`timescale 1ns / 1ns
+
+module ExtI2cSlaveEmul (scl, sda);
+
+	//
+	// parameters
+	//
+	//parameter I2C_ADR = 7'b001_0000;
+	parameter I2C_ADR = 7'b100_1000;
+
+	//
+	// input && outpus
+	//
+	input scl;
+	inout sda;
+
+	//
+	// Variable declaration
+	//
+	wire debug = 1'b1;
+
+	reg [7:0] mem [3:0]; // initiate memory
+	reg [7:0] mem_adr = 8'h0000;   // memory address
+	reg [7:0] mem_do = 8'h0000;    // memory data output
+
+	reg sta, d_sta;
+	reg sto, d_sto;
+
+	reg [7:0] sr;        // 8bit shift register
+	reg       rw;        // read/write direction
+
+	wire      my_adr;    // my address called ??
+	wire      i2c_reset; // i2c-statemachine reset
+	reg [2:0] bit_cnt;   // 3bit downcounter
+	wire      acc_done;  // 8bits transfered
+	reg       ld;        // load downcounter
+
+	reg       sda_o;     // sda-drive level
+	wire      sda_dly;   // delayed version of sda
+
+	// statemachine declaration
+	parameter idle        = 3'b000;
+	parameter slave_ack   = 3'b001;
+	parameter get_mem_adr = 3'b010;
+	parameter gma_ack     = 3'b011;
+	parameter data        = 3'b100;
+	parameter data_ack    = 3'b101;
+
+	reg [2:0] state; // synopsys enum_state
+
+	//
+	// module body
+	//
+
+	initial
+	begin
+	   sda_o = 1'b1;
+	   state = idle;
+	end
+
+	initial begin
+		mem[0] = 8'hFF;
+		mem[1] = 8'hE0;
+		mem[2] = 8'hFF;
+		mem[3] = 8'hFF;
+	end
+
+	// generate shift register
+	always @(posedge scl)
+	  sr <= #1 {sr[6:0],sda};
+
+	//detect my_address
+	assign my_adr = (sr[7:1] == I2C_ADR);
+	// FIXME: This should not be a generic assign, but rather
+	// qualified on address transfer phase and probably reset by stop
+
+	//generate bit-counter
+	always @(posedge scl)
+	  if(ld)
+	    bit_cnt <= #1 3'b111;
+	  else
+	    bit_cnt <= #1 bit_cnt - 3'h1;
+
+	//generate access done signal
+	assign acc_done = !(|bit_cnt);
+
+	// generate delayed version of sda
+	// this model assumes a hold time for sda after the falling edge of scl.
+	// According to the Phillips i2c spec, there s/b a 0 ns hold time for sda
+	// with regards to scl. If the data changes coincident with the clock, the
+	// acknowledge is missed
+	// Fix by Michael Sosnoski
+	assign #1 sda_dly = sda;
+
+
+	//detect start condition
+	always @(negedge sda)
+	  if(scl)
+	    begin
+	        sta   <= #1 1'b1;
+		d_sta <= #1 1'b0;
+		sto   <= #1 1'b0;
+
+	        if(debug)
+	          $display("DEBUG i2c_slave; start condition detected at %t", $time);
+	    end
+	  else
+	    sta <= #1 1'b0;
+
+	always @(posedge scl)
+	  d_sta <= #1 sta;
+
+	// detect stop condition
+	always @(posedge sda)
+	  if(scl)
+	    begin
+	       sta <= #1 1'b0;
+	       sto <= #1 1'b1;
+
+	       if(debug)
+	         $display("DEBUG i2c_slave; stop condition detected at %t", $time);
+	    end
+	  else
+	    sto <= #1 1'b0;
+
+	//generate i2c_reset signal
+	assign i2c_reset = sta || sto;
+
+	// generate statemachine
+	always @(negedge scl or posedge sto)
+	  if (sto || (sta && !d_sta) )
+	    begin
+	        state <= #1 idle; // reset statemachine
+
+	        sda_o <= #1 1'b1;
+	        ld    <= #1 1'b1;
+	    end
+	  else
+	    begin
+	        // initial settings
+	        sda_o <= #1 1'b1;
+	        ld    <= #1 1'b0;
+
+	        case(state) // synopsys full_case parallel_case
+	            idle: // idle state
+	              if (acc_done && my_adr)
+	                begin
+	                    state <= #1 slave_ack;
+	                    rw <= #1 sr[0];
+	                    sda_o <= #1 1'b0; // generate i2c_ack
+
+	                    #2;
+	                    if(debug && rw)
+	                      $display("DEBUG i2c_slave; command byte received (read) at %t", $time);
+	                    if(debug && !rw)
+	                      $display("DEBUG i2c_slave; command byte received (write) at %t", $time);
+
+	                    if(rw)
+	                      begin
+	                          mem_do <= #1 mem[mem_adr];
+
+	                          if(debug)
+	                            begin
+	                                #2 $display("DEBUG i2c_slave; data block read %x from address %x (1)", mem_do, mem_adr);
+	                                #2 $display("DEBUG i2c_slave; memcheck [0]=%x, [1]=%x, [2]=%x", mem[4'h0], mem[4'h1], mem[4'h2]);
+	                            end
+	                      end
+	                end
+
+	            slave_ack:
+	              begin
+	                  if(rw)
+	                    begin
+	                        state <= #1 data;
+	                        sda_o <= #1 mem_do[7];
+	                    end
+	                  else
+	                    state <= #1 get_mem_adr;
+
+	                  ld    <= #1 1'b1;
+	              end
+
+	            get_mem_adr: // wait for memory address
+	              if(acc_done)
+	                begin
+	                    state <= #1 gma_ack;
+	                    mem_adr <= #1 sr; // store memory address
+	                    sda_o <= #1 !(sr <= 15); // generate i2c_ack, for valid address
+
+	                    if(debug)
+	                      #1 $display("DEBUG i2c_slave; address received. adr=%x, ack=%b", sr, sda_o);
+	                end
+
+	            gma_ack:
+	              begin
+	                  state <= #1 data;
+	                  ld    <= #1 1'b1;
+	              end
+
+	            data: // receive or drive data
+	              begin
+	                  if(rw)
+	                    sda_o <= #1 mem_do[7];
+
+	                  if(acc_done)
+	                    begin
+	                        state <= #1 data_ack;
+	                        mem_adr <= #2 mem_adr + 8'h1;
+	                        sda_o <= #1 (rw && (mem_adr <= 15) ); // send ack on write, receive ack on read
+
+	                        if(rw)
+	                          begin
+	                              #3 mem_do <= mem[mem_adr];
+
+	                              if(debug)
+	                                #5 $display("DEBUG i2c_slave; data block read %x from address %x (2)", mem_do, mem_adr);
+	                          end
+
+	                        /*if(!rw)
+	                          begin
+	                              mem[ mem_adr[3:0] ] <= #1 sr; // store data in memory
+
+	                              if(debug)
+	                                #2 $display("DEBUG i2c_slave; data block write %x to address %x", sr, mem_adr);
+	                          end*/
+	                    end
+	              end
+
+	            data_ack:
+	              begin
+	                  ld <= #1 1'b1;
+
+	                  if(rw)
+	                    if(sr[0]) // read operation && master send NACK
+	                      begin
+	                          state <= #1 idle;
+	                          sda_o <= #1 1'b1;
+	                      end
+	                    else
+	                      begin
+	                          state <= #1 data;
+	                          sda_o <= #1 mem_do[7];
+	                      end
+	                  else
+	                    begin
+	                        state <= #1 data;
+	                        sda_o <= #1 1'b1;
+	                    end
+	              end
+
+	        endcase
+	    end
+
+	// read data from memory
+	always @(posedge scl)
+	  if(!acc_done && rw)
+	    mem_do <= #1 {mem_do[6:0], 1'b1}; // insert 1'b1 for host ack generation
+
+	// generate tri-states
+	assign sda = sda_o ? 1'bz : 1'b0;
+
+
+	//
+	// Timing checks
+	//
+
+	wire tst_sto = sto;
+	wire tst_sta = sta;
+
+	specify
+	  specparam normal_scl_low  = 4700,
+	            normal_scl_high = 4000,
+	            normal_tsu_sta  = 4700,
+	            normal_thd_sta  = 4000,
+	            normal_tsu_sto  = 4000,
+	            normal_tbuf     = 4700,
+
+	            fast_scl_low  = 1300,
+	            fast_scl_high =  600,
+	            fast_tsu_sta  = 1300,
+	            fast_thd_sta  =  600,
+	            fast_tsu_sto  =  600,
+	            fast_tbuf     = 1300;
+
+	  $width(negedge scl, normal_scl_low);  // scl low time
+	  $width(posedge scl, normal_scl_high); // scl high time
+
+	  $setup(posedge scl, negedge sda &&& scl, normal_tsu_sta); // setup start
+	  $setup(negedge sda &&& scl, negedge scl, normal_thd_sta); // hold start
+	  $setup(posedge scl, posedge sda &&& scl, normal_tsu_sto); // setup stop
+
+	  $setup(posedge tst_sta, posedge tst_sto, normal_tbuf); // stop to start time
+	endspecify
+
+endmodule
+
+

+ 205 - 0
src/src/TempRead/ExtSpiMEmul.v

@@ -0,0 +1,205 @@
+`timescale 1ns / 1ps
+
+module ExtSpiMEmul 
+(
+	input Rst_i,
+	input Clk_i,
+	
+	input Start_i,
+	output TxDone_o,
+	
+	output Sck_o,
+	output reg Ss_o,
+	output reg Mosi_o
+	
+);
+
+//================================================================================
+//  PARAMETERS
+	localparam [1:0] IDLE = 0;
+	localparam [1:0] CMD = 1;
+	localparam [1:0] TX = 2;
+	localparam [1:0] PAUSE = 3;
+
+	parameter MODE = 1'h0;
+	parameter [4:0] DEVID = 5'h8;
+	parameter [16:0] WORDSNUM = 17'h1;
+	parameter EOPBIT = 1'b1;
+	
+//================================================================================
+//  REG/WIRE
+	reg [1:0] currState;
+	reg [1:0] nextState;
+	
+	reg	[6:0]	txCnt;
+	reg	[6:0]	cmdCnt;
+	reg	[3:0]	pauseCnt;
+
+	wire	txStop	=	(cmdCnt	>=	WORDSNUM+1);
+	
+	reg [23:0] headerCmd = {MODE,DEVID,WORDSNUM,EOPBIT};
+	reg [23:0] spiData;
+	
+	reg	[23:0]	dspSpiData;
+	
+	reg sckFlag;
+//================================================================================
+//  ASSIGNMENTS
+
+assign	Sck_o		=	(sckFlag)? ~Clk_i:1'b1;
+assign	TxDone_o	=	(txStop & (currState== CMD));
+
+//================================================================================
+//  CODING
+
+always	@(posedge	Clk_i)	begin
+	if	(!Rst_i)	begin
+		if	(currState	==	CMD)	begin
+			if	(!txStop)	begin
+				cmdCnt	<=	cmdCnt+1;
+			end else begin
+				cmdCnt <= 0;
+			end
+		end
+	end	else	begin
+		cmdCnt	<=	0;
+	end
+end
+
+always	@(posedge	Clk_i)	begin
+	if	(!Rst_i)	begin
+		if	(currState	==	TX)	begin
+			txCnt	<=	txCnt+1;
+		end	else	begin
+			txCnt	<=	0;
+		end
+	end	else	begin
+		txCnt	<=	0;
+	end
+end
+
+always	@(posedge	Clk_i)	begin
+	if	(!Rst_i)	begin
+		if	(currState	==	PAUSE)	begin
+			pauseCnt	<=	pauseCnt+1;
+		end	else	begin
+			pauseCnt	<=	0;
+		end
+	end	else	begin
+		pauseCnt	<=	0;
+	end
+end
+	
+always	@(posedge	Clk_i)	begin
+	if	(!Rst_i)	begin
+		if	(currState	==	CMD)	begin
+			spiData	<=	spiData+cmdCnt;
+		end
+	end	else	begin
+		spiData	<=	24'hab;
+	end
+end
+
+always	@(posedge	Clk_i)	begin
+	if	(currState	==	CMD)	begin
+		if	(cmdCnt	==	0)	begin
+			dspSpiData		<=	headerCmd;
+		end	else	begin
+			dspSpiData		<=	spiData;
+		end	
+	end	else	if	(currState	==	TX)	begin
+		dspSpiData	<=	dspSpiData<<1;
+	end if	(currState	==	IDLE)	begin
+		dspSpiData	<=	0;
+	end
+end
+
+always	@(posedge Clk_i)	begin
+	if	(currState	==	TX)	begin
+		if	(txCnt	>=	7'd0)	begin
+			Mosi_o	<=	dspSpiData[23];
+		end	else	begin
+			Mosi_o	<=	1'b1;
+		end
+	end	else	begin
+		Mosi_o	<=	1'b1;
+	end
+end
+
+always	@(posedge	Clk_i)	begin
+	if	(currState	==	TX)	begin
+		Ss_o	<=	1'b0;
+		sckFlag	<=	1'b1;
+	end	else	begin
+		Ss_o	<=	1'b1;
+		sckFlag	<=	1'b0;
+	end
+end
+
+always	@(posedge	Clk_i)	begin
+	if	(Rst_i)	begin
+		currState	<=	IDLE;
+	end	else	begin
+		currState	<=	nextState;
+	end
+end
+
+always @(*) begin
+	nextState	=	IDLE;
+	case(currState)
+	IDLE	:	begin
+					if (Start_i)	begin
+						nextState = CMD;
+					end	else begin
+						nextState = IDLE;
+					end
+				end
+				
+	CMD	:		begin
+					if (!txStop)	begin
+						nextState = TX;
+					end	else begin
+						nextState = IDLE;
+					end
+				end
+
+	TX		:	begin
+					if (txCnt==6'd23) begin
+						nextState  = PAUSE;
+					end	else begin
+						nextState  = TX;
+					end
+				end
+        
+	PAUSE	:	begin
+					if (pauseCnt==4'd2) begin
+						nextState  = CMD;
+					end	else begin
+						nextState  = PAUSE;
+					end
+				end
+	endcase
+end
+
+
+
+endmodule
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 51 - 0
src/src/TempRead/SpiReadback.v

@@ -0,0 +1,51 @@
+module SpiReadback (
+
+	input ClkSpi_i,
+	input Rst_i,
+
+	input [23:0] RegData_i,
+
+	input FlagDirect_i,
+
+	output Miso_o
+);
+
+//==========================================
+// Registers
+//==========================================
+reg [23:0] shReg;
+reg	flagSpiSync;
+
+//==========================================
+// Wires
+//==========================================
+
+//==========================================
+// Assignments
+//==========================================
+assign Miso_o = shReg[23];
+
+//////////////////////////////////////////////////////////////////////////////////
+// 									Coding										//
+//////////////////////////////////////////////////////////////////////////////////
+always	@(negedge	ClkSpi_i)	begin
+	if	(!Rst_i)	begin
+		flagSpiSync		<=	FlagDirect_i;
+	end	else	begin
+		flagSpiSync		<=	0;
+	end
+end
+
+always @(negedge ClkSpi_i) begin
+	if (Rst_i) begin
+		shReg <= 0;
+	end
+	else if (FlagDirect_i == 0) begin
+		shReg <= RegData_i;
+	end
+	else if (flagSpiSync == 1) begin
+		shReg <= shReg << 1;
+	end
+end
+
+endmodule

+ 489 - 0
src/src/TempRead/TempI2cMaster.v

@@ -0,0 +1,489 @@
+module TempI2cMaster (
+	i_clk,
+	i_rst_n,
+	i_addr,
+	i_ptr,
+	i_req,
+	o_data,
+	o_data_valid,
+	SCK,
+	SDA
+);
+parameter	CLK_DIV = 100;
+
+parameter	CLK_DIV_HALF = CLK_DIV/2;
+parameter	CLK_DIV_QUA  = CLK_DIV/4;
+	
+parameter	IDLE 		= 4'd0;	
+parameter	START 		= 4'd1;
+parameter	WR_ADDR		= 4'd2;
+parameter	WR_ADDR_A 	= 4'd3;
+parameter	RD_MSB		= 4'd4;
+parameter	RD_MSB_A	= 4'd5;
+parameter	RD_LSB		= 4'd6;
+parameter	RD_LSB_A	= 4'd7;
+parameter	STOP		= 4'd8;
+parameter	DATA_VAL	= 4'd9;
+input	wire		i_clk;
+input	wire		i_rst_n;
+input	wire[2:0]	i_addr;
+input	wire[1:0]	i_ptr;
+input	wire		i_req;
+output	reg	[15:0]	o_data;
+output	reg			o_data_valid;
+output	wire		SCK;
+inout	wire		SDA;
+
+reg	[3:0]	present_state;
+reg	[3:0]	next_state;
+
+reg		sm_en_clk;
+reg		sm_start;
+reg		sm_transfer;
+reg		sm_rd_tr;
+reg		sm_stop;
+reg		sm_data_valid;
+reg		sm_no_ans;
+//in data buf
+reg	[2:0]	i_addr_reg;
+reg			i_req_reg;
+
+
+reg	[7:0]	data_clk_cnt;
+reg	[7:0]	sck_clk_cnt;
+reg	[7:0]	quad_clk_cnt;
+
+reg			data_clk_reg;
+reg			sck_clk_reg;
+reg			quad_clk_reg;
+
+reg			pos_data_clk;
+reg			pos_data_clk_pipe;
+reg			neg_data_clk;
+
+reg			pos_sck_clk;
+reg			neg_sck_clk;
+
+reg			pos_quad_clk;
+reg			neg_quad_clk;
+
+reg			data_clk_cnt_flag;
+reg			sck_clk_cnt_flag;
+reg			quad_clk_cnt_flag;
+
+reg			en_data_clk_cnt;
+reg			en_sck_clk_cnt;
+
+reg			sck_reg;
+reg			sm_stop_pos_data;
+reg	[7:0]	tx_data_sr;
+reg	[2:0]	tr_bit_cnt;
+reg		en_rd_tr;
+reg		tr_bit_cnt_flag;
+reg		stop_flag;
+reg		rd_data_en;
+reg		sm_en_clk_reg;
+reg		sck_clk_reg_out;
+assign	SCK = sck_clk_reg_out;
+assign	SDA = ~en_rd_tr ? sck_reg : 1'bz;
+
+always @(posedge i_clk or negedge i_rst_n) begin
+	if(!i_rst_n) begin
+		o_data_valid <= 1'b0;
+		sm_en_clk_reg <= 1'b0;
+		sck_clk_reg_out <= 1'b1;
+		en_sck_clk_cnt <= 1'b0;
+	end
+	else begin
+		o_data_valid  <= sm_data_valid;
+		sm_en_clk_reg <= sm_en_clk;
+		en_sck_clk_cnt <= sm_en_clk_reg;
+		sck_clk_reg_out <= sck_clk_reg;
+	end
+end
+
+always @(posedge i_clk or negedge i_rst_n) begin
+	if(!i_rst_n) begin
+		data_clk_reg 	<= 1'b0;
+		sck_clk_reg  	<= 1'b1;
+		quad_clk_reg 	<= 1'b0;	
+		en_data_clk_cnt <= 1'b0;
+		pos_quad_clk	<= 1'b0;
+		neg_quad_clk	<= 1'b0;
+	end
+	else if(!sm_en_clk_reg) begin
+		data_clk_reg 	<= 1'b0;
+		sck_clk_reg  	<= 1'b1;
+		quad_clk_reg 	<= 1'b0;	
+		en_data_clk_cnt <= 1'b0;		
+	end
+	else begin
+		pos_quad_clk <= ~quad_clk_reg & quad_clk_cnt_flag;
+		neg_quad_clk <=  quad_clk_reg & quad_clk_cnt_flag;
+		if(pos_quad_clk) begin
+			en_data_clk_cnt <= 1'b1;
+		end
+		if(data_clk_cnt_flag) begin
+			data_clk_reg <= ~data_clk_reg;
+		end
+		if(sck_clk_cnt_flag) begin
+			sck_clk_reg <= ~sck_clk_reg;
+		end
+		if(quad_clk_cnt_flag) begin
+			quad_clk_reg <= ~quad_clk_reg;
+		end
+	end
+end
+
+always @(posedge i_clk or negedge i_rst_n) begin
+	if(!i_rst_n) begin
+		quad_clk_cnt <= 0;
+	end
+	else if (!sm_en_clk_reg || quad_clk_cnt_flag) begin
+		quad_clk_cnt <= 0;
+	end
+	else begin
+		quad_clk_cnt <= quad_clk_cnt + 1;
+	end
+end
+
+always @(posedge i_clk or negedge i_rst_n) begin
+	if(!i_rst_n) begin
+		sck_clk_cnt <= 0;
+	end
+	else if(!en_sck_clk_cnt || sck_clk_cnt_flag) begin
+		sck_clk_cnt <= 0;
+	end
+	else begin
+		sck_clk_cnt <= sck_clk_cnt + 1;
+	end
+end
+
+always @(posedge i_clk or negedge i_rst_n) begin
+	if(!i_rst_n) begin
+		data_clk_cnt <= 0;
+	end
+	else if(!sm_en_clk_reg || data_clk_cnt_flag) begin
+		data_clk_cnt <= 0;
+	end
+	else if(en_data_clk_cnt) begin
+		data_clk_cnt <= data_clk_cnt + 1;
+	end
+end
+
+always @(posedge i_clk or negedge i_rst_n) begin
+	if(!i_rst_n) begin
+		sm_stop_pos_data <= 1'b0;
+	end
+	else if(!sm_en_clk_reg) begin
+		sm_stop_pos_data <= 1'b0;
+	end
+	else if(sm_stop && pos_data_clk) begin
+		sm_stop_pos_data <= 1'b1;
+	end
+end
+
+always @(posedge i_clk or negedge i_rst_n) begin
+	if(!i_rst_n) begin
+		stop_flag <= 1'b0;
+	end
+	else if(!sm_en_clk_reg) begin
+		stop_flag <= 1'b0;
+	end
+	else if(pos_sck_clk & sm_stop_pos_data) begin
+		stop_flag <= 1'b1;
+	end
+end
+
+always @(posedge i_clk or negedge i_rst_n) begin
+	if(!i_rst_n) begin
+		sck_reg <= 1'b1;
+	end
+	else if(!sm_en_clk_reg || pos_data_clk_pipe && sm_no_ans) begin
+		sck_reg <= 1'b1;
+	end
+	else if((pos_quad_clk && sm_start) || (sm_stop && pos_data_clk_pipe)) begin
+		sck_reg <= 1'b0;
+	end
+	else if(pos_data_clk_pipe) begin
+		sck_reg <= tx_data_sr[7];
+	end
+end
+
+always @(posedge i_clk or negedge i_rst_n) begin
+	if(!i_rst_n) begin
+		rd_data_en <= 1'b0;
+	end
+	else if(pos_data_clk_pipe) begin
+		rd_data_en <= sm_transfer & sm_rd_tr;
+	end
+end
+
+always @(posedge i_clk or negedge i_rst_n) begin
+	if(!i_rst_n) begin
+		o_data <= 16'b0;
+	end
+	else if(rd_data_en & pos_sck_clk) begin
+		o_data <= {o_data[14:0], SDA};
+	end
+end
+
+always @(posedge i_clk or negedge i_rst_n) begin
+	if(!i_rst_n) begin
+		tr_bit_cnt_flag <= 1'b0;
+	end
+	else begin
+		tr_bit_cnt_flag <= &tr_bit_cnt;
+	end
+end
+
+always @(posedge i_clk or negedge i_rst_n) begin
+	if(!i_rst_n) begin
+		en_rd_tr <= 1'b0;
+	end
+	else if(sm_rd_tr && pos_data_clk_pipe) begin
+		en_rd_tr <= 1'b1;
+	end
+	else if(pos_data_clk_pipe) begin
+		en_rd_tr <= 1'b0;
+	end
+end
+
+always @(posedge i_clk or negedge i_rst_n) begin
+	if(!i_rst_n) begin
+		tr_bit_cnt <= 3'b0;
+	end
+	else if(!sm_transfer) begin
+		tr_bit_cnt <= 3'b0;
+	end
+	else if(pos_data_clk) begin
+		tr_bit_cnt <= tr_bit_cnt + 3'b1;
+	end
+end
+
+always @(posedge i_clk or negedge i_rst_n) begin
+	if(!i_rst_n) begin
+		tx_data_sr <= 8'b0;
+	end
+	else if(sm_start) begin
+		tx_data_sr[7:0] <= {4'b1001, i_addr_reg[2:0], 1'b1};
+	end
+	else if(pos_data_clk_pipe) begin
+		tx_data_sr <= tx_data_sr << 1;
+	end
+end
+
+always @(posedge i_clk or negedge i_rst_n) begin
+	if(!i_rst_n) begin
+		data_clk_cnt_flag 		<= 1'b0;
+		quad_clk_cnt_flag 		<= 1'b0;
+		pos_data_clk			<= 1'b0;
+		neg_data_clk			<= 1'b0;
+		pos_data_clk_pipe       <= 1'b0;
+	end
+	else begin
+		data_clk_cnt_flag 		<= (data_clk_cnt == CLK_DIV_HALF-2);
+		quad_clk_cnt_flag 		<= (quad_clk_cnt == CLK_DIV_QUA-2);
+		pos_data_clk 			<= data_clk_cnt_flag & ~data_clk_reg;
+		neg_data_clk 			<= data_clk_cnt_flag &  data_clk_reg;
+		pos_data_clk_pipe       <= pos_data_clk;
+	end
+end
+
+always @(posedge i_clk or negedge i_rst_n) begin
+	if(!i_rst_n) begin
+		sck_clk_cnt_flag 	<= 1'b0;
+		pos_sck_clk			<= 1'b0;
+	end
+	else begin
+		sck_clk_cnt_flag 	<= (sck_clk_cnt == CLK_DIV_HALF-2);
+		pos_sck_clk 		<=  sck_clk_cnt_flag & ~sck_clk_reg;
+	end
+end
+//
+always @(posedge i_clk or negedge i_rst_n) begin
+	if(!i_rst_n) begin
+		i_addr_reg <= 3'b0;
+	end
+	else if(i_req) begin
+		i_addr_reg <= i_addr;
+	end
+end
+
+always @(posedge i_clk or negedge i_rst_n) begin
+	if(!i_rst_n) begin
+		i_req_reg <= 1'b0;
+	end
+	else begin
+		i_req_reg <= i_req;
+	end
+end
+
+always @(posedge i_clk or negedge i_rst_n) begin
+	if(!i_rst_n) begin
+		present_state <= IDLE;
+	end
+	else begin
+		present_state <= next_state;
+	end
+end
+
+always @(present_state or i_req_reg or pos_data_clk or neg_data_clk or tr_bit_cnt_flag or stop_flag) begin
+	sm_en_clk 		= 1'b0;
+	sm_start		= 1'b0;
+	sm_transfer		= 1'b0;
+	sm_rd_tr		= 1'b0;
+	sm_stop     	= 1'b0;
+	sm_data_valid 	= 1'b0;
+	sm_no_ans		= 1'b0;
+	next_state 	= IDLE;
+	case(present_state)
+		IDLE : begin
+			sm_en_clk 		= 1'b0;
+			sm_start		= 1'b0;
+			sm_transfer 	= 1'b0;
+			sm_rd_tr		= 1'b0;
+			sm_stop     	= 1'b0;
+			sm_data_valid 	= 1'b0;
+			sm_no_ans		= 1'b0;
+			if(i_req_reg) begin
+				next_state = START;
+			end
+			else begin
+				next_state 	= present_state;
+			end
+		end
+		START : begin
+			sm_en_clk 		= 1'b1;
+			sm_start  		= 1'b1;
+			sm_transfer 	= 1'b0;
+			sm_rd_tr		= 1'b0;
+			sm_stop     	= 1'b0;
+			sm_data_valid 	= 1'b0;
+			sm_no_ans		= 1'b0;
+			if(pos_data_clk) begin
+				next_state = WR_ADDR;
+			end
+			else begin
+				next_state = START;
+			end
+		end
+		WR_ADDR : begin
+			sm_en_clk 		= 1'b1;
+			sm_start  		= 1'b0;
+			sm_transfer 	= 1'b1;
+			sm_rd_tr		= 1'b0;
+			sm_stop     	= 1'b0;
+			sm_data_valid 	= 1'b0;
+			sm_no_ans		= 1'b0;
+			if(tr_bit_cnt_flag && pos_data_clk) begin
+				next_state = WR_ADDR_A;
+			end
+			else begin 
+				next_state = WR_ADDR;
+			end
+		end
+		WR_ADDR_A : begin
+			sm_en_clk 		= 1'b1;
+			sm_start  		= 1'b0;
+			sm_transfer 	= 1'b0;
+			sm_rd_tr		= 1'b1;
+			sm_stop     	= 1'b0;
+			sm_data_valid 	= 1'b0;
+			sm_no_ans		= 1'b0;
+			if(pos_data_clk) begin
+				next_state = RD_MSB;
+			end
+			else begin
+				next_state = WR_ADDR_A;
+			end
+		end
+		RD_MSB : begin
+			sm_en_clk 		= 1'b1;
+			sm_start  		= 1'b0;
+			sm_transfer 	= 1'b1;
+			sm_rd_tr		= 1'b1;
+			sm_stop     	= 1'b0;
+			sm_data_valid 	= 1'b0;
+			sm_no_ans		= 1'b0;
+			if(pos_data_clk && tr_bit_cnt_flag) begin
+				next_state = RD_MSB_A;
+			end
+			else begin
+				next_state  = RD_MSB;
+			end	
+		end
+		RD_MSB_A : begin
+			sm_en_clk 		= 1'b1;
+			sm_start  		= 1'b0;
+			sm_transfer 	= 1'b0;
+			sm_rd_tr		= 1'b0;//1;
+			sm_stop     	= 1'b0;
+			sm_data_valid 	= 1'b0;
+			sm_no_ans		= 1'b0;
+			if(pos_data_clk) begin
+				next_state = RD_LSB;
+			end
+			else begin
+				next_state  = RD_MSB_A;
+			end	
+		end
+		RD_LSB : begin
+			sm_en_clk 		= 1'b1;
+			sm_start  		= 1'b0;
+			sm_transfer 	= 1'b1;
+			sm_rd_tr		= 1'b1;
+			sm_stop     	= 1'b0;
+			sm_data_valid 	= 1'b0;
+			sm_no_ans		= 1'b0;
+			if(pos_data_clk && tr_bit_cnt_flag) begin
+				next_state = RD_LSB_A;
+			end
+			else begin
+				next_state  = RD_LSB;
+			end	
+		end
+		RD_LSB_A : begin
+			sm_en_clk 		= 1'b1;
+			sm_start  		= 1'b0;
+			sm_transfer 	= 1'b0;
+			sm_rd_tr		= 1'b0;
+			sm_stop     	= 1'b0;
+			sm_data_valid 	= 1'b0;
+			sm_no_ans		= 1'b1;
+			if(pos_data_clk) begin
+				next_state = STOP;
+			end
+			else begin
+				next_state  = RD_LSB_A;
+			end			
+		end
+		STOP : begin
+			sm_en_clk 		= 1'b1;
+			sm_start  		= 1'b0;
+			sm_transfer 	= 1'b0;
+			sm_rd_tr		= 1'b0;
+			sm_stop     	= 1'b1;
+			sm_data_valid 	= 1'b0;
+			sm_no_ans		= 1'b0;
+			if(neg_data_clk) begin
+				next_state = DATA_VAL;
+			end
+			else begin
+				next_state  = STOP;
+			end		
+		end
+		DATA_VAL : begin
+			sm_en_clk 		= 1'b0;
+			sm_start  		= 1'b0;
+			sm_transfer 	= 1'b0;
+			sm_rd_tr		= 1'b0;
+			sm_stop     	= 1'b0;
+			sm_data_valid 	= 1'b1;
+			sm_no_ans		= 1'b0;
+			next_state  	= IDLE;
+		end
+	endcase
+end
+
+endmodule

BIN
src/src/TempRead/TempRead.docx


+ 111 - 0
src/src/TempRead/TempRead.v

@@ -0,0 +1,111 @@
+////////////////////////////////////////////////////////////////////////////////////////////
+// Company:			TAIR
+// Engineer:		Zaytsev Mikhail
+// 
+// Create Date:		24/04/2024 
+// Design Name: 
+// Module Name:		TempRead 
+// Project Name:	SB_TMSG44V1_FPGA
+// Target Devices:	Board: SB_TMSG44v1. FPGA: GW1N-LV9PG256C6/I5
+// Tool versions:
+// Description:		The module reads data from the temperature sensor over the 
+//					I2C interface once every 42 µs and sendts the temperaure 
+//					value over the MisoTemp_o line if FlagDirectTempRead is active.
+// Dependencies:	
+// Revision: 
+// Revision 1.0 - File Created
+// Additional Comments: 
+//
+////////////////////////////////////////////////////////////////////////////////////////////
+module TempRead (
+	input Clk24Mhz_i,
+	input Rst_i,
+
+	input ClkSpi_i,
+	input FlagDirectTempRead_i,
+
+	output I2cScl_o,
+	inout I2cSda_io,
+
+	output MisoTemp_o
+);
+
+//==========================================
+// Registers
+//==========================================
+reg tempReq;
+reg [15:0] tempDataReadback;
+reg	[9:0] cntI2c;
+
+//==========================================
+// Wires
+//==========================================
+wire [15:0] tempData;
+wire tempDataValid;
+
+//==========================================
+// Parameters
+//==========================================
+
+//==========================================
+// Assignments
+//==========================================
+
+//==========================================================================//
+//									CODING									//
+//==========================================================================//
+TempI2cMaster TempI2cMaster_inst (
+	.i_clk				(Clk24Mhz_i),
+	.i_rst_n			(~Rst_i),
+	.i_addr				(3'b000),
+	.i_ptr				(2'b00),
+	.i_req				(tempReq),
+	.o_data				(tempData),
+	.o_data_valid		(tempDataValid),
+	.SCK				(I2cScl_o),
+	.SDA				(I2cSda_io)
+);
+
+always @(posedge Clk24Mhz_i) begin
+	if (Rst_i) begin
+		tempDataReadback <= 0;
+	end
+	else if (tempDataValid) begin
+		tempDataReadback[10:0] <= tempData[15:5];
+	end
+end
+
+always @(posedge Clk24Mhz_i) begin
+	if(Rst_i) begin
+		cntI2c <= 0;
+	end 
+	else if(tempDataValid) begin
+		cntI2c <= 0;
+	end 
+	else begin
+		cntI2c <= cntI2c + 1;
+	end
+end
+
+always @(posedge Clk24Mhz_i) begin
+	if (Rst_i) begin
+		tempReq <= 0;
+	end
+	else if (&cntI2c) begin
+		tempReq <= 1;
+	end
+	else begin
+		tempReq <= 0;
+	end
+end
+
+SpiReadback SpiReadback_TempReg (
+	.ClkSpi_i		(ClkSpi_i),
+	.Rst_i			(Rst_i),
+	.RegData_i		( {8'h00, tempDataReadback} ),
+	//.RegData_i	( {8'h00, 16'h9999} ), //for debug
+	.FlagDirect_i	(FlagDirectTempRead_i),
+	.Miso_o			(MisoTemp_o)
+);
+
+endmodule

+ 284 - 0
src/src/TempRead/TempReadTb.v

@@ -0,0 +1,284 @@
+`timescale 1ns / 1ps
+
+//////////////////////////////////////////////////////////////////////////////////
+// Company: Tair
+// Engineer: Zaytsev M.
+// 
+// Create Date:     
+// Design Name: 
+// Module Name:    TempReadTb
+// Project Name: 
+// Target Devices: 
+// Tool versions: 
+// Description: 
+//
+// Dependencies: 
+//
+// Revision: 
+// Revision 0.01 - File Created
+// Additional Comments: 
+//
+//////////////////////////////////////////////////////////////////////////////////
+
+module TempReadTb();
+
+//================================================================================
+//  REG/WIRE
+	
+	parameter OutWordWith = 24;
+	parameter SingleSpiWordWith = 24;
+	parameter QuadSpiWordWith = 6;
+	
+	localparam [1:0] IDLE = 0;
+	localparam [1:0] SINGLE = 1;
+	localparam [1:0] DELAY = 2;
+	localparam [1:0] QUAD = 3;
+	
+	reg SPIMODE = 1'b0; //0 - single 1- quad
+	
+	reg [31:0] tbCnt;
+	reg [31:0] delCnt;
+	reg stateCnt;
+	
+	reg Clk100;
+	reg Clk10;
+
+	reg Clk24;
+	
+	reg [1:0] currState;
+	reg [1:0] nextState;
+	
+	reg rst;
+	reg rstTemp;
+	
+	wire txStart = (tbCnt == 100 | tbCnt == 3000);
+	wire txDoneS;
+	wire txDoneQ;
+	
+	
+	wire sckS;
+	wire sckQ;
+	wire ssS;
+	wire ssQ;
+	
+	wire ss;
+	wire sck;
+	
+	wire mosi0S;
+	wire mosi0Q;
+	wire mosi1Q;
+	wire mosi2Q;
+	wire mosi3Q;
+	
+	wire delDone = (delCnt == 500);
+
+	wire scl_w_tb;
+	wire sda_w_tb;
+//================================================================================
+//  ASSIGNMENTS
+	
+	assign sck = (currState==SINGLE) ? sckS:sckQ;
+	assign ss = (currState==SINGLE) ? ssS:ssQ;
+	assign mosi0 = (currState==SINGLE) ? mosi0S:mosi0Q;
+	assign mosi1 = (currState==SINGLE) ? 1'b1:mosi1Q;
+	assign mosi2 = (currState==SINGLE) ? 1'b1:mosi2Q;
+	assign mosi3 = (currState==SINGLE) ? 1'b1:mosi3Q;
+//================================================================================
+//clocks gen
+	always	#5 Clk100	=	~Clk100;	
+	always	#50 Clk10	=	~Clk10;	
+
+	always	#21 Clk24	=	~Clk24;
+	
+//================================================================================
+//  CODING
+
+initial begin
+	Clk100	=	1'b1;
+	Clk10	=	1'b1;
+	Clk24	= 	1'b1;
+	rst		=	1'b1;
+	rstTemp	=	1'b1;
+#100;
+	rstTemp	=	1'b0;
+#200000
+	rst		=	1'b0;
+end	
+	
+always	@(negedge	Clk100)	begin
+	if	(!rst)		begin
+		tbCnt	<=	tbCnt+1;
+	end	else	begin
+		tbCnt	<=	0;
+	end
+end
+
+always	@(posedge	Clk100)	begin
+	if	(!rst)		begin
+		if (currState == DELAY) begin
+			delCnt	<=	delCnt+1;
+		end	else	begin
+			delCnt	<=	0;
+		end
+	end else	begin
+		delCnt	<=	0;
+	end
+end
+
+always	@(negedge	Clk10)	begin
+	if	(!rst)		begin
+		if (txDoneS|txDoneQ) begin
+			stateCnt	<=	stateCnt+1;
+		end	
+	end else begin
+		stateCnt <= 0;
+	end
+end
+
+always	@(posedge	Clk100)	begin
+	if	(!rst)		begin
+		case (stateCnt)
+			0:	begin
+					SPIMODE <= 1'b0;
+				end
+			1:	begin
+					SPIMODE <= 1'b1;
+				end
+			default:begin
+						SPIMODE <= 1'b0;
+					end
+		endcase
+	end else begin
+		SPIMODE <= 1'b0;
+	end
+end
+
+always	@(posedge	Clk100)	begin
+	if	(rst)	begin
+		currState	<=	IDLE;
+	end	else	begin
+		currState	<=	nextState;
+	end
+end
+
+
+always @(*) begin
+	nextState	=	IDLE;
+	case(currState)
+	IDLE	:	begin
+					if (txStart)	begin
+						case (SPIMODE)
+							1'b0:	begin
+											nextState = SINGLE;
+										end
+							1'b1:		begin
+											nextState = QUAD;
+										end
+						endcase
+					end	else begin
+						nextState = IDLE;
+					end
+				end
+				
+	SINGLE	:	begin
+					if (txDoneS)	begin
+						nextState = DELAY;
+					end	else begin
+						nextState = SINGLE;
+					end
+				end
+				
+	DELAY	:	begin
+					if (delDone)	begin
+						nextState = SINGLE;
+					end	else begin
+						nextState = DELAY;
+					end
+				end
+				
+	QUAD		:	begin
+					if (txDoneQ) begin
+						nextState  = IDLE;
+					end	else begin
+						nextState  = QUAD;
+					end
+				end
+	endcase
+end
+
+ExtSpiMEmul SingleSpiSm
+(
+	.Rst_i		(rst),
+	.Clk_i		(Clk10),
+	
+	.Start_i	((currState==SINGLE)),
+	.TxDone_o	(txDoneS),
+	
+	.Sck_o		(sckS),
+	.Ss_o		(ssS),
+	.Mosi_o		(mosi0S)
+	
+);
+
+wire dataValIntArb;
+wire [23:0] dataFromIntArb;
+wire flagDirectTemp;
+
+InterfaceArbiter InterfaceArbiter
+(
+	.Rst_i		(rst),
+	.Clk_i		(Clk100),
+	
+	.Sck_i		(sck),
+	.Ss_i		(ss),
+	
+	.Mosi0_i	(mosi0),
+	.Mosi1_i	(mosi1),
+	.Mosi2_i	(mosi2),
+	.Mosi3_i	(mosi3),
+	
+	
+	.DataVal_o	(dataValIntArb),
+	.Data_o		(dataFromIntArb)
+);
+
+PacketAnalyzer1Mosi PacketAnalyzer1Mosi_inst (
+	.Clk_i					(Clk100),	
+	.Rst_i					(rst),	
+	
+	.DataFromSpi_i 			(dataFromIntArb),
+	.ValDataFromSpi_i 		(dataValIntArb),
+	
+	.BusyMosi4_i			(0),
+
+	.FlagDirectLmx_o		(),
+	.FlagDirectDds_o		(),
+	.FlagDirectPot_o		(),
+	.FlagDirectDac_o		(),
+	.FlagDirectAtt_o		(),
+	.FlagDirectShReg_o		(),
+	.FlagDirectMax_o		(),
+	.FlagDirectGpio_o		(),
+	.FlagDirectTemp_o		(flagDirectTemp),
+
+	.Busy_o					()
+);
+
+ExtI2cSlaveEmul ExtI2cSlaveEmul_inst (
+	.scl	(scl_w_tb), 
+	.sda	(sda_w_tb)
+);
+
+pullup p2(sda_w_tb); // pullup sda line
+
+TempRead DUT(
+	.Clk24Mhz_i				(Clk24),
+	.Rst_i					(rstTemp),
+	.ClkSpi_i				(sckS),
+	.FlagDirectTempRead_i	(flagDirectTemp),
+	.I2cScl_o				(scl_w_tb),
+	.I2cSda_io				(sda_w_tb),
+	.MisoTemp_o				()
+);
+
+endmodule

+ 32 - 0
src/src/TempRead/TempReadWave.do

@@ -0,0 +1,32 @@
+onerror {resume}
+quietly WaveActivateNextPane {} 0
+add wave -noupdate /TempReadTb/DUT/Clk24Mhz_i
+add wave -noupdate /TempReadTb/DUT/Rst_i
+add wave -noupdate /TempReadTb/DUT/ClkSpi_i
+add wave -noupdate /TempReadTb/DUT/MisoTemp_o
+add wave -noupdate /TempReadTb/DUT/FlagDirectTempRead_i
+add wave -noupdate /TempReadTb/DUT/I2cScl_o
+add wave -noupdate /TempReadTb/DUT/I2cSda_io
+add wave -noupdate /TempReadTb/DUT/tempReq
+add wave -noupdate -radix binary /TempReadTb/DUT/tempDataReadback
+add wave -noupdate /TempReadTb/DUT/cntI2c
+add wave -noupdate -radix binary /TempReadTb/DUT/tempData
+add wave -noupdate /TempReadTb/DUT/tempDataValid
+TreeUpdate [SetDefaultTree]
+WaveRestoreCursors {{Cursor 2} {209858921 ps} 0}
+quietly wave cursor active 1
+configure wave -namecolwidth 150
+configure wave -valuecolwidth 100
+configure wave -justifyvalue left
+configure wave -signalnamewidth 1
+configure wave -snapdistance 10
+configure wave -datasetprefix 0
+configure wave -rowmargin 4
+configure wave -childrowmargin 2
+configure wave -gridoffset 0
+configure wave -gridperiod 1
+configure wave -griddelta 40
+configure wave -timeline 0
+configure wave -timelineunits ns
+update
+WaveRestoreZoom {0 ps} {300946623 ps}