diff options
| author | Julian Blake Kongslie | 2022-02-27 17:21:05 -0800 |
|---|---|---|
| committer | Julian Blake Kongslie | 2022-02-27 17:21:05 -0800 |
| commit | 0553c4839c06011bd044f69b4913e5c793fdd2ec (patch) | |
| tree | d11e69863532621fe1fa55cc7e8aa2a8cfa3b727 /hdl | |
| download | multipdp8-0553c4839c06011bd044f69b4913e5c793fdd2ec.tar.xz | |
Initial commit.
Diffstat (limited to 'hdl')
| -rw-r--r-- | hdl/command_parser.sv | 109 | ||||
| -rw-r--r-- | hdl/core.sv | 856 | ||||
| -rw-r--r-- | hdl/defs.svh | 58 | ||||
| -rw-r--r-- | hdl/echo_arbiter.sv | 64 | ||||
| -rw-r--r-- | hdl/front_panel.sv | 211 | ||||
| -rw-r--r-- | hdl/pll.sv | 126 | ||||
| -rw-r--r-- | hdl/ram_controller.sv | 240 | ||||
| -rw-r--r-- | hdl/result_printer.sv | 71 | ||||
| -rw-r--r-- | hdl/top.sv | 298 |
9 files changed, 2033 insertions, 0 deletions
diff --git a/hdl/command_parser.sv b/hdl/command_parser.sv new file mode 100644 index 0000000..5c49db9 --- /dev/null +++ b/hdl/command_parser.sv | |||
| @@ -0,0 +1,109 @@ | |||
| 1 | `include "defs.svh" | ||
| 2 | |||
| 3 | module command_parser | ||
| 4 | #( TAG = 0 | ||
| 5 | ) ( input bit clock | ||
| 6 | , input bit reset | ||
| 7 | |||
| 8 | , output bit uart_ready | ||
| 9 | , input bit uart_valid | ||
| 10 | , input uart_byte_t uart_data | ||
| 11 | |||
| 12 | , input bit echo_ready | ||
| 13 | , output bit echo_valid | ||
| 14 | , output uart_byte_t echo_data | ||
| 15 | |||
| 16 | , input bit command_ready | ||
| 17 | , output bit command_valid | ||
| 18 | , output ram_command_t command_data | ||
| 19 | ); | ||
| 20 | |||
| 21 | bit input_byte_valid; | ||
| 22 | uart_byte_t input_byte; | ||
| 23 | |||
| 24 | (* syn_encoding = "one-hot" *) enum int unsigned | ||
| 25 | { READ_ADDRESS_OR_COMMAND | ||
| 26 | , READ_DATA | ||
| 27 | } state; | ||
| 28 | |||
| 29 | always @(posedge clock) begin | ||
| 30 | if (reset) begin | ||
| 31 | uart_ready = 0; | ||
| 32 | command_valid = 0; | ||
| 33 | input_byte_valid = 0; | ||
| 34 | input_byte = 0; | ||
| 35 | state = state.first; | ||
| 36 | end else begin | ||
| 37 | if (echo_ready) echo_valid = 0; | ||
| 38 | if (command_ready && command_valid) begin | ||
| 39 | command_valid = 0; | ||
| 40 | command_data.address = 0; | ||
| 41 | command_data.write = 0; | ||
| 42 | for (int i = 0; i < `RAM_LINE_WORDS; i = i + 1) begin | ||
| 43 | command_data.data[i] = 0; | ||
| 44 | command_data.mask[i] = ~0; | ||
| 45 | end | ||
| 46 | command_data.tag = TAG; | ||
| 47 | end | ||
| 48 | if (uart_ready && uart_valid) begin | ||
| 49 | echo_valid = 1; | ||
| 50 | echo_data = uart_data; | ||
| 51 | input_byte_valid = 1; | ||
| 52 | input_byte = uart_data; | ||
| 53 | end | ||
| 54 | |||
| 55 | if (!command_valid && input_byte_valid) begin | ||
| 56 | case (state) | ||
| 57 | |||
| 58 | READ_ADDRESS_OR_COMMAND: begin | ||
| 59 | if (input_byte >= "0" && input_byte <= "9") begin | ||
| 60 | command_data.address = command_data.address << 4; | ||
| 61 | command_data.address[$clog2(`RAM_LINE_WORDS)+:4] = input_byte - "0"; | ||
| 62 | end else if (input_byte >= "a" && input_byte <= "f") begin | ||
| 63 | command_data.address = command_data.address << 4; | ||
| 64 | command_data.address[$clog2(`RAM_LINE_WORDS)+:4] = input_byte - "a" + 10; | ||
| 65 | end else if (input_byte >= "A" && input_byte <= "F") begin | ||
| 66 | command_data.address = command_data.address << 4; | ||
| 67 | command_data.address[$clog2(`RAM_LINE_WORDS)+:4] = input_byte - "A" + 10; | ||
| 68 | end else if (input_byte == "?") begin | ||
| 69 | command_valid = 1; | ||
| 70 | command_data.write = 0; | ||
| 71 | command_data.data = 0; | ||
| 72 | end else if (input_byte == "=") begin | ||
| 73 | command_data.write = 1; | ||
| 74 | command_data.data = 0; | ||
| 75 | state = READ_DATA; | ||
| 76 | end else begin | ||
| 77 | command_data.address = 0; | ||
| 78 | command_data.write = 0; | ||
| 79 | command_data.data = 0; | ||
| 80 | end | ||
| 81 | end | ||
| 82 | |||
| 83 | READ_DATA: begin | ||
| 84 | automatic bit [$bits(command_data.data)-1:0] flat_data = command_data.data; | ||
| 85 | flat_data = flat_data << 4; | ||
| 86 | if (input_byte >= "0" && input_byte <= "9") begin | ||
| 87 | flat_data[3:0] = input_byte - "0"; | ||
| 88 | command_data.data = flat_data; | ||
| 89 | end else if (input_byte >= "a" && input_byte <= "f") begin | ||
| 90 | flat_data[3:0] = input_byte - "a" + 10; | ||
| 91 | command_data.data = flat_data; | ||
| 92 | end else if (input_byte >= "A" && input_byte <= "F") begin | ||
| 93 | flat_data[3:0] = input_byte - "A" + 10; | ||
| 94 | command_data.data = flat_data; | ||
| 95 | end else begin | ||
| 96 | command_valid = 1; | ||
| 97 | state = state.first; | ||
| 98 | end | ||
| 99 | end | ||
| 100 | |||
| 101 | endcase | ||
| 102 | input_byte_valid = 0; | ||
| 103 | end | ||
| 104 | |||
| 105 | uart_ready = !echo_valid && !input_byte_valid; | ||
| 106 | end | ||
| 107 | end | ||
| 108 | |||
| 109 | endmodule | ||
diff --git a/hdl/core.sv b/hdl/core.sv new file mode 100644 index 0000000..17b753d --- /dev/null +++ b/hdl/core.sv | |||
| @@ -0,0 +1,856 @@ | |||
| 1 | `ifdef SYNTHESIS | ||
| 2 | `define lag(x) x | ||
| 3 | `else | ||
| 4 | `define lag(x) $past(x) | ||
| 5 | `endif | ||
| 6 | |||
| 7 | module mem | ||
| 8 | ( input bit clk | ||
| 9 | , input bit reset | ||
| 10 | |||
| 11 | , output bit ready | ||
| 12 | , input bit valid | ||
| 13 | , input bit write | ||
| 14 | , input bit [ADDR_BITS-1:0] address | ||
| 15 | , input bit [DATA_BITS-1:0] write_data | ||
| 16 | |||
| 17 | , output bit read_valid | ||
| 18 | , output bit [DATA_BITS-1:0] read_data | ||
| 19 | ); | ||
| 20 | |||
| 21 | parameter ADDR_BITS; | ||
| 22 | parameter DATA_BITS; | ||
| 23 | parameter INIT_FILE; | ||
| 24 | |||
| 25 | bit [DATA_BITS-1:0] storage [0:(1<<ADDR_BITS)-1]; | ||
| 26 | initial $readmemh(INIT_FILE, storage); | ||
| 27 | |||
| 28 | always_ff @(posedge clk) begin | ||
| 29 | if (reset) begin | ||
| 30 | ready = 0; | ||
| 31 | read_valid = 0; | ||
| 32 | end else begin | ||
| 33 | read_valid = 0; | ||
| 34 | if (ready && `lag(valid)) begin | ||
| 35 | if (`lag(write)) begin | ||
| 36 | storage[`lag(address)] = `lag(write_data); | ||
| 37 | end else begin | ||
| 38 | read_valid = 1; | ||
| 39 | read_data = storage[`lag(address)]; | ||
| 40 | end | ||
| 41 | end | ||
| 42 | ready = 1; | ||
| 43 | end | ||
| 44 | end | ||
| 45 | |||
| 46 | endmodule | ||
| 47 | |||
| 48 | module core | ||
| 49 | #( ADDR_BITS = 15 | ||
| 50 | , DATA_BITS = 12 | ||
| 51 | ) | ||
| 52 | ( input bit clk | ||
| 53 | , input bit reset | ||
| 54 | |||
| 55 | , input bit [2:0] switch_df | ||
| 56 | , input bit [2:0] switch_if | ||
| 57 | , input bit [ADDR_BITS-3-1:0] switch_sr | ||
| 58 | , input bit switch_start | ||
| 59 | , input bit switch_load_add | ||
| 60 | , input bit switch_dep | ||
| 61 | , input bit switch_exam | ||
| 62 | , input bit switch_cont | ||
| 63 | , input bit switch_stop | ||
| 64 | , input bit switch_sing_step | ||
| 65 | , input bit switch_sing_inst | ||
| 66 | |||
| 67 | // verilator lint_off UNDRIVEN | ||
| 68 | , output bit [ADDR_BITS-3-1:0] led_pc | ||
| 69 | , output bit [ADDR_BITS-3-1:0] led_memaddr | ||
| 70 | , output bit [DATA_BITS-1:0] led_memdata | ||
| 71 | , output bit [DATA_BITS-1:0] led_acc | ||
| 72 | , output bit [DATA_BITS-1:0] led_mq | ||
| 73 | , output bit led_and | ||
| 74 | , output bit led_tad | ||
| 75 | , output bit led_isz | ||
| 76 | , output bit led_dca | ||
| 77 | , output bit led_jms | ||
| 78 | , output bit led_jmp | ||
| 79 | , output bit led_iot | ||
| 80 | , output bit led_opr | ||
| 81 | , output bit led_fetch | ||
| 82 | , output bit led_execute | ||
| 83 | , output bit led_defer | ||
| 84 | , output bit led_word_count | ||
| 85 | , output bit led_current_address | ||
| 86 | , output bit led_break | ||
| 87 | , output bit led_ion | ||
| 88 | , output bit led_pause | ||
| 89 | , output bit led_run | ||
| 90 | , output bit [4:0] led_step_counter | ||
| 91 | , output bit [2:0] led_df | ||
| 92 | , output bit [2:0] led_if | ||
| 93 | , output bit led_link | ||
| 94 | // verilator lint_on UNDRIVEN | ||
| 95 | ); | ||
| 96 | |||
| 97 | `ifndef SYNTHESIS | ||
| 98 | integer pctrace; | ||
| 99 | initial pctrace = $fopen("trace.pcs", "w"); | ||
| 100 | |||
| 101 | integer eventtrace; | ||
| 102 | initial eventtrace = $fopen("trace.events", "r"); | ||
| 103 | |||
| 104 | // Event trace file format: lines of the form | ||
| 105 | // instruction-count skip interrupt | ||
| 106 | // Events are triggered before the corresponding instruction | ||
| 107 | // Skip opcodes: | ||
| 108 | // 0 Do not override skip behaviour of this instruction | ||
| 109 | // 1 Force this instruction to "not skip" | ||
| 110 | // 2 Force this instruction to "skip" | ||
| 111 | // Interrupt opcodes: | ||
| 112 | // 0 Do not force an interrupt this instruction | ||
| 113 | // 1 Force an interrupt this instruction | ||
| 114 | // The first instruction has instruction count 1 | ||
| 115 | |||
| 116 | integer unsigned nextevent = ~0; | ||
| 117 | integer force_skip = 0; | ||
| 118 | bit force_interrupt = 0; | ||
| 119 | initial if (eventtrace != 0) $fscanf(eventtrace, "%d %d %d", nextevent, force_skip, force_interrupt); | ||
| 120 | initial $display("nextevent=%d force_skip=%d force_interrupt=%d", nextevent, force_skip, force_interrupt); | ||
| 121 | `endif | ||
| 122 | |||
| 123 | bit run; | ||
| 124 | bit int_enable; | ||
| 125 | bit int_delay; | ||
| 126 | bit int_request; | ||
| 127 | |||
| 128 | bit switch_start_observed; | ||
| 129 | bit switch_load_add_observed; | ||
| 130 | bit switch_dep_observed; | ||
| 131 | bit switch_exam_observed; | ||
| 132 | bit switch_cont_observed; | ||
| 133 | |||
| 134 | assign led_run = run; | ||
| 135 | assign led_ion = int_enable; | ||
| 136 | |||
| 137 | bit mem_ready; | ||
| 138 | bit mem_valid; | ||
| 139 | bit mem_write; | ||
| 140 | bit [ADDR_BITS-1:0] mem_address; | ||
| 141 | bit [DATA_BITS-1:0] mem_write_data; | ||
| 142 | assign led_current_address = mem_valid; | ||
| 143 | |||
| 144 | assign led_memaddr = mem_address[ADDR_BITS-3-1:0]; | ||
| 145 | |||
| 146 | bit mem_read_valid; | ||
| 147 | bit [DATA_BITS-1:0] mem_read_data; | ||
| 148 | |||
| 149 | mem | ||
| 150 | #( .ADDR_BITS(ADDR_BITS) | ||
| 151 | , .DATA_BITS(DATA_BITS) | ||
| 152 | // , .INIT_FILE("mem/focal69.loaded.hex") | ||
| 153 | , .INIT_FILE("build/mem/hello.hex") | ||
| 154 | ) | ||
| 155 | memory | ||
| 156 | ( .clk(clk) | ||
| 157 | , .reset(reset) | ||
| 158 | |||
| 159 | , .ready(mem_ready) | ||
| 160 | , .valid(mem_valid) | ||
| 161 | , .address(mem_address) | ||
| 162 | , .write(mem_write) | ||
| 163 | , .write_data(mem_write_data) | ||
| 164 | |||
| 165 | , .read_valid(mem_read_valid) | ||
| 166 | , .read_data(mem_read_data) | ||
| 167 | ); | ||
| 168 | |||
| 169 | bit rx_ready; | ||
| 170 | bit rx_valid; | ||
| 171 | bit [7:0] rx_data; | ||
| 172 | |||
| 173 | bit tx_ready; | ||
| 174 | bit tx_valid; | ||
| 175 | bit [7:0] tx_data; | ||
| 176 | |||
| 177 | alt_jtag_atlantic | ||
| 178 | #( .INSTANCE_ID(1) | ||
| 179 | , .LOG2_RXFIFO_DEPTH(6) | ||
| 180 | , .LOG2_TXFIFO_DEPTH(6) | ||
| 181 | , .SLD_AUTO_INSTANCE_INDEX("NO") | ||
| 182 | ) uart | ||
| 183 | ( .clk(clk) | ||
| 184 | , .rst_n(!reset) | ||
| 185 | |||
| 186 | , .r_dat(tx_data) | ||
| 187 | , .r_val(tx_valid) | ||
| 188 | , .r_ena(tx_ready) | ||
| 189 | |||
| 190 | , .t_dat(rx_data) | ||
| 191 | , .t_dav(rx_data) | ||
| 192 | , .t_ena(rx_valid) | ||
| 193 | ); | ||
| 194 | |||
| 195 | bit [ADDR_BITS-3-1:7] page; | ||
| 196 | |||
| 197 | bit [2:0] data_field; | ||
| 198 | bit [2:0] data_field_saved; | ||
| 199 | bit [2:0] inst_field; | ||
| 200 | bit [2:0] inst_field_buffer; | ||
| 201 | bit [2:0] inst_field_saved; | ||
| 202 | bit [ADDR_BITS-3-1:0] pc; | ||
| 203 | bit [ADDR_BITS-3-1:0] next_pc; | ||
| 204 | assign led_pc = pc; | ||
| 205 | bit [2:0] opcode; | ||
| 206 | bit [8:0] operand; | ||
| 207 | bit [DATA_BITS-1:0] acc; | ||
| 208 | bit link; | ||
| 209 | |||
| 210 | assign led_df = data_field; | ||
| 211 | assign led_if = inst_field; | ||
| 212 | |||
| 213 | assign led_acc = acc; | ||
| 214 | assign led_link = link; | ||
| 215 | |||
| 216 | assign led_and = opcode == 0; | ||
| 217 | assign led_tad = opcode == 1; | ||
| 218 | assign led_isz = opcode == 2; | ||
| 219 | assign led_dca = opcode == 3; | ||
| 220 | assign led_jms = opcode == 4; | ||
| 221 | assign led_jmp = opcode == 5; | ||
| 222 | assign led_iot = opcode == 6; | ||
| 223 | assign led_opr = opcode == 7; | ||
| 224 | |||
| 225 | bit tti_int_enable; | ||
| 226 | bit tti_valid; | ||
| 227 | bit [DATA_BITS-1:0] tti_data; | ||
| 228 | |||
| 229 | bit [15:0] tto_delay; | ||
| 230 | bit tto_int_enable; | ||
| 231 | bit tto_flag; | ||
| 232 | bit tto_flag_old; | ||
| 233 | |||
| 234 | bit i; | ||
| 235 | bit z; | ||
| 236 | bit [6:0] wip; | ||
| 237 | bit [ADDR_BITS-1:0] address; | ||
| 238 | |||
| 239 | bit can_skip; | ||
| 240 | bit skip; | ||
| 241 | bit injected_instruction; | ||
| 242 | |||
| 243 | `ifndef SYNTHESIS | ||
| 244 | integer unsigned instcount = 1; | ||
| 245 | `endif | ||
| 246 | |||
| 247 | assign int_request = 0 | ||
| 248 | || (tti_int_enable && tti_valid) | ||
| 249 | || (tto_int_enable && tto_flag && !tto_flag_old) | ||
| 250 | ; | ||
| 251 | |||
| 252 | enum | ||
| 253 | { FETCH | ||
| 254 | , DECODE | ||
| 255 | , INDIRECT | ||
| 256 | , INDIRECTED | ||
| 257 | , PREINC | ||
| 258 | , AGEN | ||
| 259 | , EXEC | ||
| 260 | , MEMWAIT | ||
| 261 | , HALT | ||
| 262 | , DEPOSIT | ||
| 263 | , RETIRE | ||
| 264 | } state; | ||
| 265 | |||
| 266 | assign led_fetch = state == FETCH; | ||
| 267 | assign led_execute = state == DECODE || state == AGEN || state == EXEC; | ||
| 268 | assign led_defer = state == INDIRECT || state == INDIRECTED || state == PREINC; | ||
| 269 | assign led_pause = state == MEMWAIT || state == HALT; | ||
| 270 | |||
| 271 | always_ff @(posedge clk) begin | ||
| 272 | if (reset) begin | ||
| 273 | `ifdef SYNTHESIS | ||
| 274 | run = 0; | ||
| 275 | `else | ||
| 276 | run = 1; | ||
| 277 | `endif | ||
| 278 | int_enable = 0; | ||
| 279 | int_delay = 0; | ||
| 280 | switch_start_observed = 0; | ||
| 281 | switch_load_add_observed = 0; | ||
| 282 | switch_dep_observed = 0; | ||
| 283 | switch_exam_observed = 0; | ||
| 284 | switch_cont_observed = 0; | ||
| 285 | mem_valid = 0; | ||
| 286 | rx_ready = 0; | ||
| 287 | tx_valid = 0; | ||
| 288 | tto_delay = 0; | ||
| 289 | tto_flag = 1; | ||
| 290 | tto_flag_old = 1; | ||
| 291 | tx_data = 0; | ||
| 292 | data_field = 0; | ||
| 293 | data_field_saved = 0; | ||
| 294 | inst_field = 0; | ||
| 295 | inst_field_buffer = 0; | ||
| 296 | inst_field_saved = 0; | ||
| 297 | pc = 'o200; | ||
| 298 | acc = 0; | ||
| 299 | link = 1; | ||
| 300 | tti_int_enable = 1; | ||
| 301 | tto_int_enable = 1; | ||
| 302 | tti_valid = 0; | ||
| 303 | state = state.first; | ||
| 304 | end else begin | ||
| 305 | if (switch_start && !switch_start_observed) begin | ||
| 306 | switch_start_observed = 1; | ||
| 307 | run = 1; | ||
| 308 | int_enable = 0; | ||
| 309 | int_delay = 0; | ||
| 310 | mem_valid = 0; | ||
| 311 | acc = 0; | ||
| 312 | link = 1; | ||
| 313 | state = state.first; | ||
| 314 | end | ||
| 315 | |||
| 316 | if (!switch_start) | ||
| 317 | switch_start_observed = 0; | ||
| 318 | |||
| 319 | if (switch_load_add && !switch_load_add_observed) begin | ||
| 320 | switch_load_add_observed = 1; | ||
| 321 | data_field = switch_df; | ||
| 322 | inst_field = switch_if; | ||
| 323 | inst_field_buffer = switch_if; | ||
| 324 | pc = switch_sr; | ||
| 325 | end | ||
| 326 | |||
| 327 | if (!switch_load_add) | ||
| 328 | switch_load_add_observed = 0; | ||
| 329 | |||
| 330 | `ifdef HISTORIC_SWITCH_BEHAVIOUR | ||
| 331 | if (switch_dep) | ||
| 332 | switch_dep_observed = 1; | ||
| 333 | |||
| 334 | if (!switch_dep && switch_dep_observed) begin | ||
| 335 | `else | ||
| 336 | if (switch_dep && !switch_dep_observed) begin | ||
| 337 | switch_dep_observed = 1; | ||
| 338 | `endif | ||
| 339 | state = DEPOSIT; | ||
| 340 | mem_valid = 1; | ||
| 341 | mem_address = {inst_field, pc}; | ||
| 342 | mem_write = 1; | ||
| 343 | mem_write_data = switch_sr; | ||
| 344 | led_memdata = mem_write_data; | ||
| 345 | run = 1; | ||
| 346 | end | ||
| 347 | |||
| 348 | if (!switch_dep) | ||
| 349 | switch_dep_observed = 0; | ||
| 350 | |||
| 351 | if (switch_exam && !switch_exam_observed) begin | ||
| 352 | if (!run) begin | ||
| 353 | switch_exam_observed = 1; | ||
| 354 | state = FETCH; | ||
| 355 | run = 1; | ||
| 356 | end | ||
| 357 | end | ||
| 358 | |||
| 359 | if (!switch_exam) | ||
| 360 | switch_exam_observed = 0; | ||
| 361 | |||
| 362 | if (switch_cont && !switch_cont_observed) begin | ||
| 363 | switch_cont_observed = 1; | ||
| 364 | run = 1; | ||
| 365 | end | ||
| 366 | |||
| 367 | if (!switch_cont) | ||
| 368 | switch_cont_observed = 0; | ||
| 369 | |||
| 370 | if (switch_stop) | ||
| 371 | run = 0; | ||
| 372 | |||
| 373 | if (`lag(tx_ready)) begin | ||
| 374 | if (tx_valid) | ||
| 375 | tto_flag = 1; | ||
| 376 | tx_valid = 0; | ||
| 377 | end | ||
| 378 | if (tto_delay == 1) | ||
| 379 | tx_valid = 1; | ||
| 380 | if (tto_delay != 0) | ||
| 381 | --tto_delay; | ||
| 382 | if (rx_ready && `lag(rx_valid)) begin | ||
| 383 | tti_valid = 1; | ||
| 384 | tti_data = {4'b0, 1'b1, `lag(rx_data[6:0])}; | ||
| 385 | if (tti_data[6:0] == 7'h0a) | ||
| 386 | tti_data[6:0] = 7'h0d; | ||
| 387 | else if (tti_data[6:0] == 7'h1b) | ||
| 388 | tti_data[6:0] = 7'h03; | ||
| 389 | end | ||
| 390 | |||
| 391 | if (run) begin | ||
| 392 | case (state) | ||
| 393 | FETCH: begin | ||
| 394 | can_skip = 0; | ||
| 395 | skip = 0; | ||
| 396 | injected_instruction = 0; | ||
| 397 | mem_valid = 1; | ||
| 398 | mem_address = {inst_field, pc}; | ||
| 399 | mem_write = 0; | ||
| 400 | if (`lag(mem_ready)) begin | ||
| 401 | state = DECODE; | ||
| 402 | page = pc[ADDR_BITS-3-1:7]; | ||
| 403 | next_pc = pc + 1; | ||
| 404 | end | ||
| 405 | end | ||
| 406 | |||
| 407 | DECODE: begin | ||
| 408 | automatic bit go; | ||
| 409 | go = 0; | ||
| 410 | mem_valid = 0; | ||
| 411 | mem_write = 0; | ||
| 412 | `ifdef SYNTHESIS | ||
| 413 | if (!switch_exam_observed && (int_enable && int_request)) begin | ||
| 414 | `else | ||
| 415 | if (!switch_exam_observed && ((nextevent == ~0 && int_enable && int_request) || (instcount == nextevent && force_interrupt))) begin | ||
| 416 | if (! int_enable) | ||
| 417 | $display("ERROR: forced interrupt at a point where architecturally interrupts are disabled"); | ||
| 418 | `endif | ||
| 419 | $display("taking interrupt at instcount=%d", instcount); | ||
| 420 | int_enable = 0; | ||
| 421 | int_delay = 0; | ||
| 422 | data_field_saved = data_field; | ||
| 423 | inst_field_saved = inst_field; | ||
| 424 | data_field = 0; | ||
| 425 | inst_field = 0; | ||
| 426 | inst_field_buffer = 0; | ||
| 427 | tto_flag_old = tto_flag; | ||
| 428 | opcode = 'o4; | ||
| 429 | operand = 'o000; | ||
| 430 | next_pc = pc; | ||
| 431 | injected_instruction = 1; | ||
| 432 | go = 1; | ||
| 433 | end else if (`lag(mem_read_valid)) begin | ||
| 434 | state = RETIRE; | ||
| 435 | led_memdata = `lag(mem_read_data); | ||
| 436 | {opcode, operand} = `lag(mem_read_data); | ||
| 437 | if (switch_exam_observed) begin | ||
| 438 | run = 0; | ||
| 439 | end else begin | ||
| 440 | go = 1; | ||
| 441 | end | ||
| 442 | end | ||
| 443 | if (go) begin | ||
| 444 | int_enable = int_delay; | ||
| 445 | {i, z, wip} = operand; | ||
| 446 | if (z) | ||
| 447 | address = {inst_field, page, wip}; | ||
| 448 | else | ||
| 449 | address = {inst_field, 5'b0, wip}; | ||
| 450 | $display("%d %o: %o%o", instcount, pc, opcode, operand); | ||
| 451 | case (opcode) | ||
| 452 | 'o0, 'o1, 'o2: state = i ? INDIRECT : AGEN; | ||
| 453 | 'o3, 'o4: state = i ? INDIRECT : EXEC; | ||
| 454 | 'o5: begin | ||
| 455 | if (i) begin | ||
| 456 | state = INDIRECT; | ||
| 457 | end else begin | ||
| 458 | next_pc = address[ADDR_BITS-3-1:0]; | ||
| 459 | inst_field = inst_field_buffer; | ||
| 460 | end | ||
| 461 | end | ||
| 462 | 'o7: begin | ||
| 463 | casez (operand) | ||
| 464 | 'b0????????: begin | ||
| 465 | automatic bit cla, cll, cma, cml, rar, ral, bsw, iac; | ||
| 466 | {cla, cll, cma, cml, rar, ral, bsw, iac} = operand[7:0]; | ||
| 467 | if (cla) acc = 0; | ||
| 468 | if (cll) link = 0; | ||
| 469 | if (cma) acc = ~acc; | ||
| 470 | if (cml) link = ~link; | ||
| 471 | if (iac) {link, acc} += 1; | ||
| 472 | if (rar && !ral) begin | ||
| 473 | {link, acc} = {acc[0], link, acc[11:1]}; | ||
| 474 | if (bsw) {link, acc} = {acc[0], link, acc[11:1]}; | ||
| 475 | end | ||
| 476 | if (ral && !rar) begin | ||
| 477 | {link, acc} = {acc, link}; | ||
| 478 | if (bsw) {link, acc} = {acc, link}; | ||
| 479 | end | ||
| 480 | if (bsw && !(rar || ral)) acc = {acc[5:0], acc[11:6]}; | ||
| 481 | end | ||
| 482 | 'b1????0??0: begin | ||
| 483 | automatic bit cla, sma, sza, snl, osr, hlt; | ||
| 484 | can_skip = 1; | ||
| 485 | {cla, sma, sza, snl, osr, hlt} = {operand[7:4], operand[2:1]}; | ||
| 486 | if (sma && acc[11]) skip = 1; | ||
| 487 | if (sza && acc == 0) skip = 1; | ||
| 488 | if (snl && link != 0) skip = 1; | ||
| 489 | if (cla) acc = 0; | ||
| 490 | if (osr) begin | ||
| 491 | $display("%o: unsupported front panel switch test", pc); | ||
| 492 | $finish; | ||
| 493 | end | ||
| 494 | if (hlt) state = HALT; | ||
| 495 | end | ||
| 496 | 'b1????1??0: begin | ||
| 497 | automatic bit cla, spa, sna, szl, osr, hlt; | ||
| 498 | can_skip = 1; | ||
| 499 | skip = 1; | ||
| 500 | {cla, spa, sna, szl, osr, hlt} = {operand[7:4], operand[2:1]}; | ||
| 501 | if (spa && acc[11]) skip = 0; | ||
| 502 | if (sna && acc == 0) skip = 0; | ||
| 503 | if (szl && link != 0) skip = 0; | ||
| 504 | if (cla) acc = 0; | ||
| 505 | if (osr) begin | ||
| 506 | $display("%o: unsupported front panel switch test", pc); | ||
| 507 | $finish; | ||
| 508 | end | ||
| 509 | if (hlt) state = HALT; | ||
| 510 | end | ||
| 511 | default: begin | ||
| 512 | $display("%o: decoded unknown opcode %o %o", pc, opcode, operand); | ||
| 513 | $finish; | ||
| 514 | end | ||
| 515 | endcase | ||
| 516 | end | ||
| 517 | 'o6: begin | ||
| 518 | case (operand[8:6]) | ||
| 519 | 'o0: begin | ||
| 520 | case (operand[5:3]) | ||
| 521 | 'o0: begin | ||
| 522 | case (operand[2:0]) | ||
| 523 | 'o0: begin | ||
| 524 | can_skip = 1; | ||
| 525 | if (int_enable) | ||
| 526 | skip = 1; | ||
| 527 | int_enable = 0; | ||
| 528 | int_delay = 0; | ||
| 529 | end | ||
| 530 | 'o1: int_delay = 1; | ||
| 531 | 'o2: begin | ||
| 532 | int_enable = 0; | ||
| 533 | int_delay = 0; | ||
| 534 | end | ||
| 535 | 'o3: begin | ||
| 536 | can_skip = 1; | ||
| 537 | if (int_request) | ||
| 538 | skip = 1; | ||
| 539 | end | ||
| 540 | 'o4: acc = {link, 1'b0/*gt*/, int_request, 1'b0/*ii*/, int_enable, 1'b0/*u*/, 3'b0/*if*/, 3'b0/*df*/}; | ||
| 541 | 'o5: begin | ||
| 542 | link = acc[11]; | ||
| 543 | if (acc[7]) begin | ||
| 544 | int_delay = 1; | ||
| 545 | end else begin | ||
| 546 | int_enable = 0; | ||
| 547 | int_delay = 0; | ||
| 548 | end | ||
| 549 | end | ||
| 550 | 'o7: begin | ||
| 551 | int_enable = 0; | ||
| 552 | int_delay = 0; | ||
| 553 | acc = 0; | ||
| 554 | link = 1; | ||
| 555 | tx_valid = 0; | ||
| 556 | tto_flag = 1; | ||
| 557 | tto_flag_old = 1; | ||
| 558 | tti_valid = 0; | ||
| 559 | end | ||
| 560 | default: $display("%o: unsupported 600%o op", pc, operand[2:0]); | ||
| 561 | endcase | ||
| 562 | end | ||
| 563 | 'o3: begin | ||
| 564 | case (operand[2:0]) | ||
| 565 | 'o0: tti_valid = 0; | ||
| 566 | 'o1: begin | ||
| 567 | can_skip = 1; | ||
| 568 | if (tti_valid) skip = 1; | ||
| 569 | end | ||
| 570 | 'o2: begin | ||
| 571 | acc = 0; | ||
| 572 | tti_valid = 0; | ||
| 573 | end | ||
| 574 | 'o4: begin | ||
| 575 | acc |= tti_data; | ||
| 576 | end | ||
| 577 | 'o5: begin | ||
| 578 | tti_int_enable = acc[0]; | ||
| 579 | end | ||
| 580 | 'o6: begin | ||
| 581 | acc = tti_data; | ||
| 582 | tti_valid = 0; | ||
| 583 | end | ||
| 584 | default: begin | ||
| 585 | $display("%o: unsupported keyboard op %o", pc, operand[2:0]); | ||
| 586 | $finish; | ||
| 587 | end | ||
| 588 | endcase | ||
| 589 | end | ||
| 590 | 'o4: begin | ||
| 591 | case (operand[2:0]) | ||
| 592 | 'o0: begin | ||
| 593 | tto_flag = 1; | ||
| 594 | tto_flag_old = 1; | ||
| 595 | end | ||
| 596 | 'o1: begin | ||
| 597 | can_skip = 1; | ||
| 598 | if (tto_flag) skip = 1; | ||
| 599 | end | ||
| 600 | 'o2: begin | ||
| 601 | tto_flag = 0; | ||
| 602 | tto_flag_old = 0; | ||
| 603 | end | ||
| 604 | 'o4: begin | ||
| 605 | tto_delay = 100; | ||
| 606 | $display("[%o] write %o", pc, acc[6:0]); | ||
| 607 | tx_data = {1'b0, acc[6:0]}; | ||
| 608 | if (tx_data == 'h8d) | ||
| 609 | tx_data = 'h8a; | ||
| 610 | end | ||
| 611 | 'o5: begin | ||
| 612 | can_skip = 1; | ||
| 613 | if (tto_flag || tti_valid) skip = 1; | ||
| 614 | end | ||
| 615 | 'o6: begin | ||
| 616 | tto_delay =100; | ||
| 617 | tto_flag = 0; | ||
| 618 | tto_flag_old = 0; | ||
| 619 | $display("[%o] write %o", pc, acc[6:0]); | ||
| 620 | tx_data = {1'b0, acc[6:0]}; | ||
| 621 | if (tx_data == 'h8d) | ||
| 622 | tx_data = 'h8a; | ||
| 623 | end | ||
| 624 | default: begin | ||
| 625 | $display("%o: unsupported tty op %o", pc, operand[2:0]); | ||
| 626 | $finish; | ||
| 627 | end | ||
| 628 | endcase | ||
| 629 | end | ||
| 630 | default: begin | ||
| 631 | $display("%o: unsupported device %o (operation %o)", pc, operand[8:3], operand[2:0]); | ||
| 632 | can_skip = 1; | ||
| 633 | end | ||
| 634 | endcase | ||
| 635 | end | ||
| 636 | 'o2: begin | ||
| 637 | if (operand[0]) | ||
| 638 | data_field = operand[5:3]; | ||
| 639 | if (operand[1]) | ||
| 640 | inst_field_buffer = operand[5:3]; | ||
| 641 | if (operand[2]) begin | ||
| 642 | if (operand[3] && operand[4]) | ||
| 643 | acc = acc | {6'b0, inst_field_saved, data_field_saved}; | ||
| 644 | else if (operand[3]) | ||
| 645 | acc = acc | {6'b0, data_field, 3'b0}; | ||
| 646 | else if (operand[4]) | ||
| 647 | acc = acc | {6'b0, inst_field, 3'b0}; | ||
| 648 | if (operand[5]) begin | ||
| 649 | data_field = data_field_saved; | ||
| 650 | inst_field_buffer = inst_field_saved; | ||
| 651 | end | ||
| 652 | end | ||
| 653 | end | ||
| 654 | default: begin | ||
| 655 | $display("%o: unsupported device %o (operation %o)", pc, operand[8:3], operand[2:0]); | ||
| 656 | can_skip = 1; | ||
| 657 | end | ||
| 658 | endcase | ||
| 659 | end | ||
| 660 | default: begin | ||
| 661 | $display("%o: decoded unknown opcode %o %o", pc, opcode, operand); | ||
| 662 | $finish; | ||
| 663 | end | ||
| 664 | endcase | ||
| 665 | end | ||
| 666 | end | ||
| 667 | |||
| 668 | INDIRECT: begin | ||
| 669 | mem_valid = 1; | ||
| 670 | mem_write = 0; | ||
| 671 | mem_address = address; | ||
| 672 | state = `lag(mem_ready) ? INDIRECTED : INDIRECT; | ||
| 673 | end | ||
| 674 | |||
| 675 | INDIRECTED: begin | ||
| 676 | if (`lag(mem_ready)) begin | ||
| 677 | mem_valid = 0; | ||
| 678 | mem_write = 0; | ||
| 679 | end | ||
| 680 | if (`lag(mem_read_valid)) begin | ||
| 681 | if (opcode != 'o5 && address[7:3] == 5'b00001) begin | ||
| 682 | led_memdata = `lag(mem_read_data); | ||
| 683 | address = {3'b0, `lag(mem_read_data)}; | ||
| 684 | address += 1; | ||
| 685 | address[ADDR_BITS-1:ADDR_BITS-3] = data_field; | ||
| 686 | state = PREINC; | ||
| 687 | end else begin | ||
| 688 | led_memdata = `lag(mem_read_data); | ||
| 689 | address = {data_field, `lag(mem_read_data)}; | ||
| 690 | case (opcode) | ||
| 691 | 'o0, 'o1, 'o2: state = AGEN; | ||
| 692 | 'o3, 'o4: state = EXEC; | ||
| 693 | 'o5: begin | ||
| 694 | next_pc = address[ADDR_BITS-3-1:0]; | ||
| 695 | $display("indirect jump to %o", next_pc); | ||
| 696 | inst_field = inst_field_buffer; | ||
| 697 | state = RETIRE; | ||
| 698 | end | ||
| 699 | endcase | ||
| 700 | end | ||
| 701 | end | ||
| 702 | end | ||
| 703 | |||
| 704 | PREINC: begin | ||
| 705 | mem_valid = 1; | ||
| 706 | mem_write = 1; | ||
| 707 | mem_write_data = address[DATA_BITS-1:0]; | ||
| 708 | led_memdata = mem_write_data; | ||
| 709 | $display("preinc [%o] <- %o", mem_address, mem_write_data); | ||
| 710 | case (opcode) | ||
| 711 | 'o0, 'o1, 'o2: state = `lag(mem_ready) ? AGEN : PREINC; | ||
| 712 | 'o3, 'o4, 'o5: state = `lag(mem_ready) ? EXEC : PREINC; | ||
| 713 | endcase | ||
| 714 | end | ||
| 715 | |||
| 716 | AGEN: begin | ||
| 717 | mem_valid = 1; | ||
| 718 | case (opcode) | ||
| 719 | 'o0, 'o1, 'o2: mem_write = 0; | ||
| 720 | endcase | ||
| 721 | mem_address = address; | ||
| 722 | state = `lag(mem_ready) ? EXEC : AGEN; | ||
| 723 | end | ||
| 724 | |||
| 725 | EXEC: begin | ||
| 726 | automatic bit stall = 0; | ||
| 727 | if (`lag(mem_ready)) begin | ||
| 728 | mem_valid = 0; | ||
| 729 | mem_write = 0; | ||
| 730 | end else if (mem_valid) begin | ||
| 731 | stall = 1; | ||
| 732 | end | ||
| 733 | case (opcode) | ||
| 734 | 'o0, 'o1, 'o2: if (! `lag(mem_read_valid)) stall = 1; | ||
| 735 | endcase | ||
| 736 | if (! stall) begin | ||
| 737 | state = RETIRE; | ||
| 738 | case (opcode) | ||
| 739 | 'o0: begin led_memdata = `lag(mem_read_data); acc &= `lag(mem_read_data); end | ||
| 740 | 'o1: begin led_memdata = `lag(mem_read_data); {link, acc} += {1'b0, `lag(mem_read_data)}; end | ||
| 741 | 'o2: begin | ||
| 742 | mem_valid = 1; | ||
| 743 | mem_address = address; | ||
| 744 | mem_write = 1; | ||
| 745 | mem_write_data = `lag(mem_read_data) + 1; | ||
| 746 | led_memdata = mem_write_data; | ||
| 747 | $display("store [%o] <- %o", mem_address, mem_write_data); | ||
| 748 | can_skip = 1; | ||
| 749 | if (mem_write_data == 0) skip = 1; | ||
| 750 | state = MEMWAIT; | ||
| 751 | end | ||
| 752 | 'o3: begin | ||
| 753 | mem_valid = 1; | ||
| 754 | mem_address = address; | ||
| 755 | mem_write = 1; | ||
| 756 | mem_write_data = acc; | ||
| 757 | led_memdata = mem_write_data; | ||
| 758 | $display("store [%o] <- %o", mem_address, mem_write_data); | ||
| 759 | acc = 0; | ||
| 760 | state = MEMWAIT; | ||
| 761 | end | ||
| 762 | 'o4: begin | ||
| 763 | mem_valid = 1; | ||
| 764 | mem_address = address; | ||
| 765 | mem_write = 1; | ||
| 766 | mem_write_data = next_pc[DATA_BITS-1:0]; | ||
| 767 | led_memdata = mem_write_data; | ||
| 768 | $display("store [%o] <- %o", mem_address, mem_write_data); | ||
| 769 | next_pc = address[ADDR_BITS-3-1:0] + 1; | ||
| 770 | inst_field = inst_field_buffer; | ||
| 771 | state = MEMWAIT; | ||
| 772 | end | ||
| 773 | 'o5: begin | ||
| 774 | next_pc = address[ADDR_BITS-3-1:0]; | ||
| 775 | inst_field = inst_field_buffer; | ||
| 776 | end | ||
| 777 | endcase | ||
| 778 | end | ||
| 779 | end | ||
| 780 | |||
| 781 | MEMWAIT: state = `lag(mem_ready) ? RETIRE : MEMWAIT; | ||
| 782 | |||
| 783 | HALT: begin | ||
| 784 | run = 0; | ||
| 785 | $display("\nhalt state reached"); | ||
| 786 | $finish; | ||
| 787 | end | ||
| 788 | |||
| 789 | DEPOSIT: begin | ||
| 790 | if (`lag(mem_ready)) begin | ||
| 791 | state = FETCH; // Not a retired instruction; go directly to decode | ||
| 792 | page = pc[ADDR_BITS-3-1:7]; | ||
| 793 | ++pc; // Not a skip; normal part of panel deposit (because we are skipping RETIRE) | ||
| 794 | run = 0; | ||
| 795 | end | ||
| 796 | end | ||
| 797 | endcase | ||
| 798 | |||
| 799 | if (state == RETIRE) begin | ||
| 800 | `ifndef SYNTHESIS | ||
| 801 | if (!injected_instruction) begin | ||
| 802 | $display("retiring pc=%o%o", inst_field, pc); | ||
| 803 | $fdisplay(pctrace, "%o%o", inst_field, pc); | ||
| 804 | end | ||
| 805 | `endif | ||
| 806 | |||
| 807 | state = FETCH; | ||
| 808 | pc = next_pc; | ||
| 809 | |||
| 810 | if (can_skip) begin | ||
| 811 | `ifndef SYNTHESIS | ||
| 812 | if (instcount == nextevent) begin | ||
| 813 | $display("checking instcount=%d force_skip=%d against inferred skip=%d", instcount, force_skip, skip); | ||
| 814 | if (force_skip == 1) | ||
| 815 | skip = 0; | ||
| 816 | else if (force_skip == 2) | ||
| 817 | skip = 1; | ||
| 818 | end | ||
| 819 | `endif | ||
| 820 | if (skip) begin | ||
| 821 | $display("skip at instcount=%d pc=%o", instcount, pc); | ||
| 822 | ++pc; | ||
| 823 | end | ||
| 824 | end | ||
| 825 | `ifndef SYNTHESIS | ||
| 826 | else if (instcount == nextevent && force_skip != 0) begin | ||
| 827 | $display("Error: forced skip at impossible boundary instcount=%d nextpc=%o", instcount, pc); | ||
| 828 | $finish; | ||
| 829 | end | ||
| 830 | `endif | ||
| 831 | |||
| 832 | `ifndef SYNTHESIS | ||
| 833 | if (instcount == nextevent) begin | ||
| 834 | nextevent = ~0; | ||
| 835 | if (eventtrace != 0) $fscanf(eventtrace, "%d %d %d", nextevent, force_skip, force_interrupt); | ||
| 836 | $display("nextevent=%d force_skip=%d force_interrupt=%d", nextevent, force_skip, force_interrupt); | ||
| 837 | end | ||
| 838 | if (!injected_instruction) begin | ||
| 839 | ++instcount; | ||
| 840 | if (instcount >= 26000) $finish; | ||
| 841 | end | ||
| 842 | `endif | ||
| 843 | end | ||
| 844 | |||
| 845 | if (switch_sing_step) | ||
| 846 | run = 0; | ||
| 847 | |||
| 848 | if (state == FETCH && switch_sing_inst) | ||
| 849 | run = 0; | ||
| 850 | |||
| 851 | rx_ready = !tti_valid; | ||
| 852 | end | ||
| 853 | end | ||
| 854 | end | ||
| 855 | |||
| 856 | endmodule | ||
diff --git a/hdl/defs.svh b/hdl/defs.svh new file mode 100644 index 0000000..ea8dbc1 --- /dev/null +++ b/hdl/defs.svh | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | `define RAM_ADDRESS_BITS 23 | ||
| 2 | `define RAM_BYTE_BITS 8 | ||
| 3 | `define RAM_WORD_BYTES 2 | ||
| 4 | `define RAM_LINE_WORDS 1 | ||
| 5 | |||
| 6 | `define PDP_ADDRESS_BITS 15 | ||
| 7 | |||
| 8 | `define UART_BYTE_BITS 8 | ||
| 9 | |||
| 10 | `define TAG_BITS 1 | ||
| 11 | |||
| 12 | typedef bit [`RAM_ADDRESS_BITS-1:0] ram_word_address_t; | ||
| 13 | typedef bit [`RAM_ADDRESS_BITS-1:$clog2(`RAM_LINE_WORDS)] ram_line_address_t; | ||
| 14 | typedef bit [`RAM_BYTE_BITS-1:0] ram_byte_t; | ||
| 15 | typedef ram_byte_t [`RAM_WORD_BYTES-1:0] ram_word_t; | ||
| 16 | typedef ram_word_t [`RAM_LINE_WORDS-1:0] ram_line_t; | ||
| 17 | typedef bit [$clog2(`RAM_WORD_BYTES):0] ram_word_mask_t; | ||
| 18 | typedef ram_word_mask_t [`RAM_LINE_WORDS-1:0] ram_line_mask_t; | ||
| 19 | |||
| 20 | typedef bit [$clog2(`RAM_WORD_BYTES+1):0] ram_byte_count_t; | ||
| 21 | typedef bit [$clog2(`RAM_LINE_WORDS+1):0] ram_word_count_t; | ||
| 22 | |||
| 23 | typedef bit [`RAM_ADDRESS_BITS-1:`PDP_ADDRESS_BITS] ram_pdp_address_space_t; | ||
| 24 | |||
| 25 | typedef bit [`PDP_ADDRESS_BITS-1:0] pdp_word_address_t; | ||
| 26 | typedef bit [`PDP_ADDRESS_BITS-1:$clog2(`RAM_LINE_WORDS)] pdp_line_address_t; | ||
| 27 | |||
| 28 | typedef bit [`TAG_BITS-1:0] tag_t; | ||
| 29 | |||
| 30 | typedef bit [`UART_BYTE_BITS-1:0] uart_byte_t; | ||
| 31 | |||
| 32 | typedef struct { | ||
| 33 | ram_line_address_t address; | ||
| 34 | bit write; | ||
| 35 | ram_line_t data; | ||
| 36 | ram_line_mask_t mask; | ||
| 37 | tag_t tag; | ||
| 38 | } ram_command_t; | ||
| 39 | |||
| 40 | typedef struct { | ||
| 41 | ram_line_address_t address; | ||
| 42 | ram_line_t data; | ||
| 43 | tag_t tag; | ||
| 44 | } ram_read_response_t; | ||
| 45 | |||
| 46 | typedef struct { | ||
| 47 | pdp_line_address_t address; | ||
| 48 | bit write; | ||
| 49 | ram_line_t data; | ||
| 50 | ram_line_mask_t mask; | ||
| 51 | tag_t tag; | ||
| 52 | } pdp_command_t; | ||
| 53 | |||
| 54 | typedef struct { | ||
| 55 | pdp_line_address_t address; | ||
| 56 | ram_line_t data; | ||
| 57 | tag_t tag; | ||
| 58 | } pdp_read_response_t; | ||
diff --git a/hdl/echo_arbiter.sv b/hdl/echo_arbiter.sv new file mode 100644 index 0000000..1c27e31 --- /dev/null +++ b/hdl/echo_arbiter.sv | |||
| @@ -0,0 +1,64 @@ | |||
| 1 | `include "defs.svh" | ||
| 2 | |||
| 3 | module echo_arbiter | ||
| 4 | ( input bit clock | ||
| 5 | , input bit reset | ||
| 6 | |||
| 7 | , output bit in0_ready | ||
| 8 | , input bit in0_valid | ||
| 9 | , input uart_byte_t in0_data | ||
| 10 | |||
| 11 | , output bit in1_ready | ||
| 12 | , input bit in1_valid | ||
| 13 | , input uart_byte_t in1_data | ||
| 14 | |||
| 15 | , input bit out_ready | ||
| 16 | , output bit out_valid | ||
| 17 | , output uart_byte_t out_data | ||
| 18 | ); | ||
| 19 | |||
| 20 | bit in0_hold_valid; | ||
| 21 | uart_byte_t in0_hold; | ||
| 22 | |||
| 23 | bit in1_hold_valid; | ||
| 24 | uart_byte_t in1_hold; | ||
| 25 | |||
| 26 | always @(posedge clock) begin | ||
| 27 | if (reset) begin | ||
| 28 | in0_ready = 0; | ||
| 29 | in1_ready = 0; | ||
| 30 | out_valid = 0; | ||
| 31 | out_data = 0; | ||
| 32 | in0_hold_valid = 0; | ||
| 33 | in0_hold = 0; | ||
| 34 | in1_hold_valid = 0; | ||
| 35 | in1_hold = 0; | ||
| 36 | end else begin | ||
| 37 | if (out_ready) out_valid = 0; | ||
| 38 | if (in0_ready && in0_valid) begin | ||
| 39 | in0_hold_valid = 1; | ||
| 40 | in0_hold = in0_data; | ||
| 41 | end | ||
| 42 | if (in1_ready && in1_valid) begin | ||
| 43 | in1_hold_valid = 1; | ||
| 44 | in1_hold = in1_data; | ||
| 45 | end | ||
| 46 | |||
| 47 | if (!out_valid) begin | ||
| 48 | if (in0_hold_valid) begin | ||
| 49 | out_valid = 1; | ||
| 50 | out_data = in0_hold; | ||
| 51 | in0_hold_valid = 0; | ||
| 52 | end else if (in1_hold_valid) begin | ||
| 53 | out_valid = 1; | ||
| 54 | out_data = in1_hold; | ||
| 55 | in1_hold_valid = 0; | ||
| 56 | end | ||
| 57 | end | ||
| 58 | |||
| 59 | in0_ready = !in0_hold_valid; | ||
| 60 | in1_ready = !in1_hold_valid; | ||
| 61 | end | ||
| 62 | end | ||
| 63 | |||
| 64 | endmodule | ||
diff --git a/hdl/front_panel.sv b/hdl/front_panel.sv new file mode 100644 index 0000000..52b4bdb --- /dev/null +++ b/hdl/front_panel.sv | |||
| @@ -0,0 +1,211 @@ | |||
| 1 | module front_panel | ||
| 2 | #( DEBOUNCE_MAX = 100 | ||
| 3 | ) | ||
| 4 | ( input bit clk | ||
| 5 | , input bit reset | ||
| 6 | |||
| 7 | , input bit [8:1][12:1] led | ||
| 8 | , output bit [3:1][12:1] switch | ||
| 9 | |||
| 10 | , inout wire [10:1] gpioa | ||
| 11 | , inout wire [28:13] gpiob | ||
| 12 | , inout wire [40:31] gpioc | ||
| 13 | ); | ||
| 14 | |||
| 15 | localparam DEBOUNCE_BITS = $clog2(DEBOUNCE_MAX+1); | ||
| 16 | |||
| 17 | enum | ||
| 18 | { LED_ROW1 | ||
| 19 | , DEAD_ROW2 | ||
| 20 | , LED_ROW2 | ||
| 21 | , DEAD_ROW3 | ||
| 22 | , LED_ROW3 | ||
| 23 | , DEAD_ROW4 | ||
| 24 | , LED_ROW4 | ||
| 25 | , DEAD_ROW5 | ||
| 26 | , LED_ROW5 | ||
| 27 | , DEAD_ROW6 | ||
| 28 | , LED_ROW6 | ||
| 29 | , DEAD_ROW7 | ||
| 30 | , LED_ROW7 | ||
| 31 | , DEAD_ROW8 | ||
| 32 | , LED_ROW8 | ||
| 33 | , DEAD_ROW9 | ||
| 34 | , SWITCH_PREP | ||
| 35 | , SWITCH_ROW1 | ||
| 36 | , SWITCH_ROW2 | ||
| 37 | , SWITCH_ROW3 | ||
| 38 | } state; | ||
| 39 | |||
| 40 | bit [3:1][12:1] switch_raw; | ||
| 41 | bit [DEBOUNCE_BITS-1:0] switch_debounce; | ||
| 42 | |||
| 43 | `define LEDROW1 gpioc[38] | ||
| 44 | `define LEDROW2 gpioc[40] | ||
| 45 | `define LEDROW3 gpiob[15] | ||
| 46 | `define LEDROW4 gpiob[16] | ||
| 47 | `define LEDROW5 gpiob[18] | ||
| 48 | `define LEDROW6 gpiob[22] | ||
| 49 | `define LEDROW7 gpioc[37] | ||
| 50 | `define LEDROW8 gpiob[13] | ||
| 51 | |||
| 52 | `define SWROW1 gpioc[36] | ||
| 53 | `define SWROW2 gpioa[1] | ||
| 54 | `define SWROW3 gpioa[2] | ||
| 55 | |||
| 56 | `define COL1 gpioa[8] | ||
| 57 | `define COL2 gpioa[10] | ||
| 58 | `define COL3 gpioa[7] | ||
| 59 | `define COL4 gpiob[27] | ||
| 60 | `define COL5 gpioc[31] | ||
| 61 | `define COL6 gpiob[26] | ||
| 62 | `define COL7 gpiob[24] | ||
| 63 | `define COL8 gpiob[21] | ||
| 64 | `define COL9 gpiob[19] | ||
| 65 | `define COL10 gpiob[23] | ||
| 66 | `define COL11 gpioc[32] | ||
| 67 | `define COL12 gpioc[33] | ||
| 68 | |||
| 69 | `define DO_LEDS | ||
| 70 | `define DO_SWITCHES | ||
| 71 | |||
| 72 | always_ff @(posedge clk) begin | ||
| 73 | // LED rows (active high) | ||
| 74 | `LEDROW1 = 1'b0; | ||
| 75 | `LEDROW2 = 1'b0; | ||
| 76 | `LEDROW3 = 1'b0; | ||
| 77 | `LEDROW4 = 1'b0; | ||
| 78 | `LEDROW5 = 1'b0; | ||
| 79 | `LEDROW6 = 1'b0; | ||
| 80 | `LEDROW7 = 1'b0; | ||
| 81 | `LEDROW8 = 1'b0; | ||
| 82 | |||
| 83 | // Switch rows (active low) | ||
| 84 | `SWROW1 = 1'b1; | ||
| 85 | `SWROW2 = 1'b1; | ||
| 86 | `SWROW3 = 1'b1; | ||
| 87 | |||
| 88 | if (reset) begin | ||
| 89 | switch = 0; | ||
| 90 | switch_raw = 0; | ||
| 91 | switch_debounce = 0; | ||
| 92 | state = state.first; | ||
| 93 | end else begin | ||
| 94 | automatic bit [3:1][12:1] new_switch = switch_raw; | ||
| 95 | |||
| 96 | case (state) | ||
| 97 | `ifdef DO_LEDS | ||
| 98 | `define LED_ROW(n) \ | ||
| 99 | LED_ROW``n: begin \ | ||
| 100 | `LEDROW``n = 1'b1; \ | ||
| 101 | `COL1 = ~led[n][1]; \ | ||
| 102 | `COL2 = ~led[n][2]; \ | ||
| 103 | `COL3 = ~led[n][3]; \ | ||
| 104 | `COL4 = ~led[n][4]; \ | ||
| 105 | `COL5 = ~led[n][5]; \ | ||
| 106 | `COL6 = ~led[n][6]; \ | ||
| 107 | `COL7 = ~led[n][7]; \ | ||
| 108 | `COL8 = ~led[n][8]; \ | ||
| 109 | `COL9 = ~led[n][9]; \ | ||
| 110 | `COL10 = ~led[n][10]; \ | ||
| 111 | `COL11 = ~led[n][11]; \ | ||
| 112 | `COL12 = ~led[n][12]; \ | ||
| 113 | end | ||
| 114 | |||
| 115 | `LED_ROW(1) | ||
| 116 | `LED_ROW(2) | ||
| 117 | `LED_ROW(3) | ||
| 118 | `LED_ROW(4) | ||
| 119 | `LED_ROW(5) | ||
| 120 | `LED_ROW(6) | ||
| 121 | `LED_ROW(7) | ||
| 122 | `LED_ROW(8) | ||
| 123 | `endif | ||
| 124 | |||
| 125 | `ifdef DO_SWITCHES | ||
| 126 | SWITCH_PREP: begin | ||
| 127 | `SWROW1 = 1'b0; | ||
| 128 | |||
| 129 | `COL1 = 1'bZ; | ||
| 130 | `COL2 = 1'bZ; | ||
| 131 | `COL3 = 1'bZ; | ||
| 132 | `COL4 = 1'bZ; | ||
| 133 | `COL5 = 1'bZ; | ||
| 134 | `COL6 = 1'bZ; | ||
| 135 | `COL7 = 1'bZ; | ||
| 136 | `COL8 = 1'bZ; | ||
| 137 | `COL9 = 1'bZ; | ||
| 138 | `COL10 = 1'bZ; | ||
| 139 | `COL11 = 1'bZ; | ||
| 140 | `COL12 = 1'bZ; | ||
| 141 | end | ||
| 142 | |||
| 143 | SWITCH_ROW1: begin | ||
| 144 | `SWROW2 = 1'b0; | ||
| 145 | |||
| 146 | new_switch[1][1] = ~`COL1; | ||
| 147 | new_switch[1][2] = ~`COL2; | ||
| 148 | new_switch[1][3] = ~`COL3; | ||
| 149 | new_switch[1][4] = ~`COL4; | ||
| 150 | new_switch[1][5] = ~`COL5; | ||
| 151 | new_switch[1][6] = ~`COL6; | ||
| 152 | new_switch[1][7] = ~`COL7; | ||
| 153 | new_switch[1][8] = ~`COL8; | ||
| 154 | new_switch[1][9] = ~`COL9; | ||
| 155 | new_switch[1][10] = ~`COL10; | ||
| 156 | new_switch[1][11] = ~`COL11; | ||
| 157 | new_switch[1][12] = ~`COL12; | ||
| 158 | end | ||
| 159 | |||
| 160 | SWITCH_ROW2: begin | ||
| 161 | `SWROW3 = 1'b0; | ||
| 162 | |||
| 163 | new_switch[2][1] = ~`COL1; | ||
| 164 | new_switch[2][2] = ~`COL2; | ||
| 165 | new_switch[2][3] = ~`COL3; | ||
| 166 | new_switch[2][4] = ~`COL4; | ||
| 167 | new_switch[2][5] = ~`COL5; | ||
| 168 | new_switch[2][6] = ~`COL6; | ||
| 169 | new_switch[2][7] = ~`COL7; | ||
| 170 | new_switch[2][8] = ~`COL8; | ||
| 171 | new_switch[2][9] = ~`COL9; | ||
| 172 | new_switch[2][10] = ~`COL10; | ||
| 173 | new_switch[2][11] = ~`COL11; | ||
| 174 | new_switch[2][12] = ~`COL12; | ||
| 175 | end | ||
| 176 | |||
| 177 | SWITCH_ROW3: begin | ||
| 178 | new_switch[3][1] = ~`COL1; | ||
| 179 | new_switch[3][2] = ~`COL2; | ||
| 180 | new_switch[3][3] = ~`COL3; | ||
| 181 | new_switch[3][4] = ~`COL4; | ||
| 182 | new_switch[3][5] = ~`COL5; | ||
| 183 | new_switch[3][6] = ~`COL6; | ||
| 184 | new_switch[3][7] = ~`COL7; | ||
| 185 | new_switch[3][8] = ~`COL8; | ||
| 186 | new_switch[3][9] = ~`COL9; | ||
| 187 | new_switch[3][10] = ~`COL10; | ||
| 188 | new_switch[3][11] = ~`COL11; | ||
| 189 | new_switch[3][12] = ~`COL12; | ||
| 190 | end | ||
| 191 | `endif | ||
| 192 | endcase | ||
| 193 | |||
| 194 | if (state == state.last) | ||
| 195 | state = state.first; | ||
| 196 | else | ||
| 197 | state = state.next; | ||
| 198 | |||
| 199 | if (new_switch == switch_raw) begin | ||
| 200 | if (switch_debounce == 0) | ||
| 201 | switch = switch_raw; | ||
| 202 | else | ||
| 203 | --switch_debounce; | ||
| 204 | end else begin | ||
| 205 | switch_raw = new_switch; | ||
| 206 | switch_debounce = DEBOUNCE_MAX; | ||
| 207 | end | ||
| 208 | end | ||
| 209 | end | ||
| 210 | |||
| 211 | endmodule | ||
diff --git a/hdl/pll.sv b/hdl/pll.sv new file mode 100644 index 0000000..d348b7c --- /dev/null +++ b/hdl/pll.sv | |||
| @@ -0,0 +1,126 @@ | |||
| 1 | module pll | ||
| 2 | #( MULTIPLY_BY = 1 | ||
| 3 | , DIVIDE_BY = 1 | ||
| 4 | , NATIVE_PERIOD_PICOSECONDS = 20_000 | ||
| 5 | ) | ||
| 6 | ( input bit native_clk | ||
| 7 | , input bit reset_n | ||
| 8 | |||
| 9 | , output bit target_clk | ||
| 10 | , output bit reset | ||
| 11 | ); | ||
| 12 | |||
| 13 | enum | ||
| 14 | { NOT_LOCKED | ||
| 15 | , RESET_CYCLE | ||
| 16 | , READY | ||
| 17 | } state = state.first; | ||
| 18 | |||
| 19 | bit locked; | ||
| 20 | |||
| 21 | `ifndef SYNTHESIS | ||
| 22 | |||
| 23 | assign target_clk = native_clk; | ||
| 24 | assign locked = 1; | ||
| 25 | |||
| 26 | `else | ||
| 27 | |||
| 28 | altpll | ||
| 29 | #( .clk0_divide_by(DIVIDE_BY) | ||
| 30 | , .clk0_multiply_by(MULTIPLY_BY) | ||
| 31 | , .inclk0_input_frequency(NATIVE_PERIOD_PICOSECONDS) | ||
| 32 | , .intended_device_family("Cyclone 10 LP") | ||
| 33 | , .operation_mode("NORMAL") | ||
| 34 | , .port_activeclock("PORT_UNUSED") | ||
| 35 | , .port_areset("PORT_USED") | ||
| 36 | , .port_clkbad0("PORT_UNUSED") | ||
| 37 | , .port_clkbad1("PORT_UNUSED") | ||
| 38 | , .port_clkloss("PORT_UNUSED") | ||
| 39 | , .port_clkswitch("PORT_UNUSED") | ||
| 40 | , .port_configupdate("PORT_UNUSED") | ||
| 41 | , .port_fbin("PORT_UNUSED") | ||
| 42 | , .port_inclk0("PORT_USED") | ||
| 43 | , .port_inclk1("PORT_UNUSED") | ||
| 44 | , .port_locked("PORT_USED") | ||
| 45 | , .port_pfdena("PORT_UNUSED") | ||
| 46 | , .port_phasecounterselect("PORT_UNUSED") | ||
| 47 | , .port_phasedone("PORT_UNUSED") | ||
| 48 | , .port_phasestep("PORT_UNUSED") | ||
| 49 | , .port_phaseupdown("PORT_UNUSED") | ||
| 50 | , .port_pllena("PORT_UNUSED") | ||
| 51 | , .port_scanaclr("PORT_UNUSED") | ||
| 52 | , .port_scanclk("PORT_UNUSED") | ||
| 53 | , .port_scanclkena("PORT_UNUSED") | ||
| 54 | , .port_scandata("PORT_UNUSED") | ||
| 55 | , .port_scandataout("PORT_UNUSED") | ||
| 56 | , .port_scandone("PORT_UNUSED") | ||
| 57 | , .port_scanread("PORT_UNUSED") | ||
| 58 | , .port_scanwrite("PORT_UNUSED") | ||
| 59 | , .port_clk0("PORT_USED") | ||
| 60 | , .port_clk1("PORT_UNUSED") | ||
| 61 | , .port_clk2("PORT_UNUSED") | ||
| 62 | , .port_clk3("PORT_UNUSED") | ||
| 63 | , .port_clk4("PORT_UNUSED") | ||
| 64 | , .port_clk5("PORT_UNUSED") | ||
| 65 | , .port_clkena0("PORT_UNUSED") | ||
| 66 | , .port_clkena1("PORT_UNUSED") | ||
| 67 | , .port_clkena2("PORT_UNUSED") | ||
| 68 | , .port_clkena3("PORT_UNUSED") | ||
| 69 | , .port_clkena4("PORT_UNUSED") | ||
| 70 | , .port_clkena5("PORT_UNUSED") | ||
| 71 | , .port_extclk0("PORT_UNUSED") | ||
| 72 | , .port_extclk1("PORT_UNUSED") | ||
| 73 | , .port_extclk2("PORT_UNUSED") | ||
| 74 | , .port_extclk3("PORT_UNUSED") | ||
| 75 | , .self_reset_on_loss_lock("ON") | ||
| 76 | , .width_clock(5) | ||
| 77 | ) pll | ||
| 78 | ( .areset(!reset_n) | ||
| 79 | , .inclk(native_clk) | ||
| 80 | , .clk(target_clk) | ||
| 81 | , .locked(locked) | ||
| 82 | , .activeclock() | ||
| 83 | , .clkbad() | ||
| 84 | , .clkena({6{1'b1}}) | ||
| 85 | , .clkloss() | ||
| 86 | , .clkswitch(1'b0) | ||
| 87 | , .configupdate(1'b0) | ||
| 88 | , .extclkena({4{1'b1}}) | ||
| 89 | , .fbin(1'b1) | ||
| 90 | , .fbmimicbidir() | ||
| 91 | , .fbout() | ||
| 92 | , .fref() | ||
| 93 | , .icdrclk() | ||
| 94 | , .pfdena(1'b1) | ||
| 95 | , .phasecounterselect({4{1'b1}}) | ||
| 96 | , .phasedone() | ||
| 97 | , .phasestep(1'b1) | ||
| 98 | , .phaseupdown(1'b1) | ||
| 99 | , .pllena(1'b1) | ||
| 100 | , .scanaclr(1'b0) | ||
| 101 | , .scanclk(1'b0) | ||
| 102 | , .scanclkena(1'b1) | ||
| 103 | , .scandata(1'b0) | ||
| 104 | , .scandataout() | ||
| 105 | , .scandone() | ||
| 106 | , .scanread(1'b0) | ||
| 107 | , .scanwrite(1'b0) | ||
| 108 | , .sclkout0() | ||
| 109 | , .sclkout1() | ||
| 110 | , .vcooverrange() | ||
| 111 | , .vcounderrange() | ||
| 112 | ); | ||
| 113 | |||
| 114 | `endif | ||
| 115 | |||
| 116 | always_ff @(posedge target_clk) begin | ||
| 117 | if (!reset_n || !locked) begin | ||
| 118 | state = state.first; | ||
| 119 | end else if (state != state.last) begin | ||
| 120 | state = state.next; | ||
| 121 | end | ||
| 122 | |||
| 123 | reset = !(state == state.last); | ||
| 124 | end | ||
| 125 | |||
| 126 | endmodule | ||
diff --git a/hdl/ram_controller.sv b/hdl/ram_controller.sv new file mode 100644 index 0000000..6eeb46d --- /dev/null +++ b/hdl/ram_controller.sv | |||
| @@ -0,0 +1,240 @@ | |||
| 1 | `include "defs.svh" | ||
| 2 | |||
| 3 | module ram_controller | ||
| 4 | ( input bit clock | ||
| 5 | , input bit reset | ||
| 6 | |||
| 7 | , output bit command_ready | ||
| 8 | , input bit command_valid | ||
| 9 | , input ram_command_t command_data | ||
| 10 | |||
| 11 | , input bit result_ready | ||
| 12 | , output bit result_valid | ||
| 13 | , output ram_read_response_t result_data | ||
| 14 | |||
| 15 | , output bit ram_resetn | ||
| 16 | , output bit ram_csn | ||
| 17 | , output bit ram_clkp | ||
| 18 | , output bit ram_clkn | ||
| 19 | , output bit ram_rwds_oe | ||
| 20 | , input bit ram_rwds_in | ||
| 21 | , output bit ram_rwds_out | ||
| 22 | , output bit ram_data_oe | ||
| 23 | , input bit [7:0] ram_data_in | ||
| 24 | , output bit [7:0] ram_data_out | ||
| 25 | ); | ||
| 26 | |||
| 27 | assign ram_clkn = !ram_clkp; | ||
| 28 | |||
| 29 | bit valid; | ||
| 30 | ram_command_t command; | ||
| 31 | ram_word_address_t base_address; | ||
| 32 | |||
| 33 | bit slow; | ||
| 34 | ram_word_count_t word_count; | ||
| 35 | |||
| 36 | (* syn_encoding = "one-hot" *) enum int unsigned | ||
| 37 | { CHIP_SELECT | ||
| 38 | |||
| 39 | , SEND_COMMAND_1 | ||
| 40 | , SEND_COMMAND_2 | ||
| 41 | , SEND_COMMAND_3 | ||
| 42 | , SEND_COMMAND_4 | ||
| 43 | , SEND_COMMAND_5 | ||
| 44 | , SEND_COMMAND_6 | ||
| 45 | |||
| 46 | , LAT2_12 | ||
| 47 | , LAT2_11 | ||
| 48 | , LAT2_10 | ||
| 49 | , LAT2_9 | ||
| 50 | , LAT2_8 | ||
| 51 | , LAT2_7 | ||
| 52 | , LAT2_6 | ||
| 53 | , LAT2_5 | ||
| 54 | , LAT2_4 | ||
| 55 | , LAT2_3 | ||
| 56 | , LAT2_2 | ||
| 57 | , LAT2_1 | ||
| 58 | |||
| 59 | /* Latency blocks are 6 cycle, but you start counting after the upper | ||
| 60 | * column address is sent (SEND_COMMAND_4) so we reduce the | ||
| 61 | * lowest-latency block by one full cycle (two states). | ||
| 62 | , LAT1_12 | ||
| 63 | , LAT1_11 | ||
| 64 | */ | ||
| 65 | , LAT1_10 | ||
| 66 | , LAT1_9 | ||
| 67 | , LAT1_8 | ||
| 68 | , LAT1_7 | ||
| 69 | , LAT1_6 | ||
| 70 | , LAT1_5 | ||
| 71 | , LAT1_4 | ||
| 72 | , LAT1_3 | ||
| 73 | , LAT1_2 | ||
| 74 | , LAT1_1 | ||
| 75 | |||
| 76 | , DATA_1 | ||
| 77 | , DATA_2 | ||
| 78 | } state; | ||
| 79 | |||
| 80 | (* syn_encoding = "compact" *) enum bit | ||
| 81 | { SETUP_OUTPUTS | ||
| 82 | , TOGGLE_CLOCK | ||
| 83 | } half_state; | ||
| 84 | |||
| 85 | bit [2:0] reset_counter; | ||
| 86 | |||
| 87 | bit prev_rwds; | ||
| 88 | |||
| 89 | always @(posedge clock) begin | ||
| 90 | if (reset || reset_counter != 0) begin | ||
| 91 | command_ready = 0; | ||
| 92 | result_valid = 0; | ||
| 93 | ram_resetn = 0; | ||
| 94 | ram_csn = 1; | ||
| 95 | ram_clkp = 0; | ||
| 96 | ram_rwds_oe = 0; | ||
| 97 | ram_rwds_out = 0; | ||
| 98 | ram_data_oe = 0; | ||
| 99 | ram_data_out = 0; | ||
| 100 | base_address = 0; | ||
| 101 | slow = 0; | ||
| 102 | word_count = `RAM_LINE_WORDS; | ||
| 103 | state = state.first; | ||
| 104 | half_state = half_state.first; | ||
| 105 | if (reset) | ||
| 106 | reset_counter = 5; // Spec wants >= 100ns of reset | ||
| 107 | else | ||
| 108 | reset_counter = reset_counter - 1; | ||
| 109 | end else begin | ||
| 110 | ram_resetn = 1; | ||
| 111 | |||
| 112 | if (result_ready) result_valid = 0; | ||
| 113 | if (command_ready && command_valid) begin | ||
| 114 | valid = 1; | ||
| 115 | command = command_data; | ||
| 116 | base_address = 0; | ||
| 117 | base_address[`RAM_ADDRESS_BITS-1:$clog2(`RAM_LINE_WORDS)] = command.address; | ||
| 118 | word_count = `RAM_LINE_WORDS; | ||
| 119 | state = state.first; | ||
| 120 | end | ||
| 121 | |||
| 122 | if (!valid) begin | ||
| 123 | ram_rwds_oe = 0; | ||
| 124 | ram_data_oe = 0; | ||
| 125 | ram_csn = 1; | ||
| 126 | ram_clkp = 0; | ||
| 127 | end else if (half_state == TOGGLE_CLOCK) begin | ||
| 128 | half_state = half_state.next; | ||
| 129 | if (state != CHIP_SELECT && state != SEND_COMMAND_1) | ||
| 130 | ram_clkp = !ram_clkp; | ||
| 131 | end else if (half_state == SETUP_OUTPUTS) begin | ||
| 132 | automatic bit stall = 0; | ||
| 133 | half_state = half_state.next; | ||
| 134 | ram_rwds_oe = 0; | ||
| 135 | ram_data_oe = 0; | ||
| 136 | case (state) | ||
| 137 | |||
| 138 | CHIP_SELECT: begin | ||
| 139 | ram_clkp = 0; // Overriding clock to guarantee that we're starting the command with the correct clock polarity | ||
| 140 | ram_csn = 0; | ||
| 141 | end | ||
| 142 | |||
| 143 | SEND_COMMAND_1: begin | ||
| 144 | ram_data_oe = 1; | ||
| 145 | ram_data_out = {!command.write, 1'b0, 1'b1, 5'b0}; // R/W#, ADDRSPACE, BURST, RESERVED | ||
| 146 | end | ||
| 147 | |||
| 148 | SEND_COMMAND_2: begin | ||
| 149 | ram_data_oe = 1; | ||
| 150 | ram_data_out = {4'b0, base_address[22:19]}; // RESERVED, ROW | ||
| 151 | end | ||
| 152 | |||
| 153 | SEND_COMMAND_3: begin | ||
| 154 | ram_data_oe = 1; | ||
| 155 | ram_data_out = {base_address[18:11]}; // ROW | ||
| 156 | end | ||
| 157 | |||
| 158 | SEND_COMMAND_4: begin | ||
| 159 | ram_data_oe = 1; | ||
| 160 | ram_data_out = {base_address[10:9], base_address[8:3]}; // ROW, UPPERCOL | ||
| 161 | // This is the cycle immediately before the latency countdown *really* begins. | ||
| 162 | // So we capture RWDS now in order to know how many latency blocks are required. | ||
| 163 | slow = ram_rwds_in; | ||
| 164 | end | ||
| 165 | |||
| 166 | SEND_COMMAND_5: begin | ||
| 167 | ram_data_oe = 1; | ||
| 168 | ram_data_out = {8'b0}; // RESERVED | ||
| 169 | end | ||
| 170 | |||
| 171 | SEND_COMMAND_6: begin | ||
| 172 | ram_data_oe = 1; | ||
| 173 | ram_data_out = {5'b0, base_address[2:0]}; // RESERVED, LOWERCOL | ||
| 174 | // If we're not in "slow" mode then skip the LAT2 latency | ||
| 175 | // block. Note that the state=state.next will still happen | ||
| 176 | // below, taking us to the first state in the LAT1 block. | ||
| 177 | if (!slow) state = LAT2_1; | ||
| 178 | end | ||
| 179 | |||
| 180 | // Nothing happens on any of the LAT_* states except for | ||
| 181 | // cycling the clock and advancing state. | ||
| 182 | |||
| 183 | DATA_1: begin | ||
| 184 | if (command.write) begin | ||
| 185 | ram_rwds_oe = 1; | ||
| 186 | ram_rwds_out = !command.mask[word_count - 1][0]; | ||
| 187 | ram_data_oe = 1; | ||
| 188 | ram_data_out = command.data[word_count - 1][0]; | ||
| 189 | end else if (prev_rwds != ram_rwds_in) begin | ||
| 190 | command.data[word_count - 1][0] = ram_data_in; | ||
| 191 | end else begin | ||
| 192 | stall = 1; | ||
| 193 | end | ||
| 194 | end | ||
| 195 | |||
| 196 | DATA_2: begin | ||
| 197 | if (command.write) begin | ||
| 198 | ram_rwds_oe = 1; | ||
| 199 | ram_rwds_out = !command.mask[word_count - 1][1]; | ||
| 200 | ram_data_oe = 1; | ||
| 201 | ram_data_out = command.data[word_count - 1][1]; | ||
| 202 | word_count = word_count - 1; | ||
| 203 | if (word_count != 0) begin | ||
| 204 | stall = 1; | ||
| 205 | state = DATA_1; | ||
| 206 | end | ||
| 207 | end else if (prev_rwds != ram_rwds_in) begin | ||
| 208 | command.data[word_count - 1][1] = ram_data_in; | ||
| 209 | word_count = word_count - 1; | ||
| 210 | if (word_count != 0) begin | ||
| 211 | stall = 1; | ||
| 212 | state = DATA_1; | ||
| 213 | end | ||
| 214 | end else begin | ||
| 215 | stall = 1; | ||
| 216 | end | ||
| 217 | end | ||
| 218 | |||
| 219 | endcase | ||
| 220 | if (!stall) begin | ||
| 221 | state = state.next; | ||
| 222 | if (state == state.first) begin | ||
| 223 | valid = 0; | ||
| 224 | if (!command.write) begin | ||
| 225 | // We know that this is safe because we don't accept commands unless we have result bandwidth | ||
| 226 | result_valid = 1; | ||
| 227 | result_data.address = command.address; | ||
| 228 | result_data.data = command.data; | ||
| 229 | result_data.tag = command.tag; | ||
| 230 | end | ||
| 231 | end | ||
| 232 | end | ||
| 233 | end | ||
| 234 | |||
| 235 | prev_rwds = ram_rwds_in; | ||
| 236 | command_ready = !valid && !result_valid; | ||
| 237 | end | ||
| 238 | end | ||
| 239 | |||
| 240 | endmodule | ||
diff --git a/hdl/result_printer.sv b/hdl/result_printer.sv new file mode 100644 index 0000000..3041e6e --- /dev/null +++ b/hdl/result_printer.sv | |||
| @@ -0,0 +1,71 @@ | |||
| 1 | `include "defs.svh" | ||
| 2 | |||
| 3 | module result_printer | ||
| 4 | #( TAG = 0 | ||
| 5 | ) ( input bit clock | ||
| 6 | , input bit reset | ||
| 7 | |||
| 8 | , output bit result_ready | ||
| 9 | , input bit result_valid | ||
| 10 | , input ram_read_response_t result_data | ||
| 11 | |||
| 12 | , input bit echo_ready | ||
| 13 | , output bit echo_valid | ||
| 14 | , output uart_byte_t echo_data | ||
| 15 | ); | ||
| 16 | |||
| 17 | ram_read_response_t hold; | ||
| 18 | ram_byte_count_t byte_count; | ||
| 19 | ram_word_count_t word_count; | ||
| 20 | |||
| 21 | (* syn_encoding = "one-hot" *) enum int unsigned | ||
| 22 | { HIGH_NIBBLE | ||
| 23 | , LOW_NIBBLE | ||
| 24 | } state; | ||
| 25 | |||
| 26 | always @(posedge clock) begin | ||
| 27 | if (reset) begin | ||
| 28 | result_ready = 0; | ||
| 29 | echo_valid = 0; | ||
| 30 | echo_data = 0; | ||
| 31 | byte_count = 0; | ||
| 32 | word_count = 0; | ||
| 33 | state = state.first; | ||
| 34 | end else begin | ||
| 35 | if (echo_ready) echo_valid = 0; | ||
| 36 | if (result_ready && result_valid) begin | ||
| 37 | hold = result_data; | ||
| 38 | if (hold.tag == TAG) begin | ||
| 39 | byte_count = `RAM_WORD_BYTES; | ||
| 40 | word_count = `RAM_LINE_WORDS; | ||
| 41 | state = state.first; | ||
| 42 | end | ||
| 43 | end | ||
| 44 | |||
| 45 | if (word_count != 0 && !echo_valid) begin | ||
| 46 | automatic ram_word_t w = hold.data[word_count-1]; | ||
| 47 | automatic ram_byte_t b = w[byte_count-1]; | ||
| 48 | echo_valid = 1; | ||
| 49 | case (state) | ||
| 50 | HIGH_NIBBLE: echo_data = b[7:4]; | ||
| 51 | LOW_NIBBLE: echo_data = b[3:0]; | ||
| 52 | endcase | ||
| 53 | if (echo_data < 10) | ||
| 54 | echo_data = echo_data + "0"; | ||
| 55 | else | ||
| 56 | echo_data = echo_data + "A" - 10; | ||
| 57 | state = state.next; | ||
| 58 | if (state == state.first) begin | ||
| 59 | byte_count = byte_count - 1; | ||
| 60 | if (byte_count == 0) begin | ||
| 61 | byte_count = `RAM_WORD_BYTES; | ||
| 62 | word_count = word_count - 1; | ||
| 63 | end | ||
| 64 | end | ||
| 65 | end | ||
| 66 | |||
| 67 | result_ready = word_count == 0; | ||
| 68 | end | ||
| 69 | end | ||
| 70 | |||
| 71 | endmodule | ||
diff --git a/hdl/top.sv b/hdl/top.sv new file mode 100644 index 0000000..7ec57b7 --- /dev/null +++ b/hdl/top.sv | |||
| @@ -0,0 +1,298 @@ | |||
| 1 | `include "defs.svh" | ||
| 2 | |||
| 3 | module top | ||
| 4 | ( input bit clock | ||
| 5 | , input bit resetn | ||
| 6 | |||
| 7 | , inout wire [10:1] gpioa | ||
| 8 | , inout wire [28:13] gpiob | ||
| 9 | , inout wire [40:31] gpioc | ||
| 10 | |||
| 11 | , output bit ram_resetn | ||
| 12 | , output bit ram_csn | ||
| 13 | , output bit ram_clkp | ||
| 14 | , output bit ram_clkn | ||
| 15 | , inout bit ram_rwds | ||
| 16 | , inout bit [7:0] ram_data | ||
| 17 | ); | ||
| 18 | |||
| 19 | bit internal_clock; | ||
| 20 | bit internal_reset; | ||
| 21 | pll | ||
| 22 | #( .MULTIPLY_BY(1) | ||
| 23 | , .DIVIDE_BY(1) | ||
| 24 | ) fastpll | ||
| 25 | ( .native_clk(clock) | ||
| 26 | , .reset_n(resetn) | ||
| 27 | , .target_clk(internal_clock) | ||
| 28 | , .reset(internal_reset) | ||
| 29 | ); | ||
| 30 | |||
| 31 | bit ram_rx_ready; | ||
| 32 | bit ram_rx_valid; | ||
| 33 | uart_byte_t ram_rx_data; | ||
| 34 | |||
| 35 | bit ram_tx_ready; | ||
| 36 | bit ram_tx_valid; | ||
| 37 | uart_byte_t ram_tx_data; | ||
| 38 | |||
| 39 | bit ram_echo_in0_ready; | ||
| 40 | bit ram_echo_in0_valid; | ||
| 41 | uart_byte_t ram_echo_in0_data; | ||
| 42 | |||
| 43 | bit ram_echo_in1_ready; | ||
| 44 | bit ram_echo_in1_valid; | ||
| 45 | uart_byte_t ram_echo_in1_data; | ||
| 46 | |||
| 47 | bit command_ready; | ||
| 48 | bit command_valid; | ||
| 49 | ram_command_t command_data; | ||
| 50 | |||
| 51 | bit result_ready; | ||
| 52 | bit result_valid; | ||
| 53 | ram_read_response_t result_data; | ||
| 54 | |||
| 55 | bit ram_rwds_oe; | ||
| 56 | bit ram_rwds_out; | ||
| 57 | assign ram_rwds = ram_rwds_oe ? ram_rwds_out : 1'bZ; | ||
| 58 | |||
| 59 | bit ram_data_oe; | ||
| 60 | bit [7:0] ram_data_out; | ||
| 61 | assign ram_data = ram_data_oe ? ram_data_out : 8'bZ; | ||
| 62 | |||
| 63 | alt_jtag_atlantic | ||
| 64 | #( .INSTANCE_ID(0) | ||
| 65 | , .LOG2_RXFIFO_DEPTH(6) | ||
| 66 | , .LOG2_TXFIFO_DEPTH(6) | ||
| 67 | , .SLD_AUTO_INSTANCE_INDEX("NO") | ||
| 68 | ) ram_jtag | ||
| 69 | ( .clk(internal_clock) | ||
| 70 | , .rst_n(!internal_reset) | ||
| 71 | |||
| 72 | , .r_dat(ram_tx_data) | ||
| 73 | , .r_val(ram_tx_valid) | ||
| 74 | , .r_ena(ram_tx_ready) | ||
| 75 | |||
| 76 | , .t_dat(ram_rx_data) | ||
| 77 | , .t_dav(ram_rx_ready) | ||
| 78 | , .t_ena(ram_rx_valid) | ||
| 79 | ); | ||
| 80 | |||
| 81 | echo_arbiter arb | ||
| 82 | ( .clock(internal_clock) | ||
| 83 | , .reset(internal_reset) | ||
| 84 | |||
| 85 | , .in0_ready(ram_echo_in0_ready) | ||
| 86 | , .in0_valid(ram_echo_in0_valid) | ||
| 87 | , .in0_data(ram_echo_in0_data) | ||
| 88 | |||
| 89 | , .in1_ready(ram_echo_in1_ready) | ||
| 90 | , .in1_valid(ram_echo_in1_valid) | ||
| 91 | , .in1_data(ram_echo_in1_data) | ||
| 92 | |||
| 93 | , .out_ready(ram_tx_ready) | ||
| 94 | , .out_valid(ram_tx_valid) | ||
| 95 | , .out_data(ram_tx_data) | ||
| 96 | ); | ||
| 97 | |||
| 98 | command_parser | ||
| 99 | #( .TAG(0) | ||
| 100 | ) parser | ||
| 101 | ( .clock(internal_clock) | ||
| 102 | , .reset(internal_reset) | ||
| 103 | |||
| 104 | , .uart_ready(ram_rx_ready) | ||
| 105 | , .uart_valid(ram_rx_valid) | ||
| 106 | , .uart_data(ram_rx_data) | ||
| 107 | |||
| 108 | , .echo_ready(ram_echo_in0_ready) | ||
| 109 | , .echo_valid(ram_echo_in0_valid) | ||
| 110 | , .echo_data(ram_echo_in0_data) | ||
| 111 | |||
| 112 | , .command_ready(command_ready) | ||
| 113 | , .command_valid(command_valid) | ||
| 114 | , .command_data(command_data) | ||
| 115 | ); | ||
| 116 | |||
| 117 | ram_controller ram | ||
| 118 | ( .clock(internal_clock) | ||
| 119 | , .reset(internal_reset) | ||
| 120 | |||
| 121 | , .command_ready(command_ready) | ||
| 122 | , .command_valid(command_valid) | ||
| 123 | , .command_data(command_data) | ||
| 124 | |||
| 125 | , .result_ready(result_ready) | ||
| 126 | , .result_valid(result_valid) | ||
| 127 | , .result_data(result_data) | ||
| 128 | |||
| 129 | , .ram_resetn(ram_resetn) | ||
| 130 | , .ram_csn(ram_csn) | ||
| 131 | , .ram_clkp(ram_clkp) | ||
| 132 | , .ram_clkn(ram_clkn) | ||
| 133 | , .ram_rwds_oe(ram_rwds_oe) | ||
| 134 | , .ram_rwds_in(ram_rwds) | ||
| 135 | , .ram_rwds_out(ram_rwds_out) | ||
| 136 | , .ram_data_oe(ram_data_oe) | ||
| 137 | , .ram_data_in(ram_data) | ||
| 138 | , .ram_data_out(ram_data_out) | ||
| 139 | ); | ||
| 140 | |||
| 141 | result_printer | ||
| 142 | #( .TAG(0) | ||
| 143 | |||
| 144 | ( .clock(internal_clock) | ||
| 145 | , .reset(internal_reset) | ||
| 146 | |||
| 147 | , .result_ready(result_ready) | ||
| 148 | , .result_valid(result_valid) | ||
| 149 | , .result_data(result_data) | ||
| 150 | |||
| 151 | , .echo_ready(ram_echo_in1_ready) | ||
| 152 | , .echo_valid(ram_echo_in1_valid) | ||
| 153 | , .echo_data(ram_echo_in1_data) | ||
| 154 | ); | ||
| 155 | |||
| 156 | bit slow_clock; | ||
| 157 | bit slow_reset; | ||
| 158 | pll | ||
| 159 | #( .MULTIPLY_BY(1) | ||
| 160 | , .DIVIDE_BY(500) | ||
| 161 | ) slowpll | ||
| 162 | ( .native_clk(clock) | ||
| 163 | , .reset_n(resetn) | ||
| 164 | , .target_clk(slow_clock) | ||
| 165 | , .reset(slow_reset) | ||
| 166 | ); | ||
| 167 | |||
| 168 | bit [8:1][12:1] led; | ||
| 169 | bit [3:1][12:1] switch; | ||
| 170 | |||
| 171 | front_panel panel | ||
| 172 | ( .clk(slow_clock) | ||
| 173 | , .reset(slow_reset) | ||
| 174 | |||
| 175 | , .led(led) | ||
| 176 | , .switch(switch) | ||
| 177 | |||
| 178 | , .gpioa(gpioa) | ||
| 179 | , .gpiob(gpiob) | ||
| 180 | , .gpioc(gpioc) | ||
| 181 | ); | ||
| 182 | |||
| 183 | bit [2:0] switch_df; | ||
| 184 | bit [2:0] switch_if; | ||
| 185 | bit [11:0] switch_sr; | ||
| 186 | bit switch_start; | ||
| 187 | bit switch_load_add; | ||
| 188 | bit switch_dep; | ||
| 189 | bit switch_exam; | ||
| 190 | bit switch_cont; | ||
| 191 | bit switch_stop; | ||
| 192 | bit switch_sing_step; | ||
| 193 | bit switch_sing_inst; | ||
| 194 | |||
| 195 | // Note that we are reversing the order here on a number of aggregates because | ||
| 196 | // the panel model gives us LEDs and switches in schematic-order, which is the | ||
| 197 | // opposite of the bit order | ||
| 198 | assign switch_df = {switch[2][1], switch[2][2], switch[2][3]}; | ||
| 199 | assign switch_if = {switch[2][4], switch[2][5], switch[2][6]}; | ||
| 200 | assign switch_sr = {switch[1][1], switch[1][2], switch[1][3], switch[1][4], switch[1][5], switch[1][6], switch[1][7], switch[1][8], switch[1][9], switch[1][10], switch[1][11], switch[1][12]}; | ||
| 201 | assign switch_start = switch[3][1]; | ||
| 202 | assign switch_load_add = switch[3][2]; | ||
| 203 | assign switch_dep = switch[3][3]; | ||
| 204 | assign switch_exam = switch[3][4]; | ||
| 205 | assign switch_cont = switch[3][5]; | ||
| 206 | assign switch_stop = switch[3][6]; | ||
| 207 | `ifdef HISTORIC_SWITCH_BEHAVIOUR | ||
| 208 | assign switch_sing_step = !switch[3][7]; | ||
| 209 | assign switch_sing_inst = !switch[3][8]; | ||
| 210 | `else | ||
| 211 | assign switch_sing_step = switch[3][7]; | ||
| 212 | assign switch_sing_inst = switch[3][8]; | ||
| 213 | `endif | ||
| 214 | |||
| 215 | bit [11:0] led_pc; | ||
| 216 | bit [11:0] led_memaddr; | ||
| 217 | bit [11:0] led_memdata; | ||
| 218 | bit [11:0] led_acc; | ||
| 219 | bit [11:0] led_mq; | ||
| 220 | bit led_and; | ||
| 221 | bit led_tad; | ||
| 222 | bit led_isz; | ||
| 223 | bit led_dca; | ||
| 224 | bit led_jms; | ||
| 225 | bit led_jmp; | ||
| 226 | bit led_iot; | ||
| 227 | bit led_opr; | ||
| 228 | bit led_fetch; | ||
| 229 | bit led_execute; | ||
| 230 | bit led_defer; | ||
| 231 | bit led_word_count; | ||
| 232 | bit led_current_address; | ||
| 233 | bit led_break; | ||
| 234 | bit led_ion; | ||
| 235 | bit led_pause; | ||
| 236 | bit led_run; | ||
| 237 | bit [4:0] led_step_counter; | ||
| 238 | bit [2:0] led_df; | ||
| 239 | bit [2:0] led_if; | ||
| 240 | bit led_link; | ||
| 241 | |||
| 242 | // Note that we are reversing the order here on a number of aggregates because | ||
| 243 | // the panel model gives us LEDs and switches in schematic-order, which is the | ||
| 244 | // opposite of the bit order | ||
| 245 | assign led[1] = {led_pc[0], led_pc[1], led_pc[2], led_pc[3], led_pc[4], led_pc[5], led_pc[6], led_pc[7], led_pc[8], led_pc[9], led_pc[10], led_pc[11]}; | ||
| 246 | assign led[2] = {led_memaddr[0], led_memaddr[1], led_memaddr[2], led_memaddr[3], led_memaddr[4], led_memaddr[5], led_memaddr[6], led_memaddr[7], led_memaddr[8], led_memaddr[9], led_memaddr[10], led_memaddr[11]}; | ||
| 247 | assign led[3] = {led_memdata[0], led_memdata[1], led_memdata[2], led_memdata[3], led_memdata[4], led_memdata[5], led_memdata[6], led_memdata[7], led_memdata[8], led_memdata[9], led_memdata[10], led_memdata[11]}; | ||
| 248 | assign led[4] = {led_acc[0], led_acc[1], led_acc[2], led_acc[3], led_acc[4], led_acc[5], led_acc[6], led_acc[7], led_acc[8], led_acc[9], led_acc[10], led_acc[11]}; | ||
| 249 | assign led[5] = {led_mq[0], led_mq[1], led_mq[2], led_mq[3], led_mq[4], led_mq[5], led_mq[6], led_mq[7], led_mq[8], led_mq[9], led_mq[10], led_mq[11]}; | ||
| 250 | assign led[6] = {led_word_count, led_defer, led_execute, led_fetch, led_opr, led_iot, led_jmp, led_jms, led_dca, led_isz, led_tad, led_and}; | ||
| 251 | assign led[7] = {2'b0, led_step_counter[4], led_step_counter[3], led_step_counter[2], led_step_counter[1], led_step_counter[0], led_run, led_pause, led_ion, led_break, led_current_address}; | ||
| 252 | assign led[8] = {5'b0, led_link, led_if[0], led_if[1], led_if[2], led_df[0], led_df[1], led_df[2]}; | ||
| 253 | |||
| 254 | core cpu | ||
| 255 | ( .clk(internal_clock) | ||
| 256 | , .reset(internal_reset) | ||
| 257 | |||
| 258 | , .switch_df(switch_df) | ||
| 259 | , .switch_if(switch_if) | ||
| 260 | , .switch_sr(switch_sr) | ||
| 261 | , .switch_start(switch_start) | ||
| 262 | , .switch_load_add(switch_load_add) | ||
| 263 | , .switch_dep(switch_dep) | ||
| 264 | , .switch_exam(switch_exam) | ||
| 265 | , .switch_cont(switch_cont) | ||
| 266 | , .switch_stop(switch_stop) | ||
| 267 | , .switch_sing_step(switch_sing_step) | ||
| 268 | , .switch_sing_inst(switch_sing_inst) | ||
| 269 | |||
| 270 | , .led_pc(led_pc) | ||
| 271 | , .led_memaddr(led_memaddr) | ||
| 272 | , .led_memdata(led_memdata) | ||
| 273 | , .led_acc(led_acc) | ||
| 274 | , .led_mq(led_mq) | ||
| 275 | , .led_and(led_and) | ||
| 276 | , .led_tad(led_tad) | ||
| 277 | , .led_isz(led_isz) | ||
| 278 | , .led_dca(led_dca) | ||
| 279 | , .led_jms(led_jms) | ||
| 280 | , .led_jmp(led_jmp) | ||
| 281 | , .led_iot(led_iot) | ||
| 282 | , .led_opr(led_opr) | ||
| 283 | , .led_fetch(led_fetch) | ||
| 284 | , .led_execute(led_execute) | ||
| 285 | , .led_defer(led_defer) | ||
| 286 | , .led_word_count(led_word_count) | ||
| 287 | , .led_current_address(led_current_address) | ||
| 288 | , .led_break(led_break) | ||
| 289 | , .led_ion(led_ion) | ||
| 290 | , .led_pause(led_pause) | ||
| 291 | , .led_run(led_run) | ||
| 292 | , .led_step_counter(led_step_counter) | ||
| 293 | , .led_df(led_df) | ||
| 294 | , .led_if(led_if) | ||
| 295 | , .led_link(led_link) | ||
| 296 | ); | ||
| 297 | |||
| 298 | endmodule | ||
