module segdisplay(clk,enable,value,anodes,segments,tick);
parameter SIMULATE = 0;
input clk,enable;
input [15:0] value;
output [3:0] anodes;
output [7:0] segments;
output tick;
reg [15:0] latched_value;
/* replaced by LFSR below
parameter CLKHZ = 50000000;
reg [27:0] clk_divider;
reg tick;
always @ (posedge clk)
begin
tick <= clk_divider == (CLKHZ/1000 - 2);
clk_divider <= tick ? 0 : clk_divider+1;
end
*/
// Build a clock divider using an LFSR -- it should be smaller/faster
// than the counter commented out above.
// 50Mhz/(2^17 - 1) = ~300Hz => 75Hz refresh rate for each of the 4 digits.
// 17-bit LFSR with period of 2^17 - 1 (see Xilinx App Note 52). Use
// XNOR feedback so that lock-up state is all ones instead of all
// zeroes since the register will be zero on power-up.
reg [17:1] lfsr;
always @ (posedge clk) lfsr <= {lfsr[16:1],~(lfsr[17] ^ lfsr[14])};
wire tick = SIMULATE | lfsr==0; // decode a specific state (doesn't matter which one)
// cycle through the 4 digits
reg [1:0] display;
always @ (posedge clk) if (tick) display <= display + 1;
// latch value to be displayed at the start of each cycle
always @ (posedge clk) if (tick && display==3) latched_value <= value;
reg [3:0] digit,anodes;
reg [7:0] segments;
always @ (enable or display or latched_value) begin
// select hex digit from latched value (digit)
// turn on appropriate digit of display (anodes)
if (enable)
case (display)
0: begin digit = latched_value[3:0]; anodes = 4'b1110; end
1: begin digit = latched_value[7:4]; anodes = 4'b1101; end
2: begin digit = latched_value[11:8]; anodes = 4'b1011; end
3: begin digit = latched_value[15:12]; anodes = 4'b0111; end
endcase
else anodes = 4'b1111;
end
// hex digit -> 7-segment display
// segments[0] = top segment (a)
// segments[1] = top right segment (b)
// segments[2] = bottom right segment (c)
// segments[3] = bottom segment (d)
// segments[4] = bottom left segment (e)
// segments[5] = top left segment (f)
// segments[6] = middle segment (g)
// segments[7] = decimal point
always @ (digit) begin
case (digit)
4'h0: segments[6:0] = ~7'b0111111;
4'h1: segments[6:0] = ~7'b0000110;
4'h2: segments[6:0] = ~7'b1011011;
4'h3: segments[6:0] = ~7'b1001111;
4'h4: segments[6:0] = ~7'b1100110;
4'h5: segments[6:0] = ~7'b1101101;
4'h6: segments[6:0] = ~7'b1111101;
4'h7: segments[6:0] = ~7'b0000111;
4'h8: segments[6:0] = ~7'b1111111;
4'h9: segments[6:0] = ~7'b1100111;
4'hA: segments[6:0] = ~7'b1110111;
4'hB: segments[6:0] = ~7'b1111100;
4'hC: segments[6:0] = ~7'b1011000;
4'hD: segments[6:0] = ~7'b1011110;
4'hE: segments[6:0] = ~7'b1111001;
4'hF: segments[6:0] = ~7'b1110001;
endcase
segments[7] = ~1'b0; // decimal point
end
endmodule