diff --git a/Makefile b/Makefile
index d5840b3c..bd83b2db 100644
--- a/Makefile
+++ b/Makefile
@@ -61,11 +61,20 @@ Target = atombones
VC = verilator
VFLAGS = -cc -Wall --relative-includes --trace -D__ATOMSIM_SIMULATION__
+verilog_files = $(rtl_dir)/Timescale.vh
+verilog_files += $(rtl_dir)/core/Utils.vh
+verilog_files += $(rtl_dir)/core/Defs.vh
+verilog_files += $(rtl_dir)/core/AtomRV.v
+verilog_files += $(rtl_dir)/core/Alu.v
+verilog_files += $(rtl_dir)/core/Decode.v
+verilog_files += $(rtl_dir)/core/RegisterFile.v
+verilog_files += $(rtl_dir)/core/CSR_Unit.v
+
# Target Specific definitions
ifeq ($(Target), atombones) # ----- AtomBones -----
verilog_topmodule = AtomBones
verilog_topmodule_file = $(rtl_dir)/$(verilog_topmodule).v
-verilog_files = $(verilog_topmodule_file) $(rtl_dir)/Timescale.vh $(rtl_dir)/Config.vh $(rtl_dir)/core/AtomRV.v $(rtl_dir)/core/Alu.v $(rtl_dir)/core/Decode.v $(rtl_dir)/core/RegisterFile.v $(rtl_dir)/core/CSR_Unit.v
+verilog_files += $(verilog_topmodule_file)
sim_cpp_backend = $(sim_dir)/Backend_AtomBones.hpp
CFLAGS += -DTARGET_ATOMBONES
@@ -73,7 +82,17 @@ else
ifeq ($(Target), hydrogensoc) # ----- HydrogenSoC -----
verilog_topmodule = HydrogenSoC
verilog_topmodule_file = $(rtl_dir)/$(verilog_topmodule).v
-verilog_files = $(verilog_topmodule_file) $(rtl_dir)/Timescale.vh $(rtl_dir)/Config.vh $(rtl_dir)/uncore/BiDirectionalIO.v $(rtl_dir)/uncore/GPIO.v $(rtl_dir)/uncore/DualPortRAM_wb.v $(rtl_dir)/uncore/SinglePortRAM_wb.v $(rtl_dir)/uncore/simpleuart_wb.v $(rtl_dir)/uncore/simpleuart.v $(rtl_dir)/core/AtomRV_wb.v $(rtl_dir)/core/AtomRV.v $(rtl_dir)/core/Alu.v $(rtl_dir)/core/Decode.v $(rtl_dir)/core/RegisterFile.v $(rtl_dir)/core/CSR_Unit.v
+
+verilog_files += $(rtl_dir)/core/AtomRV_wb.v
+verilog_files += $(rtl_dir)/uncore/BiDirectionalIO.v
+verilog_files += $(rtl_dir)/uncore/GPIO.v
+verilog_files += $(rtl_dir)/uncore/DualPortRAM_wb.v
+verilog_files += $(rtl_dir)/uncore/SinglePortRAM_wb.v
+verilog_files += $(rtl_dir)/uncore/simpleuart_wb.v
+verilog_files += $(rtl_dir)/uncore/simpleuart.v
+verilog_files += $(rtl_dir)/HydrogenSoC_Config.vh
+verilog_files += $(verilog_topmodule_file)
+
VFLAGS += -D__IMEM_INIT_FILE__='"$(RVATOM)/$(init_dir)/code.hex"'
VFLAGS += -D__DMEM_INIT_FILE__='"$(RVATOM)/$(init_dir)/data.hex"'
@@ -230,6 +249,7 @@ libs: $(build_dir) $(bin_dir)
@echo "$(COLOR_GREEN)>> Compiling software libraries ...$(COLOR_NC)"
cd sw/lib && make Target=$(Target)
+
# ======== Documentation ========
#~ docs : Generate atomsim C++ source documentation
.PHONY: docs
@@ -245,8 +265,6 @@ pdf-docs: docs $(doc_dir) $(doxygen_doc_dir)
mv doc/doxygen/latex/refman.pdf doc/Atomsim_source_documentation.pdf
-
-
# ======== clean ========
#~ clean : Clean atomsim build files
.PHONY: clean
diff --git a/boards/spartan6-mini/spartan6-mini.xise b/boards/spartan6-mini/spartan6-mini.xise
index 367bffa7..6a69ca27 100644
--- a/boards/spartan6-mini/spartan6-mini.xise
+++ b/boards/spartan6-mini/spartan6-mini.xise
@@ -319,6 +319,7 @@
+
@@ -359,11 +360,13 @@
-
+
+
+
diff --git a/install-toolchain.sh b/install-toolchain.sh
index 2440750c..76f1bb15 100755
--- a/install-toolchain.sh
+++ b/install-toolchain.sh
@@ -7,7 +7,7 @@ TOOLCHAIN_CONFIG=--enable-multilib
BUILD_JOBS=4
# Toolchain install root directory (Note: Toolchain will be installed inside a folder named TOOLCHAIN_NAME in the TOOLCHAIN_ROOTPATH)
-TOOLCHAIN_ROOTPATH=/home/frozenalpha/opt/riscv
+TOOLCHAIN_ROOTPATH=/home/${user}/opt/riscv
#########################################################
# You sould not change anything below this
diff --git a/rtl/AtomBones.v b/rtl/AtomBones.v
index a8e74c4f..06ad5d4f 100644
--- a/rtl/AtomBones.v
+++ b/rtl/AtomBones.v
@@ -1,10 +1,18 @@
-/**
- * Barebones Atom
- */
+///////////////////////////////////////////////////////////////////
+// File : AtomBones.v
+// Author : Saurabh Singh (saurabh.s99100@gmail.com)
+// Description : AtomBones is a wrapper for AtomRV_wb, it is a
+// stub SoC target for AtomSim, which uses software simulated
+// memories and communication modules.
+///////////////////////////////////////////////////////////////////
+
`include "Timescale.vh"
-`include "Config.vh"
+`include "AtomBones_Config.vh"
+
`include "core/AtomRV.v"
+`default_nettype none
+
module AtomBones
(
input wire clk_i,
@@ -26,22 +34,22 @@
input wire dmem_ack_i // DMEM Ack signal
);
-// Core
-AtomRV atom_core
-(
- .clk_i (clk_i),
- .rst_i (rst_i),
- .imem_addr_o (imem_addr_o),
- .imem_data_i (imem_data_i),
- .imem_valid_o (imem_valid_o),
- .imem_ack_i (imem_ack_i),
- .dmem_addr_o (dmem_addr_o),
- .dmem_data_i (dmem_data_i),
- .dmem_data_o (dmem_data_o),
- .dmem_sel_o (dmem_sel_o),
- .dmem_we_o (dmem_we_o),
- .dmem_valid_o (dmem_valid_o),
- .dmem_ack_i (dmem_ack_i)
-);
+ // Core
+ AtomRV atom_core
+ (
+ .clk_i (clk_i),
+ .rst_i (rst_i),
+ .imem_addr_o (imem_addr_o),
+ .imem_data_i (imem_data_i),
+ .imem_valid_o (imem_valid_o),
+ .imem_ack_i (imem_ack_i),
+ .dmem_addr_o (dmem_addr_o),
+ .dmem_data_i (dmem_data_i),
+ .dmem_data_o (dmem_data_o),
+ .dmem_sel_o (dmem_sel_o),
+ .dmem_we_o (dmem_we_o),
+ .dmem_valid_o (dmem_valid_o),
+ .dmem_ack_i (dmem_ack_i)
+ );
endmodule
\ No newline at end of file
diff --git a/rtl/AtomBones_Config.vh b/rtl/AtomBones_Config.vh
new file mode 100644
index 00000000..8cea5e90
--- /dev/null
+++ b/rtl/AtomBones_Config.vh
@@ -0,0 +1,24 @@
+`ifndef __HYDROGENSOC_CONFIG_VH__
+`define __HYDROGENSOC_CONFIG_VH__
+
+// Reset address
+`define SOC_RESET_ADDRESS 32'h00000000
+
+// Atombones doesn't need the following parameters since everything
+// other that the core is software simulated
+
+// SoC Peripherals
+
+// IRAM
+// `define IRAM_ADDR 32'h00000000 // 0 GB boundry
+// `define IRAM_SIZE 32'h00008000 // 32 KB
+
+// // RAM
+// `define RAM_ADDR 32'h04000000 // 0.5 GB boundry
+// `define RAM_SIZE 32'h00002000 // 8 KB
+
+// // UART
+// `define UART_ADDR 32'h08000000 // 1.0 GB boundry
+// `define UART_SIZE 32'h00000008 // 8 bytes
+
+`endif //__HYDROGENSOC_CONFIG_VH__
\ No newline at end of file
diff --git a/rtl/Config.vh b/rtl/Config.vh
deleted file mode 100644
index 97967a61..00000000
--- a/rtl/Config.vh
+++ /dev/null
@@ -1,30 +0,0 @@
-// Config file
-`define RESET_PC_ADDRESS 32'h0000000
-
-`define __NOP_INSTRUCTION__ 32'h00000013 // NOP = addi x0, x0, 0
-
-// IMM_TYPE
-`define __I_IMMIDIATE__ 3'd0
-`define __S_IMMIDIATE__ 3'd1
-`define __B_IMMIDIATE__ 3'd2
-`define __U_IMMIDIATE__ 3'd3
-`define __J_IMMIDIATE__ 3'd4
-
-// ALU
-`define __ALU_ADD__ 3'd0
-`define __ALU_SUB__ 3'd1
-`define __ALU_XOR__ 3'd2
-`define __ALU_OR__ 3'd3
-`define __ALU_AND__ 3'd4
-`define __ALU_SLL__ 3'd5
-`define __ALU_SRL__ 3'd6
-`define __ALU_SRA__ 3'd7
-
-// COMPARATOR
-`define __CMP_UN__ 3'd0
-`define __CMP_EQ__ 3'd1
-`define __CMP_NQ__ 3'd2
-`define __CMP_LT__ 3'd3
-`define __CMP_GE__ 3'd4
-`define __CMP_LTU__ 3'd5
-`define __CMP_GEU__ 3'd6
diff --git a/rtl/HydrogenSoC.v b/rtl/HydrogenSoC.v
index a09e7fa5..0c454731 100644
--- a/rtl/HydrogenSoC.v
+++ b/rtl/HydrogenSoC.v
@@ -1,7 +1,13 @@
-`default_nettype none
+///////////////////////////////////////////////////////////////////
+// File : HydrogenSoC.v
+// Author : Saurabh Singh (saurabh.s99100@gmail.com)
+// Description : HydrogenSoC is an FPGA ready SoC, it consists of
+// a single atom core with memories and communication modules.
+///////////////////////////////////////////////////////////////////
`include "Timescale.vh"
-`include "Config.vh"
+`include "HydrogenSoC_Config.vh"
+
`include "core/AtomRV_wb.v"
`include "uncore/DualPortRAM_wb.v"
//`include "uncore/SinglePortROM_wb.v"
@@ -10,52 +16,49 @@
`include "uncore/GPIO.v"
`ifndef verilator
-// Defaults for Xilinx ISE
-`define __IMEM_INIT_FILE__ "code.hex"
-`define __DMEM_INIT_FILE__ "data.hex"
+ // Defaults for Xilinx ISE
+ `define __IMEM_INIT_FILE__ "code.hex"
+ `define __DMEM_INIT_FILE__ "data.hex"
`endif
-/**
- * === Hydrogen SoC ===
- * Barebone SoC housing a single atom core, instruction memory, data memory and a uart slave.
- */
+`default_nettype none
module HydrogenSoC
(
- // GLOBAL SIGNALS
- input wire clk_i,
- input wire rst_i,
-
- // GPIO
- inout wire [31:0] gpio_io,
+ // GLOBAL SIGNALS
+ input wire clk_i,
+ input wire rst_i,
+
+ // GPIO
+ inout wire [31:0] gpio_io,
// UART
input wire uart_usb_rx_i,
output wire uart_usb_tx_o,
- input wire uart_io_rx_i,
+ input wire uart_io_rx_i,
output wire uart_io_tx_o,
-
- // UART MUX
- input wire uart_mux_sel,
-
- // TEST POINTS
- output wire uart_rx_test_point_o,
- output wire uart_tx_test_point_o
+
+ // UART MUX
+ input wire uart_mux_sel,
+
+ // TEST POINTS
+ output wire uart_rx_test_point_o,
+ output wire uart_tx_test_point_o
);
- ////////////////////////////////////////
- // UART MUX
- wire uart_rx = uart_mux_sel ? uart_io_rx_i : uart_usb_rx_i;
-
- wire uart_tx;
- assign uart_io_tx_o = uart_mux_sel ? uart_tx : 1'b1;
- assign uart_usb_tx_o = uart_mux_sel ? 1'b1 : uart_tx;
-
- // TEST POINTS
- assign uart_rx_test_point_o = uart_rx;
- assign uart_tx_test_point_o = uart_tx;
-
-
+ ////////////////////////////////////////
+ // UART MUX
+ wire uart_rx = uart_mux_sel ? uart_io_rx_i : uart_usb_rx_i;
+
+ wire uart_tx;
+ assign uart_io_tx_o = uart_mux_sel ? uart_tx : 1'b1;
+ assign uart_usb_tx_o = uart_mux_sel ? 1'b1 : uart_tx;
+
+ // TEST POINTS
+ assign uart_rx_test_point_o = uart_rx;
+ assign uart_tx_test_point_o = uart_tx;
+
+
//////////////////////////////////////////
// SoC Parameters
@@ -68,9 +71,8 @@ module HydrogenSoC
wire wb_clk_i = clk_i;
wire wb_rst_i = rst_i;
- /* verilator lint_off UNUSED */
wire [31:0] wb_ibus_adr_o;
- /* verilator lint_on UNUSED */
+ `UNUSED_VAR(wb_ibus_adr_o)
wire [31:0] wb_ibus_dat_i;
wire wb_ibus_ack_i;
@@ -84,11 +86,8 @@ module HydrogenSoC
wire [3:0] wb_dbus_sel_o /* verilator public */;
wire wb_dbus_stb_o /* verilator public */;
reg wb_dbus_ack_i /* verilator public */;
-
- /* verilator lint_off UNUSED */
wire wb_dbus_cyc_o /* verilator public */;
- /* verilator lint_on UNUSED */
-
+
/////////////////////////////////////////////////
@@ -205,7 +204,7 @@ module HydrogenSoC
reg wb_uart_stb_i;
wire wb_uart_ack_o;
- simpleuart_wb uart (
+ simpleuart_wb uart (
.wb_clk_i (wb_clk_i),
.wb_rst_i (wb_rst_i),
@@ -220,7 +219,7 @@ module HydrogenSoC
.rx_i (uart_rx),
.tx_o (uart_tx)
- );
+ );
////////////////////////////////////////////////////
@@ -285,28 +284,34 @@ module HydrogenSoC
*/
reg [3:0] selected_device /* verilator public */;
always @(*) begin /* COMBINATORIAL */
- // default
- //selected_device = Device_None;
-
+ // default
+ //selected_device = Device_None;
+
if(wb_dbus_cyc_o) begin
- if(wb_dbus_adr_o < 32'h00008000)
+ /* verilator lint_off UNSIGNED */
+ if(wb_dbus_adr_o >= `IRAM_ADDR && wb_dbus_adr_o < `IRAM_ADDR+`IRAM_SIZE)
selected_device = Device_IRAM;
+ /* verilator lint_on UNSIGNED */
- else if(wb_dbus_adr_o >= 32'h04000000 && wb_dbus_adr_o < 32'h04002000)
+ else if(wb_dbus_adr_o >= `RAM_ADDR && wb_dbus_adr_o < `RAM_ADDR+`RAM_SIZE)
selected_device = Device_RAM;
- else if (wb_dbus_adr_o == 32'h08000000 || wb_dbus_adr_o == 32'h08000004)
+ else if (wb_dbus_adr_o >= `UART_ADDR && wb_dbus_adr_o < `UART_ADDR+`UART_SIZE)
selected_device = Device_UART;
-
- else if (wb_dbus_adr_o == 32'h08000100) // byte addresses 8000010 to 0800001f
+
+ else if (wb_dbus_adr_o >= `GPIO0_ADDR && wb_dbus_adr_o < `GPIO0_ADDR+`GPIO0_SIZE)
selected_device = Device_GPIO0;
- else if (wb_dbus_adr_o == 32'h08000104) // byte addresses 8000010 to 0800001f
+
+ else if (wb_dbus_adr_o >= `GPIO1_ADDR && wb_dbus_adr_o < `GPIO1_ADDR+`GPIO1_SIZE)
selected_device = Device_GPIO1;
else begin
- selected_device = Device_None;
- $display("RTL-ERROR: Unknown Device Selected: 0x%x\nHaulting simulation...", wb_dbus_adr_o);
- $finish();
+ selected_device = Device_None;
+
+ `ifdef verilator
+ $display("RTL-ERROR: Unknown Device Selected: 0x%x\nHaulting simulation...", wb_dbus_adr_o);
+ $finish();
+ `endif
end
end
else begin
@@ -341,13 +346,13 @@ module HydrogenSoC
logic.
*/
always @(*) begin /* COMBINATORIAL */
- // Defaults
- wb_ram_stb_i = 1'b0;
+ // Defaults
+ wb_ram_stb_i = 1'b0;
wb_iram_stb_i = 1'b0;
- wb_uart_stb_i = 1'b0;
- wb_gpio0_stb_i = 1'b0;
- wb_gpio1_stb_i = 1'b0;
-
+ wb_uart_stb_i = 1'b0;
+ wb_gpio0_stb_i = 1'b0;
+ wb_gpio1_stb_i = 1'b0;
+
case(selected_device)
Device_RAM: wb_ram_stb_i = wb_dbus_stb_o;
Device_IRAM: wb_iram_stb_i = wb_dbus_stb_o;
diff --git a/rtl/HydrogenSoC_Config.vh b/rtl/HydrogenSoC_Config.vh
new file mode 100644
index 00000000..4c1fd355
--- /dev/null
+++ b/rtl/HydrogenSoC_Config.vh
@@ -0,0 +1,37 @@
+////////////////////////////////////////////////////////////////////
+// File : HydrogeSoC_Config.vh
+// Author : Saurabh Singh (saurabh.s99100@gmail.com)
+// Description : Configuration file for HydrogenSoC. It defines the
+// HydrogensoC related parameters using verilog preprocessor macros.
+////////////////////////////////////////////////////////////////////
+
+`ifndef __HYDROGENSOC_CONFIG_VH__
+`define __HYDROGENSOC_CONFIG_VH__
+
+// Reset address
+`define SOC_RESET_ADDRESS 32'h00000000
+
+// SoC Peripherals
+
+// IRAM
+`define IRAM_ADDR 32'h00000000 // 0 GB boundry
+`define IRAM_SIZE 32'h00008000 // 32 KB
+
+// RAM
+`define RAM_ADDR 32'h04000000 // 0.5 GB boundry
+`define RAM_SIZE 32'h00002000 // 8 KB
+
+// UART
+`define UART_ADDR 32'h08000000 // 1.0 GB boundry
+`define UART_SIZE 32'h00000008 // 8 bytes
+
+// GPIO 0
+`define GPIO0_ADDR 32'h08000100
+`define GPIO0_SIZE 32'h00000004 // 4 bytes
+
+// GPIO 1
+`define GPIO1_ADDR 32'h08000104
+`define GPIO1_SIZE 32'h00000004 // 4 bytes
+
+
+`endif // __HYDROGENSOC_CONFIG_VH__
diff --git a/rtl/Timescale.vh b/rtl/Timescale.vh
index 0bcfdef3..fc3511b9 100644
--- a/rtl/Timescale.vh
+++ b/rtl/Timescale.vh
@@ -1 +1,12 @@
-`timescale 1ns/1ps
\ No newline at end of file
+///////////////////////////////////////////////////////////////////
+// File : Timescale.vh
+// Author : Saurabh Singh (saurabh.s99100@gmail.com)
+// Description : Timescale header file
+///////////////////////////////////////////////////////////////////
+
+`ifndef __TIMESCALE_VH__
+`define __TIMESCALE_VH__
+
+`timescale 1ns/1ps
+
+`endif // __TIMESCALE_VH__
\ No newline at end of file
diff --git a/rtl/core/Alu.v b/rtl/core/Alu.v
index 85808d1d..d9b63ce5 100644
--- a/rtl/core/Alu.v
+++ b/rtl/core/Alu.v
@@ -1,38 +1,94 @@
////////////////////////////////////////////////////////////////////
-// RISC-V Atom
-//
-// File : Alu.v
-//
-// Description : Arithmetic and logic unit for Atom core
+// File : Alu.v
+// Author : Saurabh Singh (saurabh.s99100@gmail.com)
+// Description : Arithmetic and logic unit for Atom core, following
+// Operations are built into the alu:
+// - Addition
+// - Subtraction
+// - Bitwise XOR
+// - Bitwise OR,
+// - Bitwise AND,
+// - Logical Shift Left (Single Cycle)
+// - Logical Shift Right (Single Cycle)
+// - Arthmetic Shift Right (Single Cycle)
////////////////////////////////////////////////////////////////////
-`default_nettype none
`include "../Timescale.vh"
+`include "Defs.vh"
+
+`default_nettype none
module Alu
(
- input wire [31:0] A,
- input wire [31:0] B,
- input wire [2:0] Sel,
+ input wire [31:0] a_i,
+ input wire [31:0] b_i,
+ input wire [2:0] sel_i,
- output reg [31:0] Out
+ output reg [31:0] result_o
);
-wire signed [31:0] A_s = A;
+ wire sel_add = (sel_i == `ALU_FUNC_ADD);
+ wire sel_sub = (sel_i == `ALU_FUNC_SUB);
+ wire sel_xor = (sel_i == `ALU_FUNC_XOR);
+ wire sel_or = (sel_i == `ALU_FUNC_OR);
+ wire sel_and = (sel_i == `ALU_FUNC_AND);
+ wire sel_sll = (sel_i == `ALU_FUNC_SLL);
+ wire sel_srl = (sel_i == `ALU_FUNC_SRL);
+ wire sel_sra = (sel_i == `ALU_FUNC_SRA);
+
+ // Result of arithmetic calculations (ADD/SUB)
+ wire [31:0] arith_result = a_i + (sel_sub ? ((~b_i)+1) : b_i);
+
+ // Bitreverse
+ function [31:0] reverse;
+ input [31:0] ain;
+ integer i;
+ begin
+ for(i=0; i<32; i=i+1) begin
+ reverse[32-1-i] = ain[i];
+ end
+ end
+ endfunction
+
+ // Input to the universal shifter
+ reg signed [32:0] shift_input;
+ always @(*) begin
+ if (sel_srl)
+ shift_input = {1'b0, a_i};
+ else if (sel_sra)
+ shift_input = {a_i[31], a_i};
+ else // if (sel_sll) // this case includes "sel_sll"
+ shift_input = {1'b0, reverse(a_i)};
+ end
+
+ /* verilator lint_off UNUSED */
+ wire [32:0] shift_output = shift_input >>> b_i[4:0]; // Universal shifter
+ /* verilator lint_on UNUSED */
-always @(*) begin
- case(Sel)
- `__ALU_ADD__: Out = A + B;
- `__ALU_SUB__: Out = A - B;
- `__ALU_XOR__: Out = A ^ B;
- `__ALU_OR__ : Out = A | B;
- `__ALU_AND__: Out = A & B;
- `__ALU_SLL__: Out = A << B[4:0];
- `__ALU_SRL__: Out = A >> B[4:0];
- `__ALU_SRA__: Out = A_s >>> B[4:0];
+ // output of universal shifter
+ reg [31:0] final_shift_output;
+ always @(*) begin
+ if (sel_sll)
+ final_shift_output = reverse(shift_output[31:0]);
+ else
+ final_shift_output = shift_output[31:0];
+ end
+
+ // Final output mux
+ always @(*) begin
+ if (sel_add | sel_sub)
+ result_o = arith_result;
+ else if (sel_sll | sel_srl | sel_sra)
+ result_o = final_shift_output;
+ else if (sel_xor)
+ result_o = a_i ^ b_i;
+ else if (sel_or)
+ result_o = a_i | b_i;
+ else if (sel_and)
+ result_o = a_i & b_i;
+ else
+ result_o = arith_result;
+ end
- default: Out = 32'd0;
- endcase
-end
endmodule
\ No newline at end of file
diff --git a/rtl/core/AtomRV.v b/rtl/core/AtomRV.v
index 40ba8b1c..a0db686f 100644
--- a/rtl/core/AtomRV.v
+++ b/rtl/core/AtomRV.v
@@ -5,24 +5,22 @@
// / _, _// / ___/ / /___ | |/ / / /_/ / /_/ /_/ / / / / / /
// /_/ |_/___//____/\____/ |___/ \__,_/\__/\____/_/ /_/ /_/
//
-// File : AtomRV.v
-// Author : Saurabh Singh (saurabh.s99100@gmail.com)
-// Description: Nano-RISCV core is a non pipelined embedded class
-// 32 bit RISCV core. It is based on RV32I ISA
-//
+// File : AtomRV.v
+// Author : Saurabh Singh (saurabh.s99100@gmail.com)
+// Description : Atom is a 2-stage pipelined embedded class 32-bit
+// RISCV core. It is based on RV32I ISA
///////////////////////////////////////////////////////////////////
-`default_nettype none
-
-`define __R0_IS_ZERO__
`include "../Timescale.vh"
-`include "../Config.vh"
+`include "Defs.vh"
`include "Decode.v"
`include "RegisterFile.v"
`include "Alu.v"
`include "CSR_Unit.v"
+`default_nettype none
+
module AtomRV
(
// ========== General ==========
@@ -50,436 +48,436 @@ module AtomRV
output wire dmem_valid_o, // DMEM Valid signal
input wire dmem_ack_i // DMEM Ack signal
);
-/*
- ///////////// Protocol specification //////////////
- CPU has a generic handshaking protocol interface (GHPI). Handshaking is done via means
- of two signals 'valid' & 'ack'. Valid signal is set by master whenever a transaction
- begins and slave responds by setting the 'ack' signal. When both signals are set,
- transaction takes place. GHPI protocol also supports delayed transactions.
-
- CPU has two GHPI ports namely imem & dmem ports. imem port is used only for reading
- the memory while dmem pot is used for both eads and writes. The CPU ca ne configured in
- both Harvard and Von-Neumann fashion. In case of Harvard configuration, separate instruction
- and data memory ae needed to be connected. In case of Von-Neumann mode, a bus arbiter is
- needed to multiplex between both ports.
-
- Reads:
- - Master sets the address, the valid signal and clears the strobe signal.
- - Slave responds by providing the data corresponding to that address & setting the ack signal.
-
- Writes:
- - Master sets the address, the data, the valid signal and the strobe signal (depending on
- the write width).
- - Slave responds by setting the ack signal.
-*/
-
-wire jump_decision = d_jump_en & comparison_result; // final jump decision signal
-
-////////////////////////////////////////////////////////////////////
-// PIPELINE CONTROL
-/*
- Raw handshaking signal: These signals make the handshaking of ibus
- Fetch stage relies on the imem handshake signal to increment PC.
-
- We dont ever need to ignore the dmem handshake because ignoring dmem handshake only happens if
- currently executing instruction happens to be a load-store instruction, but since currrent
- instruction is a jump, there is no memory request made anyways.
-*/
-wire raw_imem_handshake = (imem_valid_o && imem_ack_i);
-
-wire imem_handshake = raw_imem_handshake && !ignore_imem_handshake;
-wire dmem_handshake = (dmem_valid_o && dmem_ack_i);
-
-/*
- Definition of stall:
- Stall is a state of a pipeline stage in which the current instuction cannot popogate forward.
-
- Definition of flush:
- Flush is defined as insertion of nop in the pipeline in order to prevent an unwanted instuction
- to execute.
-*/
-
-/*
- Stall Stage2 in case it has made a memory request and the result has't arrived yet.
-*/
-wire waiting_for_dbus_response = (!dmem_handshake && dmem_valid_o);
-wire stall_stage2 = waiting_for_dbus_response;
-
-/*
- Stall Stage1 in case:
- - Stage1 is waiting for response of a memory request that is has made.
- - Stage2 is stalled, since the instruction in stage1 cant popogate to stage2. Therefore until
- the stage2 is stalled, instruction in stage1 is kept held.
-*/
-wire waiting_for_ibus_response = (!imem_handshake && imem_valid_o);
-wire stall_stage1 = waiting_for_ibus_response || stall_stage2;
-
-/*
- Flush pipeline (insert nop in s2) in case:
- - there is a jump
- - Stage1 is stalled and stage is not, in this case stage can't recieve an new instruction to
- execute therefore a bubble is introduced.
- -
-*/
-wire flush_pipeline = jump_decision || (stall_stage2 ? 0 : stall_stage1);
-
-
-reg ignore_imem_handshake = 0;
-always @(posedge clk_i) begin
- if(rst_i)
- ignore_imem_handshake <= 0;
- else begin
- case(ignore_imem_handshake)
- 0: if(jump_decision)
- ignore_imem_handshake <= 1;
-
- 1: if(raw_imem_handshake)
- ignore_imem_handshake <= 0;
- endcase
- end
-end
-
-////////////////////////////////////////////////////////////////////
-// STAGE 1 - FETCH
-////////////////////////////////////////////////////////////////////
-assign imem_valid_o = !rst_i; // Always valid (Except on Reset condition)
-/*
- Program Counter
-*/
-reg [31:0] ProgramCounter /*verilator public*/;
-wire [31:0] pc_plus_four = ProgramCounter + 32'd4;
-
-always @(posedge clk_i) begin
- if(rst_i)
- ProgramCounter <= `RESET_PC_ADDRESS;
-
- else if(jump_decision)
- ProgramCounter <= {alu_out[31:1], 1'b0}; // Only jump to 16 bit aligned addresses, also JALR enforces this
-
- else if (!stall_stage1) begin
- ProgramCounter <= pc_plus_four;
- end
-end
-
-// Connect pc to imem address input
-assign imem_addr_o = ProgramCounter;
-
-
-//----------------------------------------------------------
-// PIPELINE REGISTERS
-//----------------------------------------------------------
-/*
- This register is used to store old value of program counter
-*/
-reg [31:0] ProgramCounter_Old /* verilator public */;
-always @(posedge clk_i) begin
- if(rst_i)
- ProgramCounter_Old <= 32'd0;
- else if(!stall_stage1)
- ProgramCounter_Old <= ProgramCounter;
-end
-
-/*
- This register is used to store old value of program counter + 4
-*/
-reg [31:0] link_address;
-always @(posedge clk_i) begin
- if(rst_i)
- link_address <= 32'd0;
- else if(!stall_stage1)
- link_address <= pc_plus_four;
-end
-
-/*
- This register is used to store current instruction that is being
- executed
-*/
-reg [31:0] InstructionRegister /*verilator public*/;
-always @(posedge clk_i) begin
- if(rst_i)
- InstructionRegister <= `__NOP_INSTRUCTION__;
- else begin
- if(flush_pipeline)
- InstructionRegister <= `__NOP_INSTRUCTION__;
-
- else if(!stall_stage1)
- InstructionRegister <= imem_data_i;
+ /*
+ ///////////// Protocol specification //////////////
+ CPU has a generic handshaking protocol interface (GHPI). Handshaking is done via means
+ of two signals 'valid' & 'ack'. Valid signal is set by master whenever a transaction
+ begins and slave responds by setting the 'ack' signal. When both signals are set,
+ transaction takes place. GHPI protocol also supports delayed transactions.
+
+ CPU has two GHPI ports namely imem & dmem ports. imem port is used only for reading
+ the memory while dmem pot is used for both eads and writes. The CPU ca ne configured in
+ both Harvard and Von-Neumann fashion. In case of Harvard configuration, separate instruction
+ and data memory ae needed to be connected. In case of Von-Neumann mode, a bus arbiter is
+ needed to multiplex between both ports.
+
+ Reads:
+ - Master sets the address, the valid signal and clears the strobe signal.
+ - Slave responds by providing the data corresponding to that address & setting the ack signal.
+
+ Writes:
+ - Master sets the address, the data, the valid signal and the strobe signal (depending on
+ the write width).
+ - Slave responds by setting the ack signal.
+ */
+
+ wire jump_decision = d_jump_en & comparison_result; // final jump decision signal
+
+ ////////////////////////////////////////////////////////////////////
+ // PIPELINE CONTROL
+ /*
+ Raw handshaking signal: These signals make the handshaking of ibus
+ Fetch stage relies on the imem handshake signal to increment PC.
+
+ We dont ever need to ignore the dmem handshake because ignoring dmem handshake only happens if
+ currently executing instruction happens to be a load-store instruction, but since currrent
+ instruction is a jump, there is no memory request made anyways.
+ */
+ wire raw_imem_handshake = (imem_valid_o && imem_ack_i);
+
+ wire imem_handshake = raw_imem_handshake && !ignore_imem_handshake;
+ wire dmem_handshake = (dmem_valid_o && dmem_ack_i);
+
+ /*
+ Definition of stall:
+ Stall is a state of a pipeline stage in which the current instuction cannot popogate forward.
+
+ Definition of flush:
+ Flush is defined as insertion of nop in the pipeline in order to prevent an unwanted instuction
+ to execute.
+ */
+
+ /*
+ Stall Stage2 in case it has made a memory request and the result has't arrived yet.
+ */
+ wire waiting_for_dbus_response = (!dmem_handshake && dmem_valid_o);
+ wire stall_stage2 = waiting_for_dbus_response;
+
+ /*
+ Stall Stage1 in case:
+ - Stage1 is waiting for response of a memory request that is has made.
+ - Stage2 is stalled, since the instruction in stage1 cant popogate to stage2. Therefore until
+ the stage2 is stalled, instruction in stage1 is kept held.
+ */
+ wire waiting_for_ibus_response = (!imem_handshake && imem_valid_o);
+ wire stall_stage1 = waiting_for_ibus_response || stall_stage2;
+
+ /*
+ Flush pipeline (insert nop in s2) in case:
+ - there is a jump
+ - Stage1 is stalled and stage is not, in this case stage can't recieve an new instruction to
+ execute therefore a bubble is introduced.
+ -
+ */
+ wire flush_pipeline = jump_decision || (stall_stage2 ? 0 : stall_stage1);
+
+
+ reg ignore_imem_handshake = 0;
+ always @(posedge clk_i) begin
+ if(rst_i)
+ ignore_imem_handshake <= 0;
+ else begin
+ case(ignore_imem_handshake)
+ 0: if(jump_decision)
+ ignore_imem_handshake <= 1;
+
+ 1: if(raw_imem_handshake)
+ ignore_imem_handshake <= 0;
+ endcase
+ end
end
-end
-
-
-
-////////////////////////////////////////////////////////////////////
-// STAGE 2 - DECODE & EXECUTE
-////////////////////////////////////////////////////////////////////
-/*
- ////// Instruction Decode //////
- Instruction decode unit decodes instruction and sets various control
- signals throughout the pipeline. Is also extracts immediate values
- from instructions and sign extends them properly.
-*/
-wire [4:0] d_rd_sel;
-wire [4:0] d_rs1_sel;
-wire [4:0] d_rs2_sel;
-wire [31:0] d_imm;
-
-wire d_jump_en;
-wire [2:0] d_comparison_type;
-wire d_rf_we;
-wire [2:0] d_rf_din_sel;
-wire d_a_op_sel;
-wire d_b_op_sel;
-wire d_cmp_b_op_sel;
-wire [2:0] d_alu_op_sel;
-wire [2:0] d_mem_access_width;
-wire d_mem_load_store;
-wire d_mem_we;
-wire [2:0] d_csru_op_sel;
-wire d_csru_we;
-
-
-Decode decode
-(
- .instr_i (InstructionRegister),
-
- .rd_sel_o (d_rd_sel),
- .rs1_sel_o (d_rs1_sel),
- .rs2_sel_o (d_rs2_sel),
-
- .imm_o (d_imm),
-
- .jump_en_o (d_jump_en),
- .comparison_type_o (d_comparison_type),
- .rf_we_o (d_rf_we),
- .rf_din_sel_o (d_rf_din_sel),
- .a_op_sel_o (d_a_op_sel),
- .b_op_sel_o (d_b_op_sel),
- .cmp_b_op_sel_o (d_cmp_b_op_sel),
- .alu_op_sel_o (d_alu_op_sel),
- .mem_access_width_o (d_mem_access_width),
- .d_mem_load_store (d_mem_load_store),
- .mem_we_o (d_mem_we),
- .csru_op_sel_o (d_csru_op_sel),
- .csru_we_o (d_csru_we)
-);
-
-
-
-/*
- ////// Register File //////
- Contains cpu registers (r0-31)
-*/
-// RF_Din Multiplexer
-reg [31:0] rf_rd_data;
-always @(*) begin
- case(d_rf_din_sel)
- 3'd0: rf_rd_data = d_imm;
- 3'd1: rf_rd_data = link_address;
- 3'd2: rf_rd_data = alu_out;
- 3'd3: rf_rd_data = {31'd0, comparison_result};
- 3'd4: rf_rd_data = memload;
- 3'd5: rf_rd_data = csru_data_o;
-
- default: rf_rd_data = 32'd0;
- endcase
-end
-
-wire [31:0] rf_rs1;
-wire [31:0] rf_rs2;
-
-RegisterFile #(.REG_WIDTH(32), .REG_ADDR_WIDTH(5)) rf
-(
- .Ra_Sel_i (d_rs1_sel),
- .Ra_o (rf_rs1),
-
- .Rb_Sel_i (d_rs2_sel),
- .Rb_o (rf_rs2),
+ ////////////////////////////////////////////////////////////////////
+ // STAGE 1 - FETCH
+ ////////////////////////////////////////////////////////////////////
+ assign imem_valid_o = !rst_i; // Always valid (Except on Reset condition)
+ /*
+ Program Counter
+ */
+ reg [31:0] ProgramCounter /*verilator public*/;
+ wire [31:0] pc_plus_four = ProgramCounter + 32'd4;
+
+ always @(posedge clk_i) begin
+ if(rst_i)
+ ProgramCounter <= `RESET_PC_ADDRESS;
+
+ else if(jump_decision)
+ ProgramCounter <= {alu_out[31:1], 1'b0}; // Only jump to 16 bit aligned addresses, also JALR enforces this
+
+ else if (!stall_stage1) begin
+ ProgramCounter <= pc_plus_four;
+ end
+ end
- .Data_We_i (d_rf_we & !stall_stage2),
- .Rd_Sel_i (d_rd_sel),
- .Data_i (rf_rd_data),
+ // Connect pc to imem address input
+ assign imem_addr_o = ProgramCounter;
- .Clk_i (clk_i),
- .Rst_i (rst_i)
-);
+ //----------------------------------------------------------
+ // PIPELINE REGISTERS
+ //----------------------------------------------------------
+ /*
+ This register is used to store old value of program counter
+ */
+ reg [31:0] ProgramCounter_Old /* verilator public */;
+ always @(posedge clk_i) begin
+ if(rst_i)
+ ProgramCounter_Old <= 32'd0;
+ else if(!stall_stage1)
+ ProgramCounter_Old <= ProgramCounter;
+ end
-/*
- ////// ALU //////
- Used for arithmetic and logical computations including shifts.
-*/
-wire [31:0] alu_a_in = (d_a_op_sel) ? ProgramCounter_Old : rf_rs1;
-wire [31:0] alu_b_in = (d_b_op_sel) ? d_imm : rf_rs2;
-wire [31:0] alu_out;
+ /*
+ This register is used to store old value of program counter + 4
+ */
+ reg [31:0] link_address;
+ always @(posedge clk_i) begin
+ if(rst_i)
+ link_address <= 32'd0;
+ else if(!stall_stage1)
+ link_address <= pc_plus_four;
+ end
-Alu alu
-(
- .A (alu_a_in),
- .B (alu_b_in),
- .Sel (d_alu_op_sel),
- .Out (alu_out)
-);
+ /*
+ This register is used to store current instruction that is being
+ executed
+ */
+ reg [31:0] InstructionRegister /*verilator public*/ = `RV_INSTR_NOP;
+ always @(posedge clk_i) begin
+ if(rst_i)
+ InstructionRegister <= `RV_INSTR_NOP;
+ else begin
+ if(flush_pipeline)
+ InstructionRegister <= `RV_INSTR_NOP;
+
+ else if(!stall_stage1)
+ InstructionRegister <= imem_data_i;
+ end
+ end
-/*
- ////// Comparator //////
- Used for all comparative operations
-*/
-reg comparison_result;
+ ////////////////////////////////////////////////////////////////////
+ // STAGE 2 - DECODE & EXECUTE
+ ////////////////////////////////////////////////////////////////////
+ /*
+ ////// Instruction Decode //////
+ Instruction decode unit decodes instruction and sets various control
+ signals throughout the pipeline. Is also extracts immediate values
+ from instructions and sign extends them properly.
+ */
+ wire [4:0] d_rd_sel;
+ wire [4:0] d_rs1_sel;
+ wire [4:0] d_rs2_sel;
+ wire [31:0] d_imm;
+
+ wire d_jump_en;
+ wire [2:0] d_comparison_type;
+ wire d_rf_we;
+ wire [2:0] d_rf_din_sel;
+ wire d_a_op_sel;
+ wire d_b_op_sel;
+ wire d_cmp_b_op_sel;
+ wire [2:0] d_alu_op_sel;
+ wire [2:0] d_mem_access_width;
+ wire d_mem_load_store;
+ wire d_mem_we;
+ wire [2:0] d_csru_op_sel;
+ wire d_csru_we;
+
+
+ Decode decode
+ (
+ .instr_i (InstructionRegister),
+
+ .rd_sel_o (d_rd_sel),
+ .rs1_sel_o (d_rs1_sel),
+ .rs2_sel_o (d_rs2_sel),
+
+ .imm_o (d_imm),
+
+ .jump_en_o (d_jump_en),
+ .comparison_type_o (d_comparison_type),
+ .rf_we_o (d_rf_we),
+ .rf_din_sel_o (d_rf_din_sel),
+ .a_op_sel_o (d_a_op_sel),
+ .b_op_sel_o (d_b_op_sel),
+ .cmp_b_op_sel_o (d_cmp_b_op_sel),
+ .alu_op_sel_o (d_alu_op_sel),
+ .mem_access_width_o (d_mem_access_width),
+ .d_mem_load_store (d_mem_load_store),
+ .mem_we_o (d_mem_we),
+ .csru_op_sel_o (d_csru_op_sel),
+ .csru_we_o (d_csru_we)
+ );
+
+
+
+ /*
+ ////// Register File //////
+ Contains cpu registers (r0-31)
+ */
+
+ // RF_Din Multiplexer
+ reg [31:0] rf_rd_data;
+ always @(*) begin
+ case(d_rf_din_sel)
+ 3'd0: rf_rd_data = d_imm;
+ 3'd1: rf_rd_data = link_address;
+ 3'd2: rf_rd_data = alu_out;
+ 3'd3: rf_rd_data = {31'd0, comparison_result};
+ 3'd4: rf_rd_data = memload;
+ 3'd5: rf_rd_data = csru_data_o;
+
+ default: rf_rd_data = 32'd0;
+ endcase
+ end
-wire [31:0] cmp_A = rf_rs1;
-wire [31:0] cmp_B = (d_cmp_b_op_sel) ? d_imm : rf_rs2;
-wire signed [31:0] cmp_A_signed = cmp_A;
-wire signed [31:0] cmp_B_signed = cmp_B;
+ wire [31:0] rf_rs1;
+ wire [31:0] rf_rs2;
+
+ RegisterFile #(.REG_WIDTH(32), .REG_ADDR_WIDTH(5)) rf
+ (
+ .Ra_Sel_i (d_rs1_sel),
+ .Ra_o (rf_rs1),
+
+ .Rb_Sel_i (d_rs2_sel),
+ .Rb_o (rf_rs2),
+
+ .Data_We_i (d_rf_we & !stall_stage2),
+ .Rd_Sel_i (d_rd_sel),
+ .Data_i (rf_rd_data),
+
+ .Clk_i (clk_i),
+ .Rst_i (rst_i)
+ );
+
+
+ /*
+ ////// ALU //////
+ Used for arithmetic and logical computations including shifts.
+ */
+ wire [31:0] alu_a_in = (d_a_op_sel) ? ProgramCounter_Old : rf_rs1;
+ wire [31:0] alu_b_in = (d_b_op_sel) ? d_imm : rf_rs2;
+ wire [31:0] alu_out;
+
+ Alu alu
+ (
+ .a_i (alu_a_in),
+ .b_i (alu_b_in),
+ .sel_i (d_alu_op_sel),
+ .result_o (alu_out)
+ );
+
+
+
+ /*
+ ////// Comparator //////
+ Used for all comparative operations
+ */
+ reg comparison_result;
+
+ wire [31:0] cmp_A = rf_rs1;
+ wire [31:0] cmp_B = (d_cmp_b_op_sel) ? d_imm : rf_rs2;
+ wire signed [31:0] cmp_A_signed = cmp_A;
+ wire signed [31:0] cmp_B_signed = cmp_B;
+
+ always @(*) /* COMBINATORIAL*/
+ begin
+ case(d_comparison_type)
+ `CMP_FUNC_UN: comparison_result = 1'b1;
+ `CMP_FUNC_EQ: comparison_result = (cmp_A == cmp_B);
+ `CMP_FUNC_NQ: comparison_result = (cmp_A != cmp_B);
+ `CMP_FUNC_LT: comparison_result = (cmp_A_signed < cmp_B_signed);
+ `CMP_FUNC_GE: comparison_result = (cmp_A_signed >= cmp_B_signed);
+ `CMP_FUNC_LTU: comparison_result = (cmp_A < cmp_B);
+ `CMP_FUNC_GEU: comparison_result = (cmp_A >= cmp_B);
+
+ default: comparison_result = 1'b0;
+ endcase
+ end
-always @(*) /* COMBINATORIAL*/
-begin
- case(d_comparison_type)
- `__CMP_UN__ : comparison_result = 1'b1;
- `__CMP_EQ__ : comparison_result = (cmp_A == cmp_B);
- `__CMP_NQ__ : comparison_result = (cmp_A != cmp_B);
- `__CMP_LT__ : comparison_result = (cmp_A_signed < cmp_B_signed);
- `__CMP_GE__ : comparison_result = (cmp_A_signed >= cmp_B_signed);
- `__CMP_LTU__ : comparison_result = (cmp_A < cmp_B);
- `__CMP_GEU__ : comparison_result = (cmp_A >= cmp_B);
- default: comparison_result = 1'b0;
- endcase
-end
+ /*
+ ////// CSR Unit //////
+ Contains all the Control and status registers
+ */
+ wire [11:0] csru_addr_i = d_imm[11:0];
+ wire [31:0] csru_data_o;
+ // check if it is imm type CSR instruction and send data_i accordingly
+ wire [31:0] csru_data_i = d_csru_op_sel[2] ? {{27{1'b0}}, d_rs1_sel} : rf_rs1;
-/*
- ////// CSR Unit //////
- Contains all the Control and status registers
-*/
-wire [11:0] csru_addr_i = d_imm[11:0];
-wire [31:0] csru_data_o;
+ CSR_Unit csr_unit
+ (
+ // Global signals
+ .clk_i (clk_i),
+ .rst_i (rst_i),
-// check if it is imm type CSR instruction and send data_i accordingly
-wire [31:0] csru_data_i = d_csru_op_sel[2] ? {{27{1'b0}}, d_rs1_sel} : rf_rs1;
+ // Signals for Reading from / Writing to CSRs
+ .addr_i (csru_addr_i),
+ .data_i (csru_data_i),
+ .op_i (d_csru_op_sel[1:0]),
+ .we_i (d_csru_we),
+ .data_o (csru_data_o)
+ );
-CSR_Unit csr_unit
-(
- // Global signals
- .clk_i (clk_i),
- .rst_i (rst_i),
-
- // Signals for Reading from / Writing to CSRs
- .addr_i (csru_addr_i),
- .data_i (csru_data_i),
- .op_i (d_csru_op_sel[1:0]),
- .we_i (d_csru_we),
- .data_o (csru_data_o)
-);
+ /*
+ DATA MEMORY ACCESS
+ */
+ wire [31:0] dmem_address = alu_out;
+ wire [31:0] dmem_data_out = rf_rs2;
-/*
- DATA MEMORY ACCESS
-*/
-wire [31:0] dmem_address = alu_out;
-wire [31:0] dmem_data_out = rf_rs2;
-
-assign dmem_addr_o = {dmem_address[31:2], {2{1'b0}}}; // word aligned accesses
-assign dmem_valid_o = d_mem_load_store;
-assign dmem_we_o = d_mem_we;// & !stall_stage2; IMPORTANT
-
-/////////////////////////////////
-// READ
-
-/*
- ////// MEM_LOAD //////
-*/
-reg [31:0] memload;
-
-always @(*) /* COMBINATORIAL */
-begin
- case(d_mem_access_width[1:0])
- 2'b00: begin // Load Byte
- case(dmem_address[1:0])
- 2'b00: memload = {{24{d_mem_access_width[2] ? 1'b0 : dmem_data_i[7]}}, dmem_data_i[7:0]};
- 2'b01: memload = {{24{d_mem_access_width[2] ? 1'b0 : dmem_data_i[15]}}, dmem_data_i[15:8]};
- 2'b10: memload = {{24{d_mem_access_width[2] ? 1'b0 : dmem_data_i[23]}}, dmem_data_i[23:16]};
- 2'b11: memload = {{24{d_mem_access_width[2] ? 1'b0 : dmem_data_i[31]}}, dmem_data_i[31:24]};
- endcase
- end
-
- 2'b01: begin // Load Half Word
- case(dmem_address[1])
- 1'b0: memload = {{16{d_mem_access_width[2] ? 1'b0 : dmem_data_i[15]}}, dmem_data_i[15:0]};
- 1'b1: memload = {{16{d_mem_access_width[2] ? 1'b0 : dmem_data_i[31]}}, dmem_data_i[31:16]};
- endcase
- end
-
- 2'b10: begin // Load Word
- memload = dmem_data_i;
- end
+ assign dmem_addr_o = {dmem_address[31:2], {2{1'b0}}}; // word aligned accesses
+ assign dmem_valid_o = d_mem_load_store;
+ assign dmem_we_o = d_mem_we;// & !stall_stage2; IMPORTANT
- default: memload = 32'h00000000;
- endcase
-end
+ /////////////////////////////////
+ // READ
-////////////////////////////////
-// WRITE
+ /*
+ ////// MEM_LOAD //////
+ */
+ reg [31:0] memload;
-// Setting the sel_o signal
-always @(*) begin /* COMBINATORIAL */
- if (d_mem_we) begin
+ always @(*) /* COMBINATORIAL */
+ begin
case(d_mem_access_width[1:0])
- 2'b00: begin // Store byte
+ 2'b00: begin // Load Byte
case(dmem_address[1:0])
- 2'b00: dmem_sel_o = 4'b0001;
- 2'b01: dmem_sel_o = 4'b0010;
- 2'b10: dmem_sel_o = 4'b0100;
- 2'b11: dmem_sel_o = 4'b1000;
+ 2'b00: memload = {{24{d_mem_access_width[2] ? 1'b0 : dmem_data_i[7]}}, dmem_data_i[7:0]};
+ 2'b01: memload = {{24{d_mem_access_width[2] ? 1'b0 : dmem_data_i[15]}}, dmem_data_i[15:8]};
+ 2'b10: memload = {{24{d_mem_access_width[2] ? 1'b0 : dmem_data_i[23]}}, dmem_data_i[23:16]};
+ 2'b11: memload = {{24{d_mem_access_width[2] ? 1'b0 : dmem_data_i[31]}}, dmem_data_i[31:24]};
endcase
end
-
- 2'b01: begin // Store Half Word
+
+ 2'b01: begin // Load Half Word
case(dmem_address[1])
- 1'b0: dmem_sel_o = 4'b0011;
- 1'b1: dmem_sel_o = 4'b1100;
+ 1'b0: memload = {{16{d_mem_access_width[2] ? 1'b0 : dmem_data_i[15]}}, dmem_data_i[15:0]};
+ 1'b1: memload = {{16{d_mem_access_width[2] ? 1'b0 : dmem_data_i[31]}}, dmem_data_i[31:16]};
endcase
end
+
+ 2'b10: begin // Load Word
+ memload = dmem_data_i;
+ end
- 2'b10: dmem_sel_o = 4'b1111; // Store Word
-
- default: dmem_sel_o = 4'b1111;
- endcase
+ default: memload = 32'h00000000;
+ endcase
end
- else
- dmem_sel_o = 4'b1111; // Load (Byte/HWord/Word)
-end
+ ////////////////////////////////
+ // WRITE
+
+ // Setting the sel_o signal
+ always @(*) begin /* COMBINATORIAL */
+ if (d_mem_we) begin
+ case(d_mem_access_width[1:0])
+ 2'b00: begin // Store byte
+ case(dmem_address[1:0])
+ 2'b00: dmem_sel_o = 4'b0001;
+ 2'b01: dmem_sel_o = 4'b0010;
+ 2'b10: dmem_sel_o = 4'b0100;
+ 2'b11: dmem_sel_o = 4'b1000;
+ endcase
+ end
+
+ 2'b01: begin // Store Half Word
+ case(dmem_address[1])
+ 1'b0: dmem_sel_o = 4'b0011;
+ 1'b1: dmem_sel_o = 4'b1100;
+ endcase
+ end
+
+ 2'b10: dmem_sel_o = 4'b1111; // Store Word
+
+ default: dmem_sel_o = 4'b1111;
+ endcase
+ end
+ else
+ dmem_sel_o = 4'b1111; // Load (Byte/HWord/Word)
+ end
-// Setting the data_o signal
-always @(*) begin /* COMBINATORIAL */
- if (d_mem_we) begin
- case(d_mem_access_width[1:0])
- 2'b00: begin // Store byte
- case(dmem_address[1:0])
- 2'b00: dmem_data_o = { {24{1'b0}}, dmem_data_out[7:0] };
- 2'b01: dmem_data_o = { {16{1'b0}}, dmem_data_out[7:0], {8{1'b0}} };
- 2'b10: dmem_data_o = { {8{1'b0}} , dmem_data_out[7:0], {16{1'b0}} };
- 2'b11: dmem_data_o = { dmem_data_out[7:0], {24{1'b0}} };
- endcase
- end
-
- 2'b01: begin // Store Half Word
- case(dmem_address[1])
- 1'b0: dmem_data_o = { {16{1'b0}}, dmem_data_out[15:0] };
- 1'b1: dmem_data_o = { dmem_data_out[15:0], {16{1'b0}} };
- endcase
- end
-
- 2'b10: dmem_data_o = dmem_data_out; // Store Word
- default: dmem_data_o = dmem_data_out;
- endcase
+ // Setting the data_o signal
+ always @(*) begin /* COMBINATORIAL */
+ if (d_mem_we) begin
+ case(d_mem_access_width[1:0])
+ 2'b00: begin // Store byte
+ case(dmem_address[1:0])
+ 2'b00: dmem_data_o = { {24{1'b0}}, dmem_data_out[7:0] };
+ 2'b01: dmem_data_o = { {16{1'b0}}, dmem_data_out[7:0], {8{1'b0}} };
+ 2'b10: dmem_data_o = { {8{1'b0}} , dmem_data_out[7:0], {16{1'b0}} };
+ 2'b11: dmem_data_o = { dmem_data_out[7:0], {24{1'b0}} };
+ endcase
+ end
+
+ 2'b01: begin // Store Half Word
+ case(dmem_address[1])
+ 1'b0: dmem_data_o = { {16{1'b0}}, dmem_data_out[15:0] };
+ 1'b1: dmem_data_o = { dmem_data_out[15:0], {16{1'b0}} };
+ endcase
+ end
+
+ 2'b10: dmem_data_o = dmem_data_out; // Store Word
+
+ default: dmem_data_o = dmem_data_out;
+ endcase
+ end
+ else
+ dmem_data_o = 32'h00000000; // Load (Byte/HWord/Word)
end
- else
- dmem_data_o = 32'h00000000; // Load (Byte/HWord/Word)
-end
endmodule
\ No newline at end of file
diff --git a/rtl/core/AtomRV_wb.v b/rtl/core/AtomRV_wb.v
index 3dd50829..6ee7993c 100644
--- a/rtl/core/AtomRV_wb.v
+++ b/rtl/core/AtomRV_wb.v
@@ -1,20 +1,27 @@
-`default_nettype none
+////////////////////////////////////////////////////////////////////
+// File : AtomRV_wb.v
+// Author : Saurabh Singh (saurabh.s99100@gmail.com)
+// Description : Wishbone wrapper for Atom core
+////////////////////////////////////////////////////////////////////
+
`include "AtomRV.v"
+`default_nettype none
+
/*
Wishbone wrapper for the atom cpu.
*/
module AtomRV_wb
(
- input wire wb_clk_i,
+ input wire wb_clk_i,
input wire wb_rst_i,
- // === IBUS Wishbone Master Interface ===
- output wire [31:0] wb_ibus_adr_o,
+ // === IBUS Wishbone Master Interface ===
+ output wire [31:0] wb_ibus_adr_o,
input wire [31:0] wb_ibus_dat_i,
- output wire wb_ibus_stb_o,
- input wire wb_ibus_ack_i,
+ output wire wb_ibus_stb_o,
+ input wire wb_ibus_ack_i,
// === DBUS Wishbone Master Interface ===
output wire [31:0] wb_dbus_adr_o,
@@ -33,84 +40,68 @@ module AtomRV_wb
//output reg [31:0] eoi
);
/////////////////////////////////////////////////////////////////
- wire [31:0] imem_addr_o; // IMEM Address
- wire [31:0] imem_data_i; // IMEM data
+ wire [31:0] imem_addr_o; // IMEM Address
+ wire [31:0] imem_data_i; // IMEM data
- wire imem_valid_o; // DMEM Access width
- wire imem_ack_i; // DMEM WriteEnable
+ wire imem_valid_o; // IMEM valid
+ wire imem_ack_i; // IMEM Acknowledge
- wire [31:0] dmem_addr_o; // DMEM address
- wire [31:0] dmem_data_i; // DMEM data in
- wire [31:0] dmem_data_o; // DMEM data out
-
- wire [3:0] dmem_sel_o; // DMEM Access width
- wire dmem_we_o; // DMEM Access width
- wire dmem_valid_o; // DMEM Access width
- wire dmem_ack_i; // DMEM WriteEnable
+ wire [31:0] dmem_addr_o; // DMEM address
+ wire [31:0] dmem_data_i; // DMEM data in
+ wire [31:0] dmem_data_o; // DMEM data out
- // Core
- AtomRV atom_core
- (
- .clk_i (wb_clk_i),
- .rst_i (wb_rst_i),
-
- .imem_addr_o (imem_addr_o),
- .imem_data_i (imem_data_i),
-
- .imem_valid_o (imem_valid_o),
- .imem_ack_i (imem_ack_i),
+ wire [3:0] dmem_sel_o; // DMEM Access width
+ wire dmem_we_o; // DMEM Access width
+ wire dmem_valid_o; // DMEM Access width
+ wire dmem_ack_i; // DMEM WriteEnable
+
+ // Atom Core
+ AtomRV atom_core
+ (
+ .clk_i (wb_clk_i),
+ .rst_i (wb_rst_i),
- .dmem_addr_o (dmem_addr_o),
- .dmem_data_i (dmem_data_i),
- .dmem_data_o (dmem_data_o),
+ .imem_addr_o (imem_addr_o),
+ .imem_data_i (imem_data_i),
- .dmem_sel_o (dmem_sel_o),
- .dmem_we_o (dmem_we_o),
+ .imem_valid_o (imem_valid_o),
+ .imem_ack_i (imem_ack_i),
- .dmem_valid_o (dmem_valid_o),
- .dmem_ack_i (dmem_ack_i)
- );
-
- ////////////////////////////////////////////////////////////
- /// IBUS Wishbone Logic
- // parameter IDLE = 0;
- // parameter WAIT = 1;
- // reg state = IDLE;
+ .dmem_addr_o (dmem_addr_o),
+ .dmem_data_i (dmem_data_i),
+ .dmem_data_o (dmem_data_o),
- // always @(posedge wb_clk_i) begin
- // wb_ibus_stb_o <= 0;
- // case(state)
- // IDLE: if(imem_valid_o) begin
- // wb_ibus_stb_o <= 1;
- // state <= WAIT;
- // end
+ .dmem_sel_o (dmem_sel_o),
+ .dmem_we_o (dmem_we_o),
- // WAIT: if(imem_ack_i)
- // state <= IDLE;
+ .dmem_valid_o (dmem_valid_o),
+ .dmem_ack_i (dmem_ack_i)
+ );
+
+ ////////////////////////////////////////////////////////////
+ /// IBUS Wishbone Logic
- // endcase
- // end
+ assign wb_ibus_adr_o = imem_addr_o;
+ assign imem_data_i = wb_ibus_dat_i;
+ assign wb_ibus_stb_o = imem_valid_o;
+ assign imem_ack_i = wb_ibus_ack_i;
- assign wb_ibus_adr_o = imem_addr_o;
- assign imem_data_i = wb_ibus_dat_i;
- assign wb_ibus_stb_o = imem_valid_o;
- assign imem_ack_i = wb_ibus_ack_i;
- ////////////////////////////////////////////////////////////
- /// DBUS Wishbone Logic
- assign wb_dbus_adr_o = dmem_addr_o;
- assign dmem_data_i = wb_dbus_dat_i;
- assign wb_dbus_dat_o = dmem_data_o;
+ ////////////////////////////////////////////////////////////
+ /// DBUS Wishbone Logic
+ assign wb_dbus_adr_o = dmem_addr_o;
+ assign dmem_data_i = wb_dbus_dat_i;
+ assign wb_dbus_dat_o = dmem_data_o;
- assign wb_dbus_sel_o = dmem_sel_o;
- assign wb_dbus_we_o = dmem_we_o;
+ assign wb_dbus_sel_o = dmem_sel_o;
+ assign wb_dbus_we_o = dmem_we_o;
- assign wb_dbus_stb_o = dmem_valid_o;
- assign dmem_ack_i = wb_dbus_ack_i;
+ assign wb_dbus_stb_o = dmem_valid_o;
+ assign dmem_ack_i = wb_dbus_ack_i;
- assign wb_dbus_cyc_o = wb_dbus_stb_o;
+ assign wb_dbus_cyc_o = wb_dbus_stb_o;
endmodule
\ No newline at end of file
diff --git a/rtl/core/CSR_Unit.v b/rtl/core/CSR_Unit.v
index 03e61d49..fdb3888f 100644
--- a/rtl/core/CSR_Unit.v
+++ b/rtl/core/CSR_Unit.v
@@ -1,3 +1,13 @@
+////////////////////////////////////////////////////////////////////
+// File : CSR_Unit.v
+// Author : Saurabh Singh (saurabh.s99100@gmail.com)
+// Description : Control & Status Register (CSR) unit contains logic
+// to read and write to the CSR registers
+////////////////////////////////////////////////////////////////////
+
+`include "Utils.vh"
+`include "Defs.vh"
+
`default_nettype none
module CSR_Unit
@@ -10,9 +20,7 @@ module CSR_Unit
input wire [11:0] addr_i,
input wire [31:0] data_i,
input wire [1:0] op_i,
- /* verilator lint_off UNUSED */
input wire we_i,
- /* verilator lint_on UNUSED */
output wire [31:0] data_o
@@ -20,65 +28,65 @@ module CSR_Unit
// ouput signals to pipeline
);
-
-
-/* Generate Data to be written */
-/* verilator lint_off UNUSED */
-reg [31:0] write_value; // Value to be written onto a CSR register
-/* verilator lint_on UNUSED */
-reg [31:0] read_value; // Value of selected CSR register
-
-always @(*) /* COMBINATIONAL */ begin
- case(op_i[1:0])
- 2'b00: write_value = data_i; // CSRRW
- 2'b01: write_value = data_i & read_value; // CSRRS
- 2'b10: write_value = ~(data_i & read_value); // CSRRC
-
- default:
- write_value = read_value;
- endcase
-end
-
-////////////////////////////////////////////////////////////
-// CSR Registers
-
-// CYCLE (Read-Only)
-reg [63:0] csr_cycle = 64'd0;
-
-always @(posedge clk_i) begin
- if(rst_i)
- csr_cycle <= 64'd0;
- else
- csr_cycle <= csr_cycle + 1'b1;
-end
-
-
-////////////////////////////////////////////////////////////
-// CSR Selection
-
-// assigns the read value function to various CSRs and sets we
-// pins of CSRs (if not Readonly)
-
-always @(*) /* COMBINATIONAL */ begin
- // Defaults
- read_value = 0;
-
- case(addr_i)
- 12'hc00: begin
- read_value = csr_cycle[31:0];
- end
-
- 12'hc80: begin
- read_value = csr_cycle[63:32];
- end
-
- default: begin
- read_value = 0;
- end
-
- endcase
-end
-
-assign data_o = read_value;
+ `UNUSED_VAR(we_i)
+
+ // Generate Data to be written
+ reg [31:0] write_value; // Value to be written onto a CSR register
+ `UNUSED_VAR(write_value)
+
+ reg [31:0] read_value; // Value of selected CSR register
+
+ always @(*) /* COMBINATIONAL */ begin
+ case(op_i[1:0])
+ 2'b00: write_value = data_i; // CSRRW
+ 2'b01: write_value = data_i & read_value; // CSRRS
+ 2'b10: write_value = ~(data_i & read_value); // CSRRC
+
+ default:
+ write_value = read_value;
+ endcase
+ end
+
+ ////////////////////////////////////////////////////////////
+ // CSR Registers
+
+ // CYCLE (Read-Only)
+ reg [63:0] csr_cycle = 64'd0;
+
+ always @(posedge clk_i) begin
+ if(rst_i)
+ csr_cycle <= 64'd0;
+ else
+ csr_cycle <= csr_cycle + 1'b1;
+ end
+
+
+ ////////////////////////////////////////////////////////////
+ // CSR Selection
+
+ // assigns the read value function to various CSRs and sets we
+ // pins of CSRs (if not Readonly)
+
+ always @(*) /* COMBINATIONAL */ begin
+ // Defaults
+ read_value = 0;
+
+ case(addr_i)
+ 12'hc00: begin
+ read_value = csr_cycle[31:0];
+ end
+
+ 12'hc80: begin
+ read_value = csr_cycle[63:32];
+ end
+
+ default: begin
+ read_value = 0;
+ end
+
+ endcase
+ end
+
+ assign data_o = read_value;
endmodule
diff --git a/rtl/core/Decode.v b/rtl/core/Decode.v
index b8ca2447..beb799f0 100644
--- a/rtl/core/Decode.v
+++ b/rtl/core/Decode.v
@@ -1,9 +1,7 @@
////////////////////////////////////////////////////////////////////
-// RISC-V Atom
-//
// File : Decode.v
// Author : Saurabh Singh (saurabh.s99100@gmail.com)
-// Description : Instruction Decoder for RISCV atom core
+// Description : Instruction Decoder for RISCV atom core
////////////////////////////////////////////////////////////////////
`default_nettype none
@@ -34,425 +32,425 @@ module Decode
output reg csru_we_o
);
-// Decode fields
-wire [6:0] opcode = instr_i[6:0];
-wire [2:0] func3 = instr_i[14:12];
-wire [6:0] func7 = instr_i[31:25];
-
-assign mem_access_width_o = func3;
-assign csru_op_sel_o = func3;
-
-assign rd_sel_o = instr_i[11:7];
-assign rs1_sel_o = instr_i[19:15];
-assign rs2_sel_o = instr_i[24:20];
-
-reg [2:0] imm_format;
-
-/*
- Decode Immediate
-*/
-reg [31:0] getExtImm;
-
-always @(*) /*COMBINATORIAL*/
-begin
- case(imm_format)
- `__I_IMMIDIATE__ : getExtImm = {{21{instr_i[31]}}, instr_i[30:25], instr_i[24:21], instr_i[20]};
- `__S_IMMIDIATE__ : getExtImm = {{21{instr_i[31]}}, instr_i[30:25], instr_i[11:8], instr_i[7]};
- `__B_IMMIDIATE__ : getExtImm = {{20{instr_i[31]}}, instr_i[7], instr_i[30:25], instr_i[11:8], 1'b0};
- `__U_IMMIDIATE__ : getExtImm = {instr_i[31], instr_i[30:20], instr_i[19:12], {12{1'b0}}};
- `__J_IMMIDIATE__ : getExtImm = {{12{instr_i[31]}}, instr_i[19:12], instr_i[20], instr_i[30:25], instr_i[24:21], 1'b0};
-
- default:
- getExtImm = 32'd0;
- endcase
-end
-
-assign imm_o = getExtImm;
-
-
-always @(*) begin
- // DEFAULT VALUES
- jump_en_o = 1'b0;
- comparison_type_o = `__CMP_UN__;
- rf_we_o = 1'b0;
- rf_din_sel_o = 3'd0;
- a_op_sel_o = 1'b0;
- b_op_sel_o = 1'b0;
- cmp_b_op_sel_o = 1'b0;
- alu_op_sel_o = `__ALU_ADD__;
- mem_we_o = 1'b0;
- d_mem_load_store = 1'b0;
- imm_format = `__U_IMMIDIATE__;
- csru_we_o = 0;
-
-
- casez({func7, func3, opcode})
-
- /* LUI */
- 17'b???????_???_0110111:
- begin
- rf_we_o = 1'b1;
- rf_din_sel_o = 3'd0;
- imm_format = `__U_IMMIDIATE__;
- end
-
- /* AUIPC */
- 17'b???????_???_0010111:
- begin
- rf_we_o = 1'b1;
- rf_din_sel_o = 3'd2;
- a_op_sel_o = 1'b1;
- b_op_sel_o = 1'b1;
- alu_op_sel_o = `__ALU_ADD__;
- imm_format = `__U_IMMIDIATE__;
- end
-
- /* JAL */
- 17'b???????_???_1101111:
- begin
- jump_en_o = 1'b1;
- comparison_type_o = `__CMP_UN__;
- rf_we_o = 1'b1;
- rf_din_sel_o = 3'd1;
- a_op_sel_o = 1'b1;
- b_op_sel_o = 1'b1;
- alu_op_sel_o = `__ALU_ADD__;
- imm_format = `__J_IMMIDIATE__;
- end
-
- /* JALR */
- 17'b???????_000_1100111:
- begin
- jump_en_o = 1'b1;
- comparison_type_o = `__CMP_UN__;
- rf_we_o = 1'b1;
- rf_din_sel_o = 3'd1;
- a_op_sel_o = 1'b0;
- b_op_sel_o = 1'b1;
- alu_op_sel_o = `__ALU_ADD__;
- imm_format = `__I_IMMIDIATE__;
- end
-
- /* BEQ */
- 17'b???????_000_1100011: begin
- jump_en_o = 1'b1;
- comparison_type_o = `__CMP_EQ__;
- a_op_sel_o = 1'b1;
- b_op_sel_o = 1'b1;
- cmp_b_op_sel_o = 1'b0;
- alu_op_sel_o = `__ALU_ADD__;
- imm_format = `__B_IMMIDIATE__;
- end
-
- /* BNE */
- 17'b???????_001_1100011:
- begin
- jump_en_o = 1'b1;
- comparison_type_o = `__CMP_NQ__;
- a_op_sel_o = 1'b1;
- b_op_sel_o = 1'b1;
- cmp_b_op_sel_o = 1'b0;
- alu_op_sel_o = `__ALU_ADD__;
- imm_format = `__B_IMMIDIATE__;
- end
-
- /* BLT */
- 17'b???????_100_1100011:
- begin
- jump_en_o = 1'b1;
- comparison_type_o = `__CMP_LT__;
- a_op_sel_o = 1'b1;
- b_op_sel_o = 1'b1;
- cmp_b_op_sel_o = 1'b0;
- alu_op_sel_o = `__ALU_ADD__;
- imm_format = `__B_IMMIDIATE__;
- end
-
- /* BGE */
- 17'b???????_101_1100011:
- begin
- jump_en_o = 1'b1;
- comparison_type_o = `__CMP_GE__;
- a_op_sel_o = 1'b1;
- b_op_sel_o = 1'b1;
- cmp_b_op_sel_o = 1'b0;
- alu_op_sel_o = `__ALU_ADD__;
- imm_format = `__B_IMMIDIATE__;
- end
-
- /* BLTU */
- 17'b???????_110_1100011:
- begin
- jump_en_o = 1'b1;
- comparison_type_o = `__CMP_LTU__;
- a_op_sel_o = 1'b1;
- b_op_sel_o = 1'b1;
- cmp_b_op_sel_o = 1'b0;
- alu_op_sel_o = `__ALU_ADD__;
- imm_format = `__B_IMMIDIATE__;
- end
-
- /* BGEU */
- 17'b???????_111_1100011:
- begin
- jump_en_o = 1'b1;
- comparison_type_o = `__CMP_GEU__;
- a_op_sel_o = 1'b1;
- b_op_sel_o = 1'b1;
- cmp_b_op_sel_o = 1'b0;
- alu_op_sel_o = `__ALU_ADD__;
- imm_format = `__B_IMMIDIATE__;
- end
-
- /* LB, LH, LW, LBU, LHU */
- 17'b???????_???_0000011:
- begin
- rf_we_o = 1'b1;
- rf_din_sel_o = 3'd4;
- a_op_sel_o = 1'b0;
- b_op_sel_o = 1'b1;
- alu_op_sel_o = `__ALU_ADD__;
- mem_we_o = 1'b0;
- d_mem_load_store = 1'b1;
- imm_format = `__I_IMMIDIATE__;
- end
-
- /* SB, SH, SW */
- 17'b???????_???_0100011:
- begin
- a_op_sel_o = 1'b0;
- b_op_sel_o = 1'b1;
- alu_op_sel_o = `__ALU_ADD__;
- mem_we_o = 1'b1;
- d_mem_load_store = 1'b1;
- imm_format = `__S_IMMIDIATE__;
- end
-
- /* ADDI */
- 17'b???????_000_0010011:
- begin
- rf_we_o = 1'b1;
- rf_din_sel_o = 3'd2;
- a_op_sel_o = 1'b0;
- b_op_sel_o = 1'b1;
- alu_op_sel_o = `__ALU_ADD__;
- imm_format = `__I_IMMIDIATE__;
- end
-
- /* SLTI */
- 17'b???????_010_0010011:
- begin
- comparison_type_o = `__CMP_LT__;
- rf_we_o = 1'b1;
- rf_din_sel_o = 3'd3;
- cmp_b_op_sel_o = 1'b1;
- imm_format = `__I_IMMIDIATE__;
- end
-
- /* SLTIU */
- 17'b???????_011_0010011:
- begin
- comparison_type_o = `__CMP_LTU__;
- rf_we_o = 1'b1;
- rf_din_sel_o = 3'd3;
- cmp_b_op_sel_o = 1'b1;
- imm_format = `__I_IMMIDIATE__;
- end
-
- /* XORI */
- 17'b???????_100_0010011:
- begin
- rf_we_o = 1'b1;
- rf_din_sel_o = 3'd2;
- a_op_sel_o = 1'b0;
- b_op_sel_o = 1'b1;
- alu_op_sel_o = `__ALU_XOR__;
- imm_format = `__I_IMMIDIATE__;
- end
-
- /* ORI */
- 17'b???????_110_0010011:
- begin
- rf_we_o = 1'b1;
- rf_din_sel_o = 3'd2;
- a_op_sel_o = 1'b0;
- b_op_sel_o = 1'b1;
- alu_op_sel_o = `__ALU_OR__;
- imm_format = `__I_IMMIDIATE__;
- end
-
- /* ANDI */
- 17'b???????_111_0010011:
- begin
- rf_we_o = 1'b1;
- rf_din_sel_o = 3'd2;
- a_op_sel_o = 1'b0;
- b_op_sel_o = 1'b1;
- alu_op_sel_o = `__ALU_AND__;
- imm_format = `__I_IMMIDIATE__;
- end
-
- /* SLLI */
- 17'b0000000_001_0010011:
- begin
- rf_we_o = 1'b1;
- rf_din_sel_o = 3'd2;
- a_op_sel_o = 1'b0;
- b_op_sel_o = 1'b1;
- alu_op_sel_o = `__ALU_SLL__;
- imm_format = `__I_IMMIDIATE__;
- end
-
- /* SRLI */
- 17'b0000000_101_0010011:
- begin
- rf_we_o = 1'b1;
- rf_din_sel_o = 3'd2;
- a_op_sel_o = 1'b0;
- b_op_sel_o = 1'b1;
- alu_op_sel_o = `__ALU_SRL__;
- imm_format = `__I_IMMIDIATE__;
- end
-
- /* SRAI */
- 17'b0100000_101_0010011:
- begin
- rf_we_o = 1'b1;
- rf_din_sel_o = 3'd2;
- a_op_sel_o = 1'b0;
- b_op_sel_o = 1'b1;
- alu_op_sel_o = `__ALU_SRA__;
- imm_format = `__I_IMMIDIATE__;
- end
-
- /* ADD */
- 17'b0000000_000_0110011:
- begin
- rf_we_o = 1'b1;
- rf_din_sel_o = 3'd2;
- a_op_sel_o = 1'b0;
- b_op_sel_o = 1'b0;
- alu_op_sel_o = `__ALU_ADD__;
- end
-
- /* SUB */
- 17'b0100000_000_0110011:
- begin
- rf_we_o = 1'b1;
- rf_din_sel_o = 3'd2;
- a_op_sel_o = 1'b0;
- b_op_sel_o = 1'b0;
- alu_op_sel_o = `__ALU_SUB__;
- end
-
- /* SLL */
- 17'b0000000_001_0110011:
- begin
- rf_we_o = 1'b1;
- rf_din_sel_o = 3'd2;
- a_op_sel_o = 1'b0;
- b_op_sel_o = 1'b0;
- alu_op_sel_o = `__ALU_SLL__;
- end
-
- /* SLT */
- 17'b0000000_010_0110011:
- begin
- comparison_type_o = `__CMP_LT__;
- rf_we_o = 1'b1;
- rf_din_sel_o = 3'd3;
- cmp_b_op_sel_o = 1'b0;
- end
-
-
- /* SLTU */
- 17'b0000000_011_0110011:
- begin
- comparison_type_o = `__CMP_LTU__;
- rf_we_o = 1'b1;
- rf_din_sel_o = 3'd3;
- cmp_b_op_sel_o = 1'b0;
- end
-
- /* XOR */
- 17'b0000000_100_0110011:
- begin
- rf_we_o = 1'b1;
- rf_din_sel_o = 3'd2;
- a_op_sel_o = 1'b0;
- b_op_sel_o = 1'b0;
- alu_op_sel_o = `__ALU_XOR__;
- end
-
- /* SRL */
- 17'b0000000_101_0110011:
- begin
- rf_we_o = 1'b1;
- rf_din_sel_o = 3'd2;
- a_op_sel_o = 1'b0;
- b_op_sel_o = 1'b0;
- alu_op_sel_o = `__ALU_SRL__;
- end
-
- /* SRA */
- 17'b0100000_101_0110011:
- begin
- rf_we_o = 1'b1;
- rf_din_sel_o = 3'd2;
- a_op_sel_o = 1'b0;
- b_op_sel_o = 1'b0;
- alu_op_sel_o = `__ALU_SRA__;
- end
-
- /* OR */
- 17'b0000000_110_0110011:begin
- rf_we_o = 1'b1;
- rf_din_sel_o = 3'd2;
- a_op_sel_o = 1'b0;
- b_op_sel_o = 1'b0;
- alu_op_sel_o = `__ALU_OR__;
- end
-
- /* AND */
- 17'b0000000_111_0110011:
- begin
- rf_we_o = 1'b1;
- rf_din_sel_o = 3'd2;
- a_op_sel_o = 1'b0;
- b_op_sel_o = 1'b0;
- alu_op_sel_o = `__ALU_AND__;
- end
-
- /////////////////////////////////////////////////////////////////////////
-
- /* CSR Instructions */
- 17'b???????_???_1110011:begin
- rf_we_o = (rd_sel_o!=0); // CSR Reads should not take place if rs1 == x0
- rf_din_sel_o = 3'd5;
- csru_we_o = 1;
- imm_format = `__I_IMMIDIATE__;
- end
-
- default: begin
- jump_en_o = 0;
- comparison_type_o = `__CMP_UN__;
- rf_we_o = 0;
- rf_din_sel_o = 0;
- a_op_sel_o = 0;
- b_op_sel_o = 0;
- cmp_b_op_sel_o = 0;
- alu_op_sel_o = 0;
- mem_we_o = 1'b0;
- imm_format = 0;
- csru_we_o = 0;
-
- `ifdef ENABLE_RUNTIME_WARNINGS
- if(opcode != 7'b1110011) // EBREAK
- $display("!Unimplemented Opcode: %b", opcode);
- `endif
- end
-
- endcase
-end
+ // Decode fields
+ wire [6:0] opcode = instr_i[6:0];
+ wire [2:0] func3 = instr_i[14:12];
+ wire [6:0] func7 = instr_i[31:25];
+
+ assign mem_access_width_o = func3;
+ assign csru_op_sel_o = func3;
+
+ assign rd_sel_o = instr_i[11:7];
+ assign rs1_sel_o = instr_i[19:15];
+ assign rs2_sel_o = instr_i[24:20];
+
+ reg [2:0] imm_format;
+
+ /*
+ Decode Immediate
+ */
+ reg [31:0] getExtImm;
+
+ always @(*) /*COMBINATORIAL*/
+ begin
+ case(imm_format)
+ `RV_IMM_TYPE_I : getExtImm = {{21{instr_i[31]}}, instr_i[30:25], instr_i[24:21], instr_i[20]};
+ `RV_IMM_TYPE_S : getExtImm = {{21{instr_i[31]}}, instr_i[30:25], instr_i[11:8], instr_i[7]};
+ `RV_IMM_TYPE_B : getExtImm = {{20{instr_i[31]}}, instr_i[7], instr_i[30:25], instr_i[11:8], 1'b0};
+ `RV_IMM_TYPE_U : getExtImm = {instr_i[31], instr_i[30:20], instr_i[19:12], {12{1'b0}}};
+ `RV_IMM_TYPE_J : getExtImm = {{12{instr_i[31]}}, instr_i[19:12], instr_i[20], instr_i[30:25], instr_i[24:21], 1'b0};
+
+ default:
+ getExtImm = 32'd0;
+ endcase
+ end
+
+ assign imm_o = getExtImm;
+
+
+ always @(*) begin
+ // DEFAULT VALUES
+ jump_en_o = 1'b0;
+ comparison_type_o = `CMP_FUNC_UN;
+ rf_we_o = 1'b0;
+ rf_din_sel_o = 3'd0;
+ a_op_sel_o = 1'b0;
+ b_op_sel_o = 1'b0;
+ cmp_b_op_sel_o = 1'b0;
+ alu_op_sel_o = `ALU_FUNC_ADD;
+ mem_we_o = 1'b0;
+ d_mem_load_store = 1'b0;
+ imm_format = `RV_IMM_TYPE_U;
+ csru_we_o = 0;
+
+
+ casez({func7, func3, opcode})
+
+ /* LUI */
+ 17'b???????_???_0110111:
+ begin
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd0;
+ imm_format = `RV_IMM_TYPE_U;
+ end
+
+ /* AUIPC */
+ 17'b???????_???_0010111:
+ begin
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd2;
+ a_op_sel_o = 1'b1;
+ b_op_sel_o = 1'b1;
+ alu_op_sel_o = `ALU_FUNC_ADD;
+ imm_format = `RV_IMM_TYPE_U;
+ end
+
+ /* JAL */
+ 17'b???????_???_1101111:
+ begin
+ jump_en_o = 1'b1;
+ comparison_type_o = `CMP_FUNC_UN;
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd1;
+ a_op_sel_o = 1'b1;
+ b_op_sel_o = 1'b1;
+ alu_op_sel_o = `ALU_FUNC_ADD;
+ imm_format = `RV_IMM_TYPE_J;
+ end
+
+ /* JALR */
+ 17'b???????_000_1100111:
+ begin
+ jump_en_o = 1'b1;
+ comparison_type_o = `CMP_FUNC_UN;
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd1;
+ a_op_sel_o = 1'b0;
+ b_op_sel_o = 1'b1;
+ alu_op_sel_o = `ALU_FUNC_ADD;
+ imm_format = `RV_IMM_TYPE_I;
+ end
+
+ /* BEQ */
+ 17'b???????_000_1100011: begin
+ jump_en_o = 1'b1;
+ comparison_type_o = `CMP_FUNC_EQ;
+ a_op_sel_o = 1'b1;
+ b_op_sel_o = 1'b1;
+ cmp_b_op_sel_o = 1'b0;
+ alu_op_sel_o = `ALU_FUNC_ADD;
+ imm_format = `RV_IMM_TYPE_B;
+ end
+
+ /* BNE */
+ 17'b???????_001_1100011:
+ begin
+ jump_en_o = 1'b1;
+ comparison_type_o = `CMP_FUNC_NQ;
+ a_op_sel_o = 1'b1;
+ b_op_sel_o = 1'b1;
+ cmp_b_op_sel_o = 1'b0;
+ alu_op_sel_o = `ALU_FUNC_ADD;
+ imm_format = `RV_IMM_TYPE_B;
+ end
+
+ /* BLT */
+ 17'b???????_100_1100011:
+ begin
+ jump_en_o = 1'b1;
+ comparison_type_o = `CMP_FUNC_LT;
+ a_op_sel_o = 1'b1;
+ b_op_sel_o = 1'b1;
+ cmp_b_op_sel_o = 1'b0;
+ alu_op_sel_o = `ALU_FUNC_ADD;
+ imm_format = `RV_IMM_TYPE_B;
+ end
+
+ /* BGE */
+ 17'b???????_101_1100011:
+ begin
+ jump_en_o = 1'b1;
+ comparison_type_o = `CMP_FUNC_GE;
+ a_op_sel_o = 1'b1;
+ b_op_sel_o = 1'b1;
+ cmp_b_op_sel_o = 1'b0;
+ alu_op_sel_o = `ALU_FUNC_ADD;
+ imm_format = `RV_IMM_TYPE_B;
+ end
+
+ /* BLTU */
+ 17'b???????_110_1100011:
+ begin
+ jump_en_o = 1'b1;
+ comparison_type_o = `CMP_FUNC_LTU;
+ a_op_sel_o = 1'b1;
+ b_op_sel_o = 1'b1;
+ cmp_b_op_sel_o = 1'b0;
+ alu_op_sel_o = `ALU_FUNC_ADD;
+ imm_format = `RV_IMM_TYPE_B;
+ end
+
+ /* BGEU */
+ 17'b???????_111_1100011:
+ begin
+ jump_en_o = 1'b1;
+ comparison_type_o = `CMP_FUNC_GEU;
+ a_op_sel_o = 1'b1;
+ b_op_sel_o = 1'b1;
+ cmp_b_op_sel_o = 1'b0;
+ alu_op_sel_o = `ALU_FUNC_ADD;
+ imm_format = `RV_IMM_TYPE_B;
+ end
+
+ /* LB, LH, LW, LBU, LHU */
+ 17'b???????_???_0000011:
+ begin
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd4;
+ a_op_sel_o = 1'b0;
+ b_op_sel_o = 1'b1;
+ alu_op_sel_o = `ALU_FUNC_ADD;
+ mem_we_o = 1'b0;
+ d_mem_load_store = 1'b1;
+ imm_format = `RV_IMM_TYPE_I;
+ end
+
+ /* SB, SH, SW */
+ 17'b???????_???_0100011:
+ begin
+ a_op_sel_o = 1'b0;
+ b_op_sel_o = 1'b1;
+ alu_op_sel_o = `ALU_FUNC_ADD;
+ mem_we_o = 1'b1;
+ d_mem_load_store = 1'b1;
+ imm_format = `RV_IMM_TYPE_S;
+ end
+
+ /* ADDI */
+ 17'b???????_000_0010011:
+ begin
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd2;
+ a_op_sel_o = 1'b0;
+ b_op_sel_o = 1'b1;
+ alu_op_sel_o = `ALU_FUNC_ADD;
+ imm_format = `RV_IMM_TYPE_I;
+ end
+
+ /* SLTI */
+ 17'b???????_010_0010011:
+ begin
+ comparison_type_o = `CMP_FUNC_LT;
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd3;
+ cmp_b_op_sel_o = 1'b1;
+ imm_format = `RV_IMM_TYPE_I;
+ end
+
+ /* SLTIU */
+ 17'b???????_011_0010011:
+ begin
+ comparison_type_o = `CMP_FUNC_LTU;
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd3;
+ cmp_b_op_sel_o = 1'b1;
+ imm_format = `RV_IMM_TYPE_I;
+ end
+
+ /* XORI */
+ 17'b???????_100_0010011:
+ begin
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd2;
+ a_op_sel_o = 1'b0;
+ b_op_sel_o = 1'b1;
+ alu_op_sel_o = `ALU_FUNC_XOR;
+ imm_format = `RV_IMM_TYPE_I;
+ end
+
+ /* ORI */
+ 17'b???????_110_0010011:
+ begin
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd2;
+ a_op_sel_o = 1'b0;
+ b_op_sel_o = 1'b1;
+ alu_op_sel_o = `ALU_FUNC_OR;
+ imm_format = `RV_IMM_TYPE_I;
+ end
+
+ /* ANDI */
+ 17'b???????_111_0010011:
+ begin
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd2;
+ a_op_sel_o = 1'b0;
+ b_op_sel_o = 1'b1;
+ alu_op_sel_o = `ALU_FUNC_AND;
+ imm_format = `RV_IMM_TYPE_I;
+ end
+
+ /* SLLI */
+ 17'b0000000_001_0010011:
+ begin
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd2;
+ a_op_sel_o = 1'b0;
+ b_op_sel_o = 1'b1;
+ alu_op_sel_o = `ALU_FUNC_SLL;
+ imm_format = `RV_IMM_TYPE_I;
+ end
+
+ /* SRLI */
+ 17'b0000000_101_0010011:
+ begin
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd2;
+ a_op_sel_o = 1'b0;
+ b_op_sel_o = 1'b1;
+ alu_op_sel_o = `ALU_FUNC_SRL;
+ imm_format = `RV_IMM_TYPE_I;
+ end
+
+ /* SRAI */
+ 17'b0100000_101_0010011:
+ begin
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd2;
+ a_op_sel_o = 1'b0;
+ b_op_sel_o = 1'b1;
+ alu_op_sel_o = `ALU_FUNC_SRA;
+ imm_format = `RV_IMM_TYPE_I;
+ end
+
+ /* ADD */
+ 17'b0000000_000_0110011:
+ begin
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd2;
+ a_op_sel_o = 1'b0;
+ b_op_sel_o = 1'b0;
+ alu_op_sel_o = `ALU_FUNC_ADD;
+ end
+
+ /* SUB */
+ 17'b0100000_000_0110011:
+ begin
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd2;
+ a_op_sel_o = 1'b0;
+ b_op_sel_o = 1'b0;
+ alu_op_sel_o = `ALU_FUNC_SUB;
+ end
+
+ /* SLL */
+ 17'b0000000_001_0110011:
+ begin
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd2;
+ a_op_sel_o = 1'b0;
+ b_op_sel_o = 1'b0;
+ alu_op_sel_o = `ALU_FUNC_SLL;
+ end
+
+ /* SLT */
+ 17'b0000000_010_0110011:
+ begin
+ comparison_type_o = `CMP_FUNC_LT;
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd3;
+ cmp_b_op_sel_o = 1'b0;
+ end
+
+
+ /* SLTU */
+ 17'b0000000_011_0110011:
+ begin
+ comparison_type_o = `CMP_FUNC_LTU;
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd3;
+ cmp_b_op_sel_o = 1'b0;
+ end
+
+ /* XOR */
+ 17'b0000000_100_0110011:
+ begin
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd2;
+ a_op_sel_o = 1'b0;
+ b_op_sel_o = 1'b0;
+ alu_op_sel_o = `ALU_FUNC_XOR;
+ end
+
+ /* SRL */
+ 17'b0000000_101_0110011:
+ begin
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd2;
+ a_op_sel_o = 1'b0;
+ b_op_sel_o = 1'b0;
+ alu_op_sel_o = `ALU_FUNC_SRL;
+ end
+
+ /* SRA */
+ 17'b0100000_101_0110011:
+ begin
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd2;
+ a_op_sel_o = 1'b0;
+ b_op_sel_o = 1'b0;
+ alu_op_sel_o = `ALU_FUNC_SRA;
+ end
+
+ /* OR */
+ 17'b0000000_110_0110011:begin
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd2;
+ a_op_sel_o = 1'b0;
+ b_op_sel_o = 1'b0;
+ alu_op_sel_o = `ALU_FUNC_OR;
+ end
+
+ /* AND */
+ 17'b0000000_111_0110011:
+ begin
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd2;
+ a_op_sel_o = 1'b0;
+ b_op_sel_o = 1'b0;
+ alu_op_sel_o = `ALU_FUNC_AND;
+ end
+
+ /////////////////////////////////////////////////////////////////////////
+
+ /* CSR Instructions */
+ 17'b???????_???_1110011:begin
+ rf_we_o = (rd_sel_o!=0); // CSR Reads should not take place if rs1 == x0
+ rf_din_sel_o = 3'd5;
+ csru_we_o = 1;
+ imm_format = `RV_IMM_TYPE_I;
+ end
+
+ default: begin
+ jump_en_o = 0;
+ comparison_type_o = `CMP_FUNC_UN;
+ rf_we_o = 0;
+ rf_din_sel_o = 0;
+ a_op_sel_o = 0;
+ b_op_sel_o = 0;
+ cmp_b_op_sel_o = 0;
+ alu_op_sel_o = 0;
+ mem_we_o = 1'b0;
+ imm_format = 0;
+ csru_we_o = 0;
+
+ `ifdef verilator
+ if(opcode != 7'b1110011) // EBREAK
+ $display("!Warning: Unimplemented Opcode: %b", opcode);
+ `endif
+ end
+
+ endcase
+ end
endmodule
\ No newline at end of file
diff --git a/rtl/core/Defs.vh b/rtl/core/Defs.vh
new file mode 100644
index 00000000..4eacff91
--- /dev/null
+++ b/rtl/core/Defs.vh
@@ -0,0 +1,68 @@
+//////////////////////////////////////////////////////////////////
+// File : Defs.v
+// Author : Saurabh Singh (saurabh.s99100@gmail.com)
+// Description : Common Definitions for Atom core
+//////////////////////////////////////////////////////////////////
+
+`ifndef __DEFS_VH__
+`define __DEFS_VH__
+
+
+// Reset Address
+`ifdef SOC_RESET_ADDRESS
+ `define RESET_PC_ADDRESS `SOC_RESET_ADDRESS
+`else
+ // Default
+ `define RESET_PC_ADDRESS 32'h0000000
+`endif
+
+
+// NOP instruction (addi x0, x0, 0)
+`define RV_INSTR_NOP 32'h00000013
+
+
+// RISCV Immediate types
+`define RV_IMM_TYPE_I 3'd0
+`define RV_IMM_TYPE_S 3'd1
+`define RV_IMM_TYPE_B 3'd2
+`define RV_IMM_TYPE_U 3'd3
+`define RV_IMM_TYPE_J 3'd4
+
+
+// ALU
+`define ALU_FUNC_ADD 3'd0
+`define ALU_FUNC_SUB 3'd1
+`define ALU_FUNC_XOR 3'd2
+`define ALU_FUNC_OR 3'd3
+`define ALU_FUNC_AND 3'd4
+`define ALU_FUNC_SLL 3'd5
+`define ALU_FUNC_SRL 3'd6
+`define ALU_FUNC_SRA 3'd7
+
+
+// Comparator Unit
+`define CMP_FUNC_UN 3'd0
+`define CMP_FUNC_EQ 3'd1
+`define CMP_FUNC_NQ 3'd2
+`define CMP_FUNC_LT 3'd3
+`define CMP_FUNC_GE 3'd4
+`define CMP_FUNC_LTU 3'd5
+`define CMP_FUNC_GEU 3'd6
+
+
+// Register File
+`define RF_R0_IS_ZERO
+
+
+// ALU
+`define ALU_FUNC_ADD 3'd0
+`define ALU_FUNC_SUB 3'd1
+`define ALU_FUNC_XOR 3'd2
+`define ALU_FUNC_OR 3'd3
+`define ALU_FUNC_AND 3'd4
+`define ALU_FUNC_SLL 3'd5
+`define ALU_FUNC_SRL 3'd6
+`define ALU_FUNC_SRA 3'd7
+
+
+`endif // __DEFS_VH__
\ No newline at end of file
diff --git a/rtl/core/RegisterFile.v b/rtl/core/RegisterFile.v
index a32b2c2f..0929312a 100644
--- a/rtl/core/RegisterFile.v
+++ b/rtl/core/RegisterFile.v
@@ -3,70 +3,75 @@
//
// File : RegisterFile.v
// Author : Saurabh Singh (saurabh.s99100@gmail.com)
-// Description : Parametrized register file for RISCV atom core
+// Description : Parametrized register file for RISCV atom core
////////////////////////////////////////////////////////////////////
-`default_nettype none
`include "../Timescale.vh"
+`include "Utils.vh"
+`include "Defs.vh"
+
+`default_nettype none
-module RegisterFile #( parameter REG_WIDTH = 16, parameter REG_ADDR_WIDTH = 4)
-(
- //////////////////// PORTLIST /////////////////////
+module RegisterFile #(
+ parameter REG_WIDTH = 16,
+ parameter REG_ADDR_WIDTH = 4
+) (
+ //////////////////// PORTLIST /////////////////////
- // read port 1 (Asynchronous Read)
- input wire [REG_ADDR_WIDTH-1:0] Ra_Sel_i,
- output wire [REG_WIDTH-1:0] Ra_o,
-
- // read port 2 (Asynchronous Read)
- input wire [REG_ADDR_WIDTH-1:0] Rb_Sel_i,
- output wire [REG_WIDTH-1:0] Rb_o,
+ // read port 1 (Asynchronous Read)
+ input wire [REG_ADDR_WIDTH-1:0] Ra_Sel_i,
+ output wire [REG_WIDTH-1:0] Ra_o,
+
+ // read port 2 (Asynchronous Read)
+ input wire [REG_ADDR_WIDTH-1:0] Rb_Sel_i,
+ output wire [REG_WIDTH-1:0] Rb_o,
- // write port (Synchronous Write)
- input wire Data_We_i,
- input wire [REG_ADDR_WIDTH-1:0] Rd_Sel_i,
- input wire [REG_WIDTH-1:0] Data_i,
+ // write port (Synchronous Write)
+ input wire Data_We_i,
+ input wire [REG_ADDR_WIDTH-1:0] Rd_Sel_i,
+ input wire [REG_WIDTH-1:0] Data_i,
- input wire Clk_i,
- input wire Rst_i
+ input wire Clk_i,
+ input wire Rst_i
);
- localparam REG_COUNT = 2**REG_ADDR_WIDTH;
+ localparam REG_COUNT = 2**REG_ADDR_WIDTH;
- `ifdef __R0_IS_ZERO__
- reg [REG_WIDTH-1:0] regs [1:REG_COUNT-1] /*verilator public*/; // register array
- `else
- reg [REG_WIDTH-1:0] regs [0:REG_COUNT-1] /*verilator public*/; // register array
- `endif
-
- integer i;
+ `ifdef RF_R0_IS_ZERO
+ reg [REG_WIDTH-1:0] regs [1:REG_COUNT-1] /*verilator public*/; // register array
+ `else
+ reg [REG_WIDTH-1:0] regs [0:REG_COUNT-1] /*verilator public*/; // register array
+ `endif
+
+ integer i;
- /* === WRITE PORT ===
- Synchronous write
- */
- always @ (posedge Clk_i) begin
- if (Rst_i) begin
- for(i=1; i (y)) ? (x) : (y))
+
+
+/////////////////////////////////////////////////////////////
+// Macros for Verilator
+
+`define TRACING_ON /* verilator tracing_on */
+
+`define TRACING_OFF /* verilator tracing_off */
+
+`define UNUSED_VAR(x) always @(x) begin end
+
+`define UNUSED_PARAM(x) /* verilator lint_off UNUSED */ \
+ localparam __``x = x; \
+ /* verilator lint_on UNUSED */
+
+`define UNUSED_PIN(x) /* verilator lint_off PINCONNECTEMPTY */ \
+ . x () \
+ /* verilator lint_on PINCONNECTEMPTY */
+
+`define ASSERT(cond, msg) \
+ assert(cond) else $error msg
+
+`endif // __UTILS_H__
diff --git a/rtl/uncore/BiDirectionalIO.v b/rtl/uncore/BiDirectionalIO.v
index a37ce20c..d6ce33dc 100644
--- a/rtl/uncore/BiDirectionalIO.v
+++ b/rtl/uncore/BiDirectionalIO.v
@@ -1,3 +1,9 @@
+////////////////////////////////////////////////////////////////////
+// File : BiDirectionalIO.v
+// Author : Saurabh Singh (saurabh.s99100@gmail.com)
+// Description : BiDirectional IO (for GPIO pins)
+////////////////////////////////////////////////////////////////////
+
`default_nettype none
module BiDirectionalIO
diff --git a/rtl/uncore/DualPortRAM_wb.v b/rtl/uncore/DualPortRAM_wb.v
index 5bc25663..917bb9ce 100644
--- a/rtl/uncore/DualPortRAM_wb.v
+++ b/rtl/uncore/DualPortRAM_wb.v
@@ -1,3 +1,10 @@
+////////////////////////////////////////////////////////////////////
+// File : DualPortRAM.v
+// Author : Saurabh Singh (saurabh.s99100@gmail.com)
+// Description : A Wishbone interfaced RAM with two ports, Port 1
+// is a Read/Write port while, Port 2 is a readonly port
+////////////////////////////////////////////////////////////////////
+
`default_nettype none
module DualPortRAM_wb #(
diff --git a/rtl/uncore/GPIO.v b/rtl/uncore/GPIO.v
index 65b81087..b5d58faf 100644
--- a/rtl/uncore/GPIO.v
+++ b/rtl/uncore/GPIO.v
@@ -1,3 +1,22 @@
+////////////////////////////////////////////////////////////////////
+// File : GPIO.v
+// Author : Saurabh Singh (saurabh.s99100@gmail.com)
+// Description : GPIO module is a wishbone controlled peripheral
+// which contains 16 Gpio pins (Bi-Directional)
+//
+// Control register | width | relative address
+// ------------------|-------------|-------------------
+// gpio_state 2 bytes 0x00000000
+// gpio_direction 2 bytes 0x00000002
+//
+// each bit in the registers directly corresponds to an io pin.
+// writing "1" to a bit in gpio_direction configures that pin as
+// an input, while writing "0" configures it as an output.
+// Similarily, writing "1" in gpio_state set a pin "HIGH" while
+// writing "0" sets it "LOW".
+//
+////////////////////////////////////////////////////////////////////
+
`include "BiDirectionalIO.v"
`default_nettype none
@@ -10,9 +29,7 @@ module GPIO
output reg [31:0] wb_dat_o,
- /* verilator lint_off UNUSED */
input wire [31:0] wb_dat_i,
- /* verilator lint_on UNUSED */
input wire wb_we_i,
input wire [3:0] wb_sel_i,
diff --git a/rtl/uncore/SinglePortRAM_wb.v b/rtl/uncore/SinglePortRAM_wb.v
index 7146299d..0fed0b49 100644
--- a/rtl/uncore/SinglePortRAM_wb.v
+++ b/rtl/uncore/SinglePortRAM_wb.v
@@ -1,3 +1,9 @@
+////////////////////////////////////////////////////////////////////
+// File : SinglePortRAM.v
+// Author : Saurabh Singh (saurabh.s99100@gmail.com)
+// Description : A Wishbone interfaced RAM with single Read/Write port
+////////////////////////////////////////////////////////////////////
+
`default_nettype none
module SinglePortRAM_wb #(
diff --git a/rtl/uncore/SinglePortROM_wb.v b/rtl/uncore/SinglePortROM_wb.v
index a3e556db..0276d0b8 100644
--- a/rtl/uncore/SinglePortROM_wb.v
+++ b/rtl/uncore/SinglePortROM_wb.v
@@ -1,3 +1,8 @@
+////////////////////////////////////////////////////////////////////
+// File : SinglePortROM.v
+// Author : Saurabh Singh (saurabh.s99100@gmail.com)
+// Description : A Wishbone interfaced ROM module
+////////////////////////////////////////////////////////////////////
`default_nettype none
module SinglePortROM_wb #(
diff --git a/rtl/uncore/simpleuart_wb.v b/rtl/uncore/simpleuart_wb.v
index 86611556..63828db2 100644
--- a/rtl/uncore/simpleuart_wb.v
+++ b/rtl/uncore/simpleuart_wb.v
@@ -1,3 +1,29 @@
+////////////////////////////////////////////////////////////////////
+// File : simpleuart_wb.v
+// Author : Saurabh Singh (saurabh.s99100@gmail.com)
+// Description : Wishbone wrapper for simpleuart.v by clifford wolf
+//
+// Register Description
+// ---------------------
+//
+// let base address = 0x00000000
+//
+// 0x00000000 : 8-bit data register (D-Reg) [ Read & Write ]
+// To transmit a byte : Write to this register
+// To get recieved value : Read from this register.
+// if no value is recieved or value is already read then reg will contain -1.
+//
+// 0x00000001 : 8-bit status (S-Reg) [ Read Only ]
+// bit[0] = recv_buf_valid : recieve buffer has a valid value
+// bit[1] = tx_busy : Transmitter is busy transmitting a byte
+//
+// 0x00000004 : 32-bit Clock Divider Register (CD-Reg) [ Read & Write ]
+// CD register sets the speed of uart tx & rx.
+// if your clk freq is Fc and target baud frequency is Fb then formula for correct value
+// of CD reg is:
+// value = (Fc / Fb) - 2;
+//
+////////////////////////////////////////////////////////////////////
`default_nettype none
`include "simpleuart.v"
@@ -27,29 +53,6 @@ module simpleuart_wb
/* verilator lint_on UNDRIVEN */
);
////////////////////////////////////////////////////////////////////////////////////////////////////
-/*
- Register Description
- ---------------------
-
- let base address = 0x00000000
-
- 0x00000000 : 8-bit data register (D-Reg) [ Read & Write ]
- To transmit a byte : Write to this register
- To get recieved value : Read from this register.
- if no value is recieved or value is already read then reg will contain -1.
-
- 0x00000001 : 8-bit status (S-Reg) [ Read Only ]
- bit[0] = recv_buf_valid : recieve buffer has a valid value
- bit[1] = tx_busy : Transmitter is busy transmitting a byte
-
- 0x00000004 : 32-bit Clock Divider Register (CD-Reg) [ Read & Write ]
- CD register sets the speed of uart tx & rx.
- if your clk freq is Fc and target baud frequency is Fb then formula for correct value
- of CD reg is:
- value = (Fc / Fb) - 2;
-*/
-
-
/*
if __ATOMSIM_SIMULATION__ is defined, this module behaves as a stub. simpleuart is not
instantiated, instead reg_status, reg_data, and reg_div are converted to actual registers
diff --git a/sourceme b/sourceme
new file mode 100644
index 00000000..6547bf4b
--- /dev/null
+++ b/sourceme
@@ -0,0 +1,10 @@
+## RISCV-ATOM Environment Variabes
+
+# export RVATOM variable
+export RVATOM="/home/${USER}/work/riscv/riscv-atom"
+
+# add $RVATOM/build/bin to path
+export PATH="$RVATOM/build/bin:$PATH"
+
+# export RVATOM_LIBS variable
+export RVATOM_LIB="$RVATOM/sw/lib"
\ No newline at end of file
diff --git a/sw/examples/dining-phil/Makefile.include b/sw/examples/dining-phil/Makefile.include
new file mode 100644
index 00000000..f3243501
--- /dev/null
+++ b/sw/examples/dining-phil/Makefile.include
@@ -0,0 +1,2 @@
+src_files = dining-phil.c
+executable = dining-phil.elf
\ No newline at end of file
diff --git a/sw/examples/dining-phil/dining-phil.c b/sw/examples/dining-phil/dining-phil.c
new file mode 100644
index 00000000..26da71d7
--- /dev/null
+++ b/sw/examples/dining-phil/dining-phil.c
@@ -0,0 +1,128 @@
+// @see https://www.thecrazyprogrammer.com/2017/06/dining-philosophers-problem-c-c.html
+
+#include
+
+#define n 4
+
+int compltedPhilo = 0, i;
+
+struct fork
+{
+ int taken;
+} ForkAvil[n];
+
+struct philosp
+{
+ int left;
+ int right;
+} Philostatus[n];
+
+
+
+void goForDinner(int philID)
+{
+ if(Philostatus[philID].left==10 && Philostatus[philID].right == 10) // same like threads concept here cases implemented
+ {
+ printf("Philosopher %d completed his dinner\n", philID + 1);
+ }
+ else if(Philostatus[philID].left==1 && Philostatus[philID].right == 1) // if already completed dinner
+ {
+ printf("Philosopher %d completed his dinner\n", philID + 1); // if just taken two forks
+
+ Philostatus[philID].left = Philostatus[philID].right = 10; // remembering that he completed dinner by assigning value 10
+ int otherFork = philID - 1;
+
+ if(otherFork == -1)
+ otherFork = (n-1);
+
+ ForkAvil[philID].taken = ForkAvil[otherFork].taken = 0; // releasing forks
+ printf("Philosopher %d released fork %d and fork %d\n", philID+1, philID+1, otherFork+1);
+ compltedPhilo++;
+ }
+ else if(Philostatus[philID].left==1 && Philostatus[philID].right == 0)
+ {
+ if(philID==(n-1)) //left already taken, trying for right fork
+ {
+ if(ForkAvil[philID].taken==0) // KEY POINT OF THIS PROBLEM, THAT LAST PHILOSOPHER TRYING IN reverse DIRECTION
+ {
+ ForkAvil[philID].taken = Philostatus[philID].right = 1;
+ printf("Fork %d taken by philosopher %d\n",philID+1,philID+1);
+ }
+ else
+ {
+ printf("Philosopher %d is waiting for fork %d\n",philID+1,philID+1);
+ }
+ }
+ else
+ {
+ //except last philosopher case
+ int dupphilID = philID;
+ philID-=1;
+
+ if(philID== -1)
+ philID=(n-1);
+
+ if(ForkAvil[philID].taken == 0)
+ {
+ ForkAvil[philID].taken = Philostatus[dupphilID].right = 1;
+ printf("Fork %d taken by Philosopher %d\n",philID+1,dupphilID+1);
+ }
+ else
+ {
+ printf("Philosopher %d is waiting for Fork %d\n",dupphilID+1,philID+1);
+ }
+ }
+ }
+ else if(Philostatus[philID].left==0)
+ {
+ //nothing taken yet
+ if(philID==(n-1))
+ {
+ if(ForkAvil[philID-1].taken==0)
+ {
+ //KEY POINT OF THIS PROBLEM, THAT LAST PHILOSOPHER TRYING IN reverse DIRECTION
+ ForkAvil[philID-1].taken = Philostatus[philID].left = 1;
+ printf("Fork %d taken by philosopher %d\n",philID,philID+1);
+ }
+ else
+ {
+ printf("Philosopher %d is waiting for fork %d\n",philID+1,philID);
+ }
+ }
+ else
+ {
+ //except last philosopher case
+ if(ForkAvil[philID].taken == 0)
+ {
+ ForkAvil[philID].taken = Philostatus[philID].left = 1;
+ printf("Fork %d taken by Philosopher %d\n",philID+1,philID+1);
+ }
+ else
+ {
+ printf("Philosopher %d is waiting for Fork %d\n",philID+1,philID+1);
+ }
+ }
+ }
+ else
+ {}
+}
+
+
+int main()
+{
+ for(i=0; i> Till now num of philosophers completed dinner are %d\n\n",compltedPhilo);
+ }
+ return 0;
+}
diff --git a/test/riscv-target/atombones/model_test.h b/test/riscv-target/atombones/model_test.h
index 5e4a2096..41c81072 100644
--- a/test/riscv-target/atombones/model_test.h
+++ b/test/riscv-target/atombones/model_test.h
@@ -11,7 +11,7 @@
.align 8; .global end_regstate; end_regstate: \
.word 4;
-#include "../../../sw/lib/atombones.h"
+// #include "../../../sw/lib/atombones.h"
//TODO: Add code here to run after all tests have been run
// The .align 4 ensures that the signature begins at a 16-byte boundary
diff --git a/test/riscv-target/hydrogensoc/model_test.h b/test/riscv-target/hydrogensoc/model_test.h
index 5e4a2096..41c81072 100644
--- a/test/riscv-target/hydrogensoc/model_test.h
+++ b/test/riscv-target/hydrogensoc/model_test.h
@@ -11,7 +11,7 @@
.align 8; .global end_regstate; end_regstate: \
.word 4;
-#include "../../../sw/lib/atombones.h"
+// #include "../../../sw/lib/atombones.h"
//TODO: Add code here to run after all tests have been run
// The .align 4 ensures that the signature begins at a 16-byte boundary