Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Does <= (reg) changes value at the same clk posedge or the next clk posedge in simula

Status
Not open for further replies.

promach

Advanced Member level 4
Joined
Feb 22, 2016
Messages
1,199
Helped
2
Reputation
4
Reaction score
5
Trophy points
1,318
Activity points
11,636
Does <= (reg) changes value at the same clk posedge or the next clk posedge in simula

For https://i.imgur.com/P5svAaL.png , I am getting assignment at different clk posedge for https://github.com/promach/UART/blob/development/rtl/Rx/synchronizer.v#L19 and https://github.com/promach/UART/blob/development/rtl/Rx/rx_state.v#L44

Why is that so ?

Screenshot_P5svAaL.png


synchronizer.v

Code:
module synchronizer(clk, reset, serial_in, serial_in_synced);  // 3FF synchronizer

input clk, reset, serial_in;
output reg serial_in_synced; // third FF

reg serial_in_reg, serial_in_reg2;

always @(posedge clk)
begin
	if(reset) begin
		serial_in_reg <= 1;  	// first FF
		serial_in_reg2 <= 1;	// second FF
		serial_in_synced <= 1; // third FF
	end
	
	else begin
		serial_in_reg <= serial_in;  	// first FF
		serial_in_reg2 <= serial_in_reg;	// second FF
		serial_in_synced <= serial_in_reg2; // third FF
	end
end

initial begin
    serial_in_reg = 1;
    serial_in_reg2 = 1;
    serial_in_synced = 1;
end

`ifdef FORMAL
reg first_clock_passed = 0;

always @(posedge clk)	first_clock_passed <= 1;


always @(posedge clk)
begin
	if(reset) begin
    	assert(serial_in_reg == 1);
    	assert(serial_in_reg2 == 1);
    	assert(serial_in_synced == 1);
    end
    
    else begin
    	if(first_clock_passed) begin
			// for induction
			assert(serial_in_reg == $past(serial_in)); 
	 		assert(serial_in_reg2 == $past(serial_in_reg));
	 	end
    end
end
`endif

endmodule


rx_state.v

Code:
module rx_state(clk, reset, start_detected, sampling_strobe, data_is_available, data_is_valid, is_parity_stage, state);  // FSM for UART Rx

parameter INPUT_DATA_WIDTH = 8;
localparam NUMBER_OF_BITS = INPUT_DATA_WIDTH + 3;   // 1 start bit, 8 data bits, 1 parity bit, 1 stop bit

input clk, reset, start_detected, sampling_strobe;
output reg data_is_available;   // in data states
output reg is_parity_stage;
output reg data_is_valid;	// finished all data states
output reg [($clog2(NUMBER_OF_BITS)-1) : 0] state;


localparam Rx_IDLE       = 4'b0000;
localparam Rx_START_BIT  = 4'b0001;
localparam Rx_DATA_BIT_0 = 4'b0010;
localparam Rx_DATA_BIT_1 = 4'b0011;
localparam Rx_DATA_BIT_2 = 4'b0100;
localparam Rx_DATA_BIT_3 = 4'b0101;
localparam Rx_DATA_BIT_4 = 4'b0110;
localparam Rx_DATA_BIT_5 = 4'b0111;
localparam Rx_DATA_BIT_6 = 4'b1000;
localparam Rx_DATA_BIT_7 = 4'b1001;
localparam Rx_PARITY_BIT = 4'b1010;
localparam Rx_STOP_BIT   = 4'b1011;

initial begin
    data_is_available = 0;
    is_parity_stage = 0;
    data_is_valid = 0;
    state = 0;
end

always @(posedge clk)
begin
	if(reset) begin
		data_is_valid <= 0;
		is_parity_stage <= 0;
		data_is_available <= 0;
	end
	
	else begin
    	data_is_valid <= (state == Rx_STOP_BIT);  // so as to align with rx_error
    	is_parity_stage  <= (state == Rx_PARITY_BIT);  // parity state
    	data_is_available <= (sampling_strobe && (state == Rx_START_BIT)) || ((state >= Rx_DATA_BIT_0) && (state <= Rx_DATA_BIT_7)); // data states
    end
end

