OpenHBMC icon indicating copy to clipboard operation
OpenHBMC copied to clipboard

ISERDESE2 reset problem

Open mohammadhgh opened this issue 2 years ago • 3 comments

Hello

I use a 64 Mbit Hyper-RAM as Microblaze main memory and use a SREC boot-loader to load the program from a QSPI flash memory. Most of the time everything is OK but in some cases after loading the Hyper-RAM with the application file, reading first instruction from Hyper-RAM fails and program halts.

I captured the issue with ILA core and saw that the problem is because of wrong value (all ones) at the output of the RWDS ISERDESE2. This happens on the first time read after the power up. Sometimes, two clock cycles after reset deassertion, an output of all ones comes out of the RWDS hbmc_iobuf which causes the DRU unit to capture an extra 16-bit word before the actual burst transfer begins.

Screenshot from 2022-07-27 17-08-52

According to UG471,

After deassertion of reset, the output is not valid until after two CLKDIV cycles.

So I added an iserdes_q_invalid flag to ignore the ISERDESE2 output for two clock cycles of iserdes_clkdiv after arst falling edge.

diff --git a/OpenHBMC/hdl/hbmc_iobuf.v b/OpenHBMC/hdl/hbmc_iobuf.v
index 1df7ccf..77296db 100644
--- a/OpenHBMC/hdl/hbmc_iobuf.v
+++ b/OpenHBMC/hdl/hbmc_iobuf.v
@@ -55,6 +55,9 @@ module hbmc_iobuf #
     wire            iserdes_d;
     wire    [5:0]   iserdes_q;
     wire            iserdes_ddly;
+
+    reg             arst_shift_reg      [0:1];
+    wire            iserdes_q_invalid;
     
     
 /*----------------------------------------------------------------------------------------------------------------------------*/
@@ -221,6 +224,24 @@ module hbmc_iobuf #
         .SHIFTIN2       ( 1'b0              )
     );
     
+/*----------------------------------------------------------------------------------------------------------------------------*/
+
+    /* ISERDESE2 reset extender 
+     * According to UG471, ISERDESE2 output is invalid for two clock cycles after reset deassertion.
+     */
+
+    always @(posedge iserdes_clkdiv or posedge arst) begin
+        if (arst) begin
+            arst_shift_reg[0] <= 1'd1;
+            arst_shift_reg[1] <= 1'd1;
+        end else begin
+            arst_shift_reg[0] <= 1'd0;
+            arst_shift_reg[1] <= arst_shift_reg[0];
+        end
+    end
+
+    assign  iserdes_q_invalid = arst_shift_reg[1];
+
 /*----------------------------------------------------------------------------------------------------------------------------*/
     
     /* Register ISERDESE2 output */
@@ -228,7 +249,11 @@ module hbmc_iobuf #
         if (arst) begin
             iserdes_o <= {6{1'b0}};
         end else begin
-            iserdes_o <= iserdes_q;
+            if (iserdes_q_invalid) begin
+                iserdes_o <= {6{1'b0}};
+            end else begin
+                iserdes_o <= iserdes_q;
+            end
         end
     end

This seems to work and the boot problem is now resolved.

@OVGN To solve this I had to deep dive into the code and I have to say you have done a wonderful job, thank you very much for sharing it! :+1:

mohammadhgh avatar Jul 28 '22 09:07 mohammadhgh