瀏覽代碼

Проверка выходных данных с DdsSpiM

Anatoliy Chigirinskiy 5 月之前
父節點
當前提交
b388d99a1b

+ 4 - 4
src/constr/SbTmsg.cst

@@ -1,10 +1,10 @@
-//Copyright (C)2014-2024 Gowin Semiconductor Corporation.
+//Copyright (C)2014-2025 Gowin Semiconductor Corporation.
 //All rights reserved. 
 //All rights reserved. 
 //File Title: Physical Constraints file
 //File Title: Physical Constraints file
-//Tool Version: V1.9.9.03 (64-bit)
+//Tool Version: V1.9.11.02 (64-bit)
 //Part Number: GW1N-LV9PG256C6/I5
 //Part Number: GW1N-LV9PG256C6/I5
 //Device: GW1N-9
 //Device: GW1N-9
-//Created Time: Wed 02 26 18:14:50 2025
+//Created Time: Wed 06 25 12:33:50 2025
 
 
 IO_LOC "FpgaLed_o" L16;
 IO_LOC "FpgaLed_o" L16;
 IO_PORT "FpgaLed_o" IO_TYPE=LVCMOS33 PULL_MODE=UP DRIVE=8 BANK_VCCIO=3.3;
 IO_PORT "FpgaLed_o" IO_TYPE=LVCMOS33 PULL_MODE=UP DRIVE=8 BANK_VCCIO=3.3;
@@ -126,4 +126,4 @@ IO_PORT "Sck_i" IO_TYPE=LVCMOS33 PULL_MODE=UP BANK_VCCIO=3.3;
 IO_LOC "Rst_i" T9;
 IO_LOC "Rst_i" T9;
 IO_PORT "Rst_i" IO_TYPE=LVCMOS33 PULL_MODE=UP BANK_VCCIO=3.3;
 IO_PORT "Rst_i" IO_TYPE=LVCMOS33 PULL_MODE=UP BANK_VCCIO=3.3;
 IO_LOC "Clk_i" H11;
 IO_LOC "Clk_i" H11;
-IO_PORT "Clk_i" IO_TYPE=LVCMOS33 PULL_MODE=UP BANK_VCCIO=3.3;
+IO_PORT "Clk_i" IO_TYPE=LVCMOS33 PULL_MODE=UP BANK_VCCIO=3.3;

+ 14 - 13
src/constr/SbTmsg.sdc

@@ -1,18 +1,19 @@
 //Copyright (C)2014-2025 GOWIN Semiconductor Corporation.
 //Copyright (C)2014-2025 GOWIN Semiconductor Corporation.
 //All rights reserved.
 //All rights reserved.
 //File Title: Timing Constraints file
 //File Title: Timing Constraints file
-//Tool Version: V1.9.11 (64-bit) 
-//Created Time: 2025-06-04 14:02:12
-create_clock -name clk5 -period 200 -waveform {0 100} [get_nets {clk5}]
-create_clock -name clk60 -period 16.667 -waveform {0 8.334} [get_nets {clk60}]
+//Tool Version: V1.9.11.02 (64-bit) 
+//Created Time: 2025-06-25 11:36:44
 create_clock -name Clk_i -period 41.667 -waveform {0 20.834} [get_ports {Clk_i}]
 create_clock -name Clk_i -period 41.667 -waveform {0 20.834} [get_ports {Clk_i}]
-create_clock -name Sck_i -period 10 -waveform {0 5} [get_ports {Sck_i}]
-create_clock -name clk50 -period 20 -waveform {0 10} [get_nets {clk50}]
-set_clock_groups -asynchronous -group [get_clocks {Clk_i}] -group [get_clocks {Sck_i}]
-set_false_path -from [get_clocks {Sck_i}] -to [get_clocks {Clk_i}] 
-set_false_path -from [get_clocks {Sck_i}] -to [get_clocks {Sck_i}] 
-set_false_path -from [get_clocks {Sck_i}] -to [get_clocks {clk60}] 
-set_false_path -from [get_clocks {clk60}] -to [get_clocks {Sck_i}] 
+create_clock -name Sck_i -period 16.667 -waveform {0 8.334} [get_ports {Sck_i}]
+create_generated_clock -name clk50 -source [get_ports {Clk_i}] -master_clock Clk_i -divide_by 12 -multiply_by 25 [get_nets {clk50}]
+create_generated_clock -name clk210 -source [get_ports {Clk_i}] -master_clock Clk_i -divide_by 4 -multiply_by 35 [get_nets {ClkGen/clk210Mhz}]
+create_generated_clock -name clk5 -source [get_ports {Clk_i}] -master_clock Clk_i -divide_by 120 -multiply_by 25 [get_nets {clk5}]
+create_generated_clock -name clk26dot25 -source [get_ports {Clk_i}] -master_clock Clk_i -divide_by 32 -multiply_by 35 [get_nets {clk26dot25}]
+create_generated_clock -name clk20 -source [get_ports {Clk_i}] -master_clock Clk_i -divide_by 30 -multiply_by 25 [get_nets {clk20}]
+create_generated_clock -name clk100 -source [get_ports {Clk_i}] -master_clock Clk_i -divide_by 6 -multiply_by 25 [get_nets {ClkGen/clk100Mhz}]
+create_generated_clock -name clk60 -source [get_ports {Clk_i}] -master_clock Clk_i -divide_by 14 -multiply_by 35 [get_nets {clk60}]
 set_false_path -from [get_regs {InitRst/signal_o_s1}] 
 set_false_path -from [get_regs {InitRst/signal_o_s1}] 
-report_timing -setup -from_clock [get_clocks {clk50}] -to_clock [get_clocks {clk50}]
-report_timing -setup -from_clock [get_clocks {clk60}] -to_clock [get_clocks {clk60}]
+report_timing -setup -max_paths 300 -max_common_paths 1
+report_timing -setup -from_clock [get_clocks {clk60}] -to_clock [get_clocks {clk60}] -max_paths 50
+report_timing -setup -from_clock [get_clocks {clk50}] -to_clock [get_clocks {clk50}] -max_paths 50
+report_timing -setup -from_clock [get_clocks {clk100}] -to_clock [get_clocks {clk100}] -max_paths 50

+ 175 - 0
src/src/CDC/synchronizer.v

