LED Matrix Logic - Page 1
Forum section: electronics / general

author: Foxxz
author_rank: Regular Contributor
timestamp: May 26, 2022, 04:23:34 pm
content: I wanted to write a verilog module to drive a led matrix (schematic attached). For now I just wanted to drive the left side (matrix A) and address the LEDs 0-71 from left to right, top to bottom.I wanted to parameterize the number of matrix lines in verilog module but couldn't figure out a way to write the decode logic based on the parameter (IE - 9 in this case). If not that then using a generate block to build the case statement.Sometimes I miss the obvious so please point it out to me if I have.Code:module led_matrix (input [6:0] pixel_addr,input led_sig,output reg [8:0] matrix);always @(*) beginif (!led_sig)matrix <= 9'bz;elsecase(pixel_addr)0 : matrix <= 9'b01zzzzzzz;1 : matrix <= 9'b0z1zzzzzz;2 : matrix <= 9'b0zz1zzzzz;3 : matrix <= 9'b0zzz1zzzz;4 : matrix <= 9'b0zzzz1zzz;5 : matrix <= 9'b0zzzzz1zz;6 : matrix <= 9'b0zzzzzz1z;7 : matrix <= 9'b0zzzzzzz1;8 : matrix <= 9'b10zzzzzzz;9 : matrix <= 9'bz01zzzzzz;10 : matrix <= 9'bz0z1zzzzz;11 : matrix <= 9'bz0zz1zzzz;12 : matrix <= 9'bz0zzz1zzz;13 : matrix <= 9'bz0zzzz1zz;14 : matrix <= 9'bz0zzzzz1z;15 : matrix <= 9'bz0zzzzzz1;16 : matrix <= 9'b1z0zzzzzz;17 : matrix <= 9'bz10zzzzzz;18 : matrix <= 9'bzz01zzzzz;19 : matrix <= 9'bzz0z1zzzz;20 : matrix <= 9'bzz0zz1zzz;21 : matrix <= 9'bzz0zzz1zz;22 : matrix <= 9'bzz0zzzz1z;23 : matrix <= 9'bzz0zzzzz1;24 : matrix <= 9'b1zz0zzzzz;25 : matrix <= 9'bz1z0zzzzz;26 : matrix <= 9'bzz10zzzzz;27 : matrix <= 9'bzzz01zzzz;28 : matrix <= 9'bzzz0z1zzz;29 : matrix <= 9'bzzz0zz1zz;30 : matrix <= 9'bzzz0zzz1z;31 : matrix <= 9'bzzz0zzzz1;32 : matrix <= 9'b1zzz0zzzz;33 : matrix <= 9'bz1zz0zzzz;34 : matrix <= 9'bzz1z0zzzz;35 : matrix <= 9'bzzz10zzzz;36 : matrix <= 9'bzzzz01zzz;37 : matrix <= 9'bzzzz0z1zz;38 : matrix <= 9'bzzzz0zz1z;39 : matrix <= 9'bzzzz0zzz1;40 : matrix <= 9'b1zzzz0zzz;41 : matrix <= 9'bz1zzz0zzz;42 : matrix <= 9'bzz1zz0zzz;43 : matrix <= 9'bzzz1z0zzz;44 : matrix <= 9'bzzzz10zzz;45 : matrix <= 9'bzzzzz01zz;46 : matrix <= 9'bzzzzz0z1z;47 : matrix <= 9'bzzzzz0zz1;48 : matrix <= 9'b1zzzzz0zz;49 : matrix <= 9'bz1zzzz0zz;50 : matrix <= 9'bzz1zzz0zz;51 : matrix <= 9'bzzz1zz0zz;52 : matrix <= 9'bzzzz1z0zz;53 : matrix <= 9'bzzzzz10zz;54 : matrix <= 9'bzzzzzz01z;55 : matrix <= 9'bzzzzzz0z1;56 : matrix <= 9'b1zzzzzz0z;57 : matrix <= 9'bz1zzzzz0z;58 : matrix <= 9'bzz1zzzz0z;59 : matrix <= 9'bzzz1zzz0z;60 : matrix <= 9'bzzzz1zz0z;61 : matrix <= 9'bzzzzz1z0z;62 : matrix <= 9'bzzzzzz10z;63 : matrix <= 9'bzzzzzzz01;64 : matrix <= 9'b1zzzzzzz0;65 : matrix <= 9'bz1zzzzzz0;66 : matrix <= 9'bzz1zzzzz0;67 : matrix <= 9'bzzz1zzzz0;68 : matrix <= 9'bzzzz1zzz0;69 : matrix <= 9'bzzzzz1zz0;70 : matrix <= 9'bzzzzzz1z0;71 : matrix <= 9'bzzzzzzz10;default: matrix <= 9'bz;endcaseendendmodule

author: josuah
author_rank: Regular Contributor
timestamp: May 27, 2022, 01:36:30 pm
content: Charlieplexing is fun!Your implementation already displays a nice visual way to get around with that.It could be convenient to transform these individual addresses to x/y coordinates... Maybe just splitting the bits of the address would suffice since you have 8 pixel per row.Focusing on the first row, how to get the right pins Low/High/High-Z for each position?There might be something to do with the "<<" operator, to shift a bit by as much as a binary number tells us.With that we can already make the first row!Due to how charlieplexing work, and as you figured out, there is the need to skip a position while row == column, as well as everything after that.That looks like about trying to build-up the bitshift, then adjusting the shift amount when (row >= columns).P.S.: I might have mistaken rows for columns at a few places!

author: Foxxz
author_rank: Regular Contributor
timestamp: May 27, 2022, 02:21:22 pm
content: Thanks for your reply. In the code above I have them broken up into rows such as 0-7.You brought up a good point that I might want to try x and y addressing which I will most likely build an additional module for even if it's just a translation layer. The original module was written with the intent of being fed from a frame buffer so at the time it made sense.After using the existing module for a while I may have come up with a way to accomplish what I originally asked.As it stands the existing module occupies 2 BRAMs. Not bad. Not great :-) I'm all about better efficiency though.

author: Foxxz
author_rank: Regular Contributor
timestamp: May 28, 2022, 12:01:02 am
content: As Dave would say:For those playing along at home I was able to come up with a solution that uses only logic. My prior module using lookup tables occupied 2x 4kbit block rams. This new solution uses 16x LUT4s. And I should be able to parameterize it easily.Code:module led_matrix_two (input [6:0] pixel_addr,input led_sig,output reg [8:0] matrix);always @* beginmatrix = 9'bz;if (led_sig) beginmatrix[8 - pixel_addr[6:3]] = 0;matrix[pixel_addr[6:3] <= pixel_addr[2:0] ? 7 - pixel_addr[2:0] : 8 - pixel_addr[2:0]] = 1;endendendmodule