module i2c_lcd_send_byte (
input clk, reset_p,
input [6:0] addr, // Slave Address
input [7:0] send_buffer, // Transmission Data Buffer
input send, rs, // Send Start-bit, Register Select
output scl, sda, // Serial Clock , Serial Data
output reg busy, // Communication Situation
output [15:0] led // for Debugging
);
// Change State Using Shift
localparam I2C_IDLE = 6'b00_0001; // Standby State
localparam SEND_HIGH_NIBBLE_DISABLE = 6'b00_0010; // High Nibble(4-bit) Transmit in Enable Clear
localparam SEND_HIGH_NIBBLE_ENABLE = 6'b00_0100; // Enable Set
localparam SEND_LOW_NIBBLE_DISABLE = 6'b00_1000; // Low Nibble(4-bit) Transmit in Enable Clear
localparam SEND_LOW_NIBBLE_ENABLE = 6'b01_0000; // Enable Set
localparam SEND_DISABLE = 6'b10_0000; // Byte(8-bit) Transmission Complete
reg [7:0] data; // 4-bit Unit Transmission, D7 ~ D4, BL, E, RW, RS
reg comm_start; // Communication Start-bit
// Clock Divide 100, 10ns x 100 = 1us
wire clk_usec_nedge, clk_usec_pedge; // Divide Clock 1us
clock_div_100 us_clk (.clk(clk), .reset_p(reset_p),
.nedge_div_100(clk_usec_nedge), .pedge_div_100(clk_usec_pedge));
// Edge Detection of Send Signal
wire send_pedge, send_nedge;
edge_detector_pos comm_start_ed (.clk(clk), .reset_p(reset_p),
.cp(send), .p_edge(send_pedge), .n_edge(send_nedge));
// us Unit Count
reg [21:0] cnt_usec; // us Count
reg cnt_usec_e; // us Count Enable
always @(negedge clk, posedge reset_p) begin
if (reset_p) cnt_usec = 0; // Count Clear
else if (clk_usec_nedge && cnt_usec_e) begin // Count Start when Enable & us Negative Edge
cnt_usec = cnt_usec + 1; // Count During Enable
end
else if (!cnt_usec_e) cnt_usec = 0; // Count Clear when Disable
end
// Using Module, Address & Data Transmission, I2C Communication
i2c_master master (clk, reset_p, addr, data, 1'b0, comm_start, scl, sda);
reg [5:0] state, next_state; // Current & Next State
always @(negedge clk, posedge reset_p) begin
if (reset_p) state = I2C_IDLE; // Basic Standby
else state = next_state; // Change State in Negative Edge
end
always @(posedge clk, posedge reset_p) begin
if (reset_p) begin
next_state = I2C_IDLE; // Basic Standby
comm_start = 0; // Communication Disable
cnt_usec_e = 0; // us Count Disable, Clear
data = 0; // Transmission Data Reset
busy = 0; // Communication Available
end
else begin
case (state)
I2C_IDLE : begin // Standby State
if (send_pedge) begin // Send Start
next_state = SEND_HIGH_NIBBLE_DISABLE; // Change State SEND_HIGH_NIBBLE_DISABLE
busy = 1; // Communicating
end
end
SEND_HIGH_NIBBLE_DISABLE : begin // High Nibble(4-bit) Transmit in Enable Clear
if (cnt_usec < 22'd200) begin // About 200us Required to Complete Transmission
data = {send_buffer[7:4], 3'b100, rs}; // High Nibble Transmission
comm_start = 1; // Communication Start
cnt_usec_e = 1; // us Count Enable
end
else begin
cnt_usec_e = 0; // us Count Disable, Clear
comm_start = 0; // Communication Start-bit Clear
next_state = SEND_HIGH_NIBBLE_ENABLE; // Change State SEND_HIGH_NIBBLE_ENABLE
end
end
SEND_HIGH_NIBBLE_ENABLE : begin // Enable Set
if (cnt_usec < 22'd200) begin // About 200us Required to Complete Transmission
data = {send_buffer[7:4], 3'b110, rs}; // E Pin Enable
comm_start = 1; // Communication Start
cnt_usec_e = 1; // us Count Enable
end
else begin
cnt_usec_e = 0; // us Count Disable, Clear
comm_start = 0; // Communication Start-bit Clear
next_state = SEND_LOW_NIBBLE_DISABLE; // Change State SEND_LOW_NIBBLE_DISABLE
end
end
SEND_LOW_NIBBLE_DISABLE : begin // Low Nibble(4-bit) Transmit in Enable Clear
if (cnt_usec < 22'd200) begin // About 200us Required to Complete Transmission
data = {send_buffer[3:0], 3'b100, rs}; // Low Nibble Transmission
comm_start = 1; // Communication Start
cnt_usec_e = 1; // us Count Enable
end
else begin
cnt_usec_e = 0; // us Count Disable, Clear
comm_start = 0; // Communication Start-bit Clear
next_state = SEND_LOW_NIBBLE_ENABLE; // Change State SEND_LOW_NIBBLE_ENABLE
end
end
SEND_LOW_NIBBLE_ENABLE : begin // Enable Set
if (cnt_usec < 22'd200) begin // About 200us Required to Complete Transmission
data = {send_buffer[3:0], 3'b110, rs}; // E Pin Enable
comm_start = 1; // Communication Start
cnt_usec_e = 1; // us Count Enable
end
else begin
cnt_usec_e = 0; // us Count Disable, Clear
comm_start = 0; // Communication Start-bit Clear
next_state = SEND_DISABLE; // Change State SEND_DISABLE
end
end
SEND_DISABLE : begin // Byte(8-bit) Transmission Complete
if (cnt_usec < 22'd200) begin // About 200us Required to Complete Transmission
data = {send_buffer[7:4], 3'b100, rs}; // E Pin Disable
comm_start = 1; // Communication Start
cnt_usec_e = 1; // us Count Enable
end
else begin
cnt_usec_e = 0; // us Count Disable, Clear
comm_start = 0; // Communication Start-bit Clear
next_state = I2C_IDLE; // Change State I2C_IDLE
busy = 0; // Communication Available
end
end
default : begin
cnt_usec_e = 0; // us Count Disable, Clear
comm_start = 0; // Communication Start-bit Clear
next_state = I2C_IDLE; // Basic Standby
busy = 0; // Communication Available
end
endcase
end
end
endmodule