diff options
| -rwxr-xr-x | asm.rb | 31 | ||||
| -rw-r--r-- | hdl/top.sv | 65 | ||||
| -rw-r--r-- | mem/mem.hex | 154 |
3 files changed, 133 insertions, 117 deletions
| @@ -2,20 +2,17 @@ | |||
| 2 | 2 | ||
| 3 | OPCODES = { | 3 | OPCODES = { |
| 4 | "i" => 0x080, | 4 | "i" => 0x080, |
| 5 | "acc=" => 0x000, | 5 | "acc=" => 0x100, |
| 6 | "ladd" => 0x100, | 6 | "ladd" => 0x200, |
| 7 | "store" => 0x200, | 7 | "store" => 0x300, |
| 8 | "ifeq" => 0x300, | 8 | "ifeq" => 0x400, |
| 9 | "jmp" => 0x400, | 9 | "jmp" => 0x500, |
| 10 | "ascii" => 0x500, | 10 | "ascii" => 0x600, |
| 11 | "++acc" => 0xf01, | 11 | "cla" => 0x001, |
| 12 | "--acc" => 0xf02, | 12 | "++acc" => 0x002, |
| 13 | "++idx" => 0xf04, | 13 | "--acc" => 0x004, |
| 14 | "--idx" => 0xf08, | 14 | "tx" => 0x040, |
| 15 | "swap" => 0xf10, | 15 | "halt" => 0x080, |
| 16 | "idx" => 0xf20, | ||
| 17 | "tx" => 0xf40, | ||
| 18 | "halt" => 0xf80, | ||
| 19 | } | 16 | } |
| 20 | 17 | ||
| 21 | Line = Struct.new(:opcode, :refs, :code) | 18 | Line = Struct.new(:opcode, :refs, :code) |
| @@ -56,9 +53,11 @@ end | |||
| 56 | $code.each_with_index() do | line, i | | 53 | $code.each_with_index() do | line, i | |
| 57 | op = line.opcode | 54 | op = line.opcode |
| 58 | line.refs.each() do | ref | | 55 | line.refs.each() do | ref | |
| 59 | if $labels.key?(ref) | 56 | if ref =~ /^@(.+)$/ and $labels.key?($1) |
| 57 | op |= $labels[$1] | ||
| 58 | elsif $labels.key?(ref) | ||
| 60 | target = $labels[ref] - (i + 1) | 59 | target = $labels[ref] - (i + 1) |
| 61 | target += 0x100 if target < 0 | 60 | target += 0x80 if target < 0 |
| 62 | op |= target | 61 | op |= target |
| 63 | else | 62 | else |
| 64 | throw "I don't understand #{ref.inspect()}" | 63 | throw "I don't understand #{ref.inspect()}" |
| @@ -68,7 +68,6 @@ bit [DATA_BITS-1:0] pc; | |||
| 68 | bit [3:0] opcode; | 68 | bit [3:0] opcode; |
| 69 | bit [7:0] operand; | 69 | bit [7:0] operand; |
| 70 | bit [DATA_BITS-1:0] acc; | 70 | bit [DATA_BITS-1:0] acc; |
| 71 | bit [DATA_BITS-1:0] idx; | ||
| 72 | 71 | ||
| 73 | bit [ADDR_BITS-1:0] address; | 72 | bit [ADDR_BITS-1:0] address; |
| 74 | bit [DATA_BITS-1:0] sign_extended_operand; | 73 | bit [DATA_BITS-1:0] sign_extended_operand; |
| @@ -91,10 +90,9 @@ always_ff @(posedge clk) begin | |||
| 91 | tx_data = 0; | 90 | tx_data = 0; |
| 92 | pc = 0; | 91 | pc = 0; |
| 93 | acc = 0; | 92 | acc = 0; |
| 94 | idx = 0; | ||
| 95 | state = state.first; | 93 | state = state.first; |
| 96 | end else begin | 94 | end else begin |
| 97 | `ifdef DEBUG $display("s=%0d pc=%x (acc=%x idx=%x) (mem %b:%x)", state, pc, acc, idx, `mem_read_valid, `mem_read_data); `endif | 95 | `ifdef DEBUG $display("s=%0d pc=%x (acc=%x) (mem %b:%x)", state, pc, acc, `mem_read_valid, `mem_read_data); `endif |
| 98 | if (`tx_ready) tx_valid = 0; | 96 | if (`tx_ready) tx_valid = 0; |
| 99 | 97 | ||
| 100 | case (state) | 98 | case (state) |
| @@ -118,29 +116,33 @@ always_ff @(posedge clk) begin | |||
| 118 | sign_extended_operand = {{(DATA_BITS-8){operand[7]}}, operand}; | 116 | sign_extended_operand = {{(DATA_BITS-8){operand[7]}}, operand}; |
| 119 | `ifdef DEBUG $display("\tdecode %x:%x", opcode, operand); `endif | 117 | `ifdef DEBUG $display("\tdecode %x:%x", opcode, operand); `endif |
| 120 | case (opcode) | 118 | case (opcode) |
| 121 | 'h0: acc = sign_extended_operand; | 119 | 'h0: begin |
| 122 | 'h1, 'h2: begin | 120 | if (operand[0]) acc = 0; |
| 121 | if (operand[1]) ++acc; | ||
| 122 | if (operand[2]) --acc; | ||
| 123 | if (operand[6]) state = MEMORY; | ||
| 124 | if (operand[7]) state = HALT; | ||
| 125 | end | ||
| 126 | 'h1: acc = sign_extended_operand; | ||
| 127 | 'h2, 'h3: begin | ||
| 123 | address = {7'b0, operand[6:0]}; | 128 | address = {7'b0, operand[6:0]}; |
| 124 | state = operand[7] ? INDIRECT : AGEN; | 129 | state = operand[7] ? INDIRECT : AGEN; |
| 125 | end | 130 | end |
| 126 | 'h3: if (acc != sign_extended_operand) ++pc; | 131 | 'h4: if (acc != sign_extended_operand) ++pc; |
| 127 | 'h4: pc = pc + sign_extended_operand; | ||
| 128 | 'h5: begin | 132 | 'h5: begin |
| 133 | if (operand[7]) begin | ||
| 134 | address = {7'b0, operand[6:0]}; | ||
| 135 | state = INDIRECT; | ||
| 136 | end else begin | ||
| 137 | pc = pc + {{(ADDR_BITS-7){operand[6]}}, operand[6:0]}; | ||
| 138 | end | ||
| 139 | end | ||
| 140 | 'h6: begin | ||
| 129 | mem_write_data = acc % 10 + 'h30; | 141 | mem_write_data = acc % 10 + 'h30; |
| 130 | acc = acc / 10; | 142 | acc = acc / 10; |
| 131 | address = {7'b0, operand[6:0]}; | 143 | address = {7'b0, operand[6:0]}; |
| 132 | state = operand[7] ? INDIRECT : AGEN; | 144 | state = operand[7] ? INDIRECT : AGEN; |
| 133 | end | 145 | end |
| 134 | 'hf: begin | ||
| 135 | if (operand[0]) ++acc; | ||
| 136 | if (operand[1]) --acc; | ||
| 137 | if (operand[2]) ++idx; | ||
| 138 | if (operand[3]) --idx; | ||
| 139 | if (operand[4]) {idx, acc} = {acc, idx}; | ||
| 140 | if (operand[5]) idx = acc; | ||
| 141 | if (operand[6]) state = MEMORY; | ||
| 142 | if (operand[7]) state = HALT; | ||
| 143 | end | ||
| 144 | endcase | 146 | endcase |
| 145 | end | 147 | end |
| 146 | end | 148 | end |
| @@ -169,21 +171,22 @@ always_ff @(posedge clk) begin | |||
| 169 | state = FETCH; | 171 | state = FETCH; |
| 170 | `ifdef DEBUG $display("\tagen"); `endif | 172 | `ifdef DEBUG $display("\tagen"); `endif |
| 171 | case (opcode) | 173 | case (opcode) |
| 172 | 'h1: begin | 174 | 'h2: begin |
| 173 | mem_valid = 1; | 175 | mem_valid = 1; |
| 174 | mem_address = address + idx; | 176 | mem_address = address; |
| 175 | state = `mem_ready ? MEMORY : AGEN; | 177 | state = `mem_ready ? MEMORY : AGEN; |
| 176 | end | 178 | end |
| 177 | 'h2: begin | 179 | 'h3: begin |
| 178 | mem_valid = 1; | 180 | mem_valid = 1; |
| 179 | mem_address = address + idx; | 181 | mem_address = address; |
| 180 | mem_write = 1; | 182 | mem_write = 1; |
| 181 | mem_write_data = acc; | 183 | mem_write_data = acc; |
| 182 | state = `mem_ready ? FETCH : AGEN; | 184 | state = `mem_ready ? FETCH : AGEN; |
| 183 | end | 185 | end |
| 184 | 'h5: begin | 186 | 'h5: pc = address; |
| 187 | 'h6: begin | ||
| 185 | mem_valid = 1; | 188 | mem_valid = 1; |
| 186 | mem_address = address + idx; | 189 | mem_address = address; |
| 187 | mem_write = 1; | 190 | mem_write = 1; |
| 188 | state = `mem_ready ? FETCH : AGEN; | 191 | state = `mem_ready ? FETCH : AGEN; |
| 189 | end | 192 | end |
| @@ -198,14 +201,7 @@ always_ff @(posedge clk) begin | |||
| 198 | state = FETCH; | 201 | state = FETCH; |
| 199 | `ifdef DEBUG $display("\tstall"); `endif | 202 | `ifdef DEBUG $display("\tstall"); `endif |
| 200 | case (opcode) | 203 | case (opcode) |
| 201 | 'h1: begin | 204 | 'h0: begin |
| 202 | if (`mem_read_valid) begin | ||
| 203 | acc = acc + `mem_read_data; | ||
| 204 | end else begin | ||
| 205 | state = MEMORY; | ||
| 206 | end | ||
| 207 | end | ||
| 208 | 'hf: begin | ||
| 209 | if (operand[6]) begin | 205 | if (operand[6]) begin |
| 210 | if (tx_valid) begin | 206 | if (tx_valid) begin |
| 211 | state = MEMORY; | 207 | state = MEMORY; |
| @@ -215,6 +211,13 @@ always_ff @(posedge clk) begin | |||
| 215 | end | 211 | end |
| 216 | end | 212 | end |
| 217 | end | 213 | end |
| 214 | 'h2: begin | ||
| 215 | if (`mem_read_valid) begin | ||
| 216 | acc = acc + `mem_read_data; | ||
| 217 | end else begin | ||
| 218 | state = MEMORY; | ||
| 219 | end | ||
| 220 | end | ||
| 218 | endcase | 221 | endcase |
| 219 | end | 222 | end |
| 220 | 223 | ||
diff --git a/mem/mem.hex b/mem/mem.hex index 07023a8..4d5700f 100644 --- a/mem/mem.hex +++ b/mem/mem.hex | |||
| @@ -1,76 +1,90 @@ | |||
| 1 | @0 | 1 | @0 |
| 2 | 2 | ||
| 3 | // Reset state is acc=0 idx=0 | 3 | 10d // acc= @fib # for the toy indirect jump to fib |
| 4 | 369 // store 0x69 | ||
| 5 | 170 // acc= 0x70 | ||
| 6 | 36a // store 0x6a | ||
| 7 | 001 // loop: cla | ||
| 8 | 2ea // ladd i 0x6a | ||
| 9 | 400 // ifeq 0 | ||
| 10 | 5e9 // jmp i 0x69 # toy indirect jump to fib | ||
| 11 | 040 // tx | ||
| 12 | 003 // cla ++acc | ||
| 13 | 26a // ladd 0x6a | ||
| 14 | 36a // store 0x6a | ||
| 15 | 577 // jmp loop | ||
| 16 | 36a // fib: store 0x6a # zero, it is known | ||
| 17 | 370 // store 0x70 # 0x70 is now beginning of Fibonacci sequence (0) | ||
| 18 | 003 // cla ++acc | ||
| 19 | 371 // store 0x71 # 0x71 is 1 | ||
| 20 | 170 // fibloop: acc= 0x70 | ||
| 21 | 26a // ladd 0x6a | ||
| 22 | 369 // store 0x69 | ||
| 23 | 001 // cla | ||
| 24 | 2e9 // ladd i 0x69 # next fib number to print | ||
| 25 | 66b // ascii 0x6b # LSB of ASCII rep | ||
| 26 | 66c // ascii 0x6c | ||
| 27 | 66d // ascii 0x6d | ||
| 28 | 66e // ascii 0x6e # MSB of ASCII rep | ||
| 29 | 104 // acc= 4 | ||
| 30 | 369 // store 0x69 | ||
| 31 | 005 // scan: cla --acc | ||
| 32 | 269 // ladd 0x69 | ||
| 33 | 4ff // ifeq -1 | ||
| 34 | 508 // jmp print | ||
| 35 | 369 // store 0x69 | ||
| 36 | 16b // acc= 0x6b | ||
| 37 | 269 // ladd 0x69 | ||
| 38 | 368 // store 0x68 | ||
| 39 | 001 // cla | ||
| 40 | 2e8 // ladd i 0x68 | ||
| 41 | 430 // ifeq 0x30 | ||
| 42 | 574 // jmp scan | ||
| 43 | 16b // print: acc= 0x6b | ||
| 44 | 269 // ladd 0x69 | ||
| 45 | 368 // store 0x68 | ||
| 46 | 001 // cla | ||
| 47 | 2e8 // ladd i 0x68 | ||
| 48 | 040 // tx | ||
| 49 | 005 // cla --acc | ||
| 50 | 269 // ladd 0x69 | ||
| 51 | 4ff // ifeq -1 | ||
| 52 | 502 // jmp space | ||
| 53 | 369 // store 0x69 | ||
| 54 | 574 // jmp print | ||
| 55 | 120 // space: acc= 0x20 | ||
| 56 | 040 // tx | ||
| 57 | 170 // acc= 0x70 | ||
| 58 | 26a // ladd 0x6a | ||
| 59 | 369 // store 0x69 | ||
| 60 | 003 // cla ++acc | ||
| 61 | 269 // ladd 0x69 # compute &fib[i+1] | ||
| 62 | 368 // store 0x68 | ||
| 63 | 003 // cla ++acc | ||
| 64 | 268 // ladd 0x68 # compute &fib[i+2] | ||
| 65 | 367 // store 0x67 | ||
| 66 | 001 // cla | ||
| 67 | 2e9 // ladd i 0x69 | ||
| 68 | 2e8 // ladd i 0x68 # compute fib[i+2] | ||
| 69 | 3e7 // store i 0x67 # store it | ||
| 70 | 003 // cla ++acc | ||
| 71 | 26a // ladd 0x6a | ||
| 72 | 432 // ifeq 50 | ||
| 73 | 502 // jmp fullydone | ||
| 74 | 36a // store 0x6a | ||
| 75 | 548 // jmp fibloop | ||
| 76 | 121 // fullydone: acc= 0x21 | ||
| 77 | 040 // tx | ||
| 78 | 080 // halt | ||
| 4 | 79 | ||
| 5 | 000 // loop: acc= 0 # Print from 0x70 until we find a 0x00 byte | 80 | // 67: scratch (pointer to fib[i+2]) |
| 6 | 170 // ladd i 0x6a | 81 | // 68: scratch (pointer to fib[i+1]) |
| 7 | 300 // ifeq 0 | 82 | // 69: scratch (pointer to fib[i]) (j) |
| 8 | 402 // jmp fib | 83 | // 6a: i |
| 9 | f44 // ++idx tx | 84 | // 6b: LSB of ASCII rep |
| 10 | 4fa // jmp loop | 85 | // 6c: USB of ASCII rep |
| 11 | f20 // fib: idx # N.B. acc is 0 at this point (we got here from ifeq 0) | 86 | // 6d: USB of ASCII rep |
| 12 | 270 // store 0x70 # 0x70 is now beginning of Fibonacci sequence (0) | 87 | // 6e: MSB of ASCII rep |
| 13 | 001 // acc= 1 | ||
| 14 | 271 // store 0x71 # 0x71 is 1 | ||
| 15 | 000 // fibloop: acc= 0 | ||
| 16 | f10 // swap | ||
| 17 | 332 // ifeq 50 | ||
| 18 | 42b // jmp fullydone | ||
| 19 | 26f // store 0x6f # 0x6f is current index into Fibonacci sequence | ||
| 20 | f10 // swap | ||
| 21 | 170 // ladd 0x70 # Load next unprinted number in Fibonacci sequence | ||
| 22 | f10 // swap | ||
| 23 | 000 // acc= 0 | ||
| 24 | f10 // swap | ||
| 25 | 56b // ascii 0x6b # LSB of ASCII rep | ||
| 26 | 56c // ascii 0x6c | ||
| 27 | 56d // ascii 0x6d | ||
| 28 | 56e // ascii 0x6e # MSB of ASCII rep | ||
| 29 | 004 // acc= 4 | ||
| 30 | f10 // swap | ||
| 31 | f08 // scan: --idx | ||
| 32 | 000 // acc= 0 | ||
| 33 | 16b // ladd 0x6b | ||
| 34 | f10 // swap | ||
| 35 | 300 // ifeq 0 | ||
| 36 | 412 // jmp allzeroes | ||
| 37 | f10 // swap | ||
| 38 | 330 // ifeq 0x30 | ||
| 39 | 4f7 // jmp scan | ||
| 40 | f40 // done: tx | ||
| 41 | f10 // swap | ||
| 42 | 300 // ifeq 0 | ||
| 43 | 404 // jmp space | ||
| 44 | f12 // --acc swap | ||
| 45 | 000 // acc= 0 | ||
| 46 | 16b // ladd 0x6b | ||
| 47 | 4f8 // jmp done | ||
| 48 | 020 // space: acc= 0x20 | ||
| 49 | f40 // tx | ||
| 50 | 000 // acc= 0 | ||
| 51 | f20 // idx | ||
| 52 | 16f // ladd 0x6f | ||
| 53 | f10 // swap | ||
| 54 | 402 // jmp nextfib | ||
| 55 | f10 // allzeroes: swap | ||
| 56 | 4ef // jmp done | ||
| 57 | 170 // nextfib: ladd 0x70 # Load just-printed Fibonacci number | ||
| 58 | 171 // ladd 0x71 # Add about-to-print Fibonacci number | ||
| 59 | 272 // store 0x72 # Store n+2 Fibonacci number | ||
| 60 | f04 // ++idx | ||
| 61 | 4d1 // jmp fibloop | ||
| 62 | 021 // fullydone: acc= 0x21 | ||
| 63 | f40 // tx | ||
| 64 | f80 // halt | ||
| 65 | |||
| 66 | @6a | ||
| 67 | |||
| 68 | 070 // 6a: constant 0x070 | ||
| 69 | 000 // 6b: LSB of ASCII rep | ||
| 70 | 000 // 6c: USB of ASCII rep | ||
| 71 | 000 // 6d: USB of ASCII rep | ||
| 72 | 000 // 6e: MSB of ASCII rep | ||
| 73 | 000 // 6f: next index to store in memory image of Fibonacci sequence | ||
| 74 | 88 | ||
| 75 | @70 | 89 | @70 |
| 76 | 90 | ||
