Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add uart bits.

  • Loading branch information...
commit 7f1e6390e5ccf201fc2eb6659834a91a2c660958 1 parent 116d8fd
@atgreen authored
Showing with 12,410 additions and 44 deletions.
  1. +111 −0 moxie/cores/uart16550/bench/verilog/readme.txt
  2. +276 −0 moxie/cores/uart16550/bench/verilog/test_cases/uart_int.v
  3. +714 −0 moxie/cores/uart16550/bench/verilog/uart_device.v
  4. +320 −0 moxie/cores/uart16550/bench/verilog/uart_device_utilities.v
  5. +206 −0 moxie/cores/uart16550/bench/verilog/uart_log.v
  6. +339 −0 moxie/cores/uart16550/bench/verilog/uart_test.v
  7. +1,363 −0 moxie/cores/uart16550/bench/verilog/uart_testbench.v
  8. +86 −0 moxie/cores/uart16550/bench/verilog/uart_testbench_defines.v
  9. +320 −0 moxie/cores/uart16550/bench/verilog/uart_testbench_utilities.v
  10. +359 −0 moxie/cores/uart16550/bench/verilog/uart_wb_utilities.v
  11. +114 −0 moxie/cores/uart16550/bench/verilog/vapi.log
  12. +631 −0 moxie/cores/uart16550/bench/verilog/wb_mast.v
  13. +841 −0 moxie/cores/uart16550/bench/verilog/wb_master_model.v
  14. +79 −0 moxie/cores/uart16550/bench/verilog/wb_model_defines.v
  15. 0  moxie/cores/uart16550/bench/vhdl/.keepme
  16. +111 −0 moxie/cores/uart16550/doc/CHANGES.txt
  17. BIN  moxie/cores/uart16550/doc/UART_spec.pdf
  18. BIN  moxie/cores/uart16550/doc/src/UART_spec.doc
  19. 0  moxie/cores/uart16550/fv/.keepme
  20. 0  moxie/cores/uart16550/lint/bin/.keepme
  21. 0  moxie/cores/uart16550/lint/log/.keepme
  22. 0  moxie/cores/uart16550/lint/out/.keepme
  23. 0  moxie/cores/uart16550/lint/run/.keepme
  24. +3 −0  moxie/cores/uart16550/rtl/verilog-backup/timescale.v
  25. +177 −0 moxie/cores/uart16550/rtl/verilog-backup/uart_defines.v
  26. +278 −0 moxie/cores/uart16550/rtl/verilog-backup/uart_fifo.v
  27. +341 −0 moxie/cores/uart16550/rtl/verilog-backup/uart_receiver.v
  28. +532 −0 moxie/cores/uart16550/rtl/verilog-backup/uart_regs.v
  29. +170 −0 moxie/cores/uart16550/rtl/verilog-backup/uart_top.v
  30. +288 −0 moxie/cores/uart16550/rtl/verilog-backup/uart_transmitter.v
  31. +125 −0 moxie/cores/uart16550/rtl/verilog-backup/uart_wb.v
  32. +111 −0 moxie/cores/uart16550/rtl/verilog/raminfr.v
  33. +64 −0 moxie/cores/uart16550/rtl/verilog/timescale.v
  34. +126 −0 moxie/cores/uart16550/rtl/verilog/uart_debug_if.v
  35. +247 −0 moxie/cores/uart16550/rtl/verilog/uart_defines.v
  36. +482 −0 moxie/cores/uart16550/rtl/verilog/uart_receiver.v
  37. +893 −0 moxie/cores/uart16550/rtl/verilog/uart_regs.v
  38. +320 −0 moxie/cores/uart16550/rtl/verilog/uart_rfifo.v
  39. +122 −0 moxie/cores/uart16550/rtl/verilog/uart_sync_flops.v
  40. +243 −0 moxie/cores/uart16550/rtl/verilog/uart_tfifo.v
  41. +340 −0 moxie/cores/uart16550/rtl/verilog/uart_top.v
  42. +351 −0 moxie/cores/uart16550/rtl/verilog/uart_transmitter.v
  43. +317 −0 moxie/cores/uart16550/rtl/verilog/uart_wb.v
  44. 0  moxie/cores/uart16550/rtl/vhdl/.keepme
  45. 0  moxie/cores/uart16550/sim/gate_sim/bin/.keepme
  46. 0  moxie/cores/uart16550/sim/gate_sim/log/.keepme
  47. 0  moxie/cores/uart16550/sim/gate_sim/out/.keepme
  48. 0  moxie/cores/uart16550/sim/gate_sim/run/.keepme
  49. 0  moxie/cores/uart16550/sim/gate_sim/src/.keepme
  50. +9 −0 moxie/cores/uart16550/sim/rtl_sim/bin/nc.scr
  51. +5 −0 moxie/cores/uart16550/sim/rtl_sim/bin/sim.tcl
  52. 0  moxie/cores/uart16550/sim/rtl_sim/log/.keepme
  53. +23 −0 moxie/cores/uart16550/sim/rtl_sim/log/uart_interrupts_report.log
  54. +104 −0 moxie/cores/uart16550/sim/rtl_sim/log/uart_interrupts_verbose.log
  55. 0  moxie/cores/uart16550/sim/rtl_sim/out/.keepme
  56. +2 −0  moxie/cores/uart16550/sim/rtl_sim/run/run_signalscan
  57. +1 −0  moxie/cores/uart16550/sim/rtl_sim/run/run_sim
  58. +345 −0 moxie/cores/uart16550/sim/rtl_sim/run/run_sim.scr
  59. 0  moxie/cores/uart16550/sim/rtl_sim/src/.keepme
  60. 0  moxie/cores/uart16550/syn/bin/.keepme
  61. 0  moxie/cores/uart16550/syn/log/.keepme
  62. 0  moxie/cores/uart16550/syn/out/.keepme
  63. 0  moxie/cores/uart16550/syn/run/.keepme
  64. 0  moxie/cores/uart16550/syn/src/.keepme
  65. +67 −0 moxie/soc/muskoka/boards/de2-70/Makefile
  66. +40 −0 moxie/soc/muskoka/boards/de2-70/muskoka-de20.v
  67. +368 −0 moxie/soc/muskoka/boards/de2-70/pll.v
  68. +19 −13 moxie/soc/muskoka/boards/de2-70/setup_proj.tcl
  69. +23 −29 moxie/soc/muskoka/rtl/muskoka.v
  70. +4 −2 moxie/soc/muskoka/sim/Makefile
