this is my first post so I hope I'm doing this correctly. I'm trying to output a "4 3 2 1" on a four digit seven segment display on a BASYS2 board. I have checked to make sure that 0 enables the signal and that I have the ports mapped correctly. I believe the error is within my multiplexing logic since I am only able to display a single digit. I'm new to Verilog (am used to C) and would appreciate any suggestions. Thanks
`timescale 1ns / 1ps
module main (clock, AN0, AN1, AN2, AN3, CA, CB, CC, CD, CE, CF, CG, CDP);
//USED FOR SEVEN SEG
input clock;
output AN0, AN1, AN2, AN3, CA, CB, CC, CD, CE, CF, CG, CDP;
reg [7:0] cathodedata; //cathode data
reg [3:0] anodedata; //anode data
reg [2:0] digit = 1;
reg [6:0] data;
reg setdp;
reg [19:0] counter = 0;
assign CA = cathodedata [7];
assign CB = cathodedata [6];
assign CC = cathodedata [5];
assign CD = cathodedata [4];
assign CE = cathodedata [3];
assign CF = cathodedata [2];
assign CG = cathodedata [1];
assign CDP = cathodedata [0];
assign AN3 = anodedata [3];
assign AN2 = anodedata [2];
assign AN1 = anodedata [1];
assign AN0 = anodedata [0];
//USED FOR SEVEN SEG
//Multiplexing
//Board Clock: 50MHz
//p = t*f
//t = 16ms
//p = 16ms * 50*10^6 = 800,000 cycles
//200,000 cycles for each digit
//Refreshed every 16ms (~60Hz)
always@(negedge clock)
begin
if (digit == 1)
begin
if (counter == 200_000)
begin
digit = 2;
end
else
begin
counter = counter + 1;
data = 4;
end
end
else if (digit == 2)
begin
if (counter == 400_000)
begin
digit = 3;
end
else
begin
counter = counter + 1;
data = 3;
end
end
else if (digit == 3)
begin
if (counter == 600_000)
begin
digit = 4;
end
else
begin
counter = counter + 1;
data = 2;
end
end
else if (digit == 4)
begin
if (counter == 800_000)
begin
digit = 1;
counter = 0;
end
else
begin
counter = counter + 1;
data = 1;
end
end
end
always @ (*)
begin
case (data)
6'd0: cathodedata = 8'b00000011; //0
6'd1: cathodedata = 8'b10011111; //1
6'd2: cathodedata = 8'b00100101; //2
6'd3: cathodedata = 8'b00001101; //3
6'd4: cathodedata = 8'b10011001; //4
6'd5: cathodedata = 8'b01001001; //5
6'd6: cathodedata = 8'b01000001; //6
6'd7: cathodedata = 8'b00011111; //7
6'd8: cathodedata = 8'b00000001; //8
6'd9: cathodedata = 8'b00001001; //9
6'd10: cathodedata = 8'b00010001; //A
6'd11: cathodedata = 8'b11000001; //B
6'd12: cathodedata = 8'b01100011; //C
6'd13: cathodedata = 8'b10000101; //D
6'd14: cathodedata = 8'b00100001; //E
6'd15: cathodedata = 8'b01110001; //F
default: cathodedata = 8'b11111111; //default all off
endcase
if (setdp == 1) //decimal point
cathodedata = cathodedata & 8'hFE;
case(digit)
0: anodedata = 4'b1111; //all OFF
4: anodedata = 4'b1110; //AN0
3: anodedata = 4'b1101; //AN1
2: anodedata = 4'b1011; //AN2
1: anodedata = 4'b0111; //AN3
default:
anodedata = 4'b1111; //all OFF
endcase
end
endmodule
Here's a modified version of one of my pet projects. It should do exactly as you wanted: display
4 3 2 1
on the 4dig7seg display. I tested it on an Amani GTX CPLD, and it should transfer cleanly to your board.I like separating projects into separate modules to keep organized. The top level module takes the on board clock as an input and outputs 14 signals to a four-digit-seven-segment serial display. Make sure the pins are correctly assigned.
Next I have a simple clock divider. The case count = 500 can be modified to divide your clock to whatever frequency you like. The output should look fine in the range of about 120 Hz to about 2 MHz.
Then we have to rotate the digits. Note if you change the anodes and cathodes at the "same" time, there will be a small leakage current into the neighboring segments causing a "ghost" effect.
Towards the end you have :
always @*
implies a combinatorial block, that is no flip-flop to break up loops etc. Your simulator may not have caught this but I would expect it to have real problems in synthesis.Basically you have cathodedata driving itself.
I would replace this with something like:
I too am using a basys2 and looking for a 7-seg driver. Nathan G's code did not work for me (using system verilog perhaps?), but I found this article: http://simplefpga.blogspot.co.uk/2012/12/scrolling-or-moving-text-using-7.html?showComment=1362783256904#c5783969326158067433 and I cannibalized it to my own ends.The modified code is below. It should take (although I haven't checked the decoding fully yet) four hex values and display them on the 7-seg. In my example my board now says 'FAAF' (because getting this working was faf)
ucf file taken from digilent site:
Top level module has this:
and the file I took from the guy in the link and have edited is:
Please excuse the horrible formatting/indenting - there is a combination of his, mine, and adding four spaces to get stack overflow to recognize it as code. I don't have time to make things pretty unfortunately. I can bundle all this together and put it on dropbox if you would like.
Nathan