1
0
mirror of https://github.com/olofk/serv.git synced 2026-02-10 17:49:45 +00:00
Files
olofk.serv/rtl/serv_mem_if.v
2018-11-21 13:15:33 +01:00

136 lines
3.6 KiB
Verilog

`default_nettype none
module serv_mem_if
(
input wire i_clk,
input wire i_rst,
input wire i_en,
input wire i_init,
input wire i_dat_valid,
input wire i_cmd,
input wire [2:0] i_funct3,
input wire i_rs1,
input wire i_rs2,
input wire i_imm,
output wire o_rd,
output wire o_misalign,
input wire i_trap,
//External interface
output wire [31:0] o_wb_adr,
output reg [31:0] o_wb_dat = 32'd0,
output wire [3:0] o_wb_sel,
output wire o_wb_we ,
output reg o_wb_cyc = 1'b0,
output wire o_wb_stb,
input wire [31:0] i_wb_rdt,
input wire i_wb_ack);
wire wb_en = o_wb_cyc & i_wb_ack;
assign o_wb_stb = o_wb_cyc;
reg init_r;
reg en_r;
reg en_2r;
wire adr;
reg [31:0] dat = 32'd0;
reg signbit = 1'b0;
ser_add ser_add_rs1_plus_imm
(
.clk (i_clk),
.rst (i_rst),
.a (i_rs1),
.b (i_imm),
.clr (!i_en),
.q (adr),
.o_v ());
shift_reg #(32) shift_reg_adr
(
.clk (i_clk),
.i_en (i_init | (i_en & i_trap)),
.i_d (adr),
.o_q (o_wb_adr[0]),
.o_par (o_wb_adr[31:1])
);
wire is_signed = ~i_funct3[2];
assign o_rd = i_dat_valid ? dat[0] : signbit & is_signed;
wire is_word = i_funct3[1];
wire is_half = i_funct3[0];
wire is_byte = !(|i_funct3[1:0]);
assign o_misalign = (|misalign);
wire upper_half = bytepos[1];
assign o_wb_sel = (is_word ? 4'b1111 :
is_half ? {{2{upper_half}}, ~{2{upper_half}}} :
4'd1 << bytepos);
assign o_wb_we = i_cmd;
reg [1:0] bytepos;
reg [4:0] cnt = 5'd0;
reg dat_en;
always @(i_funct3, cnt, bytepos)
casez(i_funct3[1:0])
2'b1? : dat_en = 1'b1;
2'b01 : dat_en = bytepos[1] ? (cnt<16) : 1'b1;
2'b00 : dat_en = (bytepos == 2'd3) ? (cnt <8) :
(bytepos == 2'd2) ? (cnt < 16) :
(bytepos == 2'd1) ? (cnt < 24) : 1'b1;
endcase
reg init_2r = 1'b0;
reg [1:0] misalign = 2'b00;
always @(posedge i_clk) begin
//Async?
if (init_r) begin
o_wb_dat[7:0] <= dat[7:0];
o_wb_dat[15:8] <= (is_word | is_half) ? dat[15:8] : dat[7:0];
o_wb_dat[23:16] <= is_word ? dat[23:16] : dat[7:0];
o_wb_dat[31:24] <= is_word ? dat[31:24] : is_half ? dat[15:8] : dat[7:0];
end
if (i_init & !init_r)
misalign[0] <= (!is_byte & adr);
if (init_r & !init_2r)
misalign[1] <= (is_word & adr);
if (!i_en)
misalign <= 2'b00;
if (i_en & !en_r)
bytepos[0] <= adr;
if (en_r & !en_2r)
bytepos[1] <= adr;
if (i_dat_valid)
signbit <= dat[0];
if (wb_en & !o_wb_we) begin
dat[31:16] <= i_wb_rdt[31:16];
dat[15:8] <= (is_half & upper_half) ? i_wb_rdt[31:24] : i_wb_rdt[15:8];
dat[7:0] <= (is_byte & (bytepos == 2'b11)) ? i_wb_rdt[31:24] :
(is_byte & (bytepos == 2'b10)) ? i_wb_rdt[23:16] :
(is_half & upper_half) ? i_wb_rdt[23:16] :
(is_byte & (bytepos == 2'b01)) ? i_wb_rdt[15:8] :
i_wb_rdt[7:0];
end
en_r <= i_en;
en_2r <= en_r;
init_r <= i_init;
init_2r <= init_r;
if (wb_en)
o_wb_cyc <= 1'b0;
else if (init_r & !i_init & !i_trap) begin //Optimize?
o_wb_cyc <= 1'b1;
end
if (i_en & dat_en)
dat <= {i_rs2,dat[31:1]};
end
endmodule