diff options
| author | Julian Blake Kongslie | 2021-03-28 17:19:12 -0700 |
|---|---|---|
| committer | Julian Blake Kongslie | 2021-03-28 17:19:12 -0700 |
| commit | 0c9e672cffa935f4db57d99e161a0c22b2b25cd9 (patch) | |
| tree | 40f53c1ba25d5e111c18da67a1b67c69ffb3ac89 /hdl | |
| parent | Pessimize JTAG UART somewhat. (diff) | |
| download | noncpu-0c9e672cffa935f4db57d99e161a0c22b2b25cd9.tar.xz | |
Yet another lame attempt.
Diffstat (limited to '')
| -rw-r--r-- | hdl/mem.sv | 36 | ||||
| -rw-r--r-- | hdl/top.sv | 69 |
2 files changed, 71 insertions, 34 deletions
| @@ -1,12 +1,17 @@ | |||
| 1 | `include "util.svh" | ||
| 2 | |||
| 1 | module mem | 3 | module mem |
| 2 | ( input bit clk | 4 | ( input bit clk |
| 5 | , input bit reset | ||
| 3 | 6 | ||
| 4 | , output bit ready | 7 | , output bit ready |
| 5 | , input bit valid | 8 | , input bit valid `define valid `past(valid) |
| 6 | , input bit write | 9 | , input bit write `define write `past(write) |
| 7 | , input bit [ADDR_BITS-1:0] address | 10 | , input bit [ADDR_BITS-1:0] address `define address `past(address) |
| 8 | , input bit [DATA_BITS-1:0] write_data | 11 | , input bit [DATA_BITS-1:0] write_data `define write_data `past(write_data) |
| 9 | , output bit [DATA_BITS-1:0] read_data // Valid exactly the cycle after address is consumed. | 12 | |
| 13 | , output bit read_valid | ||
| 14 | , output bit [DATA_BITS-1:0] read_data | ||
| 10 | ); | 15 | ); |
| 11 | 16 | ||
| 12 | parameter ADDR_BITS; | 17 | parameter ADDR_BITS; |
| @@ -16,14 +21,21 @@ parameter INIT_FILE; | |||
| 16 | bit [DATA_BITS-1:0] storage [0:(1<<ADDR_BITS)-1]; | 21 | bit [DATA_BITS-1:0] storage [0:(1<<ADDR_BITS)-1]; |
| 17 | initial $readmemh(INIT_FILE, storage); | 22 | initial $readmemh(INIT_FILE, storage); |
| 18 | 23 | ||
| 19 | assign ready = 1; | ||
| 20 | |||
| 21 | always_ff @(posedge clk) begin | 24 | always_ff @(posedge clk) begin |
| 22 | if (ready && valid) begin | 25 | if (reset) begin |
| 23 | if (write) | 26 | ready = 0; |
| 24 | storage[address] <= write_data; | 27 | read_valid = 0; |
| 25 | else | 28 | end else begin |
| 26 | read_data <= storage[address]; | 29 | read_valid = 0; |
| 30 | if (ready && `valid) begin | ||
| 31 | if (`write) begin | ||
| 32 | storage[`address] = `write_data; | ||
| 33 | end else begin | ||
| 34 | read_valid = 1; | ||
| 35 | read_data = storage[`address]; | ||
| 36 | end | ||
| 37 | end | ||
| 38 | ready = 1; | ||
| 27 | end | 39 | end |
| 28 | end | 40 | end |
| 29 | 41 | ||
| @@ -18,7 +18,9 @@ bit mem_valid; | |||
| 18 | bit mem_write; | 18 | bit mem_write; |
| 19 | bit [ADDR_BITS-1:0] mem_address; | 19 | bit [ADDR_BITS-1:0] mem_address; |
| 20 | bit [DATA_BITS-1:0] mem_write_data; | 20 | bit [DATA_BITS-1:0] mem_write_data; |
| 21 | bit [DATA_BITS-1:0] mem_read_data; | 21 | |
| 22 | bit mem_read_valid; `define mem_read_valid `past(mem_read_valid) | ||
| 23 | bit [DATA_BITS-1:0] mem_read_data; `define mem_read_data `past(mem_read_data) | ||
| 22 | 24 | ||
| 23 | mem | 25 | mem |
| 24 | #( .ADDR_BITS(ADDR_BITS) | 26 | #( .ADDR_BITS(ADDR_BITS) |
| @@ -27,12 +29,15 @@ mem | |||
| 27 | ) | 29 | ) |
| 28 | memory | 30 | memory |
| 29 | ( .clk(clk) | 31 | ( .clk(clk) |
| 32 | , .reset(reset) | ||
| 30 | 33 | ||
| 31 | , .ready(mem_ready) | 34 | , .ready(mem_ready) |
| 32 | , .valid(mem_valid) | 35 | , .valid(mem_valid) |
| 33 | , .address(mem_address) | 36 | , .address(mem_address) |
| 34 | , .write(mem_write) | 37 | , .write(mem_write) |
| 35 | , .write_data(mem_write_data) | 38 | , .write_data(mem_write_data) |
| 39 | |||
| 40 | , .read_valid(mem_read_valid) | ||
| 36 | , .read_data(mem_read_data) | 41 | , .read_data(mem_read_data) |
| 37 | ); | 42 | ); |
| 38 | 43 | ||
| @@ -68,7 +73,9 @@ bit [DATA_BITS-1:0] idx; | |||
| 68 | enum | 73 | enum |
| 69 | { FETCH | 74 | { FETCH |
| 70 | , DECODE | 75 | , DECODE |
| 76 | , AGEN | ||
| 71 | , MEMORY | 77 | , MEMORY |
| 78 | , HALT | ||
| 72 | } state; | 79 | } state; |
| 73 | 80 | ||
| 74 | always_ff @(posedge clk) begin | 81 | always_ff @(posedge clk) begin |
| @@ -82,7 +89,7 @@ always_ff @(posedge clk) begin | |||
| 82 | idx = 0; | 89 | idx = 0; |
| 83 | state = state.first; | 90 | state = state.first; |
| 84 | end else begin | 91 | end else begin |
| 85 | `ifdef DEBUG $display("s=%0d pc=%x (acc=%x idx=%x)", state, pc, acc, idx); `endif | 92 | `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 |
| 86 | if (`tx_ready) tx_valid = 0; | 93 | if (`tx_ready) tx_valid = 0; |
| 87 | 94 | ||
| 88 | case (state) | 95 | case (state) |
| @@ -98,51 +105,64 @@ always_ff @(posedge clk) begin | |||
| 98 | end | 105 | end |
| 99 | 106 | ||
| 100 | DECODE: begin | 107 | DECODE: begin |
| 108 | if (`mem_read_valid) begin | ||
| 109 | mem_valid = 0; | ||
| 110 | mem_write = 0; | ||
| 111 | state = FETCH; | ||
| 112 | {opcode, operand} = `mem_read_data; | ||
| 113 | `ifdef DEBUG $display("\tdecode %x:%x", opcode, operand); `endif | ||
| 114 | case (opcode) | ||
| 115 | 'h0: acc = {{4{operand[7]}}, operand}; | ||
| 116 | 'h1: state = AGEN; | ||
| 117 | 'h2: state = AGEN; | ||
| 118 | 'h3: if (acc != operand) ++pc; | ||
| 119 | 'h4: pc = pc + {{4{operand[7]}}, operand}; | ||
| 120 | 'hf: begin | ||
| 121 | if (operand[0]) ++acc; | ||
| 122 | if (operand[1]) --acc; | ||
| 123 | if (operand[2]) ++idx; | ||
| 124 | if (operand[3]) --idx; | ||
| 125 | if (operand[4]) {idx, acc} = {acc, idx}; | ||
| 126 | if (operand[5]) idx = acc; | ||
| 127 | if (operand[6]) state = MEMORY; | ||
| 128 | if (operand[7]) state = HALT; | ||
| 129 | end | ||
| 130 | endcase | ||
| 131 | end | ||
| 132 | end | ||
| 133 | |||
| 134 | AGEN: begin | ||
| 101 | mem_valid = 0; | 135 | mem_valid = 0; |
| 102 | mem_write = 0; | 136 | mem_write = 0; |
| 103 | state = FETCH; | 137 | state = FETCH; |
| 104 | {opcode, operand} = mem_read_data; | 138 | `ifdef DEBUG $display("\tagen"); `endif |
| 105 | `ifdef DEBUG $display("\tdecode %x:%x", opcode, operand); `endif | ||
| 106 | case (opcode) | 139 | case (opcode) |
| 107 | 'h0: acc = {{4{operand[7]}}, operand}; | ||
| 108 | 'h1: begin | 140 | 'h1: begin |
| 109 | mem_valid = 1; | 141 | mem_valid = 1; |
| 110 | mem_address = idx + operand; | 142 | mem_address = idx + operand; |
| 111 | state = MEMORY; | 143 | state = `mem_ready ? MEMORY : AGEN; |
| 112 | end | 144 | end |
| 113 | 'h2: begin | 145 | 'h2: begin |
| 114 | mem_valid = 1; | 146 | mem_valid = 1; |
| 115 | mem_address = idx + operand; | 147 | mem_address = idx + operand; |
| 116 | mem_write = 1; | 148 | mem_write = 1; |
| 117 | mem_write_data = acc; | 149 | mem_write_data = acc; |
| 118 | if (! `mem_ready) state = MEMORY; | 150 | state = `mem_ready ? FETCH : AGEN; |
| 119 | end | ||
| 120 | 'h3: if (acc != operand) ++pc; | ||
| 121 | 'h4: pc = pc + {{4{operand[7]}}, operand}; | ||
| 122 | 'hf: begin | ||
| 123 | if (operand[0]) ++acc; | ||
| 124 | if (operand[1]) --acc; | ||
| 125 | if (operand[2]) ++idx; | ||
| 126 | if (operand[3]) --idx; | ||
| 127 | if (operand[4]) {idx, acc} = {acc, idx}; | ||
| 128 | if (operand[5]) idx = acc; | ||
| 129 | if (operand[6]) state = MEMORY; | ||
| 130 | if (operand[7]) state = DECODE; | ||
| 131 | end | 151 | end |
| 132 | endcase | 152 | endcase |
| 133 | end | 153 | end |
| 134 | 154 | ||
| 135 | MEMORY: begin | 155 | MEMORY: begin |
| 136 | `ifdef DEBUG $display("\tstall"); `endif | ||
| 137 | if (`mem_ready) begin | 156 | if (`mem_ready) begin |
| 138 | mem_valid = 0; | 157 | mem_valid = 0; |
| 139 | mem_write = 0; | 158 | mem_write = 0; |
| 140 | end | 159 | end |
| 141 | state = FETCH; | 160 | state = FETCH; |
| 161 | `ifdef DEBUG $display("\tstall"); `endif | ||
| 142 | case (opcode) | 162 | case (opcode) |
| 143 | 'h1: begin | 163 | 'h1: begin |
| 144 | if (`mem_ready) begin | 164 | if (`mem_read_valid) begin |
| 145 | acc = mem_read_data; | 165 | acc = `mem_read_data; |
| 146 | end else begin | 166 | end else begin |
| 147 | state = MEMORY; | 167 | state = MEMORY; |
| 148 | end | 168 | end |
| @@ -159,6 +179,11 @@ always_ff @(posedge clk) begin | |||
| 159 | end | 179 | end |
| 160 | endcase | 180 | endcase |
| 161 | end | 181 | end |
| 182 | |||
| 183 | HALT: begin | ||
| 184 | $display("Reached halt state."); | ||
| 185 | $finish; | ||
| 186 | end | ||
| 162 | endcase | 187 | endcase |
| 163 | 188 | ||
| 164 | `ifdef DEBUG if (mem_valid) $display("\tmem addr=%x w=%b", mem_address, mem_write); `endif | 189 | `ifdef DEBUG if (mem_valid) $display("\tmem addr=%x w=%b", mem_address, mem_write); `endif |
