blob: 567cdf296f4627f4d5f46e96f6825c970e83cb75 [file] [log] [blame]
/////////////////////////
// Author: Peichen Guo //
// RIOS Lab work //
// HeHe Core //
/////////////////////////
// lsu router
`ifndef LR_V
`define LR_V
`include "params.vh"
// dcache piority weights less than bus
module lr(
input clk,
input rstn,
input flush,
// <> lsq
output lsq_req_ready_o,
input lsq_req_valid_i,
input lsq_req_opcode_i, // 0 for load, 1 for store
input lsq_req_sign_i,
input [1:0] lsq_req_size_i,
input [VIRTUAL_ADDR_LEN - 1 : 0] lsq_req_addr_i,
input [XLEN - 1 : 0] lsq_req_data_i,
input [LSU_LSQ_SIZE_WIDTH - 1: 0] lsq_req_lsq_index_i,
output lsq_resp_valid_o,
output [LSU_LSQ_SIZE_WIDTH - 1: 0] lsq_resp_lsq_index_o,
output [XLEN - 1 : 0]lsq_resp_data_o,
input lsq_resp_ready_i,
// <> dcache
input dcache_req_ready_i,
output dcache_req_valid_o,
output dcache_req_opcode_o, // 0 for load, 1 for store
output dcache_req_sign_o,
output [1:0] dcache_req_size_o,
output [VIRTUAL_ADDR_LEN - 1 : 0] dcache_req_addr_o,
output [XLEN - 1 : 0] dcache_req_data_o,
output [LSU_LSQ_SIZE_WIDTH - 1: 0] dcache_req_lsq_index_o,
input dcache_resp_valid_i,
input [LSU_LSQ_SIZE_WIDTH - 1: 0] dcache_resp_lsq_index_i,
input [XLEN - 1 : 0] dcache_resp_data_i,
output dcache_resp_ready_o,
// <> bus
output wb_cyc_o,
output wb_stb_o,
output wb_we_o,
output [VIRTUAL_ADDR_LEN - 1 : 0] wb_adr_o,
output [WB_DATA_LEN-1:0] wb_dat_o,
output [WB_DATA_LEN/8-1:0] wb_sel_o,
input wb_ack_i,
input [WB_DATA_LEN -1:0] wb_dat_i
);
wire map_to_bus = (BUS_MAP_ADDR_LOWER <= lsq_req_addr_i && lsq_req_addr_i < BUS_MAP_ADDR_UPPER);
// wire map_to_bus = 0;
assign lsq_req_ready_o = map_to_bus? ~bus_lock : dcache_req_ready_i;
assign dcache_req_valid_o = ~map_to_bus & lsq_req_valid_i;
assign dcache_req_opcode_o = lsq_req_opcode_i;
assign dcache_req_sign_o = lsq_req_sign_i;
assign dcache_req_size_o = lsq_req_size_i;
assign dcache_req_addr_o = lsq_req_addr_i;
assign dcache_req_data_o = lsq_req_data_i;
assign dcache_req_lsq_index_o = lsq_req_lsq_index_i;
assign wb_cyc_o = map_to_bus & lsq_req_valid_i | bus_lock;
assign wb_stb_o = wb_cyc_o; // FIXME: risky assign
assign wb_we_o = bus_lock ? wb_opcode_save : lsq_req_opcode_i;
assign wb_adr_o = bus_lock ? wb_addr_save : lsq_req_addr_i;
assign wb_dat_o = bus_lock ? wb_data_save : lsq_req_data_i[WB_DATA_LEN -1:0];
assign wb_sel_o = bus_lock ? wb_mask_save : wb_mask32;
wire[WB_DATA_LEN/8-1:0] wb_mask32 = lsq_req_size_i == 0 ? (4'h1 << lsq_req_addr_i[1:0]) :
lsq_req_size_i == 1 ? (4'h3 << lsq_req_addr_i[1:0]) :
lsq_req_size_i == 2 ? (4'hf << lsq_req_addr_i[1:0]) :
4'b0; // wb mask is 32 bit, so size_i < 3
wire wb_resp_valid = wb_ack_i & ~wb_opcode_save; // load and ack
assign lsq_resp_valid_o = wb_resp_valid | dcache_resp_valid_i;
assign lsq_resp_lsq_index_o = wb_resp_valid ? wb_lsq_index_save : dcache_resp_lsq_index_i;
assign lsq_resp_data_o = wb_resp_valid ? {32'b0, wb_dat_i} : dcache_resp_data_i;
assign dcache_resp_ready_o = ~wb_resp_valid & lsq_resp_ready_i;
reg bus_lock;
reg [LSU_LSQ_SIZE_WIDTH - 1: 0] wb_lsq_index_save;
reg [VIRTUAL_ADDR_LEN - 1 : 0] wb_addr_save;
reg [WB_DATA_LEN-1:0] wb_data_save;
reg [WB_DATA_LEN/8-1:0] wb_mask_save;
reg wb_opcode_save;
always @(posedge clk) begin
if(rstn | flush) begin
bus_lock <= '0;
wb_lsq_index_save <= '0;
wb_addr_save <= '0;
wb_data_save <= '0;
wb_mask_save <= '0;
wb_opcode_save <= '0;
end
else begin
if(map_to_bus) begin
bus_lock <= '1;
wb_lsq_index_save <= lsq_req_lsq_index_i;
wb_addr_save <= lsq_req_addr_i;
wb_data_save <= lsq_req_data_i[WB_DATA_LEN -1:0];
wb_mask_save <= wb_mask32;
wb_opcode_save <= lsq_req_opcode_i;
end
if(wb_ack_i) begin
bus_lock <= '0;
end
// TODO: unlock bus
end
end
endmodule
`endif // LR_V