├── LICENSE ├── README.md ├── doc └── udarkrisc.pdf ├── ise └── risc.xise └── src ├── asm.awk ├── core.ucf ├── core.v ├── rom.asm ├── rom.v ├── soc.v └── system.v /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2015, Marcelo Samsoniuk 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # u[Dark]RISC -- micro-DarkRISC 2 | 3 | This is an early 16-bit RISC processor designed years before DarkRISCV. Although never intendend for real use (it was derived from a serie of experimental cores for a presentation in a University), it is very simple and easy to understand. 4 | 5 | # Features 6 | 7 | Designed back in 2015 (years before DarkRISCV), it includes: 8 | 9 | - Two state pipelined RISC 10 | - Flexible 16x16-bit registers 11 | - 16-bit Program Counter (PC) 12 | - Harvard Architecture w/ separate ROM/RAM up to 64Kword each - Memory mapped IO 13 | - Less than 100 lines of Verilog 14 | - 1/3 of a XC3S50AN@75MHz 15 | - Can be easily changed! 16 | 17 | # History & Motivation 18 | 19 | The beginning: 16-bit VLIW DSPs on FPGAs, with high optimized ALUs around DSP blocks (18x18 mul w/ 48-bit accumulators), in a way that multiple MAC operations can be optimized in parallel w/ other operations (load, branch, etc). However, conventional code was hard to port for VLIW DSPs, so a more general purpose processor was needed... 20 | 21 | Lots of different concepts around accumulator-oriented, register bank oriented, parallel data/address, VLIW, SIMD, MIMD, vector, 16/24/32/48-bits, etc most designs were identified just as “core” or “dsp”, but this specific concept was named uRISC for an external presentation on a University. Because there are too much processors called uRISC already, it was renamed to uDarkRISC (micro-DarkRISC). 22 | 23 | Designed as a evaluation processor, it was never designed to be used on real products and never tested with complex applications... however, the more conventional approach was used as base for DarkRISCV, a high-performance processor which implements a RV32I/E 100% compatible with GCC compiler! For more information about DarkRISCV, please check: https://github.com/darklife/darkriscv/tree/master 24 | 25 | # Instruction Decode 26 | 27 | The 16bit instruction word is read from the synchronous BRAM and divided in 3 or 4 fields, depending on the instruction type: 28 | 29 | - bits 15:12 are the instruction opcode 30 | - bits 11:8 are the destination register (DREG) 31 | - bits 7:4 are the source register (SREG) 32 | - bits 3:0 are reserved for instruction options 33 | 34 | Alternatively, the field 7:0 can be used to load a signed extended 8-bit constant. 35 | 36 | # Instruction Execution 37 | 38 | According to the Destination Register, Source Register, Option Data or Immediate Data, all 16 possible instructions are computed in parallel and put in a 16x16-bit array: 39 | 40 | - shift SREG>>>OPTS ROR) 41 | - shift SREG<<>>OPTS (MUL) 52 | - branch (BRA) 53 | - branch to sub-routine (BSR) 54 | - return from sub-routine (RET) 55 | - test, decrement and branch (LOP) 56 | 57 | Note that there is no conditional branches other than the LOP instruction. 58 | 59 | As far as the instructions are read from the ROM, the opcode is used to index the above array, so the result is written directly to the register bank. Also, the PC is computed, in a way that it can be 0 (RES==0), DREG (RET instruction), PC+IMM (BSR, BRA or LOP instructions) or just PC+1. 60 | 61 | Finnaly, the LOD and STO activate the RD and WR signals for load/store, with DATA active w/ DREG on store or tri-state on load and SREG as pointer in both cases (so, no addressing modes). 62 | 63 | # Pipeline Detail 64 | 65 | The micro-DarkRISC is a high performacne processor that needs a lot of bandwidth on the instructon bus: running at 75MHz, it requires 150MB/s continuously! So the pipeline is optimized in a way that the pipeline is always filled, even in the case of a branch: there is no flush pipeline, so the pre-fetched instruction is executed and the core peaks IPC = 1 all time. 66 | 67 | Since the load/store instructions are not used so often, there is no optimization regarding the load/store. The impact of such decision depends on the application: for applications that are handled only with internal registe, there is no impact. For most case, however, a small LUTRAM may be enough and, again there is no impact. 68 | 69 | Eventually, in the case of BRAM, wait-states are required, but the core does not foresee a HALT signal, so there is no way to insert wait-states. Instead, it is possible simulate such wait-states by sucessive load/store instructions at the same address, so the memory is read multiple times until it is ready. 70 | 71 | # Instruction Set 72 | 73 | The direct supported instructions are: 74 | 75 | - ROR/ROL: register right or left rotate. 76 | - ADD/SUB: register add/sub. 77 | - XOR/AND/OR/NOT: register logic operations. 78 | - LOD/STO: register to/from memory operations. 79 | - IMM: immediate data load (8-bit LSB value). 80 | - MUL: register multiply and right rotate (trying include some DSP support, but without a wide accumulator). 81 | - BRA/BSR: load PC from PC+immediate data and, optionally, save PC to a register. 82 | - RET: load PC from register data. 83 | - LOP: test register, decrement register and set PC to PC+immediate data. 84 | 85 | In addition, there is an Advanced Instruction Set (aka “pseudo-instructions”). 86 | 87 | The known pseudo-instructions are: 88 | 89 | - MOV: ROR or ROL with shift value = 0. 90 | - NOP: MOV with same source/destination register. 91 | - ADDQ/SUBQ: quick add/sub a value between 1 and 15. 92 | - JMP: move the address to a register and RET from this register - INC/DEC: ADDQ/SUBQ with value 1. 93 | - CLR: xor in the same register. 94 | - and much more! 95 | 96 | Since the design was before my contact with RISC-V technology, some important concepts are just missing and the set is mostly 68k oriented: ADDQ, SUBQ, BSR, BRA, etc. Even LOP is basically a RISC version of DBcc, which is pretty useful for DSP applications, since LOP supports delayed branch. Although there is no accumulator, the theory around a large accumulator is compute sucessive MUL + ADD, in a way that the values are shifted left. Instead, on this core, the MUL result is shifted right, so it can be accumulated in a separate step, resulting in values that fits on 16-bit only and all LSBs are lost. 97 | 98 | # Development System 99 | 100 | Limited to an AWK-based assembler that generates a Verilog file w/ the ROM description and waveform inspection of the simulation... I like show the AWK-based assembler because I developed lots and lots of assemblers and converters across my time working on Siemens, both for well-known archs (such as convert 68000 asm to coldfire asm) and obscure and fully proprietary archs (such as multi-way VLIW DSPs), as well all kind of code/data to verilog converters. 101 | 102 | # Conclusion 103 | 104 | Although the uDarkRISC was frozen in time and replaced by the DarkRISCV, there are always people trying find a simple processor to study, which means that there is no bad processors, just processors that are better for different applications. So, although DarkRISCV is good because it can actually run complex code generated by GCC, the uDarkRISC may be far better for starters that are just trying understand how design a simple processor. 105 | -------------------------------------------------------------------------------- /doc/udarkrisc.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darklife/udarkrisc/00e6da173c99a3e5f233f829bc8efd1d3b8bee10/doc/udarkrisc.pdf -------------------------------------------------------------------------------- /ise/risc.xise: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 |
377 | -------------------------------------------------------------------------------- /src/asm.awk: -------------------------------------------------------------------------------- 1 | #!/usr/bin/awk -f 2 | 3 | BEGIN { 4 | 5 | for(i=0;i!=256;i++) NEG[i]=255-i; 6 | 7 | for(j=1;j!=ARGC;j++) 8 | { 9 | print "processing asm file " ARGV[j]; 10 | 11 | FILE=ARGV[j]; 12 | LINE=0; 13 | 14 | while(getline $0 < FILE) 15 | { 16 | if(NF) 17 | { 18 | if($0~/:/) 19 | { 20 | print " label "$1" at line "LINE 21 | gsub(":","",$1); LABEL[$1]=LINE; RLABEL[LINE]=$1 22 | } 23 | else 24 | { 25 | print " instr "$0" at line "LINE 26 | 27 | SRC[LINE]=$0 28 | 29 | for(i=2;i<=NF;i++) 30 | { 31 | if($i~/^%d/) 32 | { 33 | gsub("^%d","",$i); DREG=int($i); print " DREG = "DREG 34 | } 35 | else 36 | if($i~/^%s/) 37 | { 38 | gsub("^%s","",$i); SREG=int($i); print " SREG = "SREG 39 | } 40 | else 41 | { 42 | if(LABEL[$i]) 43 | { 44 | if(LABEL[$i]>LINE) IMMX=(LABEL[$i]-LINE); 45 | else IMMX=NEG[LINE-LABEL[$i]]; 46 | 47 | print " IMMX = "IMMX" "LINE" to "LABEL[$i] 48 | } 49 | else 50 | { 51 | IMMS=int($i); print " IMMS = "IMMS 52 | } 53 | } 54 | } 55 | 56 | if($1=="ror") DST[LINE]=sprintf("%x%x%x%x",0 ,DREG,SREG,IMMS); 57 | if($1=="rol") DST[LINE]=sprintf("%x%x%x%x",1 ,DREG,SREG,IMMS); 58 | if($1=="add") DST[LINE]=sprintf("%x%x%x%x",2 ,DREG,SREG,IMMS); 59 | if($1=="sub") DST[LINE]=sprintf("%x%x%x%x",3 ,DREG,SREG,IMMS); 60 | if($1=="and") DST[LINE]=sprintf("%x%x%x%x",4 ,DREG,SREG,0); 61 | if($1=="or" ) DST[LINE]=sprintf("%x%x%x%x",5 ,DREG,SREG,0); 62 | if($1=="xor") DST[LINE]=sprintf("%x%x%x%x",6 ,DREG,SREG,0); 63 | if($1=="not") DST[LINE]=sprintf("%x%x%x%x",7 ,DREG,0,0); 64 | if($1=="lod") DST[LINE]=sprintf("%x%x%x%x",8 ,DREG,SREG,0); 65 | if($1=="sto") DST[LINE]=sprintf("%x%x%x%x",9 ,DREG,SREG,0); 66 | if($1=="imm") DST[LINE]=sprintf("%x%x%02x",10,DREG,IMMS); 67 | if($1=="mul") DST[LINE]=sprintf("%x%x%x%x",11,DREG,SREG,IMMS); 68 | if($1=="bra") DST[LINE]=sprintf("%x%x%02x",12,DREG,IMMX); 69 | if($1=="bsr") DST[LINE]=sprintf("%x%x%02x",13,DREG,IMMX); 70 | if($1=="ret") DST[LINE]=sprintf("%x%x%x%x",14,DREG,0,0); 71 | if($1=="lop") DST[LINE]=sprintf("%x%x%02x",15,DREG,IMMX); 72 | 73 | if($1=="nop") DST[LINE]=sprintf("%x%x%x%x",0 ,0,0,0); 74 | if($1=="mov") DST[LINE]=sprintf("%x%x%x%x",0 ,DREG,SREG,0); 75 | if($1=="inc") DST[LINE]=sprintf("%x%x%x%x",2 ,DREG,0,1); 76 | if($1=="dec") DST[LINE]=sprintf("%x%x%x%x",3 ,DREG,0,1); 77 | if($1=="clr") DST[LINE]=sprintf("%x%x%x%x",6 ,DREG,DREG,0); 78 | 79 | print " CODE = " DST[LINE]; 80 | 81 | LINE++; 82 | } 83 | } 84 | } 85 | close(FILE); 86 | 87 | VFILE=FILE; 88 | gsub(".asm",".v",VFILE); 89 | 90 | print "" 91 | print " processed code is from "FILE" to "VFILE":" 92 | print "" 93 | 94 | print "module rom(input CLK, input [9:0] ADDR, output reg [15:0] DATA);" > VFILE 95 | print "" > VFILE 96 | print " reg [15:0] ROM [0:1023];" > VFILE 97 | print "" > VFILE 98 | print " integer i;" > VFILE 99 | print "" > VFILE 100 | print " initial" > VFILE 101 | print " begin" > VFILE 102 | print " for(i=0;i!=1024;i=i+1)" > VFILE 103 | print " begin" > VFILE 104 | print " ROM[i] = 0;" > VFILE 105 | print " end" > VFILE 106 | print "" > VFILE 107 | 108 | for(i=0;i!=1024;i++) 109 | { 110 | if(DST[i]) 111 | { 112 | printf(" %04d:%s %20s %s\n",i,DST[i],RLABEL[i],SRC[i]); 113 | print " ROM["i"] = 16'h"DST[i]";" > VFILE 114 | } 115 | } 116 | 117 | print " end" > VFILE 118 | print "" > VFILE 119 | print " always@(posedge CLK) DATA <= ROM[ADDR];" > VFILE 120 | print "endmodule" > VFILE 121 | 122 | close(VFILE) 123 | 124 | print "done." 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/core.ucf: -------------------------------------------------------------------------------- 1 | NET CLK PERIOD = 50MHz; 2 | -------------------------------------------------------------------------------- /src/core.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 15:23:48 02/14/2015 7 | // Design Name: 8 | // Module Name: core 9 | // Project Name: 10 | // Target Devices: 11 | // Tool versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | `define ROR 4'd0 23 | `define ROL 4'd1 24 | `define ADD 4'd2 25 | `define SUB 4'd3 26 | `define AND 4'd4 27 | `define OR 4'd5 28 | `define XOR 4'd6 29 | `define NOT 4'd7 30 | `define LOD 4'd8 31 | `define STO 4'd9 32 | `define IMM 4'd10 33 | `define MUL 4'd11 34 | `define BRA 4'd12 35 | `define BSR 4'd13 36 | `define RET 4'd14 37 | `define LOP 4'd15 38 | 39 | module core( 40 | input CLK, 41 | input RES, 42 | output RD, 43 | output WR, 44 | output [15:0] ADDR, 45 | inout [15:0] DATA 46 | ); 47 | 48 | wire [15:0] IDATA; 49 | 50 | wire [ 3:0] INST = IDATA[15:12]; 51 | wire [ 3:0] DPTR = IDATA[11: 8]; 52 | wire [ 3:0] SPTR = IDATA[ 7: 4]; 53 | wire [ 3:0] OPTS = IDATA[ 3: 0]; 54 | 55 | reg [15:0] PC; 56 | 57 | reg signed [15:0] REG [0:15]; 58 | 59 | wire signed [15:0] IMMS = { IDATA[7]?8'hff:8'h00, IDATA[7:0] }; 60 | wire signed [15:0] DREG = REG[DPTR]; 61 | wire signed [15:0] SREG = REG[SPTR]; 62 | wire signed [15:0] DMUX [0:15]; 63 | 64 | assign DMUX[`ROR] = SREG>>>OPTS; // dreg = sreg>>>opts 65 | assign DMUX[`ROL] = SREG<<>>OPTS; // dreg = (dreg*sreg)>>>opts 76 | assign DMUX[`BRA] = DREG; 77 | assign DMUX[`BSR] = PC+1; // dreg = pc+1, pc += imms 78 | assign DMUX[`RET] = DREG; 79 | assign DMUX[`LOP] = DREG-1; // dreg = dreg-1 80 | 81 | always@(posedge CLK) 82 | begin 83 | REG[DPTR] <= DMUX[INST]; 84 | 85 | PC <= !RES ? 0 : 86 | INST==`RET ? DREG : 87 | PC+(INST==`BSR||INST==`BRA||(INST==`LOP&&!DREG[15])?IMMS:1); 88 | end 89 | 90 | assign RD = INST==`LOD; 91 | assign WR = INST==`STO; 92 | assign DATA = RD ? 16'hzzzz : DREG; 93 | assign ADDR = SREG; 94 | 95 | rom rom(CLK,PC[9:0],IDATA); 96 | 97 | endmodule 98 | -------------------------------------------------------------------------------- /src/rom.asm: -------------------------------------------------------------------------------- 1 | start: 2 | nop 3 | 4 | imm 0 %d0 5 | imm 1 %d1 6 | imm 2 %d2 7 | imm 3 %d3 8 | imm 4 %d4 9 | imm 5 %d5 10 | imm 6 %d6 11 | imm 7 %d7 12 | imm 8 %d8 13 | imm 9 %d9 14 | imm 10 %d10 15 | imm 11 %d11 16 | imm 12 %d12 17 | imm 13 %d13 18 | imm 14 %d14 19 | imm 15 %d15 20 | 21 | clr %d8 22 | xor %s1 %d0 23 | ror %s2 %d3 13 24 | imm 8 %d4 25 | loop: 26 | lod %p8 %d7 27 | not %d7 28 | sto %p8 %d7 29 | lop %d4 loop 30 | nop 31 | 32 | xor %d0 %d0 33 | 34 | stop: 35 | bra stop 36 | nop 37 | -------------------------------------------------------------------------------- /src/rom.v: -------------------------------------------------------------------------------- 1 | module rom(input CLK, input [9:0] ADDR, output reg [15:0] DATA); 2 | 3 | reg [15:0] ROM [0:1023]; 4 | 5 | integer i; 6 | 7 | initial 8 | begin 9 | for(i=0;i!=1024;i=i+1) 10 | begin 11 | ROM[i] = 0; 12 | end 13 | 14 | ROM[0] = 16'h0000; 15 | ROM[1] = 16'ha000; 16 | ROM[2] = 16'ha101; 17 | ROM[3] = 16'ha202; 18 | ROM[4] = 16'ha303; 19 | ROM[5] = 16'ha404; 20 | ROM[6] = 16'ha505; 21 | ROM[7] = 16'ha606; 22 | ROM[8] = 16'ha707; 23 | ROM[9] = 16'ha808; 24 | ROM[10] = 16'ha909; 25 | ROM[11] = 16'haa0a; 26 | ROM[12] = 16'hab0b; 27 | ROM[13] = 16'hac0c; 28 | ROM[14] = 16'had0d; 29 | ROM[15] = 16'hae0e; 30 | ROM[16] = 16'haf0f; 31 | ROM[17] = 16'h6880; 32 | ROM[18] = 16'h6010; 33 | ROM[19] = 16'h032d; 34 | ROM[20] = 16'ha408; 35 | ROM[21] = 16'h8720; 36 | ROM[22] = 16'h7700; 37 | ROM[23] = 16'h9720; 38 | ROM[24] = 16'hf4fc; 39 | ROM[25] = 16'h0000; 40 | ROM[26] = 16'h6020; 41 | ROM[27] = 16'hc0ff; 42 | ROM[28] = 16'h0000; 43 | end 44 | 45 | always@(posedge CLK) DATA <= ROM[ADDR]; 46 | endmodule 47 | -------------------------------------------------------------------------------- /src/soc.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 21:48:56 02/14/2015 7 | // Design Name: 8 | // Module Name: soc 9 | // Project Name: 10 | // Target Devices: 11 | // Tool versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | module soc( 23 | input CLK, 24 | input RES, 25 | input [11:0] IN0, 26 | input [11:0] IN1, 27 | input [11:0] IN2, 28 | input [11:0] IN3, 29 | output reg [11:0] OUT0 = 0, 30 | output reg [11:0] OUT1 = 0, 31 | output reg [11:0] OUT2 = 0, 32 | output reg [11:0] OUT3 = 0 33 | ); 34 | 35 | wire [15:0] ADDR0; 36 | wire [15:0] DATA0; 37 | wire RD0,WR0; 38 | 39 | core core0( 40 | .CLK(CLK), 41 | .RES(RES), 42 | .RD(RD0), 43 | .WR(WR0), 44 | .ADDR(ADDR0), 45 | .DATA(DATA0) 46 | ); 47 | 48 | wire [15:0] ADDR1; 49 | wire [15:0] DATA1; 50 | wire RD1,WR1; 51 | 52 | core core1( 53 | .CLK(CLK), 54 | .RES(RES), 55 | .RD(RD1), 56 | .WR(WR1), 57 | .ADDR(ADDR1), 58 | .DATA(DATA1) 59 | ); 60 | 61 | wire [15:0] ADDR2; 62 | wire [15:0] DATA2; 63 | wire RD2,WR2; 64 | 65 | core core2( 66 | .CLK(CLK), 67 | .RES(RES), 68 | .RD(RD2), 69 | .WR(WR2), 70 | .ADDR(ADDR2), 71 | .DATA(DATA2) 72 | ); 73 | 74 | wire [15:0] ADDR3; 75 | wire [15:0] DATA3; 76 | wire RD3,WR3; 77 | 78 | core core3( 79 | .CLK(CLK), 80 | .RES(RES), 81 | .RD(RD3), 82 | .WR(WR3), 83 | .ADDR(ADDR3), 84 | .DATA(DATA3) 85 | ); 86 | 87 | always@(posedge CLK) 88 | begin 89 | if(WR0) OUT0 = DATA0; 90 | if(WR1) OUT1 = DATA1; 91 | if(WR2) OUT2 = DATA2; 92 | if(WR3) OUT3 = DATA3; 93 | end 94 | 95 | assign DATA0 = RD0 ? IN0 : 16'hzzzz; 96 | assign DATA1 = RD1 ? IN1 : 16'hzzzz; 97 | assign DATA2 = RD2 ? IN2 : 16'hzzzz; 98 | assign DATA3 = RD3 ? IN3 : 16'hzzzz; 99 | 100 | endmodule 101 | -------------------------------------------------------------------------------- /src/system.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | //////////////////////////////////////////////////////////////////////////////// 4 | // Company: 5 | // Engineer: 6 | // 7 | // Create Date: 19:21:40 02/14/2015 8 | // Design Name: core 9 | // Module Name: Z:/Users/marcelo/Documents/Verilog/RISCv2/src/system.v 10 | // Project Name: RISCv2 11 | // Target Device: 12 | // Tool versions: 13 | // Description: 14 | // 15 | // Verilog Test Fixture created by ISE for module: core 16 | // 17 | // Dependencies: 18 | // 19 | // Revision: 20 | // Revision 0.01 - File Created 21 | // Additional Comments: 22 | // 23 | //////////////////////////////////////////////////////////////////////////////// 24 | 25 | module system; 26 | 27 | // Inputs 28 | reg CLK; 29 | reg RES; 30 | 31 | // Outputs 32 | wire RD; 33 | wire WR; 34 | wire [15:0] ADDR; 35 | 36 | // Bidirs 37 | wire [15:0] DATA; 38 | 39 | // Instantiate the Unit Under Test (UUT) 40 | core uut ( 41 | .CLK(CLK), 42 | .RES(RES), 43 | .RD(RD), 44 | .WR(WR), 45 | .ADDR(ADDR), 46 | .DATA(DATA) 47 | ); 48 | 49 | reg [15:0] RAM [0:15]; 50 | 51 | reg [15:0] DATAO = 0; 52 | 53 | integer j; 54 | 55 | initial 56 | begin 57 | for(j=0;j!=16;j=j+1) 58 | begin 59 | RAM[j] = j; 60 | end 61 | end 62 | 63 | reg [3:0] RPTR = 0; 64 | reg [3:0] XPTR = 0; 65 | 66 | assign DATA = RD ? DATAO : 16'hzzzz; 67 | 68 | always@(posedge CLK) 69 | begin 70 | DATAO <= RAM[RPTR]; 71 | if(RD) 72 | begin 73 | RPTR <= RPTR+1; 74 | end 75 | 76 | if(WR) 77 | begin 78 | RAM[XPTR] <= DATA; 79 | XPTR <= XPTR+1; 80 | end 81 | end 82 | 83 | integer i; 84 | 85 | initial begin 86 | // Initialize Inputs 87 | CLK = 0; 88 | RES = 0; 89 | 90 | for(i=0;i!=10000;i=i+1) 91 | begin 92 | #10 CLK = !CLK; 93 | if(i>10) 94 | begin 95 | RES = 1; 96 | end 97 | end 98 | end 99 | 100 | endmodule 101 | --------------------------------------------------------------------------------