Commit 014209e9 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

code cleanup & relicensing

parent 695e8467
sim_tool = "modelsim"
top_module="main"
syn_device="xc6slx150t"
action = "simulation"
target = "xilinx"
include_dirs=["."]
files = [ "rv_cpu.v",
"rv_exec.v",
"rv_fetch.v",
"rv_predecode.v",
"rv_regfile.v",
"rv_writeback.v",
"rv_shifter.v",
"rv_multiply.v",
"rv_divide.v",
"rv_csr.v",
"rv_timer.v",
"rv_exceptions.v",
files = [ "urv_cpu.v",
"urv_exec.v",
"urv_fetch.v",
"urv_decode.v",
"urv_regfile.v",
"urv_writeback.v",
"urv_shifter.v",
"urv_multiply.v",
"urv_divide.v",
"urv_csr.v",
"urv_timer.v",
"urv_exceptions.v",
"urv_iram.v",
"xrv_core.vhd" ];
"xurv_core.vhd" ];
# "../sim/rv_icache_model.sv"];
This diff is collapsed.
/*
uRV - a tiny and dumb RISC-V core
Copyright (c) 2015 twl <twlostow@printf.cc>.
Copyright (c) 2015 CERN
Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
......@@ -18,11 +19,11 @@
*/
`include "rv_defs.v"
`include "urv_defs.v"
`timescale 1ns/1ps
module rv_csr
module urv_csr
(
input clk_i,
input rst_i,
......
`timescale 1ns/1ps
`include "urv_defs.v"
module urv_debug
(
input clk_i,
input rst_i,
input x_kill_i,
input x_stall_i,
output x_stall_req_o,
output d_kill_req_o,
output f_kill_req_o,
output halt_o,
input x_valid_i,
input [31:0] x_pc_i,
input x_dm_load_i,
input x_dm_store_i,
input [31:0] x_dm_addr_i,
input [31:0] x_dm_data_s_i,
input [3:0] x_dm_data_select_i,
output [31:0] w_dm_data_l_o,
output w_dm_store_done_o,
output w_dm_load_done_o,
output x_dm_ready_o,
output dm_load_o,
output dm_store_o,
output [31:0] dm_addr_o,
output [31:0] dm_data_s_o,
output [3:0] dm_data_select_o,
input [31:0] dm_data_l_i,
input dm_store_done_i,
input dm_load_done_i,
input dm_ready_i,
output [4:0] rf_index_o,
input [31:0] rf_data_r_i
output [31:0] rf_data_w_o,
output rf_write_o,
output [31:0] f_pc_restore_o,
output f_pc_restore_load_o,
input [6:0] dbg_adr_i,
input [7:0] dbg_dat_i,
input dbg_stb_i,
input dbg_we_i,
output [7:0] dbg_dat_o,
output dbg_irq_o
);
parameter g_num_breakpoints = 4;
`define BREAK_SRC_PC 0
`define BREAK_SRC_MEM_ADDR 1
`define BREAK_SRC_MEM_ST_DATA 2
`define BREAK_SRC_MEM_LD_DATA 3
reg [31:0] break_compare_hi [0:g_num_breakpoints-1];
reg [31:0] break_compare_lo [0:g_num_breakpoints-1];
reg [1:0] break_src [0:g_num_breakpoints-1];
reg break_valid[0:g_num_breakpoints-1];
reg [31:0] in_muxed[0 : g_num_breakpoints-1];
reg in_valid[0:g_num_breakpoints-1];
reg break_hit[0: g_num_breakpoints-1];
`define ST_IDLE 0
generate
genvar gg;
for (gg = 0; gg < g_num_breakpoints; gg = gg + 1)
begin
always@*
case (break_src[gg])
`BREAK_SRC_PC: in_muxed[gg] <= x_pc_i;
`BREAK_SRC_MEM_ADDR: in_muxed[gg] <= x_dm_addr_i;
`BREAK_SRC_MEM_ST_DATA: in_muxed[gg] <= x_dm_data_s_i;
`BREAK_SRC_MEM_ST_DATA: in_muxed[gg] <= dm_data_l_i;
endcase // case (break_src[gg])
case (break_src[gg])
`BREAK_SRC_PC:
begin
in_muxed[gg] <= x_pc_i;
in_valid[gg] <= x_valid_i;
end
`BREAK_SRC_MEM_ADDR:
begin
in_muxed[gg] <= x_dm_addr_i;
in_valid[gg] <= x_dm_load_i || x_dm_store_i;
end
`BREAK_SRC_MEM_ST_DATA:
begin
in_muxed[gg] <= x_dm_data_s_i;
in_valid[gg] <= x_dm_store_i;
end
`BREAK_SRC_MEM_LD_DATA:
begin
in_muxed[gg] <= dm_data_l_i;
in_valid[gg] <= dm_load_done_i;
end
endcase // case (break_src[gg])
break_hit[gg] <= ( in_muxed[gg] >= break_comp1[gg] && in_muxed[gg] <= break_comp[gg] ) ? in_valid[gg] : 1'b0;
end
endgenerate
reg trigger_reload_pc;
reg trigger_halt;
reg trigger_resume;
reg [31:0] reload_pc_value;
`define DBG_REG_PC0 0
`define DBG_REG_PC1 1
`define DBG_REG_PC2 2
`define DBG_REG_PC3 3
always@(posedge clk_i)
if(rst_i) begin
reload_pc <= 0;
end else begin
trigger_halt <= 0;
trigger_resume <= 0;
trigger_reload_pc <= 0;
if ( dbg_we_i ) begin
case (dbg_adr_i)
`DBG_REG_PCO: reload_pc_value[7:0] <= dbg_dat_i;
`DBG_REG_PC1: reload_pc_value[15:8] <= dbg_dat_i;
`DBG_REG_PC2: reload_pc_value[23:16] <= dbg_dat_i;
`DBG_REG_PC3: reload_pc_value[31:24] <= dbg_dat_i;
`DBG_CTL:
begin
trigger_halt <= dbg_dat_i[0];
trigger_resume <= dbg_dat_i[1];
trigger_reload_pc <= dbg_dat_i[2];
end
endcase // case (dbg_adr_i)
end else begin // if ( dbg_we_i )
case (dbg_adr_i)
`DBG_REG_PCO: dbg_dat_o <= x_pc_i[7:0];
`DBG_REG_PC1: dbg_dat_o <= x_pc_i[15:8];
`DBG_REG_PC2: dbg_dat_o <= x_pc_i[23:16];
`DBG_REG_PC3: dbg_dat_o <= x_pc_i[31:24];
end // else: !if( dbg_we_i )
end // else: !if( dbg_we_i )
end
end
/*
uRV - a tiny and dumb RISC-V core
Copyright (c) 2015 twl <twlostow@printf.cc>.
Copyright (c) 2015 CERN
Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
......@@ -18,50 +19,40 @@
*/
`include "rv_defs.v"
`include "urv_defs.v"
`timescale 1ns/1ps
module rv_decode
module urv_decode
(
input clk_i,
input rst_i,
// pipeline control
input d_stall_i,
input d_kill_i,
output d_stall_req_o,
output reg x_load_hazard_o,
// from Fetch stage
input [31:0] f_ir_i,
input [31:0] f_pc_i,
input f_valid_i,
output x_valid_o,
output reg [31:0] x_pc_o,
input d_x_rs1_bypass_i,
input d_x_rs2_bypass_i,
input d_w_rs1_bypass_i,
input d_w_rs2_bypass_i,
// to Register File
output [4:0] rf_rs1_o,
output [4:0] rf_rs2_o,
// to Execute 1 stage
output x_valid_o,
output reg [31:0] x_pc_o,
output [4:0] x_rs1_o,
output [4:0] x_rs2_o,
output [4:0] x_rd_o,
output reg [4:0] x_shamt_o,
output reg [2:0] x_fun_o,
output [4:0] x_opcode_o,
output reg x_shifter_sign_o,
output reg x_is_signed_compare_o,
output reg x_is_signed_alu_op_o,
output reg x_is_add_o,
......@@ -69,32 +60,27 @@ module rv_decode
output reg x_is_load_o,
output reg x_is_store_o,
output reg x_is_undef_o,
output reg [2:0] x_rd_source_o,
output x_rd_write_o,
output reg [11:0] x_csr_sel_o,
output reg [4:0] x_csr_imm_o,
output reg x_is_csr_o,
output reg x_is_eret_o,
output reg [31:0] x_imm_o,
output reg [31:0] x_alu_op1_o,
output reg [31:0] x_alu_op2_o,
output reg x_use_op1_o,
output reg x_use_op2_o,
output reg [1:0] x_op1_sel_o,
output reg [1:0] x_op2_sel_o
);
wire [4:0] f_rs1 = f_ir_i[19:15];
wire [4:0] f_rs2 = f_ir_i[24:20];
wire [4:0] f_rd = f_ir_i[11:7];
wire [4:0] d_opcode = f_ir_i[6:2];
wire [2:0] d_fun = f_ir_i[14:12];
reg [4:0] x_rs1;
reg [4:0] x_rs2;
......@@ -114,26 +100,19 @@ module rv_decode
assign rf_rs2_o = f_rs2;
reg [31:0] x_ir;
wire [4:0] d_opcode = f_ir_i[6:2];
reg load_hazard;
// attempt to reuse ALU for jump address generation
wire [2:0] d_fun = f_ir_i[14:12];
wire d_is_shift = (d_fun == `FUNC_SL || d_fun == `FUNC_SR) &&
(d_opcode == `OPC_OP || d_opcode == `OPC_OP_IMM );
reg x_is_mul;
wire d_is_mul = (f_ir_i[25] && d_fun == `FUNC_MUL);
wire d_is_mul = (f_ir_i[25] && d_fun == 3'b000);
// hazzard detect combinatorial logic
always@*
if (x_valid && f_valid_i && ( (f_rs1 == x_rd) || (f_rs2 == x_rd) ) && (!d_kill_i) )
if ( x_valid && f_valid_i && ( (f_rs1 == x_rd) || (f_rs2 == x_rd) ) && (!d_kill_i) )
begin
case (x_opcode)
`OPC_LOAD:
......@@ -150,12 +129,12 @@ module rv_decode
reg inserting_nop;
// bubble insertion following a hazzard
always@(posedge clk_i)
if(rst_i) begin
if(rst_i)
inserting_nop <= 0;
end else if (!d_stall_i)
else if (!d_stall_i)
begin
if (inserting_nop)
inserting_nop <= 0;
else
......@@ -164,8 +143,6 @@ module rv_decode
assign d_stall_req_o = load_hazard && !inserting_nop;
wire [4:0] f_rd = f_ir_i[11:7];
assign x_valid_o = x_valid;
......@@ -182,8 +159,6 @@ module rv_decode
else
x_valid <= f_valid_i;
x_ir <= f_ir_i;
x_rs1 <= f_rs1;
x_rs2 <= f_rs2;
x_rd <= f_rd;
......@@ -192,7 +167,7 @@ module rv_decode
x_shamt_o <= f_ir_i[24:20];
end
// ALU function decoding
always@(posedge clk_i)
if(!d_stall_i)
case (d_opcode)
......@@ -218,6 +193,7 @@ module rv_decode
reg [31:0] d_imm;
// Immediate decode, comb part
always@*
case(d_opcode)
`OPC_LUI, `OPC_AUIPC: d_imm <= d_imm_u;
......@@ -229,11 +205,13 @@ module rv_decode
default: d_imm <= 32'hx;
endcase // case (opcode)
// Immediate decode, seq part
always@(posedge clk_i)
if(!d_stall_i)
x_imm_o <= d_imm;
// ALU operand decoding
always@(posedge clk_i)
if(!d_stall_i)
begin
......@@ -296,7 +274,6 @@ module rv_decode
x_is_mul <= d_is_mul;
case (d_opcode)
`OPC_BRANCH:
x_is_signed_alu_op_o <= (d_fun == `BRA_GE || d_fun == `BRA_LT);
......@@ -304,9 +281,6 @@ module rv_decode
x_is_signed_alu_op_o <= (d_fun == `FUNC_SLT);
endcase // case (d_opcode)
case (d_opcode)
`OPC_OP:
x_is_add_o <= ~f_ir_i[30] && !(d_fun == `FUNC_SLT || d_fun == `FUNC_SLTU);
......@@ -318,9 +292,8 @@ module rv_decode
x_is_add_o <= 1;
endcase // case (d_opcode)
// all multiply/divide instructions except MUL
x_is_undef_o <= (d_opcode == `OPC_OP && f_ir_i[25] && d_fun != 3'b000);
x_is_undef_o <= (d_opcode == `OPC_OP && f_ir_i[25] && d_fun != `FUNC_MUL);
if(d_is_shift)
x_rd_source_o <= `RD_SOURCE_SHIFTER;
......@@ -331,8 +304,6 @@ module rv_decode
else
x_rd_source_o <= `RD_SOURCE_ALU;
// rdest write value
case (d_opcode)
`OPC_OP_IMM, `OPC_OP, `OPC_JAL, `OPC_JALR, `OPC_LUI, `OPC_AUIPC:
......@@ -345,26 +316,20 @@ module rv_decode
end // if (!d_stall_i)
// CSR/supervisor instructions
always@(posedge clk_i)
if (!d_stall_i)
begin
x_csr_imm_o <= f_ir_i[19:15];
x_csr_sel_o <= f_ir_i[31:20];
x_is_csr_o <= (d_opcode == `OPC_SYSTEM) && (d_fun != 0);
x_is_eret_o <= (d_opcode == `OPC_SYSTEM) && (d_fun == 0) && (f_ir_i [31:20] == 12'b000100000000);
end
assign x_is_shift_o = x_is_shift;
assign x_rd_write_o = x_rd_write;
endmodule // rv_predecode
endmodule // rv_decode
/*
uRV - a tiny and dumb RISC-V core
Copyright (c) 2015 twl <twlostow@printf.cc>.
Copyright (c) 2015 CERN
Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
......@@ -18,6 +19,8 @@
*/
`include "urv_config.v"
`define OPC_OP_IMM 5'b00100
`define OPC_LUI 5'b01101
`define OPC_AUIPC 5'b00101
......
`include "rv_defs.v"
/*
uRV - a tiny and dumb RISC-V core
Copyright (c) 2015 CERN
Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library.
*/
`include "urv_defs.v"
`timescale 1ns/1ps
module rv_divide
module urv_divide
(
input clk_i,
input rst_i,
input x_stall_i,
input x_kill_i,
output x_stall_req_o,
......@@ -120,132 +142,3 @@ module rv_divide
endmodule // rv_divide
module rv_divide_nonrestoring
(
input clk_i,
input rst_i,
input x_stall_i,
input x_kill_i,
output x_stall_req_o,
input d_valid_i,
input d_is_divide_i,
input [31:0] d_rs1_i,
input [31:0] d_rs2_i,
input [2:0] d_fun_i,
output reg [31:0] x_rd_o
);
reg [31:0] a,n,d,q;
reg n_sign, d_sign;
reg [5:0] state;
wire [32:0] alu_result;
reg [31:0] alu_op1;
reg [31:0] alu_op2;
reg is_rem;
wire [31:0] a_next = { a[30:0], 1'b0 };
always@*
case(state) // synthesis full_case parallel_case
0: begin alu_op1 <= 'hx; alu_op2 <= 'hx; end
1: begin alu_op1 <= 0; alu_op2 <= d_rs1_i; end
2: begin alu_op1 <= 0; alu_op2 <= d_rs2_i; end
35: begin alu_op1 <= a; alu_op2 <= d; end
36: begin alu_op1 <= 0; alu_op2 <= q; end
37: begin alu_op1 <= 0; alu_op2 <= a; end
default: begin alu_op1 <= a_next; alu_op2 <= d; end
endcase // case (state)
reg alu_sub;
assign alu_result = alu_sub ? {1'b0, alu_op1} - {1'b0, alu_op2} : {1'b0, alu_op1} + {1'b0, alu_op2};
wire alu_ge = ~alu_result [32];
wire start_divide = !x_stall_i && !x_kill_i && d_valid_i && d_is_divide_i;
wire done = (is_rem ? state == 38 : state == 37 );
assign x_stall_req_o = (start_divide || !done);
always@*
case (state) // synthesis full_case parallel_case
1:
alu_sub <= n_sign;
2:
alu_sub <= d_sign;
35:
alu_sub <= 0;
36:
alu_sub <= n_sign ^ d_sign;
37:
alu_sub <= n_sign;
default:
alu_sub <= ~a_next[31];
endcase // case (state)
always@(posedge clk_i)
if(rst_i || done)
state <= 0;
else if (state != 0 || start_divide)
state <= state + 1;
always@(posedge clk_i)
case ( state ) // synthesis full_case parallel_case
0:
if(start_divide)
begin
//q <= 0;
a <= 0;
is_rem <= (d_fun_i == `FUNC_REM || d_fun_i ==`FUNC_REMU);
n_sign <= d_rs1_i[31];
d_sign <= d_rs2_i[31];
end
1:
q <= alu_result[31:0];
2:
d <= alu_result[31:0];
35: // correction step
if(a[31])
a <= alu_result;
36:
x_rd_o <= alu_result; // quotient
37:
x_rd_o <= alu_result; // remainder
default: // 3..34: 32 divider iterations
begin
a <= alu_result;
q <= { q[30:0], ~alu_result[31] };
// r <= alu_ge ? alu_result : r_next;
end
endcase // case ( state )
endmodule // rv_divide_nonrestoring
/*
uRV - a tiny and dumb RISC-V core
Copyright (c) 2015 twl <twlostow@printf.cc>.
Copyright (c) 2015 CERN
Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
......@@ -16,13 +17,13 @@
You should have received a copy of the GNU Lesser General Public
License along with this library.
*/
*/
`include "rv_defs.v"
`include "urv_defs.v"
`timescale 1ns/1ps
module rv_exceptions
module urv_exceptions
(
input clk_i,
input rst_i,
......@@ -192,7 +193,7 @@ module rv_exceptions
assign x_exception_pc_o = csr_mepc;
assign x_exception_o = exception & !exception_pending;
endmodule // rv_exceptions
endmodule // urv_exceptions
/*
uRV - a tiny and dumb RISC-V core
Copyright (c) 2015 twl <twlostow@printf.cc>.
Copyright (c) 2015 CERN
Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
......@@ -18,11 +19,11 @@
*/
`include "rv_defs.v"
`include "urv_defs.v"
`timescale 1ns/1ps
module rv_exec
module urv_exec
(
input clk_i,
input rst_i,
......@@ -124,19 +125,16 @@ module rv_exec
reg [31:0] dm_addr, dm_data_s, dm_select_s;
// Comparator
wire [32:0] cmp_op1 = { d_is_signed_alu_op_i ? rs1[31] : 1'b0, rs1 };
wire [32:0] cmp_op2 = { d_is_signed_alu_op_i ? rs2[31] : 1'b0, rs2 };
wire [32:0] cmp_rs = cmp_op1 - cmp_op2;
wire cmp_equal = (cmp_op1 == cmp_op2);
wire cmp_lt = cmp_rs[32];
reg f_branch_take;
wire [31:0] rd_shifter;
wire [31:0] rd_csr;
wire [31:0] rd_mul;
wire [31:0] rd_div;
wire exception;
......@@ -144,8 +142,7 @@ module rv_exec
wire [31:0] csr_write_value;
wire [31:0] exception_address, exception_vector;
rv_csr csr_regs
urv_csr csr_regs
(
.clk_i(clk_i),
......@@ -174,7 +171,7 @@ module rv_exec
.csr_mcause_i(csr_mcause)
);
rv_exceptions exception_unit
urv_exceptions exception_unit
(
.clk_i(clk_i),
.rst_i(rst_i),
......@@ -226,6 +223,7 @@ module rv_exec
always@*
dm_addr <= d_imm_i + ( ( d_opcode_i == `OPC_JALR || d_opcode_i == `OPC_LOAD || d_opcode_i == `OPC_STORE) ? rs1 : d_pc_i );
// calculate branch target address
always@*
if(d_is_eret_i )
branch_target <= exception_address;
......@@ -241,9 +239,10 @@ module rv_exec
alu_op2 <= d_use_op2_i ? d_alu_op2_i : rs2;
end
// ALU adder/subtractor
wire [32:0] alu_addsub_op1 = {d_is_signed_alu_op_i ? alu_op1[31] : 1'b0, alu_op1 };
wire [32:0] alu_addsub_op2 = {d_is_signed_alu_op_i ? alu_op2[31] : 1'b0, alu_op2 };
reg [32:0] alu_addsub_result;
always@*
......@@ -253,7 +252,7 @@ module rv_exec
alu_addsub_result <= alu_addsub_op1 - alu_addsub_op2;
// the ALU itself
// the rest of the ALU
always@*
begin
case (d_fun_i)
......@@ -273,8 +272,8 @@ module rv_exec
endcase // case (d_fun_i)
end // always@ *
rv_shifter shifter
// barel shifter
urv_shifter shifter
(
.clk_i(clk_i),
.rst_i(rst_i),
......@@ -292,7 +291,7 @@ module rv_exec
wire divider_stall_req = 0;
rv_multiply multiplier
urv_multiply multiplier
(
.clk_i(clk_i),
.rst_i(rst_i),
......@@ -307,7 +306,7 @@ module rv_exec
/* wire divider_stall_req;
wire [31:0] rd_divide;
rv_divide divider
urv_divide divider
(
.clk_i(clk_i),
.rst_i(rst_i),
......@@ -415,11 +414,11 @@ module rv_exec
assign dm_data_s_o = dm_data_s;
assign dm_data_select_o = dm_select_s;
assign dm_load_o = d_is_load_i & d_valid_i & !x_kill_i & !x_stall_i & !exception;
assign dm_store_o = d_is_store_i & d_valid_i & !x_kill_i & !x_stall_i & !exception;
// X/W pipeline registers
always@(posedge clk_i)
if (rst_i) begin
f_branch_take <= 0;
......@@ -432,11 +431,13 @@ module rv_exec
f_branch_take <= branch_take && !x_kill_i && d_valid_i;
w_rd_o <= d_rd_i;
w_rd_value_o <= rd_value;
w_rd_write_o <= d_rd_write_i && !x_kill_i && d_valid_i && !exception;
w_rd_source_o <= d_rd_source_i;
w_fun_o <= d_fun_i;
w_load_o <= d_is_load_i && !x_kill_i && d_valid_i && !exception;
w_store_o <= d_is_store_i && !x_kill_i && d_valid_i && !exception;
w_rd_source_o <= d_rd_source_i;
w_fun_o <= d_fun_i;
w_dm_addr_o <= dm_addr;
w_valid_o <= !exception;
end // else: !if(rst_i)
......@@ -444,18 +445,22 @@ module rv_exec
assign f_branch_take_o = f_branch_take;
// pipeline control: generate stall request signal
always@*
// never stall on taken branch
if(f_branch_take)
x_stall_req_o <= 0;
else if(divider_stall_req)
x_stall_req_o <= 1;
// stall if memory request pending, but memory not ready
else if ((d_is_load_i || d_is_store_i) && d_valid_i && !x_kill_i && !dm_ready_i)
x_stall_req_o <= 1;
else
x_stall_req_o <= 0;
endmodule
endmodule // urv_exec
......
/*
uRV - a tiny and dumb RISC-V core
Copyright (c) 2015 twl <twlostow@printf.cc>.
Copyright (c) 2015 CERN
Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
......@@ -20,24 +21,23 @@
`timescale 1ns/1ps
module rv_fetch
module urv_fetch
(
input clk_i,
input rst_i,
input f_stall_i,
input f_kill_i,
output [31:0] im_addr_o,
input [31:0] im_data_i,
input im_valid_i,
input f_stall_i,
input f_kill_i,
output reg f_valid_o,
output [31:0] f_ir_o,
output reg [31:0] f_pc_o,
output reg [31:0] f_pc_plus_4_o,
output reg f_valid_o,
input [31:0] x_pc_bra_i,
input x_bra_i
);
......@@ -93,7 +93,7 @@ module rv_fetch
end
end // else: !if(rst_i)
endmodule // urv_fetch
endmodule
/*
uRV - a tiny and dumb RISC-V core
Copyright (c) 2015 CERN
Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library.
*/
`timescale 1ns/1ps
`include "urv_defs.v"
`ifdef URV_PLATFORM_SPARTAN6
module urv_iram
#(
parameter g_size = 65536,
......@@ -92,7 +117,7 @@ module urv_iram
`RAM_INST(64K_31, RAMB16_S1_S1, 15:2, 31, 3)
end // if (g_size == 65536)
if(g_size == 16384) begin
else if(g_size == 16384) begin
`RAM_INST(16K_0, RAMB16_S4_S4, 13:2, 3:0, 0)
`RAM_INST(16K_1, RAMB16_S4_S4, 13:2, 7:4, 0)
`RAM_INST(16K_2, RAMB16_S4_S4, 13:2, 11:8, 1)
......@@ -101,7 +126,10 @@ module urv_iram
`RAM_INST(16K_5, RAMB16_S4_S4, 13:2, 23:20, 2)
`RAM_INST(16K_6, RAMB16_S4_S4, 13:2, 27:24, 3)
`RAM_INST(16K_7, RAMB16_S4_S4, 13:2, 31:28, 3)
end
end else begin
$fatal("Unsupported Spartan-6 IRAM size: %d", g_size);
end // else: !if(g_size == 16384)
end else begin // if (!g_simulation)
......@@ -195,3 +223,82 @@ module urv_iram
endmodule // urv_iram
`endif // `ifdef URV_PLATFORM_SPARTAN6
`ifdef URV_PLATFORM_GENERIC
module urv_iram
#(
parameter g_size = 65536,
parameter g_init_file = "",
parameter g_simulation = 0
)
(
input clk_i,
input ena_i,
input wea_i,
input [31:0] aa_i,
input [3:0] bwea_i,
input [31:0] da_i,
output [31:0] qa_o,
input enb_i,
input web_i,
input [31:0] ab_i,
input [3:0] bweb_i,
input [31:0] db_i,
output [31:0] qb_o
);
genvar i;
reg [31:0] mem[0:g_size/4-1];
reg [31:0] qa_int, qb_int;
always@(posedge clk_i)
begin
if(ena_i)
begin
qa_int <= mem[(aa_i / 4)];
if(wea_i && bwea_i[0])
mem [(aa_i / 4)][7:0] <= da_i[7:0];
if(wea_i && bwea_i[1])
mem [(aa_i / 4)][15:8] <= da_i[15:8];
if(wea_i && bwea_i[2])
mem [(aa_i / 4)][23:16] <= da_i[23:16];
if(wea_i && bwea_i[3])
mem [(aa_i / 4)][31:24] <= da_i[31:24];
end
if(enb_i)
begin
qb_int <= mem[(ab_i / 4) % g_size];
if(web_i && bweb_i[0])
mem [(ab_i / 4)][7:0] <= db_i[7:0];
if(web_i && bweb_i[1])
mem [(ab_i / 4)][15:8] <= db_i[15:8];
if(web_i && bweb_i[2])
mem [(ab_i / 4)][23:16] <= db_i[23:16];
if(web_i && bweb_i[3])
mem [(ab_i / 4)][31:24] <= db_i[31:24];
end
end // always@ (posedge clk_i)
assign qa_o = qa_int;
assign qb_o = qb_int;
// synthesis translate_on
end // else: !if(!g_simulation)
`endif
`include "rv_defs.v"
/*
`timescale 1ns/1ps
uRV - a tiny and dumb RISC-V core
Copyright (c) 2015 CERN
Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library.
*/
`define ARCH_VIRTEX6
`include "urv_defs.v"
`ifdef ARCH_SPARTAN6
`timescale 1ns/1ps
`ifdef URV_PLATFORM_SPARTAN6
module rv_mult18x18
module urv_mult18x18
(
input clk_i,
input rst_i,
......@@ -33,7 +52,7 @@ module rv_mult18x18
.OPMODEREG(0),
.PREG(0),
.RSTTYPE("SYNC")
) D1 (
) D1 (
.BCOUT(),
.PCOUT(),
.CARRYOUT(),
......@@ -64,14 +83,14 @@ module rv_mult18x18
.RSTM(rst_i),
.RSTOPMODE(1'b0),
.RSTP(1'b0)
);
);
endmodule // rv_mult18x18
`endif // `i
// fdef ARCH_SPARTAN6
endmodule // urv_mult18x18
`endif // `ifdef PLATFORM_SPARTAN6
`ifdef ARCH_VIRTEX6
module rv_mult18x18
`ifdef URV_PLATFORM_GENERIC
module urv_mult18x18
(
input clk_i,
input rst_i,
......@@ -89,12 +108,11 @@ module rv_mult18x18
if(!stall_i)
q_o <= x_i * y_i;
endmodule // rv_mult18x18
`endif // `ifdef ARCH_VIRTEX6
endmodule // urv_mult18x18
`endif // `ifdef URV_PLATFORM_GENERIC
module rv_multiply
module urv_multiply
(
input clk_i,
input rst_i,
......@@ -108,8 +126,6 @@ module rv_multiply
);
wire[17:0] xl_u = {1'b0, d_rs1_i[16:0] };
wire[17:0] yl_u = {1'b0, d_rs2_i[16:0] };
......@@ -121,7 +137,7 @@ module rv_multiply
wire [35:0] yl_xl, yl_xh, yh_xl;
rv_mult18x18 U_mul0
urv_mult18x18 mul0
(
.clk_i(clk_i),
.rst_i(rst_i),
......@@ -132,7 +148,7 @@ module rv_multiply
.q_o(yl_xl)
);
rv_mult18x18 U_mul1
urv_mult18x18 mul1
(
.clk_i(clk_i),
.rst_i(rst_i),
......@@ -143,7 +159,7 @@ module rv_multiply
.q_o(yh_xl)
);
rv_mult18x18 U_mul2
urv_mult18x18 mul2
(
.clk_i(clk_i),
.rst_i(rst_i),
......@@ -154,29 +170,12 @@ module rv_multiply
.q_o(yl_xh)
);
/* -----\/----- EXCLUDED -----\/-----
always@(posedge clk_i)
if(!x_stall_i)
begin
yh_xl <= $signed(yh) * $signed(xl);
yl_xh <= $signed(yl) * $signed(xh);
yl_xl <= $unsigned(yl) * $unsigned(xl);
end
// stage0 <= $signed(d_rs1_i) * $signed(d_rs2_i);
*/
always@*
w_rd_o <= yl_xl + {yl_xh[14:0], 17'h0} + {yh_xl[14:0], 17'h0};
endmodule // urv_multiply
endmodule // rv_multiply
/*
uRV - a tiny and dumb RISC-V core
Copyright (c) 2015 twl <twlostow@printf.cc>.
Copyright (c) 2015 CERN
Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
......@@ -18,17 +19,16 @@
*/
`include "rv_defs.v"
`include "urv_defs.v"
`timescale 1ns/1ps
module rv_regmem
(
module urv_regmem
(
input clk_i,
input rst_i,
input en1_i,
input [4:0] a1_i,
output reg [31:0] q1_o,
......@@ -38,12 +38,6 @@ module rv_regmem
);
reg [31:0] ram [0:31];
reg [31:0] bypass_r;
reg bypass;
reg [31:0] q1_int;
always@(posedge clk_i)
if(en1_i)
......@@ -53,20 +47,19 @@ module rv_regmem
if(we2_i)
ram[a2_i] <= d2_i;
// synthesis translate_off
initial begin : ram_init
// synthesis translate_off
initial begin : ram_init
integer i;
for(i=0;i<32; i=i+1) begin
ram[i] = 0;
end
end
// synthesis translate_on
endmodule // rv_regmem2
end
// synthesis translate_on
endmodule
module rv_regfile
module urv_regfile
(
input clk_i,
input rst_i,
......@@ -96,7 +89,8 @@ module rv_regfile
wire [31:0] rs2_regfile;
wire write = (w_rd_store_i && (w_rd_i != 0));
rv_regmem bank0 (
urv_regmem bank0
(
.clk_i(clk_i),
.rst_i (rst_i ),
.en1_i(!d_stall_i),
......@@ -108,7 +102,8 @@ module rv_regfile
.we2_i (write));
rv_regmem bank1 (
urv_regmem bank1
(
.clk_i(clk_i),
.rst_i (rst_i ),
.en1_i(!d_stall_i),
......@@ -162,129 +157,5 @@ module rv_regfile
endcase // case ( {rs2_bypass_x, rs2_bypass_w } )
end // always@ *
endmodule // rv_regfile
module rv_regmem_distram
(
input clk_i,
input [4:0] a1_i,
output [31:0] q1_o,
input [4:0] a2_i,
input [31:0] d2_i,
input we2_i
);
reg [31:0] ram [0:31];
assign q1_o = ram[a1_i];
always@(posedge clk_i)
if(we2_i)
ram[a2_i] <= d2_i;
// synthesis translate_off
initial begin : ram_init
integer i;
for(i=0;i<32; i=i+1) begin
ram[i] = 0;
end
end
// synthesis translate_on
endmodule // rv_regmem2
module rv_regfile_distram
(
input clk_i,
input rst_i,
input d_stall_i,
input [4:0] rf_rs1_i,
input [4:0] rf_rs2_i,
input [4:0] d_rs1_i,
input [4:0] d_rs2_i,
output reg [31:0] x_rs1_value_o,
output reg [31:0] x_rs2_value_o,
input [4:0] w_rd_i,
input [31:0] w_rd_value_i,
input w_rd_store_i,
input w_bypass_rd_write_i,
input [31:0] w_bypass_rd_value_i
);
wire [31:0] rs1_regfile;
wire [31:0] rs2_regfile;
wire write = (w_rd_store_i && (w_rd_i != 0));
rv_regmem_distram bank0 (
.clk_i(clk_i),
.a1_i(rf_rs1_i),
.q1_o(rs1_regfile),
.a2_i(w_rd_i),
.d2_i(w_rd_value_i),
.we2_i (write));
rv_regmem_distram bank1 (
.clk_i(clk_i),
.a1_i(rf_rs2_i),
.q1_o(rs2_regfile),
.a2_i (w_rd_i),
.d2_i (w_rd_value_i),
.we2_i (write)
);
wire rs1_bypass_x = w_bypass_rd_write_i && (w_rd_i == d_rs1_i) && (w_rd_i != 0);
wire rs2_bypass_x = w_bypass_rd_write_i && (w_rd_i == d_rs2_i) && (w_rd_i != 0);
reg rs1_bypass_w, rs2_bypass_w;
always@*
begin
rs1_bypass_w <= write && (rf_rs1_i == w_rd_i);
rs2_bypass_w <= write && (rf_rs2_i == w_rd_i);
end
always@(posedge clk_i)
if(!d_stall_i)
begin
case ( {rs1_bypass_x, rs1_bypass_w } ) // synthesis parallel_case full_case
2'b10, 2'b11:
x_rs1_value_o <= w_bypass_rd_value_i;
2'b01:
x_rs1_value_o <= w_rd_value_i;
default:
x_rs1_value_o <= rs1_regfile;
endcase // case ( {rs1_bypass_x, rs1_bypass_w } )
case ( {rs2_bypass_x, rs2_bypass_w } ) // synthesis parallel_case full_case
2'b10, 2'b11:
x_rs2_value_o <= w_bypass_rd_value_i;
2'b01:
x_rs2_value_o <= w_rd_value_i;
default:
x_rs2_value_o <= rs2_regfile;
endcase // case ( {rs2_bypass_x, rs2_bypass_w } )
end // always@ *
endmodule // rv_regfile
endmodule // urv_regfile
/*
uRV - a tiny and dumb RISC-V core
Copyright (c) 2015 twl <twlostow@printf.cc>.
Copyright (c) 2015 CERN
Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
......@@ -18,7 +19,7 @@
*/
`include "rv_defs.v"
`include "urv_defs.v"
`timescale 1ns/1ps
......@@ -28,7 +29,7 @@
x[16], x[17], x[18], x[19], x[20], x[21], x[22], x[23], \
x[24], x[25], x[26], x[27], x[28], x[29], x[30], x[31] }
module rv_shifter
module urv_shifter
(
input clk_i,
input rst_i,
......@@ -37,16 +38,16 @@ module rv_shifter
input d_valid_i,
input [31:0] d_rs1_i,
output reg[31:0] w_rd_o,
output reg [31:0] w_rd_o,
input [4:0] d_shamt_i,
input [2:0] d_fun_i,
input d_shifter_sign_i,
input d_is_shift_i );
input d_is_shift_i
);
wire extend_sign = ((d_fun_i == `FUNC_SR) && d_shifter_sign_i) ? d_rs1_i[31] : 1'b0;
reg [31:0] shift_pre, shift_16, shift_8, s1_out;
// stage 1
......@@ -73,16 +74,6 @@ module rv_shifter
s1_out <= shift_8;
end
/* -----\/----- EXCLUDED -----\/-----
always@*
begin
s2_extend_sign <= extend_sign;
s2_shift <= d_shamt_i;
s2_func <= d_fun_i;
s1_out <= shift_8;
end
-----/\----- EXCLUDED -----/\----- */
reg [31:0] shift_4, shift_2, shift_1, shift_post;
// stage 2
......@@ -94,109 +85,8 @@ module rv_shifter
shift_post <= (s2_func == `FUNC_SL) ? `reverse_bits(shift_1) : shift_1;
end
/* -----\/----- EXCLUDED -----\/-----
always@(posedge clk_i)
if(!x_stall_i)
w_rd_o <= shift_post;
-----/\----- EXCLUDED -----/\----- */
always@*
w_rd_o <= shift_post;
endmodule // rv_shifter
module rv_shifter2
(
input clk_i,
input rst_i,
input x_stall_i,
input w_stall_req_i,
output x_stall_req_o,
input d_valid_i,
input [31:0] d_rs1_i,
output [31:0] x_rd_o,
input [4:0] d_shamt_i,
input [2:0] d_fun_i,
input d_shifter_sign_i,
input d_is_shift_i );
wire extend_sign = ((d_fun_i == `FUNC_SR) && d_shifter_sign_i) ? d_rs1_i[31] : 1'b0;
wire shifter_req = !w_stall_req_i && d_valid_i && d_is_shift_i;
reg shifter_req_d0;
always@(posedge clk_i)
if(shifter_req_d0 && !x_stall_i)
shifter_req_d0 <= 0;
else
shifter_req_d0 <= shifter_req;
assign x_stall_req_o = shifter_req && !shifter_req_d0;
reg [31:0] shift_pre, shift_16, shift_8, s1_out;
reg [31:0] s2_mask;
// stage 1
always@*
begin
shift_16 <= d_shamt_i[4] ? { d_rs1_i[15:0], d_rs1_i[31:16] } : d_rs1_i;
shift_8 <= d_shamt_i[3] ? { shift_16[7:0], shift_16[31:8] } : shift_16;
end
reg [4:0] s2_shift;
reg [2:0] s2_func;
reg s2_extend_sign;
// stage 1 pipe register
always@(posedge clk_i)
begin : stage1
integer i;
for(i=0;i<32;i=i+1)
begin
if(d_fun_i == `FUNC_SL)
s2_mask[i] <= (d_shamt_i < i) ? 1'b1 : 1'b0;
else
s2_mask[i] <= (d_shamt_i < (31-i)) ? 1'b1 : 1'b0;
end
s2_extend_sign <= extend_sign;
s2_shift <= d_shamt_i;
s2_func <= d_fun_i;
s1_out <= shift_8;
end
reg [31:0] shift_4, shift_2, shift_1, shift_post;
// stage 2
always@*
begin : stage2
integer i;
shift_4 <= s2_shift[2] ? { s1_out[3:0], s1_out[31:4] } : s1_out;
shift_2 <= s2_shift[1] ? { s1_out[1:0], shift_4[31:2] } : shift_4;
shift_1 <= s2_shift[0] ? { s1_out[0], shift_2[31:1] } : shift_2;
for(i=0;i<32;i=i+1)
begin
if(s2_extend_sign)
shift_post <= s2_mask[i] ? 1'b1 : shift_1[i];
else
shift_post <= s2_mask[i] ? 1'b0 : shift_1[i];
end
end
assign x_rd_o = shift_post;
endmodule // rv_shifter
endmodule // urv_shifter
/*
uRV - a tiny and dumb RISC-V core
Copyright (c) 2015 twl <twlostow@printf.cc>.
Copyright (c) 2015 CERN
Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
......@@ -18,11 +19,11 @@
*/
`include "rv_defs.v"
`include "urv_defs.v"
`timescale 1ns/1ps
module rv_timer
module urv_timer
(
input clk_i,
input rst_i,
......@@ -76,4 +77,4 @@ module rv_timer
assign csr_cycles_o = cycles;
assign sys_tick_o = presc_tick;
endmodule // rv_timer
endmodule // urv_timer
/*
uRV - a tiny and dumb RISC-V core
Copyright (c) 2015 twl <twlostow@printf.cc>.
Copyright (c) 2015 CERN
Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
......@@ -18,17 +19,16 @@
*/
`include "rv_defs.v"
`include "urv_defs.v"
`timescale 1ns/1ps
module rv_writeback
module urv_writeback
(
input clk_i,
input rst_i,
input w_stall_i,
output w_stall_req_o,
input [2:0] x_fun_i,
......@@ -54,17 +54,11 @@ module rv_writeback
output [31:0] rf_rd_value_o,
output [4:0] rf_rd_o,
output rf_rd_write_o,
output [31:0] TRIG2
output rf_rd_write_o
);
reg [31:0] load_value;
// generate load value
always@*
begin
......@@ -110,7 +104,6 @@ module rv_writeback
reg rf_rd_write;
reg [31:0] rf_rd_value;
always@*
if( x_load_i )
rf_rd_value <= load_value;
......@@ -139,10 +132,4 @@ module rv_writeback
assign rf_rd_o = x_rd_i;
assign w_stall_req_o = x_valid_i && ((x_load_i && !dm_load_done_i) || (x_store_i && !dm_store_done_i));
assign TRIG2[6] = x_load_i;
assign TRIG2[8] = dm_load_done_i;
assign TRIG2[9] = x_store_i;
assign TRIG2[11] = dm_store_done_i;
assign TRIG2[15] = w_stall_req_o;
endmodule // rv_writeback
endmodule // urv_writeback
......@@ -24,7 +24,7 @@ use ieee.numeric_std.all;
use work.wishbone_pkg.all;
use work.genram_pkg.all;
entity xrv_core is
entity xurv_core is
generic (
g_internal_ram_size : integer := 65536;
g_internal_ram_init_file : string := "";
......@@ -47,13 +47,13 @@ entity xrv_core is
host_slave_i : in t_wishbone_slave_in := cc_dummy_slave_in;
host_slave_o : out t_wishbone_slave_out
);
end xrv_core;
end xurv_core;
architecture wrapper of xrv_core is
architecture wrapper of xurv_core is
constant c_mem_address_bits : integer := f_ceil_log2(g_internal_ram_size / 4);
component rv_cpu is
component urv_cpu is
port(
clk_i : in std_logic;
rst_i : in std_logic;
......@@ -90,13 +90,13 @@ architecture wrapper of xrv_core is
aa_i : in std_logic_vector(31 downto 0);
bwea_i : in std_logic_vector(3 downto 0);
da_i : in std_logic_vector(31 downto 0);
qa_o :out std_logic_vector(31 downto 0);
qa_o : out std_logic_vector(31 downto 0);
enb_i : in std_logic;
web_i : in std_logic;
ab_i : in std_logic_vector(31 downto 0);
bweb_i : in std_logic_vector(3 downto 0);
db_i : in std_logic_vector(31 downto 0);
qb_o :out std_logic_vector(31 downto 0)
qb_o : out std_logic_vector(31 downto 0)
);
end component;
......@@ -232,7 +232,7 @@ begin
im_addr_muxed <= ha_im_addr when ha_im_access = '1' else im_addr(g_address_bits-1 downto 0);
dm_ready <= '1';
cpu_core : rv_cpu
cpu_core : urv_cpu
port map (
clk_i => clk_sys_i,
rst_i => cpu_rst,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment