From 77553d9ef424dd67b0ff8aa85205e47cae081602 Mon Sep 17 00:00:00 2001 From: sorgelig Date: Sat, 6 Mar 2021 05:18:35 +0800 Subject: [PATCH] Eliminate async clocks. --- rtl/keyboard.v | 49 ++++++++++++++++++++++++++++--------------------- rtl/zx8302.v | 34 ++++++++++++++++++++++++---------- 2 files changed, 52 insertions(+), 31 deletions(-) diff --git a/rtl/keyboard.v b/rtl/keyboard.v index 04b81a8..412e95b 100644 --- a/rtl/keyboard.v +++ b/rtl/keyboard.v @@ -61,27 +61,33 @@ wire x_f4 = specialD[10]|| js0[3]; wire x_f5 = specialD[11]|| js0[4]; // Divide 11MHz clock down to ~1khz some delay -wire clk_delay = clk_delay_cnt[12]; -reg [12:0] clk_delay_cnt; // 11MHz / 8192 = 1.342kHz -always @(posedge clk) - if (ce_11m) clk_delay_cnt <= clk_delay_cnt + 13'd1; +reg ce_1k; +always @(posedge clk) begin + reg [12:0] clk_delay_cnt; // 11MHz / 8192 = 1.342kHz + + ce_1k <= 0; + if (ce_11m) begin + clk_delay_cnt <= clk_delay_cnt + 1'd1; + ce_1k <= !clk_delay_cnt; + end +end // The "main" key of a combined modifier key needs to be delayed. Otherwise // the QL will not accept it. E.g. when pressing CTRL-LEFT, the CTRL key needs // to be pressed first. Pressing both at the same time won't work. We thus delay // the "other" key like e.g. the LEFT key. Both are released at the same time wire [11:1] specialD; -delay delay_1( .clk(clk_delay), .reset(reset), .in(special[1]), .out(specialD[1]) ); -delay delay_2( .clk(clk_delay), .reset(reset), .in(special[2]), .out(specialD[2]) ); -delay delay_3( .clk(clk_delay), .reset(reset), .in(special[3]), .out(specialD[3]) ); -delay delay_4( .clk(clk_delay), .reset(reset), .in(special[4]), .out(specialD[4]) ); -delay delay_5( .clk(clk_delay), .reset(reset), .in(special[5]), .out(specialD[5]) ); -delay delay_6( .clk(clk_delay), .reset(reset), .in(special[6]), .out(specialD[6]) ); -delay delay_7( .clk(clk_delay), .reset(reset), .in(special[7]), .out(specialD[7]) ); -delay delay_8( .clk(clk_delay), .reset(reset), .in(special[8]), .out(specialD[8]) ); -delay delay_9( .clk(clk_delay), .reset(reset), .in(special[9]), .out(specialD[9]) ); -delay delay_10(.clk(clk_delay), .reset(reset), .in(special[10]),.out(specialD[10])); -delay delay_11(.clk(clk_delay), .reset(reset), .in(special[11]),.out(specialD[11])); +delay delay_1( .clk(clk), .ce(ce_1k), .reset(reset), .in(special[1]), .out(specialD[1]) ); +delay delay_2( .clk(clk), .ce(ce_1k), .reset(reset), .in(special[2]), .out(specialD[2]) ); +delay delay_3( .clk(clk), .ce(ce_1k), .reset(reset), .in(special[3]), .out(specialD[3]) ); +delay delay_4( .clk(clk), .ce(ce_1k), .reset(reset), .in(special[4]), .out(specialD[4]) ); +delay delay_5( .clk(clk), .ce(ce_1k), .reset(reset), .in(special[5]), .out(specialD[5]) ); +delay delay_6( .clk(clk), .ce(ce_1k), .reset(reset), .in(special[6]), .out(specialD[6]) ); +delay delay_7( .clk(clk), .ce(ce_1k), .reset(reset), .in(special[7]), .out(specialD[7]) ); +delay delay_8( .clk(clk), .ce(ce_1k), .reset(reset), .in(special[8]), .out(specialD[8]) ); +delay delay_9( .clk(clk), .ce(ce_1k), .reset(reset), .in(special[9]), .out(specialD[9]) ); +delay delay_10(.clk(clk), .ce(ce_1k), .reset(reset), .in(special[10]),.out(specialD[10])); +delay delay_11(.clk(clk), .ce(ce_1k), .reset(reset), .in(special[11]),.out(specialD[11])); // map the special keys onto the matrix which is then or'd with the // normal matrix @@ -233,17 +239,18 @@ endmodule // add delay to special combo keys module delay ( input clk, + input ce, input reset, input in, output out ); -reg [3:0] delay_cnt; -assign out = (delay_cnt == 15); -wire delay_reset = reset || !in; -always @(posedge clk or posedge delay_reset) begin - if(delay_reset) delay_cnt <= 4'd0; - else if(delay_cnt != 15) delay_cnt <= delay_cnt + 4'd1; +reg [4:0] delay_cnt; +assign out = delay_cnt[4] & in; + +always @(posedge clk) begin + if(reset | ~in) delay_cnt <= 0; + else if(ce & ~&delay_cnt) delay_cnt <= delay_cnt + 1'd1; end endmodule // delay diff --git a/rtl/zx8302.v b/rtl/zx8302.v index 9000ec1..886e7b5 100644 --- a/rtl/zx8302.v +++ b/rtl/zx8302.v @@ -212,27 +212,36 @@ assign ipl = { ipc_ipl[1] && (irq_pending[4:0] == 0), ipc_ipl[0] }; // vsync irq is set whenever vsync rises reg vsync_irq; wire vsync_irq_reset = reset || irq_ack[3]; -always @(posedge vs or posedge vsync_irq_reset) begin - if(vsync_irq_reset) vsync_irq <= 1'b0; - else vsync_irq <= 1'b1; +always @(posedge clk) begin + reg old_vs; + + old_vs <= vs; + if(vsync_irq_reset) vsync_irq <= 1'b0; + else if(~old_vs & vs) vsync_irq <= 1'b1; end // toggling the mask will also trigger irqs ... wire gap_irq_in = mdv_gap && irq_mask[0]; reg gap_irq; wire gap_irq_reset = reset || irq_ack[0]; -always @(posedge gap_irq_in or posedge gap_irq_reset) begin - if(gap_irq_reset) gap_irq <= 1'b0; - else gap_irq <= 1'b1; +always @(posedge clk) begin + reg old_irq; + + old_irq <= gap_irq_in; + if(gap_irq_reset) gap_irq <= 1'b0; + else if(~old_irq & gap_irq_in) gap_irq <= 1'b1; end // toggling the mask will also trigger irqs ... wire xint_irq_in = xint && irq_mask[2]; reg xint_irq; wire xint_irq_reset = reset || irq_ack[4]; -always @(posedge xint_irq_in or posedge xint_irq_reset) begin - if(xint_irq_reset) xint_irq <= 1'b0; - else xint_irq <= 1'b1; +always @(posedge clk) begin + reg old_irq; + + old_irq <= xint_irq_in; + if(xint_irq_reset) xint_irq <= 1'b0; + else if(~old_irq & xint_irq_in) xint_irq <= 1'b1; end @@ -272,7 +281,12 @@ mdv mdv // the microdrive control register mctrl generates the drive selection reg [7:0] mdv_sel; -always @(negedge mctrl[1]) mdv_sel <= { mdv_sel[6:0], mctrl[0] }; +always @(posedge clk) begin + reg old_mctrl; + + old_mctrl <= mctrl[1]; + if(old_mctrl & ~mctrl[1]) mdv_sel <= { mdv_sel[6:0], mctrl[0] }; +end // --------------------------------------------------------------------------------- // -------------------------------------- RTC --------------------------------------