/* ascii_to_HD44780_driver.v - driver that takes in ascii and outputs control sequences for an HD44780 display This file is part of the 9086 project. Copyright (c) 2023 Efthymios Kritikos This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ module ascii_to_HD44780_driver ( /* system */ input wire clock, input wire rst_n, /* Data Input */ output reg in_data_ready=0, input data_write_req, input [7:0] in_ascii_data, /* write circuitry */ input wire done_writing, output reg write_req=0, output reg [3:0] data, output reg cmd_data=0 ); initial begin init_cmd_data[ 0] = 4'h3; init_cmd_data[ 1] = 4'h3; init_cmd_data[ 2] = 4'h3; init_cmd_data[ 3] = 4'h2; init_cmd_data[ 4] = 4'h2; //0x28 init_cmd_data[ 5] = 4'h8; init_cmd_data[ 6] = 4'h0; //0x07 init_cmd_data[ 7] = 4'h7; init_cmd_data[ 8] = 4'h0; //0x0C init_cmd_data[ 9] = 4'hC; init_cmd_data[10] = 4'h0; //0x01 init_cmd_data[11] = 4'h1; init_cmd_data[12] = 4'h0; //0x06 init_cmd_data[13] = 4'h6; init_cmd_data[14] = 4'h0; // 0x02 init_cmd_data[15] = 4'h2; end reg [4:0] init_seq=0; reg [5:0] data_write_wait_counter = 0; reg [3:0] init_cmd_data [15:0]; reg byte_n=0; reg [7:0]print_data; reg [1:0]line=0; reg [5:0]col=0; reg [7:0] driver_state =0; reg next_line; always @(posedge clock,negedge rst_n) begin if(rst_n==0)begin in_data_ready<=0; write_req<=1'b0; init_seq<=5'd0; data_write_wait_counter<=6'd0; byte_n<=1'b0; cmd_data<=1'b0; line<=0; col<=0; driver_state<=0; end else begin if (data_write_wait_counter!=6'd0 && done_writing) begin data_write_wait_counter<=data_write_wait_counter-6'd1; write_req<=1'b0; in_data_ready<=0; end else begin case(driver_state) 8'd0:begin if(done_writing)begin if(init_seq!=5'd16&&data_write_wait_counter==6'd0)begin /** Initialise display **/ data<=init_cmd_data[init_seq[3:0]]; init_seq<=init_seq+5'd1; write_req<=1'b1; data_write_wait_counter<=6'd50; in_data_ready<=0; end else if(col==6'd20)begin /** Check if we run out of screen **/ data<=4'hf; write_req<=1'b1; cmd_data<=1'b0; data_write_wait_counter<=6'd50; driver_state<=8'd2; next_line<=1; end else if(data_write_req==1)begin if(in_ascii_data==8'h0a)begin data<=4'hf; cmd_data<=1'b0; write_req<=1'b1; driver_state<=8'd2; next_line<=1; end else if(in_ascii_data==8'h0d)begin data<=4'hf; cmd_data<=1'b0; write_req<=1'b1; driver_state<=8'd2; next_line<=0; end else begin cmd_data<=1'b1; print_data<=in_ascii_data; driver_state<=8'd9; end in_data_ready<=0; end else begin in_data_ready<=1; end end else begin write_req<=1'b0; in_data_ready<=0; end end 8'd1:begin if(done_writing==1) driver_state<=8'd2; end 8'd2:begin data<=4'hE; cmd_data<=1'b0; data_write_wait_counter<=6'd50; if(!done_writing)begin driver_state<=8'd3; write_req<=1'b0; end else write_req<=1'b1; end 8'd3:begin if(done_writing==1) driver_state<=8'd4; end 8'd4:begin data<=4'h0; cmd_data<=1'b0; data_write_wait_counter<=6'd50; if(!done_writing)begin driver_state<=8'd5; write_req<=1'b0; end else write_req<=1'b1; end 8'd5:begin if(done_writing==1) driver_state<=8'd6; end 8'd6:begin if(next_line)begin case(line) 2'd0: data<=4'hC; 2'd1: data<=4'h9; 2'd2: data<=4'hD; 2'd3: data<=4'hD; endcase end else begin case(line) 2'd0: data<=4'h0; 2'd1: data<=4'hC; 2'd2: data<=4'h9; 2'd3: data<=4'hD; endcase end data_write_wait_counter<=6'd50; if(!done_writing)begin driver_state<=8'd7; write_req<=1'b0; end else write_req<=1'b1; end 8'd7:begin if(done_writing==1) driver_state<=8'd8; end 8'd8:begin if(next_line)begin case(line) 2'd0: begin data<=4'h0; ; end 2'd1: begin data<=4'h4; ; end 2'd2: begin data<=4'h4; ; end 2'd3: begin data<=4'h4; ; end endcase end else begin case(line) 2'd0: begin data<=4'h0; ; end 2'd1: begin data<=4'h0; ; end 2'd2: begin data<=4'h4; ; end 2'd3: begin data<=4'h4; ; end endcase end cmd_data<=1'b0; data_write_wait_counter<=6'd50; if(!done_writing)begin driver_state<=8'd0; col<=0; write_req<=1'b0; if(next_line)begin case(line) 2'd0: begin line<=1; end 2'd1: begin line<=2; end 2'd2: begin line<=3; end 2'd3: begin line<=3; end endcase end end else write_req<=1'b1; end 8'd9:begin data<=print_data[7:4]; data_write_wait_counter<=6'd50; if(!done_writing)begin driver_state<=8'd10; write_req<=1'b0; end else write_req<=1'b1; end 8'd10:begin if(done_writing==1) driver_state<=8'd11; end 8'd11:begin data<=print_data[3:0]; data_write_wait_counter<=6'd50; if(!done_writing)begin driver_state<=8'd0; write_req<=1'b0; col<=col+1; end else write_req<=1'b1; end default: begin driver_state<=0; end endcase end end end endmodule