* feat: add ability to enable error output on the cpuif, when decoding errors occur (generate_cpuif_err in API). * fix: move signal to new place (after automatic vers) * feat: add info about new api (generate_cpuif_err) * fix: repair readback with latency * Adding generate_cpuif_err argument to peakrdl-regblock to generate cpuif error response, when the address is decoded incorrectly * add sw rd or/and wr attribure error response related and add error respone for external mem * add sw rd or/and wr error response test * add sw rd or/and wr error response for external register test and fix generation of rtl logic for external register * add sw rd or/and wr error response for external mem test * add sw rd or/and wr error response for apb3 imterfaces driver * add error response test for APB4, AXI4Lite and Avalon interfaces * rename --generate_cpuif_err to --generate-cpuif-err * style: minor typo fixes and test clean-up * refactor: move expected error check inside write/read functions * feat: add error response check to OBI testbench interface * feat: split generate-cpuif-err option into err-if-bad-addr and err-if-bad-rw options * feat: add err_if_bad_addr/rw to cfg_schema * feat: extend cpuif_err_rsp test to cover all combinations of bad_addr/bad_rw * style: lint fixes * fix: removed redundant if node.external condition to help coverage * Fix dangling hwif_in signals in testcase --------- Co-authored-by: Denis Trifonov <d.trifonov@yadro.com> Co-authored-by: Dominik Tanous <tanous@kandou.com> Co-authored-by: Sebastien Baillou <baillou@kandou.com> Co-authored-by: Alex Mykyta <amykyta3@users.noreply.github.com>
141 lines
4.9 KiB
Systemverilog
141 lines
4.9 KiB
Systemverilog
interface avalon_mm_intf_driver #(
|
|
parameter DATA_WIDTH = 32,
|
|
parameter ADDR_WIDTH = 32
|
|
)(
|
|
input wire clk,
|
|
input wire rst,
|
|
avalon_mm_intf.host avalon
|
|
);
|
|
timeunit 1ps;
|
|
timeprecision 1ps;
|
|
|
|
localparam ADDR_PAD = $clog2(DATA_WIDTH/8);
|
|
localparam WORD_ADDR_WIDTH = ADDR_WIDTH - ADDR_PAD;
|
|
|
|
logic av_read;
|
|
logic av_write;
|
|
logic av_waitrequest;
|
|
logic [WORD_ADDR_WIDTH-1:0] av_address;
|
|
logic [DATA_WIDTH-1:0] av_writedata;
|
|
logic [DATA_WIDTH/8-1:0] av_byteenable;
|
|
logic av_readdatavalid;
|
|
logic av_writeresponsevalid;
|
|
logic [DATA_WIDTH-1:0] av_readdata;
|
|
logic [1:0] av_response;
|
|
|
|
assign avalon.read = av_read;
|
|
assign avalon.write = av_write;
|
|
assign av_waitrequest = avalon.waitrequest;
|
|
assign avalon.address = av_address;
|
|
assign avalon.writedata = av_writedata;
|
|
assign avalon.byteenable = av_byteenable;
|
|
assign av_readdatavalid = avalon.readdatavalid;
|
|
assign av_writeresponsevalid = avalon.writeresponsevalid;
|
|
assign av_readdata = avalon.readdata;
|
|
assign av_response = avalon.response;
|
|
|
|
default clocking cb @(posedge clk);
|
|
default input #1step output #1;
|
|
output av_read;
|
|
output av_write;
|
|
input av_waitrequest;
|
|
output av_address;
|
|
output av_writedata;
|
|
output av_byteenable;
|
|
input av_readdatavalid;
|
|
input av_writeresponsevalid;
|
|
input av_readdata;
|
|
input av_response;
|
|
endclocking
|
|
|
|
task automatic reset();
|
|
cb.av_read <= '0;
|
|
cb.av_write <= '0;
|
|
cb.av_address <= '0;
|
|
cb.av_writedata <= '0;
|
|
cb.av_byteenable <= '0;
|
|
endtask
|
|
|
|
semaphore req_mutex = new(1);
|
|
semaphore resp_mutex = new(1);
|
|
|
|
task automatic write(logic [ADDR_WIDTH-1:0] addr, logic [DATA_WIDTH-1:0] data, logic [DATA_WIDTH/8-1:0] strb = {DATA_WIDTH{1'b1}}, logic expects_err = 1'b0);
|
|
fork
|
|
begin
|
|
req_mutex.get();
|
|
##0;
|
|
// Initiate transfer
|
|
cb.av_write <= '1;
|
|
cb.av_address <= (addr >> ADDR_PAD);
|
|
cb.av_writedata <= data;
|
|
cb.av_byteenable <= strb;
|
|
@(cb);
|
|
|
|
// Wait for transfer to be accepted
|
|
while(cb.av_waitrequest == 1'b1) @(cb);
|
|
reset();
|
|
req_mutex.put();
|
|
end
|
|
|
|
begin
|
|
resp_mutex.get();
|
|
@cb;
|
|
// Wait for response
|
|
while(cb.av_writeresponsevalid !== 1'b1) @(cb);
|
|
assert(!$isunknown(cb.av_response)) else $error("Write to 0x%0x returned X's on av_response", addr);
|
|
assert((cb.av_response == 2'b10) == expects_err) else $error("Error write response to 0x%x returned 0x%x. Expected 0x%x", addr, (cb.av_response == 2'b10), expects_err);
|
|
resp_mutex.put();
|
|
end
|
|
join
|
|
endtask
|
|
|
|
task automatic read(logic [ADDR_WIDTH-1:0] addr, output logic [DATA_WIDTH-1:0] data, input logic expects_err = 1'b0);
|
|
fork
|
|
begin
|
|
req_mutex.get();
|
|
##0;
|
|
// Initiate transfer
|
|
cb.av_read <= '1;
|
|
cb.av_address <= (addr >> ADDR_PAD);
|
|
@(cb);
|
|
|
|
// Wait for transfer to be accepted
|
|
while(cb.av_waitrequest == 1'b1) @(cb);
|
|
reset();
|
|
req_mutex.put();
|
|
end
|
|
|
|
begin
|
|
resp_mutex.get();
|
|
@cb;
|
|
// Wait for response
|
|
while(cb.av_readdatavalid !== 1'b1) @(cb);
|
|
assert(!$isunknown(cb.av_readdata)) else $error("Read from 0x%0x returned X's on av_response", av_readdata);
|
|
assert(!$isunknown(cb.av_response)) else $error("Read from 0x%0x returned X's on av_response", addr);
|
|
assert((cb.av_response == 2'b10) == expects_err) else $error("Error read response from 0x%x returned 0x%x. Expected 0x%x", addr, (cb.av_response == 2'b10), expects_err);
|
|
data = cb.av_readdata;
|
|
resp_mutex.put();
|
|
end
|
|
join
|
|
endtask
|
|
|
|
task automatic assert_read(logic [ADDR_WIDTH-1:0] addr, logic [DATA_WIDTH-1:0] expected_data, logic [DATA_WIDTH-1:0] mask = {DATA_WIDTH{1'b1}}, input logic expects_err = 1'b0);
|
|
logic [DATA_WIDTH-1:0] data;
|
|
read(addr, data, expects_err);
|
|
data &= mask;
|
|
assert(data == expected_data) else $error("Read from 0x%x returned 0x%x. Expected 0x%x", addr, data, expected_data);
|
|
endtask
|
|
|
|
initial begin
|
|
reset();
|
|
end
|
|
|
|
initial forever begin
|
|
@cb;
|
|
if(!rst) assert(!$isunknown(cb.av_waitrequest)) else $error("Saw X on av_waitrequest!");
|
|
if(!rst) assert(!$isunknown(cb.av_readdatavalid)) else $error("Saw X on av_readdatavalid!");
|
|
if(!rst) assert(!$isunknown(cb.av_writeresponsevalid)) else $error("Saw X on av_writeresponsevalid!");
|
|
end
|
|
|
|
endinterface
|