aboutsummaryrefslogtreecommitdiff
path: root/models
diff options
context:
space:
mode:
Diffstat (limited to 'models')
-rw-r--r--models/master.v62
-rw-r--r--models/slave.v68
2 files changed, 97 insertions, 33 deletions
diff --git a/models/master.v b/models/master.v
index 1793fa8..5234efe 100644
--- a/models/master.v
+++ b/models/master.v
@@ -18,7 +18,7 @@ module master_model
#(
parameter MASTER_NR = -1,
parameter WORD_SIZE = 2, /* in bytes */
- parameter GRANULARITY = 2, /* in bytes */ /* we'll use that soon */
+ parameter SEL_LINES = 1,
parameter ADR_BITS = 20,
parameter OPERATIONS_FILE = "master_operations.mem",
parameter OPERATIONS_COUNT = 10
@@ -29,7 +29,7 @@ module master_model
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 */
+ output wire [SEL_LINES - 1 : 0] SEL_O,
input wire RST_I,
output wire STB_O,
output wire CYC_O,
@@ -41,6 +41,7 @@ module master_model
);
parameter WORD_BITS = 8 * WORD_SIZE;
+ parameter GRANULARITY = WORD_BITS / SEL_LINES; /* in bits */
parameter
OP_READ = 0,
@@ -52,33 +53,34 @@ module master_model
parameter BIGGEST_WIDTH = ADR_BITS > WORD_BITS ? ADR_BITS : WORD_BITS;
/*
* 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
+ * Each (4*n)th element denotes type of operation number n.
+ * (4*n+1)th element denotes address to use, (4*n+2)th element denotes
+ * data to use and (4*n+3)th element denotes SEL_O mask to use.
*/
- reg [BIGGEST_WIDTH - 1 : 0] operations [3*OPERATIONS_COUNT - 1 : 0];
+ reg [BIGGEST_WIDTH - 1 : 0] operations [4*OPERATIONS_COUNT - 1 : 0];
/* Arrays used for verifying read reaults */
reg was_read [OPERATIONS_COUNT - 1 : 0];
+ reg [SEL_LINES - 1 : 0] SEL_mask [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, 3*OPERATIONS_COUNT - 1);
+ $readmemh(OPERATIONS_FILE, operations, 0, 4*OPERATIONS_COUNT - 1);
j = 0;
for (i = 0; i < OPERATIONS_COUNT; i++) begin
- if (operations[3*i][1:0] == OP_READ) begin
+ if (operations[4*i][1:0] == OP_READ) begin
was_read[j] <= 1;
- expected_data[j] <= operations[3*i + 2][WORD_BITS - 1 : 0];
+ expected_data[j] <= operations[4*i + 2][WORD_BITS - 1 : 0];
+ SEL_mask[j] <= operations[4*i + 3][SEL_LINES - 1 : 0];
j++;
end
- if (operations[3*i][1:0] == OP_WRITE) begin
+ if (operations[4*i][1:0] == OP_WRITE) begin
was_read[j] <= 0;
- expected_data[j] <= {(8 * WORD_SIZE - 1){1'bx}};
j++;
end
@@ -96,6 +98,7 @@ module master_model
wire [1:0] current_op_type;
wire [ADR_BITS - 1 : 0] current_op_adr;
wire [WORD_BITS - 1 : 0] current_op_data;
+ wire [SEL_LINES - 1 : 0] current_op_mask;
wire operation_successful;
wire [31:0] operations_performed_next_tick;
wire acknowledgement_successful;
@@ -108,11 +111,13 @@ module master_model
assign deselect_successful = !CYC_O;
assign current_op_type
- = operations[3*operations_performed][1:0];
+ = operations[4*operations_performed][1:0];
assign current_op_adr
- = operations[3*operations_performed + 1][ADR_BITS - 1 : 0];
+ = operations[4*operations_performed + 1][ADR_BITS - 1 : 0];
assign current_op_data
- = operations[3*operations_performed + 2][WORD_BITS - 1 : 0];
+ = operations[4*operations_performed + 2][WORD_BITS - 1 : 0];
+ assign current_op_mask
+ = operations[4*operations_performed + 3][SEL_LINES - 1 : 0];
assign operation_successful
= operations_performed < OPERATIONS_COUNT &&
@@ -135,11 +140,13 @@ module master_model
wire [1:0] next_op_type;
wire [ADR_BITS - 1 : 0] next_op_adr;
wire [WORD_BITS - 1 : 0] next_op_data;
+ wire [SEL_LINES - 1 : 0] next_op_mask;
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];
+ assign next_op_type = operations[4*idx_to_use][1:0];
+ assign next_op_adr = operations[4*idx_to_use + 1][ADR_BITS - 1 : 0];
+ assign next_op_data = operations[4*idx_to_use + 2][WORD_BITS - 1 : 0];
+ assign next_op_mask = operations[4*idx_to_use + 3][SEL_LINES - 1 : 0];
/* Drive the outputs */
@@ -155,12 +162,17 @@ module master_model
reg [WORD_BITS - 1 : 0] output_data;
assign DAT_O = output_data;
+ reg [SEL_LINES - 1 : 0] mask;
+ assign SEL_O = mask;
+
reg [ADR_BITS - 1 : 0] addr;
assign ADR_O = addr;
reg done;
assign finished = done;
+ reg [WORD_BITS - 1 : 0] masked_data;
+
initial begin
strobe <= 0;
cycle <= 0;
@@ -221,12 +233,14 @@ module master_model
cycle <= 1;
strobe <= 1;
write_enable <= 0;
+ mask <= next_op_mask;
addr <= next_op_adr;
end
OP_WRITE : begin
cycle <= 1;
strobe <= 1;
write_enable <= 1;
+ mask <= next_op_mask;
addr <= next_op_adr;
output_data <= next_op_data;
end
@@ -238,16 +252,22 @@ module master_model
cycle <= acknowledgements_needed > 0;
strobe <= 0;
end
- endcase // case (operation_to_perform[39:36])
+ endcase // case (next_op_type)
end // else: !if(operations_performed_next_tick == OPERATIONS_COUNT)
if (acknowledgement_successful) begin
- if (expected_data[commands_acknowledged] !== DAT_I &&
+ for (i = 0; i < WORD_BITS; i++) begin
+ masked_data[i] = SEL_mask[commands_acknowledged][i/GRANULARITY] &
+ DAT_I[i];
+ end
+
+ if (expected_data[commands_acknowledged] !== masked_data &&
was_read[commands_acknowledged]) begin
`MSG(("Master %0d: error: read h%x instead of h%x",
- MASTER_NR, DAT_I, expected_data[commands_acknowledged]));
+ MASTER_NR, masked_data,
+ expected_data[commands_acknowledged]));
end
- end
+ end // if (acknowledgement_successful)
end // else: !if(RST_I)
end // always @ (posedge CLK_I)
endmodule // master_model
diff --git a/models/slave.v b/models/slave.v
index f062a04..ed12a73 100644
--- a/models/slave.v
+++ b/models/slave.v
@@ -12,7 +12,7 @@ module memory_slave_model
#(
parameter SLAVE_NR = -1,
parameter WORD_SIZE = 2, /* in bytes */
- parameter GRANULARITY = 2, /* in bytes */ /* we'll use that soon */
+ parameter SEL_LINES = 1,
parameter ADR_BITS = 18,
/* Changing the following 3 allows us to make it function as ROM */
parameter WRITABLE = 1,
@@ -26,21 +26,23 @@ module memory_slave_model
input wire [ADR_BITS - 1 : 0] ADR_I,
input wire [8*WORD_SIZE - 1 : 0] DAT_I,
output wire [8*WORD_SIZE - 1 : 0] DAT_O,
- /* input wire [GRANULARITY - 1 : 0] SEL_I, */ /* we'll use that soon */
+ input wire [SEL_LINES - 1 : 0] SEL_I,
input wire RST_I,
input wire STB_I,
input wire WE_I,
output wire STALL_O
);
+ parameter GRANULARITY = 8 * WORD_SIZE / SEL_LINES; /* in bits */
+
/*
* A simple memory slave should be most useful for testing purposes;
* WARNING! The 'memory' variable might be referenced from outside the module
* by testbench code - be careful when changing or removing it
*/
- reg [8*WORD_SIZE - 1 : 0] memory [2**ADR_BITS - 1 : 0];
+ reg [GRANULARITY - 1 : 0] memory [2**ADR_BITS - 1 : 0];
- /* For random stall times and acknowledge times */
+ /* For random stall times and acknowledge times */
integer seed;
parameter MAX_STALL_TIME = 7;
@@ -53,6 +55,7 @@ module memory_slave_model
reg WE_I_pipeline [15:0];
reg [ADR_BITS - 1 : 0] ADR_I_pipeline [15:0];
reg [8*WORD_SIZE - 1 : 0] DAT_I_pipeline [15:0];
+ reg [SEL_LINES - 1 : 0] SEL_I_pipeline [15:0];
reg [3:0] pipeline_oldest_element;
reg [4:0] pipeline_elements_count;
@@ -65,16 +68,19 @@ module memory_slave_model
reg WE_I_to_process;
reg [ADR_BITS - 1 : 0] ADR_I_to_process;
reg [8*WORD_SIZE - 1 : 0] DAT_I_to_process;
+ reg [SEL_LINES - 1 : 0] SEL_I_to_process;
always @* begin
if (pipeline_elements_count) begin
WE_I_to_process = WE_I_pipeline[pipeline_oldest_element];
ADR_I_to_process = ADR_I_pipeline[pipeline_oldest_element];
DAT_I_to_process = DAT_I_pipeline[pipeline_oldest_element];
+ SEL_I_to_process = SEL_I_pipeline[pipeline_oldest_element];
end else begin
WE_I_to_process = WE_I;
ADR_I_to_process = ADR_I;
DAT_I_to_process = DAT_I;
+ SEL_I_to_process = SEL_I;
end
end // always @ *
@@ -94,11 +100,27 @@ module memory_slave_model
command_available_for_acknowledging;
+ integer i; /* loop counter */
+ reg [8*WORD_SIZE - 1 : 0] masked_out_data;
+
+ always @ (SEL_I_to_process or WE_I_to_process or ADR_I_to_process) begin
+ for (i = SEL_LINES - 1; i >= 0; i--) begin
+ if (SEL_LINES > 1) begin
+ masked_out_data[8*WORD_SIZE - 1 : GRANULARITY]
+ = masked_out_data[8*WORD_SIZE - GRANULARITY - 1 : 0];
+ end
+
+ masked_out_data[GRANULARITY - 1 : 0]
+ = SEL_I_to_process[i] ?
+ memory[ADR_I_to_process + i] : {GRANULARITY{1'bx}};
+ end
+ end // always @ (SEL_I_to_process or WE_I_to_process or ADR_I_to_process)
+
/* Finally, drive the outputs */
/* only drive data outputs for read commands */
assign DAT_O = (command_acknowledged && !WE_I_to_process) ?
- memory[ADR_I_to_process] : {(8 * WORD_SIZE - 1){1'bx}};
+ masked_out_data : {(8 * WORD_SIZE - 1){1'bx}};
assign STALL_O = !can_accept;
@@ -115,6 +137,9 @@ module memory_slave_model
$readmemb(INITIAL_CONTENTS_FILE, memory, 0, WORDS_TO_INITIALIZE - 1);
end
+ integer k; /* loop counter */
+ reg [8*WORD_SIZE - 1 : 0] masked_in_data;
+
always @ (posedge CLK_I) begin
if (RST_I) begin
pipeline_oldest_element <= 0;
@@ -125,6 +150,7 @@ module memory_slave_model
WE_I_pipeline[pipeline_index_to_insert] <= WE_I;
ADR_I_pipeline[pipeline_index_to_insert] <= ADR_I;
DAT_I_pipeline[pipeline_index_to_insert] <= DAT_I;
+ SEL_I_pipeline[pipeline_index_to_insert] <= SEL_I;
end else begin
if (stall_time_left)
stall_time_left <= stall_time_left - 1;
@@ -135,18 +161,36 @@ module memory_slave_model
pipeline_oldest_element <= pipeline_oldest_element + 1;
if (WE_I_to_process) begin /* Write command */
+ masked_in_data = DAT_I_to_process;
+
+ for (k = 0; k < SEL_LINES; k++) begin
+ if (SEL_I_to_process[k]) begin
+ if (WRITABLE) begin
+ memory[ADR_I_to_process + k]
+ <= masked_in_data[GRANULARITY - 1 : 0];
+ end
+ end else begin
+ masked_in_data[GRANULARITY - 1 : 0] = {GRANULARITY{1'bx}};
+ end
+
+ if (SEL_LINES > 1) begin
+ masked_in_data
+ = {masked_in_data[GRANULARITY - 1 : 0],
+ masked_in_data[8*WORD_SIZE - 1 : GRANULARITY]};
+ end
+ end // for (k = 0; k < SEL_LINES; k++)
+
if (WRITABLE) begin
- memory[ADR_I_to_process] <= DAT_I_to_process;
- `DBG(("Slave %0d: write of h%x at h%x", SLAVE_NR,
- DAT_I_to_process, ADR_I_to_process));
+ `DBG(("Slave %0d: write of h%x (%b) at h%x", SLAVE_NR,
+ masked_in_data, SEL_I_to_process, ADR_I_to_process));
end else begin
- `DBG(({"Slave %0d: error: write of h%x at h%x ",
+ `DBG(({"Slave %0d: error: write of h%x (%b) at h%x ",
"(read-only) memory"}, SLAVE_NR,
- DAT_I_to_process, ADR_I_to_process));
+ DAT_I_to_process, SEL_I_to_process, ADR_I_to_process));
end
end else begin /* Read command */
- `DBG(("Slave %0d: read of h%x at h%x", SLAVE_NR,
- DAT_O, ADR_I_to_process));
+ `DBG(("Slave %0d: read of h%x (%b) at h%x", SLAVE_NR,
+ DAT_O, SEL_I_to_process, ADR_I_to_process));
end
end else if (command_available_for_acknowledging) begin
acknowledge_time_left <= acknowledge_time_left - 1;