/* A wishbone slave testing module (a "mock") */ `default_nettype none `include "messages.vh" `ifndef SIMULATION `error_SIMULATION_not_defined ; /* Cause syntax error */ `endif module master_model #( parameter MASTER_NR = -1, 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, /* Non-wishbone */ output wire finished ); 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]; /* * 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 */ reg [16:0] expected_results [OPERATIONS_COUNT - 1 : 0]; integer i, j; initial begin $readmemh(OPERATIONS_FILE, operations, 0, 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}; j++; end end end 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; 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 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)); 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 = CYC_O && ACK_I && commands_sent_next_tick > commands_acknowledged; assign commands_acknowledged_next_tick = commands_acknowledged + acknowledgement_successful; assign acknowledgements_needed = commands_sent_next_tick - commands_acknowledged_next_tick; reg strobe; assign STB_O = strobe; reg cycle; assign CYC_O = cycle; reg write_enable; assign WE_O = write_enable; reg [15:0] output_data; assign DAT_O = output_data; reg [19:0] addr; assign ADR_O = addr; reg done; assign finished = done; initial begin strobe <= 0; cycle <= 0; operations_performed <= 0; commands_sent <= 0; commands_acknowledged <= 0; done <= 0; end always @ (posedge CLK_I) begin if (RST_I) begin strobe <= 0; cycle <= 0; operations_performed <= 0; commands_sent <= 0; commands_acknowledged <= 0; done <= 0; end else begin /* debug messages */ if (command_successful) begin case (current_operation_type) OP_READ : begin `DBG(("Master %0d: sent read command at h%x", MASTER_NR, operations[operations_performed][35:16])); 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])); end default : `MSG(("Master %0d: error: bug in test bench", MASTER_NR)); endcase // case (current_operation_type) end // if (command_successful) if (acknowledgement_successful) begin if (expected_results[commands_acknowledged][16]) `DBG(("Master %0d: acknowledged read of h%x", MASTER_NR, DAT_I)); else `DBG(("Master %0d: acknowledged write", MASTER_NR)); end operations_performed <= operations_performed_next_tick; commands_sent <= commands_sent_next_tick; commands_acknowledged <= commands_acknowledged_next_tick; if (operations_performed_next_tick == OPERATIONS_COUNT) begin strobe <= 0; if (acknowledgements_needed == 0) begin cycle <= 0; done <= 1; end end else begin operations_performed <= operations_performed_next_tick; case (operation_to_perform[39:36]) OP_READ : begin cycle <= 1; strobe <= 1; write_enable <= 0; addr <= operation_to_perform[35:16]; end OP_WRITE : begin cycle <= 1; strobe <= 1; write_enable <= 1; addr <= operation_to_perform[35:16]; output_data <= operation_to_perform[15:0]; end OP_WAIT : begin cycle <= 1; strobe <= 0; end OP_DESELECT : begin cycle <= acknowledgements_needed > 0; strobe <= 0; end endcase // case (operation_to_perform[39:36]) 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 `MSG(("Master %0d: error: read h%x instead of h%x", MASTER_NR, DAT_I, expected_results[commands_acknowledged][15:0])); end end end // else: !if(RST_I) end // always @ (posedge CLK_I) endmodule // master_model