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=["."] include_dirs=["."]
files = [ "rv_cpu.v", files = [ "urv_cpu.v",
"rv_exec.v", "urv_exec.v",
"rv_fetch.v", "urv_fetch.v",
"rv_predecode.v", "urv_decode.v",
"rv_regfile.v", "urv_regfile.v",
"rv_writeback.v", "urv_writeback.v",
"rv_shifter.v", "urv_shifter.v",
"rv_multiply.v", "urv_multiply.v",
"rv_divide.v", "urv_divide.v",
"rv_csr.v", "urv_csr.v",
"rv_timer.v", "urv_timer.v",
"rv_exceptions.v", "urv_exceptions.v",
"urv_iram.v", "urv_iram.v",
"xrv_core.vhd" ]; "xurv_core.vhd" ];
# "../sim/rv_icache_model.sv"]; # "../sim/rv_icache_model.sv"];
This diff is collapsed.
/* /*
uRV - a tiny and dumb RISC-V core 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 This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
...@@ -18,11 +19,11 @@ ...@@ -18,11 +19,11 @@
*/ */
`include "rv_defs.v" `include "urv_defs.v"
`timescale 1ns/1ps `timescale 1ns/1ps
module rv_csr module urv_csr
( (
input clk_i, input clk_i,
input rst_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 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 This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
...@@ -18,50 +19,40 @@ ...@@ -18,50 +19,40 @@
*/ */
`include "rv_defs.v" `include "urv_defs.v"
`timescale 1ns/1ps `timescale 1ns/1ps
module urv_decode
module rv_decode
( (
input clk_i, input clk_i,
input rst_i, input rst_i,
// pipeline control
input d_stall_i, input d_stall_i,
input d_kill_i, input d_kill_i,
output d_stall_req_o, output d_stall_req_o,
output reg x_load_hazard_o, // from Fetch stage
input [31:0] f_ir_i, input [31:0] f_ir_i,
input [31:0] f_pc_i, input [31:0] f_pc_i,
input f_valid_i, input f_valid_i,
output x_valid_o, // to Register File
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,
output [4:0] rf_rs1_o, output [4:0] rf_rs1_o,
output [4:0] rf_rs2_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_rs1_o,
output [4:0] x_rs2_o, output [4:0] x_rs2_o,
output [4:0] x_rd_o, output [4:0] x_rd_o,
output reg [4:0] x_shamt_o, output reg [4:0] x_shamt_o,
output reg [2:0] x_fun_o, output reg [2:0] x_fun_o,
output [4:0] x_opcode_o, output [4:0] x_opcode_o,
output reg x_shifter_sign_o, output reg x_shifter_sign_o,
output reg x_is_signed_compare_o, output reg x_is_signed_compare_o,
output reg x_is_signed_alu_op_o, output reg x_is_signed_alu_op_o,
output reg x_is_add_o, output reg x_is_add_o,
...@@ -69,32 +60,27 @@ module rv_decode ...@@ -69,32 +60,27 @@ module rv_decode
output reg x_is_load_o, output reg x_is_load_o,
output reg x_is_store_o, output reg x_is_store_o,
output reg x_is_undef_o, output reg x_is_undef_o,
output reg [2:0] x_rd_source_o, output reg [2:0] x_rd_source_o,
output x_rd_write_o, output x_rd_write_o,
output reg [11:0] x_csr_sel_o, output reg [11:0] x_csr_sel_o,
output reg [4:0] x_csr_imm_o, output reg [4:0] x_csr_imm_o,
output reg x_is_csr_o, output reg x_is_csr_o,
output reg x_is_eret_o, output reg x_is_eret_o,
output reg [31:0] x_imm_o, output reg [31:0] x_imm_o,
output reg [31:0] x_alu_op1_o, output reg [31:0] x_alu_op1_o,
output reg [31:0] x_alu_op2_o, output reg [31:0] x_alu_op2_o,
output reg x_use_op1_o, output reg x_use_op1_o,
output reg x_use_op2_o, output reg x_use_op2_o,
output reg [1:0] x_op1_sel_o, output reg [1:0] x_op1_sel_o,
output reg [1:0] x_op2_sel_o output reg [1:0] x_op2_sel_o
); );
wire [4:0] f_rs1 = f_ir_i[19:15]; wire [4:0] f_rs1 = f_ir_i[19:15];
wire [4:0] f_rs2 = f_ir_i[24:20]; 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_rs1;
reg [4:0] x_rs2; reg [4:0] x_rs2;
...@@ -114,26 +100,19 @@ module rv_decode ...@@ -114,26 +100,19 @@ module rv_decode
assign rf_rs2_o = f_rs2; assign rf_rs2_o = f_rs2;
reg [31:0] x_ir;
wire [4:0] d_opcode = f_ir_i[6:2];
reg load_hazard; reg load_hazard;
// attempt to reuse ALU for jump address generation // 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) && wire d_is_shift = (d_fun == `FUNC_SL || d_fun == `FUNC_SR) &&
(d_opcode == `OPC_OP || d_opcode == `OPC_OP_IMM ); (d_opcode == `OPC_OP || d_opcode == `OPC_OP_IMM );
reg x_is_mul; reg x_is_mul;
wire d_is_mul = (f_ir_i[25] && d_fun == `FUNC_MUL);
// hazzard detect combinatorial logic
wire d_is_mul = (f_ir_i[25] && d_fun == 3'b000);
always@* 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 begin
case (x_opcode) case (x_opcode)
`OPC_LOAD: `OPC_LOAD:
...@@ -150,12 +129,12 @@ module rv_decode ...@@ -150,12 +129,12 @@ module rv_decode
reg inserting_nop; reg inserting_nop;
// bubble insertion following a hazzard
always@(posedge clk_i) always@(posedge clk_i)
if(rst_i) begin if(rst_i)
inserting_nop <= 0; inserting_nop <= 0;
end else if (!d_stall_i) else if (!d_stall_i)
begin begin
if (inserting_nop) if (inserting_nop)
inserting_nop <= 0; inserting_nop <= 0;
else else
...@@ -164,8 +143,6 @@ module rv_decode ...@@ -164,8 +143,6 @@ module rv_decode
assign d_stall_req_o = load_hazard && !inserting_nop; 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; assign x_valid_o = x_valid;
...@@ -182,8 +159,6 @@ module rv_decode ...@@ -182,8 +159,6 @@ module rv_decode
else else
x_valid <= f_valid_i; x_valid <= f_valid_i;
x_ir <= f_ir_i;
x_rs1 <= f_rs1; x_rs1 <= f_rs1;
x_rs2 <= f_rs2; x_rs2 <= f_rs2;
x_rd <= f_rd; x_rd <= f_rd;
...@@ -192,7 +167,7 @@ module rv_decode ...@@ -192,7 +167,7 @@ module rv_decode
x_shamt_o <= f_ir_i[24:20]; x_shamt_o <= f_ir_i[24:20];
end end
// ALU function decoding
always@(posedge clk_i) always@(posedge clk_i)
if(!d_stall_i) if(!d_stall_i)
case (d_opcode) case (d_opcode)
...@@ -218,6 +193,7 @@ module rv_decode ...@@ -218,6 +193,7 @@ module rv_decode
reg [31:0] d_imm; reg [31:0] d_imm;
// Immediate decode, comb part
always@* always@*
case(d_opcode) case(d_opcode)
`OPC_LUI, `OPC_AUIPC: d_imm <= d_imm_u; `OPC_LUI, `OPC_AUIPC: d_imm <= d_imm_u;
...@@ -229,11 +205,13 @@ module rv_decode ...@@ -229,11 +205,13 @@ module rv_decode
default: d_imm <= 32'hx; default: d_imm <= 32'hx;
endcase // case (opcode) endcase // case (opcode)
// Immediate decode, seq part
always@(posedge clk_i) always@(posedge clk_i)
if(!d_stall_i) if(!d_stall_i)
x_imm_o <= d_imm; x_imm_o <= d_imm;
// ALU operand decoding
always@(posedge clk_i) always@(posedge clk_i)
if(!d_stall_i) if(!d_stall_i)
begin begin
...@@ -296,7 +274,6 @@ module rv_decode ...@@ -296,7 +274,6 @@ module rv_decode
x_is_mul <= d_is_mul; x_is_mul <= d_is_mul;
case (d_opcode) case (d_opcode)
`OPC_BRANCH: `OPC_BRANCH:
x_is_signed_alu_op_o <= (d_fun == `BRA_GE || d_fun == `BRA_LT); x_is_signed_alu_op_o <= (d_fun == `BRA_GE || d_fun == `BRA_LT);
...@@ -304,9 +281,6 @@ module rv_decode ...@@ -304,9 +281,6 @@ module rv_decode
x_is_signed_alu_op_o <= (d_fun == `FUNC_SLT); x_is_signed_alu_op_o <= (d_fun == `FUNC_SLT);
endcase // case (d_opcode) endcase // case (d_opcode)
case (d_opcode) case (d_opcode)
`OPC_OP: `OPC_OP:
x_is_add_o <= ~f_ir_i[30] && !(d_fun == `FUNC_SLT || d_fun == `FUNC_SLTU); x_is_add_o <= ~f_ir_i[30] && !(d_fun == `FUNC_SLT || d_fun == `FUNC_SLTU);
...@@ -318,9 +292,8 @@ module rv_decode ...@@ -318,9 +292,8 @@ module rv_decode
x_is_add_o <= 1; x_is_add_o <= 1;
endcase // case (d_opcode) endcase // case (d_opcode)
// all multiply/divide instructions except MUL // 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) if(d_is_shift)
x_rd_source_o <= `RD_SOURCE_SHIFTER; x_rd_source_o <= `RD_SOURCE_SHIFTER;
...@@ -331,8 +304,6 @@ module rv_decode ...@@ -331,8 +304,6 @@ module rv_decode
else else
x_rd_source_o <= `RD_SOURCE_ALU; x_rd_source_o <= `RD_SOURCE_ALU;
// rdest write value // rdest write value
case (d_opcode) case (d_opcode)
`OPC_OP_IMM, `OPC_OP, `OPC_JAL, `OPC_JALR, `OPC_LUI, `OPC_AUIPC: `OPC_OP_IMM, `OPC_OP, `OPC_JAL, `OPC_JALR, `OPC_LUI, `OPC_AUIPC:
...@@ -345,26 +316,20 @@ module rv_decode ...@@ -345,26 +316,20 @@ module rv_decode
end // if (!d_stall_i) end // if (!d_stall_i)
// CSR/supervisor instructions // CSR/supervisor instructions
always@(posedge clk_i) always@(posedge clk_i)
if (!d_stall_i) if (!d_stall_i)
begin begin
x_csr_imm_o <= f_ir_i[19:15]; x_csr_imm_o <= f_ir_i[19:15];
x_csr_sel_o <= f_ir_i[31:20]; x_csr_sel_o <= f_ir_i[31:20];
x_is_csr_o <= (d_opcode == `OPC_SYSTEM) && (d_fun != 0); 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); x_is_eret_o <= (d_opcode == `OPC_SYSTEM) && (d_fun == 0) && (f_ir_i [31:20] == 12'b000100000000);
end end
assign x_is_shift_o = x_is_shift; assign x_is_shift_o = x_is_shift;
assign x_rd_write_o = x_rd_write; assign x_rd_write_o = x_rd_write;
endmodule // rv_decode
endmodule // rv_predecode
/* /*
uRV - a tiny and dumb RISC-V core 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 This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
...@@ -18,6 +19,8 @@ ...@@ -18,6 +19,8 @@
*/ */
`include "urv_config.v"
`define OPC_OP_IMM 5'b00100 `define OPC_OP_IMM 5'b00100
`define OPC_LUI 5'b01101 `define OPC_LUI 5'b01101
`define OPC_AUIPC 5'b00101 `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 `timescale 1ns/1ps
module rv_divide module urv_divide
( (
input clk_i, input clk_i,
input rst_i, input rst_i,
input x_stall_i, input x_stall_i,
input x_kill_i, input x_kill_i,
output x_stall_req_o, output x_stall_req_o,
...@@ -120,132 +142,3 @@ module rv_divide ...@@ -120,132 +142,3 @@ module rv_divide
endmodule // 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 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 This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
...@@ -16,13 +17,13 @@ ...@@ -16,13 +17,13 @@
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with this library. License along with this library.
*/ */
`include "rv_defs.v" `include "urv_defs.v"
`timescale 1ns/1ps `timescale 1ns/1ps
module rv_exceptions module urv_exceptions
( (
input clk_i, input clk_i,
input rst_i, input rst_i,
...@@ -192,7 +193,7 @@ module rv_exceptions ...@@ -192,7 +193,7 @@ module rv_exceptions
assign x_exception_pc_o = csr_mepc; assign x_exception_pc_o = csr_mepc;
assign x_exception_o = exception & !exception_pending; assign x_exception_o = exception & !exception_pending;
endmodule // rv_exceptions endmodule // urv_exceptions
/* /*
uRV - a tiny and dumb RISC-V core 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 This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
...@@ -18,11 +19,11 @@ ...@@ -18,11 +19,11 @@
*/ */
`include "rv_defs.v" `include "urv_defs.v"
`timescale 1ns/1ps `timescale 1ns/1ps
module rv_exec module urv_exec
( (
input clk_i, input clk_i,
input rst_i, input rst_i,
...@@ -124,19 +125,16 @@ module rv_exec ...@@ -124,19 +125,16 @@ module rv_exec
reg [31:0] dm_addr, dm_data_s, dm_select_s; 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_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_op2 = { d_is_signed_alu_op_i ? rs2[31] : 1'b0, rs2 };
wire [32:0] cmp_rs = cmp_op1 - cmp_op2; wire [32:0] cmp_rs = cmp_op1 - cmp_op2;
wire cmp_equal = (cmp_op1 == cmp_op2); wire cmp_equal = (cmp_op1 == cmp_op2);
wire cmp_lt = cmp_rs[32]; wire cmp_lt = cmp_rs[32];
reg f_branch_take; reg f_branch_take;
wire [31:0] rd_shifter;
wire [31:0] rd_csr; wire [31:0] rd_csr;
wire [31:0] rd_mul;
wire [31:0] rd_div; wire [31:0] rd_div;
wire exception; wire exception;
...@@ -144,8 +142,7 @@ module rv_exec ...@@ -144,8 +142,7 @@ module rv_exec
wire [31:0] csr_write_value; wire [31:0] csr_write_value;
wire [31:0] exception_address, exception_vector; wire [31:0] exception_address, exception_vector;
urv_csr csr_regs
rv_csr csr_regs
( (
.clk_i(clk_i), .clk_i(clk_i),
...@@ -174,7 +171,7 @@ module rv_exec ...@@ -174,7 +171,7 @@ module rv_exec
.csr_mcause_i(csr_mcause) .csr_mcause_i(csr_mcause)
); );
rv_exceptions exception_unit urv_exceptions exception_unit
( (
.clk_i(clk_i), .clk_i(clk_i),
.rst_i(rst_i), .rst_i(rst_i),
...@@ -226,6 +223,7 @@ module rv_exec ...@@ -226,6 +223,7 @@ module rv_exec
always@* 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 ); 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@* always@*
if(d_is_eret_i ) if(d_is_eret_i )
branch_target <= exception_address; branch_target <= exception_address;
...@@ -241,9 +239,10 @@ module rv_exec ...@@ -241,9 +239,10 @@ module rv_exec
alu_op2 <= d_use_op2_i ? d_alu_op2_i : rs2; alu_op2 <= d_use_op2_i ? d_alu_op2_i : rs2;
end 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_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 }; 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; reg [32:0] alu_addsub_result;
always@* always@*
...@@ -253,7 +252,7 @@ module rv_exec ...@@ -253,7 +252,7 @@ module rv_exec
alu_addsub_result <= alu_addsub_op1 - alu_addsub_op2; alu_addsub_result <= alu_addsub_op1 - alu_addsub_op2;
// the ALU itself // the rest of the ALU
always@* always@*
begin begin
case (d_fun_i) case (d_fun_i)
...@@ -273,8 +272,8 @@ module rv_exec ...@@ -273,8 +272,8 @@ module rv_exec
endcase // case (d_fun_i) endcase // case (d_fun_i)
end // always@ * end // always@ *
// barel shifter
rv_shifter shifter urv_shifter shifter
( (
.clk_i(clk_i), .clk_i(clk_i),
.rst_i(rst_i), .rst_i(rst_i),
...@@ -292,7 +291,7 @@ module rv_exec ...@@ -292,7 +291,7 @@ module rv_exec
wire divider_stall_req = 0; wire divider_stall_req = 0;
rv_multiply multiplier urv_multiply multiplier
( (
.clk_i(clk_i), .clk_i(clk_i),
.rst_i(rst_i), .rst_i(rst_i),
...@@ -307,7 +306,7 @@ module rv_exec ...@@ -307,7 +306,7 @@ module rv_exec
/* wire divider_stall_req; /* wire divider_stall_req;
wire [31:0] rd_divide; wire [31:0] rd_divide;
rv_divide divider urv_divide divider
( (
.clk_i(clk_i), .clk_i(clk_i),
.rst_i(rst_i), .rst_i(rst_i),
...@@ -415,11 +414,11 @@ module rv_exec ...@@ -415,11 +414,11 @@ module rv_exec
assign dm_data_s_o = dm_data_s; assign dm_data_s_o = dm_data_s;
assign dm_data_select_o = dm_select_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_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; 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) always@(posedge clk_i)
if (rst_i) begin if (rst_i) begin
f_branch_take <= 0; f_branch_take <= 0;
...@@ -432,11 +431,13 @@ module rv_exec ...@@ -432,11 +431,13 @@ module rv_exec
f_branch_take <= branch_take && !x_kill_i && d_valid_i; f_branch_take <= branch_take && !x_kill_i && d_valid_i;
w_rd_o <= d_rd_i; w_rd_o <= d_rd_i;
w_rd_value_o <= rd_value; w_rd_value_o <= rd_value;
w_rd_write_o <= d_rd_write_i && !x_kill_i && d_valid_i && !exception; 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_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_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_dm_addr_o <= dm_addr;
w_valid_o <= !exception; w_valid_o <= !exception;
end // else: !if(rst_i) end // else: !if(rst_i)
...@@ -444,18 +445,22 @@ module rv_exec ...@@ -444,18 +445,22 @@ module rv_exec
assign f_branch_take_o = f_branch_take; assign f_branch_take_o = f_branch_take;
// pipeline control: generate stall request signal
always@* always@*
// never stall on taken branch
if(f_branch_take) if(f_branch_take)
x_stall_req_o <= 0; x_stall_req_o <= 0;
else if(divider_stall_req) else if(divider_stall_req)
x_stall_req_o <= 1; 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) else if ((d_is_load_i || d_is_store_i) && d_valid_i && !x_kill_i && !dm_ready_i)
x_stall_req_o <= 1; x_stall_req_o <= 1;
else else
x_stall_req_o <= 0; x_stall_req_o <= 0;
endmodule endmodule // urv_exec
......
/* /*
uRV - a tiny and dumb RISC-V core 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 This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
...@@ -20,24 +21,23 @@ ...@@ -20,24 +21,23 @@
`timescale 1ns/1ps `timescale 1ns/1ps
module rv_fetch module urv_fetch
( (
input clk_i, input clk_i,
input rst_i, input rst_i,
input f_stall_i,
input f_kill_i,
output [31:0] im_addr_o, output [31:0] im_addr_o,
input [31:0] im_data_i, input [31:0] im_data_i,
input im_valid_i, input im_valid_i,
input f_stall_i, output reg f_valid_o,
input f_kill_i,
output [31:0] f_ir_o, output [31:0] f_ir_o,
output reg [31:0] f_pc_o, output reg [31:0] f_pc_o,
output reg [31:0] f_pc_plus_4_o, output reg [31:0] f_pc_plus_4_o,
output reg f_valid_o,
input [31:0] x_pc_bra_i, input [31:0] x_pc_bra_i,
input x_bra_i input x_bra_i
); );
...@@ -93,7 +93,7 @@ module rv_fetch ...@@ -93,7 +93,7 @@ module rv_fetch
end end
end // else: !if(rst_i) 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 `timescale 1ns/1ps
`include "urv_defs.v"
`ifdef URV_PLATFORM_SPARTAN6
module urv_iram module urv_iram
#( #(
parameter g_size = 65536, parameter g_size = 65536,
...@@ -92,7 +117,7 @@ module urv_iram ...@@ -92,7 +117,7 @@ module urv_iram
`RAM_INST(64K_31, RAMB16_S1_S1, 15:2, 31, 3) `RAM_INST(64K_31, RAMB16_S1_S1, 15:2, 31, 3)
end // if (g_size == 65536) 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_0, RAMB16_S4_S4, 13:2, 3:0, 0)
`RAM_INST(16K_1, RAMB16_S4_S4, 13:2, 7:4, 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) `RAM_INST(16K_2, RAMB16_S4_S4, 13:2, 11:8, 1)
...@@ -101,7 +126,10 @@ module urv_iram ...@@ -101,7 +126,10 @@ module urv_iram
`RAM_INST(16K_5, RAMB16_S4_S4, 13:2, 23:20, 2) `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_6, RAMB16_S4_S4, 13:2, 27:24, 3)
`RAM_INST(16K_7, RAMB16_S4_S4, 13:2, 31:28, 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) end else begin // if (!g_simulation)
...@@ -195,3 +223,82 @@ module urv_iram ...@@ -195,3 +223,82 @@ module urv_iram
endmodule // 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 clk_i,
input rst_i, input rst_i,
...@@ -33,7 +52,7 @@ module rv_mult18x18 ...@@ -33,7 +52,7 @@ module rv_mult18x18
.OPMODEREG(0), .OPMODEREG(0),
.PREG(0), .PREG(0),
.RSTTYPE("SYNC") .RSTTYPE("SYNC")
) D1 ( ) D1 (
.BCOUT(), .BCOUT(),
.PCOUT(), .PCOUT(),
.CARRYOUT(), .CARRYOUT(),
...@@ -64,14 +83,14 @@ module rv_mult18x18 ...@@ -64,14 +83,14 @@ module rv_mult18x18
.RSTM(rst_i), .RSTM(rst_i),
.RSTOPMODE(1'b0), .RSTOPMODE(1'b0),
.RSTP(1'b0) .RSTP(1'b0)
); );
endmodule // rv_mult18x18 endmodule // urv_mult18x18
`endif // `i `endif // `ifdef PLATFORM_SPARTAN6
// fdef ARCH_SPARTAN6
`ifdef ARCH_VIRTEX6
module rv_mult18x18 `ifdef URV_PLATFORM_GENERIC
module urv_mult18x18
( (
input clk_i, input clk_i,
input rst_i, input rst_i,
...@@ -89,12 +108,11 @@ module rv_mult18x18 ...@@ -89,12 +108,11 @@ module rv_mult18x18
if(!stall_i) if(!stall_i)
q_o <= x_i * y_i; q_o <= x_i * y_i;
endmodule // rv_mult18x18 endmodule // urv_mult18x18
`endif // `ifdef ARCH_VIRTEX6 `endif // `ifdef URV_PLATFORM_GENERIC
module rv_multiply module urv_multiply
( (
input clk_i, input clk_i,
input rst_i, input rst_i,
...@@ -108,8 +126,6 @@ module rv_multiply ...@@ -108,8 +126,6 @@ module rv_multiply
); );
wire[17:0] xl_u = {1'b0, d_rs1_i[16:0] }; wire[17:0] xl_u = {1'b0, d_rs1_i[16:0] };
wire[17:0] yl_u = {1'b0, d_rs2_i[16:0] }; wire[17:0] yl_u = {1'b0, d_rs2_i[16:0] };
...@@ -121,7 +137,7 @@ module rv_multiply ...@@ -121,7 +137,7 @@ module rv_multiply
wire [35:0] yl_xl, yl_xh, yh_xl; wire [35:0] yl_xl, yl_xh, yh_xl;
rv_mult18x18 U_mul0 urv_mult18x18 mul0
( (
.clk_i(clk_i), .clk_i(clk_i),
.rst_i(rst_i), .rst_i(rst_i),
...@@ -132,7 +148,7 @@ module rv_multiply ...@@ -132,7 +148,7 @@ module rv_multiply
.q_o(yl_xl) .q_o(yl_xl)
); );
rv_mult18x18 U_mul1 urv_mult18x18 mul1
( (
.clk_i(clk_i), .clk_i(clk_i),
.rst_i(rst_i), .rst_i(rst_i),
...@@ -143,7 +159,7 @@ module rv_multiply ...@@ -143,7 +159,7 @@ module rv_multiply
.q_o(yh_xl) .q_o(yh_xl)
); );
rv_mult18x18 U_mul2 urv_mult18x18 mul2
( (
.clk_i(clk_i), .clk_i(clk_i),
.rst_i(rst_i), .rst_i(rst_i),
...@@ -154,29 +170,12 @@ module rv_multiply ...@@ -154,29 +170,12 @@ module rv_multiply
.q_o(yl_xh) .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@* always@*
w_rd_o <= yl_xl + {yl_xh[14:0], 17'h0} + {yh_xl[14:0], 17'h0}; 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 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 This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
...@@ -18,17 +19,16 @@ ...@@ -18,17 +19,16 @@
*/ */
`include "rv_defs.v" `include "urv_defs.v"
`timescale 1ns/1ps `timescale 1ns/1ps
module rv_regmem module urv_regmem
( (
input clk_i, input clk_i,
input rst_i, input rst_i,
input en1_i, input en1_i,
input [4:0] a1_i, input [4:0] a1_i,
output reg [31:0] q1_o, output reg [31:0] q1_o,
...@@ -38,12 +38,6 @@ module rv_regmem ...@@ -38,12 +38,6 @@ module rv_regmem
); );
reg [31:0] ram [0:31]; reg [31:0] ram [0:31];
reg [31:0] bypass_r;
reg bypass;
reg [31:0] q1_int;
always@(posedge clk_i) always@(posedge clk_i)
if(en1_i) if(en1_i)
...@@ -53,20 +47,19 @@ module rv_regmem ...@@ -53,20 +47,19 @@ module rv_regmem
if(we2_i) if(we2_i)
ram[a2_i] <= d2_i; ram[a2_i] <= d2_i;
// synthesis translate_off // synthesis translate_off
initial begin : ram_init initial begin : ram_init
integer i; integer i;
for(i=0;i<32; i=i+1) begin for(i=0;i<32; i=i+1) begin
ram[i] = 0; ram[i] = 0;
end end
end end
// synthesis translate_on // synthesis translate_on
endmodule // rv_regmem2
endmodule
module rv_regfile module urv_regfile
( (
input clk_i, input clk_i,
input rst_i, input rst_i,
...@@ -96,7 +89,8 @@ module rv_regfile ...@@ -96,7 +89,8 @@ module rv_regfile
wire [31:0] rs2_regfile; wire [31:0] rs2_regfile;
wire write = (w_rd_store_i && (w_rd_i != 0)); wire write = (w_rd_store_i && (w_rd_i != 0));
rv_regmem bank0 ( urv_regmem bank0
(
.clk_i(clk_i), .clk_i(clk_i),
.rst_i (rst_i ), .rst_i (rst_i ),
.en1_i(!d_stall_i), .en1_i(!d_stall_i),
...@@ -108,7 +102,8 @@ module rv_regfile ...@@ -108,7 +102,8 @@ module rv_regfile
.we2_i (write)); .we2_i (write));
rv_regmem bank1 ( urv_regmem bank1
(
.clk_i(clk_i), .clk_i(clk_i),
.rst_i (rst_i ), .rst_i (rst_i ),
.en1_i(!d_stall_i), .en1_i(!d_stall_i),
...@@ -162,129 +157,5 @@ module rv_regfile ...@@ -162,129 +157,5 @@ module rv_regfile
endcase // case ( {rs2_bypass_x, rs2_bypass_w } ) endcase // case ( {rs2_bypass_x, rs2_bypass_w } )
end // always@ * end // always@ *
endmodule // urv_regfile
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
/* /*
uRV - a tiny and dumb RISC-V core 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 This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
...@@ -18,7 +19,7 @@ ...@@ -18,7 +19,7 @@
*/ */
`include "rv_defs.v" `include "urv_defs.v"
`timescale 1ns/1ps `timescale 1ns/1ps
...@@ -28,7 +29,7 @@ ...@@ -28,7 +29,7 @@
x[16], x[17], x[18], x[19], x[20], x[21], x[22], x[23], \ 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] } 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 clk_i,
input rst_i, input rst_i,
...@@ -37,16 +38,16 @@ module rv_shifter ...@@ -37,16 +38,16 @@ module rv_shifter
input d_valid_i, input d_valid_i,
input [31:0] d_rs1_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 [4:0] d_shamt_i,
input [2:0] d_fun_i, input [2:0] d_fun_i,
input d_shifter_sign_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; 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; reg [31:0] shift_pre, shift_16, shift_8, s1_out;
// stage 1 // stage 1
...@@ -73,16 +74,6 @@ module rv_shifter ...@@ -73,16 +74,6 @@ module rv_shifter
s1_out <= shift_8; s1_out <= shift_8;
end 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; reg [31:0] shift_4, shift_2, shift_1, shift_post;
// stage 2 // stage 2
...@@ -94,109 +85,8 @@ module rv_shifter ...@@ -94,109 +85,8 @@ module rv_shifter
shift_post <= (s2_func == `FUNC_SL) ? `reverse_bits(shift_1) : shift_1; shift_post <= (s2_func == `FUNC_SL) ? `reverse_bits(shift_1) : shift_1;
end end
/* -----\/----- EXCLUDED -----\/-----
always@(posedge clk_i)
if(!x_stall_i)
w_rd_o <= shift_post;
-----/\----- EXCLUDED -----/\----- */
always@* always@*
w_rd_o <= shift_post; w_rd_o <= shift_post;
endmodule // rv_shifter endmodule // urv_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
/* /*
uRV - a tiny and dumb RISC-V core 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 This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
...@@ -18,11 +19,11 @@ ...@@ -18,11 +19,11 @@
*/ */
`include "rv_defs.v" `include "urv_defs.v"
`timescale 1ns/1ps `timescale 1ns/1ps
module rv_timer module urv_timer
( (
input clk_i, input clk_i,
input rst_i, input rst_i,
...@@ -76,4 +77,4 @@ module rv_timer ...@@ -76,4 +77,4 @@ module rv_timer
assign csr_cycles_o = cycles; assign csr_cycles_o = cycles;
assign sys_tick_o = presc_tick; assign sys_tick_o = presc_tick;
endmodule // rv_timer endmodule // urv_timer
/* /*
uRV - a tiny and dumb RISC-V core 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 This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
...@@ -18,17 +19,16 @@ ...@@ -18,17 +19,16 @@
*/ */
`include "rv_defs.v" `include "urv_defs.v"
`timescale 1ns/1ps `timescale 1ns/1ps
module rv_writeback module urv_writeback
( (
input clk_i, input clk_i,
input rst_i, input rst_i,
input w_stall_i, input w_stall_i,
output w_stall_req_o, output w_stall_req_o,
input [2:0] x_fun_i, input [2:0] x_fun_i,
...@@ -54,17 +54,11 @@ module rv_writeback ...@@ -54,17 +54,11 @@ module rv_writeback
output [31:0] rf_rd_value_o, output [31:0] rf_rd_value_o,
output [4:0] rf_rd_o, output [4:0] rf_rd_o,
output rf_rd_write_o, output rf_rd_write_o
output [31:0] TRIG2
); );
reg [31:0] load_value; reg [31:0] load_value;
// generate load value // generate load value
always@* always@*
begin begin
...@@ -110,7 +104,6 @@ module rv_writeback ...@@ -110,7 +104,6 @@ module rv_writeback
reg rf_rd_write; reg rf_rd_write;
reg [31:0] rf_rd_value; reg [31:0] rf_rd_value;
always@* always@*
if( x_load_i ) if( x_load_i )
rf_rd_value <= load_value; rf_rd_value <= load_value;
...@@ -139,10 +132,4 @@ module rv_writeback ...@@ -139,10 +132,4 @@ module rv_writeback
assign rf_rd_o = x_rd_i; 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 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; endmodule // urv_writeback
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
...@@ -24,7 +24,7 @@ use ieee.numeric_std.all; ...@@ -24,7 +24,7 @@ use ieee.numeric_std.all;
use work.wishbone_pkg.all; use work.wishbone_pkg.all;
use work.genram_pkg.all; use work.genram_pkg.all;
entity xrv_core is entity xurv_core is
generic ( generic (
g_internal_ram_size : integer := 65536; g_internal_ram_size : integer := 65536;
g_internal_ram_init_file : string := ""; g_internal_ram_init_file : string := "";
...@@ -47,13 +47,13 @@ entity xrv_core is ...@@ -47,13 +47,13 @@ entity xrv_core is
host_slave_i : in t_wishbone_slave_in := cc_dummy_slave_in; host_slave_i : in t_wishbone_slave_in := cc_dummy_slave_in;
host_slave_o : out t_wishbone_slave_out 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); constant c_mem_address_bits : integer := f_ceil_log2(g_internal_ram_size / 4);
component rv_cpu is component urv_cpu is
port( port(
clk_i : in std_logic; clk_i : in std_logic;
rst_i : in std_logic; rst_i : in std_logic;
...@@ -90,13 +90,13 @@ architecture wrapper of xrv_core is ...@@ -90,13 +90,13 @@ architecture wrapper of xrv_core is
aa_i : in std_logic_vector(31 downto 0); aa_i : in std_logic_vector(31 downto 0);
bwea_i : in std_logic_vector(3 downto 0); bwea_i : in std_logic_vector(3 downto 0);
da_i : in std_logic_vector(31 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; enb_i : in std_logic;
web_i : in std_logic; web_i : in std_logic;
ab_i : in std_logic_vector(31 downto 0); ab_i : in std_logic_vector(31 downto 0);
bweb_i : in std_logic_vector(3 downto 0); bweb_i : in std_logic_vector(3 downto 0);
db_i : in std_logic_vector(31 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; end component;
...@@ -232,7 +232,7 @@ begin ...@@ -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); im_addr_muxed <= ha_im_addr when ha_im_access = '1' else im_addr(g_address_bits-1 downto 0);
dm_ready <= '1'; dm_ready <= '1';
cpu_core : rv_cpu cpu_core : urv_cpu
port map ( port map (
clk_i => clk_sys_i, clk_i => clk_sys_i,
rst_i => cpu_rst, 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