From d5670b00879bddf3d64f9d9db468834018a4b078 Mon Sep 17 00:00:00 2001 From: ChUrl Date: Thu, 23 Mar 2023 21:30:10 +0100 Subject: [PATCH] Implement Counter/BCD/Segments --- BinToBcd.sv | 41 ++++++++++++++++++++++++++++++++++++++++ Counter.sv | 37 ++++++++++++++++++++++++++++++++++++ SegDriver.sv | 48 +++++++++++++++++++++++++++++++++++++++++++++++ SegmentDisplay.sv | 33 ++++++++++++++++++++++++++++++++ 4 files changed, 159 insertions(+) create mode 100644 BinToBcd.sv create mode 100644 Counter.sv create mode 100644 SegDriver.sv create mode 100644 SegmentDisplay.sv diff --git a/BinToBcd.sv b/BinToBcd.sv new file mode 100644 index 0000000..9794921 --- /dev/null +++ b/BinToBcd.sv @@ -0,0 +1,41 @@ +`default_nettype none + +// https://en.wikipedia.org/wiki/Double_dabble +module BinToBcd + #(parameter integer DIGITS = 4, + parameter integer WIDTH = 14)( + input var logic[WIDTH-1:0] binin, + output var logic[3:0] bcdout[DIGITS-1:0] +); + + // Easier to operate on a packed array + var logic[DIGITS*4-1:0] bcdscratch; + + integer ii, jj; + always @(binin) begin + bcdscratch = '0; + + // Iterate over each bit + for (ii = 0; ii < WIDTH; ii = ii + 1) begin + + // Iterate over each digit + for (jj = 0; jj < DIGITS; jj = jj + 1) begin + // Add three, if digit >= 5 + if (bcdscratch[(jj+1)*4-1 -: 4] >= 5) begin + // Select the digit: 1st digit [7:4], 2nd digit [11:8], etc. + // The -: or +: syntax specify the length of the slice + bcdscratch[(jj+1)*4-1 -: 4] = bcdscratch[(jj+1)*4-1 -: 4] + 3; + end + end + + // Shift to left and fill with lsb with corresponding binin bit + bcdscratch = {bcdscratch[DIGITS*4-2:0], binin[WIDTH-1-ii]}; + end + + // Iterate over each digit + for (jj = 0; jj < DIGITS; jj = jj + 1) begin + // Assign scratch buffer to bcdout + bcdout[jj] = bcdscratch[(jj+1)*4-1 -: 4]; + end + end +endmodule \ No newline at end of file diff --git a/Counter.sv b/Counter.sv new file mode 100644 index 0000000..ac0ebbb --- /dev/null +++ b/Counter.sv @@ -0,0 +1,37 @@ +`default_nettype none + +module Counter + #(parameter integer DIGITS = 4, + parameter integer WIDTH = 14)( + input var logic clock, + input var logic reset, + input var logic decrement, + output var logic[WIDTH-1:0] binout +); + + var logic[WIDTH-1:0] countervalue; + + always @(posedge clock or posedge reset) + if (reset) begin + // Reset the counter to 0 + countervalue <= '0; + end else if (~decrement) begin + // Increment the counter + if (countervalue == 10**DIGITS-1) begin + // Overflow + countervalue <= '0; + end else begin + countervalue <= countervalue + 1; + end + end else if (decrement) begin + // Decrement the Counter + if (countervalue == 0) begin + // Underflow + countervalue <= '{10**DIGITS-1}; + end else begin + countervalue <= countervalue - 1; + end + end + + assign binout = countervalue; +endmodule \ No newline at end of file diff --git a/SegDriver.sv b/SegDriver.sv new file mode 100644 index 0000000..d3f4f7a --- /dev/null +++ b/SegDriver.sv @@ -0,0 +1,48 @@ +`default_nettype none + +module SingleSegDriver( + input var logic[3:0] bcdin, + output var logic[6:0] segments +); + + // The segments are enabled on a low logic level + always_comb case (bcdin) + // +----a----+ + // | | + // f b + // | | + // +----g----+ + // | | + // e c + // | | + // +----d----+ gfedcba + 4'b0000: segments = ~7'b0111111; + 4'b0001: segments = ~7'b0000110; + 4'b0010: segments = ~7'b1011011; + 4'b0011: segments = ~7'b1001111; + 4'b0100: segments = ~7'b1100110; + 4'b0101: segments = ~7'b1101101; + 4'b0110: segments = ~7'b1111101; + 4'b0111: segments = ~7'b0000111; + 4'b1000: segments = ~7'b1111111; + 4'b1001: segments = ~7'b1100111; + default: segments = ~7'b0; + endcase +endmodule + +module SegDriver + #(parameter integer DIGITS = 4)( + input var logic[3:0] bcdin[DIGITS-1:0], + output var logic[6:0] segments[DIGITS-1:0] +); + + genvar ii; + generate + for (ii = 0; ii < DIGITS; ii = ii + 1) begin : generate_seg_drivers + SingleSegDriver ssd( + .bcdin(bcdin[ii]), + .segments(segments[ii]) + ); + end + endgenerate +endmodule \ No newline at end of file diff --git a/SegmentDisplay.sv b/SegmentDisplay.sv new file mode 100644 index 0000000..2fb518f --- /dev/null +++ b/SegmentDisplay.sv @@ -0,0 +1,33 @@ +`default_nettype none + +module SegmentDisplay + #(parameter integer DIGITS = 4, + parameter integer WIDTH = 14)( + input var logic reset, + input var logic clock, + input var logic decrement, + output var logic[6:0] segments[DIGITS-1:0] +); + + tri[WIDTH-1:0] cntout; + tri[3:0] bcdout[DIGITS-1:0]; + + Counter cnt( + // The KEY's provide a high logic level when not pressed + .clock(~clock), + .reset(~reset), + .decrement(decrement), + .binout(cntout) + ); + + BinToBcd bcd( + .binin(cntout), + .bcdout(bcdout) + ); + + SegDriver seg( + .bcdin(bcdout), + .segments(segments) + ); + +endmodule \ No newline at end of file