summaryrefslogtreecommitdiff
path: root/rtl/core
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2022-09-25 15:00:25 -0600
committerAlejandro Soto <alejandro@34project.org>2022-09-25 15:00:25 -0600
commit5dc62fde35731279e5ef4c7b334cb97d4f24f656 (patch)
treee2f73fccc7acd3eabfc51bc4871e396e1ed11a3d /rtl/core
parent601835e33298015cf49f0ab33a7ef3d61b003ad9 (diff)
Implement register file
Diffstat (limited to 'rtl/core')
-rw-r--r--rtl/core/isa.sv1
-rw-r--r--rtl/core/psr.sv10
-rw-r--r--rtl/core/regs/file.sv24
-rw-r--r--rtl/core/regs/map.sv32
-rw-r--r--rtl/core/regs/regs.sv76
-rw-r--r--rtl/core/uarch.sv13
6 files changed, 156 insertions, 0 deletions
diff --git a/rtl/core/isa.sv b/rtl/core/isa.sv
index be012d1..256c1cc 100644
--- a/rtl/core/isa.sv
+++ b/rtl/core/isa.sv
@@ -6,6 +6,7 @@
typedef logic[3:0] reg_num;
+`define R14 4'b1110
`define R15 4'b1111
`define COND_EQ 4'b0000
diff --git a/rtl/core/psr.sv b/rtl/core/psr.sv
index a66751a..1450333 100644
--- a/rtl/core/psr.sv
+++ b/rtl/core/psr.sv
@@ -6,4 +6,14 @@ typedef struct packed
logic n, z, c, v;
} psr_flags;
+typedef logic[4:0] psr_mode;
+
+`define MODE_USR 5'b10000
+`define MODE_FIQ 5'b10001
+`define MODE_IRQ 5'b10010
+`define MODE_SVC 5'b10011
+`define MODE_ABT 5'b10111
+`define MODE_UND 5'b11011
+`define MODE_SYS 5'b11111
+
`endif
diff --git a/rtl/core/regs/file.sv b/rtl/core/regs/file.sv
new file mode 100644
index 0000000..1b10682
--- /dev/null
+++ b/rtl/core/regs/file.sv
@@ -0,0 +1,24 @@
+`include "core/uarch.sv"
+
+module core_reg_file
+(
+ input logic clk,
+ input reg_index rd_index,
+ wr_index,
+ input logic wr_enable,
+ input word wr_value,
+
+ output word rd_value
+);
+
+ // Ver comentario en uarch.sv
+ word file[30];
+
+ always @(posedge clk)
+ if(wr_enable)
+ file[rd_index] <= wr_value;
+
+ always @(posedge clk)
+ rd_value <= wr_enable & (rd_index == wr_index) ? wr_value : file[rd_index];
+
+endmodule
diff --git a/rtl/core/regs/map.sv b/rtl/core/regs/map.sv
new file mode 100644
index 0000000..b4da988
--- /dev/null
+++ b/rtl/core/regs/map.sv
@@ -0,0 +1,32 @@
+`include "core/isa.sv"
+`include "core/psr.sv"
+`include "core/uarch.sv"
+
+module core_reg_map
+(
+ input reg_num r,
+ input psr_mode mode,
+ output logic is_pc,
+ output reg_index index
+);
+
+ reg_index usr;
+ assign usr = {1'b0, r};
+
+ always_comb begin
+ index = 5'bxxxxx;
+ is_pc = r == `R15;
+
+ if(~is_pc)
+ unique case(mode)
+ `MODE_USR, `MODE_SYS: index = usr;
+ `MODE_FIQ: index = r >= 8 ? usr + 7 : usr;
+ `MODE_IRQ: index = r >= 13 ? usr + 9 : usr;
+ `MODE_UND: index = r >= 13 ? usr + 11 : usr;
+ `MODE_ABT: index = r >= 13 ? usr + 13 : usr;
+ `MODE_SVC: index = r >= 13 ? usr + 15 : usr;
+ default: ;
+ endcase
+ end
+
+endmodule
diff --git a/rtl/core/regs/regs.sv b/rtl/core/regs/regs.sv
new file mode 100644
index 0000000..5f51faa
--- /dev/null
+++ b/rtl/core/regs/regs.sv
@@ -0,0 +1,76 @@
+`include "core/isa.sv"
+`include "core/psr.sv"
+
+module core_regs
+(
+ input logic clk,
+ input reg_num rd_r_a,
+ rd_r_b,
+ wr_r,
+ input psr_mode rd_mode,
+ wr_mode,
+ input logic wr_enable,
+ input word wr_value,
+ input ptr pc_visible,
+
+ output word rd_value_a,
+ rd_value_b,
+ output logic branch
+);
+
+ /* Las Cyclone V no tienen bloques de memoria con al menos dos puertos de
+ * lectura y uno de escritura (tres puertos), lo más que tienen son bloques
+ * de dos puertos en total. Podemos ponerle cinta a esto con dos copias
+ * sincronizadas del archivo de registros.
+ */
+
+ logic rd_pc_a, rd_pc_b, wr_pc, file_wr_enable;
+ reg_index rd_index_a, rd_index_b, wr_index;
+ word pc_word, file_rd_value_a, file_rd_value_b;
+
+ assign pc_word = {pc_visible, 2'b00};
+ assign rd_value_a = rd_pc_a ? pc_word : file_rd_value_a;
+ assign rd_value_b = rd_pc_b ? pc_word : file_rd_value_b;
+ assign branch = wr_enable & wr_pc;
+
+ core_reg_file a
+ (
+ .rd_index(rd_index_a),
+ .rd_value(file_rd_value_a),
+ .wr_enable(file_wr_enable),
+ .*
+ );
+
+ core_reg_file b
+ (
+ .rd_index(rd_index_b),
+ .rd_value(file_rd_value_b),
+ .wr_enable(wr_enable & ~wr_pc),
+ .*
+ );
+
+ core_reg_map map_rd_a
+ (
+ .r(rd_r_a),
+ .mode(rd_mode),
+ .is_pc(rd_pc_a),
+ .index(rd_index_a)
+ );
+
+ core_reg_map map_rd_b
+ (
+ .r(rd_r_b),
+ .mode(rd_mode),
+ .is_pc(rd_pc_b),
+ .index(rd_index_b)
+ );
+
+ core_reg_map map_wr
+ (
+ .r(wr_r),
+ .mode(wr_mode),
+ .is_pc(wr_pc),
+ .index(wr_index)
+ );
+
+endmodule
diff --git a/rtl/core/uarch.sv b/rtl/core/uarch.sv
index c5a449c..1ba039e 100644
--- a/rtl/core/uarch.sv
+++ b/rtl/core/uarch.sv
@@ -4,6 +4,19 @@
// Decodifica como andeq r0, r0, r0
`define NOP 32'd0
+typedef logic[31:0] word;
+typedef logic[29:0] ptr;
+
+/* Se necesitan 30 GPRs. De A2.3:
+ *
+ * The ARM processor has a total of 37 registers:
+ *
+ * Thirty-one general-purpose registers, including a program counter. These
+ * registers are 32 bits wide and are described in General-purpose registers on
+ * page A2-6.
+ */
+typedef logic[4:0] reg_index;
+
typedef enum logic[1:0]
{
ALU_ADD,