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:
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