aboutsummaryrefslogtreecommitdiff
path: root/models/master.v
diff options
context:
space:
mode:
Diffstat (limited to 'models/master.v')
-rw-r--r--models/master.v223
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