cpu32

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 796c3cd6166d1d349d1abbe77bb715d57a351cef
parent 9ab30383e1761fa0d0d969050000d13eaceaa666
Author: Brian Swetland <swetland@frotz.net>
Date:   Sat, 11 Feb 2012 00:25:02 -0800

completely overhaul the ISA, decoder, assembler, etc

- simplify encoding, move closer to MIPS
- R15 is now the zero/discard register
- adjust the ALU ops to reflect having a zero register
- update testcases and golden traces

Diffstat:
MMakefile | 2+-
Ma32.c | 235++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Misa.txt | 66++++++++++++++++++++++++++++++++++++------------------------------
Mtests/0000-nothing.s.gold | 2+-
Mtests/0010-load-imm.s | 12++++++------
Mtests/0010-load-imm.s.gold | 21+++++++++++----------
Mtests/0020-counting.s | 4++--
Mtests/0020-counting.s.gold | 62+++++++++++++++++++++++++++++++-------------------------------
Mtests/0030-ram.s | 4++--
Mtests/0030-ram.s.gold | 18+++++++++---------
Mverilog/alu.v | 23+++++++++++------------
Mverilog/control.v | 104++++++++++++++++++++-----------------------------------------------------------
Mverilog/cpu32.v | 74++++++++++++++++++++++++++++++++++++++++++++++----------------------------
Mverilog/library.v | 2++
Mverilog/ram.v | 2++
Mverilog/regfile.v | 25++++++++++++++++++-------
Mverilog/rom.v | 1-
Mverilog/testbench.v | 33++++++++++++++-------------------
18 files changed, 344 insertions(+), 346 deletions(-)

