Self clearing logic with SystemVerilog

Hello ,
I am doing RTL with System Verilog. I am trying to self clear a register bit as below. Here is the code snippet. flag_s is high after 3 clock cycles after flag_d is high. Can you please help to understand why the self clearing logic is not working? And if there is a better way to implement this code please let me know.

typedef struct packed {
    reg [7:1] RSVD;
    reg OFF;  //bit 0
} REGISTER_s;

typedef struct packed  {
     
     REGISTER_s                    REGISTER;
     } type_u; 

typedef union packed {
    reg [0:7][0:7] regs; // "byte view" to the struct, 6 bytes
    type_u fields; // "fields view" to the struct     
} u_control/*synthesis syn_preserve = 1*/;

u_control u_control_i;

if(u_control_i.fields.REGISTER.OFF == 1'b1) begin 
               flag_d <= 1'b1; //setting this flag, writing to _d
           end
            else  begin
                flag_d <= 1'b0; 
            end

            if(flag_s == 1'b1) begin //reading from _s
                u_control_i.fields.REGISTER.OFF <= 1'b0;               
              
            end

In reply to nijo:

Please explain to us what “working” and “not working” is supposed to mean. It would really help to see the declarations of everything in your example.

Did you mean to declare type_u as a packed union.

In reply to dave_59:

Hello Sir,

Thankyou.
I have edited the question to include the packed union definition as well.
Yes type_u is declared as a packed union.

What i meant by not working is this part of the code; the register bit is not getting assigned to 1’b0.

if(flag_s == 1’b1) begin //reading from _s
u_control_i.fields.REGISTER.OFF <= 1’b0;

Can you please help ?

Hello nijo,

The widths of ‘type_u fields’ and ‘reg [0:7][0:7] regs’ do not match. Did you mean to use reg [0:7] regs?

You can learn more about union from the following link:
https://verificationacademy.com/forums/systemverilog/structure-and-union

Please feel free to make a comment.

Thank you,
Paul

The following testbench was created with the 8-bit and the ‘regs’ successfully alternates between 254 and 255 as the flag_s changes.

package top_design_pkg;
  typedef struct packed {
    logic [7:1] RSVD;
    logic OFF;  //bit 0
  } REGISTER_s;
 
  typedef struct packed  {
    REGISTER_s REGISTER;
  } type_u; 
 
  typedef union packed {
    logic [0:7] regs; // "byte view" to the struct, 6 bytes
    type_u fields; // "fields view" to the struct     
  } u_control; //synthesis syn_preserve = 1
endpackage: top_design_pkg
module top_design
  import top_design_pkg::*;
  (input clk,
  input logic flag_s,
  output logic flag_d,
  output u_control u_control_i);

  always_ff @ (posedge clk) begin
    u_control_i.fields.REGISTER.RSVD <= 7'b1111111;
    if(u_control_i.fields.REGISTER.OFF == 1'b1) begin 
      flag_d <= 1'b1; //setting this flag, writing to _d
    end
    else begin
      flag_d <= 1'b0; 
    end
 
    if(flag_s == 1'b1) begin //reading from _s
      u_control_i.fields.REGISTER.OFF <= 1'b0;
    end
    else begin
      u_control_i.fields.REGISTER.OFF <= 1'b1;
    end
   
  end
endmodule
module test();
  import top_design_pkg::*;  
  logic clk;
  logic flag_s;
  logic flag_d;
  u_control u_control_i;

  top_design dut (.clk(clk), .flag_s(flag_s), .flag_d(flag_d), .u_control_i(u_control_i));

  initial begin
    clk <= 0;
    forever #5ns clk = ~clk;
  end

  initial begin
    flag_s = 1'b0; #10;
    for (int i=0; i<10; i=i+1) begin
      flag_s = ~flag_s; #10;
    end
    $finish();
  end
  
  initial begin
    $monitor("%t, flag_s=%b, flag_d=%b, u_con=%p",$realtime, flag_s, flag_d, u_control_i);
  end

endmodule

Result:


#                    0, flag_s=0, flag_d=x, u_con='{regs:x, fields:'{REGISTER:'{RSVD:x, OFF:x}}}
#                    5, flag_s=0, flag_d=0, u_con='{regs:255, fields:'{REGISTER:'{RSVD:127, OFF:1}}}
#                   10, flag_s=1, flag_d=0, u_con='{regs:255, fields:'{REGISTER:'{RSVD:127, OFF:1}}}
#                   15, flag_s=1, flag_d=1, u_con='{regs:254, fields:'{REGISTER:'{RSVD:127, OFF:0}}}
#                   20, flag_s=0, flag_d=1, u_con='{regs:254, fields:'{REGISTER:'{RSVD:127, OFF:0}}}
#                   25, flag_s=0, flag_d=0, u_con='{regs:255, fields:'{REGISTER:'{RSVD:127, OFF:1}}}
#                   30, flag_s=1, flag_d=0, u_con='{regs:255, fields:'{REGISTER:'{RSVD:127, OFF:1}}}
#                   35, flag_s=1, flag_d=1, u_con='{regs:254, fields:'{REGISTER:'{RSVD:127, OFF:0}}}
#                   40, flag_s=0, flag_d=1, u_con='{regs:254, fields:'{REGISTER:'{RSVD:127, OFF:0}}}
#                   45, flag_s=0, flag_d=0, u_con='{regs:255, fields:'{REGISTER:'{RSVD:127, OFF:1}}}
#                   50, flag_s=1, flag_d=0, u_con='{regs:255, fields:'{REGISTER:'{RSVD:127, OFF:1}}}
#                   55, flag_s=1, flag_d=1, u_con='{regs:254, fields:'{REGISTER:'{RSVD:127, OFF:0}}}
#                   60, flag_s=0, flag_d=1, u_con='{regs:254, fields:'{REGISTER:'{RSVD:127, OFF:0}}}
#                   65, flag_s=0, flag_d=0, u_con='{regs:255, fields:'{REGISTER:'{RSVD:127, OFF:1}}}
#                   70, flag_s=1, flag_d=0, u_con='{regs:255, fields:'{REGISTER:'{RSVD:127, OFF:1}}}
#                   75, flag_s=1, flag_d=1, u_con='{regs:254, fields:'{REGISTER:'{RSVD:127, OFF:0}}}
#                   80, flag_s=0, flag_d=1, u_con='{regs:254, fields:'{REGISTER:'{RSVD:127, OFF:0}}}
#                   85, flag_s=0, flag_d=0, u_con='{regs:255, fields:'{REGISTER:'{RSVD:127, OFF:1}}}
#                   90, flag_s=1, flag_d=0, u_con='{regs:255, fields:'{REGISTER:'{RSVD:127, OFF:1}}}
#                   95, flag_s=1, flag_d=1, u_con='{regs:254, fields:'{REGISTER:'{RSVD:127, OFF:0}}}
#                  100, flag_s=0, flag_d=1, u_con='{regs:254, fields:'{REGISTER:'{RSVD:127, OFF:0}}}
#                  105, flag_s=0, flag_d=0, u_con='{regs:255, fields:'{REGISTER:'{RSVD:127, OFF:1}}}

In reply to paupar:
Hi Paul,
Thankyou so much for the right pointer to look at!