mirror of
https://github.com/openhwgroup/cva5.git
synced 2025-04-22 21:17:46 -04:00
Instruction and Data Cache reorganization and cleanup
Signed-off-by: Eric Matthews <ematthew@sfu.ca>
This commit is contained in:
parent
6aeac17b9d
commit
562a9c2ff6
4 changed files with 135 additions and 138 deletions
|
@ -100,12 +100,11 @@ module dcache
|
|||
|
||||
logic hit_allowed;
|
||||
logic read_hit_allowed;
|
||||
logic read_hit_data_valid;
|
||||
logic read_hit;
|
||||
|
||||
logic address_range_valid;
|
||||
|
||||
logic idle;
|
||||
logic busy;
|
||||
logic read_miss_complete;
|
||||
|
||||
logic store_complete;
|
||||
|
@ -136,7 +135,6 @@ module dcache
|
|||
//Signal is valid for a single cycle, RAM enables are used to hold outputs in case of pipeline stalls
|
||||
always_ff @ (posedge clk) begin
|
||||
read_hit_allowed <= ls.new_request & ls.re & dcache_on & ~(amo.is_lr | amo.is_amo) & ~uncacheable;
|
||||
read_hit_data_valid <= read_hit_allowed;
|
||||
second_cycle <= ls.new_request;
|
||||
tag_update <= second_cycle & dcache_on & stage2.load & ~tag_hit & ~stage2.uncacheable;//Cache enabled, read miss
|
||||
end
|
||||
|
@ -144,14 +142,11 @@ module dcache
|
|||
assign read_hit = tag_hit & read_hit_allowed;
|
||||
|
||||
//LR reservation, cleared on exceptions
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
reservation <= 0;
|
||||
else if (second_cycle)
|
||||
reservation <= stage2.amo.is_lr;
|
||||
else if (sc_complete | clear_reservation)
|
||||
reservation <= 0;
|
||||
else
|
||||
reservation <= (reservation & ~(sc_complete | clear_reservation)) | (second_cycle & stage2.amo.is_lr);
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -165,10 +160,10 @@ module dcache
|
|||
assign l1_request.amo = stage2.amo.op;
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst | line_complete)
|
||||
if (ls.new_request)
|
||||
word_count <= 0;
|
||||
else if (l1_response.data_valid)
|
||||
word_count <= word_count + 1;
|
||||
else
|
||||
word_count <= word_count + SCONFIG.SUB_LINE_ADDR_W'(l1_response.data_valid);
|
||||
end
|
||||
assign is_target_word = (stage2.addr[SCONFIG.SUB_LINE_ADDR_W-1:0] == word_count) | stage2.uncacheable;
|
||||
|
||||
|
@ -176,32 +171,30 @@ module dcache
|
|||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
arb_request_r <= 0;
|
||||
else if (second_cycle & ~l1_request.ack)
|
||||
arb_request_r <= new_arb_request;
|
||||
else if (l1_request.ack)
|
||||
arb_request_r <= 0;
|
||||
else
|
||||
arb_request_r <= (arb_request_r | new_arb_request) & ~l1_request.ack;
|
||||
end
|
||||
assign l1_request.request = new_arb_request | arb_request_r;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Replacement policy (free runing one-hot cycler, i.e. pseudo random)
|
||||
cycler #(CONFIG.DCACHE.WAYS) replacement_policy (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.en (1'b1),
|
||||
.one_hot (replacement_way)
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.en (1'b1),
|
||||
.one_hot (replacement_way)
|
||||
);
|
||||
|
||||
//One-hot tag hit / update logic to binary int
|
||||
one_hot_to_integer #(CONFIG.DCACHE.WAYS)
|
||||
hit_way_conv (
|
||||
.one_hot(tag_hit_way),
|
||||
.int_out(tag_hit_way_int)
|
||||
.one_hot (tag_hit_way),
|
||||
.int_out (tag_hit_way_int)
|
||||
);
|
||||
one_hot_to_integer #(CONFIG.DCACHE.WAYS)
|
||||
update_way_conv (
|
||||
.one_hot (replacement_way),
|
||||
.int_out (replacement_way_int)
|
||||
.one_hot (replacement_way),
|
||||
.int_out (replacement_way_int)
|
||||
);
|
||||
|
||||
|
||||
|
@ -252,9 +245,9 @@ module dcache
|
|||
endgenerate
|
||||
|
||||
always_comb begin
|
||||
if (stage2.amo.is_amo & is_target_word)
|
||||
if (CONFIG.INCLUDE_AMO & stage2.amo.is_amo & is_target_word)
|
||||
new_line_data = amo_result;
|
||||
else if (stage2.amo.is_sc)
|
||||
else if (CONFIG.INCLUDE_AMO & stage2.amo.is_sc)
|
||||
new_line_data = stage2.data;
|
||||
else
|
||||
new_line_data = l1_response.data;
|
||||
|
@ -278,28 +271,27 @@ module dcache
|
|||
assign data_bank_addr_b = {tag_update_way_int, stage2.addr[SCONFIG.LINE_ADDR_W+SCONFIG.SUB_LINE_ADDR_W-1:SCONFIG.SUB_LINE_ADDR_W], update_word_index};
|
||||
end endgenerate
|
||||
|
||||
ddata_bank #(.LINES(DCACHE_SIZE_IN_WORDS)) data_bank (
|
||||
.clk(clk),
|
||||
.addr_a(data_bank_addr_a),
|
||||
.addr_b(data_bank_addr_b),
|
||||
.en_a(second_cycle),
|
||||
.en_b((l1_response.data_valid & ~stage2.uncacheable) | (sc_complete & sc_success)),
|
||||
.be_a(write_hit_be),
|
||||
.data_in_a(stage2.data),
|
||||
.data_in_b(new_line_data),
|
||||
.data_out_a(dbank_data_out)
|
||||
);
|
||||
ddata_bank #(.LINES(DCACHE_SIZE_IN_WORDS))
|
||||
data_bank (
|
||||
.clk(clk),
|
||||
.addr_a(data_bank_addr_a),
|
||||
.addr_b(data_bank_addr_b),
|
||||
.en_a(second_cycle),
|
||||
.en_b((l1_response.data_valid & ~stage2.uncacheable) | (sc_complete & sc_success)),
|
||||
.be_a(write_hit_be),
|
||||
.data_in_a(stage2.data),
|
||||
.data_in_b(new_line_data),
|
||||
.data_out_a(dbank_data_out)
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Output
|
||||
logic l1_data_valid_r;
|
||||
always_ff @ (posedge clk) begin
|
||||
if (l1_response.data_valid & is_target_word)
|
||||
miss_data <= l1_response.data;
|
||||
else if (sc_complete)
|
||||
miss_data <= {31'b0, sc_success};
|
||||
l1_data_valid_r <= l1_response.data_valid;
|
||||
miss_data <= sc_complete ? {31'b0, sc_success} : l1_response.data;
|
||||
end
|
||||
|
||||
assign ls.data_out = read_hit_data_valid ? dbank_data_out : miss_data;
|
||||
assign ls.data_out = l1_data_valid_r ? miss_data : dbank_data_out;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Pipeline Advancement
|
||||
|
@ -321,15 +313,13 @@ module dcache
|
|||
ls.data_valid <= (l1_response.data_valid & is_target_word) | read_hit | sc_complete;
|
||||
end
|
||||
|
||||
assign ls.ready = read_hit | store_complete | read_miss_complete | idle;
|
||||
assign ls.ready = read_hit | store_complete | read_miss_complete | ~busy;
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
idle <= 1;
|
||||
else if (ls.new_request)
|
||||
idle <= 0;
|
||||
else if (ls.ready)
|
||||
idle <= 1;
|
||||
busy <= 0;
|
||||
else
|
||||
busy <= (busy & ~ls.ready) | ls.new_request;
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
|
144
core/icache.sv
144
core/icache.sv
|
@ -42,6 +42,7 @@ module icache
|
|||
);
|
||||
|
||||
localparam derived_cache_config_t SCONFIG = get_derived_cache_params(CONFIG, CONFIG.ICACHE, CONFIG.ICACHE_ADDR);
|
||||
localparam bit [SCONFIG.SUB_LINE_ADDR_W-1:0] END_OF_LINE_COUNT = SCONFIG.SUB_LINE_ADDR_W'(CONFIG.ICACHE.LINE_W-1);
|
||||
|
||||
logic tag_hit;
|
||||
logic [CONFIG.ICACHE.WAYS-1:0] tag_hit_way;
|
||||
|
@ -51,20 +52,24 @@ module icache
|
|||
logic [CONFIG.ICACHE.WAYS-1:0] tag_update_way;
|
||||
|
||||
logic [SCONFIG.SUB_LINE_ADDR_W-1:0] word_count;
|
||||
logic [SCONFIG.SUB_LINE_ADDR_W-1:0] target_word;
|
||||
logic is_target_word;
|
||||
|
||||
logic line_complete;
|
||||
|
||||
logic [31:0] data_out [CONFIG.ICACHE.WAYS-1:0];
|
||||
logic [31:0] miss_data;
|
||||
|
||||
logic miss_in_progress;
|
||||
logic linefill_in_progress;
|
||||
logic request_in_progress;
|
||||
|
||||
logic miss_data_valid;
|
||||
logic second_cycle;
|
||||
logic [31:0] second_cycle_addr;
|
||||
|
||||
logic idle;
|
||||
logic memory_complete;
|
||||
fifo_interface #(.DATA_WIDTH(32)) input_fifo();
|
||||
|
||||
logic new_request;
|
||||
logic [31:0] new_request_addr;
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
|
||||
|
@ -72,18 +77,44 @@ module icache
|
|||
//On the second cycle of a request hit/miss determination is performed
|
||||
//On a miss, the memory request starts on the third cycle
|
||||
|
||||
assign new_request = (fetch_sub.new_request | input_fifo.valid) & ((~request_in_progress | tag_hit) & ~linefill_in_progress);
|
||||
|
||||
assign input_fifo.push = fetch_sub.new_request & (~new_request | input_fifo.valid);
|
||||
assign input_fifo.potential_push = input_fifo.push;
|
||||
assign input_fifo.pop = new_request & input_fifo.valid;
|
||||
assign input_fifo.data_in = fetch_sub.addr;
|
||||
|
||||
assign new_request_addr = input_fifo.valid ? input_fifo.data_out : fetch_sub.addr;
|
||||
|
||||
cva5_fifo #(.DATA_WIDTH(32), .FIFO_DEPTH(2))
|
||||
cache_input_fifo (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.fifo (input_fifo)
|
||||
);
|
||||
////////////////////////////////////////////////////
|
||||
//Ready determination
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
request_in_progress <= 0;
|
||||
else
|
||||
request_in_progress <= (request_in_progress & ~fetch_sub.data_valid) | new_request;
|
||||
end
|
||||
|
||||
assign fetch_sub.ready = ~input_fifo.full;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//General Control Logic
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
second_cycle <= 0;
|
||||
else
|
||||
second_cycle <= fetch_sub.new_request;
|
||||
second_cycle <= new_request;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (fetch_sub.new_request)
|
||||
second_cycle_addr <= fetch_sub.addr;
|
||||
if (new_request)
|
||||
second_cycle_addr <= new_request_addr;
|
||||
end
|
||||
|
||||
//As request can be aborted on any cycle, only update tags if memory request is in progress
|
||||
|
@ -96,13 +127,13 @@ module icache
|
|||
|
||||
//Replacement policy is psuedo random
|
||||
cycler #(CONFIG.ICACHE.WAYS) replacement_policy (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.en (1'b1),
|
||||
.one_hot (replacement_way)
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.en (1'b1),
|
||||
.one_hot (replacement_way)
|
||||
);
|
||||
always_ff @ (posedge clk) begin
|
||||
if (second_cycle)
|
||||
if (second_cycle & ~linefill_in_progress)
|
||||
tag_update_way <= replacement_way;
|
||||
end
|
||||
|
||||
|
@ -132,24 +163,24 @@ module icache
|
|||
//Miss state tracking
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
miss_in_progress <= 0;
|
||||
linefill_in_progress <= 0;
|
||||
else
|
||||
miss_in_progress <= l1_request.ack | (miss_in_progress & ~line_complete);
|
||||
linefill_in_progress <= (linefill_in_progress & ~line_complete) | l1_request.ack;
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Tag banks
|
||||
itag_banks #(.CONFIG(CONFIG), .SCONFIG(SCONFIG))
|
||||
icache_tag_banks (
|
||||
.clk(clk),
|
||||
.rst(rst), //clears the read_hit_allowed flag
|
||||
.stage1_addr(fetch_sub.addr),
|
||||
.stage2_addr(second_cycle_addr),
|
||||
.update_way(tag_update_way),
|
||||
.update(tag_update),
|
||||
.stage1_adv(fetch_sub.new_request & icache_on),
|
||||
.tag_hit(tag_hit),
|
||||
.tag_hit_way(tag_hit_way)
|
||||
.clk(clk),
|
||||
.rst(rst), //clears the read_hit_allowed flag
|
||||
.stage1_addr(new_request_addr),
|
||||
.stage2_addr(second_cycle_addr),
|
||||
.update_way(tag_update_way),
|
||||
.update(tag_update),
|
||||
.stage1_adv(new_request & icache_on),
|
||||
.tag_hit(tag_hit),
|
||||
.tag_hit_way(tag_hit_way)
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -158,9 +189,9 @@ module icache
|
|||
generate for (i=0; i < CONFIG.ICACHE.WAYS; i++) begin : idata_bank_gen
|
||||
byte_en_BRAM #(CONFIG.ICACHE.LINES*CONFIG.ICACHE.LINE_W) idata_bank (
|
||||
.clk(clk),
|
||||
.addr_a(fetch_sub.addr[2 +: SCONFIG.LINE_ADDR_W+SCONFIG.SUB_LINE_ADDR_W]),
|
||||
.addr_a(new_request_addr[2 +: SCONFIG.LINE_ADDR_W+SCONFIG.SUB_LINE_ADDR_W]),
|
||||
.addr_b({second_cycle_addr[(2+SCONFIG.SUB_LINE_ADDR_W) +: SCONFIG.LINE_ADDR_W], word_count}),
|
||||
.en_a(fetch_sub.new_request),
|
||||
.en_a(new_request),
|
||||
.en_b(tag_update_way[i] & l1_response.data_valid),
|
||||
.be_a('0),
|
||||
.be_b('1),
|
||||
|
@ -173,61 +204,42 @@ module icache
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Miss data path
|
||||
assign target_word = second_cycle_addr[2 +: SCONFIG.SUB_LINE_ADDR_W];
|
||||
assign is_target_word = (target_word == word_count);
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
word_count <= 0;
|
||||
else if (l1_response.data_valid)
|
||||
word_count <= word_count + 1;
|
||||
end
|
||||
|
||||
assign is_target_word = (second_cycle_addr[2 +: SCONFIG.SUB_LINE_ADDR_W] == word_count);
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (l1_response.data_valid & is_target_word)
|
||||
miss_data <= l1_response.data;
|
||||
else
|
||||
miss_data <= 0;
|
||||
word_count <= word_count + SCONFIG.SUB_LINE_ADDR_W'(l1_response.data_valid);
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
miss_data_valid <= 0;
|
||||
else
|
||||
miss_data_valid <= miss_in_progress & l1_response.data_valid & is_target_word;
|
||||
end
|
||||
|
||||
assign line_complete = (l1_response.data_valid && (word_count == SCONFIG.SUB_LINE_ADDR_W'(CONFIG.ICACHE.LINE_W-1)));
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
memory_complete <= 0;
|
||||
else
|
||||
memory_complete <= line_complete;
|
||||
end
|
||||
assign miss_data_valid = request_in_progress & l1_response.data_valid & is_target_word;
|
||||
assign line_complete = l1_response.data_valid & (word_count == END_OF_LINE_COUNT);
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Output muxing
|
||||
localparam OMUX_W = CONFIG.ICACHE.WAYS+1;
|
||||
logic [OMUX_W-1:0] priority_vector;
|
||||
logic [$clog2(OMUX_W)-1:0] output_sel;
|
||||
logic [31:0] output_array [OMUX_W];
|
||||
always_comb begin
|
||||
fetch_sub.data_out = miss_data;//zero if not a miss
|
||||
priority_vector[0] = miss_data_valid;
|
||||
output_array[0] = l1_response.data;
|
||||
for (int i = 0; i < CONFIG.ICACHE.WAYS; i++) begin
|
||||
fetch_sub.data_out = fetch_sub.data_out | (data_out[i] & {32{tag_hit_way[i]}});
|
||||
priority_vector[i+1] = tag_hit_way[i];
|
||||
output_array[i+1] = data_out[i];
|
||||
end
|
||||
end
|
||||
|
||||
priority_encoder #(.WIDTH(OMUX_W))
|
||||
arb_encoder
|
||||
(
|
||||
.priority_vector (priority_vector),
|
||||
.encoded_result (output_sel)
|
||||
);
|
||||
assign fetch_sub.data_out = output_array[output_sel];
|
||||
assign fetch_sub.data_valid = miss_data_valid | tag_hit;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Ready determination
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
idle <= 1;
|
||||
else if (fetch_sub.new_request)
|
||||
idle <= 0;
|
||||
else if (memory_complete | tag_hit) //read miss OR write through complete
|
||||
idle <= 1;
|
||||
end
|
||||
|
||||
assign fetch_sub.ready = tag_hit | memory_complete | idle;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//End of Implementation
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -239,7 +251,7 @@ module icache
|
|||
else $error("Spurious icache ack received from arbiter!");
|
||||
|
||||
icache_l1_arb_data_valid_assertion:
|
||||
assert property (@(posedge clk) disable iff (rst) l1_response.data_valid |-> miss_in_progress)
|
||||
assert property (@(posedge clk) disable iff (rst) l1_response.data_valid |-> linefill_in_progress)
|
||||
else $error("Spurious icache data received from arbiter!");
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -198,12 +198,12 @@ interface load_store_queue_interface;
|
|||
lsq_entry_t data_in;
|
||||
logic potential_push;
|
||||
logic push;
|
||||
logic full;
|
||||
logic pop;
|
||||
|
||||
//LSQ outputs
|
||||
data_access_shared_inputs_t data_out;
|
||||
logic valid;
|
||||
logic pop;
|
||||
logic full;
|
||||
|
||||
//LSQ status
|
||||
logic sq_empty;
|
||||
|
@ -228,12 +228,11 @@ interface store_queue_interface;
|
|||
//Issue inputs
|
||||
lsq_entry_t data_in;
|
||||
logic push;
|
||||
logic full;
|
||||
logic pop;
|
||||
|
||||
sq_entry_t data_out;
|
||||
|
||||
logic valid;
|
||||
logic pop;
|
||||
logic full;
|
||||
|
||||
//SQ status
|
||||
logic empty;
|
||||
|
|
|
@ -50,7 +50,7 @@ module l1_arbiter
|
|||
logic [L1_CONNECTIONS-1:0] acks;
|
||||
logic [((L1_CONNECTIONS == 1) ? 0 : ($clog2(L1_CONNECTIONS)-1)) : 0] arb_sel;
|
||||
|
||||
logic push_ready;
|
||||
logic fifos_full;
|
||||
logic request_exists;
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
|
@ -69,14 +69,14 @@ module l1_arbiter
|
|||
assign sc_success = CONFIG.INCLUDE_AMO & l2.con_result;
|
||||
|
||||
//Arbiter can pop address FIFO at a different rate than the data FIFO, so check that both have space.
|
||||
assign push_ready = ~(l2.request_full | l2.data_full);
|
||||
assign fifos_full = l2.request_full | l2.data_full;
|
||||
assign request_exists = |requests;
|
||||
|
||||
assign l2.request_push = push_ready & request_exists;
|
||||
assign l2.request_push = request_exists & ~fifos_full;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Dcache Specific
|
||||
assign l2.wr_data_push = CONFIG.INCLUDE_DCACHE & (push_ready & l1_request[L1_DCACHE_ID].request & ~l1_request[L1_DCACHE_ID].rnw); //Assumes data cache has highest priority
|
||||
assign l2.wr_data_push = CONFIG.INCLUDE_DCACHE & (l1_request[L1_DCACHE_ID].request & ~l1_request[L1_DCACHE_ID].rnw & ~fifos_full); //Assumes data cache has highest priority
|
||||
assign l2.wr_data = l1_request[L1_DCACHE_ID].data;
|
||||
|
||||
assign l2.inv_ack = CONFIG.DCACHE.USE_EXTERNAL_INVALIDATIONS ? l1_response[L1_DCACHE_ID].inv_ack : l2.inv_valid;
|
||||
|
@ -86,30 +86,26 @@ module l1_arbiter
|
|||
////////////////////////////////////////////////////
|
||||
//Interface mapping
|
||||
generate for (genvar i = 0; i < L1_CONNECTIONS; i++) begin : gen_l2_requests
|
||||
always_comb begin
|
||||
l2_requests[i].addr = l1_request[i].addr[31:2];
|
||||
l2_requests[i].rnw = l1_request[i].rnw;
|
||||
l2_requests[i].be = l1_request[i].be;
|
||||
l2_requests[i].is_amo = l1_request[i].is_amo;
|
||||
l2_requests[i].amo_type_or_burst_size = l1_request[i].size;
|
||||
l2_requests[i].sub_id = L2_SUB_ID_W'(i);
|
||||
end
|
||||
assign l2_requests[i] = '{
|
||||
addr : l1_request[i].addr[31:2],
|
||||
rnw : l1_request[i].rnw,
|
||||
be : l1_request[i].be,
|
||||
is_amo : l1_request[i].is_amo,
|
||||
amo_type_or_burst_size : l1_request[i].size,
|
||||
sub_id : L2_SUB_ID_W'(i)
|
||||
};
|
||||
end endgenerate
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Arbitration
|
||||
priority_encoder
|
||||
#(.WIDTH(L1_CONNECTIONS))
|
||||
priority_encoder #(.WIDTH(L1_CONNECTIONS))
|
||||
arb_encoder
|
||||
(
|
||||
.priority_vector (requests),
|
||||
.encoded_result (arb_sel)
|
||||
);
|
||||
|
||||
always_comb begin
|
||||
acks = '0;
|
||||
acks[arb_sel] = l2.request_push;
|
||||
end
|
||||
assign acks = L1_CONNECTIONS'(l2.request_push) << arb_sel;
|
||||
|
||||
assign l2.addr = l2_requests[arb_sel].addr;
|
||||
assign l2.rnw = l2_requests[arb_sel].rnw;
|
||||
|
@ -120,7 +116,7 @@ module l1_arbiter
|
|||
|
||||
generate for (genvar i = 0; i < L1_CONNECTIONS; i++) begin : gen_l1_responses
|
||||
assign l1_response[i].data = l2.rd_data;
|
||||
assign l1_response[i].data_valid = l2.rd_data_valid && (l2.rd_sub_id == i);
|
||||
assign l1_response[i].data_valid = l2.rd_data_valid & (l2.rd_sub_id == i);
|
||||
end endgenerate
|
||||
|
||||
endmodule
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue