mirror of
https://github.com/olofk/serv.git
synced 2026-03-05 18:29:00 +00:00
jal, addi, lui, lb
This commit is contained in:
@@ -3,9 +3,9 @@ module serv_ctrl_tb;
|
||||
reg clk = 1'b1;
|
||||
|
||||
reg go;
|
||||
reg instr;
|
||||
reg jal;
|
||||
|
||||
wire en;
|
||||
wire jump;
|
||||
|
||||
wire [31:0] pc_data;
|
||||
wire pc_valid;
|
||||
reg pc_ready = 1'b1;
|
||||
@@ -24,20 +24,26 @@ module serv_ctrl_tb;
|
||||
|
||||
vlog_tb_utils vtu();
|
||||
|
||||
serv_decode decode
|
||||
(
|
||||
.clk (clk),
|
||||
.i_go (go),
|
||||
.i_instr (instruction),
|
||||
.o_ctrl_jump (jump),
|
||||
.o_ctrl_en (en),
|
||||
.o_imm (offset),
|
||||
.o_rd_from_ctrl ());
|
||||
|
||||
serv_ctrl
|
||||
#(.RESET_PC (32'h464))
|
||||
dut
|
||||
(
|
||||
.clk (clk),
|
||||
.i_go (go),
|
||||
.i_instr (instr),
|
||||
.i_jal (jal),
|
||||
.i_reg11 (reg11),
|
||||
.i_reg2012 (reg2012[0]),
|
||||
.o_reg2012_en (reg2012_en),
|
||||
.o_rd (rd),
|
||||
.o_rd_valid (rd_valid),
|
||||
.o_pc_data (pc_data),
|
||||
.clk (clk),
|
||||
.i_en (en),
|
||||
.i_jump (jump),
|
||||
.i_offset (offset),
|
||||
.o_rd (rd),
|
||||
.o_i_dat (pc_data),
|
||||
.o_pc_valid (pc_valid),
|
||||
.i_pc_ready (pc_ready));
|
||||
|
||||
@@ -48,17 +54,16 @@ module serv_ctrl_tb;
|
||||
|
||||
initial begin
|
||||
instruction = 32'h3d80006f;
|
||||
instruction = 32'h0080706f;
|
||||
reg11 = instruction[20];
|
||||
reg2012 = {instruction[31],instruction[19:12]};
|
||||
//instruction = 32'h0080706f;
|
||||
offset = {instruction[31],
|
||||
instruction[19:12],
|
||||
instruction[20],
|
||||
instruction[30:21],1'b0};
|
||||
|
||||
$display("Reconstructured offset %08x", offset);
|
||||
en <= 1'b1;
|
||||
for (idx=0;idx < 31;idx=idx+1) begin
|
||||
go <= (idx == 19); //Check this
|
||||
go <= (idx == 20); //Check this
|
||||
instr <= instruction[idx];
|
||||
jal <= (idx > 7);
|
||||
if (reg2012_en) reg2012 <= (reg2012 >> 1);
|
||||
|
||||
55
bench/serv_decode_tb.v
Normal file
55
bench/serv_decode_tb.v
Normal file
@@ -0,0 +1,55 @@
|
||||
`default_nettype none
|
||||
module serv_decode_tb;
|
||||
reg clk = 1'b1;
|
||||
|
||||
reg [31:0] i_rd_dat = 32'd0;
|
||||
reg i_rd_vld = 1'b0;
|
||||
wire i_rd_rdy;
|
||||
|
||||
wire ctrl_en;
|
||||
wire ctrl_jump;
|
||||
wire [4:0] rd_addr;
|
||||
wire [4:0] rs1_addr;
|
||||
wire [4:0] rs2_addr;
|
||||
wire imm;
|
||||
wire offset_source;
|
||||
wire [1:0] rd_source;
|
||||
|
||||
reg [31:0] tb_imm;
|
||||
|
||||
always #5 clk <= !clk;
|
||||
|
||||
vlog_tb_utils vtu();
|
||||
|
||||
serv_decode decode
|
||||
(
|
||||
.clk (clk),
|
||||
.i_i_rd_dat (i_rd_dat),
|
||||
.i_i_rd_vld (i_rd_vld),
|
||||
.o_i_rd_rdy (i_rd_rdy),
|
||||
.o_ctrl_en (ctrl_en),
|
||||
.o_ctrl_jump (ctrl_jump),
|
||||
.o_rf_rd_addr (rd_addr),
|
||||
.o_rf_rs1_addr (rs1_addr),
|
||||
.o_rf_rs2_addr (rs2_addr),
|
||||
.o_imm (imm),
|
||||
.o_offset_source (offset_source),
|
||||
.o_rd_source (rd_source));
|
||||
|
||||
initial begin
|
||||
@(posedge clk);
|
||||
i_rd_dat <= 32'h3d80006f;
|
||||
i_rd_vld <= 1'b1;
|
||||
@(posedge clk);
|
||||
@(posedge i_rd_rdy);
|
||||
@(posedge clk);
|
||||
$display("imm = %08x", tb_imm);
|
||||
|
||||
$finish;
|
||||
end
|
||||
always @(posedge clk) begin
|
||||
if (ctrl_en)
|
||||
tb_imm <= {imm, tb_imm[31:1]};
|
||||
end
|
||||
|
||||
endmodule
|
||||
92
bench/serv_top_tb.v
Normal file
92
bench/serv_top_tb.v
Normal file
@@ -0,0 +1,92 @@
|
||||
`default_nettype none
|
||||
module serv_top_tb;
|
||||
reg clk = 1'b1;
|
||||
|
||||
wire [31:0] i_ca_adr;
|
||||
wire i_ca_vld;
|
||||
wire i_ca_rdy;
|
||||
wire [31:0] i_rd_dat;
|
||||
wire i_rd_vld;
|
||||
wire i_rd_rdy;
|
||||
|
||||
wire d_ca_cmd;
|
||||
wire [31:0] d_ca_adr;
|
||||
wire d_ca_vld;
|
||||
wire d_ca_rdy;
|
||||
wire [31:0] d_dm_dat;
|
||||
wire [3:0] d_dm_msk;
|
||||
wire d_dm_vld;
|
||||
wire d_dm_rdy;
|
||||
wire [31:0] d_rd_dat;
|
||||
wire d_rd_vld;
|
||||
wire d_rd_rdy;
|
||||
|
||||
reg [1023:0] firmware_file;
|
||||
|
||||
reg [31:0] pc;
|
||||
reg [31:0] instruction;
|
||||
|
||||
always #5 clk <= !clk;
|
||||
|
||||
camd_ram
|
||||
#(.memfile ("firmware.hex"),
|
||||
.depth (16384*4))
|
||||
i_mem
|
||||
(.clk_i (clk),
|
||||
.rst_i (1'b0),
|
||||
.ca_adr_i (i_ca_adr),
|
||||
.ca_cmd_i (1'b0/*i_ca_cmd*/),
|
||||
.ca_vld_i (i_ca_vld),
|
||||
.ca_rdy_o (i_ca_rdy),
|
||||
.dm_dat_i (/*i_dm_dat*/),
|
||||
.dm_msk_i (/*i_dm_msk*/),
|
||||
.dm_vld_i (/*i_dm_vld*/),
|
||||
.dm_rdy_o (/*i_dm_rdy*/),
|
||||
.rd_dat_o (i_rd_dat),
|
||||
.rd_vld_o (i_rd_vld),
|
||||
.rd_rdy_i (i_rd_rdy));
|
||||
|
||||
camd_ram
|
||||
#(.memfile ("firmware.hex"),
|
||||
.depth (16384*4))
|
||||
d_mem
|
||||
(.clk_i (clk),
|
||||
.rst_i (1'b0),
|
||||
.ca_adr_i (d_ca_adr),
|
||||
.ca_cmd_i (d_ca_cmd),
|
||||
.ca_vld_i (d_ca_vld),
|
||||
.ca_rdy_o (d_ca_rdy),
|
||||
.dm_dat_i (d_dm_dat),
|
||||
.dm_msk_i (d_dm_msk),
|
||||
.dm_vld_i (d_dm_vld),
|
||||
.dm_rdy_o (d_dm_rdy),
|
||||
.rd_dat_o (d_rd_dat),
|
||||
.rd_vld_o (d_rd_vld),
|
||||
.rd_rdy_i (d_rd_rdy));
|
||||
|
||||
vlog_tb_utils vtu();
|
||||
|
||||
serv_top
|
||||
#(.RESET_PC (32'd8))
|
||||
dut
|
||||
(
|
||||
.clk (clk),
|
||||
.o_i_ca_adr (i_ca_adr),
|
||||
.o_i_ca_vld (i_ca_vld),
|
||||
.i_i_ca_rdy (i_ca_rdy),
|
||||
.i_i_rd_dat (i_rd_dat),
|
||||
.i_i_rd_vld (i_rd_vld),
|
||||
.o_i_rd_rdy (i_rd_rdy),
|
||||
.o_d_ca_cmd (d_ca_cmd),
|
||||
.o_d_ca_adr (d_ca_adr),
|
||||
.o_d_ca_vld (d_ca_vld),
|
||||
.i_d_ca_rdy (d_ca_rdy),
|
||||
.o_d_dm_dat (d_dm_dat),
|
||||
.o_d_dm_msk (d_dm_msk),
|
||||
.o_d_dm_vld (d_dm_vld),
|
||||
.i_d_dm_rdy (d_dm_rdy),
|
||||
.i_d_rd_dat (d_rd_dat),
|
||||
.i_d_rd_vld (d_rd_vld),
|
||||
.o_d_rd_rdy (d_rd_rdy));
|
||||
|
||||
endmodule
|
||||
0
data/dummy.pcf
Normal file
0
data/dummy.pcf
Normal file
55
rtl/camd_ram.v
Normal file
55
rtl/camd_ram.v
Normal file
@@ -0,0 +1,55 @@
|
||||
module camd_ram
|
||||
#(//camd parameters
|
||||
parameter AW = 32,
|
||||
parameter DW = 32,
|
||||
//Memory parameters
|
||||
parameter depth = 256,
|
||||
parameter aw = $clog2(depth),
|
||||
parameter memfile = "")
|
||||
(input clk_i,
|
||||
input rst_i,
|
||||
|
||||
input [AW-1:0] ca_adr_i, //FIXME width = AW-clog2(WB_DW/8)
|
||||
input ca_cmd_i,
|
||||
input ca_vld_i,
|
||||
output ca_rdy_o,
|
||||
|
||||
input [DW-1:0] dm_dat_i,
|
||||
input [DW/8-1:0] dm_msk_i,
|
||||
input dm_vld_i,
|
||||
output dm_rdy_o,
|
||||
|
||||
output [DW-1:0] rd_dat_o,
|
||||
output reg rd_vld_o,
|
||||
input rd_rdy_i);
|
||||
|
||||
wire ca_en = ca_vld_i & ca_rdy_o;
|
||||
wire dm_en = dm_vld_i & dm_rdy_o;
|
||||
wire ram_we = ca_en & dm_en;
|
||||
|
||||
assign ca_rdy_o = 1'b1;
|
||||
assign dm_rdy_o = 1'b1;
|
||||
|
||||
wire [aw-1:2] raddr;
|
||||
reg [aw-1:2] latched_raddr;
|
||||
assign raddr = ca_en ? ca_adr_i[aw-1:2] : latched_raddr;
|
||||
|
||||
always @(posedge clk_i) begin
|
||||
if (ca_en)
|
||||
latched_raddr <= ca_adr_i[aw-1:2];
|
||||
rd_vld_o <= 1'b0;
|
||||
if (ca_en & !ca_cmd_i)
|
||||
rd_vld_o <= 1'b1;
|
||||
end
|
||||
wb_ram_generic
|
||||
#(.depth(depth/4),
|
||||
.memfile (memfile))
|
||||
ram0
|
||||
(.clk (clk_i),
|
||||
.we ({4{ram_we}} & dm_msk_i),
|
||||
.din (dm_dat_i),
|
||||
.waddr (ca_adr_i[aw-1:2]),
|
||||
.raddr (raddr),
|
||||
.dout (rd_dat_o));
|
||||
|
||||
endmodule
|
||||
@@ -1,17 +1,15 @@
|
||||
module ser_add
|
||||
(
|
||||
input clk,
|
||||
input a,
|
||||
input b,
|
||||
input clear,
|
||||
output reg q = 1'b0);
|
||||
input clk,
|
||||
input a,
|
||||
input b,
|
||||
input clr,
|
||||
output q);
|
||||
|
||||
reg carry = 1'b0;
|
||||
wire c = carry & ~clear;
|
||||
reg c = 1'b0;
|
||||
|
||||
always @(posedge clk) begin
|
||||
q <= a ^ b ^ c;
|
||||
carry <= a&b | a&c | b&c;
|
||||
end
|
||||
assign q = a ^ b ^ c;
|
||||
always @(posedge clk)
|
||||
c <= !clr & (a&b | a&c | b&c);
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
`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);
|
||||
input clk,
|
||||
input i_en,
|
||||
input [2:0] i_funct3,
|
||||
input i_rs1,
|
||||
input i_op_b,
|
||||
output o_rd);
|
||||
|
||||
localparam [2:0]
|
||||
ADDI = 3'b000,
|
||||
@@ -18,52 +16,17 @@ module serv_alu
|
||||
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));
|
||||
.clk (clk),
|
||||
.a (i_rs1),
|
||||
.b (i_op_b),
|
||||
.clr (!i_en),
|
||||
.q (result_add));
|
||||
|
||||
assign o_rd = (funct3 == ADDI) ? result_add : 1'b0;
|
||||
assign o_rd_valid = (cnt > 0);
|
||||
assign o_rd = (i_funct3 == ADDI) ? result_add : 1'b0;
|
||||
|
||||
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
|
||||
|
||||
|
||||
125
rtl/serv_ctrl.v
125
rtl/serv_ctrl.v
@@ -2,56 +2,36 @@
|
||||
module serv_ctrl
|
||||
(
|
||||
input clk,
|
||||
input i_go,
|
||||
input i_instr,
|
||||
input i_jal,
|
||||
input i_reg11,
|
||||
input i_reg2012,
|
||||
output o_reg2012_en,
|
||||
input i_en,
|
||||
input i_jump,
|
||||
input i_offset,
|
||||
output o_rd,
|
||||
output o_rd_valid,
|
||||
output [31:0] o_pc_data,
|
||||
output reg o_pc_valid = 1'b1,
|
||||
input i_pc_ready);
|
||||
output [31:0] o_i_ca_adr,
|
||||
output reg o_i_ca_vld = 1'b0,
|
||||
input i_i_ca_rdy);
|
||||
|
||||
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 pc;
|
||||
|
||||
wire new_pc;
|
||||
|
||||
reg [2:0] offset_source;
|
||||
|
||||
assign pc_plus_4_clr = (cnt == 0);
|
||||
assign plus_4 = (cnt == 2);
|
||||
assign plus_4 = en_2r & !en_3r;
|
||||
|
||||
assign o_i_ca_adr[0] = pc;
|
||||
|
||||
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));
|
||||
.clk (clk),
|
||||
.a (pc),
|
||||
.b (plus_4),
|
||||
.clr (!i_en),
|
||||
.q (pc_plus_4));
|
||||
|
||||
shift_reg
|
||||
#(
|
||||
@@ -60,71 +40,36 @@ module serv_ctrl
|
||||
pc_reg
|
||||
(
|
||||
.clk (clk),
|
||||
.i_en (running),
|
||||
.i_en (i_en),
|
||||
.i_d (new_pc),
|
||||
.o_q (o_pc_data[0]),
|
||||
.o_par (o_pc_data[31:1])
|
||||
.o_q (pc),
|
||||
.o_par (o_i_ca_adr[31:1])
|
||||
);
|
||||
|
||||
assign new_pc = new_pc_sel ? pc_plus_offset : pc_plus_4;
|
||||
|
||||
assign new_pc = i_jump ? 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));
|
||||
.clk (clk),
|
||||
.a (pc),
|
||||
.b (i_offset),
|
||||
.clr (!i_en),
|
||||
.q (pc_plus_offset));
|
||||
|
||||
reg done = 1'b0;
|
||||
reg en_r = 1'b1;
|
||||
reg en_2r = 1'b0;
|
||||
reg en_3r = 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
|
||||
en_r <= i_en;
|
||||
en_2r <= en_r;
|
||||
en_3r <= en_2r;
|
||||
|
||||
if (done)
|
||||
o_pc_valid <= 1'b1;
|
||||
if (o_pc_valid & i_pc_ready)
|
||||
o_pc_valid <= 1'b0;
|
||||
if (en_r & !i_en)
|
||||
o_i_ca_vld <= 1'b1;
|
||||
else if (o_i_ca_vld & i_i_ca_rdy)
|
||||
o_i_ca_vld <= 1'b0;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -1,67 +1,129 @@
|
||||
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);
|
||||
input clk,
|
||||
input [31:0] i_i_rd_dat,
|
||||
input i_i_rd_vld,
|
||||
output reg o_i_rd_rdy = 1'b1,
|
||||
output o_ctrl_en,
|
||||
output o_ctrl_jump,
|
||||
output [2:0] o_funct3,
|
||||
output o_rf_rd_en,
|
||||
output [4:0] o_rf_rd_addr,
|
||||
output o_rf_rs_en,
|
||||
output [4:0] o_rf_rs1_addr,
|
||||
output [4:0] o_rf_rs2_addr,
|
||||
output o_mem_en,
|
||||
output o_mem_init,
|
||||
output o_mem_dat_valid,
|
||||
input i_mem_busy,
|
||||
output reg o_imm,
|
||||
output o_offset_source,
|
||||
output o_op_b_source,
|
||||
output [1:0] o_rd_source);
|
||||
|
||||
`include "serv_params.vh"
|
||||
|
||||
|
||||
localparam [1:0]
|
||||
IDLE = 2'd0,
|
||||
MEM_INIT = 2'd1,
|
||||
MEM_WAIT = 2'd2,
|
||||
RUN = 2'd3;
|
||||
|
||||
localparam [4:0]
|
||||
OP_LOAD = 5'b00000,
|
||||
OP_OPIMM = 5'b00100,
|
||||
OP_LUI = 5'b01101,
|
||||
OP_JAL = 5'b11011;
|
||||
|
||||
reg [1:0] state = 2'd0;
|
||||
|
||||
reg [8:0] barrel [0:31];
|
||||
reg [4:0] cnt = 5'd0;
|
||||
reg running = 1'b0;
|
||||
reg [4:0] cnt = 5'd0;
|
||||
|
||||
wire opcode_valid;
|
||||
wire halt;
|
||||
wire running;
|
||||
wire mem_op;
|
||||
assign mem_op = (opcode == OP_LOAD);
|
||||
|
||||
assign o_ctrl_en = running;
|
||||
assign o_ctrl_jump = (opcode == OP_JAL);
|
||||
|
||||
assign o_rf_rd_en = running & ((opcode == OP_JAL) |
|
||||
(opcode == OP_OPIMM) |
|
||||
(opcode == OP_LUI));
|
||||
assign o_rf_rs_en = (running & (opcode == OP_OPIMM)) |
|
||||
(state == MEM_INIT);
|
||||
assign o_mem_en = mem_op & cnt_en;
|
||||
assign o_mem_init = (state == MEM_INIT);
|
||||
|
||||
assign o_rf_rd_addr = i_i_rd_dat[11:7];
|
||||
assign o_funct3 = i_i_rd_dat[14:12];
|
||||
assign o_rf_rs1_addr = i_i_rd_dat[19:15];
|
||||
assign o_rf_rs2_addr = i_i_rd_dat[24:20];
|
||||
assign o_offset_source = (opcode == OP_JAL) ? OFFSET_SOURCE_IMM : 1'b0;
|
||||
|
||||
assign o_op_b_source = (opcode == OP_OPIMM) ? OP_B_SOURCE_IMM : 1'b0;
|
||||
|
||||
assign o_mem_dat_valid = (o_funct3[1:0] == 2'b00) ? cnt < 8 :
|
||||
(o_funct3[1:0] == 2'b01) ? cnt < 16 : 1'b1;
|
||||
|
||||
wire [4:0] opcode = i_i_rd_dat[6:2];
|
||||
|
||||
wire [8:0] cur = barrel[cnt];
|
||||
|
||||
assign o_rd_source = (opcode == OP_JAL) ? RD_SOURCE_CTRL :
|
||||
(opcode == OP_OPIMM) ? RD_SOURCE_ALU :
|
||||
(opcode == OP_LUI) ? RD_SOURCE_IMM : 2'b00;
|
||||
|
||||
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);
|
||||
always @(cnt, opcode) begin
|
||||
o_imm = 1'bx;
|
||||
if (opcode == OP_JAL)
|
||||
if (cnt > 19) o_imm = i_i_rd_dat[31];
|
||||
else if (cnt > 11) o_imm = i_i_rd_dat[cnt];
|
||||
else if (cnt > 10) o_imm = i_i_rd_dat[20];
|
||||
else if (cnt > 0) o_imm = i_i_rd_dat[cnt+20];
|
||||
else o_imm = 1'b0;
|
||||
else if (opcode == OP_OPIMM)
|
||||
if (cnt > 10) o_imm = i_i_rd_dat[31];
|
||||
else o_imm = i_i_rd_dat[cnt+20];
|
||||
else if (opcode == OP_LUI)
|
||||
if (cnt > 11) o_imm = i_i_rd_dat[cnt];
|
||||
else o_imm = 1'b0;
|
||||
else if (opcode == OP_LOAD)
|
||||
if (cnt > 10) o_imm = i_i_rd_dat[31];
|
||||
else o_imm = i_i_rd_dat[cnt+20];
|
||||
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);
|
||||
wire go = i_i_rd_vld & o_i_rd_rdy;
|
||||
|
||||
wire cnt_en = (state == RUN) | (state == MEM_INIT);
|
||||
|
||||
wire cnt_done = cnt == 31;
|
||||
assign running = (state == RUN);
|
||||
|
||||
// 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;
|
||||
state <= state;
|
||||
case (state)
|
||||
IDLE : begin
|
||||
if (go)
|
||||
state <= mem_op ? MEM_INIT : RUN;
|
||||
end
|
||||
MEM_INIT :
|
||||
if (cnt_done)
|
||||
state <= MEM_WAIT;
|
||||
MEM_WAIT :
|
||||
if (!i_mem_busy)
|
||||
state <= RUN;
|
||||
RUN : begin
|
||||
if (cnt_done)
|
||||
state <= IDLE;
|
||||
end
|
||||
endcase
|
||||
|
||||
cnt <= cnt + {4'd0,cnt_en};
|
||||
|
||||
if (go) begin
|
||||
o_i_rd_rdy <= 1'b0;
|
||||
end else if (cnt_done & (state == RUN)) begin
|
||||
o_i_rd_rdy <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
87
rtl/serv_mem_if.v
Normal file
87
rtl/serv_mem_if.v
Normal file
@@ -0,0 +1,87 @@
|
||||
`default_nettype none
|
||||
module serv_mem_if
|
||||
(
|
||||
input i_clk,
|
||||
input i_en,
|
||||
input i_init,
|
||||
input i_dat_valid,
|
||||
input i_cmd,
|
||||
input [2:0] i_funct3,
|
||||
input i_rs1,
|
||||
input i_rs2,
|
||||
input i_imm,
|
||||
output o_rd,
|
||||
output reg o_busy = 1'b0,
|
||||
//External interface
|
||||
output o_d_ca_cmd,
|
||||
output [31:0] o_d_ca_adr,
|
||||
output reg o_d_ca_vld = 1'b0,
|
||||
input i_d_ca_rdy,
|
||||
output [31:0] o_d_dm_dat,
|
||||
output [3:0] o_d_dm_msk,
|
||||
output o_d_dm_vld,
|
||||
input i_d_dm_rdy,
|
||||
input [31:0] i_d_rd_dat,
|
||||
input i_d_rd_vld,
|
||||
output o_d_rd_rdy);
|
||||
|
||||
reg en_r;
|
||||
wire adr;
|
||||
reg [31:0] dat = 32'd0;
|
||||
reg signbit = 1'b0;
|
||||
|
||||
ser_add ser_add_rs1_plus_imm
|
||||
(
|
||||
.clk (i_clk),
|
||||
.a (i_rs1),
|
||||
.b (i_imm),
|
||||
.clr (!i_en),
|
||||
.q (adr));
|
||||
|
||||
shift_reg #(32) shift_reg_adr
|
||||
(
|
||||
.clk (i_clk),
|
||||
.i_en (i_en),
|
||||
.i_d (adr),
|
||||
.o_q (o_d_ca_adr[0]),
|
||||
.o_par (o_d_ca_adr[31:1])
|
||||
);
|
||||
|
||||
assign o_d_ca_cmd = i_cmd;
|
||||
|
||||
wire is_signed = i_funct3[2];
|
||||
assign o_rd = i_dat_valid ? dat[0] : is_signed & signbit;
|
||||
|
||||
assign o_d_rd_rdy = !i_en; //Likely bug, but probably doesn't matter
|
||||
|
||||
wire is_half = i_funct3[1];
|
||||
wire is_byte = !(|i_funct3[1:0]);
|
||||
wire [1:0] bytepos = o_d_ca_adr[3:2];
|
||||
wire upper_half = bytepos[1];
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
signbit <= dat[0];
|
||||
|
||||
if (i_en & i_init)
|
||||
o_busy <= 1'b1;
|
||||
else if (i_d_rd_vld & o_d_rd_rdy) begin
|
||||
dat[31:16] <= i_d_rd_dat[31:16];
|
||||
dat[15:8] <= (is_half & upper_half) ? i_d_rd_dat[31:24] : i_d_rd_dat[15:8];
|
||||
dat[7:0] <= (is_byte & (bytepos == 2'b11)) ? i_d_rd_dat[31:24] :
|
||||
(is_byte & (bytepos == 2'b10)) ? i_d_rd_dat[23:16] :
|
||||
(is_half & upper_half) ? i_d_rd_dat[23:16] :
|
||||
(is_byte & (bytepos == 2'b01)) ? i_d_rd_dat[15:8] :
|
||||
i_d_rd_dat[7:0];
|
||||
o_busy <= 1'b0;
|
||||
end
|
||||
|
||||
en_r <= i_en;
|
||||
if (o_d_ca_vld & i_d_ca_rdy)
|
||||
o_d_ca_vld <= 1'b0;
|
||||
else if (en_r & !i_en)
|
||||
o_d_ca_vld <= 1'b1;
|
||||
|
||||
if (i_en)
|
||||
dat <= {i_rs2,dat[31:1]};
|
||||
end
|
||||
endmodule
|
||||
14
rtl/serv_params.vh
Normal file
14
rtl/serv_params.vh
Normal file
@@ -0,0 +1,14 @@
|
||||
localparam [1:0]
|
||||
RD_SOURCE_CTRL = 2'd0,
|
||||
RD_SOURCE_ALU = 2'd1,
|
||||
RD_SOURCE_IMM = 2'd2,
|
||||
RD_SOURCE_MEM = 2'd3;
|
||||
|
||||
localparam [0:0]
|
||||
OFFSET_SOURCE_IMM = 1'd0,
|
||||
OFFSET_SOURCE_RD = 1'd1;
|
||||
|
||||
localparam [0:0]
|
||||
OP_B_SOURCE_IMM = 1'd0,
|
||||
OP_B_SOURCE_RS2 = 1'd1;
|
||||
|
||||
@@ -1,34 +1,20 @@
|
||||
`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);
|
||||
input i_clk,
|
||||
input i_rd_en,
|
||||
input [4:0] i_rd_addr,
|
||||
input i_rd,
|
||||
input [4:0] i_rs1_addr,
|
||||
input [4:0] i_rs2_addr,
|
||||
input i_rs_en,
|
||||
output o_rs1,
|
||||
output o_rs2);
|
||||
|
||||
reg [31:0] rf [0:31];
|
||||
//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 @(*)
|
||||
`ifndef SYNTHESIS
|
||||
/* always @(*)
|
||||
for (i=0;i<32;i=i+1) begin
|
||||
dbg_x1[i] = rf[i][1];
|
||||
dbg_x2[i] = rf[i][2];
|
||||
@@ -62,7 +48,7 @@ module serv_regfile
|
||||
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 ;
|
||||
@@ -96,52 +82,62 @@ module serv_regfile
|
||||
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;
|
||||
// initial for (i=0; i<32; i=i+1) rf[i] = 0;
|
||||
`endif
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (i_rd_valid) begin
|
||||
reg [4:0] raddr = 5'd1;
|
||||
reg [4:0] waddr = 5'd0;
|
||||
// reg [31:0] rs = 32'd0;
|
||||
wire [31:0] rs;
|
||||
|
||||
reg [31:0] mask;
|
||||
|
||||
always @(i_rd_addr)
|
||||
mask = ~(1 << i_rd_addr);
|
||||
|
||||
SB_RAM40_4K rf0
|
||||
(
|
||||
.RDATA (rs[15:0]),
|
||||
.RCLK (i_clk),
|
||||
.RCLKE (1'b1),
|
||||
.RE (1'b1),
|
||||
.RADDR ({6'd0,raddr2}),
|
||||
.WCLK (i_clk),
|
||||
.WCLKE (1'b1),
|
||||
.WE (i_rd_en),
|
||||
.WADDR ({6'd0,waddr}),
|
||||
.MASK (mask[15:0]),
|
||||
.WDATA ({16{i_rd}})
|
||||
);
|
||||
|
||||
SB_RAM40_4K rf1
|
||||
(
|
||||
.RDATA (rs[31:16]),
|
||||
.RCLK (i_clk),
|
||||
.RCLKE (1'b1),
|
||||
.RE (1'b1),
|
||||
.RADDR ({6'd0,raddr2}),
|
||||
.WCLK (i_clk),
|
||||
.WCLKE (1'b1),
|
||||
.WE (i_rd_en),
|
||||
.WADDR ({6'd0,waddr}),
|
||||
.MASK (mask[31:16]),
|
||||
.WDATA ({16{i_rd}})
|
||||
);
|
||||
always @(posedge i_clk) begin
|
||||
if (i_rd_en) begin
|
||||
waddr <= waddr + 1;
|
||||
rf[waddr][rd_addr] <= i_rd;
|
||||
//rf[waddr][i_rd_addr] <= i_rd;
|
||||
end
|
||||
|
||||
if (i_rs_en)
|
||||
rs <= rf[raddr];
|
||||
|
||||
raddr <= raddr + 1;
|
||||
//rs <= rf[raddr2];
|
||||
end
|
||||
|
||||
wire [4:0] rs1_addr;
|
||||
wire [4:0] rs2_addr;
|
||||
wire [4:0] rd_addr;
|
||||
wire [4:0] raddr2 = raddr & {5{i_rs_en}};
|
||||
|
||||
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;
|
||||
assign o_rs1 = (|i_rs1_addr) ? rs[i_rs1_addr] : 1'b0;
|
||||
assign o_rs2 = (|i_rs2_addr) ? rs[i_rs2_addr] : 1'b0;
|
||||
|
||||
endmodule
|
||||
|
||||
235
rtl/serv_top.v
235
rtl/serv_top.v
@@ -2,125 +2,154 @@
|
||||
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);
|
||||
output [31:0] o_i_ca_adr,
|
||||
output o_i_ca_vld,
|
||||
input i_i_ca_rdy,
|
||||
input [31:0] i_i_rd_dat,
|
||||
input i_i_rd_vld,
|
||||
output o_i_rd_rdy,
|
||||
output o_d_ca_cmd,
|
||||
output [31:0] o_d_ca_adr,
|
||||
output o_d_ca_vld,
|
||||
input i_d_ca_rdy,
|
||||
output [31:0] o_d_dm_dat,
|
||||
output [3:0] o_d_dm_msk,
|
||||
output o_d_dm_vld,
|
||||
input i_d_dm_rdy,
|
||||
input [31:0] i_d_rd_dat,
|
||||
input i_d_rd_vld,
|
||||
output o_d_rd_rdy);
|
||||
|
||||
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;
|
||||
`include "serv_params.vh"
|
||||
|
||||
wire ctrl_rd;
|
||||
wire ctrl_rd_valid;
|
||||
wire [4:0] rd_addr;
|
||||
wire [4:0] rs1_addr;
|
||||
wire [4:0] rs2_addr;
|
||||
|
||||
wire alu_rd;
|
||||
wire alu_rd_valid;
|
||||
wire [1:0] rd_source;
|
||||
wire ctrl_rd;
|
||||
wire alu_rd;
|
||||
wire mem_rd;
|
||||
wire rd;
|
||||
|
||||
wire funct3_valid;
|
||||
wire ctrl_en;
|
||||
wire jump;
|
||||
wire offset;
|
||||
wire offset_source;
|
||||
wire imm;
|
||||
|
||||
wire [2:0] funct3;
|
||||
|
||||
wire jal;
|
||||
wire opimm;
|
||||
wire rs1;
|
||||
wire rs2;
|
||||
wire rs_en;
|
||||
wire rd_en;
|
||||
|
||||
wire op_b_source;
|
||||
wire op_b;
|
||||
|
||||
wire mem_en;
|
||||
|
||||
wire mem_cmd = 1'b0 /*FIXME*/;
|
||||
wire mem_dat_valid;
|
||||
|
||||
wire mem_init;
|
||||
wire mem_busy;
|
||||
|
||||
parameter RESET_PC = 32'd8;
|
||||
|
||||
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));
|
||||
.i_i_rd_dat (i_i_rd_dat),
|
||||
.i_i_rd_vld (i_i_rd_vld),
|
||||
.o_i_rd_rdy (o_i_rd_rdy),
|
||||
.o_ctrl_en (ctrl_en),
|
||||
.o_ctrl_jump (jump),
|
||||
.o_funct3 (funct3),
|
||||
.o_rf_rd_en (rd_en),
|
||||
.o_rf_rd_addr (rd_addr),
|
||||
.o_rf_rs_en (rs_en),
|
||||
.o_rf_rs1_addr (rs1_addr),
|
||||
.o_rf_rs2_addr (rs2_addr),
|
||||
.o_mem_en (mem_en),
|
||||
.o_mem_init (mem_init),
|
||||
.o_mem_dat_valid (mem_dat_valid),
|
||||
.i_mem_busy (mem_busy),
|
||||
.o_imm (imm),
|
||||
.o_offset_source (offset_source),
|
||||
.o_op_b_source (op_b_source),
|
||||
.o_rd_source (rd_source));
|
||||
|
||||
serv_ctrl
|
||||
#(.RESET_PC (RESET_PC))
|
||||
ctrl
|
||||
(
|
||||
.clk (clk),
|
||||
.i_en (ctrl_en),
|
||||
.i_jump (jump),
|
||||
.i_offset (offset),
|
||||
.o_rd (ctrl_rd),
|
||||
.o_i_ca_adr (o_i_ca_adr),
|
||||
.o_i_ca_vld (o_i_ca_vld),
|
||||
.i_i_ca_rdy (i_i_ca_rdy));
|
||||
|
||||
assign offset = (offset_source == OFFSET_SOURCE_IMM) ? imm : rs1;
|
||||
|
||||
assign rd = (rd_source == RD_SOURCE_CTRL) ? ctrl_rd :
|
||||
(rd_source == RD_SOURCE_ALU) ? alu_rd :
|
||||
(rd_source == RD_SOURCE_IMM) ? imm :
|
||||
(rd_source == RD_SOURCE_MEM) ? mem_rd : 1'b0;
|
||||
|
||||
|
||||
assign op_b = (op_b_source == OP_B_SOURCE_IMM) ? imm :
|
||||
1'b0;
|
||||
|
||||
serv_alu alu
|
||||
(
|
||||
.clk (clk),
|
||||
.i_go (alu_go),
|
||||
.i_d (cur_instr[0]),
|
||||
.i_funct3_valid (funct3_valid),
|
||||
.i_en (ctrl_en), /*FIXME: Is this true?*/
|
||||
.i_funct3 (funct3),
|
||||
.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));
|
||||
.i_op_b (op_b),
|
||||
.o_rd (alu_rd));
|
||||
|
||||
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));
|
||||
.i_clk (clk),
|
||||
.i_rd_en (rd_en),
|
||||
.i_rd_addr (rd_addr),
|
||||
.i_rd (rd),
|
||||
.i_rs1_addr (rs1_addr),
|
||||
.i_rs2_addr (rs2_addr),
|
||||
.i_rs_en (rs_en),
|
||||
.o_rs1 (rs1),
|
||||
.o_rs2 (rs2));
|
||||
|
||||
serv_mem_if mem_if
|
||||
(
|
||||
.i_clk (clk),
|
||||
.i_en (mem_en),
|
||||
.i_init (mem_init),
|
||||
.i_dat_valid (mem_dat_valid),
|
||||
.i_cmd (mem_cmd),
|
||||
.i_funct3 (funct3),
|
||||
.i_rs1 (rs1),
|
||||
.i_rs2 (rs2),
|
||||
.i_imm (imm),
|
||||
.o_rd (mem_rd),
|
||||
.o_busy (mem_busy),
|
||||
//External interface
|
||||
.o_d_ca_cmd (o_d_ca_cmd),
|
||||
.o_d_ca_adr (o_d_ca_adr),
|
||||
.o_d_ca_vld (o_d_ca_vld),
|
||||
.i_d_ca_rdy (i_d_ca_rdy),
|
||||
.o_d_dm_dat (o_d_dm_dat),
|
||||
.o_d_dm_msk (o_d_dm_msk),
|
||||
.o_d_dm_vld (o_d_dm_vld),
|
||||
.i_d_dm_rdy (i_d_dm_rdy),
|
||||
.i_d_rd_dat (i_d_rd_dat),
|
||||
.i_d_rd_vld (i_d_rd_vld),
|
||||
.o_d_rd_rdy (o_d_rd_rdy));
|
||||
|
||||
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
|
||||
|
||||
32
serv.core
32
serv.core
@@ -5,14 +5,18 @@ name : ::serv:0
|
||||
filesets:
|
||||
core:
|
||||
files:
|
||||
- rtl/camd_ram.v
|
||||
- rtl/serv_params.vh : {is_include_file : true}
|
||||
- rtl/shift_reg.v
|
||||
- rtl/ser_add.v
|
||||
- rtl/serv_alu.v
|
||||
- rtl/serv_decode.v
|
||||
- rtl/serv_ctrl.v
|
||||
- rtl/serv_decode.v
|
||||
- rtl/serv_mem_if.v
|
||||
- rtl/serv_regfile.v
|
||||
- rtl/serv_top.v
|
||||
file_type : verilogSource
|
||||
depend : [wb_ram]
|
||||
|
||||
ser_add_tb:
|
||||
files:
|
||||
@@ -25,20 +29,35 @@ filesets:
|
||||
- bench/serv_ctrl_tb.v : {file_type : verilogSource}
|
||||
depend : [vlog_tb_utils]
|
||||
|
||||
serv_decode_tb:
|
||||
files: [bench/serv_decode_tb.v : {file_type : verilogSource}]
|
||||
depend : [vlog_tb_utils]
|
||||
serv_top_tb:
|
||||
files:
|
||||
- firmware.hex : {copyto : firmware.hex, file_type : user}
|
||||
- decode.mem : {copyto : decode.mem, file_type : user}
|
||||
- serv_top_tb.v
|
||||
- bench/serv_top_tb.v
|
||||
file_type : verilogSource
|
||||
depend : [vlog_tb_utils]
|
||||
depend : [vlog_tb_utils, "yosys:techlibs:ice40"]
|
||||
|
||||
pcf:
|
||||
files: [data/dummy.pcf : {file_type : PCF}]
|
||||
targets:
|
||||
default:
|
||||
default_tool : icarus
|
||||
filesets : [core, tb]
|
||||
toplevel : serv_top_tb
|
||||
|
||||
synth:
|
||||
default_tool : icestorm
|
||||
filesets : [core, pcf]
|
||||
toplevel : serv_top
|
||||
lint:
|
||||
default_tool : verilator
|
||||
filesets : [core]
|
||||
tools:
|
||||
verilator:
|
||||
mode : lint-only
|
||||
toplevel : serv_top
|
||||
ser_add_tb:
|
||||
default_tool : icarus
|
||||
filesets: [core, ser_add_tb]
|
||||
@@ -49,6 +68,11 @@ targets:
|
||||
filesets : [core, serv_ctrl_tb]
|
||||
toplevel : serv_ctrl_tb
|
||||
|
||||
serv_decode_tb:
|
||||
default_tool: icarus
|
||||
filesets : [core, serv_decode_tb]
|
||||
toplevel : serv_decode_tb
|
||||
|
||||
serv_top_tb:
|
||||
default_tool: icarus
|
||||
filesets : [core, serv_top_tb]
|
||||
|
||||
Reference in New Issue
Block a user