From 4a878b3d2924e74eb311b34df8b7c4091e6700bb Mon Sep 17 00:00:00 2001 From: Julian Blake Kongslie Date: Sun, 20 Mar 2022 17:27:02 -0700 Subject: Cleanup of PDP-8 core to support arbitrated memory protocol. No support yet for multiple words per line; otherwise complete. --- hdl/core.sv | 299 ++++++++++++++++++++++-------------------------------------- 1 file changed, 109 insertions(+), 190 deletions(-) (limited to 'hdl/core.sv') diff --git a/hdl/core.sv b/hdl/core.sv index 8bbea98..7fdd20a 100644 --- a/hdl/core.sv +++ b/hdl/core.sv @@ -1,80 +1,20 @@ `include "defs.svh" -`ifdef SYNTHESIS -`define lag(x) x -`else -`define lag(x) $past(x) -`endif - `define DATA_BITS 12 -module mem +module core + #( JTAG_INSTANCE = 1 + ) ( input bit clk , input bit reset - , output bit command_ready - , input bit command_valid - , input pdp_command_t command_data - - , input bit read_ready - , output bit read_valid - , output pdp_read_response_t read_data - ); - -parameter INIT_FILE; + , input bit mem_command_ready + , output bit mem_command_valid + , output pdp_command_t mem_command -bit hold_valid; -pdp_command_t hold; - -bit [`DATA_BITS-1:0] storage [0:(1 << `PDP_ADDRESS_BITS)-1]; -initial $readmemh(INIT_FILE, storage); - -always_ff @(posedge clk) begin - if (reset) begin - command_ready = 0; - read_valid = 0; - hold_valid = 0; - end else begin - if (read_ready) read_valid = 0; - - if (command_ready && command_valid) begin - hold_valid = 1; - hold = command_data; - end - - if (hold_valid && hold.write) begin -// for (int i = 0; i < `RAM_LINE_WORDS; ++i) begin - if (hold.mask[0]) begin - automatic pdp_word_address_t addr = 0; - addr[`PDP_ADDRESS_BITS-1:$clog2(`RAM_LINE_WORDS)] = hold.address; -// if (`RAM_LINE_WORDS != 1) -// addr[$clog2(`RAM_LINE_WORDS)-1:0] = i; - storage[addr] = hold.data[/*i*/0]; - end -// end - hold_valid = 0; - end else if (hold_valid && !read_valid) begin - read_valid = 1; - read_data.address = hold.address; - /*for (int i = 0; i < `RAM_LINE_WORDS; ++i)*/ begin - automatic pdp_word_address_t addr = 0; - addr[`PDP_ADDRESS_BITS-1:$clog2(`RAM_LINE_WORDS)] = hold.address; -// if (`RAM_LINE_WORDS != 1) -// addr[$clog2(`RAM_LINE_WORDS)-1:0] = i; - read_data.data[/*i*/0] = storage[addr]; - end - hold_valid = 0; - end - - command_ready = !hold_valid; - end -end - -endmodule - -module core - ( input bit clk - , input bit reset + , output bit mem_read_ready + , input bit mem_read_valid + , input pdp_read_response_t mem_read , input bit [2:0] switch_df , input bit [2:0] switch_if @@ -158,41 +98,14 @@ bit switch_cont_observed; assign led_run = run; assign led_ion = int_enable; -bit mem_ready; -bit mem_valid; -bit mem_write; -bit [`PDP_ADDRESS_BITS-1:0] mem_address; -bit [`DATA_BITS-1:0] mem_write_data; -assign led_current_address = mem_valid; - -assign led_memaddr = mem_address[`PDP_ADDRESS_BITS-3-1:0]; +assign led_current_address = mem_command_valid; -bit mem_read_valid; -bit [`DATA_BITS-1:0] mem_read_data; +assign led_memaddr = mem_command.address[`PDP_ADDRESS_BITS-3-1:0]; -pdp_command_t mem_command; -pdp_read_response_t mem_response; - -assign mem_command.address = mem_address; -assign mem_command.write = mem_write; -assign mem_command.data = mem_write_data; assign mem_command.mask = ~0; -assign mem_read_data = mem_response.data; - -mem - #( .INIT_FILE("mem/focal69.loaded.hex") - ) memory - ( .clk(clk) - , .reset(reset) - , .command_ready(mem_ready) - , .command_valid(mem_valid) - , .command_data(mem_command) - - , .read_ready(1) - , .read_valid(mem_read_valid) - , .read_data(mem_response) - ); +bit mem_hold_valid; +pdp_read_response_t mem_hold; bit rx_ready; bit rx_valid; @@ -203,7 +116,7 @@ bit tx_valid; bit [7:0] tx_data; alt_jtag_atlantic - #( .INSTANCE_ID(1) + #( .INSTANCE_ID(JTAG_INSTANCE) , .LOG2_RXFIFO_DEPTH(10) , .LOG2_TXFIFO_DEPTH(10) , .SLD_AUTO_INSTANCE_INDEX("NO") @@ -285,7 +198,6 @@ enum , PREINC , AGEN , EXEC - , MEMWAIT , HALT , DEPOSIT , RETIRE @@ -294,7 +206,7 @@ enum assign led_fetch = state == FETCH; assign led_execute = state == DECODE || state == AGEN || state == EXEC; assign led_defer = state == INDIRECT || state == INDIRECTED || state == PREINC; -assign led_pause = state == MEMWAIT || state == HALT; +assign led_pause = state == HALT; always_ff @(posedge clk) begin if (reset) begin @@ -310,7 +222,8 @@ always_ff @(posedge clk) begin switch_dep_observed = 0; switch_exam_observed = 0; switch_cont_observed = 0; - mem_valid = 0; + mem_command_valid = 0; + mem_hold_valid = 0; rx_ready = 0; tx_valid = 0; tto_delay = 0; @@ -330,12 +243,25 @@ always_ff @(posedge clk) begin tti_valid = 0; state = state.first; end else begin + if (mem_command_ready && mem_command_valid) begin + mem_command_valid = 0; + end + + if (mem_read_ready && mem_read_valid) begin + if (mem_read.address == mem_command.address) begin + mem_hold_valid = 1; + mem_hold = mem_read; + mem_hold.data &= 'hfff; + led_memdata = mem_hold.data; + end + end + if (switch_start && !switch_start_observed) begin switch_start_observed = 1; run = 1; int_enable = 0; int_delay = 0; - mem_valid = 0; + mem_command_valid = 0; acc = 0; link = 1; state = state.first; @@ -365,11 +291,11 @@ always_ff @(posedge clk) begin switch_dep_observed = 1; `endif state = DEPOSIT; - mem_valid = 1; - mem_address = {inst_field, pc}; - mem_write = 1; - mem_write_data = switch_sr; - led_memdata = mem_write_data; + mem_command_valid = 1; + mem_command.address = {inst_field, pc}; + mem_command.write = 1; + mem_command.data = switch_sr; + led_memdata = mem_command.data; run = 1; end @@ -398,7 +324,7 @@ always_ff @(posedge clk) begin if (switch_stop) run = 0; - if (`lag(tx_ready)) begin + if (tx_ready) begin if (tx_valid) tto_flag = 1; tx_valid = 0; @@ -407,9 +333,9 @@ always_ff @(posedge clk) begin tx_valid = 1; if (tto_delay != 0) --tto_delay; - if (rx_ready && `lag(rx_valid)) begin + if (rx_ready && rx_valid) begin tti_valid = 1; - tti_data = {4'b0, 1'b1, `lag(rx_data[6:0])}; + tti_data = {4'b0, 1'b1, rx_data[6:0]}; if (tti_data[6:0] == 7'h0a) tti_data[6:0] = 7'h0d; else if (tti_data[6:0] == 7'h1b) @@ -422,10 +348,11 @@ always_ff @(posedge clk) begin can_skip = 0; skip = 0; injected_instruction = 0; - mem_valid = 1; - mem_address = {inst_field, pc}; - mem_write = 0; - if (`lag(mem_ready)) begin + if (!mem_command_valid) begin + mem_command_valid = 1; + mem_command.address = {inst_field, pc}; + mem_command.write = 0; + mem_hold_valid = 0; state = DECODE; page = pc[`PDP_ADDRESS_BITS-3-1:7]; next_pc = pc + 1; @@ -435,8 +362,6 @@ always_ff @(posedge clk) begin DECODE: begin automatic bit go; go = 0; - mem_valid = 0; - mem_write = 0; `ifdef SYNTHESIS if (!switch_exam_observed && (int_enable && int_request)) begin `else @@ -458,10 +383,9 @@ always_ff @(posedge clk) begin next_pc = pc; injected_instruction = 1; go = 1; - end else if (`lag(mem_read_valid)) begin + end else if (mem_hold_valid) begin state = RETIRE; - led_memdata = `lag(mem_read_data); - {opcode, operand} = `lag(mem_read_data); + {opcode, operand} = mem_hold.data; if (switch_exam_observed) begin run = 0; end else begin @@ -694,27 +618,24 @@ always_ff @(posedge clk) begin end INDIRECT: begin - mem_valid = 1; - mem_write = 0; - mem_address = address; - state = `lag(mem_ready) ? INDIRECTED : INDIRECT; + if (!mem_command_valid) begin + mem_command_valid = 1; + mem_command.write = 0; + mem_command.address = address; + mem_hold_valid = 0; + state = INDIRECTED; + end end INDIRECTED: begin - if (`lag(mem_ready)) begin - mem_valid = 0; - mem_write = 0; - end - if (`lag(mem_read_valid)) begin + if (mem_hold_valid) begin if (opcode != 'o5 && address[7:3] == 5'b00001) begin - led_memdata = `lag(mem_read_data); - address = {3'b0, `lag(mem_read_data)}; + address = {3'b0, mem_hold.data}; address += 1; address[`PDP_ADDRESS_BITS-1:`PDP_ADDRESS_BITS-3] = data_field; state = PREINC; end else begin - led_memdata = `lag(mem_read_data); - address = {data_field, `lag(mem_read_data)}; + address = {data_field, mem_hold.data}; case (opcode) 'o0, 'o1, 'o2: state = AGEN; 'o3, 'o4: state = EXEC; @@ -730,73 +651,73 @@ always_ff @(posedge clk) begin end PREINC: begin - mem_valid = 1; - mem_write = 1; - mem_write_data = address[`DATA_BITS-1:0]; - led_memdata = mem_write_data; - $display("preinc [%o] <- %o", mem_address, mem_write_data); - case (opcode) - 'o0, 'o1, 'o2: state = `lag(mem_ready) ? AGEN : PREINC; - 'o3, 'o4, 'o5: state = `lag(mem_ready) ? EXEC : PREINC; - endcase + if (!mem_command_valid) begin + mem_command_valid = 1; + mem_command.write = 1; + mem_command.data = address[`DATA_BITS-1:0]; + mem_hold_valid = 0; + led_memdata = mem_command.data; + $display("preinc [%o] <- %o", mem_command.address, mem_command.data); + case (opcode) + 'o0, 'o1, 'o2: state = AGEN; + 'o3, 'o4, 'o5: state = EXEC; + endcase + end end AGEN: begin - mem_valid = 1; - case (opcode) - 'o0, 'o1, 'o2: mem_write = 0; - endcase - mem_address = address; - state = `lag(mem_ready) ? EXEC : AGEN; + if (!mem_command_valid) begin + mem_command_valid = 1; + case (opcode) + 'o0, 'o1, 'o2: mem_command.write = 0; + endcase + mem_command.address = address; + mem_hold_valid = 0; + state = EXEC; + end end EXEC: begin - automatic bit stall = 0; - if (`lag(mem_ready)) begin - mem_valid = 0; - mem_write = 0; - end else if (mem_valid) begin - stall = 1; - end + automatic bit stall = mem_command_valid; case (opcode) - 'o0, 'o1, 'o2: if (! `lag(mem_read_valid)) stall = 1; + 'o0, 'o1, 'o2: if (! mem_hold_valid) stall = 1; endcase if (! stall) begin state = RETIRE; case (opcode) - 'o0: begin led_memdata = `lag(mem_read_data); acc &= `lag(mem_read_data); end - 'o1: begin led_memdata = `lag(mem_read_data); {link, acc} += {1'b0, `lag(mem_read_data)}; end + 'o0: begin acc &= mem_hold.data; end + 'o1: begin {link, acc} += {1'b0, mem_hold.data}; end 'o2: begin - mem_valid = 1; - mem_address = address; - mem_write = 1; - mem_write_data = `lag(mem_read_data) + 1; - led_memdata = mem_write_data; - $display("store [%o] <- %o", mem_address, mem_write_data); + mem_command_valid = 1; + mem_command.address = address; + mem_command.write = 1; + mem_command.data = (mem_hold.data + 1) & 'hfff; + mem_hold_valid = 0; + led_memdata = mem_command.data; + $display("store [%o] <- %o", mem_command.address, mem_command.data); can_skip = 1; - if (mem_write_data == 0) skip = 1; - state = MEMWAIT; + if (mem_command.data == 0) skip = 1; end 'o3: begin - mem_valid = 1; - mem_address = address; - mem_write = 1; - mem_write_data = acc; - led_memdata = mem_write_data; - $display("store [%o] <- %o", mem_address, mem_write_data); + mem_command_valid = 1; + mem_command.address = address; + mem_command.write = 1; + mem_command.data = acc; + mem_hold_valid = 0; + led_memdata = mem_command.data; + $display("store [%o] <- %o", mem_command.address, mem_command.data); acc = 0; - state = MEMWAIT; end 'o4: begin - mem_valid = 1; - mem_address = address; - mem_write = 1; - mem_write_data = next_pc[`DATA_BITS-1:0]; - led_memdata = mem_write_data; - $display("store [%o] <- %o", mem_address, mem_write_data); + mem_command_valid = 1; + mem_command.address = address; + mem_command.write = 1; + mem_command.data = next_pc[`DATA_BITS-1:0]; + mem_hold_valid = 0; + led_memdata = mem_command.data; + $display("store [%o] <- %o", mem_command.address, mem_command.data); next_pc = address[`PDP_ADDRESS_BITS-3-1:0] + 1; inst_field = inst_field_buffer; - state = MEMWAIT; end 'o5: begin next_pc = address[`PDP_ADDRESS_BITS-3-1:0]; @@ -806,8 +727,6 @@ always_ff @(posedge clk) begin end end - MEMWAIT: state = `lag(mem_ready) ? RETIRE : MEMWAIT; - HALT: begin run = 0; $display("\nhalt state reached"); @@ -815,12 +734,10 @@ always_ff @(posedge clk) begin end DEPOSIT: begin - if (`lag(mem_ready)) begin - state = FETCH; // Not a retired instruction; go directly to decode - page = pc[`PDP_ADDRESS_BITS-3-1:7]; - ++pc; // Not a skip; normal part of panel deposit (because we are skipping RETIRE) - run = 0; - end + state = FETCH; // Not a retired instruction; go directly to decode + page = pc[`PDP_ADDRESS_BITS-3-1:7]; + ++pc; // Not a skip; normal part of panel deposit (because we are skipping RETIRE) + run = 0; end endcase @@ -878,6 +795,8 @@ always_ff @(posedge clk) begin rx_ready = !tti_valid; end + + mem_read_ready = !mem_hold_valid; end end -- cgit v1.2.3