1
0
mirror of https://github.com/olofk/serv.git synced 2026-03-02 01:30:24 +00:00

Initial HERV implementation

This commit is contained in:
Olof Kindgren
2025-05-14 01:42:41 +02:00
parent 15bf53241b
commit 1a8434b7ab
9 changed files with 248 additions and 17 deletions

View File

@@ -7,7 +7,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
width: [1, 4]
width: [1, 4, 8]
name: Linter
env:
REPO : serv

View File

@@ -83,6 +83,29 @@ module serv_bufreg #(
wire [2*W+B-2:0] muxdata = {data[W+B-1:0],data_tail};
wire [B:0] muxout = muxdata[{1'b0,shift_amount}+:W];
assign o_lsb = (MDU & i_mdu_op) ? 2'b00 : lsb;
assign o_q = i_en ? muxout : {W{1'b0}};
end else if (W == 8) begin : gen_lsb_w_8
reg [1:0] lsb;
reg [W-2:0] data_tail;
wire [3:0] shift_amount
= !i_shift_op ? 4'd7 :
i_right_shift_op ? (4'd7+{1'b0,i_shamt[2:0]}) :
({1'b0,~i_shamt[2:0]});
always @(posedge i_clk) begin
if (i_en)
if (i_cnt0) lsb <= q[1:0];
if (i_en)
data <= {i_init ? q : {W{i_sh_signed & data[31]}}, data[31:W]};
if (i_en)
data_tail <= data[B:1] & {B{~i_cnt_done}};
end
wire [2*W+B-2:0] muxdata = {data[W+B-1:0],data_tail};
wire [B:0] muxout = muxdata[{1'b0,shift_amount}+:W];
assign o_lsb = (MDU & i_mdu_op) ? 2'b00 : lsb;
assign o_q = i_en ? muxout : {W{1'b0}};
end

View File

@@ -65,11 +65,17 @@ module serv_bufreg2
*/
wire [7:0] cnt_next;
wire [7:0] sh_next;
generate
if (W == 1) begin : gen_cnt_w_eq_1
assign cnt_next = {o_op_b, dhi[7], dhi[5:0]-6'd1};
assign sh_next = {o_op_b, dhi[7:W]};
end else if (W == 4) begin : gen_cnt_w_eq_4
assign cnt_next = {o_op_b[3:2], dhi[5:0]-6'd4};
assign sh_next = {o_op_b, dhi[7:W]};
end else if (W == 8) begin : gen_cnt_w_eq_8
assign cnt_next = {o_op_b[7:6], dhi[5:0]-6'd8};
assign sh_next = o_op_b;
end
endgenerate
@@ -77,7 +83,7 @@ module serv_bufreg2
//Down counter mode
cnt_next :
//Shift reg mode
{o_op_b, dhi[7:W]};
sh_next;
assign o_sh_done = dat_shamt[5];

View File

@@ -72,6 +72,8 @@ module serv_csr
assign mstatus = ((mstatus_mie & i_cnt3) | (i_cnt11 | i_cnt12));
end else if (W==4) begin : gen_mstatus_w4
assign mstatus = {i_cnt11 | (mstatus_mie & i_cnt3), 2'b00, i_cnt12};
end else if (W==8) begin : gen_mstatus_w8
assign mstatus = {3'b000, i_cnt12, i_cnt11 | (mstatus_mie & i_cnt3), 3'b000};
end
endgenerate
@@ -83,9 +85,28 @@ module serv_csr
wire timer_irq = i_mtip & mstatus_mie & mie_mtie;
generate
if (W > 4) begin : gen_mcause_w_gt_4
assign mcause = i_cnt0to3 ? {{W-4{1'b0}},mcause3_0} : //[3:0]
i_cnt_done ? {mcause31,{B{1'b0}}} //[31]
: {W{1'b0}};
end else begin : gen_mcause_w_le_4
assign mcause = i_cnt0to3 ? mcause3_0[B:0] : //[3:0]
i_cnt_done ? {mcause31,{B{1'b0}}} //[31]
: {W{1'b0}};
end
endgenerate
wire [3:0] mcause3_0_next;
generate
if (W == 1) begin : gen_mcause_next_w_eq_1
assign mcause3_0_next = {csr_in, mcause3_0[3:1]};
end else begin : gen_mcause_next_w_eq_4
assign mcause3_0_next = csr_in[3:0];
end
endgenerate
assign o_csr_in = csr_in;
@@ -109,7 +130,7 @@ module serv_csr
These conditions are all mutually exclusive
*/
if ((i_trap & i_cnt_done) | i_mstatus_en & i_cnt3 & i_en | i_mret)
mstatus_mie <= !i_trap & (i_mret ? mstatus_mpie : csr_in[B]);
mstatus_mie <= !i_trap & (i_mret ? mstatus_mpie : csr_in[(W>4) ? 3 : B]);
/*
Note: To save resources mstatus_mpie (mstatus bit 7) is not
@@ -141,10 +162,10 @@ module serv_csr
ctrl => 0000 (jump=0)
*/
if (i_mcause_en & i_en & i_cnt0to3 | (i_trap & i_cnt_done)) begin
mcause3_0[3] <= (i_e_op & !i_ebreak) | (!i_trap & csr_in[B]);
mcause3_0[2] <= o_new_irq | i_mem_op | (!i_trap & ((W == 1) ? mcause3_0[3] : csr_in[(W == 1) ? 0 : 2]));
mcause3_0[1] <= o_new_irq | i_e_op | (i_mem_op & i_mem_cmd) | (!i_trap & ((W == 1) ? mcause3_0[2] : csr_in[(W == 1) ? 0 : 1]));
mcause3_0[0] <= o_new_irq | i_e_op | (!i_trap & ((W == 1) ? mcause3_0[1] : csr_in[0]));
mcause3_0[3] <= (i_e_op & !i_ebreak) | (!i_trap & mcause3_0_next[3]);
mcause3_0[2] <= o_new_irq | i_mem_op | (!i_trap & mcause3_0_next[2]);
mcause3_0[1] <= o_new_irq | i_e_op | (!i_trap & mcause3_0_next[1]) | (i_mem_op & i_mem_cmd);
mcause3_0[0] <= o_new_irq | i_e_op | (!i_trap & mcause3_0_next[0]);
end
if (i_mcause_en & i_cnt_done | i_trap)
mcause31 <= i_trap ? o_new_irq : csr_in[B];

View File

@@ -55,7 +55,7 @@ module serv_ctrl
generate
if (W == 1) begin : gen_plus_4_w_eq_1
assign plus_4 = i_iscomp ? i_cnt1 : i_cnt2;
end else if (W == 4) begin : gen_plus_4_w_eq_4
end else if (W >= 4) begin : gen_plus_4_w_ge_4
assign plus_4 = (i_cnt0 | i_cnt1) ? (i_iscomp ? 2 : 4) : 0;
end
endgenerate
@@ -70,6 +70,8 @@ module serv_ctrl
assign new_pc = i_trap ? (i_csr_pc & !(i_cnt0 || i_cnt1)) : i_jump ? pc_plus_offset_aligned : pc_plus_4;
end else if (W == 4) begin : gen_new_pc_w_eq_4
assign new_pc = i_trap ? (i_csr_pc & ((i_cnt0 || i_cnt1) ? 4'b1100 : 4'b1111)) : i_jump ? pc_plus_offset_aligned : pc_plus_4;
end else if (W == 8) begin : gen_new_pc_w_eq_8
assign new_pc = i_trap ? (i_csr_pc & ((i_cnt0 || i_cnt1) ? 8'b11111100 : 8'b11111111)) : i_jump ? pc_plus_offset_aligned : pc_plus_4;
end
end else begin : gen_no_csr
assign new_pc = i_jump ? pc_plus_offset_aligned : pc_plus_4;
@@ -78,7 +80,14 @@ module serv_ctrl
assign o_rd = ({W{i_utype}} & pc_plus_offset_aligned) | (pc_plus_4 & {W{i_jal_or_jalr}});
assign offset_a = {W{i_pc_rel}} & pc;
assign offset_b = i_utype ? (i_imm & {W{i_cnt12to15 | i_cnt16to31}}) : i_buf;
generate
if (W == 8) begin : gen_offset_w_eq_8
assign offset_b = i_utype ? (i_imm & {{4{i_cnt12to15 | i_cnt16to31}}, {4{i_cnt16to31}}}) : i_buf;
end else begin : gen_offset_w_lt_8
assign offset_b = i_utype ? (i_imm & {W{i_cnt12to15 | i_cnt16to31}}) : i_buf;
end
endgenerate
assign {pc_plus_offset_cy,pc_plus_offset} = offset_a+offset_b+pc_plus_offset_cy_r_w;
generate

View File

@@ -93,7 +93,7 @@ generate
end
assign o_imm = i_cnt_done ? signbit : i_ctrl[0] ? imm11_7[0] : imm24_20[0];
end else begin : gen_immdec_w_eq_4
end else if (W == 4) begin : gen_immdec_w_eq_4
reg [4:0] rd_addr;
reg [4:0] rs1_addr;
reg [4:0] rs2_addr;
@@ -223,6 +223,150 @@ generate
assign o_imm[1] = i_ctrl[0] ? i8 : i21;
assign o_imm[0] = i_ctrl[0] ? i7_2 : i20_2;
end else begin : gen_immdec_w_eq_8
reg [4:0] rd_addr;
reg [4:0] rs1_addr;
reg [4:0] rs2_addr;
reg i31;
reg i30;
reg i29;
reg i28;
reg i27;
reg i26;
reg i25;
reg i24;
reg i23;
reg i22;
reg i21;
reg i20;
reg i19;
reg i18;
reg i17;
reg i16;
reg i15;
reg i14;
reg i13;
reg i12;
reg i11;
reg i10;
reg i9;
reg i8;
reg i7;
reg i7_2;
reg i20_2;
wire signbit = i31 & !i_csr_imm_en;
assign o_csr_imm[7] = 1'b0;
assign o_csr_imm[6] = 1'b0;
assign o_csr_imm[5] = 1'b0;
assign o_csr_imm[4] = i19;
assign o_csr_imm[3] = i18;
assign o_csr_imm[2] = i17;
assign o_csr_imm[1] = i16;
assign o_csr_imm[0] = i15;
assign o_rd_addr = rd_addr;
assign o_rs1_addr = rs1_addr;
assign o_rs2_addr = rs2_addr;
always @(posedge i_clk) begin
if (i_wb_en) begin
//Common
i31 <= i_wb_rdt[31];
//Bit lane 3
i19 <= i_wb_rdt[19];
i15 <= i_wb_rdt[15];
i20 <= i_wb_rdt[20];
i7 <= i_wb_rdt[7];
i27 <= i_wb_rdt[27];
i23 <= i_wb_rdt[23];
i10 <= i_wb_rdt[10];
//Bit lane 2
i22 <= i_wb_rdt[22];
i9 <= i_wb_rdt[ 9];
i26 <= i_wb_rdt[26];
i30 <= i_wb_rdt[30];
i14 <= i_wb_rdt[14];
i18 <= i_wb_rdt[18];
//Bit lane 1
i21 <= i_wb_rdt[21];
i8 <= i_wb_rdt[ 8];
i25 <= i_wb_rdt[25];
i29 <= i_wb_rdt[29];
i13 <= i_wb_rdt[13];
i17 <= i_wb_rdt[17];
//Bit lane 0
i11 <= i_wb_rdt[11];
i7_2 <= i_wb_rdt[7 ];
i20_2 <= i_wb_rdt[20];
i24 <= i_wb_rdt[24];
i28 <= i_wb_rdt[28];
i12 <= i_wb_rdt[12];
i16 <= i_wb_rdt[16];
rd_addr <= i_wb_rdt[11:7];
rs1_addr <= i_wb_rdt[19:15];
rs2_addr <= i_wb_rdt[24:20];
end
if (i_cnt_en) begin
//Bit lane 6, 7
i10 <= i_ctrl[2] ? i7 : i_ctrl[1] ? signbit : i20;
i23 <= i_ctrl[2] ? i7 : i_ctrl[1] ? signbit : i20;
i27 <= i_ctrl[2] ? signbit : i_ctrl[1] ? signbit : i15;
i7 <= signbit;
i20 <= i19;
i15 <= i_ctrl[3] ? signbit : i23;
i19 <= i_ctrl[3] ? signbit : i27;
//Bit lane 4, 5
i22 <= i30;
i9 <= i30;
i26 <= (i_ctrl[1] | i_ctrl[2]) ? signbit : i14;
i30 <= (i_ctrl[1] | i_ctrl[2]) ? signbit : i18;
i14 <= i_ctrl[3] ? signbit : i22;
i18 <= i_ctrl[3] ? signbit : i26;
//Bit lane 2, 3
i21 <= i29;
i8 <= i29;
i25 <= (i_ctrl[1] | i_ctrl[2]) ? signbit : i13;
i29 <= (i_ctrl[1] | i_ctrl[2]) ? signbit : i17;
i13 <= i_ctrl[3] ? signbit : i21;
i17 <= i_ctrl[3] ? signbit : i25;
//Bit lane 0, 1
i7_2 <= i28;
i20_2 <= i28;
i28 <= (i_ctrl[1] | i_ctrl[2]) ? signbit : i16;
i16 <= i_ctrl[3] ? signbit : i24;
i11 <= (i_ctrl[1] | i_ctrl[2]) ? signbit : i12;
i24 <= (i_ctrl[1] | i_ctrl[2]) ? signbit : i12;
i12 <= i_ctrl[3] ? signbit : i20_2;
end
end
assign o_imm[7] = (i_cnt_done ? signbit : (i_ctrl[0] ? i27 : i27));
assign o_imm[3] = ((i_ctrl[0] ? i10 : i23));
assign o_imm[6] = i_ctrl[0] ? i26 : i26;
assign o_imm[2] = i_ctrl[0] ? i9 : i22;
assign o_imm[5] = i_ctrl[0] ? i25 : i25;
assign o_imm[1] = i_ctrl[0] ? i8 : i21;
assign o_imm[4] = i_ctrl[0] ? i11 : i24;
assign o_imm[0] = i_ctrl[0] ? i7_2 : i20_2;
end
endgenerate

View File

@@ -91,7 +91,13 @@ module serv_rf_ram_if
assign o_wen = (wtrig0 & wen0_r) | (wtrig1 & wen1_r);
assign wcnt = rcnt-4;
generate
if (W > 4) begin : gen_wcnt_w_gt_4
assign wcnt = rcnt;
end else begin : gen_wcnt_w_le_4
assign wcnt = rcnt-4;
end
endgenerate
always @(posedge i_clk) begin
if (wcnt[0]) begin

View File

@@ -73,15 +73,26 @@ module serv_state
assign o_mem_bytecnt = o_cnt[4:3];
assign o_cnt0to3 = (o_cnt[4:2] == 3'd0);
assign o_cnt12to15 = (!o_cnt[4] & (o_cnt[3:2] == 2'b11));
assign o_cnt16to31 = o_cnt[4];
assign o_cnt0 = (o_cnt[4:2] == 3'd0) & cnt_r[0];
assign o_cnt1 = (o_cnt[4:2] == 3'd0) & cnt_r[1];
assign o_cnt2 = (o_cnt[4:2] == 3'd0) & cnt_r[2];
assign o_cnt3 = (o_cnt[4:2] == 3'd0) & cnt_r[3];
assign o_cnt7 = (o_cnt[4:2] == 3'd1) & cnt_r[3];
assign o_cnt11 = (o_cnt[4:2] == 3'd2) & cnt_r[3];
assign o_cnt12 = (o_cnt[4:2] == 3'd3) & cnt_r[0];
generate
if (W == 8) begin : gen_cnt_w_8
assign o_cnt12to15 = (o_cnt[4:3] == 2'b01);
assign o_cnt7 = o_cnt0 & o_cnt_en;
assign o_cnt12 = o_cnt11;
assign o_cnt_done = (o_cnt[4:3] == 2'b11) & cnt_r[3];
end else begin : gen_cnt_w_lt_8
assign o_cnt12to15 = (o_cnt[4:2] == 3'b011);
assign o_cnt7 = (o_cnt[4:2] == 3'd1) & cnt_r[3];
assign o_cnt12 = (o_cnt[4:2] == 3'd3) & cnt_r[0];
assign o_cnt_done = (o_cnt[4:2] == 3'b111) & cnt_r[3];
end
endgenerate
//Take branch for jump or branch instructions (opcode == 1x0xx) if
//a) It's an unconditional branch (opcode[0] == 1)
@@ -133,8 +144,6 @@ module serv_state
assign o_init = i_two_stage_op & !i_new_irq & !init_done;
assign o_cnt_done = (o_cnt[4:2] == 3'b111) & cnt_r[3];
always @(posedge i_clk) begin
//ibus_cyc changes on three conditions.
//1. i_rst is asserted. Together with the async gating above, o_ibus_cyc
@@ -209,6 +218,19 @@ module serv_state
end
assign cnt_r = 4'b1111;
assign o_cnt_en = cnt_en;
end else if (W == 8) begin : gen_cnt_w_eq_8
reg cnt_en;
always @(posedge i_clk) begin
if (i_rf_ready) cnt_en <= 1; else
if (o_cnt_done) cnt_en <= 0;
o_cnt <= o_cnt + { 1'd0, cnt_en, 1'b0};
if (i_rst & (RESET_STRATEGY != "NONE")) begin
o_cnt <= 3'd0;
cnt_en <= 1'b0;
end
end
assign cnt_r = 4'b1111;
assign o_cnt_en = cnt_en;
end
endgenerate

View File

@@ -40,7 +40,7 @@ class serv(pluginTemplate):
build_serv = 'fusesoc run --target=verilator_tb --flag=mdu\
--build --build-root=servant_test servant\
--memsize=8388608 --compressed=1'
--memsize=8388608 --compressed=1 --width=8'
utils.shellCommand(build_serv).run()
def build(self, isa_yaml, platform_yaml):