diff options
Diffstat (limited to 'models/master.v')
-rw-r--r-- | models/master.v | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/models/master.v b/models/master.v new file mode 100644 index 0000000..b728bda --- /dev/null +++ b/models/master.v @@ -0,0 +1,223 @@ +/* A wishbone slave testing module (a "mock") */ +`default_nettype none + +`include "messages.vh" + +`ifndef SIMULATION + `error_SIMULATION_not_defined +; /* Cause syntax error */ +`else + +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 + +`endif // !`ifndef SIMULATION |