22#include "uintN_t.h"
33#include "intN_t.h"
44
5- // Support old single core using mem_map_out_t
6- #include "mem_map.h"
7- #ifdef riscv_mem_map_outputs_t
8- #define riscv_mmio_mod_out_t riscv_mem_map_mod_out_t(riscv_mem_map_outputs_t)
9- #else
10- #define riscv_mmio_mod_out_t mem_map_out_t
11- #endif
5+ // RISC-V components
6+ #define RISCV_REGFILE_1_CYCLE
7+ #include "risc-v.h"
128
139// Declare instruction and data memory
1410// also includes memory mapped IO
1713// Multi cycle is not a pipeline
1814#define RISCV_IMEM_NO_AUTOPIPELINE
1915#define RISCV_DMEM_NO_AUTOPIPELINE
20- #define N_CYCLES 3
2116#include "mem_decl.h"
2217
2318// CPU top level
19+ #define N_CYCLES 4 // 3 pipeline reg delays: imem, regfile, dmem = 4 cycles
2420#define riscv_out_t PPCAT(riscv_name,_out_t)
2521typedef struct riscv_out_t {
2622 // Debug IO
@@ -90,6 +86,8 @@ riscv_out_t riscv_name(
9086 }
9187
9288 // Boundary shared between cycle0 and cycle1
89+ // TODO IMEM is stateless shouldnt need if(state) logic
90+ // can do like DMEM and be always in use
9391 if (state [0 ]|state [1 ]){
9492 // Instruction memory
9593 imem_out = riscv_imem_ram (pc >>2 , 1 );
@@ -113,9 +111,10 @@ riscv_out_t riscv_name(
113111 ARRAY_1ROT_UP (uint1_t , next_state , N_CYCLES )
114112 }
115113
116- // Cycle1+2: Register file reads and writes
117- // Reads are done during cycle1
118- // Write back is next clock, cycle2
114+ // Cycle1+2+3: Register file reads and writes
115+ // Reads start during cycle1
116+ // Read finish during cycle2
117+ // Write back is next clock, cycle3
119118 // Register file write signals are not driven until later in code
120119 // but are used now, requiring FEEDBACK pragma
121120 uint5_t reg_wr_addr ;
@@ -124,7 +123,9 @@ riscv_out_t riscv_name(
124123 #pragma FEEDBACK reg_wr_addr
125124 #pragma FEEDBACK reg_wr_data
126125 #pragma FEEDBACK reg_wr_en
127- if (state [1 ]|state [2 ]){
126+ // TODO make this like DMEM, doesnt need if(state) specific
127+ // doesnt need to do next_state transition either
128+ if (state [1 ]|state [2 ]|state [3 ]){
128129 reg_file_out = reg_file (
129130 decoded .src1 , // First read port address
130131 decoded .src2 , // Second read port address
@@ -137,31 +138,31 @@ riscv_out_t riscv_name(
137138 ARRAY_1ROT_UP (uint1_t , next_state , N_CYCLES )
138139 }
139140
140- // Cycle1 : Execute
141- if (state [1 ]){
142- printf ("Execute in Cycle/Stage 1 \n" );
141+ // Cycle2 : Execute
142+ if (state [2 ]){
143+ printf ("Execute in Cycle/Stage 2 \n" );
143144 exe = execute (
144145 pc , pc_plus4_reg ,
145- decoded ,
146+ decoded_reg ,
146147 reg_file_out .rd_data1 , reg_file_out .rd_data2
147148 );
148149 // Next state/cycle (potentially redundant)
149150 next_state = state ;
150151 ARRAY_1ROT_UP (uint1_t , next_state , N_CYCLES )
151152 }
152153
153- // Boundary shared between cycle1 and cycle2
154+ // Boundary shared between cycle2 and cycle3
154155 // Data Memory inputs in stage1
155156 // Default no writes or reads
156157 ARRAY_SET (mem_wr_byte_ens , 0 , 4 )
157158 ARRAY_SET (mem_rd_byte_ens , 0 , 4 )
158159 mem_addr = exe .result ; // addr always from execute module, not always used
159160 mem_wr_data = reg_file_out .rd_data2 ;
160- if (state [1 ]){
161+ if (state [2 ]){
161162 // Only write or read en during first cycle of two cycle read
162- mem_wr_byte_ens = decoded .mem_wr_byte_ens ;
163- mem_rd_byte_ens = decoded .mem_rd_byte_ens ;
164- if (decoded .mem_wr_byte_ens [0 ]){
163+ mem_wr_byte_ens = decoded_reg .mem_wr_byte_ens ;
164+ mem_rd_byte_ens = decoded_reg .mem_rd_byte_ens ;
165+ if (decoded_reg .mem_wr_byte_ens [0 ]){
165166 printf ("Write Mem[0x%X] = %d\n" , mem_addr , mem_wr_data );
166167 }
167168 }
@@ -182,21 +183,21 @@ riscv_out_t riscv_name(
182183 #ifdef riscv_mem_map_outputs_t
183184 o .mem_map_outputs = dmem_out .mem_map_outputs ;
184185 #endif
185- // Data memory outputs in stage2
186- if (state [2 ]){
186+ // Data memory outputs in stage3
187+ if (state [3 ]){
187188 // Read output available from dmem_out in second cycle of two cycle read
188189 if (decoded_reg .mem_rd_byte_ens [0 ]){
189190 printf ("Read Mem[0x%X] = %d\n" , mem_addr_reg , dmem_out .rd_data );
190191 }
191192 }
192193
193- // Cycle 2 : Write Back + Next PC
194+ // Cycle 3 : Write Back + Next PC
194195 // default values needed for feedback signals
195196 reg_wr_en = 0 ; // default no writes
196197 reg_wr_addr = 0 ;
197198 reg_wr_data = 0 ;
198- if (state [2 ]){
199- printf ("Write Back + Next PC in Cycle/Stage 2 \n" );
199+ if (state [3 ]){
200+ printf ("Write Back + Next PC in Cycle/Stage 3 \n" );
200201 // Reg file write back, drive inputs (FEEDBACK)
201202 reg_wr_en = decoded_reg .reg_wr ;
202203 reg_wr_addr = decoded_reg .dest ;
0 commit comments