@@ -0,0 +1,175 @@
+//---------------------------------------------------
+//------------- BASIC SYNCHRONIZER ------------------
+//---------------------------------------------------
+module basicSynchronizer #
+(	parameter Length = 2)
+(	
+	input Rst_i,	
+	input Clk_i,
+	input D_i,
+	output D_o
+);
+
+	reg [Length-1 : 0] dReg;
+
+	always @ (posedge Rst_i or posedge Clk_i)
+		if (Rst_i)
+			dReg <= 0;
+		else
+			dReg <= {dReg[Length-2 : 0], D_i};
+	
+	assign D_o = dReg[Length - 1];
+	
+endmodule
+
+//---------------------------------------------------
+//--------- EDGE-DETECTING SYNCHRONIZER -------------
+//---------------------------------------------------
+
+module edgeDetectingSynchronizer #
+( 
+	parameter Length = 2,
+	parameter EdgeType = "rising"
+)
+(		
+	input Rst_i,	
+	input Clk_i,
+	input D_i,
+	output D_o
+);
+
+	wire basicSyncOut;
+	reg outReg;
+
+	basicSynchronizer # (.Length(Length)) 
+	basicSynch (
+		.Rst_i(Rst_i),
+		.Clk_i(Clk_i),
+		.D_i(D_i),
+		.D_o(basicSyncOut)
+	);
+		
+	always @ (posedge Rst_i or posedge Clk_i)
+		if (Rst_i)
+			outReg <= 0;
+		else
+			outReg <= basicSyncOut;
+			
+	generate 
+		if (EdgeType == "rising")
+			assign D_o = (basicSyncOut & (~outReg));
+		else
+			assign D_o = ((~basicSyncOut) & (outReg));
+	endgenerate
+	
+endmodule
+
+
+//--------------------------------------------------------------------------
+//------------- FAST-TO-SLOW FREQUENCY DOMAIN SYNCHRONIZER -----------------
+//--------------------------------------------------------------------------
+module fastToSlowSynch
+(		
+	input Rst_i,	
+	input Clk_i,
+	input D_i,
+	output D_o
+);
+
+	reg din_r, dout_r, rsti;
+	
+	wire rsts = (Rst_i || rsti);
+	
+	always @ (posedge rsts or posedge D_i)
+		if (rsts)
+			din_r <= 0;
+		else
+			din_r <= 1;
+			
+	always @ (posedge Rst_i or posedge Clk_i)
+		if (Rst_i)
+			begin
+				dout_r <= 0;
+				rsti <= 0;
+			end
+		else 
+			if (din_r)
+				begin
+					dout_r <= 1;
+					rsti <= 1;
+				end
+			else if (dout_r)
+				begin
+					dout_r <= 0;
+					rsti <= 0;
+				end
+
+	assign D_o = dout_r;	
+	
+endmodule
+
+//--------------------------------------------------------------------------
+//------------- FAST-TO-SLOW FREQUENCY DOMAIN SYNCHRONIZER -----------------
+//--------------------------------------------------------------------------
+module fastToSlowSynchPosPulseStretch #
+(
+	parameter StretchInClock = 2,
+	parameter SyncLength = 2
+)
+(		
+	input Rst_i,
+	input D_i,
+	output D_o,
+	input ClkIn_i,
+	input ClkOut_i
+);
+
+	reg dStretched;
+	generate 
+		if (StretchInClock > 2)
+			begin
+				reg [StretchInClock-2:0] dShReg;
+				always @ (posedge ClkIn_i or posedge Rst_i)
+					if (Rst_i)
+						begin
+							dShReg <= 0;
+							dStretched <= 0;
+						end
+					else
+						begin
+							dShReg <= {dShReg[StretchInClock-3:0], D_i};
+							dStretched <= (D_i || (dShReg != 0)) ? 1 : 0;
+						end
+			end
+		else if (StretchInClock == 2)
+			begin
+				reg dReg;
+				always @ (posedge ClkIn_i or posedge Rst_i)
+					if (Rst_i)
+						begin
+							dReg <= 0;
+							dStretched <= 0;
+						end
+					else
+						begin
+							dReg <= D_i;
+							dStretched <= dReg | D_i;
+						end
+			end
+	endgenerate
+	
+	edgeDetectingSynchronizer #
+	( 
+		.Length(SyncLength),
+		.EdgeType("rising")
+	)
+	edgeSyncInst
+	(		
+		.Rst_i(Rst_i),
+		.Clk_i(ClkOut_i),
+		.D_i(dStretched),
+		.D_o(D_o)
+	);	
+	
+endmodule
+

+ 26 - 4
src/src/InterfaceArbiter/InterfaceArbiter.v

@@ -39,7 +39,7 @@ module InterfaceArbiter
 	input Mosi3_i,
 	input Mosi3_i,
 	
 	
 	
 	
-	output DataVal_o,
+	output reg DataVal_o,
 	output reg TestTrig_o,
 	output reg TestTrig_o,
 	output [OUTWORDWIDTH-1:0] Data_o
 	output [OUTWORDWIDTH-1:0] Data_o
 );
 );
@@ -77,6 +77,8 @@ module InterfaceArbiter
 	reg ssRegRR;
 	reg ssRegRR;
 	
 	
 	reg spiMode;
 	reg spiMode;
+	reg spiModeSyncA;
+	reg spiModeSyncB;
 	
 	
 	wire ssPos;
 	wire ssPos;
 	reg ssPosR;
 	reg ssPosR;
@@ -106,8 +108,8 @@ module InterfaceArbiter
 	assign ssPos = ssRegR & !ssRegRR;
 	assign ssPos = ssRegR & !ssRegRR;
 
 
 	
 	
-	assign DataVal_o = plsToggleSyncSignalR;
-	assign Data_o = (spiMode)? dataRegQSpi:dataRegSSpi;
+	// assign DataVal_o = plsToggleSyncSignalR;
+	assign Data_o = (spiModeSyncB)? dataRegQSpi:dataRegSSpi;
 
 
 	assign plsToggleSyncSignal = plsToggleSyncB^plsToggleSyncA;
 	assign plsToggleSyncSignal = plsToggleSyncB^plsToggleSyncA;
 
 
@@ -116,6 +118,15 @@ module InterfaceArbiter
 //================================================================================
 //================================================================================
 //  CODING
 //  CODING
 
 
