1
0
mirror of https://github.com/olofk/serv.git synced 2026-04-29 05:25:07 +00:00

Initial commit

This commit is contained in:
Olof Kindgren
2018-10-23 23:45:41 +02:00
commit e10c41be8d
38 changed files with 35681 additions and 0 deletions

17
rtl/ser_add.v Normal file
View File

@@ -0,0 +1,17 @@
module ser_add
(
input clk,
input a,
input b,
input clear,
output reg q = 1'b0);
reg carry = 1'b0;
wire c = carry & ~clear;
always @(posedge clk) begin
q <= a ^ b ^ c;
carry <= a&b | a&c | b&c;
end
endmodule

69
rtl/serv_alu.v Normal file
View File

@@ -0,0 +1,69 @@
`default_nettype none
module serv_alu
(
input clk,
input i_d,
input i_go,
input i_funct3_valid,
input i_rs1,
output o_rs_en,
output o_rd,
output o_rd_valid);
localparam [2:0]
ADDI = 3'b000,
SLTI = 3'b010,
SLTIU = 3'b011,
XORI = 3'b100,
ORI = 3'b110,
ANDI = 3'b111;
wire [2:0] funct3;
shift_reg #(3) shift_reg_funct3
(
.clk (clk),
.i_d (i_d),
.i_en (i_funct3_valid),
.o_q (funct3[0]),
.o_par (funct3[2:1]));
wire op_b;
wire result_add;
assign op_b = i_d; //FIXME mux for rs2
assign o_rs_en = running;
ser_add ser_add
(
.clk (clk),
.a (i_rs1),
.b (op_b),
.clear (i_go),
.q (result_add));
assign o_rd = (funct3 == ADDI) ? result_add : 1'b0;
assign o_rd_valid = (cnt > 0);
reg [5:0] cnt = 6'd0;
reg done;
reg running = 1'd0;
always @(posedge clk) begin
cnt <= 6'd0;
done <= 1'b0;
if (i_go)
running <= 1'b1;
else if (cnt == 32) begin
running <= 1'b0;
done <= 1'b1;
end
if (running) begin
cnt <= cnt + 1;
end
end
endmodule

131
rtl/serv_ctrl.v Normal file
View File

@@ -0,0 +1,131 @@
`default_nettype none
module serv_ctrl
(
input clk,
input i_go,
input i_instr,
input i_jal,
input i_reg11,
input i_reg2012,
output o_reg2012_en,
output o_rd,
output o_rd_valid,
output [31:0] o_pc_data,
output reg o_pc_valid = 1'b1,
input i_pc_ready);
parameter RESET_PC = 32'd8;
localparam [2:0]
NULL = 3'd0,
INSTR = 3'd1,
REG11 = 3'd2,
REG2012 = 3'd3,
SIGNBIT = 3'd4;
wire offset;
reg signbit = 1'd0;
reg [5:0] cnt = 5'd0;
reg new_pc_sel = 1'b0;
wire pc_plus_4;
wire pc_plus_offset;
reg pc_plus_offset_clr = 1'b0;
wire plus_4;
wire pc_plus_4_clr;
reg running = 1'b0;
wire new_pc;
reg [2:0] offset_source;
assign pc_plus_4_clr = (cnt == 0);
assign plus_4 = (cnt == 2);
ser_add ser_add_pc_plus_4
(
.clk (clk),
.a (plus_4),
.b (o_pc_data[0]),
.clear (pc_plus_4_clr),
.q (pc_plus_4));
shift_reg
#(
.LEN (32),
.INIT (RESET_PC))
pc_reg
(
.clk (clk),
.i_en (running),
.i_d (new_pc),
.o_q (o_pc_data[0]),
.o_par (o_pc_data[31:1])
);
assign new_pc = new_pc_sel ? pc_plus_offset : pc_plus_4;
assign o_rd = pc_plus_4;
assign o_rd_valid = running & i_jal;
always @(cnt, i_jal, running) begin
offset_source = NULL;
new_pc_sel = 1'b0;
if (i_jal) begin
new_pc_sel = 1'b1;
if (cnt < 10)
offset_source = INSTR;
else if (cnt < 11)
offset_source = REG11;
else if (cnt < 20)
offset_source = REG2012;
else
offset_source = SIGNBIT;
end
end
wire o_reg11_en = (offset_source == REG11);
wire o_reg2012_en = (offset_source == REG2012);
assign offset = (offset_source == INSTR) ? i_instr :
(offset_source == REG11) ? i_reg11 :
(offset_source == REG2012) ? i_reg2012 :
(offset_source == SIGNBIT) ? signbit :
1'b0;
ser_add ser_add_pc_plus_offset
(
.clk (clk),
.a (o_pc_data[0]), //FIXME Need a mux before this
.b (offset),
.clear (pc_plus_offset_clr),
.q (pc_plus_offset));
reg done = 1'b0;
always @(posedge clk) begin
cnt <= 6'd0;
done <= 1'b0;
if (i_go)
running <= 1'b1;
else if (cnt == 32) begin
running <= 1'b0;
done <= 1'b1;
end
if (running) begin
cnt <= cnt + 1;
end
if (done)
o_pc_valid <= 1'b1;
if (o_pc_valid & i_pc_ready)
o_pc_valid <= 1'b0;
end
endmodule

