diff options
-rw-r--r-- | src/rtl/coretest.v | 897 | ||||
-rwxr-xr-x | src/sw/seriedebug.py | 118 | ||||
-rw-r--r-- | src/tb/tb_coretest.v | 362 |
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 +//====================================================================== |