module logic_analyzer ( clk_speed, OSC, size, PIC_clk, read_storeb, clk_sel, clk_div, RST, OE, WR, done, AD ); input [2:0] clk_speed; input OSC, RST, PIC_clk, read_storeb, clk_sel; input [2:0] size; output OE, WR, done, clk_div; output [16:0] AD; wire counter_clk, counter_clk_by2, current_clk, CS, OE_inv, WR_inv; clock_divider my_clock_divider ( .clk_speed(clk_speed), .OSC(OSC), .clk_div(clk_div) ); counter_clk_stop my_counter_clk_stop ( .clk(current_clk), .RST(RST), .size(size), .AD(AD), .counter_clk(counter_clk_by2), .done(done) ); DFF my_DFF ( .CLK(counter_clk_by2), .Q(counter_clk) ); CS_generator my_CS_generator ( .clk(counter_clk_by2), .RST(RST), .CS(CS) ); read_write_selector my_read_write_selector ( .read_storeb(read_storeb), .CS(CS), .OE(OE_inv), .WR(WR_inv) ); assign OE = !OE_inv; assign WR = !WR_inv; counter my_counter ( .clk(counter_clk), .AD(AD), .RST(RST) ); choose_clk my_choose_clk ( .clk_div(clk_div), .PIC_clk(PIC_clk), .clk_sel(clk_sel), .current_clk(current_clk) ); endmodule // module read_write_selector // drives the appropriat pin (either the write pin or the OE pin) // on the memory depending on read_storeb module read_write_selector ( read_storeb, CS, OE, WR ); input read_storeb, CS; output OE, WR; reg OE, WR; always @ (CS) begin if (read_storeb) begin OE = CS; WR = 1'b0; end else begin OE = 1'b0; WR = CS; end end endmodule // module choose_clk // lets the PIC select which clock to use, the clock from the clock divider // or the PIC clocking itself module choose_clk ( clk_div, PIC_clk, clk_sel, current_clk ); input clk_div, PIC_clk, clk_sel; output current_clk; reg current_clk; always @ (clk_div or PIC_clk) begin case (clk_sel) 1'b0: current_clk = PIC_clk; 1'b1: current_clk = clk_div; endcase end endmodule // module posedge_DFF // a resetable D flip flop triggered on the positive clock edge module posedge_DFF ( CLK, RST, D, Q ); input CLK, RST, D; output Q; reg Q; always @ (posedge CLK or posedge RST) begin if (RST) Q = 0; else Q = D; end endmodule // module negedge_DFF // a resetable D flip flop triggered on the NEGATIVE clock edge module negedge_DFF ( CLK, RST, D, Q ); input CLK, RST, D; output Q; reg Q; always @ (negedge CLK or posedge RST) begin if (RST) Q = 0; else Q = D; end endmodule module CS_generator ( clk, RST, CS ); input clk, RST; output CS; reg CS_internal; initial CS_internal = 0; assign CS = CS_internal & !RST; always @ (negedge clk) begin CS_internal = !CS_internal; end endmodule // module counter_clk_stop // constantly looks at the output of the counter and compares it // with the max value set by size, if there is a match it stops // the counter's clock. Indirectly reset by the counter's reset // signal (since the output of the counter would no longer match) module counter_clk_stop ( clk, RST, size, AD, counter_clk, done ); input clk, RST; input [2:0] size; input [16:0] AD; output counter_clk, done; reg done_internal; reg [16:0] size_value; always @ (AD or size_value) begin if (AD == size_value) done_internal = 1; else done_internal = 0; end negedge_DFF my_negedge_DFF ( .D(done_internal), .CLK(clk), .Q(done_internal2) ); posedge_DFF my_posedge_DFF ( .D(done_internal2), .CLK(clk), .Q(done) ); assign counter_clk = clk && !done; always @ (size) begin case (size [2:0]) 3'b000: size_value = 17'h3ff; 3'b001: size_value = 17'h7ff; 3'b010: size_value = 17'hfff; 3'b011: size_value = 17'h1fff; 3'b100: size_value = 17'h3fff; 3'b101: size_value = 17'h7fff; 3'b110: size_value = 17'hffff; 3'b111: size_value = 17'h1ffff; endcase end endmodule // module counter // a simple counter, most of the control (stopping the counter, etc.) is // handled by other modules module counter ( clk, AD, RST ); input clk, RST; output [16:0] AD; reg [16:0] AD; always @ (posedge clk or posedge RST) begin if (RST) AD = 0; else AD = AD + 1; end endmodule // module clock_divider // divides the OSC signal by clk_speed to the power of two module clock_divider ( clk_speed, OSC, clk_div ); input [2:0] clk_speed; input OSC; output clk_div; reg clk_div; wire clk_2, clk_3, clk_4, clk_5, clk_6, clk_7, clk_8; always @ (OSC) begin case (clk_speed [2:0]) 3'b000: clk_div = OSC; 3'b001: clk_div = clk_2; 3'b010: clk_div = clk_3; 3'b011: clk_div = clk_4; 3'b100: clk_div = clk_5; 3'b101: clk_div = clk_6; 3'b110: clk_div = clk_7; 3'b111: clk_div = clk_8; endcase end DFF dff0 ( .CLK(OSC), .Q(clk_2) ); DFF dff1 ( .CLK(clk_2), .Q(clk_3) ); DFF dff2 ( .CLK(clk_3), .Q(clk_4) ); DFF dff3 ( .CLK(clk_4), .Q(clk_5) ); DFF dff4 ( .CLK(clk_5), .Q(clk_6) ); DFF dff5 ( .CLK(clk_6), .Q(clk_7) ); DFF dff6 ( .CLK(clk_7), .Q(clk_8) ); endmodule // module DFF // a simple flip flop module DFF ( CLK, Q ); input CLK; output Q; reg Q; initial Q = 0; always @ (posedge CLK) begin Q = !Q; end endmodule