68
rtl/serv_decode.v Normal file
View File

@@ -0,0 +1,68 @@
module serv_decode
(
input clk,
input i_go,
input i_instr,
output o_imm_31_12,
output o_imm_11_0,
output o_rd,
output o_field_rs2,
output o_field_rs1,
output o_funct3,
output o_funct7,
output o_jal,
output o_opimm,
output o_alu_go,
output o_ctrl_go);
localparam [4:0]
OP_OPIMM = 5'b00100,
OP_JAL = 5'b11011;
reg [8:0] barrel [0:31];
reg [4:0] cnt = 5'd0;
reg running = 1'b0;
wire opcode_valid;
wire halt;
wire [8:0] cur = barrel[cnt];
assign o_imm_31_12 = cur[8];
assign o_imm_11_0 = cur[7];
assign o_rd = cur[6];
assign o_field_rs2 = cur[5] & (1'b0);
assign o_field_rs1 = cur[4] & (1'b0);
assign o_funct3 = cur[3];
assign o_funct7 = cur[2];
assign opcode_valid = cur[1];
assign halt = cur[0];
initial begin
$readmemb("decode.mem", barrel);
end
reg [4:0] opcode = 5'd0;
assign o_jal = (opcode == OP_JAL);
assign o_ctrl_go = (cnt == 19);
assign o_opimm = (opcode == OP_OPIMM);
assign o_alu_go = o_opimm & (cnt == 19);
// shift_reg #(5) shift_reg_opcode
always @(posedge clk) begin
if (opcode_valid)
opcode <= {opcode[3:0], i_instr};
cnt <= cnt + (i_go | running);
if (i_go)
running <= 1'd1;
else if (halt) begin
running <= 1'd0;
cnt <= 1'b0;
end
end
endmodule

147
rtl/serv_regfile.v Normal file
View File

@@ -0,0 +1,147 @@
`default_nettype none
module serv_regfile
(
input clk,
input i_d,
input i_field_rs1,
input i_field_rs2,
input i_field_rd,
input i_rs_en,
output o_rs1,
output o_rs2,
input i_rd,
input i_rd_valid);
reg [31:0] rf [0:31];
function automatic [31:0] xreg;
input [4:0] regnum;
begin
xreg = {rf[31][regnum],rf[30][regnum],rf[29][regnum],rf[28][regnum],
rf[27][regnum],rf[26][regnum],rf[25][regnum],rf[24][regnum],
rf[23][regnum],rf[22][regnum],rf[21][regnum],rf[20][regnum],
rf[19][regnum],rf[18][regnum],rf[17][regnum],rf[16][regnum],
rf[15][regnum],rf[14][regnum],rf[13][regnum],rf[12][regnum],
rf[11][regnum],rf[10][regnum],rf[9][regnum] ,rf[8][regnum],
rf[7][regnum] ,rf[6][regnum] ,rf[5][regnum] ,rf[4][regnum],
rf[3][regnum] ,rf[2][regnum] ,rf[1][regnum] ,rf[0][regnum]};
end
endfunction // xreg
always @(*)
for (i=0;i<32;i=i+1) begin
dbg_x1[i] = rf[i][1];
dbg_x2[i] = rf[i][2];
dbg_x3[i] = rf[i][3];
dbg_x4[i] = rf[i][4];
dbg_x5[i] = rf[i][5];
dbg_x6[i] = rf[i][6];
dbg_x7[i] = rf[i][7];
dbg_x8[i] = rf[i][8];
dbg_x9[i] = rf[i][9];
dbg_x10[i] = rf[i][10];
dbg_x11[i] = rf[i][11];
dbg_x12[i] = rf[i][12];
dbg_x13[i] = rf[i][13];
dbg_x14[i] = rf[i][14];
dbg_x15[i] = rf[i][15];
dbg_x16[i] = rf[i][16];
dbg_x17[i] = rf[i][17];
dbg_x18[i] = rf[i][18];
dbg_x19[i] = rf[i][19];
dbg_x20[i] = rf[i][20];
dbg_x21[i] = rf[i][21];
dbg_x22[i] = rf[i][22];
dbg_x23[i] = rf[i][23];
dbg_x24[i] = rf[i][24];
dbg_x25[i] = rf[i][25];
dbg_x26[i] = rf[i][26];
dbg_x27[i] = rf[i][27];
dbg_x28[i] = rf[i][28];
dbg_x29[i] = rf[i][29];
dbg_x30[i] = rf[i][30];
dbg_x31[i] = rf[i][31];
end
reg [31:0] dbg_x0 ;
reg [31:0] dbg_x1 ;
reg [31:0] dbg_x2 ;
reg [31:0] dbg_x3 ;
reg [31:0] dbg_x4 ;
reg [31:0] dbg_x5 ;
reg [31:0] dbg_x6 ;
reg [31:0] dbg_x7 ;
reg [31:0] dbg_x8 ;
reg [31:0] dbg_x9 ;
reg [31:0] dbg_x10;
reg [31:0] dbg_x11;
reg [31:0] dbg_x12;
reg [31:0] dbg_x13;
reg [31:0] dbg_x14;
reg [31:0] dbg_x15;
reg [31:0] dbg_x16;
reg [31:0] dbg_x17;
reg [31:0] dbg_x18;
reg [31:0] dbg_x19;
reg [31:0] dbg_x20;
reg [31:0] dbg_x21;
reg [31:0] dbg_x22;
reg [31:0] dbg_x23;
reg [31:0] dbg_x24;
reg [31:0] dbg_x25;
reg [31:0] dbg_x26;
reg [31:0] dbg_x27;
reg [31:0] dbg_x28;
reg [31:0] dbg_x29;
reg [31:0] dbg_x30;
reg [31:0] dbg_x31;
reg [4:0] raddr = 5'd0;
reg [4:0] waddr = 5'd0;
reg [31:0] rs = 32'd0;
integer i;
initial for (i=0; i<32; i=i+1) rf[i] = 0;
always @(posedge clk) begin
if (i_rd_valid) begin
waddr <= waddr + 1;
rf[waddr][rd_addr] <= i_rd;
end
if (i_rs_en)
rs <= rf[raddr];
end
wire [4:0] rs1_addr;
wire [4:0] rs2_addr;
wire [4:0] rd_addr;
shift_reg #(5) shift_reg_rs1_addr
(.clk (clk),
.i_en (i_field_rs1),
.i_d (i_d),
.o_q (rs1_addr[0]),
.o_par (rs1_addr[4:1]));
shift_reg #(5) shift_reg_rs2_addr
(.clk (clk),
.i_en (i_field_rs2),
.i_d (i_d),
.o_q (rs2_addr[0]),
.o_par (rs2_addr[4:1]));
shift_reg #(5) shift_reg_rd_addr
(.clk (clk),
.i_en (i_field_rd),
.i_d (i_d),
.o_q (rd_addr[0]),
.o_par (rd_addr[4:1]));
assign o_rs1 = (|rs1_addr) ? rs[rs1_addr] : 1'b0;
assign o_rs2 = (|rs2_addr) ? rs[rs2_addr] : 1'b0;
endmodule

126
rtl/serv_top.v Normal file
View File

@@ -0,0 +1,126 @@
`default_nettype none
module serv_top
(
input clk,
input [31:0] i_i_data,
input i_i_valid,
output reg o_i_ready = 1'b1,
output [31:0] o_pc_data,
output o_pc_valid,
input i_pc_ready);
reg [31:0] cur_instr = 32'd0;
reg instr;
wire imm_31_12;
wire imm_11_0;
wire field_rd;
wire field_rs1;
wire field_rs2;
wire funct3;
wire funct7;
reg decode_go = 1'b0;
wire ctrl_go;
wire alu_go;
wire rs_en;
wire rs1;
wire rs2;
wire rd;
wire ctrl_rd;
wire ctrl_rd_valid;
wire alu_rd;
wire alu_rd_valid;
wire funct3_valid;
wire jal;
wire opimm;
serv_decode decode
(
.clk (clk),
.i_instr (cur_instr[0]),
.i_go (decode_go),
.o_funct7 (funct7),
.o_funct3 (funct3_valid),
.o_field_rs1 (field_rs1),
.o_field_rs2 (field_rs2),
.o_rd (field_rd),
.o_imm_11_0 (imm_11_0),
.o_imm_31_12 (imm_31_12),
.o_jal (jal),
.o_opimm (opimm),
.o_alu_go (alu_go),
.o_ctrl_go (ctrl_go));
wire reg_2012_en_decode;
wire reg_2012_en_ctrl;
wire reg_2012_data;
wire reg_2012_en = reg_2012_en_decode | reg_2012_en_ctrl;
shift_reg
#(
.LEN (9))
reg_2012
(
.clk (clk),
.i_en (reg_2012_en),
.i_d (cur_instr[0]),
.o_q (reg_2012_data));
serv_alu alu
(
.clk (clk),
.i_go (alu_go),
.i_d (cur_instr[0]),
.i_funct3_valid (funct3_valid),
.i_rs1 (rs1),
.o_rs_en (rs_en),
.o_rd (alu_rd),
.o_rd_valid (alu_rd_valid));
serv_ctrl ctrl
(
.clk (clk),
.i_go (ctrl_go),
.i_instr (cur_instr[0]),
.i_jal (jal),
.i_reg11 (1'b0), //FIXME
.i_reg2012 (reg_2012_data),
.o_reg2012_en (reg_2012_en_ctrl),
.o_rd (ctrl_rd),
.o_rd_valid (ctrl_rd_valid),
.o_pc_data (o_pc_data),
.o_pc_valid (o_pc_valid),
.i_pc_ready (i_pc_ready));
serv_regfile regfile
(
.clk (clk),
.i_d (cur_instr[0]),
.i_field_rs1 (field_rs1),
.i_field_rs2 (field_rs2),
.i_field_rd (field_rd),
.i_rs_en (rs_en),
.o_rs1 (rs1),
.o_rs2 (rs2),
.i_rd ((ctrl_rd & ctrl_rd_valid) | (alu_rd & alu_rd_valid)),
.i_rd_valid (ctrl_rd_valid | alu_rd_valid));
always @(posedge clk) begin
decode_go <= 1'b0;
cur_instr <= {1'b0, cur_instr[31:1]};
if (o_pc_valid)
o_i_ready <= 1'b1;
if (i_i_valid & o_i_ready) begin
cur_instr <= i_i_data;
o_i_ready <= 1'b0;
decode_go <= 1'b1;
end
end // always @ (posedge clk)
endmodule

18
rtl/shift_reg.v Normal file
View File

@@ -0,0 +1,18 @@
module shift_reg
(
input clk,
input i_en,
input i_d,
output o_q,
output [LEN-2:0] o_par);
parameter LEN = 0;
parameter INIT = 0;
reg [LEN-1:0] data = INIT;
assign o_q = data[0];
assign o_par = data[LEN-1:1];
always @(posedge clk)
if (i_en)
data <= {i_d, data[LEN-1:1]};
endmodule