View
111 moxie/cores/uart16550/bench/verilog/readme.txt
@@ -0,0 +1,111 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// readme.txt ////
+//// ////
+//// ////
+//// This file is part of the "UART 16550 compatible" project ////
+//// http://www.opencores.org/projects/uart16550/ ////
+//// ////
+//// Documentation related to this project: ////
+//// http://www.opencores.org/projects/uart16550/ ////
+//// ////
+//// Projects compatibility: ////
+//// - WISHBONE ////
+//// RS232 Protocol ////
+//// 16550D uart (mostly supported) ////
+//// ////
+//// Overview (main Features): ////
+//// Device interface for testing purposes ////
+//// ////
+//// Known problems (limits): ////
+//// ////
+//// To Do: ////
+//// Nothing. ////
+//// ////
+//// Author(s): ////
+//// - Igor Mohor (igorm@opencores.org) ////
+//// ////
+//// Created and updated: (See log for the revision history) ////
+//// ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2001 Authors ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer. ////
+//// ////
+//// This source file is free software; you can redistribute it ////
+//// and/or modify it under the terms of the GNU Lesser General ////
+//// Public License as published by the Free Software Foundation; ////
+//// either version 2.1 of the License, or (at your option) any ////
+//// later version. ////
+//// ////
+//// This source is distributed in the hope that it will be ////
+//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
+//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
+//// PURPOSE. See the GNU Lesser General Public License for more ////
+//// details. ////
+//// ////
+//// You should have received a copy of the GNU Lesser General ////
+//// Public License along with this source; if not, download it ////
+//// from http://www.opencores.org/lgpl.shtml ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//
+// CVS Revision History
+//
+// $Log: not supported by cvs2svn $
+//
+//
+//
+//
+
+
+Following files are making an UART16550 PHY and are used for testing:
+
+uart_device_if_defines.v - defines related to PHY
+uart_device_if_memory.v - Module for initializing PHY (reading commands from vapi.log file)
+uart_device_if.v - Uart PHY with additional feature for testing
+vapi.log - File with commands (expected data, data to be send, etc.)
+readme.txt - This file
+
+
+
+
+OPERATION:
+uart_device_if.v is a uart PHY and connects to the uart_top.v. PHY takes commands from vapi.log
+file. Depending on command it can:
+- set a mode (5, 6, 7, 8-bit, parity, stop bits, etc.)
+- set a frequency divider (dll)
+- send a character
+- receive a character and compare it to the expected one
+- send a glitch (after a certain period of time)
+- send a break
+- detect a break
+- Check if fifo is empty/not empty (and generate an error if expected value differs from actual)
+- delay (does nothing for certain number of characters)
+
+On the other side of uart some kind of host must be connected that controls the phy.
+
+This is the structure:
+
+
+ |||||||||||||| |||||||||||||||| ||||||||||||||||
+ | | | | | |
+ | Host | <----------> | UART | <----------> | PHY |
+ | | | | | |
+ |||||||||||||| |||||||||||||||| ||||||||||||||||
+
+
+ PHY must know how host sets th UART and work in the same mode. Besides that it must know what
+ host is sending or expecting to receive. Operation of the PHY must be written in the vapi.log
+ file.
+
+ When I was using this testing environment, I used OpenRISC1200 as a host. Everything is fully
+ operational. UART was also tested in hardware (on two different boards), running uCLinux in
+ both, interrupt and polling mode.
+
+
View
276 moxie/cores/uart16550/bench/verilog/test_cases/uart_int.v
@@ -0,0 +1,276 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// uart_int.v ////
+//// ////
+//// This file is part of the "uart16550" project ////
+//// http://www.opencores.org/projects/uart16550/ ////
+//// ////
+//// Author(s): ////
+//// - tadej@opencores.org (Tadej Markovic) ////
+//// ////
+//// All additional information is avaliable in the README.txt ////
+//// file. ////
+//// ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2000 - 2004 authors ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer. ////
+//// ////
+//// This source file is free software; you can redistribute it ////
+//// and/or modify it under the terms of the GNU Lesser General ////
+//// Public License as published by the Free Software Foundation; ////
+//// either version 2.1 of the License, or (at your option) any ////
+//// later version. ////
+//// ////
+//// This source is distributed in the hope that it will be ////
+//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
+//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
+//// PURPOSE. See the GNU Lesser General Public License for more ////
+//// details. ////
+//// ////
+//// You should have received a copy of the GNU Lesser General ////
+//// Public License along with this source; if not, download it ////
+//// from http://www.opencores.org/lgpl.shtml ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//
+// CVS Revision History
+//
+// $Log: not supported by cvs2svn $
+//
+//
+
+
+`include "uart_defines.v"
+`include "uart_testbench_defines.v"
+`include "timescale.v"
+
+module testcase;
+
+
+// Testcase INDEPENDENT code - common to all testcases
+//#####################################################
+
+ // Variables
+ // Testbench reporting events & signals
+ event severe_err_event;
+ event err_event;
+ event wrn_event;
+ event msg_event;
+ event val_event;
+ event testbench_log_written;
+ reg [7999: 0] tim;
+ reg [7999: 0] severe_err_msg;
+ reg [7999: 0] msg;
+ integer val;
+ // Testcase reporting events & signals
+ event testcase_log_written;
+ event test_end;
+ reg [1599: 0] test_name;
+ reg error_detected;
+
+ // Module for writing to log files
+ uart_log log ();
+ defparam log.testcase_name = "uart_interrupts";
+
+ // Log
+ initial
+ fork
+ begin: init_log
+ reg ok;
+ // Delay allows all other blocks in this fork - join block to execute
+ #1;
+ log.start_log(ok);
+ if (ok !== 1'b1)
+ begin
+ `SEVERE_ERROR("Failed to open log file(s)!");
+ disable init_log;
+ end
+ testcase_init;
+ testcase_test;
+ log.end_log;
+ # 100;
+ $finish;
+ end
+ begin
+ forever
+ begin
+ @(test_name);
+ error_detected = 1'b0;
+ log.report_test_name(test_name);
+ log.verbose_test_name(test_name);
+ -> testcase_log_written;
+ end
+ end
+ begin
+ forever
+ begin
+ @(test_end);
+ if (error_detected)
+ begin
+ log.tests_failed = log.tests_failed + 1'b1;
+ end
+ else
+ begin
+ log.tests_ok = log.tests_ok + 1'b1;
+ log.report_test_ok;
+ end
+ -> testcase_log_written;
+ end
+ end
+ begin
+ @(severe_err_event);
+ error_detected = 1'b1;
+ -> test_end;
+ @(testcase_log_written);
+ log.report_test_failed(severe_err_msg);
+ if (testcase.log.free == 0)
+ begin
+ wait (testcase.log.free);
+ severe_err_msg = "Failed to write to log file(s)!";
+ end
+ log.verbose_severe_err(tim, severe_err_msg);
+ -> testbench_log_written;
+ # 100; $finish;
+ end
+ begin
+ forever
+ begin
+ @(err_event);
+ error_detected = 1'b1;
+ -> test_end;
+ @(testcase_log_written);
+ log.report_test_failed(msg);
+ if (testcase.log.free == 0)
+ begin
+ `SEVERE_ERROR("Failed to write to log file(s)!");
+ end
+ log.verbose_err(tim, msg);
+ -> testbench_log_written;
+ `PROMPT;
+ end
+ end
+ begin
+ forever
+ begin
+ @(wrn_event);
+ if (testcase.log.free == 0)
+ begin
+ `SEVERE_ERROR("Failed to write to log file(s)!");
+ end
+ log.verbose_wrn(tim, msg);
+ -> testbench_log_written;
+ end
+ end
+ begin
+ forever
+ begin
+ @(msg_event);
+ if (testcase.log.free == 0)
+ begin
+ `SEVERE_ERROR("Failed to write to log file(s)!");
+ end
+ log.verbose_msg(tim, msg);
+ -> testbench_log_written;
+ end
+ end
+ begin
+ forever
+ begin
+ @(val_event);
+ if (testcase.log.free == 0)
+ begin
+ `SEVERE_ERROR("Failed to write to log file(s)!");
+ end
+ log.verbose_val(tim, msg, val);
+ -> testbench_log_written;
+ end
+ end
+ join
+
+
+// Testcase (DEPENDENT) code
+//###########################
+
+ // Initialization
+ task testcase_init;
+ begin:init
+ test_name = "Initialization of UART.";
+ @(testcase_log_written);
+ //
+ testbench_utilities.do_reset;
+ testbench_utilities.disable_clk_generators(1, 1, 1, 1);
+ testbench_utilities.set_device_tx_rx_clk_divisor(32'h1000);
+ testbench_utilities.set_wb_clock_period(100);
+ testbench_utilities.enable_clk_generators(1, 1, 1, 1);
+ #100;
+ testbench_utilities.release_reset;
+ //
+ uart_wb_utilities.write_dlr(16'h1000);
+ uart_wb_utilities.write_ier(8'h07);
+ uart_wb_utilities.write_fcr(8'hC0);
+ uart_wb_utilities.write_lcr(8'h03);
+ //
+ uart_device_utilities.set_rx_length(8);
+ uart_device_utilities.disable_rx_parity;
+ uart_device_utilities.set_rx_second_stop_bit(0);
+ //
+ uart_device_utilities.set_tx_length(8);
+ uart_device_utilities.disable_tx_parity;
+ uart_device_utilities.correct_tx_parity;
+ uart_device_utilities.correct_tx_frame;
+ uart_device_utilities.generate_tx_glitch(0);
+
+ -> test_end;
+ @(testcase_log_written);
+ end
+ endtask // testcase_init
+
+ // Testcase
+ task testcase_test;
+ begin:test
+ test_name = "Interrupt test.";
+ @(testcase_log_written);
+ fork
+ begin: test
+ uart_wb_utilities.write_char(8'hAA);
+ @(testbench.int_aserted);
+ `TC_MSG("INT ASSERTED!");
+ uart_wb_utilities.write_char(8'hAA);
+ @(testbench.int_released);
+ `TC_MSG("INT RELEASED!");
+ @(testbench.int_aserted);
+ `TC_MSG("INT ASSERTED!");
+ uart_wb_utilities.read_iir;
+ @(testbench.int_released);
+ `TC_MSG("INT RELEASED!");
+ end
+ begin: wait_end
+ @(testbench.i_uart_device.device_received_packet);
+ @(testbench.i_uart_device.device_received_packet);
+ repeat(2) @(testbench.i_uart_device.rx_clk);
+ disable test;
+ disable wait_clk;
+ end
+ begin: wait_clk
+ testbench_utilities.wait_for_num_of_wb_clk(32'h450000);
+ disable test;
+ disable wait_end;
+ end
+ join
+ repeat (4) @(posedge testbench.wb_clk);
+ # 100;
+
+ -> test_end;
+ @(testcase_log_written);
+ end
+ endtask // testcase_test
+
+
+endmodule
+
View
714 moxie/cores/uart16550/bench/verilog/uart_device.v
@@ -0,0 +1,714 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// uart_device.v ////
+//// ////
+//// This file is part of the "uart16550" project ////
+//// http://www.opencores.org/projects/uart16550/ ////
+//// ////
+//// Author(s): ////
+//// - tadej@opencores.org (Tadej Markovic) ////
+//// - igorm@opencores.org (Igor Mohor) ////
+//// ////
+//// All additional information is avaliable in the README.txt ////
+//// file. ////
+//// ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2000 - 2004 authors ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer. ////
+//// ////
+//// This source file is free software; you can redistribute it ////
+//// and/or modify it under the terms of the GNU Lesser General ////
+//// Public License as published by the Free Software Foundation; ////
+//// either version 2.1 of the License, or (at your option) any ////
+//// later version. ////
+//// ////
+//// This source is distributed in the hope that it will be ////
+//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
+//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
+//// PURPOSE. See the GNU Lesser General Public License for more ////
+//// details. ////
+//// ////
+//// You should have received a copy of the GNU Lesser General ////
+//// Public License along with this source; if not, download it ////
+//// from http://www.opencores.org/lgpl.shtml ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//
+// CVS Revision History
+//
+// $Log: not supported by cvs2svn $
+//
+//
+
+
+`include "uart_testbench_defines.v"
+`include "timescale.v"
+
+module uart_device
+(
+ // UART signals
+ stx_i,
+ srx_o,
+ // Modem signals
+ rts_i,
+ cts_o,
+ dtr_i,
+ dsr_o,
+ ri_o,
+ dcd_o
+);
+
+
+// IN/OUT signals
+//###############
+
+ // UART signals
+ input stx_i;
+ output srx_o;
+ // Modem signals
+ input rts_i;
+ output cts_o;
+ input dtr_i;
+ output dsr_o;
+ output ri_o;
+ output dcd_o;
+
+
+// INTERNAL signals
+//#################
+
+
+ // Clock generation signals
+ //#########################
+
+ // Operational and transmission clock signals
+ reg rx_clk; // RX device clock with period T_clk_period (should be equal to wb_clk_period)
+ reg tx_clk; // TX device clock with period (T_clk_period + T_clk_delay)
+ reg tx_clk_divided; // divided TX device clock with period ((T_clk_period + T_clk_delay) * T_divisor * 16)
+ // Clock enable signals
+ reg rx_clk_en = 1'b1;
+ reg tx_clk_en = 1'b1;
+ reg tx_clk_divided_en = 1'b1;
+ // Clock period variables
+ real T_clk_period = 20;
+ real T_clk_delay = 0;
+ integer T_divisor = 5;
+
+
+ // IN/OUT assignment signals
+ //##########################
+
+ // Modem signals
+ wire rts;
+ wire dtr;
+
+
+ // UART receiver signals
+ //######################
+
+ // RX packet control signals
+ wire rx;
+ reg [3:0] rx_length;
+ reg rx_odd_parity;
+ reg rx_even_parity;
+ reg rx_stick1_parity;
+ reg rx_stick0_parity;
+ reg rx_parity_enabled;
+ reg rx_stop_bit_1;
+ reg rx_stop_bit_1_5;
+ reg rx_stop_bit_2;
+ // RX logic signals
+ wire [3:0] rx_total_length;
+ wire [5:0] rx_break_detection_length;
+ reg rx_packet_end;
+ reg rx_packet_end_q;
+ reg rx_clk_cnt_en;
+ reg [31:0] rx_clk_cnt;
+ reg rx_sample_clock;
+ integer rx_bit_index;
+ integer rx_stop_bit_index;
+ reg [7:0] rx_data;
+ reg [1:0] rx_stop;
+ reg rx_framing_error;
+ reg rx_parity;
+ reg rx_parity_error;
+ reg rx_break_detected;
+ reg rx_break_detected_q;
+ reg [31:0] rx_break_cnt;
+ // RX events
+ event device_received_packet;
+ event device_received_last_bit;
+ event device_received_stop_bit;
+ event device_detected_rx_break;
+
+
+ // UART transmitter signals
+ //#########################
+
+ // TX packet control signals
+ reg tx;
+ reg [3:0] tx_length;
+ reg tx_odd_parity;
+ reg tx_even_parity;
+ reg tx_stick1_parity;
+ reg tx_stick0_parity;
+ reg tx_parity_enabled;
+ reg tx_parity_wrong;
+ reg tx_framing_wrong;
+ // TX logic signals
+ reg [23:0] tx_glitch_num;
+ reg start_tx_glitch_cnt;
+ reg [31:0] tx_glitch_cnt;
+ reg tx_glitch;
+ reg tx_break_enable;
+ reg [15:0] tx_break_num;
+ reg start_tx_break_cnt;
+ reg [31:0] tx_break_cnt;
+ reg tx_break;
+ // TX test signals
+ reg [7:0] sent_data;
+ reg tx_accept_next_framing_err;
+ reg tx_framing_err;
+ reg tx_framing_glitch_err;
+ // TX events
+ event device_sent_packet;
+ event sent_packet_received;
+
+
+// Clock generation
+//#################
+
+ // Example of TESTBENCH's task for setting UART clock period:
+ // ----------------
+ // task set_uart_clk_period;
+ // input [31:0] clk_period;
+ // begin
+ // //@(posedge testbench.uart_device.clk);
+ // testbench.uart_device.T_clk_period = clk_period;
+ // end
+ // endtask // set_uart_clk_period
+ // ----------------
+ // Example of TESTBENCH's task for setting UART clock rising edge
+ // delayed for time_delay_i after WB clock rising edge:
+ // ----------------
+ // task uart_clk_follows_wb_clk;
+ // input [31:0] time_delay_i;
+ // integer time_delay;
+ // begin
+ // time_delay = time_delay_i;
+ // @(posedge testbench.uart_device.clk);
+ // testbench.uart_device.clk_en = 1'b0;
+ // @(posedge wb_clk);
+ // #time_delay testbench.uart_device.clk = 1'b1;
+ // testbench.uart_device.clk_en = 1'b1;
+ // end
+ // endtask // uart_clk_follows_wb_clk
+ // ----------------
+
+ // rx_clk rising edge
+ always@(posedge rx_clk)
+ if (rx_clk_en)
+ #(T_clk_period / 2) rx_clk = 1'b0;
+ // rx_clk falling edge
+ always@(negedge rx_clk)
+ if (rx_clk_en)
+ #(T_clk_period / 2) rx_clk = 1'b1;
+
+ // tx_clk rising edge
+ always@(posedge tx_clk)
+ if (tx_clk_en)
+ #((T_clk_period + T_clk_delay) / 2) tx_clk = 1'b0;
+ // tx_clk falling edge
+ always@(negedge tx_clk)
+ if (tx_clk_en)
+ #((T_clk_period + T_clk_delay) / 2) tx_clk = 1'b1;
+
+ // tx_clk_divided rising edge
+ always@(posedge tx_clk_divided)
+ if (tx_clk_divided_en)
+ #(((T_clk_period + T_clk_delay) / 2) * 16 * T_divisor) tx_clk_divided = 1'b0;
+ // tx_clk_divided falling edge
+ always@(negedge tx_clk_divided)
+ if (tx_clk_divided_en)
+ #(((T_clk_period + T_clk_delay) / 2) * 16 * T_divisor) tx_clk_divided = 1'b1;
+
+ // Inital CLK values
+ initial
+ begin:device
+ rx_clk = 1'b0;
+ tx_clk = 1'b0;
+ tx_clk_divided = 1'b0;
+ end
+
+
+// IN/OUT assignments
+//###################
+
+ // UART output
+ assign srx_o = (tx ^ tx_glitch) & ~tx_break;
+ // Modem output
+ assign cts_o = 0;
+ assign dsr_o = 0;
+ assign ri_o = 0;
+ assign dcd_o = 0;
+ // UART input
+ assign rx = stx_i;
+ // Modem input
+ assign rts = rts_i;
+ assign dtr = dtr_i;
+
+
+// UART receiver
+//##############
+
+ // Initial values for RX
+ initial
+ begin
+ // Default LENGTH
+ rx_length = 8;
+ // Default PARITY
+ rx_odd_parity = 1'b0;
+ rx_even_parity = 1'b0;
+ rx_stick1_parity = 1'b0;
+ rx_stick0_parity = 1'b0;
+ rx_parity_enabled = 1'b0;
+ // Default STOP
+ rx_stop_bit_1 = 1'b1;
+ rx_stop_bit_1_5 = 1'b0;
+ rx_stop_bit_2 = 1'b0;
+ end
+
+ // Total length of RX packet (for proper generation of the rx_packet_end signal):
+ // data length + parity + 1 stop bit + second stop bit (when enabled)
+ assign rx_total_length = rx_length + rx_parity_enabled + 1 + rx_stop_bit_2;
+ // +1 is used because start bit was not included in rx_total_length.
+ assign rx_break_detection_length = rx_total_length + 1;
+
+ // Generating rx_clk_cnt_en signal.
+ always@(posedge rx_clk)
+ begin
+ if (~rx_clk_cnt_en)
+ begin
+ wait (~rx);
+ end
+ rx_clk_cnt_en = 1;
+ rx_packet_end = 0;
+ wait (rx_packet_end);
+ rx_clk_cnt_en = 0;
+ wait (rx); // Must be high to continue, because of break condition
+ end
+
+ // Counter used in data reception
+ always@(posedge rx_clk)
+ begin
+ if (rx_clk_cnt_en)
+ begin
+ if (rx_clk_cnt == (8 * T_divisor - 1) & rx) // False start bit detection
+ rx_packet_end = 1;
+ if (rx_clk_cnt_en) // Checking is still enabled after devisor clocks
+ rx_clk_cnt <= #1 rx_clk_cnt + 1;
+ else
+ rx_clk_cnt <= #1 0;
+ end
+ else
+ rx_clk_cnt <= #1 0;
+ end
+
+ // Delayed rx_packet_end signal
+ always@(posedge rx_clk)
+ rx_packet_end_q = rx_packet_end;
+
+ // Generating sample clock and end of the frame (Received data is sampled with this clock)
+ always@(posedge rx_clk)
+ begin
+ if (rx_clk_cnt == 8 * T_divisor - 1)
+ rx_bit_index = 0;
+ else if (rx_clk_cnt == (8 * T_divisor + 16 * T_divisor * (rx_bit_index + 1) - 1))
+ begin
+ rx_sample_clock = 1;
+ rx_bit_index = rx_bit_index + 1;
+ if (rx_bit_index == rx_total_length)
+ rx_packet_end = 1;
+ end
+ else
+ rx_sample_clock = 0;
+ end
+
+ // Sampling data (received data)
+ always@(posedge rx_clk)
+ begin
+ if (rx_sample_clock)
+ begin
+ if (rx_bit_index <= rx_length) // Sampling data
+ begin
+ rx_stop_bit_index <= 0; // Stop bit index reset at the beginning of the data stage
+// $display("\t\t\t\t\t\t\t(rx_bit_index = %0d) Reading data bits = %0x", rx_bit_index, rx);
+ rx_data[rx_bit_index - 1] = rx;
+ if (rx_bit_index == rx_length)
+ -> device_received_last_bit;
+ end
+ else
+ begin
+ if (rx_bit_index == (rx_length + 1))
+ begin
+ if (rx_parity_enabled)
+ begin
+// $display("\t\t\t\t\t\t\t(rx_bit_index = %0d) Reading parity bits = %0x", rx_bit_index, rx);
+ end
+ else
+ begin
+ -> device_received_stop_bit;
+ rx_stop[rx_stop_bit_index] = rx;
+ rx_stop_bit_index <= rx_stop_bit_index + 1;
+ end
+ rx_parity = rx & rx_parity_enabled;
+ end
+ if (rx_bit_index >= (rx_length + 1 + rx_parity_enabled))
+ begin
+// $display("\t\t\t\t\t\t\t(rx_bit_index = %0d) Reading stop bits = %0x", rx_bit_index, rx);
+ rx_stop[rx_stop_bit_index] = rx;
+ rx_stop_bit_index <= rx_stop_bit_index + 1;
+ end
+ end
+ end
+
+ // Filling the rest of the data with 0
+ if (rx_length == 5)
+ rx_data[7:5] = 0;
+ if (rx_length == 6)
+ rx_data[7:6] = 0;
+ if (rx_length == 7)
+ rx_data[7] = 0;
+
+ // Framing error generation
+ // When 1 or 1.5 stop bits are used, only first stop bit is checked
+ rx_framing_error = (rx_stop_bit_1 | rx_stop_bit_1_5) ? ~rx_stop[0] : ~(&rx_stop[1:0]);
+
+ // Parity error generation
+ if (rx_odd_parity)
+ rx_parity_error = ~(^{rx_data, rx_parity});
+ else if (rx_even_parity)
+ rx_parity_error = ^{rx_data, rx_parity};
+ else if (rx_stick0_parity)
+ rx_parity_error = rx_parity;
+ else if (rx_stick1_parity)
+ rx_parity_error = ~rx_parity;
+ else
+ rx_parity_error = 0;
+ end
+
+ // Break detection
+ always@(posedge rx_clk)
+ begin
+ rx_break_detected_q <= rx_break_detected;
+ if (rx)
+ begin
+ rx_break_cnt = 0; // Reseting counter
+ rx_break_detected = 0; // Clearing break detected signal
+ end
+ else
+ rx_break_cnt = rx_break_cnt + 1;
+ if (rx_break_cnt == rx_break_detection_length * 16 * T_divisor)
+ begin
+// $display("\n(%0t) Break_detected.", $time);
+ rx_break_detected <= 1;
+ -> device_detected_rx_break;
+ end
+ end
+
+ // Writing received data
+ always@(posedge rx_clk)
+ begin
+ if ((rx_packet_end & ~rx_packet_end_q) | (rx_break_detected & ~rx_break_detected_q))
+ begin
+ wait (rx | rx_break_detected); // Waiting for "end of cycle detected" or "break to be activated"
+ // rx_break_detected
+ // rx_length
+ // rx_parity_enabled
+ // rx_odd_parity | rx_even_parity | rx_stick1_parity | rx_stick0_parity
+ // rx_stop_bit_1 | rx_stop_bit_1_5 | rx_stop_bit_2
+ -> device_received_packet;
+ end
+ end
+
+
+// UART transmitter
+//#################
+
+ // Initial values for TX
+ initial
+ begin
+ // Default LENGTH
+ tx_length = 8;
+ // Default PARITY
+ tx_odd_parity = 1'b0;
+ tx_even_parity = 1'b0;
+ tx_stick1_parity = 1'b0;
+ tx_stick0_parity = 1'b0;
+ tx_parity_enabled = 1'b0;
+ // Default CORRECT PARITY
+ tx_parity_wrong = 1'b0;
+ // Default CORRECT FRAME
+ tx_framing_wrong = 1'b0;
+ tx_framing_err = 0;
+ tx_framing_glitch_err = 0;
+ // Default NO GLITCH
+ tx_glitch_num = 24'h0;
+ // Default NO BREAK
+ tx_break_enable = 1'b0;
+ tx_break_num = 16'h0;
+ end
+
+ // Counter for TX glitch generation
+ always@(posedge tx_clk or posedge start_tx_glitch_cnt)
+ begin
+ if (start_tx_glitch_cnt)
+ begin
+ tx_glitch_cnt <= tx_glitch_cnt + 1;
+ if (tx_glitch_cnt == ((tx_glitch_num - 1) * T_divisor))
+ tx_glitch = 1'b1;
+ else if (tx_glitch_cnt == (tx_glitch_num * T_divisor))
+ begin
+ tx_glitch = 1'b0;
+ start_tx_glitch_cnt = 1'b0;
+ end
+ end
+ else
+ tx_glitch_cnt <= 0;
+ end
+
+ // Break setting & break counter
+ always@(posedge tx_clk)
+ begin
+ if (tx_break_enable && (tx_break_cnt == (tx_break_num * T_divisor)))
+ begin
+ start_tx_break_cnt = 0;
+ end
+ else if (start_tx_break_cnt)
+ begin
+ tx_break_cnt = tx_break_cnt + 1;
+ tx_break = 1;
+ end
+ else
+ begin
+ tx_break_cnt = 0;
+ tx_break = 0;
+ end
+ end
+
+ // Sending packets
+ task send_packet;
+ input tx_random_i;
+ input [7:0] tx_data_i;
+ input num_of_tx_data_i;
+ reg [7:0] tx_data;
+ reg tx_parity_xor;
+ integer tx_bit_index;
+ integer num_of_tx_data;
+ reg last_tx_data;
+ begin
+ // SEVERE ERROR
+ if (// WRONG combinations of parameters for testing
+ ((T_clk_delay != 0) && (tx_parity_wrong || tx_framing_wrong)) ||
+ ((T_clk_delay != 0) && (tx_glitch_num != 0)) ||
+ ((T_clk_delay != 0) && (tx_break_enable)) ||
+ ((tx_parity_wrong || tx_framing_wrong) && (tx_glitch_num != 0)) ||
+ ((tx_parity_wrong || tx_framing_wrong) && (tx_break_enable)) ||
+ ((tx_glitch_num != 0) && (tx_break_enable)) ||
+ (tx_glitch_num > ((tx_length + 2'h2 + tx_parity_enabled) * 16 * T_divisor)) || // with STOP bit
+// (tx_glitch_num > ((tx_length + 2'h1 + tx_parity_enabled) * 16 * T_divisor)) || // without STOP bit
+ // WRONG input parameters
+ (num_of_tx_data_i == 0) ||
+ ((num_of_tx_data_i > 1) && tx_break_enable)
+ )
+ begin
+ `SEVERE_ERROR("WRONG combination of parameters for testing UART receiver");
+ end
+
+ for (num_of_tx_data = 0;
+ num_of_tx_data < num_of_tx_data_i;
+ num_of_tx_data = (num_of_tx_data + 1'b1))
+ begin
+
+ if (num_of_tx_data == (num_of_tx_data_i - 1'b1))
+ last_tx_data = 1'b1;
+ else
+ last_tx_data = 0;
+
+ // TX data
+ if (~tx_random_i)
+ tx_data = tx_data_i;
+ else
+ tx_data = {$random}%256; // 0..255
+
+ // Sending start bit
+ @(posedge tx_clk_divided);
+ tx = 0;
+ if (tx_glitch_num > 0)
+ start_tx_glitch_cnt = 1; // enabling tx_glitch generation
+ if (tx_break_enable)
+ start_tx_break_cnt = 1; // Start counter that counts break tx_length
+ // Wait for almost 1 bit
+ #(((T_clk_period + T_clk_delay) / 2) * 16 * T_divisor); // wait half period
+ #((((T_clk_period + T_clk_delay) / 2) * 16 * T_divisor) - 2); // wait 2 less than half period
+
+ // Sending tx_data bits
+ for (tx_bit_index = 0; tx_bit_index < tx_length; tx_bit_index = tx_bit_index + 1)
+ begin
+ @(posedge tx_clk_divided);
+ tx = tx_data[tx_bit_index];
+ end
+ // Wait for almost 1 bit
+ #(((T_clk_period + T_clk_delay) / 2) * 16 * T_divisor); // wait half period
+ #((((T_clk_period + T_clk_delay) / 2) * 16 * T_divisor) - 2); // wait 2 less than half period
+
+ sent_data = tx_data;
+
+ // Calculating parity
+ if(tx_length == 5)
+ begin
+ tx_parity_xor = ^tx_data[4:0];
+ end
+ else if(tx_length == 6)
+ begin
+ tx_parity_xor = ^tx_data[5:0];
+ end
+ else if(tx_length == 7)
+ begin
+ tx_parity_xor = ^tx_data[6:0];
+ end
+ else if(tx_length == 8)
+ begin
+ tx_parity_xor = ^tx_data[7:0];
+ end
+ else
+ $display("WRONG length of TX data packet");
+
+ // Sending parity bit
+ if (tx_parity_enabled)
+ begin
+ @(posedge tx_clk_divided);
+ if (tx_odd_parity)
+ tx = tx_parity_wrong ^ (~tx_parity_xor);
+ else if (tx_even_parity)
+ tx = tx_parity_wrong ^ tx_parity_xor;
+ else if (tx_stick1_parity)
+ tx = tx_parity_wrong ^ 1;
+ else if (tx_stick0_parity)
+ tx = tx_parity_wrong ^ 0;
+ // Wait for almost 1 bit
+ #(((T_clk_period + T_clk_delay) / 2) * 16 * T_divisor); // wait half period
+ #((((T_clk_period + T_clk_delay) / 2) * 16 * T_divisor) - 2); // wait 2 less than half period
+ end
+
+ // Sending stop bit
+ if (~tx_framing_wrong ||
+ (tx_glitch_num != ((((tx_length + 2'h2 + tx_parity_enabled) * 2) - 1'b1) * 8 * T_divisor)))
+ begin
+ @(posedge tx_clk_divided);
+ tx = 1;
+ // Wait for almost 1 bit
+ #(((T_clk_period + T_clk_delay) / 2) * 16 * T_divisor); // wait half period
+ #((((T_clk_period + T_clk_delay) / 2) * 16 * T_divisor) - 2); // wait 2 less than half period
+ -> device_sent_packet;
+ @(sent_packet_received);
+ end
+ else if (~tx_framing_wrong ||
+ (tx_glitch_num == ((((tx_length + 2'h2 + tx_parity_enabled) * 2) - 1'b1) * 8 * T_divisor)))
+ begin
+ @(posedge tx_clk_divided);
+ tx = 1;
+ // Wait for 1 bit
+ @(posedge tx_clk_divided); // this will be like 2. stop bit
+ -> device_sent_packet;
+ @(sent_packet_received);
+ end
+ else if (tx_framing_wrong && last_tx_data)
+ begin
+ @(posedge tx_clk_divided);
+ // Wrong stop | start bit
+ tx = 0;
+ @(posedge tx_clk_divided);
+ -> device_sent_packet;
+ @(sent_packet_received);
+ tx_framing_wrong = 0;
+ // TX data
+ tx = 1;
+ tx_data = 8'hFF;
+ // Sending tx_data bits
+ for (tx_bit_index = 0; tx_bit_index < tx_length; tx_bit_index = tx_bit_index + 1)
+ begin
+ @(posedge tx_clk_divided);
+ tx = tx_data[tx_bit_index];
+ end
+ // Wait for almost 1 bit
+ #(((T_clk_period + T_clk_delay) / 2) * 16 * T_divisor); // wait half period
+ #((((T_clk_period + T_clk_delay) / 2) * 16 * T_divisor) - 2); // wait 2 less than half period
+
+ sent_data = tx_data;
+
+ // Calculating parity
+ if(tx_length == 5)
+ begin
+ tx_parity_xor = ^tx_data[4:0];
+ end
+ else if(tx_length == 6)
+ begin
+ tx_parity_xor = ^tx_data[5:0];
+ end
+ else if(tx_length == 7)
+ begin
+ tx_parity_xor = ^tx_data[6:0];
+ end
+ else if(tx_length == 8)
+ begin
+ tx_parity_xor = ^tx_data[7:0];
+ end
+ else
+ $display("WRONG length of TX data packet");
+
+ // Sending parity bit
+ if (tx_parity_enabled)
+ begin
+ @(posedge tx_clk_divided);
+ if (tx_odd_parity)
+ tx = tx_parity_wrong ^ (~tx_parity_xor);
+ else if (tx_even_parity)
+ tx = tx_parity_wrong ^ tx_parity_xor;
+ else if (tx_stick1_parity)
+ tx = tx_parity_wrong ^ 1;
+ else if (tx_stick0_parity)
+ tx = tx_parity_wrong ^ 0;
+ // Wait for almost 1 bit
+ #(((T_clk_period + T_clk_delay) / 2) * 16 * T_divisor); // wait half period
+ #((((T_clk_period + T_clk_delay) / 2) * 16 * T_divisor) - 2); // wait 2 less than half period
+ end
+
+ // Stop bit
+ @(posedge tx_clk_divided);
+ tx = 1;
+ // Wait for almost 1 bit
+ #(((T_clk_period + T_clk_delay) / 2) * 16 * T_divisor); // wait half period
+ #((((T_clk_period + T_clk_delay) / 2) * 16 * T_divisor) - 2); // wait 2 less than half period
+ -> device_sent_packet;
+ @(sent_packet_received);
+ tx_framing_wrong = 1'b1;
+ end
+ else if (last_tx_data)
+ begin
+ @(posedge tx_clk_divided);
+ -> device_sent_packet;
+ @(sent_packet_received);
+ end
+ end
+ end
+ endtask // send_packet
+
+
+endmodule
View
320 moxie/cores/uart16550/bench/verilog/uart_device_utilities.v
@@ -0,0 +1,320 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// uart_device_utilities.v ////
+//// ////
+//// This file is part of the "uart16550" project ////
+//// http://www.opencores.org/projects/uart16550/ ////
+//// ////
+//// Author(s): ////
+//// - tadej@opencores.org (Tadej Markovic) ////
+//// ////
+//// All additional information is avaliable in the README.txt ////
+//// file. ////
+//// ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2000 - 2004 authors ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer. ////
+//// ////
+//// This source file is free software; you can redistribute it ////
+//// and/or modify it under the terms of the GNU Lesser General ////
+//// Public License as published by the Free Software Foundation; ////
+//// either version 2.1 of the License, or (at your option) any ////
+//// later version. ////
+//// ////
+//// This source is distributed in the hope that it will be ////
+//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
+//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
+//// PURPOSE. See the GNU Lesser General Public License for more ////
+//// details. ////
+//// ////
+//// You should have received a copy of the GNU Lesser General ////
+//// Public License along with this source; if not, download it ////
+//// from http://www.opencores.org/lgpl.shtml ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//
+// CVS Revision History
+//
+// $Log: not supported by cvs2svn $
+//
+//
+
+
+`include "uart_defines.v"
+`include "uart_testbench_defines.v"
+`include "wb_model_defines.v"
+`include "timescale.v"
+
+module uart_device_utilities;
+
+// UART receiver setting TASKs
+//############################
+
+ // Set RX length
+ task set_rx_length;
+ input [3:0] len;
+ begin
+ `UTILS_MSG("SETTING RX CHAR length.");
+ testbench.i_uart_device.rx_length = len;
+ `UTILS_VAL1("Length:", len);
+ end
+ endtask // set_rx_length
+
+ // Enable RX odd parity
+ task enable_rx_odd_parity;
+ begin
+ `UTILS_MSG("ENABLING RX CHAR odd parity.");
+ testbench.i_uart_device.rx_odd_parity = 1'b1;
+ testbench.i_uart_device.rx_even_parity = 1'b0;
+ testbench.i_uart_device.rx_stick1_parity = 1'b0;
+ testbench.i_uart_device.rx_stick0_parity = 1'b0;
+ testbench.i_uart_device.rx_parity_enabled = 1'b1;
+ end
+ endtask // enable_rx_odd_parity
+
+ // Enable RX even parity
+ task enable_rx_even_parity;
+ begin
+ `UTILS_MSG("ENABLING RX CHAR even parity.");
+ testbench.i_uart_device.rx_odd_parity = 1'b0;
+ testbench.i_uart_device.rx_even_parity = 1'b1;
+ testbench.i_uart_device.rx_stick1_parity = 1'b0;
+ testbench.i_uart_device.rx_stick0_parity = 1'b0;
+ testbench.i_uart_device.rx_parity_enabled = 1'b1;
+ end
+ endtask // enable_rx_even_parity
+
+ // Enable RX stick1 parity
+ task enable_rx_stick1_parity;
+ begin
+ `UTILS_MSG("ENABLING RX CHAR stick1 parity.");
+ testbench.i_uart_device.rx_odd_parity = 1'b0;
+ testbench.i_uart_device.rx_even_parity = 1'b0;
+ testbench.i_uart_device.rx_stick1_parity = 1'b1;
+ testbench.i_uart_device.rx_stick0_parity = 1'b0;
+ testbench.i_uart_device.rx_parity_enabled = 1'b1;
+ end
+ endtask // enable_rx_stick1_parity
+
+ // Enable RX stick0 parity
+ task enable_rx_stick0_parity;
+ begin
+ `UTILS_MSG("ENABLING RX CHAR stick0 parity.");
+ testbench.i_uart_device.rx_odd_parity = 1'b0;
+ testbench.i_uart_device.rx_even_parity = 1'b0;
+ testbench.i_uart_device.rx_stick1_parity = 1'b0;
+ testbench.i_uart_device.rx_stick0_parity = 1'b1;
+ testbench.i_uart_device.rx_parity_enabled = 1'b1;
+ end
+ endtask // enable_rx_stick0_parity
+
+ // Disable RX parity
+ task disable_rx_parity;
+ begin
+ `UTILS_MSG("DISABLING RX CHAR parity.");
+ testbench.i_uart_device.rx_odd_parity = 1'b0;
+ testbench.i_uart_device.rx_even_parity = 1'b0;
+ testbench.i_uart_device.rx_stick1_parity = 1'b0;
+ testbench.i_uart_device.rx_stick0_parity = 1'b0;
+ testbench.i_uart_device.rx_parity_enabled = 1'b0;
+ end
+ endtask // disable_rx_parity
+
+ // Set 1 or 2 (1.5) RX stop bits
+ task set_rx_second_stop_bit;
+ input second_stop_bit;
+ begin
+ if (~second_stop_bit)
+ begin
+ `UTILS_MSG("SETTING RX CHAR 1 stop bit.");
+ end
+ else if (second_stop_bit && (testbench.i_uart_device.rx_length == 5))
+ begin
+ `UTILS_MSG("SETTING RX CHAR 1.5 stop bit.");
+ end
+ else
+ begin
+ `UTILS_MSG("SETTING RX CHAR 2 stop bits.");
+ end
+ testbench.i_uart_device.rx_stop_bit_1 = ~second_stop_bit;
+ testbench.i_uart_device.rx_stop_bit_1_5 = second_stop_bit & (testbench.i_uart_device.rx_length == 5);
+ testbench.i_uart_device.rx_stop_bit_2 = second_stop_bit & (testbench.i_uart_device.rx_length != 5);
+ end
+ endtask // set_rx_second_stop_bit
+
+// UART transmitter setting TASKs
+//###############################
+
+ // Set TX length
+ task set_tx_length;
+ input [3:0] len;
+ begin
+ `UTILS_MSG("SETTING TX CHAR length.");
+ testbench.i_uart_device.tx_length = len;
+ `UTILS_VAL1("Length:", len);
+ end
+ endtask // set_tx_length
+
+ // Enable TX odd parity
+ task enable_tx_odd_parity;
+ begin
+ `UTILS_MSG("ENABLING TX CHAR odd parity.");
+ testbench.i_uart_device.tx_odd_parity = 1'b1;
+ testbench.i_uart_device.tx_even_parity = 1'b0;
+ testbench.i_uart_device.tx_stick1_parity = 1'b0;
+ testbench.i_uart_device.tx_stick0_parity = 1'b0;
+ testbench.i_uart_device.tx_parity_enabled = 1'b1;
+ end
+ endtask // enable_tx_odd_parity
+
+ // Enable TX even parity
+ task enable_tx_even_parity;
+ begin
+ `UTILS_MSG("ENABLING TX CHAR even parity.");
+ testbench.i_uart_device.tx_odd_parity = 1'b0;
+ testbench.i_uart_device.tx_even_parity = 1'b1;
+ testbench.i_uart_device.tx_stick1_parity = 1'b0;
+ testbench.i_uart_device.tx_stick0_parity = 1'b0;
+ testbench.i_uart_device.tx_parity_enabled = 1'b1;
+ end
+ endtask // enable_tx_even_parity
+
+ // Enable TX stick1 parity
+ task enable_tx_stick1_parity;
+ begin
+ `UTILS_MSG("ENABLING TX CHAR stick1 parity.");
+ testbench.i_uart_device.tx_odd_parity = 1'b0;
+ testbench.i_uart_device.tx_even_parity = 1'b0;
+ testbench.i_uart_device.tx_stick1_parity = 1'b1;
+ testbench.i_uart_device.tx_stick0_parity = 1'b0;
+ testbench.i_uart_device.tx_parity_enabled = 1'b1;
+ end
+ endtask // enable_tx_stick1_parity
+
+ // Enable TX stick0 parity
+ task enable_tx_stick0_parity;
+ begin
+ `UTILS_MSG("ENABLING TX CHAR stick0 parity.");
+ testbench.i_uart_device.tx_odd_parity = 1'b0;
+ testbench.i_uart_device.tx_even_parity = 1'b0;
+ testbench.i_uart_device.tx_stick1_parity = 1'b0;
+ testbench.i_uart_device.tx_stick0_parity = 1'b1;
+ testbench.i_uart_device.tx_parity_enabled = 1'b1;
+ end
+ endtask // enable_tx_stick0_parity
+
+ // Disable TX parity
+ task disable_tx_parity;
+ begin
+ `UTILS_MSG("DISABLING TX CHAR parity.");
+ testbench.i_uart_device.tx_odd_parity = 1'b0;
+ testbench.i_uart_device.tx_even_parity = 1'b0;
+ testbench.i_uart_device.tx_stick1_parity = 1'b0;
+ testbench.i_uart_device.tx_stick0_parity = 1'b0;
+ testbench.i_uart_device.tx_parity_enabled = 1'b0;
+ end
+ endtask // disable_tx_parity
+
+ // Correct TX parity
+ task correct_tx_parity;
+ begin
+ `UTILS_MSG("DISABLING WRONG parity generation.");
+ testbench.i_uart_device.tx_parity_wrong = 1'b0;
+ end
+ endtask // correct_tx_parity
+
+ // Wrong TX parity
+ task wrong_tx_parity;
+ begin
+ `UTILS_MSG("ENABLING WRONG parity generation.");
+ testbench.i_uart_device.tx_parity_wrong = 1'b1;
+ end
+ endtask // wrong_tx_parity
+
+ // Correct TX frame
+ task correct_tx_frame;
+ begin
+ `UTILS_MSG("DISABLING WRONG frame generation.");
+ testbench.i_uart_device.tx_framing_wrong = 1'b0;
+ end
+ endtask // correct_tx_frame
+
+ // Wrong TX frame
+ task wrong_tx_frame;
+ begin
+ `UTILS_MSG("ENABLING WRONG frame generation.");
+ testbench.i_uart_device.tx_framing_wrong = 1'b1;
+ end
+ endtask // wrong_tx_frame
+
+ // Generate TX glitch
+ task generate_tx_glitch;
+ input [23:0] generate_glitch_num;
+ begin
+ if (generate_glitch_num == 0)
+ begin
+ `UTILS_MSG("DISABLING 1 TIME glitch generation with CLKs delay.");
+ end
+ else
+ begin
+ `UTILS_MSG("ENABLING 1 TIME glitch generation with CLKs delay.");
+ end
+ testbench.i_uart_device.tx_glitch_num = generate_glitch_num;
+ `UTILS_VAL1("CLKs delay from start bit edge:", generate_glitch_num);
+ end
+ endtask // generate_tx_glitch
+
+ // Enable TX break
+ task enable_tx_break;
+ input [15:0] break_num;
+ begin
+ `UTILS_MSG("ENABLING brake generation with each TX CHAR with brake length.");
+ testbench.i_uart_device.tx_break_enable = 1'b1;
+ testbench.i_uart_device.tx_break_num = break_num;
+ `UTILS_VAL1("Brake bit length:", break_num);
+ end
+ endtask // enable_tx_break
+
+ // Disable TX break
+ task disable_tx_break;
+ begin
+ `UTILS_MSG("DISABLING brake generation with each TX CHAR.");
+ testbench.i_uart_device.tx_break_enable = 1'b0;
+ end
+ endtask // disable_tx_break
+
+// UART transmitter send TASKs
+//############################
+
+ // Send character
+ task send_char;
+ input [7:0] char;
+ begin
+ testbench.i_uart_device.send_packet(1'b0, char, 1);
+ end
+ endtask // Send character
+
+ // Send random character
+ task send_rnd_char;
+ begin
+ testbench.i_uart_device.send_packet(1'b1, 8'h0, 1);
+ end
+ endtask // send_rnd_char
+
+ // Send burst random character
+ task send_burst_rnd_char;
+ input [31:0] num_of_char;
+ integer i;
+ begin
+ testbench.i_uart_device.send_packet(1'b1, 8'h0, num_of_char);
+ end
+ endtask // send_burst_rnd_char
+
+
+endmodule
View
206 moxie/cores/uart16550/bench/verilog/uart_log.v
@@ -0,0 +1,206 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// uart_log.v ////
+//// ////
+//// This file is part of the "uart16550" project ////
+//// http://www.opencores.org/projects/uart16550/ ////
+//// ////
+//// Author(s): ////
+//// - Miha Dolenc, mihad@opencores.org ////
+//// - Tadej Markovic, tadejm@opencores.org ////
+//// ////
+//// All additional information is avaliable in the README.txt ////
+//// file. ////
+//// ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2000 Miha Dolenc, mihad@opencores.org ////
+//// Tadej Markovic, tadejm@opencores.org ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer. ////
+//// ////
+//// This source file is free software; you can redistribute it ////
+//// and/or modify it under the terms of the GNU Lesser General ////
+//// Public License as published by the Free Software Foundation; ////
+//// either version 2.1 of the License, or (at your option) any ////
+//// later version. ////
+//// ////
+//// This source is distributed in the hope that it will be ////
+//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
+//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
+//// PURPOSE. See the GNU Lesser General Public License for more ////
+//// details. ////
+//// ////
+//// You should have received a copy of the GNU Lesser General ////
+//// Public License along with this source; if not, download it ////
+//// from http://www.opencores.org/lgpl.shtml ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//
+// CVS Revision History
+//
+// $Log: not supported by cvs2svn $
+//
+//
+
+// synopsys translate_off
+`include "timescale.v"
+// synopsys translate_on
+
+module uart_log;
+
+
+parameter testcase_name = "";
+
+integer report_log_file_desc;
+integer verbose_log_file_desc;
+
+reg free;
+integer tests_ok;
+integer tests_failed;
+
+initial free = 1;
+initial tests_ok = 0;
+initial tests_failed = 0;
+
+task start_log;
+ output ok_o;
+begin
+ report_log_file_desc = $fopen({"../log/", testcase_name, "_report.log"});
+ verbose_log_file_desc = $fopen({"../log/", testcase_name, "_verbose.log"});
+ if ((report_log_file_desc == 0) || (verbose_log_file_desc == 0))
+ ok_o = 1'b0;
+ else
+ ok_o = 1'b1;
+end
+endtask // start_log
+
+task end_log;
+begin
+ report_add_delimiter;
+ $fdisplay(report_log_file_desc, "TEST CASE execution summary:");
+ $fdisplay(report_log_file_desc, "Number of tests PASSED=%0d", tests_ok);
+ $fdisplay(report_log_file_desc, "Number of tests FAILED=%0d", tests_failed);
+ $fdisplay(report_log_file_desc, " Simulation End Time: %t", $time);
+ report_add_delimiter;
+ $fclose(report_log_file_desc);
+ $fclose(verbose_log_file_desc);
+end
+endtask // end_log
+
+task report_test_name;
+ input [1599:0] test_i;
+begin
+ report_add_delimiter;
+ $fdisplay(report_log_file_desc, "%0s", test_i);
+end
+endtask // report_test_name
+
+task report_test_failed;
+ input [7999:0] message_i;
+begin
+ $fdisplay(report_log_file_desc, " FAILED!");
+ $fdisplay(report_log_file_desc, " Failure message: %0s.", message_i);
+ $fdisplay(report_log_file_desc, " Simulation Time: %t", $time);
+end
+endtask // report_test_failed
+
+task report_test_ok;
+begin
+ $fdisplay(report_log_file_desc, " PASSED!");
+ $fdisplay(report_log_file_desc, " Simulation Time: %t", $time);
+end
+endtask // report_test_ok
+
+task report_add_delimiter;
+begin
+ $fdisplay(report_log_file_desc, "");
+ $fdisplay(report_log_file_desc, "%0s", {75{"-"}});
+ $fdisplay(report_log_file_desc, "");
+end
+endtask // report_add_delimiter
+
+task report_add_text;
+ input [7999:0] text_i;
+begin
+ $fdisplay(report_log_file_desc, " %0s", text_i);
+end
+endtask // report_add_text
+
+task verbose_test_name;
+ input [1599:0] test_i;
+begin
+ free = 0;
+ $fdisplay(verbose_log_file_desc, "");
+ $fdisplay(verbose_log_file_desc, "%0s", {75{"-"}});
+ $fdisplay(verbose_log_file_desc, "- %0s", test_i);
+ $fdisplay(verbose_log_file_desc, "%0s", {75{"-"}});
+ $fdisplay(verbose_log_file_desc, "");
+ free = 1;
+end
+endtask // verbose_test_name
+
+task verbose_severe_err;
+ input [7999:0] time_i;
+ input [7999:0] severe_error_i;
+begin
+ free = 0;
+ $fdisplay(verbose_log_file_desc, "%0s", time_i);
+ $fdisplay(verbose_log_file_desc, "*E, Reporting severe error:");
+ $fdisplay(verbose_log_file_desc, " %0s", severe_error_i);
+ free = 1;
+end
+endtask // verbose_severe_err
+
+task verbose_err;
+ input [7999:0] time_i;
+ input [7999:0] error_i;
+begin
+ free = 0;
+ $fdisplay(verbose_log_file_desc, "%0s", time_i);
+ $fdisplay(verbose_log_file_desc, "*E, %0s", error_i);
+ free = 1;
+end
+endtask // verbose_err
+
+task verbose_wrn;
+ input [7999:0] time_i;
+ input [7999:0] warning_i;
+begin
+ free = 0;
+ $fdisplay(verbose_log_file_desc, "%0s", time_i);
+ $fdisplay(verbose_log_file_desc, "*W, %0s", warning_i);
+ free = 1;
+end
+endtask // verbose_wrn
+
+task verbose_msg;
+ input [7999:0] time_i;
+ input [7999:0] message_i;
+begin
+ free = 0;
+ $fdisplay(verbose_log_file_desc, "%0s", time_i);
+ $fdisplay(verbose_log_file_desc, "*N, %0s", message_i);
+ free = 1;
+end
+endtask // verbose_msg
+
+task verbose_val;
+ input [7999:0] time_i;
+ input [7999:0] message_i;
+ input [31:0] value_i;
+begin
+ free = 0;
+ $fdisplay(verbose_log_file_desc, "%0s", time_i);
+ $fdisplay(verbose_log_file_desc, "*N, %0s %0h.", message_i, value_i);
+ free = 1;
+end
+endtask // verbose_val
+
+
+endmodule // uart_log
+
View
339 moxie/cores/uart16550/bench/verilog/uart_test.v
@@ -0,0 +1,339 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// uart_test.v ////
+//// ////
+//// ////
+//// This file is part of the "UART 16550 compatible" project ////
+//// http://www.opencores.org/cores/uart16550/ ////
+//// ////
+//// Documentation related to this project: ////
+//// - http://www.opencores.org/cores/uart16550/ ////
+//// ////
+//// Projects compatibility: ////
+//// - WISHBONE ////
+//// RS232 Protocol ////
+//// 16550D uart (mostly supported) ////
+//// ////
+//// Overview (main Features): ////
+//// UART core test bench ////
+//// ////
+//// Known problems (limits): ////
+//// A very simple test bench. Creates two UARTS and sends ////
+//// data on to the other. ////
+//// ////
+//// To Do: ////
+//// More complete testing should be done!!! ////
+//// ////
+//// Author(s): ////
+//// - gorban@opencores.org ////
+//// - Jacob Gorban ////
+//// ////
+//// Created: 2001/05/12 ////
+//// Last Updated: 2001/05/17 ////
+//// (See log for the revision history) ////
+//// ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2000 Jacob Gorban, gorban@opencores.org ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer. ////
+//// ////
+//// This source file is free software; you can redistribute it ////
+//// and/or modify it under the terms of the GNU Lesser General ////
+//// Public License as published by the Free Software Foundation; ////
+//// either version 2.1 of the License, or (at your option) any ////
+//// later version. ////
+//// ////
+//// This source is distributed in the hope that it will be ////
+//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
+//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
+//// PURPOSE. See the GNU Lesser General Public License for more ////
+//// details. ////
+//// ////
+//// You should have received a copy of the GNU Lesser General ////
+//// Public License along with this source; if not, download it ////
+//// from http://www.opencores.org/lgpl.shtml ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//
+// CVS Revision History
+//
+// $Log: uart_test.v,v $
+// Revision 1.3 2001/05/31 20:08:01 gorban
+// FIFO changes and other corrections.
+//
+// Revision 1.2 2001/05/17 18:34:18 gorban
+// First 'stable' release. Should be sythesizable now. Also added new header.
+//
+// Revision 1.0 2001-05-17 21:27:12+02 jacob
+// Initial revision
+//
+//
+//`define DATA_BUS_WIDTH_8
+`include "timescale.v"
+module uart_test ();
+
+`include "uart_defines.v"
+
+reg clkr;
+reg wb_rst_ir;
+wire [`UART_ADDR_WIDTH-1:0] wb_adr_i;
+wire [31:0] wb_dat_i;
+wire [31:0] wb_dat_o;
+wire [3:0] wb_sel_i;
+wire pad_stx_o;
+reg pad_srx_ir;
+
+integer e;
+
+uart_top uart_snd(
+ clk,
+
+ // Wishbone signals
+ wb_rst_i, wb_adr_i, wb_dat_i, wb_dat_o, wb_we_i, wb_stb_i, wb_cyc_i, wb_ack_o, wb_sel_i,
+ int_o, // interrupt request
+
+ // UART signals
+ // serial input/output
+ pad_stx_o, pad_srx_i,
+
+ // modem signals
+ rts_o, cts_i, dtr_o, dsr_i, ri_i, dcd_i
+`ifdef UART_HAS_BAUDRATE_OUTPUT
+ , baud1_o
+`endif
+
+
+
+ );
+
+
+// All the signals and regs named with a 1 are receiver fifo signals
+
+wire [`UART_ADDR_WIDTH-1:0] wb1_adr_i;
+wire [31:0] wb1_dat_i;
+wire [31:0] wb1_dat_o;
+wire [3:0] wb1_sel_i;
+wire int1_o;
+wire stx1_o;
+reg srx1_ir;
+
+uart_top uart_rcv(
+ clk,
+
+ // Wishbone signals
+ wb_rst_i, wb1_adr_i, wb1_dat_i, wb1_dat_o, wb1_we_i, wb1_stb_i, wb1_cyc_i, wb1_ack_o, wb1_sel_i,
+ int1_o, // interrupt request
+
+ // UART signals
+ // serial input/output
+ stx1_o, srx1_i,
+
+ // modem signals
+ rts1_o, cts1_i, dtr1_o, dsr1_i, ri1_i, dcd1_i
+`ifdef UART_HAS_BAUDRATE_OUTPUT
+ , baud2_o
+`endif
+
+ );
+
+assign clk = clkr;
+assign wb_rst_i = wb_rst_ir;
+assign pad_srx_i = pad_srx_ir;
+assign cts_i = 1; //cts_ir;
+assign dsr_i = 1; //dsr_ir;
+assign ri_i = 1; //ri_ir;
+assign dcd_i = 1; //dcd_ir;
+
+assign srx1_i = srx1_ir;
+assign cts1_i = 1; //cts1_ir;
+assign dsr1_i = 1; //dsr1_ir;
+assign ri1_i = 1; //ri1_ir;
+assign dcd1_i = 1; //dcd1_ir;
+
+reg [31:0] dat_o;
+/////////// CONNECT THE UARTS
+always @(pad_stx_o)
+begin
+ srx1_ir = pad_stx_o;
+end
+
+initial
+begin
+ clkr = 0;
+ #50000 $finish;
+end
+
+wb_mast wbm(// Outputs
+ .adr (wb_adr_i),
+ .dout (wb_dat_i),
+ .cyc (wb_cyc_i),
+ .stb (wb_stb_i),
+ .sel (wb_sel_i),
+ .we (wb_we_i),
+ // Inputs
+ .clk (clk),
+ .rst (wb_rst_i),
+ .din (wb_dat_o),
+ .ack (wb_ack_o),
+ .err (1'b0),
+ .rty (1'b0));
+
+wb_mast wbm1(// Outputs
+ .adr (wb1_adr_i),
+ .dout (wb1_dat_i),
+ .cyc (wb1_cyc_i),
+ .stb (wb1_stb_i),
+ .sel (wb1_sel_i),
+ .we (wb1_we_i),
+ // Inputs
+ .clk (clk),
+ .rst (wb_rst_i),
+ .din (wb1_dat_o),
+ .ack (wb1_ack_o),
+ .err (1'b0),
+ .rty (1'b0));
+
+// The test sequence
+initial
+begin
+ #1 wb_rst_ir = 1;
+ #10 wb_rst_ir = 0;
+
+ //write to lcr. set bit 7
+ //wb_cyc_ir = 1;
+ wbm.wb_wr1(`UART_REG_LC, 4'b1000, {8'b10011011, 24'b0});
+ // set dl to divide by 3
+ wbm.wb_wr1(`UART_REG_DL1,4'b0001, 32'd2);
+ @(posedge clk);
+ @(posedge clk);
+ // restore normal registers
+ wbm.wb_wr1(`UART_REG_LC, 4'b1000, {8'b00011011, 24'b0}); //00011011
+
+ fork
+ begin
+ $display("%m : %t : sending : %h", $time, 8'b10000001);
+ wbm.wb_wr1(0, 4'b1, 32'b10000001);
+ @(posedge clk);
+ @(posedge clk);
+ $display("%m : %t : sending : %h", $time, 8'b01000010);
+ wbm.wb_wr1(0, 4'b1, 32'b01000010);
+ @(posedge clk);
+ @(posedge clk);
+ $display("%m : %t : sending : %h", $time, 8'b11000011);
+ wbm.wb_wr1(0, 4'b1, 32'b11000011);
+ @(posedge clk);
+ @(posedge clk);
+ $display("%m : %t : sending : %h", $time, 8'b00100100);
+ wbm.wb_wr1(0, 4'b1, 32'b00100100);
+ @(posedge clk);
+ @(posedge clk);
+ $display("%m : %t : sending : %h", $time, 8'b10100101);
+ wbm.wb_wr1(0, 4'b1, 32'b10100101);
+ @(posedge clk);
+ @(posedge clk);
+ $display("%m : %t : sending : %h", $time, 8'b01100110);
+ wbm.wb_wr1(0, 4'b1, 32'b01100110);
+ @(posedge clk);
+ @(posedge clk);
+ $display("%m : %t : sending : %h", $time, 8'b11100111);
+ wbm.wb_wr1(0, 4'b1, 32'b11100111);
+ @(posedge clk);
+ @(posedge clk);
+ $display("%m : %t : sending : %h", $time, 8'b00011000);
+ wbm.wb_wr1(0, 4'b1, 32'b00011000);
+ wait (uart_snd.regs.tstate==0 && uart_snd.regs.transmitter.tf_count==0);
+// disable check;
+ end
+// begin: check
+// end
+ join
+end
+
+always @(int1_o)
+ if (int1_o)
+ $display("INT_O high (%g)", $time);
+ else
+ $display("INT_O low (%g)", $time);
+
+always @(int1_o)
+begin
+ if (int1_o) begin
+ wbm1.wb_rd1(2,4'b0100, dat_o);
+ $display("IIR : %h", dat_o);
+ wbm1.wb_rd1(5,4'b0010, dat_o);
+ $display("LSR : %h", dat_o);
+ wbm1.wb_rd1(0, 4'b1, dat_o);
+ $display("%m : %t : Data out: %h", $time, dat_o);
+ end
+end
+
+// receiver side
+initial
+begin
+ #11;
+ //write to lcr. set bit 7
+ //wb_cyc_ir = 1;
+ wbm1.wb_wr1(`UART_REG_LC, 4'b1000, {8'b10011011, 24'b0});
+ // set dl to divide by 3
+ wbm1.wb_wr1(`UART_REG_DL1, 4'b1, 32'd2);
+ @(posedge clk);
+ @(posedge clk);
+ // restore normal registers
+ wbm1.wb_wr1(`UART_REG_LC, 4'b1000, {8'b00011011, 24'b0});
+ wbm1.wb_wr1(`UART_REG_IE, 4'b0010, {16'b0, 8'b00001111, 8'b0});
+ wait(uart_rcv.regs.receiver.rf_count == 2);
+ e = 800;
+ while (e > 0)
+ begin
+ @(posedge clk)
+ if (uart_rcv.regs.enable) e = e - 1;
+ end
+ wbm1.wb_rd1(0, 4'b1, dat_o);
+ $display("%m : %t : Data out: %h", $time, dat_o);
+ @(posedge clk);
+ wbm1.wb_rd1(0, 4'b1, dat_o);
+ $display("%m : %t : Data out: %h", $time, dat_o);
+ $display("%m : Finish");
+ e = 800;
+ while (e > 0)
+ begin
+ @(posedge clk)
+ if (uart_rcv.regs.enable) e = e - 1;
+ end
+ e = 800;
+ while (e > 0)
+ begin
+ @(posedge clk)
+ if (uart_rcv.regs.enable) e = e - 1;
+ end
+ $finish;
+end
+
+//always @(uart_rcv.regs.rstate)
+//begin
+// $display($time,": Receiver state changed to: ", uart_rcv.regs.rstate);
+//end
+
+initial
+ begin
+ `ifdef DATA_BUS_WIDTH_8
+$display("DATA BUS IS 8");
+`else
+$display("DATA BUS IS 32");
+`endif
+ $display("%d %d", `UART_ADDR_WIDTH, `UART_DATA_WIDTH);
+
+ end
+
+
+always
+begin
+ #5 clkr = ~clk;
+end
+
+endmodule
View
1,363 moxie/cores/uart16550/bench/verilog/uart_testbench.v
@@ -0,0 +1,1363 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// uart_testbench.v ////
+//// ////
+//// This file is part of the "uart16550" project ////
+//// http://www.opencores.org/projects/uart16550/ ////
+//// ////
+//// Author(s): ////
+//// - tadej@opencores.org (Tadej Markovic) ////
+//// ////
+//// All additional information is avaliable in the README.txt ////
+//// file. ////
+//// ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2000 - 2004 authors ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer. ////
+//// ////
+//// This source file is free software; you can redistribute it ////
+//// and/or modify it under the terms of the GNU Lesser General ////
+//// Public License as published by the Free Software Foundation; ////
+//// either version 2.1 of the License, or (at your option) any ////
+//// later version. ////
+//// ////
+//// This source is distributed in the hope that it will be ////
+//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
+//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
+//// PURPOSE. See the GNU Lesser General Public License for more ////
+//// details. ////
+//// ////
+//// You should have received a copy of the GNU Lesser General ////
+//// Public License along with this source; if not, download it ////
+//// from http://www.opencores.org/lgpl.shtml ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//
+// CVS Revision History
+//
+// $Log: not supported by cvs2svn $
+//
+//
+
+
+`include "uart_defines.v"
+`include "uart_testbench_defines.v"
+`include "wb_model_defines.v"
+`include "timescale.v"
+
+module testbench;
+
+
+parameter max_wait_cnt = 20000;
+
+// INTERNAL signals
+//#################
+
+ // WB slave signals
+ //#################
+
+ // UART Wishbone Slave signals
+ wire wb_int_o;
+ wire [`UART_ADDR_WIDTH-1:0] wbs_adr_i;
+ wire [`UART_DATA_WIDTH-1:0] wbs_dat_i;
+ wire [`UART_DATA_WIDTH-1:0] wbs_dat_o;
+ wire [3:0] wbs_sel_i;
+ wire wbs_cyc_i;
+ wire wbs_stb_i;
+ wire [2:0] wbs_cti_i;
+ wire [1:0] wbs_bte_i;
+ wire wbs_we_i;
+ wire wbs_ack_o;
+ wire wbs_rty_o = 1'b0;
+ wire wbs_err_o = 1'b0;
+
+ // UART signals
+ //#############
+
+ // UART Serial Data I/O signals
+ wire stx_pad_o;
+ wire srx_pad_i;
+ // UART Modem I/O signals
+ wire rts_pad_o;
+ wire cts_pad_i;
+ wire dtr_pad_o;
+ wire dsr_pad_i;
+ wire ri_pad_i;
+ wire dcd_pad_i;
+ `ifdef UART_HAS_BAUDRATE_OUTPUT
+ wire baud_o;
+ `endif
+
+ // System signals
+ //###############
+
+ // WB clock signal
+ reg wb_clk; // divided device clock with period T_wb_clk_period
+ // WB clock enable signal
+ reg wb_clk_en = 1'b1;
+ // WB clock period variable
+ real T_wb_clk_period = 20;
+ // WB reset signal
+ reg wb_reset;
+ event reset_aserted;
+ event reset_released;
+ event int_aserted;
+ event int_released;
+ // Error detection event
+ event error_detected;
+
+ // UART register monitor
+ //#########################
+
+ // Line Status Register
+ // Reading LSR register
+ reg lsr_reg_read;
+ // Bit 0 - Data Ready
+ reg lsr_reg_bit0_change_allowed;
+ // Bit 1 - Overrun Error
+ reg lsr_reg_bit1_change_allowed;
+ // Bit 2 - Parity Error
+ reg lsr_reg_bit2_change_allowed;
+ reg [4:0] rx_fifo_par_rd_pointer;
+ integer i2;
+ // Bit 3 - Framing Error
+ reg lsr_reg_bit3_change_allowed;
+ reg [4:0] rx_fifo_frm_rd_pointer;
+ integer i3;
+ // Bit 4 - Break Interrupt
+ reg lsr_reg_bit4_change_allowed;
+ reg [4:0] rx_fifo_brk_rd_pointer;
+ integer i4;
+ // Bit 5 - Transmitter Holding Register Empty
+ reg lsr_reg_bit5_change_allowed;
+ // Bit 6 - Transmitter Empty
+ reg lsr_reg_bit6_change_allowed;
+ // Bit 7 - Error in RX FIFO
+ reg lsr_reg_bit7_change_allowed;
+
+ // UART transmitter monitor
+ //#########################
+
+ // TX FIFO signals
+ reg [7:0] tx_shift_reg;
+ reg tx_shift_reg_empty;
+ reg tx_start_bit_edge;
+ reg [7:0] tx_fifo [0:31];
+ reg [4:0] tx_fifo_wr_pointer;
+ reg [4:0] tx_fifo_rd_pointer;
+ reg [4:0] tx_fifo_status;
+
+ // UART receiver monitor
+ //######################
+
+ // RX FIFO signals
+ reg [7:0] rx_shift_reg;
+ reg rx_shift_reg_full;
+ reg rx_parity_err;
+ reg rx_framing_err;
+ reg rx_framing_glitch;
+ reg rx_break_int;
+ reg rx_overrun_err_occured;
+ reg [7:0] rx_fifo_data [0:31];
+ reg [31:0] rx_fifo_par;
+ reg [31:0] rx_fifo_frm;
+ reg [31:0] rx_fifo_brk;
+ reg [4:0] rx_fifo_wr_pointer;
+ reg [4:0] rx_fifo_rd_pointer;
+ reg [4:0] rx_fifo_status;
+ reg rx_fifo_read;
+
+ // UART register tracker
+ //######################
+
+ // Registers
+ wire [7:0] ier_reg;
+ wire [7:0] iir_reg;
+ wire [7:0] fcr_reg;
+ wire [7:0] lcr_reg;
+ wire [7:0] mcr_reg;
+ wire [7:0] lsr_reg;
+ wire [7:0] msr_reg;
+ wire [7:0] dll_reg;
+ wire [7:0] dlm_reg;
+ // Events
+ event ier_reg_changed;
+ event iir_reg_changed;
+ event fcr_reg_changed;
+ event lcr_reg_changed;
+ event mcr_reg_changed;
+ event lsr_reg_changed;
+ event msr_reg_changed;
+ event dll_reg_changed;
+ event dlm_reg_changed;
+ // Register access
+ reg [`UART_ADDR_WIDTH-1:0] reg_adr;
+ reg [`UART_DATA_WIDTH-1:0] reg_dat;
+ reg reg_dlab;
+ event reg_written;
+ event tx_reg_written;
+ event reg_read;
+ event rx_reg_read;
+
+
+
+uart_top #(`UART_DATA_WIDTH, `UART_ADDR_WIDTH) i_uart_top
+(
+ .wb_clk_i (wb_clk),
+ .wb_rst_i (wb_reset),
+ .int_o (wb_int_o),
+// WB slave signals - 2 address locations for two registers!
+ .wb_cyc_i (wbs_cyc_i),
+ .wb_stb_i (wbs_stb_i),
+ .wb_we_i (wbs_we_i),
+ .wb_sel_i (wbs_sel_i),
+ .wb_adr_i (wbs_adr_i),
+ .wb_dat_i (wbs_dat_i),
+ .wb_dat_o (wbs_dat_o),
+ .wb_ack_o (wbs_ack_o),
+// UART signals
+ .stx_pad_o (stx_pad_o),
+ .srx_pad_i (srx_pad_i),
+// Modem signals
+ .rts_pad_o (rts_pad_o),
+ .cts_pad_i (cts_pad_i),
+ .dtr_pad_o (dtr_pad_o),
+ .dsr_pad_i (dsr_pad_i),
+ .ri_pad_i (ri_pad_i),
+ .dcd_pad_i (dcd_pad_i)
+`ifdef UART_HAS_BAUDRATE_OUTPUT
+ ,
+ .baud_o (baud_o)
+`endif
+);
+
+uart_device i_uart_device
+(
+// UART signals
+ .stx_i (stx_pad_o),
+ .srx_o (srx_pad_i),
+// Modem signals
+ .rts_i (rts_pad_o),
+ .cts_o (cts_pad_i),
+ .dtr_i (dtr_pad_o),
+ .dsr_o (dsr_pad_i),
+ .ri_o (ri_pad_i),
+ .dcd_o (dcd_pad_i)
+);
+
+wb_master_model #(`UART_DATA_WIDTH, `UART_ADDR_WIDTH, 4) i_wb_master_model
+(
+ .wb_rst_i (wb_reset),
+ .wb_clk_i (wb_clk),
+ .wbm_cyc_o (wbs_cyc_i),
+ .wbm_cti_o (),
+ .wbm_bte_o (),
+ .wbm_stb_o (wbs_stb_i),
+ .wbm_we_o (wbs_we_i),
+ .wbm_adr_o (wbs_adr_i),
+ .wbm_sel_o (wbs_sel_i),
+ .wbm_dat_o (wbs_dat_i),
+ .wbm_dat_i (wbs_dat_o),
+ .wbm_ack_i (wbs_ack_o),
+ .wbm_err_i (wbs_err_o), // inactive (1'b0)
+ .wbm_rty_i (wbs_rty_o) // inactive (1'b0)
+);
+
+
+initial
+begin:system
+ // Initial system values
+ wb_reset = 1'b1;
+ wb_clk = 1'b0;
+end
+
+
+// WB clock generation (DEVICE clock is generated in uart_device.v)
+//#################################################################
+
+ // DEVICE's clock generation:
+ // ----------------
+ // // rx_clk rising edge
+ // always@(posedge rx_clk)
+ // if (rx_clk_en)
+ // #(T_clk_period / 2) rx_clk = 1'b0;
+ // // rx_clk falling edge
+ // always@(negedge rx_clk)
+ // if (rx_clk_en)
+ // #(T_clk_period / 2) rx_clk = 1'b1;
+ // ----------------
+ // DEVICE's transmit clocks generation:
+ // ----------------
+ // // tx_clk rising edge
+ // always@(posedge tx_clk)
+ // if (tx_clk_en)
+ // #((T_clk_period / 2) * 16 * T_divisor) tx_clk = 1'b0;
+ // // tx_clk falling edge
+ // always@(negedge tx_clk)
+ // if (tx_clk_en)
+ // #((T_clk_period / 2) * 16 * T_divisor) tx_clk = 1'b1;
+ // ----------------
+
+ // WB clock
+ always@(posedge wb_clk)
+ if (wb_clk_en)
+ #(T_wb_clk_period / 2) wb_clk = 1'b0;
+ always@(negedge wb_clk)
+ if (wb_clk_en)
+ #(T_wb_clk_period / 2) wb_clk = 1'b1;
+
+
+// SYSTEM signals tracker
+//#######################
+
+ // Reset
+ always@(posedge wb_reset)
+ -> reset_aserted;
+ always@(negedge wb_reset)
+ -> reset_released;
+
+ // Interrupt
+ always@(posedge wb_int_o)
+ -> int_aserted;
+ always@(negedge wb_int_o)
+ -> int_released;
+
+
+// UART register tracker
+//######################
+
+ // UART registers:
+ // ----------------
+ // RBR (R/ | ADR 0 | DLAB 0)
+ // [7:0] -RX---- "rxdata" Receiver Buffer Register
+ // ----------------
+ // THR ( /W | ADR 0 | DLAB 0)
+ // [7:0] ----TX- "txdata" Transmitter Holding Register
+ // ----------------
+ // IER (R/W | ADR 1 | DLAB 0)
+ // [0] -RX---- "1" Received Data Available & Receive Fifo Timeout
+ // [1] ----TX- "1" Transmitter Holding Register Empty
+ // [2] -RX---- "1" Receiver Line Status
+ // [3] -MODEM- "1" Modem Status
+ // ----------------
+ // IIR (R/ | ADR 2)
+ // [0] ------- "0" Interrupt is Pending (decreasing priority level in following 3 bits)
+ // [3:1] -RX---- "011" Receiver Line Status - Overrun, Parity, Framing error or Break int. ---> READ LSR
+ // [3:1] -RX---- "010" Received Data Available - Fifo Trigger Level Reached ------------------> READ RBR (Fifo lower than trig.)
+ // [3:1] -RX---- "110" Timeout Indication - Fifo not empty & no Fifo action for 4 char times -> READ RBR
+ // [3:1] ----TX- "001" Transmitter Holding Register Empty - THR Empty ------------------------> READ IIR | WRITE THR
+ // [3:1] -MODEM- "000" Modem Status - CTS, DSR, DCD changed or RI changed from '0' to '1' ----> READ MSR
+ // ----------------
+ // FCR ( /W | ADR 2)
+ // [1] -RX---- "1" Clear only Receiver Fifo (not shift register)
+ // [2] ----TX- "1" Clear only Transmitter Fifo (not shift register)
+ // [7:6] -RX---- "00" 1 BYTE Receiver Fifo Interrupt trigger level
+ // [7:6] -RX---- "01" 4 BYTEs Receiver Fifo Interrupt trigger level
+ // [7:6] -RX---- "10" 8 BYTEs Receiver Fifo Interrupt trigger level
+ // [7:6] -RX---- "11" 14 BYTEs Receiver Fifo Interrupt trigger level
+ // ----------------
+ // LCR (R/W | ADR 3)
+ // [1:0] -RX-TX- "00" 5 bits in each character
+ // [1:0] -RX-TX- "01" 6 bits in each character
+ // [1:0] -RX-TX- "10" 7 bits in each character
+ // [1:0] -RX-TX- "11" 8 bits in each character
+ // [2] -RX-TX- "0" 1 stop bit
+ // [2] -RX-TX- "1" 1.5 stop bits (when 5 bits of char.) or 2 stop bits (when 6, 7 or 8 bits of char.)
+ // [3] -RX-TX- "1" Parity bit enabled
+ // [5:4] -RX-TX- "00" NO Stick Parity & ODD Parity bit - ODD num. of '1's is transmitted
+ // [5:4] -RX-TX- "01" NO Stick Parity & EVEN Parity bit - EVEN num. of '1's is transmitted
+ // [5:4] -RX-TX- "10" Stick Parity bit - Stick '1' as Parity bit
+ // [5:4] -RX-TX- "11" Stick Parity bit - Stick '0' as Parity bit
+ // [6] ----TX- "1" Break Control - Output is forced to '0'
+ // [7] ------- "1" DLAB - for access to DLL and DLM
+ // ----------------
+ // MCR ( /W | ADR 4)
+ // [0] -MODEM- "1" Force DTR to '0' - in LoopBack connected to DSR input
+ // [1] -MODEM- "1" Force RTS to '0' - in LoopBack connected to CTS input
+ // [2] -MODEM- "1" Force N.C.1 to '0' - in LoopBack connected to RI input
+ // [3] -MODEM- "1" Force N.C.2 to '0' - in LoopBack connected to DCD input
+ // [4] -MODEM- "1" LoopBack mode
+ // ----------------
+ // LSR (R/ | ADR 5)
+ // [0] -RX---- "1" Data Ready - At least 1 char. received and is in Fifo----------> READ RBR (Fifo empty)
+ // [1] -RX---- "1" Overrun Error - Fifo full & 1 char. received in shift reg. ----> READ LSR
+ // [2] -RX---- "1" Parity Error - top Fifo char. has invalid parity bit ----------> READ LSR
+ // [3] -RX---- "1" Framing Error - top Fifo char. has invalid stop bit -----------> READ LSR
+ // [4] -RX---- "1" Break Int. - top Fifo char. bits are '0' and it's ctrl. bits --> READ LSR
+ // [5] ----TX- "1" Transmitter Holding Register Empty - transmitter Fifo empty ---> WRITE THR
+ // [6] ----TX- "1" Transmitter EMpTy - transmitter Fifo empty & shift reg. empty -> WRITE THR
+ // [7] -RX---- "1" At least 1 Parity Error, Framing Error or Break Int. in Fifo --> READ LSR & No More Errors in Fifo
+ // ----------------
+ // MSR (R/ | ADR 6)
+ // [0] -MODEM- "1" Delta CTS indicator - CTS has changed it's state --------------> READ MSR
+ // [1] -MODEM- "1" Delta DSR indicator - DSR has changed it's state --------------> READ MSR
+ // [2] -MODEM- "1" Trailing Edge of RI - RI has changed from '0' to '1' ----------> READ MSR
+ // [3] -MODEM- "1" Delta DCD indicator - DCD has changed it's state --------------> READ MSR
+ // [4] -MODEM- "x" Complement of CTS input | in LoopBack equal to RTS = MCR[1]
+ // [5] -MODEM- "x" Complement of DSR input | in LoopBack equal to DTR = MCR[0]
+ // [6] -MODEM- "x" Complement of RI input | in LoopBack equal to N.C.1 = MCR[2]
+ // [7] -MODEM- "x" Complement of DCD input | in LoopBack equal to N.C.2 = MCR[3]
+ // ----------------
+ // DLL (R/W | ADR 0 | DLAB 1)
+ // [7:0] ------- "dl[ 7:0]" LSB of DL Reg. written 2. - dl == '0' disables outputs / dl = 1/(T_wb_clk_period*16*BaudRate)
+ // ----------------
+ // DLM (R/W | ADR 1 | DLAB 1)
+ // [7:0] ------- "dl[15:8]" MSB of DL Reg. written 1. - dl == '0' disables outputs / dl = 1/(T_wb_clk_period*16*BaudRate)
+ // ----------------
+
+ // Transparent UART registers
+ assign ier_reg[7:0] = {4'h0, testbench.i_uart_top.regs.ier };
+ assign iir_reg[7:0] = {4'hC, testbench.i_uart_top.regs.iir };
+ assign fcr_reg[7:0] = { testbench.i_uart_top.regs.fcr, 6'h0};
+ assign lcr_reg[7:0] = { testbench.i_uart_top.regs.lcr }; // lcr_reg[7] == DLAB !!!
+ assign mcr_reg[7:0] = {3'h0, testbench.i_uart_top.regs.mcr };
+ assign lsr_reg[7:0] = { testbench.i_uart_top.regs.lsr };
+ assign msr_reg[7:0] = { testbench.i_uart_top.regs.msr };
+ assign dll_reg[7:0] = { testbench.i_uart_top.regs.dl[ 7:0] };
+ assign dlm_reg[7:0] = { testbench.i_uart_top.regs.dl[15:8] };
+
+ // Tracking changes of registers
+ always@(ier_reg)
+ begin
+ -> ier_reg_changed;
+ end
+ always@(iir_reg)
+ begin
+ -> iir_reg_changed;
+ end
+ always@(fcr_reg)
+ begin
+ -> fcr_reg_changed;
+ end
+ always@(lcr_reg)
+ begin
+ -> lcr_reg_changed;
+ end
+ always@(mcr_reg)
+ begin
+ -> mcr_reg_changed;
+ end
+ always@(lsr_reg)
+ begin
+ -> lsr_reg_changed;
+ end
+ always@(msr_reg)
+ begin
+ -> msr_reg_changed;
+ end
+ always@(dll_reg)
+ begin
+ -> dll_reg_changed;
+ end
+ always@(dlm_reg)
+ begin
+ -> dlm_reg_changed;
+ end
+
+ // Tracking read/write access to registers