URL
https://opencores.org/ocsvn/uart16550/uart16550/trunk
Subversion Repositories uart16550
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 92 to Rev 93
- ↔ Reverse comparison
Rev 92 → Rev 93
/trunk/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 |
|
/trunk/bench/verilog/uart_wb_utilities.v
0,0 → 1,359
////////////////////////////////////////////////////////////////////// |
//// //// |
//// uart_wb_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_wb_utilities; |
|
// Single read/write TASKs |
//######################## |
|
// SINGLE_READ |
task single_read; |
input [`UART_ADDR_WIDTH-1:0] read_adr_i; |
reg [3:0] read_sel_i; |
reg `WBM_MODEL_READ_IN_TYPE read_stim; |
reg `WBM_MODEL_READ_OUT_TYPE read_result; |
integer master_waits; |
integer slave_waits; |
integer num_of_reads; |
reg fast_b2b; |
begin |
read_sel_i = 4'hF; |
testbench.i_wb_master_model.next_read_adr = read_adr_i; |
testbench.i_wb_master_model.next_read_sel = read_sel_i; |
testbench.i_wb_master_model.next_read_cti = 3'b000; // Clasic WB |
testbench.i_wb_master_model.next_read_bte = $random; // Don't care hwen Clasic WB |
master_waits = {$random} % 13; |
slave_waits = 4; |
num_of_reads = 1; |
fast_b2b = 1'b0; |
read_stim`WBM_MODEL_READ_WAITS = master_waits; |
read_stim`WBM_MODEL_READ_ALLOWED_SLAVE_WAITS = slave_waits; |
read_stim`WBM_MODEL_READ_LAST = (num_of_reads == 1); |
read_stim`WBM_MODEL_READ_FAST_B2B = fast_b2b; |
// Start read |
testbench.i_wb_master_model.start_read(read_stim, read_result); |
// ACK response |
if (read_result`WBM_MODEL_READ_SLAVE_ACK !== 1'b1) |
begin |
`TC_ERROR("Wishbone master model did not receive expected transfer termination from the design."); |
end |
// |
if (read_result`WBM_MODEL_READ_STIM_ERR !== 1'b0) |
begin |
`TC_ERROR("No reads done since design's wishbone slave interface responded with an error."); |
end |
// |
if (read_result`WBM_MODEL_READ_DESIGN_ERR !== 1'b0) |
begin |
`TC_ERROR("Wishbone master model detected a design response error during single read access."); |
end |
end |
endtask // single_read |
|
// SINGLE_WRITE |
task single_write; |
input [`UART_ADDR_WIDTH-1:0] write_adr_i; |
input [`UART_DATA_WIDTH-1:0] write_dat_i; |
reg [3:0] write_sel_i; |
reg `WBM_MODEL_WRITE_IN_TYPE write_stim; |
reg `WBM_MODEL_WRITE_OUT_TYPE write_result; |
integer master_waits; |
integer slave_waits; |
integer num_of_writes; |
reg fast_b2b; |
begin |
write_sel_i = 4'hF; |
testbench.i_wb_master_model.next_write_adr = write_adr_i; |
testbench.i_wb_master_model.next_write_sel = write_sel_i; |
testbench.i_wb_master_model.next_write_dat = write_dat_i; |
testbench.i_wb_master_model.next_write_cti = 3'b000; // Clasic WB |
testbench.i_wb_master_model.next_write_bte = $random; // Don't care hwen Clasic WB |
master_waits = {$random} % 13; |
slave_waits = 4; |
num_of_writes = 1; |
fast_b2b = 1'b0; |
write_stim`WBM_MODEL_WRITE_WAITS = master_waits; |
write_stim`WBM_MODEL_WRITE_ALLOWED_SLAVE_WAITS = slave_waits; |
write_stim`WBM_MODEL_WRITE_LAST = (num_of_writes == 1); |
write_stim`WBM_MODEL_WRITE_FAST_B2B = fast_b2b; |
// Start write |
testbench.i_wb_master_model.start_write(write_stim, write_result); |
// ACK response |
if (write_result`WBM_MODEL_WRITE_SLAVE_ACK !== 1'b1) |
begin |
`TC_ERROR("Wishbone master model did not receive expected transfer termination from the design."); |
end |
// |
if (write_result`WBM_MODEL_WRITE_STIM_ERR !== 1'b0) |
begin |
`TC_ERROR("No writes done since wishbone master model reported an error."); |
end |
// |
if (write_result`WBM_MODEL_WRITE_DESIGN_ERR !== 1'b0) |
begin |
`TC_ERROR("Wishbone master model detected a design response error during single write access."); |
end |
end |
endtask // single_write |
|
// Char read/write TASKs |
//###################### |
|
// READ_CHAR |
task read_char; |
begin |
if (testbench.lcr_reg[7] === 1'b1) // dlab == 1 |
begin |
`UTILS_ERROR("READING of CHAR from RB Register NOT possible, since DLAB in LC Register is set."); |
end |
else |
begin |
`UTILS_MSG("READING of CHAR from UART's RB Register."); |
single_read(`UART_REG_RB); |
`UTILS_VAL1("Read RBR =", testbench.i_wb_master_model.read_dat); |
end |
end |
endtask // read_char |
|
// WRITE_CHAR |
task write_char; |
input [7:0] char_i; |
begin |
if (testbench.lcr_reg[7] === 1'b1) // dlab == 1 |
begin |
`UTILS_ERROR("WRITING CHAR to TR Register NOT possible, since DLAB in LC Register is set."); |
end |
else |
begin |
`UTILS_MSG("WRITING CHAR to UART's TR Register."); |
single_write(`UART_REG_TR, char_i); |
`UTILS_VAL1("Write TRR =", testbench.i_wb_master_model.write_dat); |
end |
end |
endtask // write_char |
|
// Register read/write TASKs |
//########################## |
|
// READ_IER - adr 1 |
task read_ier; |
begin |
if (testbench.lcr_reg[7] === 1'b1) // dlab == 1 |
begin |
`UTILS_ERROR("READING of IE Register NOT possible, since DLAB in LC Register is set."); |
end |
else |
begin |
`UTILS_MSG("READING UART's IE Register."); |
single_read(`UART_REG_IE); |
`UTILS_VAL1("Read IER =", testbench.i_wb_master_model.read_dat); |
end |
end |
endtask // read_ier |
|
// WRITE_IER - adr 1 |
task write_ier; |
input [7:0] data_i; |
begin |
if (testbench.lcr_reg[7] === 1'b1) // dlab == 1 |
begin |
`UTILS_ERROR("WRITING to IE Register NOT possible, since DLAB in LC Register is set."); |
end |
else |
begin |
`UTILS_MSG("WRITING UART's IE Register."); |
single_write(`UART_REG_IE, data_i); |
`UTILS_VAL1("Write IER =", testbench.i_wb_master_model.write_dat); |
end |
end |
endtask // write_ier |
|
// READ_IIR - adr 2 |
task read_iir; |
begin |
`UTILS_MSG("READING UART's II Register."); |
single_read(`UART_REG_II); |
`UTILS_VAL1("Read IIR =", testbench.i_wb_master_model.read_dat); |
end |
endtask // read_iir |
|
// WRITE_FCR - adr 2 |
task write_fcr; |
input [7:0] data_i; |
begin |
`UTILS_MSG("WRITING UART's FC Register."); |
single_write(`UART_REG_FC, data_i); |
`UTILS_VAL1("Write FCR =", testbench.i_wb_master_model.write_dat); |
end |
endtask // write_fcr |
|
// READ_LCR - adr 3 |
task read_lcr; |
begin |
`UTILS_MSG("READING UART's LC Register."); |
single_read(`UART_REG_LC); |
`UTILS_VAL1("Read LCR =", testbench.i_wb_master_model.read_dat); |
end |
endtask // read_lcr |
|
// WRITE_LCR - adr 3 |
task write_lcr; |
input [7:0] data_i; |
begin |
`UTILS_MSG("WRITING UART's LC Register."); |
single_write(`UART_REG_LC, data_i); |
`UTILS_VAL1("Write LCR =", testbench.i_wb_master_model.write_dat); |
end |
endtask // write_lcr |
|
// WRITE_MCR - adr 4 |
task write_mcr; |
input [7:0] data_i; |
begin |
`UTILS_MSG("WRITING UART's MC Register."); |
single_write(`UART_REG_MC, data_i); |
`UTILS_VAL1("Write MCR =", testbench.i_wb_master_model.write_dat); |
end |
endtask // write_mcr |
|
// READ_LSR - adr 5 |
task read_lsr; |
begin |
`UTILS_MSG("READING UART's LS Register."); |
single_read(`UART_REG_LS); |
`UTILS_VAL1("Read LSR =", testbench.i_wb_master_model.read_dat); |
end |
endtask // read_lsr |
|
// READ_MSR - adr 6 |
task read_msr; |
begin |
`UTILS_MSG("READING UART's MS Register."); |
single_read(`UART_REG_MS); |
`UTILS_VAL1("Read MSR =", testbench.i_wb_master_model.read_dat); |
end |
endtask // read_msr |
|
// READ_DLR - adr 0, 1 |
task read_dlr; |
begin |
if (testbench.lcr_reg[7] === 1'b0) // dlab == 0 |
begin |
// Setting DLAB |
`UTILS_MSG("DLAB in LC Register is going to be 1."); |
`UTILS_VAL1("Current LCR =", testbench.lcr_reg); |
write_lcr(testbench.lcr_reg | 8'h80); |
// Reading DL Register |
`UTILS_MSG("READING UART's DL Register [15:8]."); |
single_read(`UART_REG_DL2); |
`UTILS_VAL1("Read DLR [15:8] =", testbench.i_wb_master_model.read_dat); |
`UTILS_MSG("READING UART's DL Register [ 7:0]."); |
single_read(`UART_REG_DL1); |
`UTILS_VAL1("Read DLR [ 7:0] =", testbench.i_wb_master_model.read_dat); |
// Resetting DLAB |
`UTILS_MSG("DLAB in LC Register is going to be 0."); |
write_lcr(testbench.lcr_reg & 8'h7F); |
end |
else |
begin |
`UTILS_MSG("DLAB in LC Register is already 1."); |
`UTILS_VAL1("Current LCR =", testbench.lcr_reg); |
// Reading DL Register |
`UTILS_MSG("READING UART's DL Register [15:8]."); |
single_read(`UART_REG_DL2); |
`UTILS_VAL1("Read DLR [15:8] =", testbench.i_wb_master_model.read_dat); |
`UTILS_MSG("READING UART's DL Register [ 7:0]."); |
single_read(`UART_REG_DL1); |
`UTILS_VAL1("Read DLR [ 7:0] =", testbench.i_wb_master_model.read_dat); |
end |
end |
endtask // read_dlr |
|
// WRITE_DLR - adr 0, 1 |
task write_dlr; |
input [15:0] data_i; |
begin |
if (testbench.lcr_reg[7] === 1'b0) // dlab == 0 |
begin |
// Setting DLAB |
`UTILS_MSG("DLAB in LC Register is going to be 1."); |
`UTILS_VAL1("Current LCR =", testbench.lcr_reg); |
write_lcr(testbench.lcr_reg | 8'h80); |
// Writing DL Register |
`UTILS_MSG("WRITING UART's DL Register [15:8]."); |
single_write(`UART_REG_DL2, data_i[15:8]); |
`UTILS_VAL1("Write DLR [15:8] =", testbench.i_wb_master_model.write_dat); |
`UTILS_MSG("WRITING UART's DL Register [ 7:0]."); |
single_write(`UART_REG_DL1, data_i[ 7:0]); |
`UTILS_VAL1("Write DLR [ 7:0] =", testbench.i_wb_master_model.write_dat); |
// Resetting DLAB |
`UTILS_MSG("DLAB in LC Register is going to be 0."); |
write_lcr(testbench.lcr_reg & 8'h7F); |
end |
else |
begin |
`UTILS_MSG("DLAB in LC Register is already 1."); |
`UTILS_VAL1("Current LCR =", testbench.lcr_reg); |
// Writing DL Register |
`UTILS_MSG("WRITING UART's DL Register [15:8]."); |
single_write(`UART_REG_DL2, data_i[15:8]); |
`UTILS_VAL1("Write DLR [15:8] =", testbench.i_wb_master_model.write_dat); |
`UTILS_MSG("WRITING UART's DL Register [ 7:0]."); |
single_write(`UART_REG_DL1, data_i[ 7:0]); |
`UTILS_VAL1("Write DLR [ 7:0] =", testbench.i_wb_master_model.write_dat); |
end |
end |
endtask // write_dlr |
|
|
endmodule |
/trunk/bench/verilog/wb_master_model.v
0,0 → 1,841
////////////////////////////////////////////////////////////////////// |
//// //// |
//// wb_master_model.v //// |
//// //// |
//// This file is part of the "uart16550" project //// |
//// http://www.opencores.org/projects/uart16550/ //// |
//// //// |
//// Author(s): //// |
//// - mihad@opencores.org (Miha Dolenc) //// |
//// //// |
//// 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 "wb_model_defines.v" |
`include "timescale.v" |
|
module wb_master_model |
( |
wb_rst_i , |
wb_clk_i , |
wbm_cyc_o , |
wbm_cti_o , |
wbm_bte_o , |
wbm_stb_o , |
wbm_we_o , |
wbm_adr_o , |
wbm_sel_o , |
wbm_dat_o , |
wbm_dat_i , |
wbm_ack_i , |
wbm_err_i , |
wbm_rty_i |
); |
|
// set the parameters to impossible values, so errors will be detected at compile time |
parameter wb_dat_width = 1 ; |
parameter wb_adr_width = 1 ; |
parameter wb_sel_width = 1 ; |
|
real Tperiod ; |
|
input wb_rst_i , |
wb_clk_i ; |
|
output wbm_cyc_o ; |
reg wbm_cyc_o ; |
|
output [ 2: 0] wbm_cti_o ; |
reg [ 2: 0] wbm_cti_o ; |
|
output [ 1: 0] wbm_bte_o ; |
reg [ 1: 0] wbm_bte_o ; |
|
output wbm_stb_o ; |
reg wbm_stb_o ; |
|
output wbm_we_o ; |
reg wbm_we_o ; |
|
output [wb_adr_width - 1:0] wbm_adr_o ; |
reg [wb_adr_width - 1:0] wbm_adr_o ; |
|
output [wb_sel_width - 1:0] wbm_sel_o ; |
reg [wb_sel_width - 1:0] wbm_sel_o ; |
|
output [wb_dat_width - 1:0] wbm_dat_o ; |
reg [wb_dat_width - 1:0] wbm_dat_o ; |
|
input [wb_dat_width - 1:0] wbm_dat_i ; |
|
input wbm_ack_i ; |
|
input wbm_err_i ; |
|
input wbm_rty_i ; |
|
event write_transfer ; |
event read_transfer ; |
|
reg [wb_adr_width - 1:0] write_adr ; |
reg [wb_sel_width - 1:0] write_sel ; |
reg [wb_dat_width - 1:0] write_dat ; |
|
reg [wb_adr_width - 1:0] read_adr ; |
reg [wb_sel_width - 1:0] read_sel ; |
reg [wb_dat_width - 1:0] read_dat ; |
|
reg [wb_adr_width - 1:0] next_write_adr ; |
reg [wb_sel_width - 1:0] next_write_sel ; |
reg [wb_dat_width - 1:0] next_write_dat ; |
reg [ 2: 0] next_write_cti ; |
reg [ 1: 0] next_write_bte ; |
|
event write_accepted ; |
event write_request ; |
|
reg [wb_adr_width - 1:0] next_read_adr ; |
reg [wb_sel_width - 1:0] next_read_sel ; |
reg [ 2: 0] next_read_cti ; |
reg [ 1: 0] next_read_bte ; |
|
event read_accepted ; |
event read_request ; |
|
real Tsetup ; |
real Thold ; |
|
initial Tsetup = 0.0 ; |
initial Thold = 0.0 ; |
|
reg reset_done ; |
initial reset_done = 1'b0 ; |
|
event error_event ; |
reg [ 799: 0] error_message ; |
|
initial |
fork |
begin |
forever |
begin |
@(wb_rst_i) ; |
if ((wb_rst_i ^ wb_rst_i) !== 1'b0) |
begin |
reset_done = 1'b0 ; |
error_message = "Invalid WISHBONE reset line value detected" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
end |
|
if (wb_rst_i === `WB_MODEL_RST_ACTIVE) |
begin |
reset_done = 1'b0 ; |
end |
end |
end |
begin |
forever |
begin |
@(wb_rst_i) ; |
if (wb_rst_i === `WB_MODEL_RST_ACTIVE) |
begin |
@(posedge wb_clk_i or wb_rst_i) ; |
if (wb_rst_i !== `WB_MODEL_RST_ACTIVE) |
begin |
error_message = "Reset de-activated prior to at least one positive clock transition" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
end |
else |
begin |
reset_done = 1'b1 ; |
end |
end |
end |
end |
join |
|
always@(wb_rst_i) |
begin |
if (wb_rst_i === `WB_MODEL_RST_ACTIVE) |
wbm_cyc_o <= 1'b0 ; |
end |
|
reg access_in_progress ; |
initial access_in_progress = 1'b0 ; |
|
task start_write ; |
input `WBM_MODEL_WRITE_IN_TYPE write_stim_i ; |
output `WBM_MODEL_WRITE_OUT_TYPE write_res_o ; |
reg [31: 0] num_of_slave_waits ; |
reg end_access ; |
begin:main |
|
write_res_o = 'h0 ; |
|
if (access_in_progress === 1'b1) |
begin |
error_message = "Task called when some other access was in progress" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
write_res_o`WBM_MODEL_WRITE_STIM_ERR = 1'b1 ; |
disable main ; |
end |
|
if (reset_done !== 1'b1) |
begin |
error_message = "Task called before reset was applied to the design" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
write_res_o`WBM_MODEL_WRITE_STIM_ERR = 1'b1 ; |
disable main ; |
end |
|
access_in_progress = 1'b1 ; |
end_access = write_stim_i`WBM_MODEL_WRITE_LAST ; |
|
if (write_stim_i`WBM_MODEL_WRITE_FAST_B2B !== 1'b1) |
@(posedge wb_clk_i) ; |
|
wbm_cyc_o <= #(Tperiod - Tsetup) 1'b1 ; |
|
insert_waits(write_stim_i`WBM_MODEL_WRITE_WAITS, 'h0, num_of_slave_waits) ; |
|
if ((num_of_slave_waits ^ num_of_slave_waits) === 'h0) |
begin |
error_message = "Slave responded to initial write access" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
end |
|
num_of_slave_waits = 0 ; |
|
wbm_stb_o <= #(Tperiod - Tsetup) 1'b1 ; |
wbm_we_o <= #(Tperiod - Tsetup) 1'b1 ; |
wbm_adr_o <= #(Tperiod - Tsetup) next_write_adr ; |
wbm_dat_o <= #(Tperiod - Tsetup) get_write_dat(next_write_dat, next_write_sel) ; |
wbm_sel_o <= #(Tperiod - Tsetup) next_write_sel ; |
wbm_cti_o <= #(Tperiod - Tsetup) next_write_cti ; |
wbm_bte_o <= #(Tperiod - Tsetup) next_write_bte ; |
|
-> write_accepted ; |
|
@(posedge wb_clk_i) ; |
|
while((wbm_ack_i === 1'b0) & (wbm_err_i === 1'b0) & (wbm_rty_i === 1'b0) & (num_of_slave_waits < write_stim_i`WBM_MODEL_WRITE_ALLOWED_SLAVE_WAITS)) |
begin |
num_of_slave_waits = num_of_slave_waits + 1'b1 ; |
write_adr = wbm_adr_o ; |
write_sel = wbm_sel_o ; |
write_dat = wbm_dat_o ; |
-> write_request ; |
@(posedge wb_clk_i) ; |
end |
|
if ((wbm_ack_i === 1'b0) & (wbm_err_i === 1'b0) & (wbm_rty_i === 1'b0)) |
begin |
error_message = "Cycle terminated because allowed number of slave wait states constraint violation" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
end_access = 1'b1 ; |
write_res_o`WBM_MODEL_WRITE_DESIGN_ERR = 1'b1 ; |
end |
else if ((wbm_ack_i + wbm_err_i + wbm_rty_i) !== 'h1) |
begin |
error_message = "Cycle terminated because invalid slave response was received" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
end_access = 1'b1 ; |
write_res_o`WBM_MODEL_WRITE_DESIGN_ERR = 1'b1 ; |
end |
else |
begin |
write_res_o`WBM_MODEL_WRITE_SLAVE_WAITS = num_of_slave_waits ; |
write_res_o`WBM_MODEL_WRITE_SLAVE_ACK = wbm_ack_i ; |
write_res_o`WBM_MODEL_WRITE_SLAVE_ERR = wbm_err_i ; |
write_res_o`WBM_MODEL_WRITE_SLAVE_RTY = wbm_rty_i ; |
|
if (wbm_ack_i === 1'b1) |
begin |
write_adr = wbm_adr_o ; |
write_dat = wbm_dat_o ; |
write_sel = wbm_sel_o ; |
-> write_transfer ; |
end |
end |
|
if (end_access) |
begin |
wbm_cyc_o <= #(Thold) 1'b0 ; |
wbm_stb_o <= #(Thold) 1'bx ; |
wbm_we_o <= #(Thold) 1'bx ; |
wbm_sel_o <= #(Thold) 'hx ; |
wbm_adr_o <= #(Thold) 'hx ; |
wbm_dat_o <= #(Thold) 'hx ; |
wbm_cti_o <= #(Thold) 'hx ; |
wbm_bte_o <= #(Thold) 'hx ; |
access_in_progress = 1'b0 ; |
end |
end |
endtask // start_write |
|
task subsequent_write ; |
input `WBM_MODEL_WRITE_IN_TYPE write_stim_i ; |
output `WBM_MODEL_WRITE_OUT_TYPE write_res_o ; |
reg [31: 0] num_of_slave_waits ; |
reg end_access ; |
begin:main |
|
write_res_o = 'h0 ; |
|
if (access_in_progress !== 1'b1) |
begin |
error_message = "Task called when no access was in progress" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
write_res_o`WBM_MODEL_WRITE_STIM_ERR = 1'b1 ; |
disable main ; |
end |
|
end_access = write_stim_i`WBM_MODEL_WRITE_LAST ; |
|
insert_waits(write_stim_i`WBM_MODEL_WRITE_WAITS, 'h0, num_of_slave_waits) ; |
|
if ((num_of_slave_waits ^ num_of_slave_waits) !== 'h0) |
begin |
num_of_slave_waits = write_stim_i`WBM_MODEL_WRITE_WAITS ; |
end |
|
wbm_stb_o <= #(Tperiod - Tsetup) 1'b1 ; |
wbm_we_o <= #(Tperiod - Tsetup) 1'b1 ; |
wbm_adr_o <= #(Tperiod - Tsetup) next_write_adr ; |
wbm_dat_o <= #(Tperiod - Tsetup) get_write_dat(next_write_dat, next_write_sel) ; |
wbm_sel_o <= #(Tperiod - Tsetup) next_write_sel ; |
wbm_cti_o <= #(Tperiod - Tsetup) next_write_cti ; |
wbm_bte_o <= #(Tperiod - Tsetup) next_write_bte ; |
|
-> write_accepted ; |
|
@(posedge wb_clk_i) ; |
|
while((wbm_ack_i === 1'b0) & (wbm_err_i === 1'b0) & (wbm_rty_i === 1'b0) & (num_of_slave_waits < write_stim_i`WBM_MODEL_WRITE_ALLOWED_SLAVE_WAITS)) |
begin |
num_of_slave_waits = num_of_slave_waits + 1'b1 ; |
write_adr = wbm_adr_o ; |
write_sel = wbm_sel_o ; |
write_dat = wbm_dat_o ; |
-> write_request ; |
@(posedge wb_clk_i) ; |
end |
|
if ((wbm_ack_i === 1'b0) & (wbm_err_i === 1'b0) & (wbm_rty_i === 1'b0)) |
begin |
error_message = "Cycle terminated because allowed number of slave wait states constraint violation" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
end_access = 1'b1 ; |
write_res_o`WBM_MODEL_WRITE_DESIGN_ERR = 1'b1 ; |
end |
else if ((wbm_ack_i + wbm_err_i + wbm_rty_i) !== 'h1) |
begin |
error_message = "Cycle terminated because invalid slave response was received" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
end_access = 1'b1 ; |
write_res_o`WBM_MODEL_WRITE_DESIGN_ERR = 1'b1 ; |
end |
else |
begin |
write_res_o`WBM_MODEL_WRITE_SLAVE_WAITS = num_of_slave_waits ; |
write_res_o`WBM_MODEL_WRITE_SLAVE_ACK = wbm_ack_i ; |
write_res_o`WBM_MODEL_WRITE_SLAVE_ERR = wbm_err_i ; |
write_res_o`WBM_MODEL_WRITE_SLAVE_RTY = wbm_rty_i ; |
|
if (wbm_ack_i === 1'b1) |
begin |
write_adr = wbm_adr_o ; |
write_dat = wbm_dat_o ; |
write_sel = wbm_sel_o ; |
-> write_transfer ; |
end |
end |
|
if (end_access) |
begin |
wbm_cyc_o <= #(Thold) 1'b0 ; |
wbm_stb_o <= #(Thold) 1'bx ; |
wbm_we_o <= #(Thold) 1'bx ; |
wbm_sel_o <= #(Thold) 'hx ; |
wbm_adr_o <= #(Thold) 'hx ; |
wbm_dat_o <= #(Thold) 'hx ; |
wbm_cti_o <= #(Thold) 'hx ; |
wbm_bte_o <= #(Thold) 'hx ; |
access_in_progress = 1'b0 ; |
end |
end |
endtask // subsequent_write |
|
task start_read ; |
input `WBM_MODEL_READ_IN_TYPE read_stim_i ; |
output `WBM_MODEL_READ_OUT_TYPE read_res_o ; |
reg [31: 0] num_of_slave_waits ; |
reg end_access ; |
begin:main |
|
read_res_o = 'h0 ; |
|
if (access_in_progress === 1'b1) |
begin |
error_message = "Task called when some other access was in progress" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
read_res_o`WBM_MODEL_READ_STIM_ERR = 1'b1 ; |
disable main ; |
end |
|
if (reset_done !== 1'b1) |
begin |
error_message = "Task called before reset was applied to the design" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
read_res_o`WBM_MODEL_READ_STIM_ERR = 1'b1 ; |
disable main ; |
end |
|
access_in_progress = 1'b1 ; |
end_access = read_stim_i`WBM_MODEL_READ_LAST ; |
|
if (read_stim_i`WBM_MODEL_READ_FAST_B2B !== 1'b1) |
@(posedge wb_clk_i) ; |
|
wbm_cyc_o <= #(Tperiod - Tsetup) 1'b1 ; |
|
insert_waits(read_stim_i`WBM_MODEL_READ_WAITS, 'h0, num_of_slave_waits) ; |
|
if ((num_of_slave_waits ^ num_of_slave_waits) === 'h0) |
begin |
error_message = "Slave responded to initial read access" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
end |
|
num_of_slave_waits = 0 ; |
|
wbm_stb_o <= #(Tperiod - Tsetup) 1'b1 ; |
wbm_we_o <= #(Tperiod - Tsetup) 1'b0 ; |
wbm_adr_o <= #(Tperiod - Tsetup) next_read_adr ; |
wbm_sel_o <= #(Tperiod - Tsetup) next_read_sel ; |
wbm_cti_o <= #(Tperiod - Tsetup) next_read_cti ; |
wbm_bte_o <= #(Tperiod - Tsetup) next_read_bte ; |
|
-> read_accepted ; |
|
@(posedge wb_clk_i) ; |
|
while((wbm_ack_i === 1'b0) & (wbm_err_i === 1'b0) & (wbm_rty_i === 1'b0) & (num_of_slave_waits < read_stim_i`WBM_MODEL_READ_ALLOWED_SLAVE_WAITS)) |
begin |
num_of_slave_waits = num_of_slave_waits + 1'b1 ; |
read_adr = wbm_adr_o ; |
read_sel = wbm_sel_o ; |
-> read_request ; |
@(posedge wb_clk_i) ; |
end |
|
if ((wbm_ack_i === 1'b0) & (wbm_err_i === 1'b0) & (wbm_rty_i === 1'b0)) |
begin |
error_message = "Cycle terminated because allowed number of slave wait states constraint violation" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
end_access = 1'b1 ; |
read_res_o`WBM_MODEL_READ_DESIGN_ERR = 1'b1 ; |
end |
else if ((wbm_ack_i + wbm_err_i + wbm_rty_i) !== 'h1) |
begin |
error_message = "Cycle terminated because invalid slave response was received" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
end_access = 1'b1 ; |
read_res_o`WBM_MODEL_READ_DESIGN_ERR = 1'b1 ; |
end |
else |
begin |
read_res_o`WBM_MODEL_READ_SLAVE_WAITS = num_of_slave_waits ; |
read_res_o`WBM_MODEL_READ_SLAVE_ACK = wbm_ack_i ; |
read_res_o`WBM_MODEL_READ_SLAVE_ERR = wbm_err_i ; |
read_res_o`WBM_MODEL_READ_SLAVE_RTY = wbm_rty_i ; |
|
if (wbm_ack_i === 1'b1) |
begin |
read_adr = wbm_adr_o ; |
read_dat = wbm_dat_i ; |
read_sel = wbm_sel_o ; |
-> read_transfer ; |
end |
end |
|
if (end_access) |
begin |
wbm_cyc_o <= #(Thold) 1'b0 ; |
wbm_stb_o <= #(Thold) 1'bx ; |
wbm_we_o <= #(Thold) 1'bx ; |
wbm_sel_o <= #(Thold) 'hx ; |
wbm_adr_o <= #(Thold) 'hx ; |
wbm_cti_o <= #(Thold) 'hx ; |
wbm_bte_o <= #(Thold) 'hx ; |
access_in_progress = 1'b0 ; |
end |
end |
endtask // start_read |
|
task subsequent_read ; |
input `WBM_MODEL_READ_IN_TYPE read_stim_i ; |
output `WBM_MODEL_READ_OUT_TYPE read_res_o ; |
reg [31: 0] num_of_slave_waits ; |
reg end_access ; |
begin:main |
|
read_res_o = 'h0 ; |
|
if (access_in_progress !== 1'b1) |
begin |
error_message = "Task called when no access was in progress" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
read_res_o`WBM_MODEL_READ_STIM_ERR = 1'b1 ; |
disable main ; |
end |
|
end_access = read_stim_i`WBM_MODEL_READ_LAST ; |
|
insert_waits(read_stim_i`WBM_MODEL_READ_WAITS, 'h1, num_of_slave_waits) ; |
|
if ((num_of_slave_waits ^ num_of_slave_waits) !== 'h0) |
begin |
num_of_slave_waits = read_stim_i`WBM_MODEL_READ_WAITS ; |
end |
|
wbm_stb_o <= #(Tperiod - Tsetup) 1'b1 ; |
wbm_we_o <= #(Tperiod - Tsetup) 1'b0 ; |
wbm_adr_o <= #(Tperiod - Tsetup) next_read_adr ; |
wbm_sel_o <= #(Tperiod - Tsetup) next_read_sel ; |
wbm_cti_o <= #(Tperiod - Tsetup) next_read_cti ; |
wbm_bte_o <= #(Tperiod - Tsetup) next_read_bte ; |
|
-> read_accepted ; |
|
@(posedge wb_clk_i) ; |
|
while((wbm_ack_i === 1'b0) & (wbm_err_i === 1'b0) & (wbm_rty_i === 1'b0) & (num_of_slave_waits < read_stim_i`WBM_MODEL_READ_ALLOWED_SLAVE_WAITS)) |
begin |
num_of_slave_waits = num_of_slave_waits + 1'b1 ; |
read_adr = wbm_adr_o ; |
read_sel = wbm_sel_o ; |
-> read_request ; |
@(posedge wb_clk_i) ; |
end |
|
if ((wbm_ack_i === 1'b0) & (wbm_err_i === 1'b0) & (wbm_rty_i === 1'b0)) |
begin |
error_message = "Cycle terminated because allowed number of slave wait states constraint violation" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
end_access = 1'b1 ; |
read_res_o`WBM_MODEL_READ_DESIGN_ERR = 1'b1 ; |
end |
else if ((wbm_ack_i + wbm_err_i + wbm_rty_i) !== 'h1) |
begin |
error_message = "Cycle terminated because invalid slave response was received" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
end_access = 1'b1 ; |
read_res_o`WBM_MODEL_WRITE_DESIGN_ERR = 1'b1 ; |
end |
else |
begin |
read_res_o`WBM_MODEL_READ_SLAVE_WAITS = num_of_slave_waits ; |
read_res_o`WBM_MODEL_READ_SLAVE_ACK = wbm_ack_i ; |
read_res_o`WBM_MODEL_READ_SLAVE_ERR = wbm_err_i ; |
read_res_o`WBM_MODEL_READ_SLAVE_RTY = wbm_rty_i ; |
|
if (wbm_ack_i === 1'b1) |
begin |
read_adr = wbm_adr_o ; |
read_dat = wbm_dat_i ; |
read_sel = wbm_sel_o ; |
-> read_transfer ; |
end |
end |
|
if (end_access) |
begin |
wbm_cyc_o <= #(Thold) 1'b0 ; |
wbm_stb_o <= #(Thold) 1'bx ; |
wbm_we_o <= #(Thold) 1'bx ; |
wbm_sel_o <= #(Thold) 'hx ; |
wbm_adr_o <= #(Thold) 'hx ; |
wbm_cti_o <= #(Thold) 'hx ; |
wbm_bte_o <= #(Thold) 'hx ; |
access_in_progress = 1'b0 ; |
end |
end |
endtask // subsequent_read |
|
task insert_waits ; |
input [31: 0] num_of_waits_i ; |
input read_req_on_wait_i ; |
output [31: 0] num_of_slave_waits ; |
reg [31: 0] cur_num_of_waits ; |
begin |
num_of_slave_waits = 'hx ; |
|
for (cur_num_of_waits = 0 ; cur_num_of_waits < num_of_waits_i ; cur_num_of_waits = cur_num_of_waits + 1'b1) |
begin |
wbm_stb_o <= #(Thold) 1'b0 ; |
wbm_adr_o <= #(Thold) 'hx ; |
wbm_sel_o <= #(Thold) 'hx ; |
wbm_we_o <= #(Thold) 'hx ; |
wbm_dat_o <= #(Thold) 'hx ; |
wbm_cti_o <= #(Thold) 'hx ; |
wbm_bte_o <= #(Thold) 'hx ; |
|
@(posedge wb_clk_i) ; |
|
if (read_req_on_wait_i) |
begin |
if ( (wbm_ack_i === 1'b0) & (wbm_err_i === 1'b0) & (wbm_rty_i === 1'b0) ) |
begin |
if ( (next_read_cti === 'h1) | (next_read_cti === 'h2) | (next_read_cti === 'h7) ) |
begin |
read_adr = next_read_adr ; |
read_sel = next_read_sel ; |
-> read_request ; |
end |
end |
end |
|
if ((num_of_slave_waits ^ num_of_slave_waits) !== 'h0) |
begin |
if ((wbm_ack_i !== 1'b0) | (wbm_err_i !== 1'b0) | (wbm_rty_i !== 1'b0)) |
num_of_slave_waits = cur_num_of_waits ; |
end |
end |
end |
endtask |
|
always@(posedge wb_clk_i) |
begin:wb_monitoring_blk |
reg burst_in_progress ; |
reg ack_prev ; |
reg rty_prev ; |
reg err_prev ; |
reg stb_prev ; |
reg cyc_prev ; |
reg [wb_dat_width - 1:0] sdat_prev ; |
|
ack_prev <= wbm_ack_i ; |
rty_prev <= wbm_rty_i ; |
err_prev <= wbm_err_i ; |
stb_prev <= wbm_stb_o ; |
cyc_prev <= wbm_cyc_o ; |
sdat_prev <= wbm_dat_i ; |
|
if (wb_rst_i === `WB_MODEL_RST_ACTIVE) |
begin |
if (wbm_ack_i !== 1'b0) |
begin |
error_message = "ACK input signal was not de-asserted while reset was asserted" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
end |
|
if (wbm_err_i !== 1'b0) |
begin |
error_message = "ERR input signal was not de-asserted while reset was asserted" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
end |
|
if (wbm_rty_i !== 1'b0) |
begin |
error_message = "RTY input signal was not de-asserted while reset was asserted" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
end |
|
burst_in_progress <= 1'b0 ; |
end |
else |
begin |
if (wbm_cyc_o !== 1'b1) |
begin |
if (wbm_ack_i !== 1'b0) |
begin |
error_message = "ACK input signal was asserted while no cycle was in progress" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
end |
|
if (wbm_err_i !== 1'b0) |
begin |
error_message = "ERR input signal was asserted while no cycle was in progress" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
end |
|
if (wbm_rty_i !== 1'b0) |
begin |
error_message = "RTY input signal was asserted while no cycle was in progress" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
end |
end |
else |
begin |
if (burst_in_progress !== 1'b1) |
begin |
if ((wbm_ack_i !== 1'b0) & (wbm_stb_o !== 1'b1)) |
begin |
error_message = "ACK input signal was asserted while STB was de-asserted and no burst was in progress" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
end |
|
if ((wbm_err_i !== 1'b0) & (wbm_stb_o !== 1'b1)) |
begin |
error_message = "ERR input signal was asserted while STB was de-asserted and no burst was in progress" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
end |
|
if ((wbm_rty_i !== 1'b0) & (wbm_stb_o !== 1'b1)) |
begin |
error_message = "RTY input signal was asserted while STB was de-asserted and no burst was in progress" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
end |
end |
else |
begin |
if ((ack_prev !== 1'b0) & (stb_prev !== 1'b1)) |
begin |
if (wbm_ack_i !== 1'b1) |
begin |
error_message = "Slave de-asserted ACK signal during burst cycle without receiving STB asserted" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
end |
|
if (wbm_we_o !== 'b1) |
begin |
if (sdat_prev !== wbm_dat_i) |
begin |
error_message = "Slave changed the value of data output bus during burst cycle without receiving STB asserted" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
end |
end |
end |
|
if ((rty_prev !== 1'b0) & (stb_prev !== 1'b1) & (wbm_rty_i !== 1'b1)) |
begin |
error_message = "Slave de-asserted RTY signal during burst cycle without receiving STB asserted" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
end |
|
if ((err_prev !== 1'b0) & (stb_prev !== 1'b1) & (wbm_err_i !== 1'b1)) |
begin |
error_message = "Slave de-asserted ERR signal during burst cycle without receiving STB asserted" ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
end |
end |
|
if (wbm_stb_o === 1'b1) |
begin |
case (wbm_cti_o) |
3'b000:burst_in_progress <= 1'b0 ; |
3'b001:burst_in_progress <= 1'b1 ; |
3'b010:burst_in_progress <= 1'b1 ; |
3'b011:burst_in_progress <= 1'b0 ; |
3'b100:burst_in_progress <= 1'b0 ; |
3'b101:burst_in_progress <= 1'b0 ; |
3'b110:burst_in_progress <= 1'b0 ; |
3'b111:if (wbm_ack_i === 1'b1) burst_in_progress <= 1'b0 ; |
default: |
begin |
error_message = "WISHBONE master sent invalid cycle type identifier" ; |
burst_in_progress <= 1'bx ; |
`WB_MODEL_ERR_MSG(error_message) ; |
-> error_event ; |
end |
endcase |
|
if (wbm_err_i === 1'b1) |
burst_in_progress <= 1'b0 ; |
|
if (wbm_rty_i === 1'b1) |
burst_in_progress <= 1'b0 ; |
|
end |
end |
end |
end |
|
function [wb_dat_width - 1:0] get_write_dat ; |
input [wb_dat_width - 1:0] dat_i ; |
input [wb_sel_width - 1:0] sel_i ; |
|
integer cur_bit ; |
reg [wb_dat_width - 1:0] dat_o ; |
begin |
for (cur_bit = 0 ; cur_bit < wb_dat_width ; cur_bit = cur_bit + 1'b1) |
begin |
if (sel_i[cur_bit >> 3] === 1'b1) |
dat_o[cur_bit] = dat_i[cur_bit] ; |
else |
dat_o[cur_bit] = 1'bx ; |
end |
|
get_write_dat = dat_o ; |
end |
endfunction // get_write_dat |
|
endmodule |
|
/trunk/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 |
/trunk/bench/verilog/uart_testbench_utilities.v
0,0 → 1,320
////////////////////////////////////////////////////////////////////// |
//// //// |
//// uart_testbench_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 testbench_utilities; |
|
// Basic system TASKs |
//################### |
|
// DO_RESET |
task do_reset; |
begin |
testbench.wb_reset = 1'b1; |
#1; |
`UTILS_MSG("RESET signal asynchronously set."); |
end |
endtask // do_reset |
|
// RELEASE_RESET |
task release_reset; |
begin |
@(posedge testbench.wb_clk); |
#1; |
testbench.wb_reset = 1'b0; |
`UTILS_MSG("RESET signal released synchronously to WB clk."); |
end |
endtask // release_reset |
|
// DISABLE_CLK_GENERATORS |
task disable_clk_generators; |
input wb_clk_disable; |
input rx_clk_disable; |
input tx_clk_disable; |
input tx_clk_divided_disable; |
begin |
`UTILS_MSG("Following clocks are DISABLED:"); |
if (wb_clk_disable) |
begin |
testbench.wb_clk_en = 1'b0; |
`UTILS_MSG("- WB_clk"); |
end |
if (rx_clk_disable) |
begin |
testbench.i_uart_device.rx_clk_en = 1'b0; |
`UTILS_MSG("- RX_clk"); |
end |
if (tx_clk_disable) |
begin |
testbench.i_uart_device.tx_clk_en = 1'b0; |
`UTILS_MSG("- TX_clk"); |
end |
if (tx_clk_divided_disable) |
begin |
testbench.i_uart_device.tx_clk_divided_en = 1'b0; |
`UTILS_MSG("- TX_clk_divided"); |
end |
if (~wb_clk_disable && ~rx_clk_disable && ~tx_clk_disable && ~tx_clk_divided_disable) |
begin |
`UTILS_MSG("- NO clocks DISABLED"); |
end |
end |
endtask // disable_clk_generators |
|
// ENABLE_CLK_GENERATORS |
task enable_clk_generators; |
input wb_clk_enable; |
input rx_clk_enable; |
input tx_clk_enable; |
input tx_clk_divided_enable; |
begin |
`UTILS_MSG("Following clocks are ENABLED:"); |
if (wb_clk_enable) |
begin |
testbench.wb_clk_en = 1'b1; |
`UTILS_MSG("- WB_clk"); |
end |
if (rx_clk_enable) |
begin |
testbench.i_uart_device.rx_clk_en = 1'b1; |
`UTILS_MSG("- RX_clk"); |
end |
if (tx_clk_enable) |
begin |
testbench.i_uart_device.tx_clk_en = 1'b1; |
`UTILS_MSG("- TX_clk"); |
end |
if (tx_clk_divided_enable) |
begin |
testbench.i_uart_device.tx_clk_divided_en = 1'b1; |
`UTILS_MSG("- TX_clk_divided"); |
end |
if (~wb_clk_enable && ~rx_clk_enable && ~tx_clk_enable && ~tx_clk_divided_enable) |
begin |
`UTILS_MSG("- NO clocks ENABLED"); |
end |
end |
endtask // enable_clk_generators |
|
// SET_DEVICE_TX_RX_CLK_PERIOD |
task set_device_tx_rx_clk_period; |
input [31:0] clk_period; |
begin |
testbench.i_uart_device.T_clk_period = clk_period; |
`UTILS_VAL1("UART DEVICE TX/RX clock period:", clk_period); |
end |
endtask // set_device_tx_rx_clk_period |
|
// SET_DEVICE_TX_CLK_DELAY |
task set_device_tx_clk_delay; |
input [31:0] tx_clk_delay; |
begin |
testbench.i_uart_device.T_clk_delay = tx_clk_delay; |
`UTILS_VAL1("UART DEVICE TX clock delay:", tx_clk_delay); |
end |
endtask // set_device_tx_clk_delay |
|
// SET_DEVICE_TX_RX_CLK_DIVISOR |
task set_device_tx_rx_clk_divisor; |
input [31:0] clk_divisor; |
begin |
testbench.i_uart_device.T_divisor = clk_divisor; |
`UTILS_VAL1("UART DEVICE TX/RX clock divisor:", clk_divisor); |
end |
endtask // set_device_tx_rx_clk_divisor |
|
// SET_WB_CLK_PERIOD |
task set_wb_clock_period; |
input [31:0] clk_period; |
begin |
testbench.T_wb_clk_period = clk_period; |
testbench.i_uart_device.T_clk_period = clk_period; |
`UTILS_VAL1("WB & UART DEVICE TX/RX clock period:", clk_period); |
end |
endtask // set_wb_clock_period |
|
// WB_CLK_FOLLOWS_DEVICE_RX_CLK |
task wb_clk_follows_device_rx_clk; |
input [31:0] time_delay_i; |
integer time_delay; |
begin |
time_delay = time_delay_i; |
@(posedge testbench.wb_clk); |
testbench.wb_clk_en = 1'b0; |
@(posedge testbench.i_uart_device.rx_clk); |
#time_delay testbench.wb_clk = 1'b1; |
testbench.wb_clk_en = 1'b1; |
`UTILS_VAL1("WB followed UART DEVICE rising edge RX clock for time delay:", time_delay); |
end |
endtask // wb_clk_follows_device_rx_clk |
|
// DEVICE_RX_CLK_FOLLOWS_WB_CLK |
task device_rx_clk_follows_wb_clk; |
input [31:0] time_delay_i; |
integer time_delay; |
begin |
time_delay = time_delay_i; |
@(posedge testbench.i_uart_device.rx_clk); |
testbench.i_uart_device.rx_clk_en = 1'b0; |
@(posedge testbench.wb_clk); |
#time_delay testbench.i_uart_device.rx_clk = 1'b1; |
testbench.i_uart_device.rx_clk_en = 1'b1; |
`UTILS_VAL1("UART DEVICE RX followed WB rising edge clock for time delay:", time_delay); |
end |
endtask // device_rx_clk_follows_wb_clk |
|
// Utility tasks |
//############## |
|
// WAIT_FOR_NUM_OF_WB_CLK |
task wait_for_num_of_wb_clk; |
input [31:0] num_of_clk; |
integer count; |
begin |
count = 0; |
`UTILS_VAL1("Waiting for following number of WB CLK periods:", num_of_clk); |
while (count < num_of_clk) |
begin |
@(testbench.wb_clk); |
count = count + 1'b1; |
#1; |
end |
`UTILS_MSG("Waiting expired."); |
end |
endtask // wait_for_num_of_wb_clk |
|
// WAIT_RX_FIFO_FULL_REGARDLESS_INT |
task wait_rx_fifo_full_regardless_int; |
integer count; |
begin |
count = 0; |
`UTILS_MSG("Waiting for RX FIFO to get full regardless of interrupt."); |
fork |
begin:fifo_full_loop |
while (testbench.i_uart_top.regs.receiver.fifo_rx.count < |
testbench.i_uart_top.regs.receiver.fifo_rx.fifo_depth) // While RX fifo not full |
begin |
@(testbench.wb_clk); |
end |
disable counter; |
`UTILS_MSG("RX FIFO got full."); |
end |
begin:counter |
while (count < testbench.max_wait_cnt) |
begin |
@(testbench.wb_clk); |
count = count + 1'b1; |
#1; |
end |
disable fifo_full_loop; |
`UTILS_ERROR("WAIT counter exceeded max value."); |
end |
join |
end |
endtask // wait_rx_fifo_full_regardless_int |
|
// WAIT_RX_FIFO_FULL_UNLESS_INT |
task wait_rx_fifo_full_unless_int; |
integer count; |
begin |
count = 0; |
`UTILS_MSG("Waiting for RX FIFO to get full unless interrupt occures before."); |
fork |
begin:fifo_full_loop |
while (testbench.i_uart_top.regs.receiver.fifo_rx.count < |
testbench.i_uart_top.regs.receiver.fifo_rx.fifo_depth) // While RX fifo not full |
begin |
@(testbench.wb_clk); |
end |
disable counter; |
disable int_loop; |
`UTILS_MSG("RX FIFO got full."); |
end |
begin:int_loop |
if (testbench.ier_reg[3:0] == 4'h0) |
begin |
`UTILS_MSG("All interrupts are disabled."); |
end |
else |
begin |
`UTILS_MSG("Interrupts are enabled in IE Register."); |
`UTILS_VAL1("IER:", testbench.ier_reg); |
@(testbench.int_aserted); |
`UTILS_MSG("Interrupt is asserted. The pending interrupt of highest priority is in II Register."); |
`UTILS_VAL1("IIR:", testbench.iir_reg); |
disable counter; |
disable fifo_full_loop; |
end |
end |
begin:counter |
while (count < testbench.max_wait_cnt) |
begin |
@(testbench.wb_clk); |
count = count + 1'b1; |
#1; |
end |
disable int_loop; |
disable fifo_full_loop; |
`UTILS_ERROR("WAIT counter exceeded max value."); |
end |
join |
end |
endtask // wait_rx_fifo_full_unless_int |
|
|
// UART Initialize TASKs |
//###################### |
|
// POSSIBLE INITIALIZE TASKS - NOW FEW STEPS ARE MADE IN EACH testcase!!! |
|
|
endmodule |
/trunk/bench/verilog/wb_model_defines.v
0,0 → 1,79
////////////////////////////////////////////////////////////////////// |
//// //// |
//// wb_model_defines.v //// |
//// //// |
//// This file is part of the "uart16550" project //// |
//// http://www.opencores.org/projects/uart16550/ //// |
//// //// |
//// Author(s): //// |
//// - mihad@opencores.org (Miha Dolenc) //// |
//// //// |
//// 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 $ |
// |
// |
|
|
`define WB_MODEL_RST_ACTIVE 1'b1 |
`define WB_MODEL_ERR_MSG(TEXT) $display("Error detected at time %t!", $time) ; $display("%m reports: %0s.", TEXT) ; testcase.msg = TEXT ; -> testcase.err_event |
|
`define WBM_MODEL_WRITE_IN_TYPE [65: 0] |
`define WBM_MODEL_WRITE_WAITS [31: 0] |
`define WBM_MODEL_WRITE_ALLOWED_SLAVE_WAITS [63:32] |
`define WBM_MODEL_WRITE_LAST [64:64] |
`define WBM_MODEL_WRITE_FAST_B2B [65:65] |
|
`define WBM_MODEL_WRITE_OUT_TYPE [36: 0] |
`define WBM_MODEL_WRITE_SLAVE_WAITS [31: 0] |
`define WBM_MODEL_WRITE_STIM_ERR [32:32] |
`define WBM_MODEL_WRITE_DESIGN_ERR [33:33] |
`define WBM_MODEL_WRITE_SLAVE_ACK [34:34] |
`define WBM_MODEL_WRITE_SLAVE_ERR [35:35] |
`define WBM_MODEL_WRITE_SLAVE_RTY [36:36] |
|
`define WBM_MODEL_READ_IN_TYPE [65: 0] |
`define WBM_MODEL_READ_WAITS [31: 0] |
`define WBM_MODEL_READ_ALLOWED_SLAVE_WAITS [63:32] |
`define WBM_MODEL_READ_LAST [64:64] |
`define WBM_MODEL_READ_FAST_B2B [65:65] |
|
`define WBM_MODEL_READ_OUT_TYPE [36: 0] |
`define WBM_MODEL_READ_SLAVE_WAITS [31: 0] |
`define WBM_MODEL_READ_STIM_ERR [32:32] |
`define WBM_MODEL_READ_DESIGN_ERR [33:33] |
`define WBM_MODEL_READ_SLAVE_ACK [34:34] |
`define WBM_MODEL_READ_SLAVE_ERR [35:35] |
`define WBM_MODEL_READ_SLAVE_RTY [36:36] |
|
/trunk/bench/verilog/uart_testbench_defines.v
0,0 → 1,86
////////////////////////////////////////////////////////////////////// |
//// //// |
//// uart_testbench_defines.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 $ |
// |
// |
|
|
`ifdef VERBOSE |
// Displaying messages to CRT and providing to "testcase" |
`define SEVERE_ERROR(TEXT) $display("Time: %t (%m)", $time); $display("*E, Object %m reporting severe error:"); $display(" %0s", TEXT); $sformat(testcase.tim, "Time: %t (%m)", $time); testcase.severe_err_msg = TEXT; -> testcase.severe_err_event; @(testcase.testbench_log_written) |
`define UTILS_WARNING(TEXT) $display("Time: %t (%m)", $time); $display("*W, %0s", TEXT); $sformat(testcase.tim, "Time: %t (%m)", $time); testcase.msg = TEXT; -> testcase.wrn_event; @(testcase.testbench_log_written) |
`define UTILS_ERROR(TEXT) $display("Time: %t (%m)", $time); $display("*E, %0s", TEXT); $sformat(testcase.tim, "Time: %t (%m)", $time); testcase.msg = TEXT; -> testcase.err_event; @(testcase.testbench_log_written) |
`define BENCH_WARNING(TEXT) $display("Time: %t (%m)", $time); $display("*W, %0s", TEXT); $sformat(testcase.tim, "Time: %t (%m)", $time); testcase.msg = TEXT; -> testcase.wrn_event; @(testcase.testbench_log_written) |
`define BENCH_ERROR(TEXT) $display("Time: %t (%m)", $time); $display("*E, %0s", TEXT); $sformat(testcase.tim, "Time: %t (%m)", $time); testcase.msg = TEXT; -> testcase.err_event; @(testcase.testbench_log_written) |
`define TC_ERROR(TEXT) $display("Time: %t (%m)", $time); $display("*E, %0s", TEXT); $sformat(testcase.tim, "Time: %t (%m)", $time); testcase.msg = TEXT; -> testcase.err_event; @(testcase.testbench_log_written) |
`define DEVICE_WARNING(TEXT) $display("Time: %t (%m)", $time); $display("*W, %0s", TEXT); $sformat(testcase.tim, "Time: %t (%m)", $time); testcase.msg = TEXT; -> testcase.wrn_event; @(testcase.testbench_log_written) |
`define DEVICE_ERROR(TEXT) $display("Time: %t (%m)", $time); $display("*E, %0s", TEXT); $sformat(testcase.tim, "Time: %t (%m)", $time); testcase.msg = TEXT; -> testcase.err_event; @(testcase.testbench_log_written) |
// Displaying messages to CRT |
`define UTILS_MSG(TEXT) $display("Time %t (%m)", $time); $display("*N, %0s", TEXT); $sformat(testcase.tim, "Time: %t (%m)", $time); testcase.msg = TEXT; -> testcase.msg_event; @(testcase.testbench_log_written) |
`define UTILS_VAL1(TEXT, VAL) $display("Time %t (%m)", $time); $display("*N, %0s %0h.", TEXT, VAL); $sformat(testcase.tim, "Time: %t (%m)", $time); testcase.msg = TEXT; testcase.val = VAL; -> testcase.val_event; @(testcase.testbench_log_written) |
`define BENCH_MSG(TEXT) $display("Time %t (%m)", $time); $display("*N, %0s", TEXT); $sformat(testcase.tim, "Time: %t (%m)", $time); testcase.msg = TEXT; -> testcase.msg_event; @(testcase.testbench_log_written) |
`define BENCH_VAL1(TEXT, VAL) $display("Time %t (%m)", $time); $display("*N, %0s %0h.", TEXT, VAL); $sformat(testcase.tim, "Time: %t (%m)", $time); testcase.msg = TEXT; testcase.val = VAL; -> testcase.val_event; @(testcase.testbench_log_written) |
`define TC_MSG(TEXT) $display("Time %t (%m)", $time); $display("*N, %0s", TEXT); $sformat(testcase.tim, "Time: %t (%m)", $time); testcase.msg = TEXT; -> testcase.msg_event; @(testcase.testbench_log_written) |
`define TC_VAL1(TEXT, VAL) $display("Time %t (%m)", $time); $display("*N, %0s %0h.", TEXT, VAL); $sformat(testcase.tim, "Time: %t (%m)", $time); testcase.msg = TEXT; testcase.val = VAL; -> testcase.val_event; @(testcase.testbench_log_written) |
`else |
// Displaying messages to CRT and providing to "testcase" |
`define SEVERE_ERROR(TEXT) $display("*E, Object %m reporting severe error:"); $display(" %0s", TEXT); $sformat(testcase.tim, "Time: %t (%m)", $time); testcase.severe_err_msg = TEXT; -> testcase.severe_err_event; @(testcase.testbench_log_written) |
`define UTILS_WARNING(TEXT) $display("*W, %0s", TEXT); $sformat(testcase.tim, "Time: %t (%m)", $time); testcase.msg = TEXT; -> testcase.wrn_event; @(testcase.testbench_log_written) |
`define UTILS_ERROR(TEXT) $display("*E, %0s", TEXT); $sformat(testcase.tim, "Time: %t (%m)", $time); testcase.msg = TEXT; -> testcase.err_event; @(testcase.testbench_log_written) |
`define BENCH_WARNING(TEXT) $display("*W, %0s", TEXT); $sformat(testcase.tim, "Time: %t (%m)", $time); testcase.msg = TEXT; -> testcase.wrn_event; @(testcase.testbench_log_written) |
`define BENCH_ERROR(TEXT) $display("*E, %0s", TEXT); $sformat(testcase.tim, "Time: %t (%m)", $time); testcase.msg = TEXT; -> testcase.err_event; @(testcase.testbench_log_written) |
`define TC_ERROR(TEXT) $display("*E, %0s", TEXT); $sformat(testcase.tim, "Time: %t (%m)", $time); testcase.msg = TEXT; -> testcase.err_event; @(testcase.testbench_log_written) |
`define DEVICE_WARNING(TEXT) $display("*W, %0s", TEXT); $sformat(testcase.tim, "Time: %t (%m)", $time); testcase.msg = TEXT; -> testcase.wrn_event; @(testcase.testbench_log_written) |
`define DEVICE_ERROR(TEXT) $display("*E, %0s", TEXT); $sformat(testcase.tim, "Time: %t (%m)", $time); testcase.msg = TEXT; -> testcase.err_event; @(testcase.testbench_log_written) |
// Displaying messages to CRT |
`define UTILS_MSG(TEXT) $display("*N, %0s", TEXT); $sformat(testcase.tim, "Time: %t (%m)", $time); testcase.msg = TEXT; -> testcase.msg_event; @(testcase.testbench_log_written) |
`define UTILS_VAL1(TEXT, VAL) $display("*N, %0s %0h.", TEXT, VAL); $sformat(testcase.tim, "Time: %t (%m)", $time); testcase.msg = TEXT; testcase.val = VAL; -> testcase.val_event; @(testcase.testbench_log_written) |
`define BENCH_MSG(TEXT) $display("*N, %0s", TEXT); $sformat(testcase.tim, "Time: %t (%m)", $time); testcase.msg = TEXT; -> testcase.msg_event; @(testcase.testbench_log_written) |
`define BENCH_VAL1(TEXT, VAL) $display("*N, %0s %0h.", TEXT, VAL); $sformat(testcase.tim, "Time: %t (%m)", $time); testcase.msg = TEXT; testcase.val = VAL; -> testcase.val_event; @(testcase.testbench_log_written) |
`define TC_MSG(TEXT) $display("*N, %0s", TEXT); $sformat(testcase.tim, "Time: %t (%m)", $time); testcase.msg = TEXT; -> testcase.msg_event; @(testcase.testbench_log_written) |
`define TC_VAL1(TEXT, VAL) $display("*N, %0s %0h.", TEXT, VAL); $sformat(testcase.tim, "Time: %t (%m)", $time); testcase.msg = TEXT; testcase.val = VAL; -> testcase.val_event; @(testcase.testbench_log_written) |
`endif |
|
// Testcase end |
`define PROMPT #1000000; log.end_log; $finish |
/trunk/bench/verilog/uart_test.v
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/trunk/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 |
/trunk/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 |
always@(wbs_cyc_i or wbs_stb_i or wbs_we_i or wbs_sel_i or wbs_adr_i or |
wbs_dat_i /*or wbs_ack_o*/ /*or posedge wb_clk*/) |
begin |
if (wbs_cyc_i && wbs_stb_i) |
begin |
if (wbs_we_i /*&& wbs_ack_o*/) // WRITE |
begin |
// LOG's example of detecting of register write: |
// ---------------- |
// case (wbs_adr_i) |
// `UART_REG_TR: if (lcr_reg[7]) // lcr_reg[7] == DLAB !!! |
// -> dll_reg_written; |
// else |
// -> thr_reg_written; |
// `UART_REG_IE: if (lcr_reg[7]) // lcr_reg[7] == DLAB !!! |
// -> dlm_reg_written; |
// else |
// -> ier_reg_written; |
// `UART_REG_FC: -> fcr_reg_written; |
// `UART_REG_LC: -> lcr_reg_written; |
// `UART_REG_MC: -> mcr_reg_written; |
// default: -> erroneous_write_location; |
// endcase |
// ---------------- |
|
reg_adr = wbs_adr_i; |
reg_dat = wbs_dat_i; |
reg_dlab = lcr_reg[7]; |
-> reg_written; |
if (~reg_dlab && (reg_adr == `UART_REG_TR)) // write to FIFO |
-> tx_reg_written; |
end |
end |
end |
always@(wbs_cyc_i or wbs_stb_i or wbs_we_i or wbs_sel_i or wbs_adr_i or |
wbs_dat_o or wbs_ack_o /*or posedge wb_clk*/) |
begin |
if (wbs_cyc_i && wbs_stb_i) |
begin |
if (~wbs_we_i && wbs_ack_o) // READ |
begin |
// LOG's example of detecting of register read: |
// ---------------- |
// case (wbs_adr_i) |
// `UART_REG_RB: if (lcr_reg[7]) // lcr_reg[7] == DLAB !!! |
// -> dll_reg_read; |
// else |
// -> rbr_reg_read; |
// `UART_REG_IE: if (lcr_reg[7]) // lcr_reg[7] == DLAB !!! |
// -> dlm_reg_read; |
// else |
// -> ier_reg_read; |
// `UART_REG_II: -> iir_reg_read; |
// `UART_REG_LC: -> lcr_reg_read; |
// `UART_REG_LS: -> lsr_reg_read; |
// `UART_REG_MS: -> msr_reg_read; |
// default: -> erroneous_read_location; |
// endcase |
// ---------------- |
|
reg_adr = wbs_adr_i; |
reg_dat = wbs_dat_o; |
reg_dlab = lcr_reg[7]; |
-> reg_read; |
if (~reg_dlab && (reg_adr == `UART_REG_RB)) |
-> rx_reg_read; |
end |
end |
end |
|
|
// UART register monitor |
//####################### |
|
// Line Status Register |
// Reading LSR register |
initial |
begin |
lsr_reg_read = 0; |
forever |
begin |
@(reg_read); |
if (reg_adr == `UART_REG_LS) |
begin |
lsr_reg_read = 1'b1; |
repeat (1) @(posedge wb_clk); |
lsr_reg_read = 0; |
end |
end |
end |
// Bit 0 - Data Ready |
initial |
begin |
lsr_reg_bit0_change_allowed = 0; |
@(reset_released); |
#10; |
fork |
begin: rx_fifo_status_changing |
forever |
begin |
if (rx_fifo_status == 0) |
begin |
wait (rx_fifo_status > 0); |
lsr_reg_bit0_change_allowed = 1'b1; |
repeat (1) @(posedge wb_clk); |
#2; |
lsr_reg_bit0_change_allowed = 0; |
if (~lsr_reg[0]) |
begin |
`BENCH_ERROR("Bit 0 of LSR register not '1'!"); |
-> error_detected; |
end |
end |
else |
begin |
wait (rx_fifo_status == 0); |
lsr_reg_bit0_change_allowed = 1'b1; |
repeat (1) @(posedge wb_clk); |
#2; |
lsr_reg_bit0_change_allowed = 0; |
if (lsr_reg[0]) |
begin |
`BENCH_ERROR("Bit 0 of LSR register not '0'!"); |
-> error_detected; |
end |
end |
end |
end |
begin: lsr_reg_bit0_changing |
forever |
begin |
wait (~lsr_reg_bit0_change_allowed); |
begin |
@(lsr_reg[0] or lsr_reg_bit0_change_allowed); |
if (~lsr_reg_bit0_change_allowed) |
begin |
`BENCH_ERROR("Bit 0 of LSR register should not change!"); |
-> error_detected; |
end |
end |
end |
end |
join |
end |
// Bit 1 - Overrun Error |
initial |
begin |
lsr_reg_bit1_change_allowed = 0; |
@(reset_released); |
#10; |
fork |
begin: rx_overrun_err_occured_changing |
forever |
begin |
if (~rx_overrun_err_occured) |
begin |
wait (rx_overrun_err_occured); |
lsr_reg_bit1_change_allowed = 1'b1; |
repeat (1) @(posedge wb_clk); |
#2; |
lsr_reg_bit1_change_allowed = 0; |
if (~lsr_reg[1]) |
begin |
`BENCH_ERROR("Bit 1 of LSR register not '1'!"); |
-> error_detected; |
end |
end |
else |
begin |
wait (lsr_reg_read); |
lsr_reg_bit1_change_allowed = 1'b1; |
repeat (1) @(posedge wb_clk); |
#2; |
lsr_reg_bit1_change_allowed = 0; |
rx_overrun_err_occured = 0; |
if (lsr_reg[1]) |
begin |
`BENCH_ERROR("Bit 1 of LSR register not '0'!"); |
-> error_detected; |
end |
end |
end |
end |
begin: lsr_reg_bit1_changing |
forever |
begin |
wait (~lsr_reg_bit1_change_allowed); |
begin |
@(lsr_reg[1] or lsr_reg_bit1_change_allowed); |
if (~lsr_reg_bit1_change_allowed) |
begin |
`BENCH_ERROR("Bit 1 of LSR register should not change!"); |
-> error_detected; |
end |
end |
end |
end |
join |
end |
// Bit 2 - Parity Error |
initial |
begin |
lsr_reg_bit2_change_allowed = 0; |
rx_fifo_par_rd_pointer = 0; |
@(reset_released); |
#10; |
fork |
begin: rx_parity_err_changing |
forever |
begin |
if (~rx_fifo_par[rx_fifo_par_rd_pointer]) |
begin |
wait (rx_fifo_read); |
lsr_reg_bit2_change_allowed = 1'b1; |
repeat (1) @(posedge wb_clk); |
#2; |
lsr_reg_bit2_change_allowed = 0; |
rx_fifo_par_rd_pointer = rx_fifo_par_rd_pointer + 1'b1; |
// check bit |
if (~lsr_reg[2] && rx_fifo_par[rx_fifo_par_rd_pointer]) |
begin |
`BENCH_ERROR("Bit 2 of LSR register not '1'!"); |
-> error_detected; |
end |
else if (lsr_reg[2] && ~rx_fifo_par[rx_fifo_par_rd_pointer]) |
begin |
`BENCH_ERROR("Bit 2 of LSR register not '0'!"); |
-> error_detected; |
end |
end |
else |
begin |
wait (lsr_reg_read); |
lsr_reg_bit2_change_allowed = 1'b1; |
repeat (1) @(posedge wb_clk); |
#2; |
lsr_reg_bit2_change_allowed = 0; |
if (rx_fifo_par_rd_pointer < rx_fifo_rd_pointer) |
begin |
for (i2 = rx_fifo_par_rd_pointer; i2 <= rx_fifo_rd_pointer; i2 = i2 + 1) |
rx_fifo_par[i2] = 0; |
rx_fifo_par_rd_pointer = rx_fifo_rd_pointer; |
end |
else if (rx_fifo_par_rd_pointer > rx_fifo_rd_pointer) |
begin |
for (i2 = rx_fifo_par_rd_pointer; i2 <= 31; i2 = i2 + 1) |
rx_fifo_par[i2] = 0; |
for (i2 = 0; i2 <= rx_fifo_rd_pointer; i2 = i2 + 1) |
rx_fifo_par[i2] = 0; |
rx_fifo_par_rd_pointer = rx_fifo_rd_pointer; |
end |
else |
begin |
rx_fifo_par = 0; |
rx_fifo_par_rd_pointer = rx_fifo_rd_pointer; |
end |
// check bit |
if (~lsr_reg[2] && rx_fifo_par[rx_fifo_par_rd_pointer]) |
begin |
`BENCH_ERROR("Bit 2 of LSR register not '1'!"); |
-> error_detected; |
end |
else if (lsr_reg[2] && ~rx_fifo_par[rx_fifo_par_rd_pointer]) |
begin |
`BENCH_ERROR("Bit 2 of LSR register not '0'!"); |
-> error_detected; |
end |
end |
end |
end |
begin: lsr_reg_bit2_changing |
forever |
begin |
wait (~lsr_reg_bit2_change_allowed); |
begin |
@(lsr_reg[2] or lsr_reg_bit2_change_allowed); |
if (~lsr_reg_bit2_change_allowed) |
begin |
`BENCH_ERROR("Bit 2 of LSR register should not change!"); |
-> error_detected; |
end |
end |
end |
end |
join |
end |
// Bit 3 - Framing Error |
initial |
begin |
lsr_reg_bit3_change_allowed = 0; |
rx_fifo_frm_rd_pointer = 0; |
@(reset_released); |
#10; |
fork |
begin: rx_framing_err_changing |
forever |
begin |
if (~rx_fifo_frm[rx_fifo_frm_rd_pointer]) |
begin |
wait (rx_fifo_read); |
lsr_reg_bit3_change_allowed = 1'b1; |
repeat (1) @(posedge wb_clk); |
#2; |
lsr_reg_bit3_change_allowed = 0; |
rx_fifo_frm_rd_pointer = rx_fifo_frm_rd_pointer + 1'b1; |
// check bit |
if (~lsr_reg[3] && rx_fifo_frm[rx_fifo_frm_rd_pointer]) |
begin |
`BENCH_ERROR("Bit 3 of LSR register not '1'!"); |
-> error_detected; |
end |
else if (lsr_reg[3] && ~rx_fifo_frm[rx_fifo_frm_rd_pointer]) |
begin |
`BENCH_ERROR("Bit 3 of LSR register not '0'!"); |
-> error_detected; |
end |
end |
else |
begin |
wait (lsr_reg_read); |
lsr_reg_bit3_change_allowed = 1'b1; |
repeat (1) @(posedge wb_clk); |
#2; |
lsr_reg_bit3_change_allowed = 0; |
if (rx_fifo_frm_rd_pointer < rx_fifo_rd_pointer) |
begin |
for (i3 = rx_fifo_frm_rd_pointer; i3 <= rx_fifo_rd_pointer; i3 = i3 + 1) |
rx_fifo_frm[i3] = 0; |
rx_fifo_frm_rd_pointer = rx_fifo_rd_pointer; |
end |
else if (rx_fifo_frm_rd_pointer > rx_fifo_rd_pointer) |
begin |
for (i3 = rx_fifo_frm_rd_pointer; i3 <= 31; i3 = i3 + 1) |
rx_fifo_frm[i3] = 0; |
for (i3 = 0; i3 <= rx_fifo_rd_pointer; i3 = i3 + 1) |
rx_fifo_frm[i3] = 0; |
rx_fifo_frm_rd_pointer = rx_fifo_rd_pointer; |
end |
else |
begin |
rx_fifo_frm = 0; |
rx_fifo_frm_rd_pointer = rx_fifo_rd_pointer; |
end |
// check bit |
if (~lsr_reg[3] && rx_fifo_frm[rx_fifo_frm_rd_pointer]) |
begin |
`BENCH_ERROR("Bit 3 of LSR register not '1'!"); |
-> error_detected; |
end |
else if (lsr_reg[3] && ~rx_fifo_frm[rx_fifo_frm_rd_pointer]) |
begin |
`BENCH_ERROR("Bit 3 of LSR register not '0'!"); |
-> error_detected; |
end |
end |
end |
end |
begin: lsr_reg_bit3_changing |
forever |
begin |
wait (~lsr_reg_bit3_change_allowed); |
begin |
@(lsr_reg[3] or lsr_reg_bit3_change_allowed); |
if (~lsr_reg_bit3_change_allowed) |
begin |
`BENCH_ERROR("Bit 3 of LSR register should not change!"); |
-> error_detected; |
end |
end |
end |
end |
join |
end |
// Bit 4 - Break Interrupt |
initial |
begin |
lsr_reg_bit4_change_allowed = 0; |
rx_fifo_brk_rd_pointer = 0; |
@(reset_released); |
#10; |
fork |
begin: rx_break_int_changing |
forever |
begin |
if (~rx_fifo_brk[rx_fifo_brk_rd_pointer]) |
begin |
wait (rx_fifo_read); |
lsr_reg_bit4_change_allowed = 1'b1; |
repeat (1) @(posedge wb_clk); |
#2; |
lsr_reg_bit4_change_allowed = 0; |
rx_fifo_brk_rd_pointer = rx_fifo_brk_rd_pointer + 1'b1; |
// check bit |
if (~lsr_reg[4] && rx_fifo_brk[rx_fifo_brk_rd_pointer]) |
begin |
`BENCH_ERROR("Bit 4 of LSR register not '1'!"); |
-> error_detected; |
end |
else if (lsr_reg[4] && ~rx_fifo_brk[rx_fifo_brk_rd_pointer]) |
begin |
`BENCH_ERROR("Bit 4 of LSR register not '0'!"); |
-> error_detected; |
end |
end |
else |
begin |
wait (lsr_reg_read); |
lsr_reg_bit4_change_allowed = 1'b1; |
repeat (1) @(posedge wb_clk); |
#2; |
lsr_reg_bit4_change_allowed = 0; |
if (rx_fifo_brk_rd_pointer < rx_fifo_rd_pointer) |
begin |
for (i4 = rx_fifo_brk_rd_pointer; i4 <= rx_fifo_rd_pointer; i4 = i4 + 1) |
rx_fifo_brk[i4] = 0; |
rx_fifo_brk_rd_pointer = rx_fifo_rd_pointer; |
end |
else if (rx_fifo_brk_rd_pointer > rx_fifo_rd_pointer) |
begin |
for (i4 = rx_fifo_brk_rd_pointer; i4 <= 31; i4 = i4 + 1) |
rx_fifo_brk[i4] = 0; |
for (i4 = 0; i4 <= rx_fifo_rd_pointer; i4 = i4 + 1) |
rx_fifo_brk[i4] = 0; |
rx_fifo_brk_rd_pointer = rx_fifo_rd_pointer; |
end |
else |
begin |
rx_fifo_brk = 0; |
rx_fifo_brk_rd_pointer = rx_fifo_rd_pointer; |
end |
// check bit |
if (~lsr_reg[4] && rx_fifo_brk[rx_fifo_brk_rd_pointer]) |
begin |
`BENCH_ERROR("Bit 4 of LSR register not '1'!"); |
-> error_detected; |
end |
else if (lsr_reg[4] && ~rx_fifo_brk[rx_fifo_brk_rd_pointer]) |
begin |
`BENCH_ERROR("Bit 4 of LSR register not '0'!"); |
-> error_detected; |
end |
end |
end |
end |
begin: lsr_reg_bit4_changing |
forever |
begin |
wait (~lsr_reg_bit4_change_allowed); |
begin |
@(lsr_reg[4] or lsr_reg_bit4_change_allowed); |
if (~lsr_reg_bit4_change_allowed) |
begin |
`BENCH_ERROR("Bit 4 of LSR register should not change!"); |
-> error_detected; |
end |
end |
end |
end |
join |
end |
// Bit 5 - Transmitter Holding Register Empty |
initial |
begin |
lsr_reg_bit5_change_allowed = 0; |
@(reset_released); |
#10; |
fork |
begin: tx_fifo_status_changing |
forever |
begin |
if (tx_fifo_status == 0) |
begin |
// @(tx_reg_written); |
wait (tx_fifo_status > 0); |
lsr_reg_bit5_change_allowed = 1'b1; |
repeat (3) @(posedge wb_clk); |
#2; |
lsr_reg_bit5_change_allowed = 0; |
if (lsr_reg[5]) |
begin |
`BENCH_ERROR("Bit 5 of LSR register not '0'!"); |
-> error_detected; |
end |
end |
else |
begin |
wait (tx_fifo_status == 0); |
lsr_reg_bit5_change_allowed = 1'b1; |
repeat (3) @(posedge wb_clk); |
#2; |
lsr_reg_bit5_change_allowed = 0; |
if (~lsr_reg[5]) |
begin |
`BENCH_ERROR("Bit 5 of LSR register not '1'!"); |
-> error_detected; |
end |
end |
end |
end |
begin: lsr_reg_bit5_changing |
forever |
begin |
wait (~lsr_reg_bit5_change_allowed); |
begin |
@(lsr_reg[5] or lsr_reg_bit5_change_allowed); |
if (~lsr_reg_bit5_change_allowed) |
begin |
`BENCH_ERROR("Bit 5 of LSR register should not change!"); |
-> error_detected; |
end |
end |
end |
end |
join |
end |
// Bit 6 - Transmitter Empty |
initial |
begin |
lsr_reg_bit6_change_allowed = 0; |
@(reset_released); |
#10; |
fork |
begin: tx_fifo_status_and_shift_reg_changing |
forever |
begin |
if ((tx_fifo_status == 0) && tx_shift_reg_empty) |
begin |
// @(tx_reg_written); |
wait (tx_fifo_status > 0); |
lsr_reg_bit6_change_allowed = 1'b1; |
repeat (3) @(posedge wb_clk); |
#2; |
lsr_reg_bit6_change_allowed = 0; |
if (lsr_reg[6]) |
begin |
`BENCH_ERROR("Bit 6 of LSR register not '0'!"); |
-> error_detected; |
end |
end |
else |
begin |
wait ((tx_fifo_status == 0) && tx_shift_reg_empty); |
lsr_reg_bit6_change_allowed = 1'b1; |
repeat (3) @(posedge wb_clk); |
#2; |
lsr_reg_bit6_change_allowed = 0; |
if (~lsr_reg[6]) |
begin |
`BENCH_ERROR("Bit 6 of LSR register not '1'!"); |
-> error_detected; |
end |
end |
end |
end |
begin: lsr_reg_bit6_changing |
forever |
begin |
wait (~lsr_reg_bit6_change_allowed); |
begin |
@(lsr_reg[6] or lsr_reg_bit6_change_allowed); |
if (~lsr_reg_bit6_change_allowed) |
begin |
`BENCH_ERROR("Bit 6 of LSR register should not change!"); |
-> error_detected; |
end |
end |
end |
end |
join |
end |
// Bit 7 - Error in RX FIFO |
initial |
begin |
lsr_reg_bit7_change_allowed = 0; |
@(reset_released); |
#10; |
fork |
begin: error_changing |
forever |
begin |
if ((rx_fifo_par == 0) && (rx_fifo_frm == 0) && (rx_fifo_brk == 0)) |
begin |
wait (rx_parity_err || rx_framing_err || rx_framing_glitch || rx_break_int); |
lsr_reg_bit7_change_allowed = 1'b1; |
repeat (3) @(posedge wb_clk); |
#2; |
lsr_reg_bit7_change_allowed = 0; |
// check bit |
if (~lsr_reg[7]) |
begin |
`BENCH_ERROR("Bit 7 of LSR register not '1'!"); |
-> error_detected; |
end |
end |
else |
begin |
wait (lsr_reg_read && (rx_fifo_par == 0) && (rx_fifo_frm == 0) && (rx_fifo_brk == 0)); |
lsr_reg_bit7_change_allowed = 1'b1; |
repeat (2) @(posedge wb_clk); |
#2; |
lsr_reg_bit7_change_allowed = 0; |
// check bit |
if (lsr_reg[7]) |
begin |
`BENCH_ERROR("Bit 7 of LSR register not '0'!"); |
-> error_detected; |
end |
end |
end |
end |
begin: lsr_reg_bit7_changing |
forever |
begin |
wait (~lsr_reg_bit7_change_allowed); |
begin |
@(lsr_reg[7] or lsr_reg_bit7_change_allowed); |
if (~lsr_reg_bit7_change_allowed) |
begin |
`BENCH_ERROR("Bit 7 of LSR register should not change!"); |
-> error_detected; |
end |
end |
end |
end |
join |
end |
|
|
// UART transmitter monitor |
//######################### |
|
// TX FIFO status |
always@(tx_fifo_wr_pointer or tx_fifo_rd_pointer) |
begin |
if (tx_fifo_wr_pointer >= tx_fifo_rd_pointer) |
tx_fifo_status = tx_fifo_wr_pointer - tx_fifo_rd_pointer; |
else |
tx_fifo_status = (5'h1F - tx_fifo_rd_pointer) + tx_fifo_wr_pointer; |
end |
// TX FIFO and TX data |
initial |
begin |
tx_fifo_wr_pointer = 0; |
tx_fifo_rd_pointer = 0; |
tx_shift_reg_empty = 1; |
tx_fifo_status = 0; |
tx_start_bit_edge = 1; |
fork |
begin:write_tx_shift_reg_read_tx_fifo |
forever |
begin |
wait ((tx_fifo_status !== 0) && tx_shift_reg_empty && tx_start_bit_edge && ~stx_pad_o); |
tx_start_bit_edge = 0; |
tx_shift_reg = tx_fifo[tx_fifo_rd_pointer]; |
tx_shift_reg_empty = 0; |
@(testbench.i_uart_device.device_received_last_bit); |
repeat (16393) @(posedge wb_clk); |
tx_fifo_rd_pointer = tx_fifo_rd_pointer + 1'b1; |
@(posedge wb_clk); |
if (tx_fifo_status == 0) |
begin |
`BENCH_MSG("TX FIFO is empty!"); |
end |
end |
end |
begin:write_tx_fifo |
forever |
begin |
@(tx_reg_written); // write to FIFO |
repeat (1) @(posedge wb_clk); // delay when writing into registers |
if (tx_fifo_status <= 5'h0F) |
begin |
tx_fifo[tx_fifo_wr_pointer] = reg_dat; |
tx_fifo_wr_pointer = tx_fifo_wr_pointer + 1'b1; |
end |
else // FIFO overflow |
begin |
`BENCH_WARNING("TX FIFO overflow!"); |
end |
end |
end |
begin:empty_tx_fifo |
forever |
begin |
wait (fcr_reg[2]); |
tx_fifo_wr_pointer = 0; |
tx_fifo_rd_pointer = 0; |
@(posedge wb_clk); |
if (tx_fifo_status == 0) |
begin |
`BENCH_MSG("TX FIFO is empty!"); |
end |
end |
end |
begin:read_tx_shift_reg |
forever |
begin |
@(testbench.i_uart_device.device_received_packet); |
// Check data |
if (tx_shift_reg != testbench.i_uart_device.rx_data) |
begin |
`BENCH_ERROR("TX data has ERROR!"); |
-> error_detected; |
end |
else |
`BENCH_MSG("TX data correct!"); |
if (testbench.i_uart_device.rx_parity_error) |
begin |
`BENCH_ERROR("TX data has parity ERROR!"); |
-> error_detected; |
end |
else |
`BENCH_MSG("TX data parity correct!"); |
if (testbench.i_uart_device.rx_framing_error) |
begin |
`BENCH_ERROR("TX data has framing ERROR!"); |
-> error_detected; |
end |
else |
`BENCH_MSG("TX data framing correct!"); |
// Set TX FIFO read pointer |
tx_start_bit_edge = 1; |
repeat (7) @(wb_clk); |
if (tx_shift_reg_empty == 0) |
begin |
tx_shift_reg_empty = 1'b1; |
end |
else |
begin |
`BENCH_ERROR("TX shift register empty while transmiting data!"); |
-> error_detected; |
end |
end |
end |
join |
end |
|
|
// UART receiver monitor |
//###################### |
|
// RX FIFO status |
always@(rx_fifo_wr_pointer or rx_fifo_rd_pointer) |
begin |
if (rx_fifo_wr_pointer >= rx_fifo_rd_pointer) |
rx_fifo_status = rx_fifo_wr_pointer - rx_fifo_rd_pointer; |
else |
rx_fifo_status = (5'h1F - rx_fifo_rd_pointer) + rx_fifo_wr_pointer; |
end |
// RX FIFO and RX data |
initial |
begin |
rx_parity_err = 0; |
rx_framing_err = 0; |
rx_framing_glitch = 0; |
rx_break_int = 0; |
rx_overrun_err_occured = 0; |
rx_fifo_par = 0; |
rx_fifo_frm = 0; |
rx_fifo_brk = 0; |
rx_shift_reg_full = 0; |
rx_fifo_wr_pointer = 0; |
rx_fifo_rd_pointer = 0; |
rx_fifo_status = 0; |
fork |
begin:write_rx_shift_reg |
forever |
begin |
@(testbench.i_uart_device.device_sent_packet); |
repeat (1) @(posedge wb_clk); |
rx_shift_reg = testbench.i_uart_device.sent_data; |
rx_parity_err = testbench.i_uart_device.tx_parity_enabled && |
(testbench.i_uart_device.tx_parity_wrong || |
( // sample point is BIT_NUM * 2 - 1 => 3, 5, 7... |
((testbench.i_uart_device.tx_glitch_num == (3 * 8 * testbench.i_uart_device.T_divisor)) || |
(testbench.i_uart_device.tx_glitch_num == (5 * 8 * testbench.i_uart_device.T_divisor)) || |
(testbench.i_uart_device.tx_glitch_num == (7 * 8 * testbench.i_uart_device.T_divisor)) || |
(testbench.i_uart_device.tx_glitch_num == (9 * 8 * testbench.i_uart_device.T_divisor)) || |
(testbench.i_uart_device.tx_glitch_num == (11 * 8 * testbench.i_uart_device.T_divisor)) || |
(testbench.i_uart_device.tx_glitch_num == (13 * 8 * testbench.i_uart_device.T_divisor)) || |
(testbench.i_uart_device.tx_glitch_num == (15 * 8 * testbench.i_uart_device.T_divisor)) || |
(testbench.i_uart_device.tx_glitch_num == (17 * 8 * testbench.i_uart_device.T_divisor)) || |
(testbench.i_uart_device.tx_glitch_num == (19 * 8 * testbench.i_uart_device.T_divisor)) || |
(testbench.i_uart_device.tx_glitch_num == (21 * 8 * testbench.i_uart_device.T_divisor)) || |
(testbench.i_uart_device.tx_glitch_num == (23 * 8 * testbench.i_uart_device.T_divisor))) && |
(testbench.i_uart_device.tx_glitch_num[23:0] < ((testbench.i_uart_device.tx_length + 2'h1) * |
16 * testbench.i_uart_device.T_divisor)) |
)); |
rx_framing_err = testbench.i_uart_device.tx_framing_wrong; |
rx_framing_glitch = (testbench.i_uart_device.tx_glitch_num == ((((testbench.i_uart_device.tx_length + 2'h2 + |
testbench.i_uart_device.tx_parity_enabled) * |
2) - 1'b1) * 8 * testbench.i_uart_device.T_divisor)); |
rx_break_int = testbench.i_uart_device.tx_break_enable && |
(testbench.i_uart_device.tx_break_num[15:0] >= ((testbench.i_uart_device.tx_length + 2'h2 + |
testbench.i_uart_device.tx_parity_enabled) * |
16 * testbench.i_uart_device.T_divisor)); |
-> testbench.i_uart_device.sent_packet_received; |
if (rx_fifo_status > 5'h0F) |
rx_overrun_err_occured = 1'b1; |
rx_shift_reg_full = 1'b1; |
end |
end |
begin:write_rx_fifo_read_rx_shift_reg |
forever |
begin |
wait (rx_shift_reg_full); |
if (rx_fifo_status <= 5'h0F) |
begin |
rx_fifo_data[rx_fifo_wr_pointer] = testbench.i_uart_device.sent_data; |
rx_fifo_par[rx_fifo_wr_pointer] = rx_parity_err; |
rx_fifo_frm[rx_fifo_wr_pointer] = rx_framing_err || rx_framing_glitch; |
rx_fifo_brk[rx_fifo_wr_pointer] = rx_break_int; |
rx_fifo_wr_pointer = rx_fifo_wr_pointer + 1'b1; |
end |
else // FIFO overflow |
begin |
`BENCH_WARNING("RX FIFO overflow!"); |
end |
repeat (1) @(posedge wb_clk); |
rx_shift_reg_full = 0; |
end |
end |
begin:empty_rx_fifo |
forever |
begin |
wait (fcr_reg[1]); |
rx_fifo_wr_pointer = 0; |
rx_fifo_rd_pointer = 0; |
// rx_fifo_par = 0; |
// rx_fifo_frm = 0; |
// rx_fifo_brk = 0; |
@(posedge wb_clk); |
if (rx_fifo_status == 0) |
begin |
`BENCH_MSG("RX FIFO is empty!"); |
end |
end |
end |
begin:read_rx_fifo |
rx_fifo_read = 0; |
forever |
begin |
@(rx_reg_read); |
if (rx_fifo_status > 0) |
begin |
rx_fifo_read = 1'b1; |
// Check data |
if (rx_fifo_data[rx_fifo_rd_pointer] != reg_dat) |
begin |
`BENCH_ERROR("RX data has ERROR!"); |
-> error_detected; |
end |
else |
begin |
`BENCH_MSG("RX data correct!"); |
end |
// Set RX FIFO read pointer |
repeat (1) @(posedge wb_clk); |
rx_fifo_read = 0; |
rx_fifo_rd_pointer = rx_fifo_rd_pointer + 1'b1; |
end |
else |
begin |
`BENCH_WARNING("Reading RX FIFO while RX FIFO is empty!"); |
end |
|
|
if ((~rx_fifo_frm[rx_fifo_rd_pointer] && lsr_reg[3]) || |
(rx_fifo_frm[rx_fifo_rd_pointer] && ~lsr_reg[3])) |
begin |
`BENCH_ERROR("RX data has wrong framing ERROR!"); |
-> error_detected; |
end |
else |
`BENCH_MSG("RX data has correct framing error!"); |
// Set RX FIFO read pointer |
repeat (1) @(posedge wb_clk); |
rx_fifo_read = 0; |
if (rx_fifo_status > 0) |
begin |
// rx_fifo_par[rx_fifo_rd_pointer] = 1'b0; |
// rx_fifo_frm[rx_fifo_rd_pointer] = 1'b0; |
// rx_fifo_brk[rx_fifo_rd_pointer] = 1'b0; |
rx_fifo_rd_pointer = rx_fifo_rd_pointer + 1'b1; |
end |
end |
end |
join |
end |
|
|
// UART interrupt monitor |
//####################### |
|
|
|
|
endmodule |
|
|