From 8651fe2b0f78569d4fc1c182833a08d6e463ebe6 Mon Sep 17 00:00:00 2001 From: Wojciech Kosior Date: Fri, 4 Sep 2020 17:08:21 +0200 Subject: enable parametrizable address and data widths for master model --- models/master.v | 168 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 100 insertions(+), 68 deletions(-) (limited to 'models') diff --git a/models/master.v b/models/master.v index 0e128ec..5c8bacf 100644 --- a/models/master.v +++ b/models/master.v @@ -1,4 +1,10 @@ -/* A wishbone slave testing module (a "mock") */ +/* + * A wishbone slave testing module (a "mock") + * + * It performs a sequence of wishbone writes, reads and waits based on contents + * of provided .mem file. It prints error messages whenever the value it reads + * if different from the one it expects. + */ `default_nettype none `include "messages.vh" @@ -11,95 +17,111 @@ module master_model #( parameter MASTER_NR = -1, + parameter WORD_SIZE = 2, /* in bytes */ + parameter GRANULARITY = 2, /* in bytes */ /* we'll use that soon */ + parameter ADR_BITS = 20, parameter OPERATIONS_FILE = "master_operations.mem", parameter OPERATIONS_COUNT = 10 ) ( - input wire ACK_I, - input wire CLK_I, - output wire [19:0] ADR_O, - input wire [15:0] DAT_I, - output wire [15:0] DAT_O, - input wire RST_I, - output wire STB_O, - output wire CYC_O, - output wire WE_O, - input wire STALL_I, + input wire ACK_I, + input wire CLK_I, + output wire [ADR_BITS - 1 : 0] ADR_O, + input wire [8*WORD_SIZE - 1 : 0] DAT_I, + output wire [8*WORD_SIZE - 1 : 0] DAT_O, + /* output wire [GRANULARITY - 1 : 0] SEL_O, */ /* we'll use that soon */ + input wire RST_I, + output wire STB_O, + output wire CYC_O, + output wire WE_O, + input wire STALL_I, /* Non-wishbone */ - output wire finished + output wire finished ); + parameter WORD_BITS = 8 * WORD_SIZE; + parameter OP_READ = 0, OP_WRITE = 1, OP_WAIT = 2, /* Keep CYC_O high, but STB_O low for 1 tick */ OP_DESELECT = 3; /* Drive CYC_O low for one tick */ - /* - * Bits 39:36 specify type of the operation; bits 35:16 contain the - * address for read wnd write operations (may contain garbage otherwise); - * bits 15:0 contain data to write (for write operation) or expected data - * (for read operation) or are irrelevant (for other operations) - */ - reg [39:0] operations [OPERATIONS_COUNT - 1 : 0]; + /* See below what we need this for */ + parameter BIGGEST_WIDTH = ADR_BITS > WORD_BITS ? ADR_BITS : WORD_BITS; /* - * This will allow us to check whether read operation returned proper data; - * bit 16 tells us whether the corresponding command was a read; if not, - * bits 15:0 don't matter; if yes bits 15:0 contain the data we should - * receive from that read operation + * Contents of this array determine, what this master will do. + * Each (3*n)th element denotes type of operation number n. + * (3*n+1)th element denotes address to use and (3*n+2)th element denotes + * data to use */ - reg [16:0] expected_results [OPERATIONS_COUNT - 1 : 0]; + reg [BIGGEST_WIDTH - 1 : 0] operations [3*OPERATIONS_COUNT - 1 : 0]; - integer i, j; + /* Arrays used for verifying read reaults */ + reg was_read [OPERATIONS_COUNT - 1 : 0]; + reg [WORD_BITS - 1 : 0] expected_data [OPERATIONS_COUNT - 1 : 0]; + + integer i, j; initial begin - $readmemh(OPERATIONS_FILE, operations, 0, OPERATIONS_COUNT - 1); + $readmemh(OPERATIONS_FILE, operations, 0, 3*OPERATIONS_COUNT - 1); j = 0; for (i = 0; i < OPERATIONS_COUNT; i++) begin - if (operations[i][39:36] == OP_READ || - operations[i][39:36] == OP_WRITE) begin - if (operations[i][39:36] == OP_READ) - expected_results[j] <= {1'b1, operations[i][15:0]}; - else - expected_results[j] <= {1'b0, 16'bx}; + if (operations[3*i][1:0] == OP_READ) begin + was_read[j] <= 1; + expected_data[j] <= operations[3*i + 2][WORD_BITS - 1 : 0]; j++; end - end - end + + if (operations[3*i][1:0] == OP_WRITE) begin + was_read[j] <= 0; + expected_data[j] <= {(8 * WORD_SIZE - 1){1'bx}}; - reg [31:0] operations_performed; - reg [31:0] commands_sent; - reg [31:0] commands_acknowledged; + j++; + end + end // for (i = 0; i < OPERATIONS_COUNT; i++) + end // initial begin + + reg [31:0] operations_performed; + reg [31:0] commands_sent; + reg [31:0] commands_acknowledged; /* Those are irrelevant if RST_I is high */ - wire command_successful; - wire wait_successful; - wire deselect_successful; - wire [2:0] current_operation_type; - wire operation_successful; - wire [31:0] operations_performed_next_tick; - wire [39:0] operation_to_perform; - wire acknowledgement_successful; - wire [31:0] commands_sent_next_tick; - wire [31:0] commands_acknowledged_next_tick; - wire [31:0] acknowledgements_needed; + wire command_successful; + wire wait_successful; + wire deselect_successful; + wire [1:0] current_op_type; + wire [ADR_BITS - 1 : 0] current_op_adr; + wire [WORD_BITS - 1 : 0] current_op_data; + wire operation_successful; + wire [31:0] operations_performed_next_tick; + wire acknowledgement_successful; + wire [31:0] commands_sent_next_tick; + wire [31:0] commands_acknowledged_next_tick; + wire [31:0] acknowledgements_needed; assign command_successful = CYC_O && STB_O && !STALL_I; assign wait_successful = !STB_O && !STALL_I; assign deselect_successful = !CYC_O; - assign current_operation_type = operations[operations_performed][39:36]; + + assign current_op_type + = operations[3*operations_performed][1:0]; + assign current_op_adr + = operations[3*operations_performed + 1][ADR_BITS - 1 : 0]; + assign current_op_data + = operations[3*operations_performed + 2][WORD_BITS - 1 : 0]; + assign operation_successful = operations_performed < OPERATIONS_COUNT && - ((current_operation_type == OP_READ && command_successful) || - (current_operation_type == OP_WRITE && command_successful) || - (current_operation_type == OP_WAIT && wait_successful) || - (current_operation_type == OP_DESELECT && deselect_successful)); + ((current_op_type == OP_READ && command_successful) || + (current_op_type == OP_WRITE && command_successful) || + (current_op_type == OP_WAIT && wait_successful) || + (current_op_type == OP_DESELECT && deselect_successful)); assign operations_performed_next_tick = operations_performed + operation_successful; - assign operation_to_perform = operations[operations_performed_next_tick]; assign commands_sent_next_tick = commands_sent + command_successful; assign acknowledgement_successful @@ -109,6 +131,18 @@ module master_model assign acknowledgements_needed = commands_sent_next_tick - commands_acknowledged_next_tick; + wire [31:0] idx_to_use; + wire [1:0] next_op_type; + wire [ADR_BITS - 1 : 0] next_op_adr; + wire [WORD_BITS - 1 : 0] next_op_data; + + assign idx_to_use = operations_performed_next_tick; + assign next_op_type = operations[3*idx_to_use][1:0]; + assign next_op_adr = operations[3*idx_to_use + 1][ADR_BITS - 1 : 0]; + assign next_op_data = operations[3*idx_to_use + 2][WORD_BITS - 1 : 0]; + + /* Drive the outputs */ + reg strobe; assign STB_O = strobe; @@ -147,23 +181,22 @@ module master_model end else begin /* debug messages */ if (command_successful) begin - case (current_operation_type) + case (current_op_type) OP_READ : begin `DBG(("Master %0d: sent read command at h%x", MASTER_NR, - operations[operations_performed][35:16])); + current_op_adr)); end OP_WRITE : begin `DBG(("Master %0d: sent write command of h%x at h%x", - MASTER_NR, operations[operations_performed][15:0], - operations[operations_performed][35:16])); + MASTER_NR, current_op_data, current_op_adr)); end default : `MSG(("Master %0d: error: bug in test bench", MASTER_NR)); - endcase // case (current_operation_type) + endcase // case (current_op_type) end // if (command_successful) if (acknowledgement_successful) begin - if (expected_results[commands_acknowledged][16]) + if (was_read[commands_acknowledged]) `DBG(("Master %0d: acknowledged read of h%x", MASTER_NR, DAT_I)); else `DBG(("Master %0d: acknowledged write", MASTER_NR)); @@ -183,19 +216,19 @@ module master_model end else begin operations_performed <= operations_performed_next_tick; - case (operation_to_perform[39:36]) + case (next_op_type) OP_READ : begin cycle <= 1; strobe <= 1; write_enable <= 0; - addr <= operation_to_perform[35:16]; + addr <= next_op_adr; end OP_WRITE : begin cycle <= 1; strobe <= 1; write_enable <= 1; - addr <= operation_to_perform[35:16]; - output_data <= operation_to_perform[15:0]; + addr <= next_op_adr; + output_data <= next_op_data; end OP_WAIT : begin cycle <= 1; @@ -209,11 +242,10 @@ module master_model end // else: !if(operations_performed_next_tick == OPERATIONS_COUNT) if (acknowledgement_successful) begin - if (expected_results[commands_acknowledged][15:0] !== DAT_I && - expected_results[commands_acknowledged][16]) begin + if (expected_data[commands_acknowledged] !== DAT_I && + was_read[commands_acknowledged]) begin `MSG(("Master %0d: error: read h%x instead of h%x", - MASTER_NR, DAT_I, - expected_results[commands_acknowledged][15:0])); + MASTER_NR, DAT_I, expected_data[commands_acknowledged])); end end end // else: !if(RST_I) -- cgit v1.2.3