// GNU GPL LED Display -- Display GNU GPL on LED Matrix (32x16) // // Copyright (C) 2006 The Free Software Initiative of Japan (FSIJ) // This file can be distributed under the terms of GNU GPL version 2 (or later) // // Author: Niibe Yutaka module divider(clk, div_clk); input clk; output div_clk; reg [3:0] count; // When system clock is 10MHz, count[3] will be 625kHz, pulse width = 1.6us assign div_clk = count[3]; // 1.60us : V = ~305Hz, 2048*1.60=3276.8us, always @ (negedge clk) count <= count + 1; endmodule // // 0 1 2 3 //: < >< >< // BIT: < // L-BIT: >< >< > // LL-BIT: < >< >< // WE#: ~~~~~~__~~~~~~__ // // // S-ROW: ~~ ~~ ~~ // S-OUT: >< >< > = L-BIT // S-CLK: ~~____~~~~____~~~~ // // // BIT-OUT: <><****><><****><> *: valid module matrix_driver(clk, s, row, bit_in, bit_out, opcode, oprand, s_clk, s_row, s_bit, s_latch, s_strobe); input clk; output reg [6:0] s; // 4 CLK * 32 columns : 128 CLK output reg [3:0] row; input bit_in; output bit_out; input opcode; input [15:0] oprand; output s_clk, s_row, s_bit, s_latch, s_strobe; wire [4:0] col; reg l_bit, ll_bit; assign s_clk = ~(s[0]^s[1]); assign col = s[6:2]; assign bit_out = (opcode==0)? l_bit : (col == 0)? oprand[row] : ll_bit; assign s_row = s[1:0] == 2'b00 ? 1'b1 : (col[3:0] == row); assign s_bit = l_bit; assign s_latch = |s[6:1]; assign s_strobe = (~s[2])|s[1]; // 75% power save always @ (negedge clk) case (s[1:0]) 2'b00: ll_bit <= l_bit; 2'b01: l_bit <= bit_in; 2'b10: /* No action */; 2'b11: /* No action */; endcase always @ (negedge clk) begin s = s + 1; // Not <= , but = !! if (|s == 0) row <= row + 1; end endmodule // State definition `define DATA0 6'b000000 `define DATA1 6'b000001 `define DATA2 6'b000010 `define DATA3 6'b000011 `define DATA4 6'b000100 `define DATA5 6'b000101 `define DATA6 6'b000110 `define DATA7 6'b000111 `define DATA8 6'b001000 `define DATA9 6'b001001 `define DATAa 6'b001010 `define DATAb 6'b001011 `define DATAc 6'b001100 `define DATAd 6'b001101 `define DATAe 6'b001110 `define DATAf 6'b001111 // `define ADDR0 6'b010000 `define ADDR1 6'b010001 `define ADDR2 6'b010010 `define ADDR3 6'b010011 `define ADDR4 6'b010100 `define ADDR5 6'b010101 `define ADDR6 6'b010110 `define ADDR7 6'b010111 `define ADDR8 6'b011000 `define ADDR9 6'b011001 `define ADDRa 6'b011010 `define ADDRb 6'b011011 `define ADDRc 6'b011100 `define ADDRd 6'b011101 `define ADDRe 6'b011110 `define ADDRf 6'b011111 // `define START 6'b100000 `define ZERO 6'b100001 `define ONE 6'b100010 `define ACK 6'b100011 `define STOP 6'b100100 `define IDLE 6'b100101 `define CONTENT_SIZE 16'H_C4E0 module i2c_srom_fetch(clk,s,row,scl_pin,sda_pin,opcode,oprand); input clk; // 128*16 CLK for V, 8*V for one fetch input [6:0] s; input [3:0] row; inout scl_pin, sda_pin; output opcode; output [15:0] oprand; reg scl, sda; reg [17:0] frame; reg [5:0] command; wire [1:0] state = s[1:0]; reg ack; reg [15:0] data; assign sda_pin = sda ? 1'bZ : 0; assign scl_pin = scl ? 1'bZ : 0; assign oprand = data ; assign opcode = &frame[2:0]; // 7/8 idle, 1/8 work wire [15:0] pc = {frame[17:3], 1'b0}; always @(negedge row[3]) begin frame = frame + 1; if (pc >= `CONTENT_SIZE) frame <= 0; end always @ (posedge clk) begin if ((|frame[2:0]) | (|row[3:1])) command = `IDLE; else case ({row[0], s[6:2]}) 0: command = `START; 1: command = `ONE; // DEVICE_ADDRESS6 2: command = `ZERO; // DEVICE_ADDRESS5 3: command = `ONE; // DEVICE_ADDRESS4 4: command = `ZERO; // DEVICE_ADDRESS3 5: command = `ZERO; // DEVICE_ADDRESS2 6: command = `ZERO; // DEVICE_ADDRESS1 7: command = `ZERO; // DEVICE_ADDRESS0 8: command = `ZERO; // WRITE 9: command = `ACK; 10: if (ack) command = `ADDRf; else command = `STOP; 11: if (ack) command = `ADDRe; else command = `IDLE; 12: if (ack) command = `ADDRd; else command = `IDLE; 13: if (ack) command = `ADDRc; else command = `IDLE; 14: if (ack) command = `ADDRb; else command = `IDLE; 15: if (ack) command = `ADDRa; else command = `IDLE; 16: if (ack) command = `ADDR9; else command = `IDLE; 17: if (ack) command = `ADDR8; else command = `IDLE; 18: if (ack) command = `ACK; else command = `IDLE; 19: if (ack) command = `ADDR7; else command = `IDLE; 20: if (ack) command = `ADDR6; else command = `IDLE; 21: if (ack) command = `ADDR5; else command = `IDLE; 22: if (ack) command = `ADDR4; else command = `IDLE; 23: if (ack) command = `ADDR3; else command = `IDLE; 24: if (ack) command = `ADDR2; else command = `IDLE; 25: if (ack) command = `ADDR1; else command = `IDLE; 26: if (ack) command = `ADDR0; else command = `IDLE; 27: if (ack) command = `ACK; else command = `IDLE; 28: if (ack) command = `START; else command = `IDLE; 29: if (ack) command = `ONE; else command = `IDLE; 30: if (ack) command = `ZERO; else command = `IDLE; 31: if (ack) command = `ONE; else command = `IDLE; 32: if (ack) command = `ZERO; else command = `IDLE; 33: if (ack) command = `ZERO; else command = `IDLE; 34: if (ack) command = `ZERO; else command = `IDLE; 35: if (ack) command = `ZERO; else command = `IDLE; 36: if (ack) command = `ONE; else command = `IDLE; 37: if (ack) command = `ACK; else command = `IDLE; 38: if (ack) command = `DATAf; else command = `STOP; 39: if (ack) command = `DATAe; else command = `IDLE; 40: if (ack) command = `DATAd; else command = `IDLE; 41: if (ack) command = `DATAc; else command = `IDLE; 42: if (ack) command = `DATAb; else command = `IDLE; 43: if (ack) command = `DATAa; else command = `IDLE; 44: if (ack) command = `DATA9; else command = `IDLE; 45: if (ack) command = `DATA8; else command = `IDLE; 46: if (ack) command = `ZERO; else command = `IDLE; // ACK 47: if (ack) command = `DATA7; else command = `IDLE; 48: if (ack) command = `DATA6; else command = `IDLE; 49: if (ack) command = `DATA5; else command = `IDLE; 50: if (ack) command = `DATA4; else command = `IDLE; 51: if (ack) command = `DATA3; else command = `IDLE; 52: if (ack) command = `DATA2; else command = `IDLE; 53: if (ack) command = `DATA1; else command = `IDLE; 54: if (ack) command = `DATA0; else command = `IDLE; 55: if (ack) command = `ONE; else command = `IDLE; // NOACK 56: if (ack) command = `STOP; else command = `IDLE; default: command = `IDLE; endcase case (command) `START: case (state) 2'b00: begin /* scl nc */ sda <= 1'b1; end // nc: no change 2'b01: begin scl <= 1'b1; sda <= 1'b1; end 2'b10: begin scl <= 1'b1; sda <= 1'b0; end 2'b11: begin scl <= 1'b0; sda <= 1'b0; end endcase `ONE: case (state) 2'b00: begin scl <= 1'b0; sda <= 1'b1; end 2'b01: begin scl <= 1'b1; sda <= 1'b1; end 2'b10: begin scl <= 1'b1; sda <= 1'b1; end 2'b11: begin scl <= 1'b0; sda <= 1'b1; end endcase `ZERO: case (state) 2'b00: begin scl <= 1'b0; sda <= 1'b0; end 2'b01: begin scl <= 1'b1; sda <= 1'b0; end 2'b10: begin scl <= 1'b1; sda <= 1'b0; end 2'b11: begin scl <= 1'b0; sda <= 1'b0; end endcase `ACK: case (state) 2'b00: begin scl <= 1'b0; sda <= 1'b1; end 2'b01: begin scl <= 1'b1; sda <= 1'b1; end 2'b10: begin scl <= 1'b1; sda <= 1'b1; ack <= (sda_pin == 1'b0); end 2'b11: begin scl <= 1'b0; sda <= 1'b1; end endcase `STOP: case (state) 2'b00: begin scl <= 1'b0; sda <= 1'b0; end 2'b01: begin scl <= 1'b1; sda <= 1'b0; end 2'b10: begin scl <= 1'b1; sda <= 1'b1; end 2'b11: begin scl <= 1'b1; sda <= 1'b1; end endcase `IDLE: case (state) 2'b00: begin scl <= 1'b1; sda <= 1'b1; end 2'b01: begin scl <= 1'b1; sda <= 1'b1; end 2'b10: begin scl <= 1'b1; sda <= 1'b1; end 2'b11: begin scl <= 1'b1; sda <= 1'b1; end endcase `DATA0,`DATA1,`DATA2,`DATA3,`DATA4,`DATA5,`DATA6,`DATA7, `DATA8,`DATA9,`DATAa,`DATAb,`DATAc,`DATAd,`DATAe,`DATAf: case (state) 2'b00: begin scl <= 1'b0; sda <= 1'b1; end 2'b01: begin scl <= 1'b1; sda <= 1'b1; end 2'b10: begin scl <= 1'b1; sda <= 1'b1; data[command[3:0]] <= sda_pin; end 2'b11: begin scl <= 1'b0; sda <= 1'b1; end endcase `ADDR0,`ADDR1,`ADDR2,`ADDR3,`ADDR4,`ADDR5,`ADDR6,`ADDR7, `ADDR8,`ADDR9,`ADDRa,`ADDRb,`ADDRc,`ADDRd,`ADDRe,`ADDRf: case (state) 2'b00: begin scl <= 1'b0; sda <= pc[command[3:0]]; end 2'b01: begin scl <= 1'b1; sda <= pc[command[3:0]]; end 2'b10: begin scl <= 1'b1; sda <= pc[command[3:0]]; end 2'b11: begin scl <= 1'b0; sda <= pc[command[3:0]]; end endcase endcase end endmodule module video_ram_access(clk, s, row, bit_read, bit_to_write, addr, n_we, data); input clk; input [6:0] s; input [3:0] row; input bit_to_write; output bit_read; inout data; output n_we; output [8:0] addr; assign bit_read = data; assign n_we = ~(s[1:0] == 2'b11); assign addr = { row, s[6:2] }; assign data = (s[1] == 1'b0) ? 1'bZ : bit_to_write; endmodule module gdpy(system_clk, s_clk, s_row, s_bit, s_latch, s_strobe, scl_pin, sda_pin, addr, n_we, data); input system_clk; output s_clk, s_row, s_bit, s_latch, s_strobe; inout scl_pin; inout sda_pin; output [8:0] addr; output n_we; inout data; wire clk; wire [3:0] row; wire [6:0] s; wire bit_read, bit_to_write, opcode; wire [15:0] oprand; divider DIV (system_clk, clk); video_ram_access VRAM (clk, s, row, bit_read, bit_to_write, addr, n_we, data); matrix_driver MTX (clk, s, row, bit_read, bit_to_write, opcode, oprand, s_clk, s_row, s_bit, s_latch, s_strobe); i2c_srom_fetch I2CROM (clk, s, row, scl_pin, sda_pin, opcode, oprand); endmodule