📄 uart_testbench.v
字号:
// 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -