diff options
| author | Julian Blake Kongslie | 2021-04-18 17:02:12 -0700 |
|---|---|---|
| committer | Julian Blake Kongslie | 2021-04-18 17:02:12 -0700 |
| commit | e3e1938231ef16ace235f4d958e49913275dcbde (patch) | |
| tree | f4594cf98a6ebe666add8e079df35471a19dbf27 /hdl | |
| parent | Less noisy file format conversion. (diff) | |
| download | noncpu-e3e1938231ef16ace235f4d958e49913275dcbde.tar.xz | |
PDP-8 memory opcodes
Diffstat (limited to '')
| -rw-r--r-- | hdl/core.sv | 176 |
1 files changed, 92 insertions, 84 deletions
diff --git a/hdl/core.sv b/hdl/core.sv index 919dac9..83f4f01 100644 --- a/hdl/core.sv +++ b/hdl/core.sv | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | `include "util.svh" | 1 | `include "util.svh" |
| 2 | 2 | ||
| 3 | module core | 3 | module core |
| 4 | #( ADDR_BITS = 14 | 4 | #( ADDR_BITS = 12 |
| 5 | , DATA_BITS = 12 | 5 | , DATA_BITS = 12 |
| 6 | ) | 6 | ) |
| 7 | ( input bit clk | 7 | ( input bit clk |
| @@ -20,7 +20,7 @@ bit [DATA_BITS-1:0] mem_read_data; | |||
| 20 | mem | 20 | mem |
| 21 | #( .ADDR_BITS(ADDR_BITS) | 21 | #( .ADDR_BITS(ADDR_BITS) |
| 22 | , .DATA_BITS(DATA_BITS) | 22 | , .DATA_BITS(DATA_BITS) |
| 23 | , .INIT_FILE("mem/mem.hex") | 23 | , .INIT_FILE("build/mem/hello.hex") |
| 24 | ) | 24 | ) |
| 25 | memory | 25 | memory |
| 26 | ( .clk(clk) | 26 | ( .clk(clk) |
| @@ -59,21 +59,28 @@ jtag_uart | |||
| 59 | , .tx_data(tx_data) | 59 | , .tx_data(tx_data) |
| 60 | ); | 60 | ); |
| 61 | 61 | ||
| 62 | bit [ADDR_BITS-1:ADDR_BITS-6] page; | ||
| 63 | |||
| 62 | bit [ADDR_BITS-1:0] pc; | 64 | bit [ADDR_BITS-1:0] pc; |
| 63 | bit [3:0] opcode; | 65 | bit [2:0] opcode; |
| 64 | bit [7:0] operand; | 66 | bit [8:0] operand; |
| 65 | bit [DATA_BITS-1:0] acc; | 67 | bit [DATA_BITS-1:0] acc; |
| 68 | bit link; | ||
| 66 | 69 | ||
| 70 | bit i; | ||
| 71 | bit z; | ||
| 72 | bit [6:0] wip; | ||
| 67 | bit [ADDR_BITS-1:0] address; | 73 | bit [ADDR_BITS-1:0] address; |
| 68 | bit [DATA_BITS-1:0] sign_extended_operand; | ||
| 69 | 74 | ||
| 70 | enum | 75 | enum |
| 71 | { FETCH | 76 | { FETCH |
| 72 | , DECODE | 77 | , DECODE |
| 73 | , INDIRECT | 78 | , INDIRECT |
| 74 | , INDIRECTED | 79 | , INDIRECTED |
| 80 | , PREINC | ||
| 75 | , AGEN | 81 | , AGEN |
| 76 | , MEMORY | 82 | , EXEC |
| 83 | , STORE | ||
| 77 | , HALT | 84 | , HALT |
| 78 | } state; | 85 | } state; |
| 79 | 86 | ||
| @@ -83,8 +90,9 @@ always_ff @(posedge clk) begin | |||
| 83 | rx_ready = 0; | 90 | rx_ready = 0; |
| 84 | tx_valid = 0; | 91 | tx_valid = 0; |
| 85 | tx_data = 0; | 92 | tx_data = 0; |
| 86 | pc = 0; | 93 | pc = 'o200; |
| 87 | acc = 0; | 94 | acc = 0; |
| 95 | link = 0; | ||
| 88 | state = state.first; | 96 | state = state.first; |
| 89 | end else begin | 97 | end else begin |
| 90 | if (`lag(tx_ready)) tx_valid = 0; | 98 | if (`lag(tx_ready)) tx_valid = 0; |
| @@ -96,6 +104,7 @@ always_ff @(posedge clk) begin | |||
| 96 | mem_write = 0; | 104 | mem_write = 0; |
| 97 | if (`lag(mem_ready)) begin | 105 | if (`lag(mem_ready)) begin |
| 98 | state = DECODE; | 106 | state = DECODE; |
| 107 | page = pc[ADDR_BITS-1:ADDR_BITS-6]; | ||
| 99 | ++pc; | 108 | ++pc; |
| 100 | end | 109 | end |
| 101 | end | 110 | end |
| @@ -106,39 +115,21 @@ always_ff @(posedge clk) begin | |||
| 106 | if (`lag(mem_read_valid)) begin | 115 | if (`lag(mem_read_valid)) begin |
| 107 | state = FETCH; | 116 | state = FETCH; |
| 108 | {opcode, operand} = `lag(mem_read_data); | 117 | {opcode, operand} = `lag(mem_read_data); |
| 109 | sign_extended_operand = {{(DATA_BITS-8){operand[7]}}, operand}; | 118 | {i, z, wip} = operand; |
| 119 | if (z) | ||
| 120 | address = {page, wip}; | ||
| 121 | else | ||
| 122 | address = {5'b0, wip}; | ||
| 110 | case (opcode) | 123 | case (opcode) |
| 111 | 'h0: begin | 124 | 'b000, 'b001, 'b010: state = i ? INDIRECT : AGEN; |
| 112 | if (operand[0]) acc = 0; | 125 | 'b011, 'b100: state = i ? INDIRECT : EXEC; |
| 113 | if (operand[1]) ++acc; | 126 | 'b101: begin |
| 114 | if (operand[2]) --acc; | 127 | if (i) begin |
| 115 | if (operand[6]) state = MEMORY; | ||
| 116 | if (operand[7]) begin | ||
| 117 | rx_ready = 1; | ||
| 118 | state = MEMORY; | ||
| 119 | end | ||
| 120 | if (operand == 0) state = HALT; | ||
| 121 | end | ||
| 122 | 'h1: acc = sign_extended_operand; | ||
| 123 | 'h2, 'h3: begin | ||
| 124 | address = {7'b0, operand[6:0]}; | ||
| 125 | state = operand[7] ? INDIRECT : AGEN; | ||
| 126 | end | ||
| 127 | 'h4: if (acc != sign_extended_operand) ++pc; | ||
| 128 | 'h5: begin | ||
| 129 | if (operand[7]) begin | ||
| 130 | address = {7'b0, operand[6:0]}; | ||
| 131 | state = INDIRECT; | 128 | state = INDIRECT; |
| 132 | end else begin | 129 | end else begin |
| 133 | pc = pc + {{(ADDR_BITS-7){operand[6]}}, operand[6:0]}; | 130 | pc = address; |
| 134 | end | 131 | end |
| 135 | end | 132 | end |
| 136 | 'h6: begin | ||
| 137 | mem_write_data = acc % 10 + 'h30; | ||
| 138 | acc = acc / 10; | ||
| 139 | address = {7'b0, operand[6:0]}; | ||
| 140 | state = operand[7] ? INDIRECT : AGEN; | ||
| 141 | end | ||
| 142 | endcase | 133 | endcase |
| 143 | end | 134 | end |
| 144 | end | 135 | end |
| @@ -156,73 +147,90 @@ always_ff @(posedge clk) begin | |||
| 156 | mem_write = 0; | 147 | mem_write = 0; |
| 157 | end | 148 | end |
| 158 | if (`lag(mem_read_valid)) begin | 149 | if (`lag(mem_read_valid)) begin |
| 159 | address = {{(ADDR_BITS - DATA_BITS){1'b0}}, `lag(mem_read_data)}; | 150 | if (address[7:3] == 5'b00001) begin |
| 160 | state = AGEN; | 151 | address = {{(ADDR_BITS - DATA_BITS){1'b0}}, `lag(mem_read_data)}; |
| 152 | address += 1; | ||
| 153 | state = PREINC; | ||
| 154 | end else begin | ||
| 155 | address = {{(ADDR_BITS - DATA_BITS){1'b0}}, `lag(mem_read_data)}; | ||
| 156 | case (opcode) | ||
| 157 | 'b000, 'b001, 'b010: state = AGEN; | ||
| 158 | 'b011, 'b100: state = EXEC; | ||
| 159 | 'b101: begin | ||
| 160 | pc = address; | ||
| 161 | state = FETCH; | ||
| 162 | end | ||
| 163 | endcase | ||
| 164 | end | ||
| 161 | end | 165 | end |
| 162 | end | 166 | end |
| 163 | 167 | ||
| 168 | PREINC: begin | ||
| 169 | mem_valid = 1; | ||
| 170 | mem_write = 1; | ||
| 171 | mem_write_data = address[DATA_BITS-1:0]; | ||
| 172 | case (opcode) begin | ||
| 173 | 'b000, 'b001, 'b010: state = `lag(mem_ready) ? PREINC : AGEN; | ||
| 174 | 'b011, 'b100, 'b101: state = `lag(mem_ready) ? PREINC : EXEC; | ||
| 175 | endcase | ||
| 176 | end | ||
| 177 | |||
| 164 | AGEN: begin | 178 | AGEN: begin |
| 165 | mem_valid = 0; | 179 | mem_valid = 1; |
| 166 | mem_write = 0; | ||
| 167 | state = FETCH; | ||
| 168 | case (opcode) | 180 | case (opcode) |
| 169 | 'h2: begin | 181 | 'b000, 'b001, 'b010: mem_write = 0; |
| 170 | mem_valid = 1; | ||
| 171 | mem_address = address; | ||
| 172 | state = `lag(mem_ready) ? MEMORY : AGEN; | ||
| 173 | end | ||
| 174 | 'h3: begin | ||
| 175 | mem_valid = 1; | ||
| 176 | mem_address = address; | ||
| 177 | mem_write = 1; | ||
| 178 | mem_write_data = acc; | ||
| 179 | state = `lag(mem_ready) ? FETCH : AGEN; | ||
| 180 | end | ||
| 181 | 'h5: pc = address; | ||
| 182 | 'h6: begin | ||
| 183 | mem_valid = 1; | ||
| 184 | mem_address = address; | ||
| 185 | mem_write = 1; | ||
| 186 | state = `lag(mem_ready) ? FETCH : AGEN; | ||
| 187 | end | ||
| 188 | endcase | 182 | endcase |
| 183 | mem_address = address; | ||
| 184 | state = `lag(mem_ready) ? EXEC : AGEN; | ||
| 189 | end | 185 | end |
| 190 | 186 | ||
| 191 | MEMORY: begin | 187 | EXEC: begin |
| 188 | automatic bit stall = 0; | ||
| 192 | if (`lag(mem_ready)) begin | 189 | if (`lag(mem_ready)) begin |
| 193 | mem_valid = 0; | 190 | mem_valid = 0; |
| 194 | mem_write = 0; | 191 | mem_write = 0; |
| 192 | end else if (mem_valid) begin | ||
| 193 | stall = 1; | ||
| 195 | end | 194 | end |
| 196 | state = FETCH; | ||
| 197 | case (opcode) | 195 | case (opcode) |
| 198 | 'h0: begin | 196 | 'b000, 'b001, 'b010: if (! `lag(mem_read_valid)) stall = 1; |
| 199 | if (operand[6]) begin | 197 | endcase |
| 200 | if (tx_valid) begin | 198 | if (! stall) begin |
| 201 | state = MEMORY; | 199 | state = FETCH; |
| 202 | end else begin | 200 | case (opcode) |
| 203 | tx_valid = 1; | 201 | 'b000: acc &= `lag(mem_read_data); |
| 204 | tx_data = acc[7:0]; | 202 | 'b001: {link, acc} += {1'b0, `lag(mem_read_data)}; |
| 205 | end | 203 | 'b010: begin |
| 204 | mem_valid = 1; | ||
| 205 | mem_address = address; | ||
| 206 | mem_write = 1; | ||
| 207 | mem_write_data = `lag(mem_read_data) + 1; | ||
| 208 | if (mem_write_data == 0) ++pc; | ||
| 209 | state = MEMWAIT; | ||
| 206 | end | 210 | end |
| 207 | if (operand[7]) begin | 211 | 'b011: begin |
| 208 | if (`lag(rx_valid)) begin | 212 | mem_valid = 1; |
| 209 | rx_ready = 0; | 213 | mem_address = address; |
| 210 | acc = {{(DATA_BITS-8){1'b0}}, `lag(rx_data)}; | 214 | mem_write = 1; |
| 211 | end else begin | 215 | mem_write_data = acc; |
| 212 | state = MEMORY; | 216 | acc = 0; |
| 213 | end | 217 | state = MEMWAIT; |
| 214 | end | 218 | end |
| 215 | end | 219 | 'b100: begin |
| 216 | 'h2: begin | 220 | mem_valid = 1; |
| 217 | if (`lag(mem_read_valid)) begin | 221 | mem_address = address; |
| 218 | acc = acc + `lag(mem_read_data); | 222 | mem_write = 1; |
| 219 | end else begin | 223 | mem_write_data = pc[DATA_BITS-1:0]; |
| 220 | state = MEMORY; | 224 | pc = address + 1; |
| 225 | state = MEMWAIT; | ||
| 221 | end | 226 | end |
| 222 | end | 227 | 'b101: pc = address; |
| 223 | endcase | 228 | endcase |
| 229 | end | ||
| 224 | end | 230 | end |
| 225 | 231 | ||
| 232 | MEMWAIT: state = `lag(mem_ready) ? FETCH : MEMWAIT; | ||
| 233 | |||
| 226 | HALT: $finish; | 234 | HALT: $finish; |
| 227 | endcase | 235 | endcase |
| 228 | end | 236 | end |
