115 lines
3.0 KiB
Verilog
115 lines
3.0 KiB
Verilog
`include "../VX_define.v"
|
|
|
|
module VX_priority_encoder_sm
|
|
#(
|
|
parameter NB = 4,
|
|
parameter BITS_PER_BANK = 3,
|
|
parameter NUM_REQ = 3
|
|
)
|
|
(
|
|
//INPUTS
|
|
input wire clk,
|
|
input wire reset,
|
|
input wire[`NT_M1:0] in_valid,
|
|
input wire[`NT_M1:0][31:0] in_address,
|
|
input wire[`NT_M1:0][31:0] in_data,
|
|
// OUTPUTS
|
|
// To SM Module
|
|
output reg[NB:0] out_valid,
|
|
output reg[NB:0][31:0] out_address,
|
|
output reg[NB:0][31:0] out_data,
|
|
|
|
// To Processor
|
|
output wire[NB:0][`CLOG2(NUM_REQ) - 1:0] req_num,
|
|
output reg stall,
|
|
output wire send_data // Finished all of the requests
|
|
);
|
|
|
|
reg[`NT_M1:0] left_requests;
|
|
reg[`NT_M1:0] serviced;
|
|
|
|
|
|
wire[`NT_M1:0] use_valid;
|
|
|
|
|
|
wire requests_left = (|left_requests);
|
|
|
|
assign use_valid = (requests_left) ? left_requests : in_valid;
|
|
|
|
|
|
wire[NB:0][`NT_M1:0] bank_valids;
|
|
VX_bank_valids #(.NB(NB), .BITS_PER_BANK(BITS_PER_BANK)) vx_bank_valid(
|
|
.in_valids(use_valid),
|
|
.in_addr(in_address),
|
|
.bank_valids(bank_valids)
|
|
);
|
|
|
|
wire[NB:0] more_than_one_valid;
|
|
|
|
genvar curr_bank;
|
|
generate
|
|
for (curr_bank = 0; curr_bank <= NB; curr_bank = curr_bank + 1)
|
|
begin
|
|
wire[`CLOG2(`NT):0] num_valids;
|
|
|
|
VX_countones #(.N(`NT)) valids_counter (
|
|
.valids(bank_valids[curr_bank]),
|
|
.count (num_valids)
|
|
);
|
|
assign more_than_one_valid[curr_bank] = num_valids > 1;
|
|
// assign more_than_one_valid[curr_bank] = $countones(bank_valids[curr_bank]) > 1;
|
|
end
|
|
endgenerate
|
|
|
|
|
|
assign stall = (|more_than_one_valid);
|
|
assign send_data = (!stall) && (|in_valid); // change
|
|
|
|
wire[NB:0][(`CLOG2(NUM_REQ)) - 1:0] internal_req_num;
|
|
wire[NB:0] internal_out_valid;
|
|
|
|
|
|
// There's one or less valid per bank
|
|
genvar curr_bank_o;
|
|
for (curr_bank_o = 0; curr_bank_o <= NB; curr_bank_o = curr_bank_o + 1)
|
|
begin
|
|
|
|
VX_generic_priority_encoder #(.N(NUM_REQ)) vx_priority_encoder(
|
|
.valids(bank_valids[curr_bank_o]),
|
|
.index(internal_req_num[curr_bank_o]),
|
|
.found(internal_out_valid[curr_bank_o])
|
|
);
|
|
assign out_address[curr_bank_o] = internal_out_valid[curr_bank_o] ? in_address[internal_req_num[curr_bank_o]] : 0;
|
|
assign out_data[curr_bank_o] = internal_out_valid[curr_bank_o] ? in_data[internal_req_num[curr_bank_o]] : 0;
|
|
end
|
|
|
|
integer curr_b;
|
|
always @(*) begin
|
|
serviced = 0;
|
|
for (curr_b = 0; curr_b <= NB; curr_b=curr_b+1) begin
|
|
serviced[internal_req_num[curr_b]] = 1;
|
|
end
|
|
end
|
|
|
|
|
|
assign req_num = internal_req_num;
|
|
assign out_valid = internal_out_valid;
|
|
|
|
|
|
wire[`NT_M1:0] serviced_qual = in_valid & (serviced);
|
|
|
|
wire[`NT_M1:0] new_left_requests = (left_requests == 0) ? (in_valid & ~serviced_qual) : (left_requests & ~ serviced_qual);
|
|
|
|
// wire[`NT_M1:0] new_left_requests = left_requests & ~(serviced_qual);
|
|
|
|
always @(posedge clk, posedge reset) begin
|
|
if (reset) begin
|
|
left_requests <= 0;
|
|
// serviced = 0;
|
|
end else begin
|
|
if (!stall) left_requests <= 0;
|
|
else left_requests <= new_left_requests;
|
|
end
|
|
end
|
|
|
|
endmodule |