+	always @(posedge Clk_i) begin 
+		if (Rst_i) begin 
+			DataVal_o <= 1'b0;
+		end
+		else begin 
+			DataVal_o <= plsToggleSyncSignalR;
+		end
+	end
+
 	always @(posedge Clk_i) begin 
 	always @(posedge Clk_i) begin 
     	if (Rst_i) begin 
     	if (Rst_i) begin 
     	    plsToggleSyncA <= 1'b0;
     	    plsToggleSyncA <= 1'b0;
@@ -277,11 +288,22 @@ module InterfaceArbiter
 			end
 			end
 		end
 		end
 	end
 	end
+
+	always @(posedge Clk_i) begin 
+		if (Rst_i) begin 
+			spiModeSyncA <= 1'b0;
+			spiModeSyncB <= 1'b0;
+		end
+		else begin 
+			spiModeSyncA <= spiMode;
+			spiModeSyncB <= spiModeSyncA;
+		end
+	end
 	
 	
 	always @(posedge Clk_i) begin
 	always @(posedge Clk_i) begin
 		if (!Rst_i) begin
 		if (!Rst_i) begin
 			if (currState == IDLE) begin
 			if (currState == IDLE) begin
-				if (!spiMode) begin
+				if (!spiModeSyncB) begin
 					wordsNum <= dataRegSSpi[17:1];
 					wordsNum <= dataRegSSpi[17:1];
 				end else begin
 				end else begin
 					wordsNum <= dataRegQSpi[21:19]+dataRegQSpi[17:16]+dataRegQSpi[15:12]+dataRegQSpi[11:9]+dataRegQSpi[7:6]+dataRegQSpi[4:3]+dataRegQSpi[2]+dataRegQSpi[1];
 					wordsNum <= dataRegQSpi[21:19]+dataRegQSpi[17:16]+dataRegQSpi[15:12]+dataRegQSpi[11:9]+dataRegQSpi[7:6]+dataRegQSpi[4:3]+dataRegQSpi[2]+dataRegQSpi[1];

+ 120 - 0
src/src/SpiS/SpiSlave.v

@@ -0,0 +1,120 @@
+module SpiSlave#(
+    parameter WIDTH = 80
+)(
+    input Clk_i,
+    input Rst_i,
+
+    input Sck_i,
+    input Ss_i,
+    input Mosi_i,
+
+    output reg [WIDTH-1:0] Data_o,
+    output reg Val_o
+);
+
+//================================================================================
+//	                                REG/WIRE
+//================================================================================
+reg [WIDTH-1:0] dataShiftReg;
+
+reg ssReg;
+reg ssPosedge;
+
+reg plsToggle;
+reg plsToggleSyncA;
+reg plsToggleSyncB;
+reg plsToggleSyncC;
+wire valPulseSync = plsToggleSyncB ^ plsToggleSyncA;
+
+//================================================================================
+//	                                CODE
+//================================================================================
+always @(posedge Clk_i) begin 
+    ssReg <= Ss_i;
+end
+
+always @(posedge Clk_i) begin 
+    if (Rst_i) begin 
+        ssPosedge <= 1'b0;
+    end
+    else begin 
+        if (!ssReg && Ss_i) begin 
+            ssPosedge <= 1'b1;
+        end
+        else if (ssPosedge) begin 
+            ssPosedge <= 1'b0;
+        end
+    end
+end
+
+always @(posedge Clk_i) begin 
+	if (Rst_i) begin 
+	    plsToggleSyncA <= 1'b0;
+	    plsToggleSyncB <= 1'b0;
+	end
+	else begin 
+	    plsToggleSyncA <= plsToggle;
+	    plsToggleSyncB <= plsToggleSyncA;
+	end
+end
+always @(posedge Clk_i) begin 
+    if (Rst_i) begin 
+        plsToggleSyncC <= 1'b0;
+    end
+    else begin
+        plsToggleSyncC <= plsToggleSyncB;
+    end
+end
+
+always @(posedge Ss_i or posedge Rst_i) begin 
+	if (Rst_i) begin 
+		plsToggle <= 1'b0;
+	end
+	else begin 
+		if (Ss_i) begin 
+			plsToggle <= ~plsToggle;
+		end
+		else begin 
+			plsToggle <= plsToggle;
+		end
+	end
+end
+
+always @(posedge Sck_i or posedge Rst_i) begin 
+    if (Rst_i) begin 
+        dataShiftReg <= {WIDTH{1'b0}};
+    end
+    else begin 
+        if (!Ss_i) begin 
+            dataShiftReg <= {dataShiftReg[WIDTH-2:0], Mosi_i};
+        end
+    end
+end
+
+always @(posedge Clk_i) begin 
+    if (Rst_i) begin 
+        Val_o <= 1'b0;
+    end
+    else begin 
+        if (valPulseSync) begin 
+            Val_o <= 1'b1;
+        end
+        else begin
+            Val_o <= 1'b0;
+        end
+    end
+end
+
+always @(posedge Clk_i) begin 
+    if (Rst_i) begin 
+        Data_o <= 1'b0;
+    end
+    else begin 
+        if (valPulseSync) begin 
+            Data_o <= dataShiftReg;
+        end
+    end
+end
+
+
+endmodule

+ 5 - 1
src/src/Top/TopSbTmsg.v

@@ -210,6 +210,8 @@ localparam LED_TICK_RATE = 48000000;//0.5Hz 24MHz
 	reg [31:0] ledCnt;
 	reg [31:0] ledCnt;
 	/* LedReg */
 	/* LedReg */
 	reg ledReg;
 	reg ledReg;
+	/* Result of test */
+	wire resultOfTest;
 
 
 //================================================================================
 //================================================================================
 //  ASSIGNMENTS
 //  ASSIGNMENTS
@@ -245,7 +247,7 @@ assign AnyFlag_o = anyFlag;//Debug-only
 
 
 assign servInfo	= {BOARD_VER, FIRMWARE_VER};
 assign servInfo	= {BOARD_VER, FIRMWARE_VER};
 
 
-assign FpgaLed_o = ledReg;
+assign FpgaLed_o = resultOfTest;
 // assign FpgaLed_o = 1'b1; //Golden-Image
 // assign FpgaLed_o = 1'b1; //Golden-Image
 
 
 //================================================================================
 //================================================================================
@@ -504,6 +506,7 @@ DDSWrapper #(
 	.WrClk_i			(clk60),
 	.WrClk_i			(clk60),
 	.RdClk_i			(clk50),
 	.RdClk_i			(clk50),
 	.Rst_i				(initRst),
 	.Rst_i				(initRst),
+	.RstExt_i			(Rst_i), //External reset for DDS
 	.DdsWordNum_i		(ddsWordNum),
 	.DdsWordNum_i		(ddsWordNum),
 	.DdsWordNumVal_i	( valWordNum && (ddsWordNum != 0)),
 	.DdsWordNumVal_i	( valWordNum && (ddsWordNum != 0)),
 	.DdsDirectFlag_i	(flagDirectDds),
 	.DdsDirectFlag_i	(flagDirectDds),
@@ -511,6 +514,7 @@ DDSWrapper #(
 	.Val_i				(valDdsDataToFifo),
 	.Val_i				(valDdsDataToFifo),
 	.DdsWordNumReg_o	(ddsWordNumReg),
 	.DdsWordNumReg_o	(ddsWordNumReg),
 	.DdsSyncFpga_o		(DdsSyncFpga_o),
 	.DdsSyncFpga_o		(DdsSyncFpga_o),
+	.ResultOfTest_o		(resultOfTest),
 	.Ss_o				(ddsCsSpiM),
 	.Ss_o				(ddsCsSpiM),
 	.Sck_o				(ddsClkSpiM),
 	.Sck_o				(ddsClkSpiM),
 	.Mosi_o				(ddsMosiSpiM)
 	.Mosi_o				(ddsMosiSpiM)

+ 126 - 13
src/src/WrapFifoChain/DDSWrapper.v

@@ -24,6 +24,7 @@ module DDSWrapper #(
     input WrClk_i,
     input WrClk_i,
     input RdClk_i,
     input RdClk_i,
     input Rst_i,
     input Rst_i,
+	input RstExt_i,
 	input [2:0] DdsWordNum_i,
 	input [2:0] DdsWordNum_i,
 	input DdsWordNumVal_i,
 	input DdsWordNumVal_i,
 	input DdsDirectFlag_i,
 	input DdsDirectFlag_i,
@@ -33,6 +34,8 @@ module DDSWrapper #(
 	output reg DdsSyncFpga_o,
 	output reg DdsSyncFpga_o,
 	output [2:0] DdsWordNumReg_o,
 	output [2:0] DdsWordNumReg_o,
 
 
+	output reg ResultOfTest_o,
+
     output Ss_o,
     output Ss_o,
     output Sck_o,
     output Sck_o,
     output Mosi_o
     output Mosi_o
@@ -57,11 +60,24 @@ wire ddsFifoEmpty;
 
 
 reg ssR;
 reg ssR;
 reg ssReg;
 reg ssReg;
-reg ddsDirectFlagR;
+// reg ddsDirectFlagR;
+reg ddsDirectFlagSyncA;
+reg ddsDirectFlagSyncB;
+reg ddsDirectFlagSyncC;
 reg [2:0] ddsWordNumReg;
 reg [2:0] ddsWordNumReg;
-reg [2:0] ddsWordNumRegSync;
+reg [2:0] ddsWordNumRegRdDomain;
+reg [2:0] ddsWordNumRegSyncA;
+reg [2:0] ddsWordNumRegSyncB;
+
 reg [2:0] ddsSyncCnt;
 reg [2:0] ddsSyncCnt;
 
 
+/* WordNumVal Synchronization */
+wire ddsWordNumValSyncRdDomain;
+reg plsToggleWordNumVal;
+reg plsToggleWordNumValSyncA;
+reg plsToggleWordNumValSyncB;
+
+
 reg plsToggle;
 reg plsToggle;
 reg plsToggleSyncA;
 reg plsToggleSyncA;
 reg plsToggleSyncB;
 reg plsToggleSyncB;
@@ -71,6 +87,17 @@ wire [63:0] dataFromDdsFifoCut;
 reg [9:0] parityErrors;      // Ошибки чётности для каждого байта
 reg [9:0] parityErrors;      // Ошибки чётности для каждого байта
 wire [9:0] byteParityBits;   // Вычисленные биты чётности
 wire [9:0] byteParityBits;   // Вычисленные биты чётности
 wire [9:0] storedParityBits; // Сохранённые биты чётности
 wire [9:0] storedParityBits; // Сохранённые биты чётности
+
+// Промежуточные регистры для улучшения тайминга
+reg ssNegEdge;
+reg isLastWord;
+reg directFlagRisingEdge;
+
+reg currentSample;
+
+/* Spi Slave */
+wire valFromSpiSlave;
+wire [79:0] dataFromSpiSlave;
 //================================================================================
 //================================================================================
 //	                                ASSIGNMENTS
 //	                                ASSIGNMENTS
 //================================================================================ 
 //================================================================================ 
@@ -88,9 +115,34 @@ assign byteParityBits[6] = ^dataFromDdsFifo[55:48];
 assign byteParityBits[7] = ^dataFromDdsFifo[63:56];
 assign byteParityBits[7] = ^dataFromDdsFifo[63:56];
 assign byteParityBits[8] = ^dataFromDdsFifo[71:64];
 assign byteParityBits[8] = ^dataFromDdsFifo[71:64];
 assign byteParityBits[9] = ^dataFromDdsFifo[79:72];
 assign byteParityBits[9] = ^dataFromDdsFifo[79:72];
+
+/* ddsWordNumVal Synchronization */
+assign ddsWordNumValSyncRdDomain = plsToggleWordNumValSyncB^plsToggleWordNumValSyncA;
 //==========================================================================//
 //==========================================================================//
 //									CODING									//
 //									CODING									//
 //==========================================================================//
 //==========================================================================//
+always @(posedge WrClk_i) begin 
+	if (Rst_i) begin 
+		plsToggleWordNumVal <= 1'b0;
+	end
+	else if (DdsWordNumVal_i) begin 
+		plsToggleWordNumVal <= ~plsToggleWordNumVal;
+	end
+	else begin 
+		plsToggleWordNumVal <= plsToggleWordNumVal;
+	end
+end
+always @(posedge RdClk_i) begin 
+	if (Rst_i) begin 
+		plsToggleWordNumValSyncA <= 1'b0;
+		plsToggleWordNumValSyncB <= 1'b0;
+	end
+	else begin 
+		plsToggleWordNumValSyncA <= plsToggleWordNumVal;
+		plsToggleWordNumValSyncB <= plsToggleWordNumValSyncA;
+	end
+end
+
 /* Check parity bits */
 /* Check parity bits */
 always @(posedge RdClk_i) begin 
 always @(posedge RdClk_i) begin 
 	if (Rst_i) begin 
 	if (Rst_i) begin 
@@ -114,10 +166,14 @@ end
 
 
 always @(posedge RdClk_i) begin 
 always @(posedge RdClk_i) begin 
 	if (Rst_i) begin 
 	if (Rst_i) begin 
-		ddsDirectFlagR <= 1'b0;
+		ddsDirectFlagSyncA <= 1'b0;
+		ddsDirectFlagSyncB <= 1'b0;
+		ddsDirectFlagSyncC <= 1'b0;
 	end
 	end
 	else begin 
 	else begin 
-		ddsDirectFlagR <= DdsDirectFlag_i;
+		ddsDirectFlagSyncA <= DdsDirectFlag_i;
+		ddsDirectFlagSyncB <= ddsDirectFlagSyncA;
+		ddsDirectFlagSyncC <= ddsDirectFlagSyncB;
 	end
 	end
 end
 end
 
 
@@ -134,6 +190,28 @@ always @(posedge RdClk_i) begin
 	end
 	end
 end
 end
 
 
+// Детекция спадающего фронта SS для улучшения тайминга
+always @(posedge RdClk_i) begin 
+	if (Rst_i) begin 
+		ssNegEdge <= 1'b0;
+	end
+	else begin 
+		ssNegEdge <= (!Ss_o && ssReg);
+	end
+end
+
+// Предварительное вычисление условий для улучшения тайминга
+always @(posedge RdClk_i) begin 
+	if (Rst_i) begin 
+		isLastWord <= 1'b0;
+		directFlagRisingEdge <= 1'b0;
+	end
+	else begin 
+		isLastWord <= (ddsWordNumRegSyncB == 3'h1);
+		directFlagRisingEdge <= (ddsDirectFlagSyncC && !ddsDirectFlagSyncB);
+	end
+end
+
 always @(posedge RdClk_i) begin 
 always @(posedge RdClk_i) begin 
 	if (Rst_i) begin 
 	if (Rst_i) begin 
 		plsToggle <= 1'b0;
 		plsToggle <= 1'b0;
@@ -175,10 +253,12 @@ end
 
 
 always @(posedge RdClk_i) begin 
 always @(posedge RdClk_i) begin 
 	if (Rst_i) begin 
 	if (Rst_i) begin 
-		ddsWordNumRegSync <= 3'h0;
+		ddsWordNumRegSyncA <= 3'h0;
+		ddsWordNumRegSyncB <= 3'h0;
 	end
 	end
 	else begin 
 	else begin 
-		ddsWordNumRegSync <= ddsWordNumReg;
+		ddsWordNumRegSyncA <= ddsWordNumReg;
+		ddsWordNumRegSyncB <= ddsWordNumRegSyncA;
 	end
 	end
 end
 end
 
 
@@ -187,19 +267,40 @@ always @(posedge RdClk_i) begin
 		DdsSyncFpga_o <= 1'b0;
 		DdsSyncFpga_o <= 1'b0;
 	end
 	end
 	else begin
 	else begin
-		if (ddsDirectFlagR && !DdsDirectFlag_i) begin 
-				DdsSyncFpga_o <= 1'b1;
+		if (directFlagRisingEdge) begin 
+			DdsSyncFpga_o <= 1'b1;
 		end 
 		end 
-		else if ((!Ss_o && ssReg) && (ddsWordNumRegSync != 0)) begin 
+		else if (ssNegEdge && (ddsWordNumRegSyncB != 0)) begin 
 			DdsSyncFpga_o <= 1'b0;
 			DdsSyncFpga_o <= 1'b0;
 		end
 		end
+		else if (isLastWord && ssPosEdge) begin 
+			DdsSyncFpga_o <= 1'b1;
+		end
 		else begin 
 		else begin 
-			if (ddsWordNumRegSync == 3'h1 && (Ss_o && !ssReg)) begin 
-				DdsSyncFpga_o <= 1'b1;
+			DdsSyncFpga_o <= DdsSyncFpga_o; // Удерживаем состояние
+		end
+	end
+end
+
+/* Spi Master Check */
+always @(posedge RdClk_i) begin 
+	if (RstExt_i) begin
+		ResultOfTest_o <= 1'b0;
+		currentSample <= 1'b0;
+	end
+	else begin
+		if (valFromSpiSlave) begin 
+			if ((currentSample == 0) && dataFromSpiSlave == 80'hAAAAAAAAAAAAAAAAAAAA ) begin 
+				currentSample <= 1'b1;
+				ResultOfTest_o <= 1'b0;
 			end
 			end
-			else begin 
-				DdsSyncFpga_o <= 1'b0;
+			else if ((currentSample == 1) && dataFromSpiSlave == 80'h55555555555555555555 ) begin 
+				currentSample <= 1'b0;
+				ResultOfTest_o <= 1'b0;
 			end
 			end
+			else begin 
+				ResultOfTest_o <= 1'b1; // Ошибка, данные не совпадают
+			end  
 		end
 		end
 	end
 	end
 end
 end
@@ -252,4 +353,16 @@ SpiM #(
 	.Sck_o		(Sck_o)
 	.Sck_o		(Sck_o)
 );
 );
 
 
+SpiSlave #(
+	.WIDTH		(OUT_WIDTH)
+) SpiS_inst (
+	.Clk_i		(RdClk_i),
+	.Rst_i		(Rst_i),
+	.Ss_i		(Ss_o),
+	.Mosi_i		(Mosi_o),
+	.Sck_i		(Sck_o),
+	.Val_o		(valFromSpiSlave),
+	.Data_o		(dataFromSpiSlave)
+);
+
 endmodule
 endmodule

+ 11 - 4
src/src/WrapFifoChain/LmxWrapper.v

@@ -59,7 +59,10 @@ reg plsToggleSyncB;
 
 
 reg ssR;
 reg ssR;
 reg ssReg;
 reg ssReg;
-reg ssRegDds;
+// reg ssRegDds;
+reg ssDdsSyncA;
+reg ssDdsSyncB;
+reg ssDdsSyncC;
 reg [3:0] lmxWordNumReg; 
 reg [3:0] lmxWordNumReg; 
 reg [3:0] lmxWordNumRegR;
 reg [3:0] lmxWordNumRegR;
 //==========================================================================//
 //==========================================================================//
@@ -112,10 +115,14 @@ end
 
 
 always @(posedge RdClk_i) begin 
 always @(posedge RdClk_i) begin 
 	if (Rst_i) begin 
 	if (Rst_i) begin 
-		ssRegDds <= 1'b0;
+		ssDdsSyncA <= 1'b0;
+		ssDdsSyncB <= 1'b0;
+		ssDdsSyncC <= 1'b0;
 	end
 	end
 	else begin 
 	else begin 
-		ssRegDds <= DdsCs_i;
+		ssDdsSyncA <= DdsCs_i;
+		ssDdsSyncB <= ssDdsSyncA;
+		ssDdsSyncC <= ssDdsSyncB;
 	end
 	end
 end
 end
 
 
@@ -144,7 +151,7 @@ always @(posedge RdClk_i) begin
 			if ((lmxWordNumReg == 0) && (DdsWordNumReg_i == 0)) begin
 			if ((lmxWordNumReg == 0) && (DdsWordNumReg_i == 0)) begin
 				PllVtuneCtrl_o <= 1'b1;
 				PllVtuneCtrl_o <= 1'b1;
 			end
 			end
-			else if ((!DdsCs_i && ssRegDds) && (DdsWordNumReg_i != 0)) begin 
+			else if ((!ssDdsSyncC && ssDdsSyncB ) && (DdsWordNumReg_i != 0)) begin 
 				PllVtuneCtrl_o <= 1'b0;
 				PllVtuneCtrl_o <= 1'b0;
 			end
 			end
 			else if ((!Ss_o && ssReg) && (lmxWordNumReg != 0) ) begin 
 			else if ((!Ss_o && ssReg) && (lmxWordNumReg != 0) ) begin