diff --git a/Makefile b/Makefile @@ -12,7 +12,7 @@ TESTS := $(wildcard tests/*.s) RESULTS := $(TESTS:.s=.s.pass) testbench: $(SRC) - iverilog -o testbench $(SRC) + iverilog -Wall -o testbench $(SRC) a32: a32.c gcc -g -Wall -o a32 a32.c diff --git a/a32.c b/a32.c @@ -167,12 +167,11 @@ enum tokens { tSTRING, tNUMBER, tORR, tAND, tADD, tSUB, tSHL, tSHR, tXOR, tTBS, - tSEQ, tSLT, tSGT, tMOV, tBIS, tBIC, tMLO, tMHI, + tBIS, tBIC, tSLT, tSGT, tMLO, tMHI, tASR, tMUL, tB, tBL, tBZ, tBNZ, tBLZ, tBLNZ, tLW, tSW, tR0, tR1, tR2, tR3, tR4, tR5, tR6, tR7, - rR8, tR9, tR10, tR11, tR12, tR13, tR14, tR15, - tSP, tLR, - tNOP, + rR8, tR9, tR10, tR11, tR12, tSP, tLR, tZR, + tNOP, tSNE, tNOT, tMOV, tEQU, tWORD, tASCII, tASCIIZ, NUMTOKENS, }; @@ -183,19 +182,18 @@ char *tnames[] = { "<STRING>", "<NUMBER>", "ORR", "AND", "ADD", "SUB", "SHL", "SHR", "XOR", "TBS", - "SEQ", "SLT", "SGT", "MOV", "BIS", "BIC", "MLO", "MHI", + "BIS", "BIC", "SLT", "SGT", "MLO", "MHI", "ASR", "MUL", "B", "BL", "BZ", "BNZ", "BLZ", "BLNZ", "LW", "SW", "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", - "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", - "SP", "LR", - "NOP", + "R8", "R9", "R10", "R11", "R12", "SP", "LR", "ZR", + "NOP", "SNE", "NOT", "MOV", "EQU", "WORD", "STRING", "ASCIIZ" }; #define FIRST_ALU_OP tORR -#define LAST_ALU_OP tMHI +#define LAST_ALU_OP tMUL #define FIRST_REGISTER tR0 -#define LAST_REGISTER tR15 +#define LAST_REGISTER tZR int is_register(unsigned tok) { return ((tok >= FIRST_REGISTER) && (tok <= LAST_REGISTER)); @@ -363,93 +361,112 @@ void expect_register(unsigned got) { #define REG(n) (tnames[FIRST_REGISTER + (n)]) -void disassemble(char *buf, unsigned pc, unsigned instr) { - unsigned op = instr >> 28; +int match(unsigned n, unsigned mask, unsigned value) { + return (n & mask) == value; +} + +char *append(char *buf, char *s) +{ + while (*s) + *buf++ = *s++; + return buf; +} +char *append_u32(char *buf, unsigned n) { + sprintf(buf,"%08x",n); + return buf + strlen(buf); +} +char *append_u16(char *buf, unsigned n) { + sprintf(buf,"%04x",n&0xFFFF); + return buf + strlen(buf); +} +char *append_s16(char *buf, short n) { + sprintf(buf,"%d",n); + return buf + strlen(buf); +} + +void printinst(char *buf, unsigned pc, unsigned instr, const char *fmt) { unsigned fn = (instr >> 24) & 0xF; - unsigned opfn = (instr >> 24) & 0xFF; unsigned a = (instr >> 20) & 0xF; unsigned b = (instr >> 16) & 0xF; unsigned d = (instr >> 12) & 0xF; unsigned i16 = instr & 0xFFFF; int s16 = ((short) i16) * 4; - /* check for special forms */ - if (instr == 0) { - sprintf(buf, "NOP"); - return; + while (*fmt) { + if (*fmt != '@') { + *buf++ = *fmt++; + continue; + } + switch (*++fmt) { + case 'A': + buf = append(buf,REG(a)); + break; + case 'B': + buf = append(buf,REG(b)); + break; + case 'D': + buf = append(buf,REG(d)); + break; + case 'F': /* alu function */ + buf = append(buf,tnames[FIRST_ALU_OP + fn]); + break; + case 'u': + buf = append_u16(buf,i16); + break; + case 's': + buf = append_s16(buf,(short)i16); + break; + case 'r': + buf = append(buf,"0x"); + buf = append_u32(buf,(pc + s16)); + break; + case 0: + goto done; + } + fmt++; } +done: + *buf = 0; +} - switch (opfn) { - case 0x0B: - sprintf(buf, "MOV %s, %s", REG(d), REG(b)); - break; - case 0x0E: - sprintf(buf, "MLO %s, %s", REG(d), REG(b)); - break; - case 0x0F: - sprintf(buf, "MHI %s, %s", REG(d), REG(b)); - break; - case 0x1B: - sprintf(buf, "MOV %s, %d", REG(b), i16); - break; - case 0x1E: - sprintf(buf, "MOV %s, #%d", REG(b), ((short)i16)); - break; - case 0x1F: - sprintf(buf, "MOV %s, #0x%04x0000", REG(b), i16); - break; - case 0x20: - sprintf(buf, "LW %s, [%s, #%d]", REG(b), REG(a), i16); - break; - case 0x30: - sprintf(buf, "SW %s, [%s, #%d]", REG(b), REG(a), i16); - break; - case 0x41: - sprintf(buf, "BZ %s, 0x%08x", REG(a), (pc + s16)); - break; - case 0x42: - sprintf(buf, "BNZ %s, 0x%08x", REG(a), (pc + s16)); - break; - case 0x43: - sprintf(buf, "B 0x%08x", (pc + s16)); - break; - case 0x49: - sprintf(buf, "BLZ %s, 0x%08x", REG(a), (pc + s16)); - break; - case 0x4A: - sprintf(buf, "BLNZ %s, 0x%08x", REG(a), (pc + s16)); - break; - case 0x4B: - sprintf(buf, "BL 0x%08x", (pc + s16)); - break; - case 0x51: - sprintf(buf, "BZ %s, %s", REG(a), REG(b)); - break; - case 0x52: - sprintf(buf, "BNZ %s, %s", REG(a), REG(b)); - break; - case 0x53: - sprintf(buf, "B %s", REG(b)); - break; - case 0x59: - sprintf(buf, "BLZ %s, %s", REG(a), REG(b)); - break; - case 0x5A: - sprintf(buf, "BLNZ %s, %s", REG(a), REG(b)); - break; - case 0x5B: - sprintf(buf, "BL %s", REG(b)); - break; - default: - if (op == 0) { - sprintf(buf, "%-5s%s, %s, %s", - tnames[FIRST_ALU_OP + fn], REG(d), REG(a), REG(b)); - } else if (op == 1) { - sprintf(buf, "%-5s%s, %s, #%d", - tnames[FIRST_ALU_OP + fn], REG(b), REG(a), i16); +struct { + unsigned mask; + unsigned value; + const char *fmt; +} decode[] = { + { 0xFFFFFFFF, 0x00000000, "NOP", }, + { 0xFFFFFFFF, 0xFFFFFFFF, "HALT", }, + { 0xFFF00000, 0x10F00000, "MOV @B, #@s", }, // ORR Rd, Rz, #I + { 0xFFF00000, 0x1CF00000, "MLO @B, #0x@u", }, // MLO Rd, Rz, #I + { 0xFFF00000, 0x1DF00000, "MOV @B, #0x@u0000", }, // MHI Rd, Rz, #I + { 0xFF000000, 0x1C000000, "MLO @B, @A, #0x@u", }, // MLO Rd, Ra, #I + { 0xF0000000, 0x00000000, "@F @D, @A, @B", }, + { 0xF0000000, 0x10000000, "@F @B, @A, @s", }, + { 0xFF00FFFF, 0x22000000, "LW @B, [@A]", }, + { 0xFF000000, 0x22000000, "LW @B, [@A, #@s]", }, + { 0xFF00FFFF, 0x32000000, "SW @B, [@A]", }, + { 0xFF000000, 0x32000000, "SW @B, [@A, #@s]", }, + { 0xFFFF0000, 0x40FF0000, "B @r", }, + { 0xFFFF0000, 0x40FE0000, "BL @r", }, + { 0xFF0F0000, 0x400F0000, "BZ @A, @r", }, + { 0xFF0F0000, 0x400E0000, "BLZ @A, @r", }, + { 0xFFF0F000, 0x44F0F000, "B @B", }, + { 0xFFF0F000, 0x44F0E000, "BL @B", }, + { 0xFF00F000, 0x4400F000, "BZ @A, @B", }, + { 0xFF00F000, 0x4400E000, "BLZ @A, @B", }, + { 0xFF0F0000, 0x480F0000, "BNZ @A, @r", }, + { 0xFF0F0000, 0x480E0000, "BLNZ @A, @r", }, + { 0xFF00F000, 0x4800F000, "BNZ @A, @B", }, + { 0xFF00F000, 0x4800E000, "BLNZ @A, @B", }, + { 0x00000000, 0x00000000, "UNDEFINED", }, +}; + +void disassemble(char *buf, unsigned pc, unsigned instr) { + int n = 0; + for (n = 0 ;; n++) { + if ((instr & decode[n].mask) == decode[n].value) { + printinst(buf, pc, instr, decode[n].fmt); return; - } else { - sprintf(buf, "UND 0x%02x", opfn); } } } @@ -487,44 +504,44 @@ void assemble_line(int n, unsigned *tok, unsigned *num, char **str) { expect(tCOMMA,tok[2]); expect(tNUMBER,tok[3]); if (num[3] == 0xFFFF) { - /* special case, need to use unsigned MOV */ - emit(0x1B00FFFF | TO_B(to_register(tok[1]))); + /* special case, need to use MLO */ + emit(0x1CF0FFFF | TO_B(to_register(tok[1]))); return; } tmp = num[3] & 0xFFFF8000; if ((tmp == 0) || (tmp == 0xFFFF8000)) { - /* otherwise, sign extending MLO instruction will work */ - emit(0x1E000000 | TO_B(to_register(tok[1])) | TO_I16(num[3])); + /* otherwise, sign extending MOV instruction will work */ + emit(0x10F00000 | TO_B(to_register(tok[1])) | TO_I16(num[3])); return; } - /* MHI instruction to set the high bits */ - emit(0x1F000000 | TO_B(to_register(tok[1])) | (TO_I16(num[3] >> 16))); + /* MHI Rd, Rz, #I instruction to set the high bits */ + emit(0x1DF00000 | TO_B(to_register(tok[1])) | (TO_I16(num[3] >> 16))); if (num[3] & 0xFFFF) { - /* OR in the low bits if present */ - emit(0x10000000 | TO_A(to_register(tok[1])) | TO_B(to_register(tok[1])) | TO_I16(num[3])); + /* MLO Rd, Rd, #I - in the low bits if present */ + emit(0x1C000000 | TO_A(to_register(tok[1])) | TO_B(to_register(tok[1])) | TO_I16(num[3])); } return; case tMHI: expect_register(tok[1]); expect(tCOMMA,tok[2]); expect(tNUMBER,tok[3]); - emit(0x1F000000 | TO_B(to_register(tok[1])) | TO_I16(num[3])); + emit(0x1D000000 | TO_B(to_register(tok[1])) | TO_I16(num[3])); return; case tB: case tBL: if (tok[0] == tB) { - instr = 0x43000000; + tmp = 15; } else { - instr = 0x4B0F0000; + tmp = 14; } if (is_register(tok[1])) { - emit(instr | 0x10000000 | TO_B(to_register(tok[1]))); + emit(0x44F00000 | TO_D(tmp) | TO_B(to_register(tok[1]))); } else if (tok[1] == tSTRING) { - emit(instr); + emit(0x40F00000 | TO_B(tmp)); uselabel(str[1], PC - 1, 16); } else if ((tok[1] == tNUMBER) || (tok[1] == tDOT)) { if (!is_signed_16(num[1])) die("branch target out of range"); - emit(instr | TO_I16(num[1])); + emit(0x40F00000 | TO_B(tmp) | TO_I16(num[1])); } else { die("expected branch target, got %s", tnames[tok[1]]); } @@ -534,18 +551,18 @@ void assemble_line(int n, unsigned *tok, unsigned *num, char **str) { case tBLNZ: case tBLZ: switch (tok[0]) { - case tBZ: instr = 0x41000000; break; - case tBNZ: instr = 0x42000000; break; - case tBLZ: instr = 0x490F0000; break; - case tBLNZ: instr = 0x4A0F0000; break; + case tBZ: instr = 0x40000000; tmp = 15; break; + case tBNZ: instr = 0x48000000; tmp = 15; break; + case tBLZ: instr = 0x40000000; tmp = 14; break; + case tBLNZ: instr = 0x48000000; tmp = 14; break; } expect_register(tok[1]); expect(tCOMMA,tok[2]); instr |= TO_A(to_register(tok[1])); if (is_register(tok[3])) { - emit(instr | 0x10000000 | TO_B(to_register(tok[3]))); + emit(instr | 0x04000000 | TO_D(tmp) | TO_B(to_register(tok[3]))); } else if (tok[3] == tSTRING) { - emit(instr); + emit(instr | TO_B(tmp)); uselabel(str[3], PC - 1, 16); } else if ((tok[3] == tNUMBER) || (tok[3] == tDOT)) { if (!is_signed_16(num[3])) die("branch target out of range"); @@ -557,9 +574,9 @@ void assemble_line(int n, unsigned *tok, unsigned *num, char **str) { case tLW: case tSW: if (tok[0] == tLW) { - instr = 0x20000000; + instr = 0x22000000; } else { - instr = 0x30000000; + instr = 0x32000000; } expect_register(tok[1]); expect(tCOMMA,tok[2]); diff --git a/isa.txt b/isa.txt @@ -6,7 +6,6 @@ Encoding Formats R OOOOFFFFAAAABBBBDDDDXXXXXXXXXXXX register I OOOOFFFFAAAADDDDIIIIIIIIIIIIIIII immediate -L OOOOFFFFIIIIIIIIIIIIIIIIIIIIIIII large (not currently used) Core Instruction Set -------------------- @@ -14,28 +13,23 @@ Core Instruction Set 0X ALU Rd, Ra, Rb see ALU ops below 1X ALU Rd, Ra, #I -20 LW Rd, [Ra, #I] Rd = M(Ra + I) (TBD F->lane/width select) -30 SW Rd, [Ra, #I] M(Ra + I) = Rd +22 LW Rd, [Ra, #I] Rd = M(Ra + I) +32 SW Rd, [Ra, #I] M(Ra + I) = Rd -41 BZ Ra, rel16 if Ra == 0: PC += I -42 BNZ Ra, rel16 if Ra != 0: PC += I -43 B rel16 PC += I -49 BLZ Ra, rel16 if Ra == 0: R15 = PC + 4, PC += I -4A BLNZ Ra, rel16 if Ra != 0: R15 = PC + 4, PC += I -4B BL rel16 R15 = PC + 4, PC += I +40 BLZ Rd, Ra, rel if (Ra == 0) { Rd = PC + 4, PC += I } +44 BLZ Rd, Ra, Rb if (Ra == 0) { Rd = PC + 4, PC = Rb } +48 BLNZ Rd, Ra, rel if (Ra != 0) { Rd = PC + 4, PC += I } +4C BLNZ Rd, Ra, Rb if (Ra != 0) { Rd = PC + 4, PC = Rb } -51 BZ Ra, Rb if Ra == 0: PC = Rb -52 BNZ Ra, Rb if Ra != 0: PC = Rb -53 B Rb PC = Rb -59 BNZ Ra, Rb if Ra == 0: R15 = PC, PC = Rb -5A BLNZ Ra, Rb if Ra != 0: R15 = PC, PC = Rb -5B BL Rb R15 = PC, PC = Rb - -Extended Instruction Set +Extended Instruction Set (tbd) ------------------------ -60 J rel24 PC = PC + I -68 JL rel24 R15 = PC + 4, PC = PC + I +52 LW Rd, [PC, #I] Rd = M(PC + I) + +6X LB +7X SB +8X LH +9X SH ALU Instructions (replace Rb w/ #I for immediate form) ------------------------------------------------------ @@ -47,21 +41,33 @@ X3 SUB Rd, Ra, Rb Rd = Ra - Rb X4 SHL Rd, Ra, Rb Rd = Ra << Rb[0:4] X5 SHR Rd, Ra, Rb Rd = Ra >> Rb[0:4] X6 XOR Rd, Ra, Rb Rd = Ra ^ Rb -X7 TBS Rd, Ra, Rb Rd = Ra & (1 << Rb) ? 1 : 0 +X7 TBS Rd, Ra, Rb Rd = Ra & (1 << Rb) + +X8 BIS Rd, Ra, Rb Rd = Ra | (1 << Rb) +X9 BIC Rd, Ra, Rb Rd = Ra & ~(1 << Rb) +XA SLT Rd, Ra, Rb Rd = Ra < Rb +XB SGT Rd, Ra, Rb Rd = Ra > Rb +XC MLO Rd, Ra, Rb Rd = (Ra & 0xFFFF0000) | (Rb & 0xFFFF) +XD MHI Rd, Ra, Rb Rd = (Ra & 0xFFFF) | (Rb << 16) +XE ASR Rd, Ra, Rb Rd = (Ra >>> Rb[0:4]) +XF MUL Rd, Ra, Rb Rd = Ra * Rb + +Pseudo Instructions +------------------- + +MOV Rd, Rb OR Rd, R0, Rb +SNE Rd, Ra, Rb SUB Rd, Ra, Rb +NOT Rd, Ra XOR Rd, Ra, #-1 -X8 SEQ Rd, Ra, Rb Rd = Ra == Rb -X9 SLT Rd, Ra, Rb Rd = Ra < Rb -XA SGT Rd, Ra, Rb Rd = Ra > Rb -XB MOV Rd, Ra Rd = Ra -XC BIS Rd, Ra, Rb Rd = Ra | (1 << Rb) -XD BIC Rd, Ra, Rb Rd = Ra & ~(1 << Rb) -XE MLO Rd, Rb Rd = signextend(Rb[15:0]) -XF MHI Rd, Ra, Rb Rd = (Ra & 0xFFFF) | (Rb << 16) +Registers +--------- +R0-R3 args / results +R13 stack pointer (aka SP) +R14 link (aka LR) +R15 zero (aka ZR) Open Issues ----------- -- should ALU IMM16 be signed? -- figure out func field coding for variant LW/SW instructions - syntax for conditional branches is confusing - consider allowing B [Rx] as well as B Rx? - allow # in front of constants diff --git a/tests/0000-nothing.s.gold b/tests/0000-nothing.s.gold @@ -1,2 +1,2 @@ -PC> 00000000 I> 1e000000 R> xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000000 I> 10f00000 R> xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx PC> EXIT diff --git a/tests/0010-load-imm.s b/tests/0010-load-imm.s @@ -1,18 +1,18 @@ NOP load_zero: -MOV R0, 0 +MOV R1, 0 load_F0000000: MOV R0, 0xF0000000 load_12345678: -MOV R0, 0x12345678 +MOV R2, 0x12345678 load_FFFFFFFF: -MOV R0, 0xFFFFFFFF +MOV R3, 0xFFFFFFFF load_0000FFFF: -MOV R0, 0xFFFF +MOV R11, 0xFFFF load_00000020: -MOV R0, 32 +MOV R12, 32 load_00042000: MOV R0, 0x00042000 - +NOP success: WORD 0xFFFFFFFF diff --git a/tests/0010-load-imm.s.gold b/tests/0010-load-imm.s.gold @@ -1,11 +1,12 @@ -PC> 00000000 I> 00000000 R> xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000004 I> 1e000000 R> xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000008 I> 1f00f000 R> 00000000 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx -PC> 0000000c I> 1f001234 R> f0000000 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000010 I> 10005678 R> 12340000 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000014 I> 1e00ffff R> 12345678 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000018 I> 1b00ffff R> ffffffff xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx -PC> 0000001c I> 1e000020 R> 0000ffff xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000020 I> 1f000004 R> 00000020 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000024 I> 10002000 R> 00040000 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000000 I> 00000000 R> xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000004 I> 10f10000 R> xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000008 I> 1df0f000 R> xxxxxxxx 00000000 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 0000000c I> 1df21234 R> f0000000 00000000 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000010 I> 1c225678 R> f0000000 00000000 12340000 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000014 I> 10f3ffff R> f0000000 00000000 12345678 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000018 I> 1cfbffff R> f0000000 00000000 12345678 ffffffff xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 0000001c I> 10fc0020 R> f0000000 00000000 12345678 ffffffff 0000ffff xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000020 I> 1df00004 R> f0000000 00000000 12345678 ffffffff 0000ffff 00000020 xxxxxxxx xxxxxxxx +PC> 00000024 I> 1c002000 R> 00040000 00000000 12345678 ffffffff 0000ffff 00000020 xxxxxxxx xxxxxxxx +PC> 00000028 I> 00000000 R> 00042000 00000000 12345678 ffffffff 0000ffff 00000020 xxxxxxxx xxxxxxxx PC> EXIT diff --git a/tests/0020-counting.s b/tests/0020-counting.s @@ -1,6 +1,6 @@ MOV R0, 0 loop: ADD R0, R0, 1 -SEQ R1, R0, 10 -BZ R1, loop +SUB R1, R0, 10 +BNZ R1, loop WORD 0xffffffff diff --git a/tests/0020-counting.s.gold b/tests/0020-counting.s.gold @@ -1,32 +1,32 @@ -PC> 00000000 I> 1e000000 R> xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000004 I> 12000001 R> 00000000 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000008 I> 1801000a R> 00000001 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx -PC> 0000000c I> 4110fffe R> 00000001 00000000 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000004 I> 12000001 R> 00000001 00000000 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000008 I> 1801000a R> 00000002 00000000 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 0000000c I> 4110fffe R> 00000002 00000000 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000004 I> 12000001 R> 00000002 00000000 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000008 I> 1801000a R> 00000003 00000000 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 0000000c I> 4110fffe R> 00000003 00000000 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000004 I> 12000001 R> 00000003 00000000 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000008 I> 1801000a R> 00000004 00000000 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 0000000c I> 4110fffe R> 00000004 00000000 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000004 I> 12000001 R> 00000004 00000000 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000008 I> 1801000a R> 00000005 00000000 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 0000000c I> 4110fffe R> 00000005 00000000 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000004 I> 12000001 R> 00000005 00000000 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000008 I> 1801000a R> 00000006 00000000 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 0000000c I> 4110fffe R> 00000006 00000000 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000004 I> 12000001 R> 00000006 00000000 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000008 I> 1801000a R> 00000007 00000000 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 0000000c I> 4110fffe R> 00000007 00000000 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000004 I> 12000001 R> 00000007 00000000 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000008 I> 1801000a R> 00000008 00000000 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 0000000c I> 4110fffe R> 00000008 00000000 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000004 I> 12000001 R> 00000008 00000000 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000008 I> 1801000a R> 00000009 00000000 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 0000000c I> 4110fffe R> 00000009 00000000 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000004 I> 12000001 R> 00000009 00000000 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000008 I> 1801000a R> 0000000a 00000000 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 0000000c I> 4110fffe R> 0000000a 00000001 xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000000 I> 10f00000 R> xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000004 I> 12000001 R> 00000000 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000008 I> 1301000a R> 00000001 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 0000000c I> 481ffffe R> 00000001 fffffff7 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000004 I> 12000001 R> 00000001 fffffff7 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000008 I> 1301000a R> 00000002 fffffff7 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 0000000c I> 481ffffe R> 00000002 fffffff8 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000004 I> 12000001 R> 00000002 fffffff8 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000008 I> 1301000a R> 00000003 fffffff8 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 0000000c I> 481ffffe R> 00000003 fffffff9 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000004 I> 12000001 R> 00000003 fffffff9 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000008 I> 1301000a R> 00000004 fffffff9 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 0000000c I> 481ffffe R> 00000004 fffffffa xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000004 I> 12000001 R> 00000004 fffffffa xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000008 I> 1301000a R> 00000005 fffffffa xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 0000000c I> 481ffffe R> 00000005 fffffffb xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000004 I> 12000001 R> 00000005 fffffffb xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000008 I> 1301000a R> 00000006 fffffffb xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 0000000c I> 481ffffe R> 00000006 fffffffc xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000004 I> 12000001 R> 00000006 fffffffc xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000008 I> 1301000a R> 00000007 fffffffc xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 0000000c I> 481ffffe R> 00000007 fffffffd xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000004 I> 12000001 R> 00000007 fffffffd xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000008 I> 1301000a R> 00000008 fffffffd xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 0000000c I> 481ffffe R> 00000008 fffffffe xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000004 I> 12000001 R> 00000008 fffffffe xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000008 I> 1301000a R> 00000009 fffffffe xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 0000000c I> 481ffffe R> 00000009 ffffffff xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000004 I> 12000001 R> 00000009 ffffffff xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000008 I> 1301000a R> 0000000a ffffffff xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 0000000c I> 481ffffe R> 0000000a 00000000 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx PC> EXIT diff --git a/tests/0030-ram.s b/tests/0030-ram.s @@ -2,7 +2,7 @@ MOV R1, 0x74 SW R0, [R1] MOV R2, 0x77777777 - LW R14, [R1] - ADD R15, R14, R0 + LW R3, [R1] + ADD R11, R3, R0 NOP WORD 0xFFFFFFFF diff --git a/tests/0030-ram.s.gold b/tests/0030-ram.s.gold @@ -1,10 +1,10 @@ -PC> 00000000 I> 1f001122 R> xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000004 I> 10003344 R> 11220000 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000008 I> 1e010074 R> 11223344 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx -PC> 0000000c I> 30100000 R> 11223344 00000074 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000010 I> 1f027777 R> 11223344 00000074 xxxxxxxx xxxxxxxx xxxxxxxx -PC> 00000014 I> 10227777 R> 11223344 00000074 77770000 xxxxxxxx xxxxxxxx -PC> 00000018 I> 201e0000 R> 11223344 00000074 77777777 xxxxxxxx xxxxxxxx -PC> 0000001c I> 02e0f000 R> 11223344 00000074 77777777 11223344 xxxxxxxx -PC> 00000020 I> 00000000 R> 11223344 00000074 77777777 11223344 22446688 +PC> 00000000 I> 1df01122 R> xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000004 I> 1c003344 R> 11220000 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000008 I> 10f10074 R> 11223344 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 0000000c I> 32100000 R> 11223344 00000074 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000010 I> 1df27777 R> 11223344 00000074 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000014 I> 1c227777 R> 11223344 00000074 77770000 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000018 I> 22130000 R> 11223344 00000074 77777777 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 0000001c I> 0230b000 R> 11223344 00000074 77777777 11223344 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx +PC> 00000020 I> 00000000 R> 11223344 00000074 77777777 11223344 22446688 xxxxxxxx xxxxxxxx xxxxxxxx PC> EXIT diff --git a/verilog/alu.v b/verilog/alu.v @@ -2,6 +2,8 @@ // // Copyright 2012, Brian Swetland. Use at your own risk. +`timescale 1ns/1ns + module alu ( input [3:0] opcode, input [31:0] left, @@ -10,10 +12,7 @@ module alu ( ); wire [31:0] rbit; -wire S; - assign rbit = (1 << right[4:0]); -assign S = right[15]; always @ (*) case (opcode) @@ -24,14 +23,14 @@ always @ (*) 4'b0100: out <= (left << right[4:0]); 4'b0101: out <= (left >> right[4:0]); 4'b0110: out <= (left ^ right); - 4'b0111: out <= (left & rbit) ? 1 : 0; - 4'b1000: out <= (left == right) ? 1 : 0; - 4'b1001: out <= (left < right) ? 1 : 0; - 4'b1010: out <= (left > right) ? 1 : 0; - 4'b1011: out <= right; - 4'b1100: out <= (left | rbit); - 4'b1101: out <= (left & ~rbit); - 4'b1110: out <= { S,S,S,S,S,S,S,S,S,S,S,S,S,S,S,S,right[15:0] }; - 4'b1111: out <= { right[15:0], 16'h0 }; + 4'b0111: out <= (left & rbit); + 4'b1000: out <= (left | rbit); + 4'b1001: out <= (left & ~rbit); + 4'b1010: out <= (left < right) ? 1 : 0; + 4'b1011: out <= (left > right) ? 1 : 0; + 4'b1100: out <= { left[31:16], right[15:0] }; + 4'b1101: out <= { right[15:0], left[31:16] }; + 4'b1110: out <= (left >>> right[4:0]); + 4'b1111: out <= (left * right); endcase endmodule diff --git a/verilog/control.v b/verilog/control.v @@ -1,97 +1,45 @@ // Copyright 2012, Brian Swetland. Use at your own risk. -`define PC_SRC_NEXT 2'b00 // normal -`define PC_SRC_B_IMM 2'b01 // on immediate branches -`define PC_SRC_B_REG 2'b10 // on indirect branches -`define PC_SRC_X 2'b11 // unspecified - -`define W_SRC_ALU 2'b00 // normal -`define W_SRC_RAM 2'b01 // on ram read ops -`define W_SRC_PC_NEXT 2'b10 // on branch link ops -`define W_SRC_X 2'b11 // unspecified - +`timescale 1ns/1ns module control ( input [3:0] opcode, input [3:0] opfunc, - input ctl_adata_zero, - output ctl_regs_we, - output ctl_ram_we, - output ctl_ram_rd, - output ctl_d_or_b, - output ctl_imm16, - output reg [1:0] ctl_pc_src, - output reg [1:0] ctl_wdata_src, - output [3:0] ctl_alu_func - ); + input ctl_adata_zero, // 1=(adata==0) -reg ctl_branch; + output ctl_alu_pc, // 0=adata, 1=pc+4 -> alu.left + output ctl_alu_imm, // 0=bdata, 1=signed_imm16 + output ctl_regs_we, // 1=write to reg file + output ctl_ram_we, // 1=write to ram + output ctl_alu_altdest, // 0=alu.daddr=opd, 1=alu.daddr=opb + output [1:0] ctl_wdata_src, // 00=alu,01=ram,10=pc+4,11=0 + + output ctl_branch_ind, // 0=relative branch, 1=indirect branch + output ctl_branch_taken // 0=pc=pc+4, 1=pc=branch_to + ); wire ctl_branch_op; -wire ctl_branch_ind; -wire ctl_ram_op; -wire ctl_regs_we_; +wire ctl_branch_nz; reg [7:0] control; always @ (*) case (opcode) - 4'b0000: control = 8'b01000000; // ALU Rd, Ra, Rb - 4'b0001: control = 8'b01001100; // ALU Rd, Ra, #I - 4'b0010: control = 8'b01101100; // LW Rd, [Ra, #] - 4'b0011: control = 8'b00010100; // SW Rd, [Ra, #] - 4'b0100: control = 8'b10001100; // B* rel16 - 4'b0101: control = 8'b10000100; // B* Rb - 4'b0110: control = 8'b00000000; - 4'b0111: control = 8'b00000000; - 4'b1000: control = 8'b00000000; - 4'b1001: control = 8'b00000000; - 4'b1010: control = 8'b00000000; - 4'b1011: control = 8'b00000000; - 4'b1100: control = 8'b00000000; - 4'b1101: control = 8'b00000000; - 4'b1110: control = 8'b00000000; - 4'b1111: control = 8'b00000000; - endcase - -assign { ctl_branch_op, ctl_regs_we_, ctl_ram_rd, ctl_ram_we, ctl_d_or_b, ctl_imm16 } = control[7:2]; - -wire ctl_cond_z; -wire ctl_cond_nz; -wire ctl_link_bit; - -assign ctl_cond_z = opfunc[0]; -assign ctl_cond_nz = opfunc[1]; -assign ctl_link_bit = opfunc[3]; -assign ctl_branch_ind = opcode[0]; - -always @ (*) - case ( { ctl_branch_op, ctl_cond_z, ctl_cond_nz, ctl_adata_zero } ) - 4'b1110: ctl_branch = 1'b1; - 4'b1111: ctl_branch = 1'b1; - 4'b1101: ctl_branch = 1'b1; - 4'b1010: ctl_branch = 1'b1; - default: ctl_branch = 1'b0; - endcase - -always @ (*) - case ( { ctl_branch, ctl_branch_ind } ) - 2'b00: ctl_pc_src = `PC_SRC_NEXT; - 2'b01: ctl_pc_src = `PC_SRC_NEXT; - 2'b10: ctl_pc_src = `PC_SRC_B_IMM; - 2'b11: ctl_pc_src = `PC_SRC_B_REG; - endcase - -always @ (*) - case ( { ctl_branch, ctl_ram_rd } ) - 2'b00: ctl_wdata_src = `W_SRC_ALU; - 2'b01: ctl_wdata_src = `W_SRC_RAM; - 2'b10: ctl_wdata_src = `W_SRC_PC_NEXT; - 2'b11: ctl_wdata_src = `W_SRC_PC_NEXT; + 4'b0000: control = 8'b00100000; // ALU Rd, Ra, Rb + 4'b0001: control = 8'b01101000; // ALU Rd, Ra, #I + 4'b0010: control = 8'b01101001; // LW Rd, [Ra, #I] + 4'b0011: control = 8'b01010000; // SW Rd, [Ra, #I] + 4'b0100: control = 8'b10101110; // B rel16 + default: control = 8'b00000000; endcase -assign ctl_alu_func = (ctl_ram_rd | ctl_ram_we) ? 4'b0010 : opfunc; +assign { + ctl_alu_pc, ctl_alu_imm, ctl_regs_we, ctl_ram_we, + ctl_alu_altdest, ctl_branch_op, ctl_wdata_src + } = control[7:0]; -assign ctl_regs_we = ctl_regs_we_ | (ctl_branch & ctl_link_bit); +assign ctl_branch_nz = opfunc[3]; +assign ctl_branch_ind = opfunc[2]; +assign ctl_branch_taken = (ctl_branch_op & (ctl_adata_zero != ctl_branch_nz)); endmodule diff --git a/verilog/cpu32.v b/verilog/cpu32.v @@ -2,6 +2,8 @@ // // Copyright 2012, Brian Swetland. Use at your own risk. +`timescale 1ns/1ns + module cpu32 ( input clk, input reset, @@ -30,28 +32,32 @@ assign opselb = ir[19:16]; assign opseld = ir[15:12]; assign opimm16 = ir[15:0]; -wire ctl_regs_we; // 1 = write back to register file -wire ctl_d_or_b; // 0 = write to R[opseld], 1 = R[opselb] -wire ctl_imm16; // 0 = bdata, 1 = imm16 -> alu right -wire [3:0] ctl_alu_func; -wire ctl_ram_we; -wire ctl_ram_rd; +wire [31:0] opimm16s; +assign opimm16s[31:0] = { {16{opimm16[15]}} , opimm16[15:0] }; +wire ctl_alu_pc; +wire ctl_alu_imm; +wire ctl_regs_we; +wire ctl_ram_we; +wire ctl_alu_altdest; wire [1:0] ctl_wdata_src; -wire [1:0] ctl_pc_src; +wire ctl_branch_ind; +wire ctl_branch_taken; control control( .opcode(opcode), .opfunc(opfunc), .ctl_adata_zero(ctl_adata_zero), + + .ctl_alu_pc(ctl_alu_pc), + .ctl_alu_imm(ctl_alu_imm), .ctl_regs_we(ctl_regs_we), - .ctl_d_or_b(ctl_d_or_b), - .ctl_pc_src(ctl_pc_src), - .ctl_wdata_src(ctl_wdata_src), - .ctl_imm16(ctl_imm16), .ctl_ram_we(ctl_ram_we), - .ctl_ram_rd(ctl_ram_rd), - .ctl_alu_func(ctl_alu_func) + .ctl_alu_altdest(ctl_alu_altdest), + .ctl_wdata_src(ctl_wdata_src), + + .ctl_branch_ind(ctl_branch_ind), + .ctl_branch_taken(ctl_branch_taken) ); wire ctl_adata_zero; @@ -65,7 +71,8 @@ register #(32) PC ( .dout(pc) ); -regfile #(32,4) REGS ( +regfile REGS ( + .reset(reset), .clk(clk), .we(ctl_regs_we), .wsel(alu_wsel), .wdata(wdata), @@ -73,7 +80,7 @@ regfile #(32,4) REGS ( .bsel(opselb), .bdata(bdata) ); -mux4 #(32) wdata_mux( +mux4 #(32) mux_wdata_src( .sel(ctl_wdata_src), .in0(result), .in1(d_data_r), @@ -84,40 +91,51 @@ mux4 #(32) wdata_mux( assign pc_plus_4 = (pc + 32'h4); -wire S; -assign S = opimm16[15]; +wire [31:0] branch_to; +mux2 #(32) mux_branch_to( + .sel(ctl_branch_ind), + .in0(pc + { opimm16s[29:0], 2'b00 } ), + .in1(bdata), + .out(branch_to) + ); -mux4 #(32) pc_source( - .sel(ctl_pc_src), +mux2 #(32) mux_pc_source( + .sel(ctl_branch_taken), .in0(pc_plus_4), - .in1(pc + {S,S,S,S,S,S,S,S,S,S,S,S,S,S,opimm16,2'h0} ), - .in2(bdata), - .in3(bdata), + .in1(branch_to), .out(next_pc) ); assign i_addr = pc; assign ir = i_data; +wire [31:0] ainput; wire [31:0] binput; -mux2 #(32) alu_right_mux( - .sel(ctl_imm16), +mux2 #(32) mux_alu_left( + .sel(ctl_alu_pc), + .in0(adata), + .in1(pc_plus_4), + .out(ainput) + ); + +mux2 #(32) mux_alu_right( + .sel(ctl_alu_imm), .in0(bdata), - .in1({ 16'h0, opimm16 }), + .in1(opimm16s), .out(binput) ); mux2 #(4) alu_wsel_mux( - .sel(ctl_d_or_b), + .sel(ctl_alu_altdest), .in0(opseld), .in1(opselb), .out(alu_wsel) ); alu alu( - .opcode(ctl_alu_func), - .left(adata), + .opcode(opfunc), + .left(ainput), .right(binput), .out(result) ); diff --git a/verilog/library.v b/verilog/library.v @@ -2,6 +2,8 @@ // // Copyright 2009, Brian Swetland. Use at your own risk. +`timescale 1ns/1ns + module decoder2 ( input [1:0] in, output out0, out1, out2, out3 diff --git a/verilog/ram.v b/verilog/ram.v @@ -2,6 +2,8 @@ // // Copyright 2009, Brian Swetland. Use at your own risk. +`timescale 1ns/1ns + module ram #(parameter DWIDTH=16, parameter AWIDTH=3) ( input clk, input we, input [AWIDTH-1:0] addr, diff --git a/verilog/regfile.v b/verilog/regfile.v @@ -2,18 +2,29 @@ // // Copyright 2009, Brian Swetland. Use at your own risk. -module regfile #(parameter DWIDTH=16, parameter AWIDTH=3) ( +`timescale 1ns/1ns + +module regfile ( + input reset, input clk, input we, - input [AWIDTH-1:0] wsel, input [DWIDTH-1:0] wdata, - input [AWIDTH-1:0] asel, output [DWIDTH-1:0] adata, - input [AWIDTH-1:0] bsel, output [DWIDTH-1:0] bdata + input [3:0] wsel, input [31:0] wdata, + input [3:0] asel, output [31:0] adata, + input [3:0] bsel, output [31:0] bdata ); -reg [DWIDTH-1:0] R[0:2**AWIDTH-1]; +reg [31:0] R[0:15]; + +initial + R[4'b1111] = 32'b0; -always @ (posedge clk) +always @ (posedge clk) begin if (we) - R[wsel] <= wdata; + case(wsel) + 4'b1111: ; + default: R[wsel] <= wdata; + endcase +// R[4'b1111] <= 32'b0; +end assign adata = R[asel]; assign bdata = R[bsel]; diff --git a/verilog/rom.v b/verilog/rom.v @@ -5,7 +5,6 @@ `timescale 1ns/1ns module rom #(parameter DWIDTH=16, parameter AWIDTH=8) ( - input clk, input [AWIDTH-1:0] addr, output [DWIDTH-1:0] data ); diff --git a/verilog/testbench.v b/verilog/testbench.v @@ -10,29 +10,21 @@ reg clk, reset; wire [31:0] romaddr, romdata, ramaddr, ramrdata, ramwdata; wire ramwe; -initial - begin - reset = 0; - #15 - reset = 1; - #20 - reset = 0; +initial begin + clk = 0; + reset = 0; +// #1 reset = 1; +// #4 reset = 0; end always - begin - clk = 0; - #10 ; - clk = 1; - #10 ; - end + #10 clk = ~clk; wire [7:0] urdata; cpu32 cpu( .clk(clk), - .reset(0), -// .reset(reset), + .reset(reset), .i_addr(romaddr), .i_data(romdata), .d_data_r(ramrdata), @@ -80,7 +72,7 @@ initial begin $dumpvars(0,testbench); end -initial #1000 $finish; +initial #10000 $finish; always @(posedge clk) begin @@ -92,13 +84,16 @@ always @(posedge clk) begin $display("PC> ERROR"); $finish(); end - $display("PC> %h I> %h R> %h %h %h %h %h", + $display("PC> %h I> %h R> %h %h %h %h %h %h %h %h", cpu.pc, cpu.ir, cpu.REGS.R[0], cpu.REGS.R[1], cpu.REGS.R[2], - cpu.REGS.R[14], - cpu.REGS.R[15] + cpu.REGS.R[3], + cpu.REGS.R[11], + cpu.REGS.R[12], + cpu.REGS.R[13], + cpu.REGS.R[14] ); end