aboutsummaryrefslogblamecommitdiff
path: root/src/rtl/coretest.v
blob: 550aafdd7854cf68af297bb45502b8dc8323fdc5 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11










                                                                        



























                                                                           





                                                                        
 



                                                  
 


                                             
 









                                                      
 


                                                                    


                                            


                              



                              









                             
                            

                            
 
                      





                            
 

                                       








                                       




                                       
                                       


                                       

                                       
                                       

 







                                                                    
 




                          
 


                                
 







                           






                                 
 
                       

                      



                                   
 








                                      


                                  

















                                    
 

                                  
 


                                 
                                 
                                 


                                 



                              
 


                             
 


                             
 



                               
 


                                                                    








                               


                               

                      

 










                                                                    
                                                                      
                                                                           
                                                                            

 









                                                                    















                                          
 













                                          
 





                                         
 

                                      
 






                                          
 




                                                 
 


                                              














                                       
 

                           
                                                         
               
 

                           








                                               
               


































                                                
 
                                  
                 
                                                           
               
 
                                  
                 
                                                           
               
 
                               
                 

                                                     
 


                                                     

               
                            
                 
                                               
               
 























                                                     
 




                                                   
 



                                             
 



                                             
 






                                                 








                                                                   

 









                                                                   











                               



                           
                                 



                              









                                                               



                     





                                                       



                     



                                            



                   




                                           




                                                                                  




                                           




                                         
 
                                                                    
                     
    
                                          

                                                                    
                           
                            


                                  
 
                               
             


                                                             
           

                           
 










                                                                    
 
                               
             


                                                             
           
                           
 
 
                                                                    










                                                                    
 




















                                                       

 
                                                                    








                                                                    
                               
 
                            
             

                                                       
           

                                 
             

                                   

                        
 




                                                                    
                                                           



                                                                    





                                     
 




                           





                                           

                 
 

               




                                           
             
 

                

                            


                                        

                                  

             

                
 













                                                                    
                            
                            



                            
 






















                                         
                 







                                        
                 
             
 

                
                                                    




















                                           
 

                

                                  
                                  


                                        
 






                                     

 









                                                                    





















                                        
 


                            
                                 
                   





                                                   

                 
 
                     
               







                                                      
 

                       


                          
                                                 




                                      
                                                   




                                      
                                                   




                                      
                                                     



                                      





































































































































                                                             






                                             
 
 





                                           
 









                                                  
 







                                           
 






                                             
 















                                           
 


                                                 

 





                            
 


                                           

 






                                           
 
                    
















                                            
 



                                                  

                         






                                                  









                                                  











                                              
 
 

                
                                                       





                                        
 




                                                                        
//======================================================================
//
// coretest.v
// ----------
// The Cryptech coretest testing module. Combined with an external
// interface that sends and receives bytes using a SYN-ACK
// handshake and a core to be tested, coretest can parse read
// and write commands needed to test the connected core.
//
//
// Author: Joachim Strombergson
// Copyright (c) 2014, NORDUnet A/S
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// - Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
//
// - Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
//
// - Neither the name of the NORDUnet nor the names of its contributors may
//   be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//======================================================================

