CPLD and Verilog Learning Experiment with 8 5x7 Displays
Posted: Tue Nov 25, 2025 5:01 am
Greetings,
I first got started with CPLD's with the CPLD trainer from plasmo. I only dabbled a bit from examples in books and others. This time I took on another challenge. I have a bunch of TIL305/LTP305/LRT1704 5x7 dot matrix displays. Also, some newer ones from Pimoroni. My goal? Output the hex value at a specific 32 bit address for some machine. In this case, an M68K type machine.
This project was started in August, and just now, got to the point where I can drive 8 of these displays. There are probably many ways to bite this beast, but I've used Maxim 6952/3's and some other devices that do all the hard work when multiplexing or charlieplexing. I decided to figure how to drive these bad boys with 2 CPLD's and supporting drive hardware.
All of this has been prototyped using Altera evaluation boards, ATF15xx boards, bread boards, darlington arrays (UDN2982A for the columns, ULN2803APG for the rows) AT28C16 (character ROM), etc. I've been simulating 32 bit data input from an external source.
It took quite a bit of work getting to this point, but starting with figuring out how to multiplex a 5x7 display, column scanning (programming a custom ring counter) and sending row data and keep it synced took quite a bit of effort. However, it is possible using 2 EPM7128/ATF1508AS CPLD's with supporting driving hardware.
I present the 8 digit 5x7 custom driver! Still a huge work in progress! (Only recently fabricated a PCB for the 5x7 displays with anode column/decimal point with cathode row limiting resistors.
Why do this? Because hardware was hanging around staring me in the face to do something with it.
I'm not the best with verilog and still quite the young guy with it. However I'll share what I have so, far.
The column scanning isn't demanding, but the row data driver is demanding and I have been able to get Quartus 13.0.1 Build 232 06/12/2013 SJ eb Edition with SP1 to build and get 107/128 (84%) macrocells after some tweaking.
For the column scanning (Using the ATF1508AS for this, use POF2JED and program with an ATF15xx programmer)
For the row data driver (Using the EPM7128SLC84-7 with the Altera UP1 Evaluation Board)
I first got started with CPLD's with the CPLD trainer from plasmo. I only dabbled a bit from examples in books and others. This time I took on another challenge. I have a bunch of TIL305/LTP305/LRT1704 5x7 dot matrix displays. Also, some newer ones from Pimoroni. My goal? Output the hex value at a specific 32 bit address for some machine. In this case, an M68K type machine.
This project was started in August, and just now, got to the point where I can drive 8 of these displays. There are probably many ways to bite this beast, but I've used Maxim 6952/3's and some other devices that do all the hard work when multiplexing or charlieplexing. I decided to figure how to drive these bad boys with 2 CPLD's and supporting drive hardware.
All of this has been prototyped using Altera evaluation boards, ATF15xx boards, bread boards, darlington arrays (UDN2982A for the columns, ULN2803APG for the rows) AT28C16 (character ROM), etc. I've been simulating 32 bit data input from an external source.
It took quite a bit of work getting to this point, but starting with figuring out how to multiplex a 5x7 display, column scanning (programming a custom ring counter) and sending row data and keep it synced took quite a bit of effort. However, it is possible using 2 EPM7128/ATF1508AS CPLD's with supporting driving hardware.
I present the 8 digit 5x7 custom driver! Still a huge work in progress! (Only recently fabricated a PCB for the 5x7 displays with anode column/decimal point with cathode row limiting resistors.
Why do this? Because hardware was hanging around staring me in the face to do something with it.
I'm not the best with verilog and still quite the young guy with it. However I'll share what I have so, far.
The column scanning isn't demanding, but the row data driver is demanding and I have been able to get Quartus 13.0.1 Build 232 06/12/2013 SJ eb Edition with SP1 to build and get 107/128 (84%) macrocells after some tweaking.
For the column scanning (Using the ATF1508AS for this, use POF2JED and program with an ATF15xx programmer)
Code: Select all
module ringcounter (CLK,CLK_DIV,SYNC,ANODE);
input CLK; // Clock input
output CLK_DIV; // Passthrough CLK for external device
output wire SYNC; // Sync for external row data driver
output reg [39:0] ANODE; // Internal Anode Scanning for 40 Columns
reg [5:0] cols;
assign CLK_DIV = CLK;
assign SYNC = ANODE[39]; // Sync on first anode column (For Row data driver)
always @ (posedge CLK) begin
ANODE[39:0] <= 1 << cols;
cols = cols + 1;
if (cols > 39) cols = 0;
end
endmoduleCode: Select all
module TIL305_02 (CLK,CLK_DIV,SYNC,ROMADDR,NIBBLE1,NIBBLE2,NIBBLE3,NIBBLE4,NIBBLE5,NIBBLE6,NIBBLE7,NIBBLE8);
input CLK; // Clock input
output wire CLK_DIV; // CLK passthrough for another device when needed (40 bit shift register)
input SYNC; // Sync with external column scan.
input [3:0] NIBBLE1; // First Digit
input [3:0] NIBBLE2; // Second Digit
input [3:0] NIBBLE3; // Third Digit
input [3:0] NIBBLE4; // Fourth Digit
input [3:0] NIBBLE5; // Fifth Digit
input [3:0] NIBBLE6; // Sixth Digit
input [3:0] NIBBLE7; // Seventh Digit
input [3:0] NIBBLE8; // Eighth Digit
output reg [6:0] ROMADDR; // 7 bit ROM Address
reg [5:0] cols = 1;
assign CLK_DIV = CLK;
always @ (posedge CLK) begin
if (SYNC == 1) cols = 0;
if (cols > 39) cols = 0;
case (cols)
0, 1, 2, 3, 4 : ROMADDR <= ( NIBBLE1 * 5 + (cols % 5));
5, 6, 7, 8, 9 : ROMADDR <= ( NIBBLE2 * 5 + (cols % 5));
10, 11, 12, 13, 14 : ROMADDR <= ( NIBBLE3 * 5 + (cols % 5));
15, 16, 17, 18, 19 : ROMADDR <= ( NIBBLE4 * 5 + (cols % 5));
20, 21, 22, 23, 24 : ROMADDR <= ( NIBBLE5 * 5 + (cols % 5));
25, 26, 27, 28, 29 : ROMADDR <= ( NIBBLE6 * 5 + (cols % 5));
30, 31, 32, 33, 34 : ROMADDR <= ( NIBBLE7 * 5 + (cols % 5));
default : ROMADDR <= ( NIBBLE8 * 5 + (cols % 5));
endcase
cols = cols + 1;
end
endmodule