From ca0c557e2c61e2fc6cc97482a17f68fd2ee61392 Mon Sep 17 00:00:00 2001 From: Julian Blake Kongslie Date: Sun, 5 Dec 2021 15:16:41 -0800 Subject: Implement DF and IF, and Dep and Exam switches. --- hdl/core.sv | 259 ++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 172 insertions(+), 87 deletions(-) (limited to 'hdl/core.sv') diff --git a/hdl/core.sv b/hdl/core.sv index b607e4b..34a1e44 100644 --- a/hdl/core.sv +++ b/hdl/core.sv @@ -1,7 +1,7 @@ `include "util.svh" module core - #( ADDR_BITS = 12 + #( ADDR_BITS = 15 , DATA_BITS = 12 ) ( input bit clk @@ -9,7 +9,7 @@ module core , input bit [2:0] switch_df , input bit [2:0] switch_if - , input bit [ADDR_BITS-1:0] switch_sr + , input bit [ADDR_BITS-3-1:0] switch_sr , input bit switch_start , input bit switch_load_add , input bit switch_dep @@ -20,8 +20,8 @@ module core , input bit switch_sing_inst // verilator lint_off UNDRIVEN - , output bit [ADDR_BITS-1:0] led_pc - , output bit [ADDR_BITS-1:0] led_memaddr + , output bit [ADDR_BITS-3-1:0] led_pc + , output bit [ADDR_BITS-3-1:0] led_memaddr , output bit [DATA_BITS-1:0] led_memdata , output bit [DATA_BITS-1:0] led_acc , output bit [DATA_BITS-1:0] led_mq @@ -70,9 +70,7 @@ bit [ADDR_BITS-1:0] mem_address; bit [DATA_BITS-1:0] mem_write_data; assign led_current_address = mem_valid; -assign led_df = switch_df; // FIXME actually implement DF and IF -assign led_if = switch_if; -assign led_memaddr = mem_address; +assign led_memaddr = mem_address[ADDR_BITS-3-1:0]; bit mem_read_valid; bit [DATA_BITS-1:0] mem_read_data; @@ -80,8 +78,8 @@ bit [DATA_BITS-1:0] mem_read_data; mem #( .ADDR_BITS(ADDR_BITS) , .DATA_BITS(DATA_BITS) -// , .INIT_FILE("mem/focal69.loaded.hex") - , .INIT_FILE("build/mem/hello.hex") + , .INIT_FILE("mem/focal69.loaded.hex") +// , .INIT_FILE("build/mem/hello.hex") ) memory ( .clk(clk) @@ -120,14 +118,23 @@ jtag_uart , .tx_data(tx_data) ); -bit [ADDR_BITS-1:7] page; +bit [ADDR_BITS-3-1:7] page; -bit [ADDR_BITS-1:0] pc; +bit [2:0] data_field; +bit [2:0] data_field_saved; +bit [2:0] inst_field; +bit [2:0] inst_field_buffer; +bit [2:0] inst_field_saved; +bit [ADDR_BITS-3-1:0] pc; +assign led_pc = pc; bit [2:0] opcode; bit [8:0] operand; bit [DATA_BITS-1:0] acc; bit link; +assign led_df = data_field; +assign led_if = inst_field; + assign led_acc = acc; assign led_link = link; @@ -163,16 +170,21 @@ enum , EXEC , MEMWAIT , HALT + , DEPOSIT } state; -assign led_fetch = state == FETCH || state == DECODE; -assign led_execute = state == AGEN || state == EXEC; +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; always_ff @(posedge clk) begin if (reset) begin +`ifdef SYNTHESIS run = 0; +`else + run = 1; +`endif int_enable = 0; int_delay = 0; switch_start_observed = 0; @@ -184,8 +196,12 @@ always_ff @(posedge clk) begin rx_ready = 0; tx_valid = 0; tx_data = 0; + data_field = 0; + data_field_saved = 0; + inst_field = 0; + inst_field_buffer = 0; + inst_field_saved = 0; pc = 'o200; - led_pc = pc; acc = 0; link = 1; tti_int_enable = 0; @@ -208,22 +224,42 @@ always_ff @(posedge clk) begin if (switch_load_add && !switch_load_add_observed) begin switch_load_add_observed = 1; + data_field = switch_df; + inst_field = switch_if; + inst_field_buffer = switch_if; pc = switch_sr; - led_pc = pc; end if (!switch_load_add) switch_load_add_observed = 0; +`ifdef HISTORIC_SWITCH_BEHAVIOUR + if (switch_dep) + switch_dep_observed = 1; + + if (!switch_dep && switch_dep_observed) begin +`else if (switch_dep && !switch_dep_observed) 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; + run = 1; end if (!switch_dep) switch_dep_observed = 0; if (switch_exam && !switch_exam_observed) begin - switch_exam_observed = 1; + if (!run) begin + switch_exam_observed = 1; + state = FETCH; + run = 1; + end end if (!switch_exam) @@ -250,12 +286,11 @@ always_ff @(posedge clk) begin case (state) FETCH: begin mem_valid = 1; - mem_address = pc; + mem_address = {inst_field, pc}; mem_write = 0; if (`lag(mem_ready)) begin state = DECODE; - page = pc[ADDR_BITS-1:7]; - led_pc = pc; + page = pc[ADDR_BITS-3-1:7]; ++pc; end end @@ -265,18 +300,27 @@ always_ff @(posedge clk) begin go = 0; mem_valid = 0; mem_write = 0; - if (int_enable && int_request) begin + if (!switch_exam_observed && (int_enable && int_request)) begin int_enable = 0; int_delay = 0; + data_field_saved = data_field; + inst_field_saved = inst_field; + data_field = 0; + inst_field = 0; + inst_field_buffer = 0; --pc; opcode = 'b100; - operand = 'b000000; + operand = 'b000000000; go = 1; end else if (`lag(mem_read_valid)) begin state = FETCH; led_memdata = `lag(mem_read_data); {opcode, operand} = `lag(mem_read_data); - go = 1; + if (switch_exam_observed) begin + run = 0; + end else begin + go = 1; + end end if (go) begin int_enable = int_delay; @@ -286,9 +330,9 @@ always_ff @(posedge clk) begin // verilator lint_on WIDTH {i, z, wip} = operand; if (z) - address = {page, wip}; + address = {inst_field, page, wip}; else - address = {5'b0, wip}; + address = {inst_field, 5'b0, wip}; case (opcode) 'o0, 'o1, 'o2: state = i ? INDIRECT : AGEN; 'o3, 'o4: state = i ? INDIRECT : EXEC; @@ -296,7 +340,8 @@ always_ff @(posedge clk) begin if (i) begin state = INDIRECT; end else begin - pc = address; + pc = address[ADDR_BITS-3-1:0]; + inst_field = inst_field_buffer; end end 'o7: begin @@ -358,73 +403,98 @@ always_ff @(posedge clk) begin endcase end 'o6: begin - case (operand[8:3]) - 'o00: begin - case (operand[2:0]) + case (operand[8:6]) + 'o0: begin + case (operand[5:3]) 'o0: begin - if (int_enable) - ++pc; - int_enable = 0; - int_delay = 0; - end - 'o1: int_delay = 1; - 'o2: begin - int_enable = 0; - int_delay = 0; + case (operand[2:0]) + 'o0: begin + if (int_enable) + ++pc; + int_enable = 0; + int_delay = 0; + end + 'o1: int_delay = 1; + 'o2: begin + int_enable = 0; + int_delay = 0; + end + 'o3: begin + if (int_request) + ++pc; + end + 'o4: acc = {link, 1'b0/*gt*/, int_request, 1'b0/*ii*/, int_enable, 1'b0/*u*/, 3'b0/*if*/, 3'b0/*df*/}; + 'o5: begin + link = acc[11]; + if (acc[7]) begin + int_delay = 1; + end else begin + int_enable = 0; + int_delay = 0; + end + end + 'o7: begin + int_enable = 0; + int_delay = 0; + acc = 0; + link = 1; + tx_valid = 0; + tti_valid = 0; + end + default: $display("%o: unsupported 600%o op", pc-1, operand[2:0]); + endcase end 'o3: begin - if (int_request) - ++pc; - end - 'o4: acc = {link, 1'b0/*gt*/, int_request, 1'b0/*ii*/, int_enable, 1'b0/*u*/, 3'b0/*if*/, 3'b0/*df*/}; - 'o5: begin - link = acc[11]; - if (acc[7]) begin - int_delay = 1; - end else begin - int_enable = 0; - int_delay = 0; - end - end - 'o7: begin - int_enable = 0; - int_delay = 0; - acc = 0; - link = 1; - tx_valid = 0; - tti_valid = 0; - end - default: $display("%o: unsupported 600%o op", pc-1, operand[2:0]); - endcase - end - 'o03: begin - case (operand[2:0]) - 'o1: if (tti_valid) pc++; - 'o5: begin - tti_int_enable = acc[0]; + case (operand[2:0]) + 'o1: if (tti_valid) pc++; + 'o5: begin + tti_int_enable = acc[0]; + end + 'o6: begin + acc = tti_data; + tti_valid = 0; + end + default: begin + $display("%o: unsupported keyboard op %o", pc-1, operand[2:0]); + $finish; + end + endcase end - 'o6: begin - acc = tti_data; - tti_valid = 0; + 'o4: begin + case (operand[2:0]) + 'o1: if (!tx_valid) pc++; + 'o6: begin + tx_valid = 1; + tx_data = {1'b0, acc[6:0]}; + end + default: begin + $display("%o: unsupported tty op %o", pc-1, operand[2:0]); + $finish; + end + endcase end default: begin - $display("%o: unsupported keyboard op %o", pc-1, operand[2:0]); - $finish; + $display("%o: unsupported device %o (operation %o)", pc-1, operand[8:3], operand[2:0]); end endcase end - 'o04: begin - case (operand[2:0]) - 'o1: if (!tx_valid) pc++; - 'o6: begin - tx_valid = 1; - tx_data = {1'b0, acc[6:0]}; + 'o2: begin + if (operand[0]) + data_field = operand[5:3]; + if (operand[1]) + inst_field_buffer = operand[5:3]; + if (operand[2]) begin + if (operand[3] && operand[4]) + acc = acc | {6'b0, inst_field_saved, data_field_saved}; + else if (operand[3]) + acc = acc | {6'b0, data_field, 3'b0}; + else if (operand[4]) + acc = acc | {6'b0, inst_field, 3'b0}; + if (operand[5]) begin + data_field = data_field_saved; + inst_field_buffer = inst_field_saved; end - default: begin - $display("%o: unsupported tty op %o", pc-1, operand[2:0]); - $finish; - end - endcase + end end default: begin $display("%o: unsupported device %o (operation %o)", pc-1, operand[8:3], operand[2:0]); @@ -454,17 +524,19 @@ always_ff @(posedge clk) begin if (`lag(mem_read_valid)) begin if (address[7:3] == 5'b00001) begin led_memdata = `lag(mem_read_data); - address = {{(ADDR_BITS - DATA_BITS){1'b0}}, `lag(mem_read_data)}; + address = {3'b0, `lag(mem_read_data)}; address += 1; + address[ADDR_BITS-1:ADDR_BITS-3] = data_field; state = PREINC; end else begin led_memdata = `lag(mem_read_data); - address = {{(ADDR_BITS - DATA_BITS){1'b0}}, `lag(mem_read_data)}; + address = {data_field, `lag(mem_read_data)}; case (opcode) 'o0, 'o1, 'o2: state = AGEN; 'o3, 'o4: state = EXEC; 'o5: begin - pc = address; + pc = address[ADDR_BITS-3-1:0]; + inst_field = inst_field_buffer; state = FETCH; end endcase @@ -532,10 +604,14 @@ always_ff @(posedge clk) begin mem_write = 1; mem_write_data = pc[DATA_BITS-1:0]; led_memdata = mem_write_data; - pc = address + 1; + pc = address[ADDR_BITS-3-1:0] + 1; + inst_field = inst_field_buffer; state = MEMWAIT; end - 'o5: pc = address; + 'o5: begin + pc = address[ADDR_BITS-3-1:0]; + inst_field = inst_field_buffer; + end endcase end end @@ -547,6 +623,15 @@ always_ff @(posedge clk) begin $display("\nhalt state reached"); $finish; end + + DEPOSIT: begin + if (`lag(mem_ready)) begin + state = FETCH; + page = pc[ADDR_BITS-3-1:7]; + ++pc; + run = 0; + end + end endcase if (switch_sing_step) -- cgit v1.2.3