Bài viết này sẽ mô tả về các checker được sử dụng trong môi trường UVM là "apb_protocol_checker" và "uart_protocol_checker".
Các bài viết cùng chủ đề có thể tìm thấy ở đây.
1) Tổng quan về checker
Checker là một thành phần hỗ trợ kiểm tra một vài chức năng nào đó của DUT hoặc các thành phần khác trong môi trường test. Checker có nhiệm vụ giám sát điểm cần kiểm tra và đưa ra các cảnh báo nếu điểm cần kiểm tra vi phạm các điều kiện nhất định.
Với ý nghĩa giám sát và kiểm tra, tùy vào từng trường hợp, chức nằng của checker có thể là một thành phần độc lập viết bằng System Verilog đơn thuần hoặc tích hợp trong Monitor hay Scoreboard.
Như vậy, việc có hay không có checker là một tùy chọn của người build môi trường.
Trong thực tế, đối với các thiết kế không thể được tiếp cận sâu hơn vào RTL code mà chỉ có thể test (kiểm tra) thông qua các port (input và output), thì việc thực hiện một thành phần checker độc lập, phần lớn là không cần thiết vì chức năng giám sát và kiểm tra được tích hợp vào Monitor và Scoreboard. Ví dụ, một thiết kế của một nhà cung cấp lõi IP được mua về để sử dụng nhưng bị đóng gói (mã hóa) RTL code.
Đối với các thiết kế tự phát triển, ví dụ như lõi IP UART-APB trong loạt bài viết này, checker có thể giúp giám sát và kiểm tra hoạt động của các tín hiệu nội nằm bên sâu bên trong thiết kế thông qua việc sự dụng đường dẫn cấu trúc, ví dụ như:
testTop.dut_top.uart_0.receiver.<tên tín hiệu>
Trong ví dụ trên, chúng ta lấy một tín hiệu chứa trong instance "receiver" của "uart_0".
Việc sử dụng checker giúp kiểm tra và xác thực hoạt động chính xác của các tín hiệu nội trong các điều kiện test. Bên cạnh đó, checker có thể hỗ trợ phát hiện lỗi bên trong thiết kế một cách hiệu quả.
Hình 1: Minh họa kết nối tín hiệu cần kiểm tra đến checker |
Đối với môi trường này, hai checker được sử dụng để kiểm tra một số điều kiện lỗi trên giao thức APB và UART. Việc kiểm tra này có thể thực hiện bằng cách cách khác. Tuy nhiên, các bạn hãy xem đây như một tham khảo về việc thực hiện checker.
2) Mô tả các thực hiện checker
Trong môi trường, các checker được đặt trong thư mục "UvmEnvUartApb/checker". Mỗi checker gồm 2 phần:
- Lõi checker: là một module thực thi giám sát và kiểm tra chức năng các input của nó. Các input là các điểm cần test.
- <tên checker>.sv
- Kết nối checker (Top checker): là một module gọi (instance) lõi checker và kết nối các điểm cần check của môi trường đến lõi checker.
- <tên checker>_top.sv
Trong đó, Top checker sẽ được instance ở file top của môi trường, file testTop.sv, và cùng cấp với instance của top DUT là module dut_top.
Môi trường hiện tại có hai checker là:
Hình 2: Vị trí của checker trong môi trường |
- APB protocol checker
- UART protocol checker
- APB protocol checker có 2 instance:
- apb0_chk nối với APB interface giữa Driver của coApbMasterAgentTx và uart_0 trong dut_top
- apb1_chk nối với APB interface giữa Driver của coApbMasterAgentRx và uart_1 trong dut_top
- UART protocol checker có 2 instance:
- uart0_chk nối với:
- APB interface giữa Driver của coApbMasterAgentTx và uart_0 trong dut_top
- đường truyền UART uart_0to1, đường kết nối từ port truyền nối tiếp uart_tx của uart_0 đến port nhận nối tiếp của uart_1
- apb1_chk nối với:
- APB interface giữa Driver của coApbMasterAgentRx và uart_1 trong dut_top
- đường truyền UART uart_1to0, đường kết nối từ port truyền nối tiếp uart_tx của uart_1 đến port nhận nối tiếp của uart_0
Hình 3: Vị trí các checker apb_protocol_checker_top và uart_protocol_checker_top trong đường bao số 2 |
Mỗi checker sẽ có 3 cấp cảnh báo lỗi, gọi là SEVERITY, là:
- ERROR - Lỗi phải sửa
- WARNING - Cảnh báo phải kiểm tra
- INFO - Thông tin giúp việc debug và trace dễ dàng hơn
Mỗi cấp độ cảnh báo lỗi sẽ được quy định có hiển thị hay không thông qua các `define sau khi chạy mô phỏng:
- APB_ERROR_SEVERITY - Chỉ hiện thị các thông điệp ERROR
- APB_WARNING_SEVERITY - Chỉ hiện thị các thông điệp ERROR và WARNING
- APB_INFO_SEVERITY - Hiện thị các thông điệp ERROR, WARNING và INFO
Mặc định là APB_ERROR_SEVERITY, nghĩa là chỉ có các thông điệp ở mức ERROR được hiển thị nếu có.
2) APB protocol checker
APB protocol checker là checker giám sát kiểm tra giao thức APB giữa Driver và DUT (dut_top).
Checker này sẽ dùng một biến trạng thái apb_state[1:0] để giám sát trạng thái SETUP và ACCESS của một APB transfer.
Máy trạng thái của checker hoạt động như sau:
Ví dụ 1 - Máy trạng thái của APB protocol checker
Ví dụ 4 - Code in thông tin read/write transfer của APB
Hình 4: Các trạng thái hoạt động của APB protocol, tham khảo mục Operating states trong tài liệu AMBA™ 3 APB Protocol specification của ARM |
- Luôn giữ trong trạng thái IDLE khi reset đang xảy ra, preset_n=0
- Chuyển từ IDLE sang trạng thái giám sát SETUP, SETUP_CHECK, ngay khi hết reset, preset_n=1
- Chuyển từ trạng thái SETUP_CHECK sang trạng thái ACCESS_CHECK khi psel=1
- Chuyển từ trạng thái ACCESS_CHECK về SETUP_CHECK khi pready=1
Hình 5: Máy trạng thái (FSM) của APB protocol checker |
always @ (posedge pclk, negedge preset_n) beginChecker sẽ báo lỗi trong hai trường hợp sau:
if (~preset_n) apb_state <= `DLYCHK IDLE;
else apb_state[1:0] <= `DLYCHK apb_next_state[1:0];
end
always @ (*) begin
case (apb_state[1:0])
IDLE: begin
apb_next_state[1:0] = SETUP_CHECK;
end
SETUP_CHECK: begin
if (psel)
apb_next_state[1:0] = ACCESS_CHECK;
else
apb_next_state[1:0] = SETUP_CHECK;
end
ACCESS_CHECK: begin
if (pready)
apb_next_state[1:0] = SETUP_CHECK;
else
apb_next_state[1:0] = ACCESS_CHECK;
end
default: begin
apb_next_state[1:0] = apb_state[1:0];
end
endcase
end
- [APB_ERROR] psel và penable cùng tích cực trong trạng thái SETUP_CHECK
- [APB_ERROR] penable không tích cực trong trạng thái ACCESS_CHECK
always @ (posedge pclk) beginBên cạnh đó, checker còn hỗ trợ cảnh báo giá trị "x" và "z" trên các tín hiệu APB trong khi hoạt động, bao gồm:
case (apb_state[1:0])
SETUP_CHECK: begin
if (psel) begin
//Check 1
if (penable) begin
$display ("[APB_ERROR][%s][%t] PSEL and PENABLE are asserted 1 in the SETUP phase\n", INST_NAME, $time);
end
end
end
ACCESS_CHECK: begin
//Check 1
if (~penable) begin
$display ("[APB_ERROR][%s][%t] PENABLE is not asserted 1 in the ACCESS phase\n", INST_NAME, $time);
end
end
endcase
end
- [APB_ERROR] Báo lỗi psel bị "x" hoặc "z"
- [APB_ERROR] Báo lỗi penable bị "x" hoặc "z"
- [APB_ERROR] Báo lỗi pwrite bị "x" hoặc "z"
- [APB_ERROR] Báo lỗi paddr bị "x" hoặc "z"
- [APB_ERROR] Báo lỗi pstrb bị "x" hoặc "z" trong Write transfer
- [APB_ERROR] Báo lỗi pready bị "x" hoặc "z"
- [APB_ERROR] Báo lỗi pslverr bị "x" hoặc "z"
- [APB_WARNING] Báo lỗi pwdata bị "x" hoặc "z"
- [APB_WARNING] Báo lỗi prdata bị "x" hoặc "z"
assign paddr_or = |paddr;Cuối cùng, checker hỗ trợ hiển thị thông tin các Read/Write transfer trên các APB interface hỗ trợ bedug khi cần.
assign pstrb_or = |pstrb;
assign pwdata_or = |pwdata;
assign prdata_or = |prdata;
always @ (posedge pclk) begin
if (preset_n & psel) begin
//Check 2
case (penable)
1'bx: $display ("[APB_ERROR][%s][%t] PENABLE is x\n", INST_NAME, $time);
1'bz: $display ("[APB_ERROR][%s][%t] PENABLE is z\n", INST_NAME, $time);
endcase
//Check 3
case (pwrite)
1'bx: $display ("[APB_ERROR][%s][%t] PWRITE is x\n", INST_NAME, $time);
1'bz: $display ("[APB_ERROR][%s][%t] PWRITE is z\n", INST_NAME, $time);
endcase
//Check 4
case (paddr_or)
1'bx: $display ("[APB_ERROR][%s][%t] PADDR is x\n", INST_NAME, $time);
1'bz: $display ("[APB_ERROR][%s][%t] PADDR is z\n", INST_NAME, $time);
endcase
//Check 5
if (pwrite) begin
case (pstrb_or)
1'bx: $display ("[APB_ERROR][%s][%t] PSTRB is x\n", INST_NAME, $time);
1'bz: $display ("[APB_ERROR][%s][%t] PSTRB is z\n", INST_NAME, $time);
endcase
end
//Check 7
case (pready)
1'bx: $display ("[APB_ERROR][%s][%t] PREADY is x\n", INST_NAME, $time);
1'bz: $display ("[APB_ERROR][%s][%t] PREADY is z\n", INST_NAME, $time);
endcase
//Check 8
if (pready) begin
case (pslverr)
1'bx: $display ("[APB_ERROR][%s][%t] PSLVERR is x\n", INST_NAME, $time);
1'bz: $display ("[APB_ERROR][%s][%t] PSLVERR is z\n", INST_NAME, $time);
endcase
end
//Check 6
`ifdef APB_WARNING_SEVERITY
if (pwrite) begin
case (pwdata_or)
1'bx: $display ("[APB_WARNING][%s][%t] PWDATA is x\n", INST_NAME, $time);
1'bz: $display ("[APB_WARNING][%s][%t] PWDATA is z\n", INST_NAME, $time);
endcase
end
//Check 9
if (pready) begin
case (prdata_or)
1'bx: $display ("[APB_WARNING][%s][%t] PRDATA is x\n", INST_NAME, $time);
1'bz: $display ("[APB_WARNING][%s][%t] PRDATA is z\n", INST_NAME, $time);
endcase
end
`endif
end
//Check 10
case (psel)
1'bx: $display ("[APB_ERROR][%s][%t] PSEL is x\n", INST_NAME, $time);
1'bz: $display ("[APB_ERROR][%s][%t] PSEL is z\n", INST_NAME, $time);
endcase
end
Ví dụ 4 - Code in thông tin read/write transfer của APB
always @ (posedge pclk) begin
if ((apb_state[1:0] == ACCESS_CHECK) & pready) begin
if (pwrite) begin
$display ("[APB_INFO][%s][%t] A WRITE transaction PADDR=%8h PWDATA=%8h PSTRB=%4h PSLVERR=%b\n", INST_NAME, $time, paddr, pwdata, pstrb, pslverr);
end
else begin
$display ("[APB_INFO][%s][%t] A READ transaction PADDR=%8h PRDATA=%h PSLVERR=%b\n", INST_NAME, $time, paddr, prdata, pslverr);
end
end
end
end
3) UART protocol checker
UART protocol checker là checker giám sát độ rộng bit truyền trên đường truyền UART, từ chân TX của UART này đến chân RX của UART kia. Để thực hiện được điều này, checker sẽ cần biết các thông tin cấu hình liên quan đến khung truyền UART. Vì vậy, ngoài UART interface, checker còn được kết nối đến APB interface để cập nhật thông tin cấu hình của DUT khi thông tin này bị thay đổi.
Các thông tin liên quan đến khung truyền UART bao gồm:
Ví dụ 6 - Code của FSM
Ví dụ 7 - Code của bộ đếm số bit trong truyền UART
Ví dụ 8 - Code bộ đếm độ rộng bit
Các thông tin liên quan đến khung truyền UART bao gồm:
- UART có được enable hay không? bit 0 của thanh ghi SE, địa chỉ offset 0x04
- UART có truyền parity hay không? bit 1 của thanh ghi SE, địa chỉ offset 0x04
- Tốc độ baud được thiết lập là bao nhiêu? thanh ghi BR, địa chỉ offset 0x08
Ví dụ 5 - Code lưu lại thông tin cấu hình của UART
assign reg_sel = psel & penable & pready;Về phía đường truyền UART, một bit trạng thái được sử dụng để giám sát khi nào đường truyền cần được kiểm tra. Bit này được tích cực 1 nếu phát hiện một cạnh xuống trên đường truyền UART và xóa khi kết thúc của bit STOP.
assign reg_we = pwrite & reg_sel & (&pstrb[3:0]);
assign se_we = reg_we & (paddr[4:0] == 5'b0_0100);
assign br_we = reg_we & (paddr[4:0] == 5'b0_1000);
//Enable register
always @(posedge pclk)begin
if(~preset_n) apb_chk_se_info[2:0] <= `DLYCHK 3'd0;
else if(se_we) apb_chk_se_info[2:0] <= `DLYCHK pwdata[2:0];
end
//Baud rate register
always @(posedge pclk)begin
if(~preset_n) apb_chk_br_info[7:0] <= `DLYCHK 8'd0;
else if(br_we) apb_chk_br_info[7:0] <= `DLYCHK pwdata[7:0];
end
Ví dụ 6 - Code của FSM
// Detect the falling edgeViệc phát hiện START và STOP bit của checker hoạt động độc lập với DUT. Một bộ đếm số bit truyền, bit_count, trong khung truyền UART sẽ giám sát khi nào một khung truyền UART được hoàn thành.
always @ (posedge pclk, negedge preset_n) begin
if (~preset_n) uart_net_sync <= `DLYCHK 1'b1;
else uart_net_sync <= `DLYCHK uart_net;
end
assign uart_net_rising = ~uart_net_sync & uart_net;
assign uart_net_falling = uart_net_sync & ~uart_net;
//Select the number of bits of UART frame
always @ (posedge pclk, negedge preset_n) begin
if (~preset_n)
chk_uart_state <= `DLYCHK CHK_UART_IDLE;
else if (frame_start)
chk_uart_state <= `DLYCHK CHK_UART_CHECK;
else if (frame_end)
chk_uart_state <= `DLYCHK CHK_UART_IDLE;
end
assign frame_end = next_bit & apb_chk_se_info[0]
& (bit_count[3:0] == uart_bit_num[3:0]);
assign frame_start = uart_net_falling & (~chk_uart_state | frame_end);
Ví dụ 7 - Code của bộ đếm số bit trong truyền UART
assign bit_count_clr = frame_end;Nguyên tắc kiểm tra độ rộng bit như sau:
assign bit_count_inc = (chk_uart_state == CHK_UART_CHECK) & next_bit;
always @ (posedge pclk, negedge preset_n) begin
if (~preset_n)
bit_count[3:0] <= `DLYCHK 4'd0;
else if (bit_count_clr)
bit_count[3:0] <= `DLYCHK 4'd0;
else if (bit_count_inc)
bit_count[3:0] <= `DLYCHK bit_count[3:0] + 1'b1;
end
// Parity: START - 8 DATA - 1 Parity - 1 STOP
// No parity: START - 8 DATA - 1 STOP
assign uart_bit_num[3:0] = apb_chk_se_info[1]? 4'd10: 4'd9;
//UART bit width
assign bit_width[12:0] = 16*(apb_chk_br_info[7:0] + 1'b1) - 1'b1;
//Bit width counter
assign next_bit = (width_count[12:0] == bit_width[12:0]);
- Giá trị bit sẽ được lưu lại trong 1 biến, bitCheckedValue, khi bắt đầu mỗi bit. Một bộ đếm độ rộng bit, width_count, được sử dụng để giám sát khi nào kết thúc 1 bit. Bộ đếm độ rộng bit đếm số xung clock theo công thức baud rate mà DUT hỗ trợ.
- Trong suốt qua trình kiểm tra, nếu giá trị trên đường truyền UART khác giá trị bit cần kiểm tra lưu trong bitCheckedValue thì một lỗi sinh ra.
Ví dụ 8 - Code bộ đếm độ rộng bit
assign clr_width_count = next_bit;
assign inc_width_count = chk_uart_state;
always @ (posedge pclk, negedge preset_n) begin
if (~preset_n) width_count[12:0] <= `DLYCHK 13'd0;
else if (clr_width_count)
width_count[12:0] <= `DLYCHK 13'd0;
else if (inc_width_count)
width_count[12:0] <= `DLYCHK width_count[12:0] + 1'b1;
end
Ví dụ 9 - Code của phần kiểm tra giá trị bit truyền ứng với độ rộng bit đã thiết lập
always @ (posedge pclk) begin
if (preset_n & next_bit)
bitCheckedValue <= `DLYCHK uart_net;
end
assign baud_rate_error = (bitCheckedValue != uart_net_sync) & chk_uart_state;
always @ (posedge pclk, negedge preset_n) begin
if (~preset_n) begin
baud_rate_error_sync <= `DLYCHK 1'b0;
end
else begin
baud_rate_error_sync <= `DLYCHK baud_rate_error;
end
end
assign baud_rate_error_rising = ~baud_rate_error_sync & baud_rate_error;
//
always @ (posedge pclk, negedge preset_n) begin
if (~preset_n) begin
baud_rate_error_report <= `DLYCHK 1'b0;
end
else if (preset_n & baud_rate_error) begin
baud_rate_error_report <= `DLYCHK 1'b1;
end
end
Cuối cùng, checker sẽ cảnh báo các lỗi sau đây:
- Lỗi đường truyền UART bị "x" hoặc "z".
- Lỗi nếu độ rộng bit bị vi phạm, vi phạm này xảy ra khi giá trị 1 bit bị thay đổi trước khi bit này đạt được độ rộng mong muốn.
Ví dụ 10 - Code của phần cảnh báo lỗi "x" và "z" trên đường truyền UART
always @ (posedge pclk) beginif (preset_n) begincase (uart_net)1'bx: $display ("[UART_ERROR][%t][%s] %s is x\n", $time, INST_NAME, INST_NET);1'bz: $display ("[UART_ERROR][%t][%s] %s is z\n", $time, INST_NAME, INST_NET);endcaseendend
Ví dụ 11 - Code của phần cảnh báo lỗi độ rộng bit
always @ (posedge pclk, negedge preset_n) begin
if (preset_n & baud_rate_error_rising) begin
$display ("[UART_ERROR][%t][%s] %s Bit width is violated \n-- Expected bit value: %b\n-- Actual bit value: %b", $time, INST_NAME, INST_NET, bitCheckedValue, uart_net_sync);
end
end
Chi tiết hơn các bạn hãy tải code của checker, chạy mô phỏng thử, xem waveform để phân tích.
Dữ liệu có thể tải:
Lịch sử cập nhật:
1/ 2019.09.22 - Tạo lần đầu
Danh sách tác giả:
1. Phạm Thanh Trâm
2. Nguyễn Sinh Tơn
3. Đoàn Đức Hoàng (email: hoangbk154@gmail.com)
4. Trương Công Hoàng Việt
5. Nguyễn Hùng Quân
0 bình luận:
Đăng nhận xét