aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoachim Strömbergson <joachim@secworks.se>2014-03-13 14:51:02 +0100
committerJoachim Strömbergson <joachim@secworks.se>2014-03-13 14:51:02 +0100
commit040614752772141d1541068e2d05eef72cda5c43 (patch)
treecf65c9377a3b79655f05a11de4b7609c2bff03cc
Adding source files for coretest.
-rw-r--r--src/rtl/coretest.v897
-rwxr-xr-xsrc/sw/seriedebug.py118
-rw-r--r--src/tb/tb_coretest.v362
3 files changed, 1377 insertions, 0 deletions
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
+//======================================================================