always @(posedge clk)
begin
    if (reset)
        state <= Rx_IDLE;
    
    else begin
        if (sampling_strobe) begin
            case(state)

				Rx_IDLE			: state <= (start_detected) ? Rx_START_BIT : Rx_IDLE;

	            Rx_START_BIT	: state <= Rx_DATA_BIT_0;

	            Rx_DATA_BIT_0,
	            Rx_DATA_BIT_1,
	            Rx_DATA_BIT_2,	
	            Rx_DATA_BIT_3,
	            Rx_DATA_BIT_4,
	            Rx_DATA_BIT_5,
	            Rx_DATA_BIT_6,
	            Rx_DATA_BIT_7	: state <= state + 1'b1;

	            Rx_PARITY_BIT 	: state <= Rx_STOP_BIT;

	            Rx_STOP_BIT 	: state <= Rx_IDLE;

	            default      	: state <= Rx_IDLE;
            endcase
        end
        
        else begin   // start bit falling edge is detected every clock cycle for better Rx synchronization accuracy
        
            if((state == Rx_IDLE) && (start_detected))
	    	    state <= Rx_START_BIT;
        end
    end
end

`ifdef FORMAL
    
    always @(posedge clk) 
    begin
        assert(state <= Rx_STOP_BIT);
    
    	if(((state == Rx_DATA_BIT_0) && ($past(state) == Rx_DATA_BIT_0)) || ((state > Rx_DATA_BIT_0) && (state <= Rx_DATA_BIT_7))) begin
    		assert(data_is_available);
    	end
    	
        //if (state == Rx_STOP_BIT)
            //assume(reset == 0);  // this is to assume for induction test because Tx internal registers are not reset/initialized properly at time = 0, such that data_is_valid signal will not be asserted in the next clock cycle after the "FIRST" stop bit state
    end
`endif

endmodule
 

Re: Does <= (reg) changes value at the same clk posedge or the next clk posedge in si

assuming that sampling_strobe is connected to serial_in_synced, then next clock edge, as would be expected.
Did you draw the logic for this design on paper?
 

Re: Does <= (reg) changes value at the same clk posedge or the next clk posedge in si

What about data_is_available <= (sampling_strobe && (state == Rx_START_BIT)) || ((state >= Rx_DATA_BIT_0) && (state <= Rx_DATA_BIT_7)); // data states ?

Both registers are assigned the new values at different posedge clk
 

Re: Does <= (reg) changes value at the same clk posedge or the next clk posedge in si

Thats what I was refering to. How do you expect data_is_available to update until sampling_strobe has been updated?
 

Re: Does <= (reg) changes value at the same clk posedge or the next clk posedge in si

@promach: For the simulation waveform, it might be helpful to mentally draw rise/fall time for non-clock signals. Imagine if, instead of rising instantly near the clock edge, the sampling_strobe rose slowly to 1 over maybe half of the clock cycle. Then instead of falling instantly it slowly fell to 0 over some amount of time less than one cycle. With this visualization, it is clear what the value of sampling_strobe is at the clock edge. Over time, you'll get accustomed to how the simulator works and won't need to do this.

Next, you are writing questionable logic for data_is_valid, is_parity_stage, and data_is_available. In your code attempts, you wanted to write code based on the current state, but also have it be registered. This creates a one cycle delay on these three signals. Next, you realized that you could get rid of that one cycle delay for the 0 to 1 transition by regenerating part of the FSM transition logic in the other always block. However, you missed the 1-0 case. Likewise, you also only did your change for data_is_available. This is an issue because it isn't clear to the reader if you are skipping the 1-0 case as an optimization or if there is intended to be different delays for these three registers.

You can solve this by realizing that this style of design is based on transitions -- including the current_state to current_state transition. The coding style you've chosen is also not good for this application. Notice that you are using (sampling_strobe && (state == Rx_START_BIT)) in the output registers' always block. However, this expression really comes from the FSM transition logic for the transition from Rx_START_BIT to Rx_DATA_BIT_0. This means you are regenerating the logic for the transition. This is fine in terms of area/perf, but now the two processes are strongly coupled. It also isn't clear to the reader what your intention is -- especially when there are mismatches like the missing Rx_DATA_BIT_7 to Rx_PARITY_BIT transition logic.

This can be improved by placing the output logic in the FSM switch statement. Some developers don't like this as it can pollute the FSM with extra logic, making the FSM harder to read. The two-process style FSM also solves this problem as it provides next_state logic. Most developers don't like this style as it requires more micromanagement.

