1
0
mirror of https://github.com/olofk/serv.git synced 2026-01-24 02:57:20 +00:00
olofk.serv/rtl/serv_mem_if.v
2019-08-14 22:15:45 +02:00

109 lines
3.0 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_cnt_done,
input wire i_cmd,
input wire [1:0] i_bytecnt,
input wire [2:0] i_funct3,
input wire i_rs2,
output wire o_rd,
input wire [1:0] i_lsb,
output reg o_misalign,
//External interface
output wire [31:0] o_wb_dat,
output wire [3:0] o_wb_sel,
output wire o_wb_we ,
output reg o_wb_cyc,
input wire [31:0] i_wb_rdt,
input wire i_wb_ack);
wire wb_en = o_wb_cyc & i_wb_ack;
reg signbit = 1'b0;
reg [7:0] dat0;
reg [7:0] dat1;
reg [7:0] dat2;
reg [7:0] dat3;
wire dat0_en;
wire dat1_en;
wire dat2_en;
wire dat3_en;
reg [1:0] bytepos;
wire [1:0] dat_sel = i_bytecnt[1] ? i_bytecnt : (i_bytecnt | bytepos);
wire dat_cur = (dat_sel == 3) ? dat3[0] :
(dat_sel == 2) ? dat2[0] :
(dat_sel == 1) ? dat1[0] : dat0[0];
wire is_signed = ~i_funct3[2];
wire is_word = i_funct3[1];
wire is_half = i_funct3[0];
wire is_byte = !(|i_funct3[1:0]);
wire dat_valid = is_word | (i_bytecnt == 2'b00) | (is_half & !i_bytecnt[1]);
assign o_rd = dat_valid ? dat_cur : signbit & is_signed;
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_sel[3] = is_word | (is_half & bytepos[1]) | (bytepos == 2'b11);
assign o_wb_sel[2] = (bytepos == 2'b10) | is_word;
assign o_wb_sel[1] = ((is_word | is_half) & !bytepos[1]) | (bytepos == 2'b01);
assign o_wb_sel[0] = (bytepos == 2'b00);
assign o_wb_we = i_cmd;
wire wbyte0 = (i_bytecnt == 2'b00);
wire wbyte1 = ((i_bytecnt == 2'b01) & !bytepos[0]);
wire wbyte2 = ((i_bytecnt == 2'b10) & !bytepos[1]);
wire wbyte3 = ((i_bytecnt == 2'b11) & !bytepos[1]);
assign dat0_en = i_en & (i_init ? wbyte0 : (dat_sel == 2'd0));
assign dat1_en = i_en & (i_init ? (wbyte0 | wbyte1) : (dat_sel == 2'd1));
assign dat2_en = i_en & (i_init ? (wbyte0 | wbyte2) : (dat_sel == 2'd2));
assign dat3_en = i_en & (i_init ? (wbyte0 | wbyte1 | wbyte3) : (dat_sel == 2'd3));
assign o_wb_dat = {dat3,dat2,dat1,dat0};
always @(posedge i_clk) begin
if (i_init)
bytepos <= i_lsb;
if (dat0_en)
dat0 <= {i_rs2, dat0[7:1]};
if (dat1_en)
dat1 <= {i_rs2, dat1[7:1]};
if (dat2_en)
dat2 <= {i_rs2, dat2[7:1]};
if (dat3_en)
dat3 <= {i_rs2, dat3[7:1]};
if (wb_en)
{dat3,dat2,dat1,dat0} <= i_wb_rdt;
o_misalign <= i_en & ((bytepos[0] & !is_byte) | (bytepos[1] & is_word));
if (dat_valid)
signbit <= dat_cur;
if (wb_en)
o_wb_cyc <= 1'b0;
else if (i_init & i_cnt_done & !o_misalign)
o_wb_cyc <= 1'b1;
if (i_rst) begin
o_wb_cyc <= 1'b0;
end
end
endmodule