diff options
| author | Julian Blake Kongslie | 2021-04-05 10:20:02 -0700 |
|---|---|---|
| committer | Julian Blake Kongslie | 2021-04-05 10:20:02 -0700 |
| commit | 6a1c04608090cc8fc88aafac0b4899e4cbb9cae9 (patch) | |
| tree | 9a03984357020c00dfeed299a8b321f832a48bd4 | |
| parent | Make PC ADDR-sized rather than DATA-sized for now (diff) | |
| download | noncpu-6a1c04608090cc8fc88aafac0b4899e4cbb9cae9.tar.xz | |
Change our simulator timing model to use continuous assignment guards.
Instead of depending on verilator getting $past right, this (ab-)uses
the SystemVerilog scheduling model which allows us to get a consistent
view of the universe by "isolating" the blocking updates. Easier to code
to and seems to be more reliable in verilator.
Diffstat (limited to '')
| -rw-r--r-- | hdl/jtag_uart.sv | 43 | ||||
| -rw-r--r-- | hdl/mem.sv | 34 | ||||
| -rw-r--r-- | hdl/top.sv | 115 | ||||
| -rw-r--r-- | hdl/util.svh | 7 |
4 files changed, 113 insertions, 86 deletions
diff --git a/hdl/jtag_uart.sv b/hdl/jtag_uart.sv index ad4665e..2b5f334 100644 --- a/hdl/jtag_uart.sv +++ b/hdl/jtag_uart.sv | |||
| @@ -9,15 +9,22 @@ module jtag_uart | |||
| 9 | ( input bit clk | 9 | ( input bit clk |
| 10 | , input bit reset | 10 | , input bit reset |
| 11 | 11 | ||
| 12 | , input bit rx_ready `define rx_ready `past(rx_ready) | 12 | , input bit rx_ready |
| 13 | , output bit rx_valid | 13 | , output bit rx_valid |
| 14 | , output bit [7:0] rx_data | 14 | , output bit [7:0] rx_data |
| 15 | 15 | ||
| 16 | , output bit tx_ready | 16 | , output bit tx_ready |
| 17 | , input bit tx_valid `define tx_valid `past(tx_valid) | 17 | , input bit tx_valid |
| 18 | , input bit [7:0] tx_data `define tx_data `past(tx_data) | 18 | , input bit [7:0] tx_data |
| 19 | ); | 19 | ); |
| 20 | 20 | ||
| 21 | `input(rx_ready) | ||
| 22 | `output(rx_valid) | ||
| 23 | `output(rx_data) | ||
| 24 | `output(tx_ready) | ||
| 25 | `input(tx_valid) | ||
| 26 | `input(tx_data) | ||
| 27 | |||
| 21 | `ifdef SYNTHESIS | 28 | `ifdef SYNTHESIS |
| 22 | 29 | ||
| 23 | alt_jtag_atlantic | 30 | alt_jtag_atlantic |
| @@ -28,12 +35,12 @@ alt_jtag_atlantic | |||
| 28 | ) real_jtag | 35 | ) real_jtag |
| 29 | ( .clk(clk) | 36 | ( .clk(clk) |
| 30 | , .rst_n(!reset) | 37 | , .rst_n(!reset) |
| 31 | , .r_dat(tx_data) | 38 | , .r_dat(tx_data_) |
| 32 | , .r_val(tx_valid) | 39 | , .r_val(tx_valid_) |
| 33 | , .r_ena(tx_ready) | 40 | , .r_ena(tx_ready_) |
| 34 | , .t_dat(rx_data) | 41 | , .t_dat(rx_data_) |
| 35 | , .t_dav(rx_ready) | 42 | , .t_dav(rx_ready_) |
| 36 | , .t_ena(rx_valid) | 43 | , .t_ena(rx_valid_) |
| 37 | ); | 44 | ); |
| 38 | 45 | ||
| 39 | `else | 46 | `else |
| @@ -48,34 +55,34 @@ bit [7:0] tx_b_data; | |||
| 48 | 55 | ||
| 49 | always_ff @(posedge clk) begin | 56 | always_ff @(posedge clk) begin |
| 50 | if (reset) begin | 57 | if (reset) begin |
| 51 | rx_valid = 0; | 58 | rx_valid_ = 0; |
| 52 | tx_ready = 0; | 59 | tx_ready_ = 0; |
| 53 | sim_rx_addr = 0; | 60 | sim_rx_addr = 0; |
| 54 | tx_b_valid = 0; | 61 | tx_b_valid = 0; |
| 55 | end else begin | 62 | end else begin |
| 56 | automatic bit [7:0] sim_rx_data = sim_rx_rom[sim_rx_addr]; | 63 | automatic bit [7:0] sim_rx_data = sim_rx_rom[sim_rx_addr]; |
| 57 | 64 | ||
| 58 | // RX logic | 65 | // RX logic |
| 59 | if (`rx_ready) rx_valid = 0; | 66 | if (rx_ready_) rx_valid_ = 0; |
| 60 | if (!rx_valid && (sim_rx_data != 0)) begin | 67 | if (!rx_valid_ && (sim_rx_data != 0)) begin |
| 61 | `ifdef JTAG_UART_LOCAL_ECHO | 68 | `ifdef JTAG_UART_LOCAL_ECHO |
| 62 | $write("%s", sim_rx_data); | 69 | $write("%s", sim_rx_data); |
| 63 | `endif | 70 | `endif |
| 64 | rx_valid = 1; | 71 | rx_valid_ = 1; |
| 65 | rx_data = sim_rx_data; | 72 | rx_data_ = sim_rx_data; |
| 66 | ++sim_rx_addr; | 73 | ++sim_rx_addr; |
| 67 | end | 74 | end |
| 68 | 75 | ||
| 69 | // TX logic | 76 | // TX logic |
| 70 | if (tx_ready && `tx_valid) begin | 77 | if (tx_ready_ && tx_valid_) begin |
| 71 | tx_b_valid = 1; | 78 | tx_b_valid = 1; |
| 72 | tx_b_data = `tx_data; | 79 | tx_b_data = tx_data_; |
| 73 | end | 80 | end |
| 74 | if (tx_b_valid) begin | 81 | if (tx_b_valid) begin |
| 75 | $write("%s", tx_b_data); | 82 | $write("%s", tx_b_data); |
| 76 | tx_b_valid = 0; | 83 | tx_b_valid = 0; |
| 77 | end | 84 | end |
| 78 | tx_ready = !tx_b_valid; | 85 | tx_ready_ = !tx_b_valid; |
| 79 | end | 86 | end |
| 80 | end | 87 | end |
| 81 | 88 | ||
| @@ -5,10 +5,10 @@ module mem | |||
| 5 | , input bit reset | 5 | , input bit reset |
| 6 | 6 | ||
| 7 | , output bit ready | 7 | , output bit ready |
| 8 | , input bit valid `define valid `past(valid) | 8 | , input bit valid |
| 9 | , input bit write `define write `past(write) | 9 | , input bit write |
| 10 | , input bit [ADDR_BITS-1:0] address `define address `past(address) | 10 | , input bit [ADDR_BITS-1:0] address |
| 11 | , input bit [DATA_BITS-1:0] write_data `define write_data `past(write_data) | 11 | , input bit [DATA_BITS-1:0] write_data |
| 12 | 12 | ||
| 13 | , output bit read_valid | 13 | , output bit read_valid |
| 14 | , output bit [DATA_BITS-1:0] read_data | 14 | , output bit [DATA_BITS-1:0] read_data |
| @@ -18,24 +18,32 @@ parameter ADDR_BITS; | |||
| 18 | parameter DATA_BITS; | 18 | parameter DATA_BITS; |
| 19 | parameter INIT_FILE; | 19 | parameter INIT_FILE; |
| 20 | 20 | ||
| 21 | `output(ready) | ||
| 22 | `input(valid) | ||
| 23 | `input(write) | ||
| 24 | `input(address) | ||
| 25 | `input(write_data) | ||
| 26 | `output(read_valid) | ||
| 27 | `output(read_data) | ||
| 28 | |||
| 21 | bit [DATA_BITS-1:0] storage [0:(1<<ADDR_BITS)-1]; | 29 | bit [DATA_BITS-1:0] storage [0:(1<<ADDR_BITS)-1]; |
| 22 | initial $readmemh(INIT_FILE, storage); | 30 | initial $readmemh(INIT_FILE, storage); |
| 23 | 31 | ||
| 24 | always_ff @(posedge clk) begin | 32 | always_ff @(posedge clk) begin |
| 25 | if (reset) begin | 33 | if (reset) begin |
| 26 | ready = 0; | 34 | ready_ = 0; |
| 27 | read_valid = 0; | 35 | read_valid_ = 0; |
| 28 | end else begin | 36 | end else begin |
| 29 | read_valid = 0; | 37 | read_valid_ = 0; |
| 30 | if (ready && `valid) begin | 38 | if (ready_ && valid_) begin |
| 31 | if (`write) begin | 39 | if (write_) begin |
| 32 | storage[`address] = `write_data; | 40 | storage[address_] = write_data_; |
| 33 | end else begin | 41 | end else begin |
| 34 | read_valid = 1; | 42 | read_valid_ = 1; |
| 35 | read_data = storage[`address]; | 43 | read_data_ = storage[address_]; |
| 36 | end | 44 | end |
| 37 | end | 45 | end |
| 38 | ready = 1; | 46 | ready_ = 1; |
| 39 | end | 47 | end |
| 40 | end | 48 | end |
| 41 | 49 | ||
| @@ -13,14 +13,14 @@ bit have_reset = 0; | |||
| 13 | always_ff @(posedge clk) if (reset) have_reset <= 1; | 13 | always_ff @(posedge clk) if (reset) have_reset <= 1; |
| 14 | assign reset = !reset_n || !have_reset; | 14 | assign reset = !reset_n || !have_reset; |
| 15 | 15 | ||
| 16 | bit mem_ready; `define mem_ready `past(mem_ready) | 16 | bit mem_ready; |
| 17 | bit mem_valid; | 17 | 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 | 21 | ||
| 22 | bit mem_read_valid; `define mem_read_valid `past(mem_read_valid) | 22 | bit mem_read_valid; |
| 23 | bit [DATA_BITS-1:0] mem_read_data; `define mem_read_data `past(mem_read_data) | 23 | bit [DATA_BITS-1:0] mem_read_data; |
| 24 | 24 | ||
| 25 | mem | 25 | mem |
| 26 | #( .ADDR_BITS(ADDR_BITS) | 26 | #( .ADDR_BITS(ADDR_BITS) |
| @@ -41,6 +41,14 @@ mem | |||
| 41 | , .read_data(mem_read_data) | 41 | , .read_data(mem_read_data) |
| 42 | ); | 42 | ); |
| 43 | 43 | ||
| 44 | `input(mem_ready) | ||
| 45 | `output(mem_valid) | ||
| 46 | `output(mem_address) | ||
| 47 | `output(mem_write) | ||
| 48 | `output(mem_write_data) | ||
| 49 | `input(mem_read_valid) | ||
| 50 | `input(mem_read_data) | ||
| 51 | |||
| 44 | bit rx_ready; | 52 | bit rx_ready; |
| 45 | bit rx_valid; | 53 | bit rx_valid; |
| 46 | bit [7:0] rx_data; | 54 | bit [7:0] rx_data; |
| @@ -56,14 +64,21 @@ jtag_uart | |||
| 56 | , .reset(reset) | 64 | , .reset(reset) |
| 57 | 65 | ||
| 58 | , .rx_ready(rx_ready) | 66 | , .rx_ready(rx_ready) |
| 59 | , .rx_valid(rx_valid) `define rx_valid `past(rx_valid) | 67 | , .rx_valid(rx_valid) |
| 60 | , .rx_data(rx_data) `define rx_data `past(rx_data) | 68 | , .rx_data(rx_data) |
| 61 | 69 | ||
| 62 | , .tx_ready(tx_ready) `define tx_ready `past(tx_ready) | 70 | , .tx_ready(tx_ready) |
| 63 | , .tx_valid(tx_valid) | 71 | , .tx_valid(tx_valid) |
| 64 | , .tx_data(tx_data) | 72 | , .tx_data(tx_data) |
| 65 | ); | 73 | ); |
| 66 | 74 | ||
| 75 | `output(rx_ready) | ||
| 76 | `input(rx_valid) | ||
| 77 | `input(rx_data) | ||
| 78 | `input(tx_ready) | ||
| 79 | `output(tx_valid) | ||
| 80 | `output(tx_data) | ||
| 81 | |||
| 67 | bit [ADDR_BITS-1:0] pc; | 82 | bit [ADDR_BITS-1:0] pc; |
| 68 | bit [3:0] opcode; | 83 | bit [3:0] opcode; |
| 69 | bit [7:0] operand; | 84 | bit [7:0] operand; |
| @@ -84,33 +99,33 @@ enum | |||
| 84 | 99 | ||
| 85 | always_ff @(posedge clk) begin | 100 | always_ff @(posedge clk) begin |
| 86 | if (reset) begin | 101 | if (reset) begin |
| 87 | mem_valid = 0; | 102 | mem_valid_ = 0; |
| 88 | rx_ready = 0; | 103 | rx_ready_ = 0; |
| 89 | tx_valid = 0; | 104 | tx_valid_ = 0; |
| 90 | tx_data = 0; | 105 | tx_data_ = 0; |
| 91 | pc = 0; | 106 | pc = 0; |
| 92 | acc = 0; | 107 | acc = 0; |
| 93 | state = state.first; | 108 | state = state.first; |
| 94 | end else begin | 109 | end else begin |
| 95 | if (`tx_ready) tx_valid = 0; | 110 | if (tx_ready_) tx_valid_ = 0; |
| 96 | 111 | ||
| 97 | case (state) | 112 | case (state) |
| 98 | FETCH: begin | 113 | FETCH: begin |
| 99 | mem_valid = 1; | 114 | mem_valid_ = 1; |
| 100 | mem_address_ = pc; | 115 | mem_address_ = pc; |
| 101 | mem_write = 0; | 116 | mem_write_ = 0; |
| 102 | if (`mem_ready) begin | 117 | if (mem_ready_) begin |
| 103 | state = DECODE; | 118 | state = DECODE; |
| 104 | ++pc; | 119 | ++pc; |
| 105 | end | 120 | end |
| 106 | end | 121 | end |
| 107 | 122 | ||
| 108 | DECODE: begin | 123 | DECODE: begin |
| 109 | mem_valid = 0; | 124 | mem_valid_ = 0; |
| 110 | mem_write = 0; | 125 | mem_write_ = 0; |
| 111 | if (`mem_read_valid) begin | 126 | if (mem_read_valid_) begin |
| 112 | state = FETCH; | 127 | state = FETCH; |
| 113 | {opcode, operand} = `mem_read_data; | 128 | {opcode, operand} = mem_read_data_; |
| 114 | sign_extended_operand = {{(DATA_BITS-8){operand[7]}}, operand}; | 129 | sign_extended_operand = {{(DATA_BITS-8){operand[7]}}, operand}; |
| 115 | case (opcode) | 130 | case (opcode) |
| 116 | 'h0: begin | 131 | 'h0: begin |
| @@ -135,7 +150,7 @@ always_ff @(posedge clk) begin | |||
| 135 | end | 150 | end |
| 136 | end | 151 | end |
| 137 | 'h6: begin | 152 | 'h6: begin |
| 138 | mem_write_data = acc % 10 + 'h30; | 153 | mem_write_data_ = acc % 10 + 'h30; |
| 139 | acc = acc / 10; | 154 | acc = acc / 10; |
| 140 | address = {7'b0, operand[6:0]}; | 155 | address = {7'b0, operand[6:0]}; |
| 141 | state = operand[7] ? INDIRECT : AGEN; | 156 | state = operand[7] ? INDIRECT : AGEN; |
| @@ -145,70 +160,70 @@ always_ff @(posedge clk) begin | |||
| 145 | end | 160 | end |
| 146 | 161 | ||
| 147 | INDIRECT: begin | 162 | INDIRECT: begin |
| 148 | mem_valid = 1; | 163 | mem_valid_ = 1; |
| 149 | mem_write = 0; | 164 | mem_write_ = 0; |
| 150 | mem_address = address; | 165 | mem_address_ = address; |
| 151 | state = `mem_ready ? INDIRECTED : INDIRECT; | 166 | state = mem_ready_ ? INDIRECTED : INDIRECT; |
| 152 | end | 167 | end |
| 153 | 168 | ||
| 154 | INDIRECTED: begin | 169 | INDIRECTED: begin |
| 155 | if (`mem_ready) begin | 170 | if (mem_ready_) begin |
| 156 | mem_valid = 0; | 171 | mem_valid_ = 0; |
| 157 | mem_write = 0; | 172 | mem_write_ = 0; |
| 158 | end | 173 | end |
| 159 | if (`mem_read_valid) begin | 174 | if (mem_read_valid_) begin |
| 160 | address = {{(ADDR_BITS - DATA_BITS){1'b0}}, `mem_read_data}; | 175 | address = {{(ADDR_BITS - DATA_BITS){1'b0}}, mem_read_data_}; |
| 161 | state = AGEN; | 176 | state = AGEN; |
| 162 | end | 177 | end |
| 163 | end | 178 | end |
| 164 | 179 | ||
| 165 | AGEN: begin | 180 | AGEN: begin |
| 166 | mem_valid = 0; | 181 | mem_valid_ = 0; |
| 167 | mem_write = 0; | 182 | mem_write_ = 0; |
| 168 | state = FETCH; | 183 | state = FETCH; |
| 169 | case (opcode) | 184 | case (opcode) |
| 170 | 'h2: begin | 185 | 'h2: begin |
| 171 | mem_valid = 1; | 186 | mem_valid_ = 1; |
| 172 | mem_address = address; | 187 | mem_address_ = address; |
| 173 | state = `mem_ready ? MEMORY : AGEN; | 188 | state = mem_ready_ ? MEMORY : AGEN; |
| 174 | end | 189 | end |
| 175 | 'h3: begin | 190 | 'h3: begin |
| 176 | mem_valid = 1; | 191 | mem_valid_ = 1; |
| 177 | mem_address = address; | 192 | mem_address_ = address; |
| 178 | mem_write = 1; | 193 | mem_write_ = 1; |
| 179 | mem_write_data = acc; | 194 | mem_write_data_ = acc; |
| 180 | state = `mem_ready ? FETCH : AGEN; | 195 | state = mem_ready_ ? FETCH : AGEN; |
| 181 | end | 196 | end |
| 182 | 'h5: pc = address; | 197 | 'h5: pc = address; |
| 183 | 'h6: begin | 198 | 'h6: begin |
| 184 | mem_valid = 1; | 199 | mem_valid_ = 1; |
| 185 | mem_address = address; | 200 | mem_address_ = address; |
| 186 | mem_write = 1; | 201 | mem_write_ = 1; |
| 187 | state = `mem_ready ? FETCH : AGEN; | 202 | state = mem_ready_ ? FETCH : AGEN; |
| 188 | end | 203 | end |
| 189 | endcase | 204 | endcase |
| 190 | end | 205 | end |
| 191 | 206 | ||
| 192 | MEMORY: begin | 207 | MEMORY: begin |
| 193 | if (`mem_ready) begin | 208 | if (mem_ready_) begin |
| 194 | mem_valid = 0; | 209 | mem_valid_ = 0; |
| 195 | mem_write = 0; | 210 | mem_write_ = 0; |
| 196 | end | 211 | end |
| 197 | state = FETCH; | 212 | state = FETCH; |
| 198 | case (opcode) | 213 | case (opcode) |
| 199 | 'h0: begin | 214 | 'h0: begin |
| 200 | if (operand[6]) begin | 215 | if (operand[6]) begin |
| 201 | if (tx_valid) begin | 216 | if (tx_valid_) begin |
| 202 | state = MEMORY; | 217 | state = MEMORY; |
| 203 | end else begin | 218 | end else begin |
| 204 | tx_valid = 1; | 219 | tx_valid_ = 1; |
| 205 | tx_data = acc[7:0]; | 220 | tx_data_ = acc[7:0]; |
| 206 | end | 221 | end |
| 207 | end | 222 | end |
| 208 | end | 223 | end |
| 209 | 'h2: begin | 224 | 'h2: begin |
| 210 | if (`mem_read_valid) begin | 225 | if (mem_read_valid_) begin |
| 211 | acc = acc + `mem_read_data; | 226 | acc = acc + mem_read_data_; |
| 212 | end else begin | 227 | end else begin |
| 213 | state = MEMORY; | 228 | state = MEMORY; |
| 214 | end | 229 | end |
diff --git a/hdl/util.svh b/hdl/util.svh index db5e4e6..fa6ddc5 100644 --- a/hdl/util.svh +++ b/hdl/util.svh | |||
| @@ -1,5 +1,2 @@ | |||
| 1 | `ifdef SYNTHESIS | 1 | `define input(x) type(x) x``_; assign x``_ = x; |
| 2 | `define past(x) x | 2 | `define output(x) type(x) x``_; assign x = x``_; |
| 3 | `else | ||
| 4 | `define past(x) $sampled(x) | ||
| 5 | `endif | ||