module coretest(
                input wire           clk,
                input wire           reset_n,

                // Interface to communication core
                input wire           rx_syn,
                input wire [7 : 0]   rx_data,
                output wire          rx_ack,

                output wire          tx_syn,
                output wire [7 : 0]  tx_data,
                input wire           tx_ack,

                // Interface to the core being tested.
                output wire          core_reset_n,
                output wire          core_cs,
                output wire          core_we,
                output wire [15 : 0] core_address,
                output wire [31 : 0] core_write_data,
                input wire  [31 : 0] core_read_data,
                input wire           core_error
               );


  //----------------------------------------------------------------
  // Internal constant and parameter definitions.
  //----------------------------------------------------------------
  // Max elements in read and write buffers.
  parameter BUFFER_MAX = 4'hf;

  // Command constants.
  parameter SOC       = 8'h55;
  parameter EOC       = 8'haa;
  parameter RESET_CMD = 8'h01;
  parameter READ_CMD  = 8'h10;
  parameter WRITE_CMD = 8'h11;

  // Response constants.
  parameter SOR      = 8'haa;
  parameter EOR      = 8'h55;
  parameter UNKNOWN  = 8'hfe;
  parameter ERROR    = 8'hfd;
  parameter READ_OK  = 8'h7f;
  parameter WRITE_OK = 8'h7e;
  parameter RESET_OK = 8'h7d;

  // rx_engine states.
  parameter RX_IDLE  = 3'h0;
  parameter RX_ACK   = 3'h1;
  parameter RX_NSYN  = 3'h2;

  // tx_engine states.
  parameter TX_IDLE  = 3'h0;
  parameter TX_SYN   = 3'h1;
  parameter TX_NOACK = 3'h2;
  parameter TX_NEXT  = 3'h3;
  parameter TX_SENT  = 3'h4;
  parameter TX_DONE  = 3'h5;

  // test_engine states.
  parameter TEST_IDLE          = 8'h00;
  parameter TEST_GET_CMD       = 8'h10;
  parameter TEST_PARSE_CMD     = 8'h11;
  parameter TEST_GET_ADDR0     = 8'h20;
  parameter TEST_GET_ADDR1     = 8'h21;
  parameter TEST_GET_DATA0     = 8'h24;
  parameter TEST_GET_DATA1     = 8'h25;
  parameter TEST_GET_DATA2     = 8'h26;
  parameter TEST_GET_DATA3     = 8'h27;
  parameter TEST_GET_EOC       = 8'h28;
  parameter TEST_RST_START     = 8'h30;
  parameter TEST_RST_WAIT      = 8'h31;
  parameter TEST_RST_END       = 8'h32;
  parameter TEST_RD_START      = 8'h50;
  parameter TEST_RD_WAIT       = 8'h51;
  parameter TEST_RD_END        = 8'h52;
  parameter TEST_WR_START      = 8'h60;
  parameter TEST_WR_WAIT       = 8'h61;
  parameter TEST_WR_END        = 8'h62;
  parameter TEST_CMD_UNKNOWN   = 8'h80;
  parameter TEST_CMD_ERROR     = 8'h81;
  parameter TEST_SEND_RESPONSE = 8'hc0;


  //----------------------------------------------------------------
  // Registers including update variables and write enable.
  //----------------------------------------------------------------
  reg          rx_syn_reg;

  reg          rx_ack_reg;
  reg          rx_ack_new;
  reg          rx_ack_we;

  reg          tx_syn_reg;
  reg          tx_syn_new;
  reg          tx_syn_we;

  reg          tx_ack_reg;

  reg          core_reset_n_reg;
  reg          core_reset_n_new;
  reg          core_reset_n_we;

  reg          core_cs_reg;
  reg          core_cs_new;
  reg          core_cs_we;

  reg          core_we_reg;
  reg          core_we_new;
  reg          core_we_we;

  reg          send_response_reg;
  reg          send_response_new;
  reg          send_response_we;

  reg          response_sent_reg;
  reg          response_sent_new;
  reg          response_sent_we;

  reg [7 : 0]  cmd_reg;
  reg          cmd_we;

  reg [7 : 0]  core_addr_byte0_reg;
  reg          core_addr_byte0_we;
  reg [7 : 0]  core_addr_byte1_reg;
  reg          core_addr_byte1_we;

  reg [7 : 0]  core_wr_data_byte0_reg;
  reg          core_wr_data_byte0_we;
  reg [7 : 0]  core_wr_data_byte1_reg;
  reg          core_wr_data_byte1_we;
  reg [7 : 0]  core_wr_data_byte2_reg;
  reg          core_wr_data_byte2_we;
  reg [7 : 0]  core_wr_data_byte3_reg;
  reg          core_wr_data_byte3_we;

  reg [31 : 0] core_read_data_reg;
  reg          core_error_reg;
  reg          sample_core_output;

  reg [3 : 0]  rx_buffer_rd_ptr_reg;
  reg [3 : 0]  rx_buffer_rd_ptr_new;
  reg          rx_buffer_rd_ptr_we;
  reg          rx_buffer_rd_ptr_inc;

  reg [3 : 0]  rx_buffer_wr_ptr_reg;
  reg [3 : 0]  rx_buffer_wr_ptr_new;
  reg          rx_buffer_wr_ptr_we;
  reg          rx_buffer_wr_ptr_inc;

  reg [3 : 0]  rx_buffer_ctr_reg;
  reg [3 : 0]  rx_buffer_ctr_new;
  reg          rx_buffer_ctr_we;
  reg          rx_buffer_ctr_inc;
  reg          rx_buffer_ctr_dec;
  reg          rx_buffer_full;
  reg          rx_buffer_empty;

  reg [7 : 0]  rx_buffer [0 : 15];
  reg          rx_buffer_we;

  reg [3 : 0]  tx_buffer_ptr_reg;
  reg [3 : 0]  tx_buffer_ptr_new;
  reg          tx_buffer_ptr_we;
  reg          tx_buffer_ptr_inc;
  reg          tx_buffer_ptr_rst;

  reg [7 : 0]  tx_buffer [0 : 8];
  reg          tx_buffer_we;

  reg [3 : 0]  tx_msg_len_reg;
  reg [3 : 0]  tx_msg_len_new;
  reg          tx_msg_len_we;

  reg [2 : 0]  rx_engine_reg;
  reg [2 : 0]  rx_engine_new;
  reg          rx_engine_we;

  reg [2 : 0]  tx_engine_reg;
  reg [2 : 0]  tx_engine_new;
  reg          tx_engine_we;

  reg [7 : 0]  test_engine_reg;
  reg [7 : 0]  test_engine_new;
  reg          test_engine_we;


  //----------------------------------------------------------------
  // Wires.
  //----------------------------------------------------------------
  reg [7 : 0] tx_buffer_muxed0;
  reg [7 : 0] tx_buffer_muxed1;
  reg [7 : 0] tx_buffer_muxed2;
  reg [7 : 0] tx_buffer_muxed3;
  reg [7 : 0] tx_buffer_muxed4;
  reg [7 : 0] tx_buffer_muxed5;
  reg [7 : 0] tx_buffer_muxed6;
  reg [7 : 0] tx_buffer_muxed7;
  reg [7 : 0] tx_buffer_muxed8;

  reg         update_tx_buffer;
  reg [7 : 0] response_type;

  reg [7 : 0] rx_byte;


  //----------------------------------------------------------------
  // Concurrent connectivity for ports etc.
  //----------------------------------------------------------------
  assign rx_ack          = rx_ack_reg;

  assign tx_syn          = tx_syn_reg;
  assign tx_data         = tx_buffer[tx_buffer_ptr_reg];

  assign core_reset_n    = core_reset_n_reg & reset_n;
  assign core_cs         = core_cs_reg;
  assign core_we         = core_we_reg;
  assign core_address    = {core_addr_byte0_reg, core_addr_byte1_reg};
  assign core_write_data = {core_wr_data_byte0_reg, core_wr_data_byte1_reg,
                            core_wr_data_byte2_reg, core_wr_data_byte3_reg};


  //----------------------------------------------------------------
  // reg_update
  // Update functionality for all registers in the core.
  // All registers are positive edge triggered with synchronous
  // active low reset. All registers have write enable.
  //----------------------------------------------------------------
  always @ (posedge clk)
    begin: reg_update
      if (!reset_n)
        begin
          rx_buffer[0]           <= 8'h00;
          rx_buffer[1]           <= 8'h00;
          rx_buffer[2]           <= 8'h00;
          rx_buffer[3]           <= 8'h00;
          rx_buffer[4]           <= 8'h00;
          rx_buffer[5]           <= 8'h00;
          rx_buffer[6]           <= 8'h00;
          rx_buffer[7]           <= 8'h00;
          rx_buffer[8]           <= 8'h00;
          rx_buffer[9]           <= 8'h00;
          rx_buffer[10]          <= 8'h00;
          rx_buffer[11]          <= 8'h00;
          rx_buffer[12]          <= 8'h00;
          rx_buffer[13]          <= 8'h00;
          rx_buffer[14]          <= 8'h00;
          rx_buffer[15]          <= 8'h00;

          tx_buffer[0]           <= 8'h00;
          tx_buffer[1]           <= 8'h00;
          tx_buffer[2]           <= 8'h00;
          tx_buffer[3]           <= 8'h00;
          tx_buffer[4]           <= 8'h00;
          tx_buffer[5]           <= 8'h00;
          tx_buffer[6]           <= 8'h00;
          tx_buffer[7]           <= 8'h00;
          tx_buffer[8]           <= 8'h00;

          rx_syn_reg             <= 0;
          rx_ack_reg             <= 0;
          tx_ack_reg             <= 0;
          tx_syn_reg             <= 0;

          rx_buffer_rd_ptr_reg   <= 4'h0;
          rx_buffer_wr_ptr_reg   <= 4'h0;
          rx_buffer_ctr_reg      <= 4'h0;

          tx_buffer_ptr_reg      <= 4'h0;
          tx_msg_len_reg         <= 4'h0;

          send_response_reg      <= 0;
          response_sent_reg      <= 0;

          cmd_reg                <= 8'h00;
          core_addr_byte0_reg    <= 8'h00;
          core_addr_byte1_reg    <= 8'h00;
          core_wr_data_byte0_reg <= 8'h00;
          core_wr_data_byte1_reg <= 8'h00;
          core_wr_data_byte2_reg <= 8'h00;
          core_wr_data_byte3_reg <= 8'h00;

          core_reset_n_reg       <= 1;
          core_cs_reg            <= 0;
          core_we_reg            <= 0;
          core_error_reg         <= 0;
          core_read_data_reg     <= 32'h00000000;

          rx_engine_reg          <= RX_IDLE;
          tx_engine_reg          <= TX_IDLE;
          test_engine_reg        <= TEST_IDLE;
        end
      else
        begin
          rx_syn_reg <= rx_syn;
          tx_ack_reg <= tx_ack;

          if (rx_ack_we)
            begin
              rx_ack_reg <= rx_ack_new;
            end

          if (tx_syn_we)
            begin
              tx_syn_reg <= tx_syn_new;
            end

          if (rx_buffer_we)
            begin
              rx_buffer[rx_buffer_wr_ptr_reg] <= rx_data;
            end

          if (tx_buffer_we)
            begin
              tx_buffer[0] <= tx_buffer_muxed0;
              tx_buffer[1] <= tx_buffer_muxed1;
              tx_buffer[2] <= tx_buffer_muxed2;
              tx_buffer[3] <= tx_buffer_muxed3;
              tx_buffer[4] <= tx_buffer_muxed4;
              tx_buffer[5] <= tx_buffer_muxed5;
              tx_buffer[6] <= tx_buffer_muxed6;
              tx_buffer[7] <= tx_buffer_muxed7;
              tx_buffer[8] <= tx_buffer_muxed8;
            end

          if (cmd_we)
            begin
              cmd_reg <= rx_byte;
            end

          if (core_addr_byte0_we)
            begin
              core_addr_byte0_reg <= rx_byte;
            end

          if (core_addr_byte1_we)
            begin
              core_addr_byte1_reg <= rx_byte;
            end

          if (core_wr_data_byte0_we)
            begin
              core_wr_data_byte0_reg <= rx_byte;
            end

          if (core_wr_data_byte1_we)
            begin
              core_wr_data_byte1_reg <= rx_byte;
            end

          if (core_wr_data_byte2_we)
            begin
              core_wr_data_byte2_reg <= rx_byte;
            end

          if (core_wr_data_byte3_we)
            begin
              core_wr_data_byte3_reg <= rx_byte;
            end

          if (rx_buffer_rd_ptr_we)
            begin
              rx_buffer_rd_ptr_reg <= rx_buffer_rd_ptr_new;
            end

          if (rx_buffer_wr_ptr_we)
            begin
              rx_buffer_wr_ptr_reg <= rx_buffer_wr_ptr_new;
            end

          if (rx_buffer_ctr_we)
            begin
              rx_buffer_ctr_reg <= rx_buffer_ctr_new;
            end

          if (tx_buffer_ptr_we)
            begin
              tx_buffer_ptr_reg <= tx_buffer_ptr_new;
            end

          if (tx_msg_len_we)
            begin
              tx_msg_len_reg <= tx_msg_len_new;
            end

          if (core_reset_n_we)
            begin
              core_reset_n_reg <= core_reset_n_new;
            end

          if (core_cs_we)
            begin
              core_cs_reg <= core_cs_new;
            end

          if (core_we_we)
            begin
              core_we_reg <= core_we_new;
            end

          if (send_response_we)
            begin
              send_response_reg <= send_response_new;
            end

          if (response_sent_we)
            begin
              response_sent_reg <= response_sent_new;
            end

          if (sample_core_output)
            begin
              core_error_reg     <= core_error;
              core_read_data_reg <= core_read_data;
            end

          if (rx_engine_we)
            begin
              rx_engine_reg <= rx_engine_new;
            end

          if (tx_engine_we)
            begin
              tx_engine_reg <= tx_engine_new;
            end

          if (test_engine_we)
            begin
              test_engine_reg <= test_engine_new;
            end
        end
    end // reg_update


  //---------------------------------------------------------------
  // read_rx_buffer
  // Combinatinal read mux for the rx_buffer.
  //---------------------------------------------------------------
  always @*
    begin : read_rx_buffer
      rx_byte = rx_buffer[rx_buffer_rd_ptr_reg];
    end // read_rx_buffer


  //---------------------------------------------------------------
  // tx_buffer_logic
  //
  // Update logic for the tx-buffer. Given the response type and
  // the correct contents of the tx_buffer is assembled when
  // and update is signalled by the test engine.
  //---------------------------------------------------------------
  always @*
    begin: tx_buffer_logic
      // Defafult assignments
      tx_buffer_muxed0 = 8'h00;
      tx_buffer_muxed1 = 8'h00;
      tx_buffer_muxed2 = 8'h00;
      tx_buffer_muxed3 = 8'h00;
      tx_buffer_muxed4 = 8'h00;
      tx_buffer_muxed5 = 8'h00;
      tx_buffer_muxed6 = 8'h00;
      tx_buffer_muxed7 = 8'h00;
      tx_buffer_muxed8 = 8'h00;
      tx_msg_len_new   = 4'h0;
      tx_msg_len_we    = 0;
      tx_buffer_we     = 0;

      if (update_tx_buffer)
        begin
          tx_buffer_we = 1;
          tx_buffer_muxed0 = SOR;

          case (response_type)
            READ_OK:
              begin
                tx_buffer_muxed1 = READ_OK;
                tx_buffer_muxed2 = core_addr_byte0_reg;
                tx_buffer_muxed3 = core_addr_byte1_reg;
                tx_buffer_muxed4 = core_read_data_reg[31 : 24];
                tx_buffer_muxed5 = core_read_data_reg[23 : 16];
                tx_buffer_muxed6 = core_read_data_reg[15 :  8];
                tx_buffer_muxed7 = core_read_data_reg[7  :  0];
                tx_buffer_muxed8 = EOR;
                tx_msg_len_new   = 4'h8;
                tx_msg_len_we    = 1;
              end

            WRITE_OK:
              begin
                tx_buffer_muxed1 = WRITE_OK;
                tx_buffer_muxed2 = core_addr_byte0_reg;
                tx_buffer_muxed3 = core_addr_byte1_reg;
                tx_buffer_muxed4 = EOR;
                tx_msg_len_new   = 4'h4;
                tx_msg_len_we    = 1;
              end

            RESET_OK:
              begin
                tx_buffer_muxed1 = RESET_OK;
                tx_buffer_muxed2 = EOR;
                tx_msg_len_new   = 4'h2;
                tx_msg_len_we    = 1;
              end

            ERROR:
              begin
                tx_buffer_muxed1 = ERROR;
                tx_buffer_muxed2 = cmd_reg;
                tx_buffer_muxed3 = EOR;
                tx_msg_len_new   = 4'h3;
                tx_msg_len_we    = 1;
              end

            default:
              begin
                // Any response type not explicitly defined is treated as UNKNOWN.
                tx_buffer_muxed1 = UNKNOWN;
                tx_buffer_muxed2 = cmd_reg;
                tx_buffer_muxed3 = EOR;
                tx_msg_len_new   = 4'h3;
                tx_msg_len_we    = 1;
              end
          endcase // case (response_type)
        end
    end // tx_buffer_logic


  //----------------------------------------------------------------
  // rx_buffer_rd_ptr
  //
  // Logic for the rx buffer read pointer.
  //----------------------------------------------------------------
  always @*
    begin: rx_buffer_rd_ptr
      // Default assignments
      rx_buffer_rd_ptr_new = 4'h0;
      rx_buffer_rd_ptr_we  = 1'b0;
      rx_buffer_ctr_dec    = 0;

      if (rx_buffer_rd_ptr_inc)
        begin
          rx_buffer_ctr_dec    = 1;
          rx_buffer_rd_ptr_new = rx_buffer_rd_ptr_reg + 1'b1;
          rx_buffer_rd_ptr_we  = 1'b1;
        end
    end // rx_buffer_rd_ptr


  //----------------------------------------------------------------
  // rx_buffer_wr_ptr
  //
  // Logic for the rx buffer write pointer.
  //----------------------------------------------------------------
  always @*
    begin: rx_buffer_wr_ptr
      // Default assignments
      rx_buffer_wr_ptr_new = 4'h0;
      rx_buffer_wr_ptr_we  = 1'b0;
      rx_buffer_ctr_inc    = 0;

      if (rx_buffer_wr_ptr_inc)
        begin
          rx_buffer_ctr_inc    = 1;
          rx_buffer_wr_ptr_new = rx_buffer_wr_ptr_reg + 1'b1;
          rx_buffer_wr_ptr_we  = 1'b1;
        end
    end // rx_buffer_wr_ptr


  //----------------------------------------------------------------
  // rx_buffer_ctr
  //
  // Logic for the rx buffer element counter.
  //----------------------------------------------------------------
  always @*
    begin: rx_buffer_ctr
      // Default assignments
      rx_buffer_ctr_new = 4'h0;
      rx_buffer_ctr_we  = 1'b0;
      rx_buffer_empty   = 1'b0;
      rx_buffer_full    = 1'b0;

      if (rx_buffer_ctr_inc)
        begin
          rx_buffer_ctr_new = rx_buffer_ctr_reg + 1'b1;
          rx_buffer_ctr_we  = 1'b1;
        end
      else if (rx_buffer_ctr_dec)
        begin
          rx_buffer_ctr_new = rx_buffer_ctr_reg - 1'b1;
          rx_buffer_ctr_we  = 1'b1;
        end

      if (rx_buffer_ctr_reg == 4'h0)
        begin
          rx_buffer_empty = 1'b1;
        end

      if (rx_buffer_ctr_reg == BUFFER_MAX)
        begin
          rx_buffer_full = 1'b1;
        end
    end // rx_buffer_ctr


  //----------------------------------------------------------------
  // tx_buffer_ptr
  //
  // Logic for the tx buffer pointer. Supports reset and
  // incremental updates.
  //----------------------------------------------------------------
  always @*
    begin: tx_buffer_ptr
      // Default assignments
      tx_buffer_ptr_new = 4'h0;
      tx_buffer_ptr_we  = 1'b0;

      if (tx_buffer_ptr_inc)
        begin
          tx_buffer_ptr_new = tx_buffer_ptr_reg + 1'b1;
          tx_buffer_ptr_we  = 1'b1;
        end

      else if (tx_buffer_ptr_rst)
        begin
          tx_buffer_ptr_new = 4'h0;
          tx_buffer_ptr_we  = 1'b1;
        end
    end // tx_buffer_ptr


  //----------------------------------------------------------------
  // rx_engine
  //
  // FSM responsible for handling receiving message bytes from the
  // host interface and storing them in the receive buffer.
  //----------------------------------------------------------------
  always @*
    begin: rx_engine
      // Default assignments
      rx_ack_new           = 1'b0;
      rx_ack_we            = 1'b0;
      rx_buffer_we         = 1'b0;
      rx_buffer_wr_ptr_inc = 1'b0;
      rx_engine_new        = RX_IDLE;
      rx_engine_we         = 1'b0;

      case (rx_engine_reg)
        RX_IDLE:
          begin
            if (rx_syn_reg)
              begin
                if (!rx_buffer_full)
                  begin
                    rx_buffer_we  = 1'b1;
                    rx_engine_new = RX_ACK;
                    rx_engine_we  = 1'b1;
                  end
              end
          end

        RX_ACK:
          begin
            rx_ack_new           = 1'b1;
            rx_ack_we            = 1'b1;
            rx_buffer_wr_ptr_inc = 1'b1;
            rx_engine_new        = RX_NSYN;
            rx_engine_we         = 1'b1;
          end

        RX_NSYN:
          begin
            if (!rx_syn_reg)
              begin
                rx_ack_new    = 1'b0;
                rx_ack_we     = 1'b1;
                rx_engine_new = RX_IDLE;
                rx_engine_we  = 1;
              end
          end

        default:
          begin

          end
      endcase // case (rx_engine_reg)
    end // rx_engine


  //----------------------------------------------------------------
  // tx_engine
  //
  // FSM responsible for handling transmitting message bytes
  // to the host interface.
  //----------------------------------------------------------------
  always @*
    begin: tx_engine
      // Default assignments
      tx_buffer_ptr_inc = 0;
      tx_buffer_ptr_rst = 0;
      response_sent_new = 0;
      response_sent_we  = 0;
      tx_syn_new        = 0;
      tx_syn_we         = 0;

      tx_engine_new     = TX_IDLE;
      tx_engine_we      = 0;

      case (tx_engine_reg)
        TX_IDLE:
          begin
            if (send_response_reg)
              begin
                tx_syn_new    = 1;
                tx_syn_we     = 1;
                tx_engine_new = TX_SYN;
                tx_engine_we  = 1;
              end
          end

        TX_SYN:
          begin
            if (tx_ack_reg)
              begin
                tx_syn_new    = 0;
                tx_syn_we     = 1;
                tx_engine_new = TX_NOACK;
                tx_engine_we  = 1;
              end
          end

        TX_NOACK:
          begin
            if (!tx_ack_reg)
              begin
                tx_engine_new = TX_NEXT;
                tx_engine_we  = 1;
              end
          end

        TX_NEXT:
          begin
            if (tx_buffer_ptr_reg == tx_msg_len_reg)
              begin
                tx_engine_new = TX_SENT;
                tx_engine_we  = 1;
              end
            else
              begin
                tx_buffer_ptr_inc = 1;
                tx_syn_new        = 1;
                tx_syn_we         = 1;
                tx_engine_new     = TX_SYN;
                tx_engine_we      = 1;
              end
          end

        TX_SENT:
          begin
            response_sent_new = 1;
            response_sent_we  = 1;
            tx_engine_new     = TX_DONE;
            tx_engine_we      = 1;
          end

        TX_DONE:
          begin
            response_sent_new = 0;
            response_sent_we  = 1;
            tx_buffer_ptr_rst = 1;
            tx_engine_new     = TX_IDLE;
            tx_engine_we      = 1;
          end

        default:
          begin
            tx_engine_new = TX_IDLE;
            tx_engine_we  = 1;
          end
      endcase // case (tx_engine_reg)
    end // tx_engine


  //----------------------------------------------------------------
  // test_engine
  //
  // Test engine FSM logic. Parses received commands, tries to
  // execute the commands and assmbles the response to the
  // given commands.
  //----------------------------------------------------------------
  always @*
    begin: test_engine
      // Default assignments.
      core_reset_n_new      = 1;
      core_reset_n_we       = 0;
      core_cs_new           = 0;
      core_cs_we            = 0;
      core_we_new           = 0;
      core_we_we            = 0;
      sample_core_output    = 0;
      update_tx_buffer      = 0;
      response_type         = 8'h00;
      rx_buffer_rd_ptr_inc  = 0;
      cmd_we                = 0;
      core_addr_byte0_we    = 0;
      core_addr_byte1_we    = 0;
      core_wr_data_byte0_we = 0;
      core_wr_data_byte1_we = 0;
      core_wr_data_byte2_we = 0;
      core_wr_data_byte3_we = 0;
      send_response_new     = 0;
      send_response_we      = 0;
      test_engine_new       = TEST_IDLE;
      test_engine_we        = 0;


      case (test_engine_reg)
        TEST_IDLE:
          begin
            if (!rx_buffer_empty)
              begin
                rx_buffer_rd_ptr_inc = 1;
                if (rx_byte == SOC)
                  begin
                    test_engine_new = TEST_GET_CMD;
                    test_engine_we  = 1;
                  end
              end
          end

        TEST_GET_CMD:
          begin
            if (!rx_buffer_empty)
              begin
                rx_buffer_rd_ptr_inc = 1;
                cmd_we               = 1;
                test_engine_new      = TEST_PARSE_CMD;
                test_engine_we       = 1;
              end
          end

        TEST_PARSE_CMD:
          begin
            case (cmd_reg)
              RESET_CMD:
                begin
                  test_engine_new = TEST_GET_EOC;
                  test_engine_we  = 1;
                end

              READ_CMD:
                begin
                  test_engine_new = TEST_GET_ADDR0;
                  test_engine_we  = 1;
                end

              WRITE_CMD:
                begin
                  test_engine_new = TEST_GET_ADDR0;
                  test_engine_we  = 1;
                end

              default:
                begin
                  test_engine_new = TEST_CMD_UNKNOWN;
                  test_engine_we  = 1;
                end
            endcase // case (cmd_reg)
          end


        TEST_GET_ADDR0:
          begin
            if (!rx_buffer_empty)
              begin
                rx_buffer_rd_ptr_inc = 1;
                core_addr_byte0_we   = 1;
                test_engine_new      = TEST_GET_ADDR1;
                test_engine_we       = 1;
              end
          end


        TEST_GET_ADDR1:
          begin
            if (!rx_buffer_empty)
              begin
                rx_buffer_rd_ptr_inc = 1;
                core_addr_byte1_we   = 1;

                case (cmd_reg)
                  READ_CMD:
                    begin
                      test_engine_new = TEST_GET_EOC;
                      test_engine_we  = 1;
                    end

                  WRITE_CMD:
                    begin
                      test_engine_new = TEST_GET_DATA0;
                      test_engine_we  = 1;
                    end

                  default:
                    begin
                      test_engine_new = TEST_CMD_UNKNOWN;
                      test_engine_we  = 1;
                    end
                endcase // case (cmd_reg)
              end
          end


        TEST_GET_DATA0:
          begin
            if (!rx_buffer_empty)
              begin
                rx_buffer_rd_ptr_inc  = 1;
                core_wr_data_byte0_we = 1;
                test_engine_new       = TEST_GET_DATA1;
                test_engine_we        = 1;
              end
          end


        TEST_GET_DATA1:
          begin
            if (!rx_buffer_empty)
              begin
                rx_buffer_rd_ptr_inc  = 1;
                core_wr_data_byte1_we = 1;
                test_engine_new       = TEST_GET_DATA2;
                test_engine_we        = 1;
              end
          end


        TEST_GET_DATA2:
          begin
            if (!rx_buffer_empty)
              begin
                rx_buffer_rd_ptr_inc  = 1;
                core_wr_data_byte2_we = 1;
                test_engine_new       = TEST_GET_DATA3;
                test_engine_we        = 1;
              end
          end


        TEST_GET_DATA3:
          begin
            if (!rx_buffer_empty)
              begin
                rx_buffer_rd_ptr_inc  = 1;
                core_wr_data_byte3_we = 1;
                test_engine_new       = TEST_GET_EOC;
                test_engine_we        = 1;
              end
          end


        TEST_GET_EOC:
          begin
            if (!rx_buffer_empty)
              begin
                rx_buffer_rd_ptr_inc = 1;
                if (rx_byte == EOC)
                  begin
                    case (cmd_reg)
                      RESET_CMD:
                        begin
                          test_engine_new = TEST_RST_START;
                          test_engine_we  = 1;
                        end

                      READ_CMD:
                        begin
                          test_engine_new = TEST_RD_START;
                          test_engine_we  = 1;
                        end

                      WRITE_CMD:
                        begin
                          test_engine_new = TEST_WR_START;
                          test_engine_we  = 1;
                        end

                      default:
                        begin
                          test_engine_new = TEST_CMD_UNKNOWN;
                          test_engine_we  = 1;
                        end
                    endcase // case (cmd_reg)
                  end
                else
                  begin
                    test_engine_new  = TEST_CMD_ERROR;
                    test_engine_we   = 1;
                  end
              end
          end


        TEST_RST_START:
          begin
            core_reset_n_new = 0;
            core_reset_n_we  = 1;
            test_engine_new  = TEST_RST_WAIT;
            test_engine_we   = 1;
          end


        TEST_RST_WAIT:
          begin
            test_engine_new = TEST_RST_END;
            test_engine_we  = 1;
          end


        TEST_RST_END:
          begin
            core_reset_n_new = 1;
            core_reset_n_we  = 1;
            update_tx_buffer = 1;
            response_type    = RESET_OK;
            test_engine_new  = TEST_SEND_RESPONSE;
            test_engine_we   = 1;
          end


        TEST_RD_START:
          begin
            core_cs_new     = 1;
            core_cs_we      = 1;
            test_engine_new = TEST_RD_WAIT;
            test_engine_we  = 1;
          end


        TEST_RD_WAIT:
          begin
            sample_core_output = 1;
            test_engine_new    = TEST_RD_END;
            test_engine_we     = 1;
          end


        TEST_RD_END:
          begin
            core_cs_new        = 0;
            core_cs_we         = 1;
            sample_core_output = 0;

            if (core_error_reg)
              begin
                update_tx_buffer = 1;
                response_type    = ERROR;
              end
            else
              begin
                update_tx_buffer = 1;
                response_type    = READ_OK;
              end

            test_engine_new = TEST_SEND_RESPONSE;
            test_engine_we  = 1;
          end


        TEST_WR_START:
          begin
            core_cs_new = 1;
            core_cs_we  = 1;
            core_we_new = 1;
            core_we_we  = 1;

            test_engine_new = TEST_WR_WAIT;
            test_engine_we  = 1;
          end


        TEST_WR_WAIT:
          begin
            sample_core_output = 1;
            test_engine_new  = TEST_WR_END;
            test_engine_we   = 1;
          end


        TEST_WR_END:
          begin
            core_cs_new        = 0;
            core_cs_we         = 1;
            core_we_new        = 0;
            core_we_we         = 1;
            sample_core_output = 0;

            if (core_error_reg)
              begin
                update_tx_buffer = 1;
                response_type    = ERROR;
              end
            else
              begin
                update_tx_buffer = 1;
                response_type    = WRITE_OK;
              end

            test_engine_new  = TEST_SEND_RESPONSE;
            test_engine_we   = 1;
          end


        TEST_CMD_UNKNOWN:
          begin
            update_tx_buffer = 1;
            response_type    = UNKNOWN;
            test_engine_new  = TEST_SEND_RESPONSE;
            test_engine_we   = 1;
          end


        TEST_CMD_ERROR:
          begin
            update_tx_buffer = 1;
            response_type    = ERROR;
            test_engine_new  = TEST_SEND_RESPONSE;
            test_engine_we   = 1;
          end


        TEST_SEND_RESPONSE:
          begin
            send_response_new = 1;
            send_response_we  = 1;
            if (response_sent_reg)
              begin
                send_response_new = 0;
                send_response_we  = 1;
                test_engine_new   = TEST_IDLE;
                test_engine_we    = 1;
              end
          end


        default:
          begin
            // If we encounter an unknown state we move
            // back to idle.
            test_engine_new = TEST_IDLE;
            test_engine_we  = 1;
          end
      endcase // case (test_engine_reg)
    end // test_engine

endmodule // coretest

//======================================================================
// EOF coretest.v
//======================================================================