0
votes

`timescale 1ns / 1ps

module StateMachine(
   input [1:0] OP,
   input [1:0] RESULT_COM,
   input clk,
   input rst,
   output reg [1:0] CONTROL_AS=0,
   output reg RESET_C,
   output reg  CONTROL_C,
   output reg [1:0] state=0
    );

  parameter toLOWER=2'b01,toUPPER=2'b10,IDLE=0;
    reg [1:0] n_state = IDLE;
    //reg [1:0] state = IDLE;
    reg [1:0] p_state = IDLE;
    reg [1:0] prevOP = 2'b00;
    reg [1:0] p_state_copy = 2'b00;
    reg [15:0] count = 0;

   always @ (posedge clk)
    begin   
     if(rst == 1)
      RESET_C = 1;
     else
      RESET_C = 0;  

      if(OP == 2'b01)
        n_state = toLOWER;
      else 
        if(OP == 2'b10)
        n_state = toUPPER;
      else
        n_state = IDLE;

      if(prevOP == OP)
         p_state = state;

      if((OP != prevOP && OP[0] != OP[1]) || (rst == 1 && (OP != 2'b00 && OP != 2'b11)))
        CONTROL_C = 1;
      else
        CONTROL_C = 0;

      if(state != n_state)      
         prevOP = OP;

      state = n_state;
   end

   always @ (n_state)
    begin
      p_state_copy = p_state;    
    end

   always @ (p_state)
    begin
      case(p_state)
       toLOWER:
         begin
           if(RESULT_COM == 2'b10)
             CONTROL_AS <= 2'b10;
           else
             CONTROL_AS <= 2'b00; 
         end

       toUPPER:
         begin
           if(RESULT_COM == 2'b01)
             CONTROL_AS <= 2'b01;
           else
             CONTROL_AS <= 2'b00; 
         end

       IDLE:
         begin
           if(p_state_copy == toUPPER && RESULT_COM == 2'b01)
              CONTROL_AS <= 2'b01;  
          else if(p_state_copy == toLOWER && RESULT_COM == 2'b10)
               CONTROL_AS <= 2'b10;
          else if(p_state_copy == toUPPER && RESULT_COM == 2'b10)
              CONTROL_AS <= 2'b0; 
          else if(p_state_copy == toLOWER && RESULT_COM == 2'b01)
              CONTROL_AS <= 2'b0;  
          else if(p_state_copy == toUPPER && RESULT_COM == 2'b0)
              CONTROL_AS <= 2'b0; 
           //(p_state_copy == toLOWER && RESULT_COM == 2'b0)
          else CONTROL_AS <= 2'b0; 
         end

      endcase
    end
endmodule    

It is a letter converter. OP is 2 bits input. 11 and 00 means do nothing. 01 load next letter from ROM (using a counter to update the address) and convert to lower case. 10 load next letter and convert to lower case. letter won't be converted if it is not upper or lower case, or it is lower case but OP want to convert it to lower case, etc. If no input (00 or 11) or valid input always asserted (01 or 10), then output remains.

I use the p_state_copy to conserve the previous state and when next clk rising edge comes, it has some part overlap with the state. So it can check whether the previous state is IDDLE (input 00 or 11). RESULT_COM is the result from comparator, which is used to check the letter status. In the picture, hidden part in RESULT is 0 since reset is asserted.enter image description here

I can simulate, synthesize and implement it. But I can not run it on the board. May I know what the problem is? Thank you.

2

2 Answers

0
votes
always @ (n_state)
 begin
   p_state_copy = p_state;    
 end

This logic can't be synthesized. There's no practical way for an FPGA to latch a value (like p_state_copy) on the change of a logic signal (like n_state).

Generally speaking, always blocks in code intended for synthesis on an FPGA should be sensitive to either posedge clk (or some other clock signal) for synchronous blocks, or * for random logic. Specifying individual signals will only get you into trouble.

0
votes

There's several things wrong with this code that will stop it synthesizing properly.

 always @ (posedge clk)
 begin   
   if(rst == 1)
     RESET_C = 1;

should be more like

 always @ (posedge clk or posedge rst)
 if(rst == 1)
   RESET_C = 1;
else
begin

There are several always @(...) sensitivity lists that are incomplete. e.g.

always @ (p_state)
begin
  case(p_state)
   toLOWER:

is missing p_state_copy and RESULT_COM that I've spotted so far. I'd suggest for maintainability either using always @(*) or even better if your tools allow always_comb

But with an incorrect sensitivity list it will almost certainly simulate incorrectly. (the simulation tool will only evaluate the block of code when the specified input changes as opposed to real combinatorial logic which won't make that restriction). For this reason many synthesis engines ignore the sensitivity list.

You're also using non-blocking assignments in a comb logic block, and blocking assignments in a comb logic block.

You're using initial statements on your variable defines. These will be ignored by the synthesis engine.

Further, (rst == 1 && (OP != 2'b00 && OP != 2'b11)) Will not synthesize correctly. You need to stick to the standard flip-flop verilog template if you want it to behave correctly.

These will all cause really wonky simulation results. I think you need to fix these issues first and check if your simulation still behaves as you expect.