Version with 2 process FSM for state/next_state only. This ends up being very clean because the outputs are based on current state, but also need to be registered. Having next_state logic is ideal:
Code:
module rx_state(clk, reset, start_detected, sampling_strobe, data_is_available, data_is_valid, is_parity_stage, state);
  // ... code omitted
  output reg [($clog2(NUMBER_OF_BITS)-1) : 0] state;
  reg        [($clog2(NUMBER_OF_BITS)-1) : 0] next_state;
  // ... code omitted
  always @(posedge clk) begin
    if(reset) begin
      data_is_valid     <= 0;
      is_parity_stage   <= 0;
      data_is_available <= 0;
      state <= Rx_IDLE;
    end else begin
      // it is now easy to define logic based on transitions to/from states.  It is also very clear that you are doing this.
      data_is_valid     <= (next_state == Rx_STOP_BIT);
      is_parity_stage   <= (next_state == Rx_PARITY_BIT);
      data_is_available <= ((next_state >= Rx_DATA_BIT_0) && (next_state <= Rx_DATA_BIT_7));
    end
  end

  always @(*) begin
    // sets the default.  safe to do as subsequent assigns will override this.  This behavior is clear in this case.
    next_state = state;
    if (sampling_strobe) begin
      case(state)
      Rx_IDLE        : next_state = (start_detected) ? Rx_START_BIT : Rx_IDLE;
      Rx_START_BIT   : next_state = Rx_DATA_BIT_0;
      Rx_DATA_BIT_0,
      Rx_DATA_BIT_1,
      Rx_DATA_BIT_2,
      Rx_DATA_BIT_3,
      Rx_DATA_BIT_4,
      Rx_DATA_BIT_5,
      Rx_DATA_BIT_6,
      Rx_DATA_BIT_7  : next_state = state + 1'b1;
      Rx_PARITY_BIT  : next_state = Rx_STOP_BIT;
      Rx_STOP_BIT    : next_state = Rx_IDLE;
      default        : next_state = Rx_IDLE;
      endcase
    end else begin
      if((state == Rx_IDLE) && (start_detected)) begin
        next_state = Rx_START_BIT;
      end
    end
  end
//... code omitted
endmodule


Version with mixture of output assignments within the FSM. I added some commentary about different design choices that could be made. There are other ways people would write this code based on how explicit they want to be.
Code:
module rx_state(clk, reset, start_detected, samplin_strobe, data_is_available, data_is_valid, is_parity_stage, state);
//... code omitted
always @(posede clk) begin
  if (reset) bein
    state <= Rx_IDLE;
    data_is_valid <= 0;
    is_parity_stae   <= 0;
    data_is_available <= 0;
  end else bein
    if (samplin_strobe) begin
      // there are a handful of ways to write this loic.  This style allows the output logic to be
      //iven a zero default.  Some developers do not like this and prefer to place the zero transitions
      // into the switch, or have all outputs defined in all states.  
      data_is_valid <= 1'b0;
      is_parity_stae <= 1'b0;
      data_is_available <= 1'b0;

      case(state)
      Rx_IDLE			  : state <= (start_detected) ? Rx_START_BIT : Rx_IDLE;
      Rx_START_BIT	: bein state <= Rx_DATA_BIT_0; data_is_available <= 1'b1; end
      Rx_DATA_BIT_0,
      Rx_DATA_BIT_1,
      Rx_DATA_BIT_2,	
      Rx_DATA_BIT_3,
      Rx_DATA_BIT_4,
      Rx_DATA_BIT_5,
      // some devs will omit this when outputs don't have the zero-assins above
      Rx_DATA_BIT_6 : bein state <= state + 1'b1; data_is_available <= 1'b1; end
      // some developers will place the 1-0 transition loic in the line below
      Rx_DATA_BIT_7	: bein state <= state + 1'b1; is_parity_stage <= 1'b1; end
      Rx_PARITY_BIT : bein state <= Rx_STOP_BIT; data_is_valid <= 1'b1; end
      Rx_STOP_BIT 	: state <= Rx_IDLE;
      default      	: state <= Rx_IDLE;
      endcase
    end else bein   // start bit falling edge is detected every clock cycle for better Rx synchronization accuracy
      if((state == Rx_IDLE) && (start_detected))
        state <= Rx_START_BIT;
        // these miht also be omitted as reading the code shows that they aren't technically required.
        data_is_valid <= 1'b0;
        is_parity_stae <= 1'b0;
        data_is_available <= 1'b0;
      end
    end
  end
end

endmodule
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top