Skip to content

Possible race condition in the sprite rendering state machine #4

@gyurco

Description

@gyurco

Hi!

First thanks for this new core! I'm trying to make it work on MiST-derivate (SiDi128). As it doesn't have a DDR3 RAM, I wrote an emulation module using SDR SDRAM. I noticed in some cases, the last 4 pixels were missing on sprites. It turned out that the last (80th) write to the framebuffer was missing (see the attached trace).
It turned out that in the ST_DRAW_TILE3 state where the shifter is advanced to the last row, if busy is active even for one cycle, then the shifter_done status will be active, without giving a chance to write the last state to the framebuffer. The attached patch solved it for me. Maybe on the Cyclone V DDR3 controller, busy is never activated for writes?
(Sorry for not sending a PR, but I don't have a DE10-nano to test with MiSTer).

diff --git a/rtl/tc0200obj.sv b/rtl/tc0200obj.sv
index 9c16aee..c46c3c5 100644
--- a/rtl/tc0200obj.sv
+++ b/rtl/tc0200obj.sv
@@ -135,7 +135,8 @@ typedef enum
     ST_READ_TILE_WAIT,
     ST_DRAW_TILE1,
     ST_DRAW_TILE2,
-    ST_DRAW_TILE3
+    ST_DRAW_TILE3,
+    ST_DRAW_END
 } draw_state_t;
 
 draw_state_t obj_state = ST_IDLE;
@@ -562,7 +563,6 @@ always @(posedge clk) begin
         ST_DRAW_TILE2: begin
             ddr_obj.acquire <= 1;
             if (~ddr_obj.busy) begin
-                shifter_read <= 1;
                 ddr_obj.addr <= OBJ_FB_DDR_BASE + {13'd0, draw_buffer, shifter_addr, 3'd0 };
                 ddr_obj.burstcnt <= 1;
                 ddr_obj.wdata <= shifter_data;
@@ -571,7 +571,12 @@ always @(posedge clk) begin
 
                 fb_dirty_set_addr <= fb_dirty_draw_addr;
                 fb_dirty_set <= 1;
-                obj_state <= ST_DRAW_TILE3;
+                if (shifter_done)
+                  obj_state <= ST_DRAW_END;
+                else begin
+                  obj_state <= ST_DRAW_TILE3;
+                  shifter_read <= 1;
+                end
             end
         end
 
@@ -581,11 +586,16 @@ always @(posedge clk) begin
             shifter_read <= 0;
             if (~ddr_obj.busy ) begin
                 ddr_obj.write <= 0;
-                if (shifter_done) begin
-                    obj_state <= ST_READ_START;
-                end else begin
-                    obj_state <= ST_DRAW_TILE1;
-                end
+                obj_state <= ST_DRAW_TILE1;
+            end
+        end
+
+        ST_DRAW_END: begin
+            ddr_obj.acquire <= 1;
+            fb_dirty_set <= 0;
+            if (~ddr_obj.busy ) begin
+                ddr_obj.write <= 0;
+                obj_state <= ST_READ_START;
             end
         end
Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions