Add sign extend in LSU

This commit is contained in:
Florian Zaruba 2017-04-25 15:27:18 +02:00
parent c4edf3de3d
commit ec4384a95f
2 changed files with 146 additions and 15 deletions

153
lsu.sv
View file

@ -32,6 +32,7 @@ module lsu #(
input logic lsu_valid_i, // Input is valid
input logic [TRANS_ID_BITS-1:0] lsu_trans_id_i, // transaction id, needed for WB
output logic [TRANS_ID_BITS-1:0] lsu_trans_id_o, // ID of scoreboard entry at which to write back
output logic [63:0] lsu_result_o,
output logic lsu_valid_o, // transaction id for which the output is the requested one
input logic enable_translation_i,
@ -56,11 +57,20 @@ module lsu #(
output exception lsu_exception_o // to WB, signal exception status LD/ST exception
);
mem_if ptw_if(clk_i);
// data is misaligned
logic data_misaligned;
assign lsu_trans_id_o = lsu_trans_id_i;
assign lsu_valid_o = 1'b0;
logic [63:0] vaddr;
// ------------------------------
// Address Generation Unit (AGU)
// ------------------------------
assign vaddr = imm_i + operand_a_i;
assign data_if.address = vaddr;
// ---------------
// Memory Arbiter
// ---------------
@ -73,7 +83,8 @@ module lsu #(
logic [2:0] data_rvalid_o;
logic [2:0][63:0] data_rdata_o;
mem_arbiter i_mem_arbiter (
// port 0 PTW, port 1 loads, port 2 stores
mem_arbiter mem_arbiter_i (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
@ -98,6 +109,16 @@ module lsu #(
.data_rdata_o ( data_rdata_o )
);
// connecting PTW to D$ (aka mem arbiter)
assign address_i[0] = ptw_if.address;
assign data_wdata_i[0] = ptw_if.data_wdata;
assign data_req_i[0] = ptw_if.data_req;
assign data_we_i [0] = ptw_if.data_we;
assign data_be_i [0] = ptw_if.data_be;
assign ptw_if.data_rvalid = data_rvalid_o[0];
assign ptw_if.data_rdata = data_rdata_o[0];
// -------------------
// MMU e.g.: TLBs/PTW
// -------------------
@ -112,32 +133,142 @@ module lsu #(
) i_mmu (
.lsu_req_i ( lsu_req_i ),
.lsu_vaddr_i ( lsu_vaddr_i ),
.lsu_valid_o ( ),
.lsu_valid_o ( ),
.data_if ( ptw_if ),
.*
);
// ------------------
// LSU Control
// ------------------
always_comb begin : lsu_control
end
// ---------------
// Store Queue
// ---------------
// ---------------
// Sign Extend
// Byte Enable
// ---------------
// ------------------------------
// Address Generation Unit (AGU)
// ------------------------------
assign vaddr = imm_i + operand_a_i;
assign data_if.address = vaddr;
// ---------------
// Sign Extend
// ---------------
logic [63:0] rdata_ext;
// data coming from arbiter interface 1
assign rdata_ext = data_rdata_o[1];
logic [63:0] rdata_d_ext; // sign extension for double words, actually only misaligned assembly
logic [63:0] rdata_w_ext; // sign extension for words
logic [63:0] rdata_h_ext; // sign extension for half words
logic [63:0] rdata_b_ext; // sign extension for bytes
// ------------------
// LSU Control
// ------------------
// double words
always_comb begin : sign_extend_double_word
case (vaddr[2:0])
3'b000: rdata_d_ext = operand_b_i[63:0];
// this is for misaligned accesse only
// 3'b001: rdata_d_ext = {data_rdata_i[7:0], rdata_q[63:8]};
// 3'b010: rdata_d_ext = {data_rdata_i[15:0], rdata_q[63:16]};
// 3'b011: rdata_d_ext = {data_rdata_i[23:0], rdata_q[63:24]};
// 3'b100: rdata_d_ext = {data_rdata_i[31:0], rdata_q[63:32]};
// 3'b101: rdata_d_ext = {data_rdata_i[39:0], rdata_q[63:40]};
// 3'b110: rdata_d_ext = {data_rdata_i[47:0], rdata_q[63:48]};
// 3'b111: rdata_d_ext = {data_rdata_i[55:0], rdata_q[63:56]};
endcase
end
// sign extension for words
always_comb begin : sign_extend_word
case (vaddr[2:0])
3'b000: rdata_w_ext = (operator_i == LW) ? {{32{rdata_ext[31]}}, rdata_ext[31:0]} : {32'h0, rdata_ext[31:0]};
3'b001: rdata_w_ext = (operator_i == LW) ? {{32{rdata_ext[39]}}, rdata_ext[39:8]} : {32'h0, rdata_ext[39:8]};
3'b010: rdata_w_ext = (operator_i == LW) ? {{32{rdata_ext[47]}}, rdata_ext[47:16]} : {32'h0, rdata_ext[47:16]};
3'b011: rdata_w_ext = (operator_i == LW) ? {{32{rdata_ext[55]}}, rdata_ext[55:24]} : {32'h0, rdata_ext[55:24]};
3'b100: rdata_w_ext = (operator_i == LW) ? {{32{rdata_ext[63]}}, rdata_ext[63:32]} : {32'h0, rdata_ext[63:32]};
// miss-aligned access
// 3'b101: rdata_w_ext = (data_sign_ext_q) ? {{32{data_rdata_i[7]}}, data_rdata_i[7:0], rdata_q[63:40]} : {32'h0, data_rdata_i[7:0], rdata_q[63:40]};
// 3'b110: rdata_w_ext = (data_sign_ext_q) ? {{32{data_rdata_i[15]}}, data_rdata_i[15:0], rdata_q[63:48]} : {32'h0, data_rdata_i[15:0], rdata_q[63:48]};
// 3'b111: rdata_w_ext = (data_sign_ext_q) ? {{32{data_rdata_i[23]}}, data_rdata_i[23:0], rdata_q[63:56]} : {32'h0, data_rdata_i[23:0], rdata_q[63:56]};
endcase
end
// sign extension for half words
always_comb begin : sign_extend_half_word
case (vaddr[2:0])
3'b000: rdata_h_ext = (operator_i == LH) ? {{48{rdata_ext[15]}}, rdata_ext[15:0]} : {48'h0, rdata_ext[15:0]};
3'b001: rdata_h_ext = (operator_i == LH) ? {{48{rdata_ext[23]}}, rdata_ext[23:8]} : {48'h0, rdata_ext[23:8]};
3'b010: rdata_h_ext = (operator_i == LH) ? {{48{rdata_ext[31]}}, rdata_ext[31:16]} : {48'h0, rdata_ext[31:16]};
3'b011: rdata_h_ext = (operator_i == LH) ? {{48{rdata_ext[39]}}, rdata_ext[39:24]} : {48'h0, rdata_ext[39:24]};
3'b100: rdata_h_ext = (operator_i == LH) ? {{48{rdata_ext[47]}}, rdata_ext[47:32]} : {48'h0, rdata_ext[47:32]};
3'b101: rdata_h_ext = (operator_i == LH) ? {{48{rdata_ext[55]}}, rdata_ext[55:40]} : {48'h0, rdata_ext[55:40]};
3'b110: rdata_h_ext = (operator_i == LH) ? {{48{rdata_ext[63]}}, rdata_ext[63:48]} : {48'h0, rdata_ext[63:48]};
// miss-aligned access
// 3'b111: rdata_h_ext = (data_sign_ext_q) ? {{48{data_rdata_i[7]}}, data_rdata_i[7:0], rdata_q[31:24]} : {48'h0, data_rdata_i[7:0], rdata_q[31:24]};
endcase
end
always_comb begin : sign_extend_byte
case (vaddr[2:0])
3'b000: rdata_b_ext = (operator_i == LB) ? {{56{rdata_ext[7]}}, rdata_ext[7:0]} : {56'h0, rdata_ext[7:0]};
3'b001: rdata_b_ext = (operator_i == LB) ? {{56{rdata_ext[15]}}, rdata_ext[15:8]} : {56'h0, rdata_ext[15:8]};
3'b010: rdata_b_ext = (operator_i == LB) ? {{56{rdata_ext[23]}}, rdata_ext[23:16]} : {56'h0, rdata_ext[23:16]};
3'b011: rdata_b_ext = (operator_i == LB) ? {{56{rdata_ext[31]}}, rdata_ext[31:24]} : {56'h0, rdata_ext[31:24]};
3'b100: rdata_b_ext = (operator_i == LB) ? {{56{rdata_ext[39]}}, rdata_ext[39:32]} : {56'h0, rdata_ext[39:32]};
3'b101: rdata_b_ext = (operator_i == LB) ? {{56{rdata_ext[47]}}, rdata_ext[47:40]} : {56'h0, rdata_ext[47:40]};
3'b110: rdata_b_ext = (operator_i == LB) ? {{56{rdata_ext[55]}}, rdata_ext[55:48]} : {56'h0, rdata_ext[55:48]};
3'b111: rdata_b_ext = (operator_i == LB) ? {{56{rdata_ext[63]}}, rdata_ext[63:56]} : {56'h0, rdata_ext[63:56]};
endcase // case (rdata_offset_q)
end
always_comb begin
case (operator_i)
LD: lsu_result_o = rdata_d_ext;
LW, LWU: lsu_result_o = rdata_w_ext;
LH, LHU: lsu_result_o = rdata_h_ext;
LB, LBU: lsu_result_o = rdata_b_ext;
endcase //~case(rdata_type_q)
end
// ------------------
// Exception Control
// ------------------
// misaligned detector
// page fault, privilege exception
always_comb begin : exception_control
data_misaligned = 1'b0;
if(lsu_valid_i) begin
case (operator_i)
LD, SD: begin // double word
if(vaddr[2:0] != 3'b000)
data_misaligned = 1'b1;
end
LW, LWU, SW: begin // word
if(vaddr[2] == 1'b1 && vaddr[2:0] != 3'b100)
data_misaligned = 1'b1;
end
LH, LHU, SH: begin // half word
if(vaddr[2:0] == 3'b111)
data_misaligned = 1'b1;
end // byte -> is always aligned
default:;
endcase
end
end
// registers
always_ff @(posedge clk_i or negedge rst_ni) begin
if(~rst_ni) begin
// if the request was valid latch it
// it is the purpose of the issue stage to not dispatch
// instructions if the unit was not ready
end else if (lsu_valid_i) begin
end
end
endmodule

View file

@ -108,11 +108,11 @@ module mem_arbiter #(
data_rvalid_o[i] = 1'b0;
data_rdata_o[i] = 64'b0;
end
// if there is an entry in the queue we are waiting for a read to return
// there is a valid signal and the FIFO should not be empty anyway
// if there is an entry in the queue -> we are waiting for a read/write to return
// if there is a valid signal the FIFO should not be empty anyway
if (data_rvalid_i) begin
// pass the read through to the appropriate slave
pop_i = 1'b1;
// pass the read to the appropriate slave
pop_i = 1'b1;
data_rvalid_o[data_o] = data_rvalid_i;
data_rdata_o[data_o] = data_rdata_i;
end