[Cryptech-Commits] [core/coretest] 01/01: Adding source files for coretest.

git at cryptech.is git at cryptech.is
Thu Mar 13 13:51:11 UTC 2014


This is an automated email from the git hooks/post-receive script.

joachim at secworks.se pushed a commit to branch master
in repository core/coretest.

commit 040614752772141d1541068e2d05eef72cda5c43
Author: Joachim Strömbergson <joachim at secworks.se>
Date:   Thu Mar 13 14:51:02 2014 +0100

    Adding source files for coretest.
---
 src/rtl/coretest.v   | 897 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/sw/seriedebug.py | 118 +++++++
 src/tb/tb_coretest.v | 362 +++++++++++++++++++++
 3 files changed, 1377 insertions(+)

diff --git a/src/rtl/coretest.v b/src/rtl/coretest.v
new file mode 100644
index 0000000..92fab28
--- /dev/null
+++ b/src/rtl/coretest.v
@@ -0,0 +1,897 @@
+//======================================================================
+//
+// 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 SUNET
+// 
+// Redistribution and use in source and binary forms, with or 
+// without modification, are permitted provided that the following 
+// conditions are met: 
+// 
+// 1. Redistributions of source code must retain the above copyright 
+//    notice, this list of conditions and the following disclaimer. 
+// 
+// 2. 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. 
+// 
+// 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 OWNER 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.
+  //----------------------------------------------------------------
+  // 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_SYN  = 3'h1;
+  parameter RX_ACK  = 3'h2;
+  parameter RX_CMD  = 3'h3;
+  parameter RX_DONE = 3'h4;
+
+  // rx_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_PARSE_CMD     = 8'h10;
+  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_UNKNOWN       = 8'h80;
+  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          cmd_available_reg;
+  reg          cmd_available_new;
+  reg          cmd_available_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 [15 : 0] core_address_reg;
+  reg [31 : 0] core_write_data_reg;
+  reg [31 : 0] core_read_data_reg;
+  reg          core_error_reg;
+  reg          sample_core_output;
+  
+  reg [3 : 0]  rx_buffer_ptr_reg;
+  reg [3 : 0]  rx_buffer_ptr_new;
+  reg          rx_buffer_ptr_we;
+  reg          rx_buffer_ptr_rst;
+  reg          rx_buffer_ptr_inc;
+  
+  reg [3 : 0]  tx_buffer_ptr_reg;
+  reg [3 : 0]  tx_buffer_ptr_new;
+  reg          tx_buffer_ptr_we;
+  reg          tx_buffer_ptr_rst;
+  reg          tx_buffer_ptr_inc;
+  
+  reg [7 : 0]  rx_buffer [0 : 8];
+  reg          rx_buffer_we;
+
+  reg [7 : 0]  tx_buffer [0 : 8];
+  reg          tx_buffer_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_buffert_muxed0;
+  reg [7 : 0] tx_buffert_muxed1;
+  reg [7 : 0] tx_buffert_muxed2;
+  reg [7 : 0] tx_buffert_muxed3;
+  reg [7 : 0] tx_buffert_muxed4;
+  reg [7 : 0] tx_buffert_muxed5;
+  reg [7 : 0] tx_buffert_muxed6;
+  reg [7 : 0] tx_buffert_muxed7;
+  reg [7 : 0] tx_buffert_muxed8;
+
+  reg extract_cmd_fields;
+
+  reg         update_tx_buffer;
+  reg [7 : 0] response_type;
+                
+  reg          cmd_accepted;
+  
+  
+  //----------------------------------------------------------------
+  // 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_address_reg;
+  assign core_write_data = core_write_data_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;
+          
+          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_ptr_reg   <= 4'h0;
+          tx_buffer_ptr_reg   <= 4'h0;
+
+          send_response_reg   <= 0;
+          response_sent_reg   <= 0;
+          
+          cmd_reg             <= 8'h00;
+          cmd_available_reg   <= 0;
+          
+          core_reset_n_reg    <= 1;
+          core_cs_reg         <= 0;
+          core_we_reg         <= 0;
+          core_error_reg      <= 0;
+          core_address_reg    <= 16'h0000;
+          core_write_data_reg <= 32'h00000000;
+          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_ptr_reg] <= rx_data;
+            end
+          
+          if (tx_buffer_we)
+            begin
+              tx_buffer[0] <= tx_buffert_muxed0;
+              tx_buffer[1] <= tx_buffert_muxed1;
+              tx_buffer[2] <= tx_buffert_muxed2;
+              tx_buffer[3] <= tx_buffert_muxed3;
+              tx_buffer[4] <= tx_buffert_muxed4;
+              tx_buffer[5] <= tx_buffert_muxed5;
+              tx_buffer[6] <= tx_buffert_muxed6;
+              tx_buffer[7] <= tx_buffert_muxed7;
+              tx_buffer[8] <= tx_buffert_muxed8;
+            end 
+          
+          if (rx_buffer_ptr_we)
+            begin
+              rx_buffer_ptr_reg <= rx_buffer_ptr_new;
+            end
+          
+          if (tx_buffer_ptr_we)
+            begin
+              tx_buffer_ptr_reg <= tx_buffer_ptr_new;
+            end
+
+          if (extract_cmd_fields)
+            begin
+              cmd_reg             <= rx_buffer[1];
+              core_address_reg    <= {rx_buffer[2], rx_buffer[3]};
+              core_write_data_reg <= {rx_buffer[4], rx_buffer[5], 
+                                      rx_buffer[6], rx_buffer[7]};
+            end
+
+          if (cmd_available_we)
+            begin
+              cmd_available_reg <= cmd_available_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
+
+  
+  //---------------------------------------------------------------
+  // 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_buffert_muxed0 = 8'h00;
+      tx_buffert_muxed1 = 8'h00;
+      tx_buffert_muxed2 = 8'h00;
+      tx_buffert_muxed3 = 8'h00;
+      tx_buffert_muxed4 = 8'h00;
+      tx_buffert_muxed5 = 8'h00;
+      tx_buffert_muxed6 = 8'h00;
+      tx_buffert_muxed7 = 8'h00;
+      tx_buffert_muxed8 = 8'h00;
+
+      tx_buffer_we      = 0;
+
+      if (update_tx_buffer)
+        begin
+          tx_buffer_we = 1;
+          tx_buffert_muxed0 = SOR;
+
+          case (response_type)
+            READ_OK:
+              begin
+                tx_buffert_muxed1 = READ_OK;
+                tx_buffert_muxed2 = core_address_reg[15 : 8];
+                tx_buffert_muxed3 = core_address_reg[7  : 0];
+                tx_buffert_muxed4 = core_read_data_reg[31 : 24];
+                tx_buffert_muxed5 = core_read_data_reg[23 : 16];
+                tx_buffert_muxed6 = core_read_data_reg[15 :  8];
+                tx_buffert_muxed7 = core_read_data_reg[7  :  0];
+                tx_buffert_muxed8 = EOR;
+              end
+
+            WRITE_OK:
+              begin
+                tx_buffert_muxed1 = WRITE_OK;
+                tx_buffert_muxed2 = core_address_reg[15 : 8];
+                tx_buffert_muxed3 = core_address_reg[7  : 0];
+                tx_buffert_muxed4 = EOR;
+              end
+
+            RESET_OK:
+              begin
+                tx_buffert_muxed1 = RESET_OK;
+                tx_buffert_muxed2 = EOR;
+              end
+
+            ERROR:
+              begin
+                tx_buffert_muxed1 = ERROR;
+                tx_buffert_muxed2 = cmd_reg;
+                tx_buffert_muxed3 = EOR;
+              end
+
+            default:
+              begin
+                // Any response type not explicitly defined is treated as UNKNOWN.
+                tx_buffert_muxed1 = UNKNOWN;
+                tx_buffert_muxed2 = cmd_reg;
+                tx_buffert_muxed3 = EOR;
+              end
+          endcase // case (response_type)
+        end
+    end // tx_buffer_logic
+
+  
+  //----------------------------------------------------------------
+  // rx_buffer_ptr
+  //
+  // Logic for the rx buffer pointer. Supports reset and
+  // incremental updates.
+  //----------------------------------------------------------------
+  always @*
+    begin: rx_buffer_ptr
+      // Default assignments
+      rx_buffer_ptr_new = 4'h0;
+      rx_buffer_ptr_we  = 0;
+      
+      if (rx_buffer_ptr_rst)
+        begin
+          rx_buffer_ptr_new = 4'h0;
+          rx_buffer_ptr_we  = 1;
+        end
+      
+      else if (rx_buffer_ptr_inc)
+        begin
+          rx_buffer_ptr_new = rx_buffer_ptr_reg + 1'b1;
+          rx_buffer_ptr_we  = 1;
+        end
+    end // rx_buffer_ptr
+
+  
+  //----------------------------------------------------------------
+  // 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  = 0;
+      
+      if (tx_buffer_ptr_rst)
+        begin
+          tx_buffer_ptr_new = 4'h0;
+          tx_buffer_ptr_we  = 1;
+        end
+      
+      else if (tx_buffer_ptr_inc)
+        begin
+          tx_buffer_ptr_new = tx_buffer_ptr_reg + 1'b1;
+          tx_buffer_ptr_we  = 1;
+        end
+    end // tx_buffer_ptr
+  
+
+  //----------------------------------------------------------------
+  // rx_engine
+  //
+  // FSM responsible for handling receiving message bytes from the
+  // host interface and signalling the test engine that there is
+  // a new command to be executed.
+  //----------------------------------------------------------------
+  always @*
+    begin: rx_engine
+      // Default assignments
+      rx_ack_new        = 0;
+      rx_ack_we         = 0;
+      rx_buffer_we      = 0;
+      rx_buffer_ptr_rst = 0;
+      rx_buffer_ptr_inc = 0;
+      cmd_available_new = 0;
+      cmd_available_we  = 0;
+      rx_engine_new     = RX_IDLE;
+      rx_engine_we      = 0;
+      
+      case (rx_engine_reg)
+        RX_IDLE:
+          begin
+            if (rx_syn_reg)
+              begin
+                rx_buffer_we  = 1;
+                rx_engine_new = RX_ACK;
+                rx_engine_we  = 1;
+              end
+          end
+        
+        RX_ACK:
+          begin
+            rx_ack_new = 1;
+            rx_ack_we  = 1;
+
+            if (!rx_syn_reg)
+              begin
+                rx_ack_new = 0;
+                rx_ack_we  = 1;
+                
+                if (rx_buffer[rx_buffer_ptr_reg] == EOC)
+                  begin
+                    rx_engine_new = RX_DONE;
+                    rx_engine_we  = 1;
+                  end
+
+                else
+                  begin
+                    rx_buffer_ptr_inc = 1;
+                    rx_engine_new     = RX_IDLE;
+                    rx_engine_we      = 1;
+                  end
+              end
+          end
+
+        RX_DONE:
+          begin
+            cmd_available_new = 1;
+            cmd_available_we  = 1;
+            rx_engine_new     = RX_CMD;
+            rx_engine_we      = 1;
+          end
+
+        RX_CMD:
+            if (cmd_accepted)
+              begin
+                cmd_available_new = 0;
+                cmd_available_we  = 1;
+                rx_buffer_ptr_rst = 1;
+                rx_engine_new     = RX_IDLE;
+                rx_engine_we      = 1;
+              end
+        
+        default:
+          begin
+            rx_buffer_ptr_rst = 1;
+            rx_engine_new     = RX_IDLE;
+            rx_engine_we      = 1;
+          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_rst = 0;
+      tx_buffer_ptr_inc = 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[tx_buffer_ptr_reg] == EOR) 
+              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
+            tx_buffer_ptr_rst = 1;
+            response_sent_new = 0;
+            response_sent_we  = 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;
+      cmd_accepted       = 0;
+      extract_cmd_fields = 0;
+      sample_core_output = 0;
+      update_tx_buffer   = 0;
+      response_type      = 8'h00;
+      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 (cmd_available_reg)
+              begin
+                extract_cmd_fields = 1;
+                test_engine_new    = TEST_PARSE_CMD;
+                test_engine_we     = 1;
+              end
+          end
+        
+        TEST_PARSE_CMD:
+          begin
+            cmd_accepted = 1;
+
+            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
+                  // Unknown command.
+                  test_engine_new = TEST_UNKNOWN;
+                  test_engine_we  = 1;
+                end
+            endcase // case (cmd_reg)
+          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_UNKNOWN:
+          begin
+            update_tx_buffer = 1;
+            response_type    = UNKNOWN;
+            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
+//======================================================================
diff --git a/src/sw/seriedebug.py b/src/sw/seriedebug.py
new file mode 100755
index 0000000..2062116
--- /dev/null
+++ b/src/sw/seriedebug.py
@@ -0,0 +1,118 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#=======================================================================
+#
+# seriedebug.py
+# -------------
+# Program that sends test bytes onto the serial link and print out
+# any response.
+#
+# Note: This proram requires the PySerial module.
+# http://pyserial.sourceforge.net/
+#
+# 
+# Author: Joachim Strömbergson
+# Copyright (c) 2014 SUNET
+# 
+# Redistribution and use in source and binary forms, with or 
+# without modification, are permitted provided that the following 
+# conditions are met: 
+# 
+# 1. Redistributions of source code must retain the above copyright 
+#    notice, this list of conditions and the following disclaimer. 
+# 
+# 2. 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. 
+# 
+# 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 OWNER 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.
+#
+#=======================================================================
+
+#-------------------------------------------------------------------
+# Python module imports.
+#-------------------------------------------------------------------
+import sys
+import serial
+
+    
+#-------------------------------------------------------------------
+# main()
+#
+# Parse arguments.
+#-------------------------------------------------------------------
+def main():
+    print "Seriedebug started..."
+    print
+
+    verbose = True
+    
+    # Create a serial devce and configure it.
+    # Should be:
+    # 1200 Baud
+    # 1 start bit
+    # 8 data bits
+    # 1 even parity bit
+    # 2 stop bits
+    # No RTS/CTS
+    # Note: You need to update to the correct device in your system.
+    ser = serial.Serial()
+    ser.port='/dev/cu.usbserial-A5020LKF'
+    ser.baudrate=1200
+    ser.bytesize=8
+    ser.parity='E'
+    ser.stopbits=2
+    ser.timeout=1
+    ser.writeTimeout=0
+
+    # Open the interface.
+    ser.open()
+    if verbose:
+        print "Opening device."
+        
+    # Send a byte and try to get the response.
+    test_byte = '\xaa'
+    ser.write(test_byte)
+    if verbose:
+        print "transmitting byte 0x%0x" % ord(test_byte)
+
+    
+    if verbose:
+        print "Waiting for response..."
+
+    response = ""
+    while not len(response):
+        response = ser.read()
+        if len(response):
+            print "received response: 0x%0x" % ord(response)
+
+    # Exit nicely.
+    if verbose:
+        print "Done. Closing device."
+    ser.close()
+
+
+#-------------------------------------------------------------------
+# __name__
+# Python thingy which allows the file to be run standalone as
+# well as parsed from within a Python interpreter.
+#-------------------------------------------------------------------
+if __name__=="__main__": 
+    # Run the main function.
+    sys.exit(main())
+
+#=======================================================================
+# EOF seriedebug.py
+#=======================================================================
diff --git a/src/tb/tb_coretest.v b/src/tb/tb_coretest.v
new file mode 100644
index 0000000..415a9e6
--- /dev/null
+++ b/src/tb/tb_coretest.v
@@ -0,0 +1,362 @@
+//======================================================================
+//
+// tb_coretest.v
+// -------------
+// Testbench for coretest. Generates commands and observes responses.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2014 SUNET
+// 
+// Redistribution and use in source and binary forms, with or 
+// without modification, are permitted provided that the following 
+// conditions are met: 
+// 
+// 1. Redistributions of source code must retain the above copyright 
+//    notice, this list of conditions and the following disclaimer. 
+// 
+// 2. 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. 
+// 
+// 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 OWNER 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.
+//
+//======================================================================
+
+//------------------------------------------------------------------
+// Simulator directives.
+//------------------------------------------------------------------
+`timescale 1ns/10ps
+
+
+module tb_coretest();
+  
+  //----------------------------------------------------------------
+  // Internal constant and parameter definitions.
+  //----------------------------------------------------------------
+  parameter DEBUG           = 0;
+  parameter VERBOSE         = 1;
+
+  parameter CLK_HALF_PERIOD = 1;
+  parameter CLK_PERIOD      = CLK_HALF_PERIOD * 2;
+  
+
+  parameter SOF = 8'h55;
+  parameter EOF = 8'haa;
+  parameter OP_RESET = 8'h01;
+  parameter OP_READ  = 8'h10;
+  parameter OP_WRITE = 8'h11;
+  
+  
+  //----------------------------------------------------------------
+  // Register and Wire declarations.
+  //----------------------------------------------------------------
+  reg [31 : 0]  cycle_ctr;
+  reg [31 : 0]  error_ctr;
+  reg [31 : 0]  tc_ctr;
+
+  reg           tb_clk;
+  reg           tb_reset_n;
+
+  reg           tb_rx_syn;
+  reg [7 : 0]   tb_rx_data;
+  wire          tb_rx_ack;
+  wire          tb_tx_syn;
+  wire [7 : 0]  tb_tx_data;
+  reg           tb_tx_ack;
+
+  wire          tb_core_reset_;
+  wire          tb_core_cs;
+  wire          tb_core_we;
+  wire [15 : 0] tb_core_address;
+  wire [31 : 0] tb_core_write_data;
+  reg [31 : 0]  tb_core_read_data;
+  reg           tb_core_error;
+
+  reg [7 : 0]   received_tx_data;
+  
+  
+
+  //----------------------------------------------------------------
+  // Device Under Test.
+  //----------------------------------------------------------------
+  coretest dut(
+               .clk(tb_clk),
+               .reset_n(tb_reset_n),
+                
+               // Interface to communication core
+               .rx_syn(tb_rx_syn),
+               .rx_data(tb_rx_data),
+               .rx_ack(tb_rx_ack),
+               
+               .tx_syn(tb_tx_syn),
+               .tx_data(tb_tx_data),
+               .tx_ack(tb_tx_ack),
+                
+               // Interface to the core being tested.
+               .core_reset_n(tb_core_reset_n),
+               .core_cs(tb_core_cs),
+               .core_we(tb_core_we),
+               .core_address(tb_core_address),
+               .core_write_data(tb_core_write_data),
+               .core_read_data(tb_core_read_data),
+               .core_error(tb_core_error)
+              );
+
+  
+  //----------------------------------------------------------------
+  // Concurrent assignments.
+  //----------------------------------------------------------------
+  
+
+  //----------------------------------------------------------------
+  // clk_gen
+  //
+  // Clock generator process. 
+  //----------------------------------------------------------------
+  always 
+    begin : clk_gen
+      #CLK_HALF_PERIOD tb_clk = !tb_clk;
+    end // clk_gen
+    
+
+  //----------------------------------------------------------------
+  // sys_monitor
+  //----------------------------------------------------------------
+  always
+    begin : sys_monitor
+      #(CLK_PERIOD);      
+      if (DEBUG)
+        begin
+          $display("");
+        end
+
+      if (VERBOSE)
+        begin
+          $display("cycle: 0x%016x", cycle_ctr);
+        end
+      cycle_ctr = cycle_ctr + 1;
+    end
+
+  
+  //----------------------------------------------------------------
+  // dump_dut_state()
+  //
+  // Dump the state of the dut when needed.
+  //----------------------------------------------------------------
+  task dump_dut_state();
+    begin
+      $display("State of DUT");
+      $display("------------");
+      $display("Inputs and outputs:");
+      $display("rx_syn = 0x%01x, rx_data = 0x%02x, rx_ack = 0x%01x",
+               dut.rx_syn, dut.rx_data, dut.rx_ack);
+      $display("tx_syn = 0x%01x, tx_data = 0x%02x, tx_ack = 0x%01x",
+               dut.tx_syn, dut.tx_data, dut.tx_ack);
+      $display("cs = 0x%01x, we = 0x%01x, address = 0x%04x, write_data = 0x%08x, read_data = 0x%08x, error = 0x%01x",
+               dut.core_cs, dut.core_we, dut.core_address, dut.core_write_data, dut.core_read_data, dut.core_error);
+      $display("");
+
+      $display("Control signals and FSM state:");
+      $display("test_engine_reg = 0x%02x, cmd_reg = 0x%02x, rx_buffer_ptr = 0x%02x, tx_buffer_ptr = 0x%02x",
+               dut.test_engine_reg, dut.cmd_reg, dut.rx_buffer_ptr_reg, dut.tx_buffer_ptr_reg);
+      $display("");
+    end
+  endtask // dump_dut_state
+
+  
+  //----------------------------------------------------------------
+  // reset_dut()
+  //----------------------------------------------------------------
+  task reset_dut();
+    begin
+      $display("*** Toggle reset.");
+      tb_reset_n = 0;
+      #(2 * CLK_PERIOD);
+      tb_reset_n = 1;
+    end
+  endtask // reset_dut
+
+  
+  //----------------------------------------------------------------
+  // init_sim()
+  //
+  // Initialize all counters and testbed functionality as well
+  // as setting the DUT inputs to defined values.
+  //----------------------------------------------------------------
+  task init_sim();
+    begin
+      cycle_ctr         = 0;
+      error_ctr         = 0;
+      tc_ctr            = 0;
+      
+      tb_clk            = 0;
+      tb_reset_n        = 1;
+      tb_rx_syn         = 0;
+      tb_rx_data        = 8'h00;
+      tb_tx_ack         = 1;
+      tb_core_read_data = 32'h00000000;
+      tb_core_error     = 0;
+    end
+  endtask // init_sim
+
+
+  //----------------------------------------------------------------
+  // send_byte
+  //
+  // Send a byte of data to the DUT.
+  //----------------------------------------------------------------
+  task send_byte(input [7 : 0] data);
+    integer i;
+    begin
+      $display("*** Sending byte 0x%02x to the dut.", data);
+
+      if (VERBOSE)
+        begin
+          $display("*** Setting RX data and RX SYN.");
+        end
+      tb_rx_data = data;
+      tb_rx_syn  = 1;
+
+      while (!tb_rx_ack)
+        begin
+          #CLK_PERIOD;
+          if (VERBOSE)
+            begin
+              $display("*** Waiting for RX ACK.");
+            end
+        end
+
+      if (VERBOSE)
+        begin
+          $display("*** RX ACK seen. Dropping SYN.");
+        end
+      tb_rx_syn  = 0;
+
+      #(2 * CLK_PERIOD);
+    end
+  endtask // send_byte
+
+  
+  //----------------------------------------------------------------
+  // send_reset_command
+  //
+  // Generates a reset command to the dut.
+  //----------------------------------------------------------------
+  task send_reset_command();
+    begin
+      $display("*** Sending reset command.");
+      send_byte(SOF);
+      send_byte(OP_RESET);
+      send_byte(EOF);
+      $display("*** Sending reset command done.");
+    end
+  endtask // send_write_command
+
+  
+  //----------------------------------------------------------------
+  // send_write_command
+  //
+  // Generates a read command to the dut.
+  //----------------------------------------------------------------
+  task send_read_command(input [15 : 0] addr);
+    begin
+      $display("*** Sending read command: address 0x%04x.", addr);
+      send_byte(SOF);
+      send_byte(OP_READ);
+      send_byte(addr[15 : 8]);
+      send_byte(addr[7 : 0]);
+      send_byte(EOF);
+      $display("*** Sending read command done.");
+    end
+  endtask // send_write_command
+
+  
+  //----------------------------------------------------------------
+  // send_write_command
+  //
+  // Generates a write command to the dut.
+  //----------------------------------------------------------------
+  task send_write_command(input [15 : 0] addr, input [31 : 0] data);
+    begin
+      $display("*** Sending write command: address 0x%04x = 0x%08x.", addr, data);
+      send_byte(SOF);
+      send_byte(OP_WRITE);
+      send_byte(addr[15 : 8]);
+      send_byte(addr[7 : 0]);
+      send_byte(data[31 : 24]);
+      send_byte(data[23 : 16]);
+      send_byte(data[15 : 8]);
+      send_byte(data[7 : 0]);
+      send_byte(EOF);
+      $display("*** Sending write command done.");
+    end
+  endtask // send_write_command
+  
+  
+  //----------------------------------------------------------------
+  // display_test_result()
+  //
+  // Display the accumulated test results.
+  //----------------------------------------------------------------
+  task display_test_result();
+    begin
+      if (error_ctr == 0)
+        begin
+          $display("*** All %02d test cases completed successfully", tc_ctr);
+        end
+      else
+        begin
+          $display("*** %02d test cases did not complete successfully.", error_ctr);
+        end
+    end
+  endtask // display_test_result
+                         
+    
+  //----------------------------------------------------------------
+  // coretest_test
+  // The main test functionality. 
+  //----------------------------------------------------------------
+  initial
+    begin : coretest_test
+      $display("   -- Testbench for coretest started --");
+
+      init_sim();
+      dump_dut_state();
+      reset_dut();
+      dump_dut_state();
+
+      #(64 * CLK_PERIOD);
+
+      send_reset_command();
+//      dump_dut_state();
+
+      send_read_command(16'h0123);
+//      dump_dut_state();
+
+      send_write_command(16'h4224, 32'h1337beef);
+//      dump_dut_state();
+
+      #(64 * CLK_PERIOD);
+
+      display_test_result();
+      $display("*** Simulation done.");
+      $finish;
+    end // coretest_test
+endmodule // tb_coretest
+
+//======================================================================
+// EOF tb_coretest.v
+//======================================================================



More information about the Commits mailing list