diff options
| -rw-r--r-- | hdl/core.sv | 231 | ||||
| -rw-r--r-- | hdl/top.sv | 220 |
2 files changed, 232 insertions, 219 deletions
diff --git a/hdl/core.sv b/hdl/core.sv new file mode 100644 index 0000000..919dac9 --- /dev/null +++ b/hdl/core.sv | |||
| @@ -0,0 +1,231 @@ | |||
| 1 | `include "util.svh" | ||
| 2 | |||
| 3 | module core | ||
| 4 | #( ADDR_BITS = 14 | ||
| 5 | , DATA_BITS = 12 | ||
| 6 | ) | ||
| 7 | ( input bit clk | ||
| 8 | , input bit reset | ||
| 9 | ); | ||
| 10 | |||
| 11 | bit mem_ready; | ||
| 12 | bit mem_valid; | ||
| 13 | bit mem_write; | ||
| 14 | bit [ADDR_BITS-1:0] mem_address; | ||
| 15 | bit [DATA_BITS-1:0] mem_write_data; | ||
| 16 | |||
| 17 | bit mem_read_valid; | ||
| 18 | bit [DATA_BITS-1:0] mem_read_data; | ||
| 19 | |||
| 20 | mem | ||
| 21 | #( .ADDR_BITS(ADDR_BITS) | ||
| 22 | , .DATA_BITS(DATA_BITS) | ||
| 23 | , .INIT_FILE("mem/mem.hex") | ||
| 24 | ) | ||
| 25 | memory | ||
| 26 | ( .clk(clk) | ||
| 27 | , .reset(reset) | ||
| 28 | |||
| 29 | , .ready(mem_ready) | ||
| 30 | , .valid(mem_valid) | ||
| 31 | , .address(mem_address) | ||
| 32 | , .write(mem_write) | ||
| 33 | , .write_data(mem_write_data) | ||
| 34 | |||
| 35 | , .read_valid(mem_read_valid) | ||
| 36 | , .read_data(mem_read_data) | ||
| 37 | ); | ||
| 38 | |||
| 39 | bit rx_ready; | ||
| 40 | bit rx_valid; | ||
| 41 | bit [7:0] rx_data; | ||
| 42 | |||
| 43 | bit tx_ready; | ||
| 44 | bit tx_valid; | ||
| 45 | bit [7:0] tx_data; | ||
| 46 | |||
| 47 | jtag_uart | ||
| 48 | #( .INSTANCE(0) | ||
| 49 | ) uart0 | ||
| 50 | ( .clk(clk) | ||
| 51 | , .reset(reset) | ||
| 52 | |||
| 53 | , .rx_ready(rx_ready) | ||
| 54 | , .rx_valid(rx_valid) | ||
| 55 | , .rx_data(rx_data) | ||
| 56 | |||
| 57 | , .tx_ready(tx_ready) | ||
| 58 | , .tx_valid(tx_valid) | ||
| 59 | , .tx_data(tx_data) | ||
| 60 | ); | ||
| 61 | |||
| 62 | bit [ADDR_BITS-1:0] pc; | ||
| 63 | bit [3:0] opcode; | ||
| 64 | bit [7:0] operand; | ||
| 65 | bit [DATA_BITS-1:0] acc; | ||
| 66 | |||
| 67 | bit [ADDR_BITS-1:0] address; | ||
| 68 | bit [DATA_BITS-1:0] sign_extended_operand; | ||
| 69 | |||
| 70 | enum | ||
| 71 | { FETCH | ||
| 72 | , DECODE | ||
| 73 | , INDIRECT | ||
| 74 | , INDIRECTED | ||
| 75 | , AGEN | ||
| 76 | , MEMORY | ||
| 77 | , HALT | ||
| 78 | } state; | ||
| 79 | |||
| 80 | always_ff @(posedge clk) begin | ||
| 81 | if (reset) begin | ||
| 82 | mem_valid = 0; | ||
| 83 | rx_ready = 0; | ||
| 84 | tx_valid = 0; | ||
| 85 | tx_data = 0; | ||
| 86 | pc = 0; | ||
| 87 | acc = 0; | ||
| 88 | state = state.first; | ||
| 89 | end else begin | ||
| 90 | if (`lag(tx_ready)) tx_valid = 0; | ||
| 91 | |||
| 92 | case (state) | ||
| 93 | FETCH: begin | ||
| 94 | mem_valid = 1; | ||
| 95 | mem_address = pc; | ||
| 96 | mem_write = 0; | ||
| 97 | if (`lag(mem_ready)) begin | ||
| 98 | state = DECODE; | ||
| 99 | ++pc; | ||
| 100 | end | ||
| 101 | end | ||
| 102 | |||
| 103 | DECODE: begin | ||
| 104 | mem_valid = 0; | ||
| 105 | mem_write = 0; | ||
| 106 | if (`lag(mem_read_valid)) begin | ||
| 107 | state = FETCH; | ||
| 108 | {opcode, operand} = `lag(mem_read_data); | ||
| 109 | sign_extended_operand = {{(DATA_BITS-8){operand[7]}}, operand}; | ||
| 110 | case (opcode) | ||
| 111 | 'h0: begin | ||
| 112 | if (operand[0]) acc = 0; | ||
| 113 | if (operand[1]) ++acc; | ||
| 114 | if (operand[2]) --acc; | ||
| 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; | ||
| 132 | end else begin | ||
| 133 | pc = pc + {{(ADDR_BITS-7){operand[6]}}, operand[6:0]}; | ||
| 134 | end | ||
| 135 | 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 | ||
| 143 | end | ||
| 144 | end | ||
| 145 | |||
| 146 | INDIRECT: begin | ||
| 147 | mem_valid = 1; | ||
| 148 | mem_write = 0; | ||
| 149 | mem_address = address; | ||
| 150 | state = `lag(mem_ready) ? INDIRECTED : INDIRECT; | ||
| 151 | end | ||
| 152 | |||
| 153 | INDIRECTED: begin | ||
| 154 | if (`lag(mem_ready)) begin | ||
| 155 | mem_valid = 0; | ||
| 156 | mem_write = 0; | ||
| 157 | end | ||
| 158 | if (`lag(mem_read_valid)) begin | ||
| 159 | address = {{(ADDR_BITS - DATA_BITS){1'b0}}, `lag(mem_read_data)}; | ||
| 160 | state = AGEN; | ||
| 161 | end | ||
| 162 | end | ||
| 163 | |||
| 164 | AGEN: begin | ||
| 165 | mem_valid = 0; | ||
| 166 | mem_write = 0; | ||
| 167 | state = FETCH; | ||
| 168 | case (opcode) | ||
| 169 | 'h2: begin | ||
| 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 | ||
| 189 | end | ||
| 190 | |||
| 191 | MEMORY: begin | ||
| 192 | if (`lag(mem_ready)) begin | ||
| 193 | mem_valid = 0; | ||
| 194 | mem_write = 0; | ||
| 195 | end | ||
| 196 | state = FETCH; | ||
| 197 | case (opcode) | ||
| 198 | 'h0: begin | ||
| 199 | if (operand[6]) begin | ||
| 200 | if (tx_valid) begin | ||
| 201 | state = MEMORY; | ||
| 202 | end else begin | ||
| 203 | tx_valid = 1; | ||
| 204 | tx_data = acc[7:0]; | ||
| 205 | end | ||
| 206 | end | ||
| 207 | if (operand[7]) begin | ||
| 208 | if (`lag(rx_valid)) begin | ||
| 209 | rx_ready = 0; | ||
| 210 | acc = {{(DATA_BITS-8){1'b0}}, `lag(rx_data)}; | ||
| 211 | end else begin | ||
| 212 | state = MEMORY; | ||
| 213 | end | ||
| 214 | end | ||
| 215 | end | ||
| 216 | 'h2: begin | ||
| 217 | if (`lag(mem_read_valid)) begin | ||
| 218 | acc = acc + `lag(mem_read_data); | ||
| 219 | end else begin | ||
| 220 | state = MEMORY; | ||
| 221 | end | ||
| 222 | end | ||
| 223 | endcase | ||
| 224 | end | ||
| 225 | |||
| 226 | HALT: $finish; | ||
| 227 | endcase | ||
| 228 | end | ||
| 229 | end | ||
| 230 | |||
| 231 | endmodule | ||
| @@ -1,9 +1,6 @@ | |||
| 1 | `include "util.svh" | 1 | `include "util.svh" |
| 2 | 2 | ||
| 3 | module top | 3 | module top |
| 4 | #( ADDR_BITS = 14 | ||
| 5 | , DATA_BITS = 12 | ||
| 6 | ) | ||
| 7 | ( input bit native_clk // verilator public | 4 | ( input bit native_clk // verilator public |
| 8 | , input bit reset_n // verilator public | 5 | , input bit reset_n // verilator public |
| 9 | ); | 6 | ); |
| @@ -21,224 +18,9 @@ clock | |||
| 21 | , .reset(reset) | 18 | , .reset(reset) |
| 22 | ); | 19 | ); |
| 23 | 20 | ||
| 24 | bit mem_ready; | 21 | core cpu |
| 25 | bit mem_valid; | ||
| 26 | bit mem_write; | ||
| 27 | bit [ADDR_BITS-1:0] mem_address; | ||
| 28 | bit [DATA_BITS-1:0] mem_write_data; | ||
| 29 | |||
| 30 | bit mem_read_valid; | ||
| 31 | bit [DATA_BITS-1:0] mem_read_data; | ||
| 32 | |||
| 33 | mem | ||
| 34 | #( .ADDR_BITS(ADDR_BITS) | ||
| 35 | , .DATA_BITS(DATA_BITS) | ||
| 36 | , .INIT_FILE("mem/mem.hex") | ||
| 37 | ) | ||
| 38 | memory | ||
| 39 | ( .clk(clk) | ||
| 40 | , .reset(reset) | ||
| 41 | |||
| 42 | , .ready(mem_ready) | ||
| 43 | , .valid(mem_valid) | ||
| 44 | , .address(mem_address) | ||
| 45 | , .write(mem_write) | ||
| 46 | , .write_data(mem_write_data) | ||
| 47 | |||
| 48 | , .read_valid(mem_read_valid) | ||
| 49 | , .read_data(mem_read_data) | ||
| 50 | ); | ||
| 51 | |||
| 52 | bit rx_ready; | ||
| 53 | bit rx_valid; | ||
| 54 | bit [7:0] rx_data; | ||
| 55 | |||
| 56 | bit tx_ready; | ||
| 57 | bit tx_valid; | ||
| 58 | bit [7:0] tx_data; | ||
| 59 | |||
| 60 | jtag_uart | ||
| 61 | #( .INSTANCE(0) | ||
| 62 | ) uart0 | ||
| 63 | ( .clk(clk) | 22 | ( .clk(clk) |
| 64 | , .reset(reset) | 23 | , .reset(reset) |
| 65 | |||
| 66 | , .rx_ready(rx_ready) | ||
| 67 | , .rx_valid(rx_valid) | ||
| 68 | , .rx_data(rx_data) | ||
| 69 | |||
| 70 | , .tx_ready(tx_ready) | ||
| 71 | , .tx_valid(tx_valid) | ||
| 72 | , .tx_data(tx_data) | ||
| 73 | ); | 24 | ); |
| 74 | 25 | ||
| 75 | bit [ADDR_BITS-1:0] pc; | ||
| 76 | bit [3:0] opcode; | ||
| 77 | bit [7:0] operand; | ||
| 78 | bit [DATA_BITS-1:0] acc; | ||
| 79 | |||
| 80 | bit [ADDR_BITS-1:0] address; | ||
| 81 | bit [DATA_BITS-1:0] sign_extended_operand; | ||
| 82 | |||
| 83 | enum | ||
| 84 | { FETCH | ||
| 85 | , DECODE | ||
| 86 | , INDIRECT | ||
| 87 | , INDIRECTED | ||
| 88 | , AGEN | ||
| 89 | , MEMORY | ||
| 90 | , HALT | ||
| 91 | } state; | ||
| 92 | |||
| 93 | always_ff @(posedge clk) begin | ||
| 94 | if (reset) begin | ||
| 95 | mem_valid = 0; | ||
| 96 | rx_ready = 0; | ||
| 97 | tx_valid = 0; | ||
| 98 | tx_data = 0; | ||
| 99 | pc = 0; | ||
| 100 | acc = 0; | ||
| 101 | state = state.first; | ||
| 102 | end else begin | ||
| 103 | if (`lag(tx_ready)) tx_valid = 0; | ||
| 104 | |||
| 105 | case (state) | ||
| 106 | FETCH: begin | ||
| 107 | mem_valid = 1; | ||
| 108 | mem_address = pc; | ||
| 109 | mem_write = 0; | ||
| 110 | if (`lag(mem_ready)) begin | ||
| 111 | state = DECODE; | ||
| 112 | ++pc; | ||
| 113 | end | ||
| 114 | end | ||
| 115 | |||
| 116 | DECODE: begin | ||
| 117 | mem_valid = 0; | ||
| 118 | mem_write = 0; | ||
| 119 | if (`lag(mem_read_valid)) begin | ||
| 120 | state = FETCH; | ||
| 121 | {opcode, operand} = `lag(mem_read_data); | ||
| 122 | sign_extended_operand = {{(DATA_BITS-8){operand[7]}}, operand}; | ||
| 123 | case (opcode) | ||
| 124 | 'h0: begin | ||
| 125 | if (operand[0]) acc = 0; | ||
| 126 | if (operand[1]) ++acc; | ||
| 127 | if (operand[2]) --acc; | ||
| 128 | if (operand[6]) state = MEMORY; | ||
| 129 | if (operand[7]) begin | ||
| 130 | rx_ready = 1; | ||
| 131 | state = MEMORY; | ||
| 132 | end | ||
| 133 | if (operand == 0) state = HALT; | ||
| 134 | end | ||
| 135 | 'h1: acc = sign_extended_operand; | ||
| 136 | 'h2, 'h3: begin | ||
| 137 | address = {7'b0, operand[6:0]}; | ||
| 138 | state = operand[7] ? INDIRECT : AGEN; | ||
| 139 | end | ||
| 140 | 'h4: if (acc != sign_extended_operand) ++pc; | ||
| 141 | 'h5: begin | ||
| 142 | if (operand[7]) begin | ||
| 143 | address = {7'b0, operand[6:0]}; | ||
| 144 | state = INDIRECT; | ||
| 145 | end else begin | ||
| 146 | pc = pc + {{(ADDR_BITS-7){operand[6]}}, operand[6:0]}; | ||
| 147 | end | ||
| 148 | end | ||
| 149 | 'h6: begin | ||
| 150 | mem_write_data = acc % 10 + 'h30; | ||
| 151 | acc = acc / 10; | ||
| 152 | address = {7'b0, operand[6:0]}; | ||
| 153 | state = operand[7] ? INDIRECT : AGEN; | ||
| 154 | end | ||
| 155 | endcase | ||
| 156 | end | ||
| 157 | end | ||
| 158 | |||
| 159 | INDIRECT: begin | ||
| 160 | mem_valid = 1; | ||
| 161 | mem_write = 0; | ||
| 162 | mem_address = address; | ||
| 163 | state = `lag(mem_ready) ? INDIRECTED : INDIRECT; | ||
| 164 | end | ||
| 165 | |||
| 166 | INDIRECTED: begin | ||
| 167 | if (`lag(mem_ready)) begin | ||
| 168 | mem_valid = 0; | ||
| 169 | mem_write = 0; | ||
| 170 | end | ||
| 171 | if (`lag(mem_read_valid)) begin | ||
| 172 | address = {{(ADDR_BITS - DATA_BITS){1'b0}}, `lag(mem_read_data)}; | ||
| 173 | state = AGEN; | ||
| 174 | end | ||
| 175 | end | ||
| 176 | |||
| 177 | AGEN: begin | ||
| 178 | mem_valid = 0; | ||
| 179 | mem_write = 0; | ||
| 180 | state = FETCH; | ||
| 181 | case (opcode) | ||
| 182 | 'h2: begin | ||
| 183 | mem_valid = 1; | ||
| 184 | mem_address = address; | ||
| 185 | state = `lag(mem_ready) ? MEMORY : AGEN; | ||
| 186 | end | ||
| 187 | 'h3: begin | ||
| 188 | mem_valid = 1; | ||
| 189 | mem_address = address; | ||
| 190 | mem_write = 1; | ||
| 191 | mem_write_data = acc; | ||
| 192 | state = `lag(mem_ready) ? FETCH : AGEN; | ||
| 193 | end | ||
| 194 | 'h5: pc = address; | ||
| 195 | 'h6: begin | ||
| 196 | mem_valid = 1; | ||
| 197 | mem_address = address; | ||
| 198 | mem_write = 1; | ||
| 199 | state = `lag(mem_ready) ? FETCH : AGEN; | ||
| 200 | end | ||
| 201 | endcase | ||
| 202 | end | ||
| 203 | |||
| 204 | MEMORY: begin | ||
| 205 | if (`lag(mem_ready)) begin | ||
| 206 | mem_valid = 0; | ||
| 207 | mem_write = 0; | ||
| 208 | end | ||
| 209 | state = FETCH; | ||
| 210 | case (opcode) | ||
| 211 | 'h0: begin | ||
| 212 | if (operand[6]) begin | ||
| 213 | if (tx_valid) begin | ||
| 214 | state = MEMORY; | ||
| 215 | end else begin | ||
| 216 | tx_valid = 1; | ||
| 217 | tx_data = acc[7:0]; | ||
| 218 | end | ||
| 219 | end | ||
| 220 | if (operand[7]) begin | ||
| 221 | if (`lag(rx_valid)) begin | ||
| 222 | rx_ready = 0; | ||
| 223 | acc = {{(DATA_BITS-8){1'b0}}, `lag(rx_data)}; | ||
| 224 | end else begin | ||
| 225 | state = MEMORY; | ||
| 226 | end | ||
| 227 | end | ||
| 228 | end | ||
| 229 | 'h2: begin | ||
| 230 | if (`lag(mem_read_valid)) begin | ||
| 231 | acc = acc + `lag(mem_read_data); | ||
| 232 | end else begin | ||
| 233 | state = MEMORY; | ||
| 234 | end | ||
| 235 | end | ||
| 236 | endcase | ||
| 237 | end | ||
| 238 | |||
| 239 | HALT: $finish; | ||
| 240 | endcase | ||
| 241 | end | ||
| 242 | end | ||
| 243 | |||
| 244 | endmodule | 26 | endmodule |
