349 lines
7.4 KiB
Verilog
349 lines
7.4 KiB
Verilog
/* 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) 2024 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 <http://www.gnu.org/licenses/>. */
|
|
|
|
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; //0x0F
|
|
init_cmd_data[ 9] = 4'hF;
|
|
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 [3:0] init_cmd_data [15: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;
|
|
|
|
reg [7:0]clear_count;
|
|
|
|
always @(posedge clock) begin
|
|
if(rst_n==0)begin
|
|
in_data_ready<=0;
|
|
write_req<=1'b0;
|
|
init_seq<=5'd0;
|
|
cmd_data<=1'b0;
|
|
line<=0;
|
|
col<=0;
|
|
driver_state<=0;
|
|
end else begin
|
|
case(driver_state)
|
|
8'd0:begin
|
|
if(init_seq!=5'd16)begin
|
|
/** Initialise display **/
|
|
data<=init_cmd_data[init_seq[3:0]];
|
|
cmd_data<=1'b0;
|
|
in_data_ready<=0;
|
|
if(!done_writing)begin
|
|
init_seq<=init_seq+5'd1;
|
|
driver_state<=8'd12;
|
|
write_req<=1'b0;
|
|
end else begin
|
|
write_req<=1'b1;
|
|
end
|
|
end else if(col==6'd20)begin
|
|
/** Check if we run out of screen **/
|
|
driver_state<=8'd6;
|
|
cmd_data<=1'b0;
|
|
next_line<=1;
|
|
end else if(data_write_req==1)begin
|
|
if(in_ascii_data==8'h0A)begin // '\n'
|
|
driver_state<=8'd6;
|
|
cmd_data<=1'b0;
|
|
next_line<=1;
|
|
end else if(in_ascii_data==8'h0D)begin // '\r'
|
|
driver_state<=8'd6;
|
|
cmd_data<=1'b0;
|
|
next_line<=0;
|
|
end else if(in_ascii_data==8'h1b)begin // '\e'
|
|
driver_state<=8'd13;
|
|
cmd_data<=1'b1;
|
|
in_data_ready<=0;
|
|
end else begin
|
|
if (in_ascii_data[7:5]==3'b000||in_ascii_data[7:7]==1'b1)
|
|
if(in_ascii_data==8'h00)
|
|
print_data<=8'h23;
|
|
else
|
|
print_data<=8'h3F;
|
|
else
|
|
print_data<=in_ascii_data;
|
|
cmd_data<=1'b1;
|
|
driver_state<=8'd9;
|
|
end
|
|
in_data_ready<=0;
|
|
end else begin
|
|
in_data_ready<=1;
|
|
end
|
|
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'h8;
|
|
2'd1: data<=4'hC;
|
|
2'd2: data<=4'h9;
|
|
2'd3: data<=4'hD;
|
|
endcase
|
|
end
|
|
if(done_writing==0)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
|
|
if(!done_writing)begin
|
|
driver_state<=8'd12;
|
|
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
|
|
write_req<=1'b0;
|
|
end else
|
|
write_req<=1'b1;
|
|
end
|
|
8'd9:begin
|
|
data<=print_data[7:4];
|
|
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];
|
|
if(!done_writing)begin
|
|
driver_state<=8'd12;
|
|
write_req<=1'b0;
|
|
col<=col+1;
|
|
end else
|
|
write_req<=1'b1;
|
|
end
|
|
8'd12:begin
|
|
if(done_writing)
|
|
driver_state<=8'd0;
|
|
end
|
|
8'd13:begin // Escape sequence start
|
|
if(data_write_req==1'b0)begin
|
|
driver_state<=8'd14;
|
|
in_data_ready<=1;
|
|
end
|
|
end
|
|
8'd14:begin
|
|
if(data_write_req==1'b1)begin
|
|
in_data_ready<=1'b0;
|
|
case(in_ascii_data[7:0])
|
|
8'h5b:begin// '['
|
|
driver_state<=8'd16;
|
|
end
|
|
default:begin
|
|
driver_state<=8'd15;
|
|
end
|
|
endcase
|
|
end
|
|
end
|
|
8'd15:begin
|
|
if(data_write_req==1'b0)begin
|
|
driver_state<=8'd0;
|
|
end
|
|
end
|
|
8'd16:begin // Second part of escape sequency
|
|
if(data_write_req==1'b0)begin
|
|
in_data_ready<=1'b1;
|
|
driver_state<=8'd17;
|
|
end
|
|
end
|
|
8'd17:begin
|
|
if(data_write_req==1'b1)begin
|
|
driver_state<=8'd17;
|
|
in_data_ready<=1'b0;
|
|
case(in_ascii_data[7:0])
|
|
8'h48:begin// 'H'
|
|
driver_state<=8'd25;
|
|
cmd_data<=1'b0;
|
|
clear_count<=8'd80;
|
|
end
|
|
8'h32:begin// '2'
|
|
driver_state<=8'd23;
|
|
end
|
|
default: begin
|
|
driver_state<=8'd15;
|
|
end
|
|
endcase
|
|
end
|
|
end
|
|
8'd18:begin
|
|
data<=4'h2;
|
|
if(!done_writing)begin
|
|
driver_state<=8'd19;
|
|
write_req<=1'b0;
|
|
end else
|
|
write_req<=1'b1;
|
|
end
|
|
8'd19:begin
|
|
if(done_writing==1)
|
|
driver_state<=8'd20;
|
|
end
|
|
8'd20:begin
|
|
data<=4'h0;
|
|
if(!done_writing)begin
|
|
driver_state<=8'd21;
|
|
write_req<=1'b0;
|
|
end else
|
|
write_req<=1'b1;
|
|
end
|
|
8'd21:begin
|
|
if(done_writing)begin
|
|
driver_state<=8'd22;
|
|
clear_count<=clear_count-8'd1;
|
|
end
|
|
end
|
|
8'd22:begin
|
|
if(clear_count==8'd0)begin
|
|
driver_state<=8'd0;
|
|
end else begin
|
|
driver_state<=8'd18;
|
|
end
|
|
end
|
|
8'd23:begin
|
|
if(data_write_req==1'b0)begin
|
|
in_data_ready<=1'b1;
|
|
driver_state<=8'd24;
|
|
end
|
|
end
|
|
8'd24:begin
|
|
if(data_write_req==1'b1)begin
|
|
driver_state<=8'd17;
|
|
in_data_ready<=1'b0;
|
|
case(in_ascii_data[7:0])
|
|
8'h4a:begin// 'J'
|
|
driver_state<=8'd18;
|
|
clear_count<=8'd80;
|
|
end
|
|
default:begin
|
|
driver_state<=8'd0;
|
|
end
|
|
endcase
|
|
end
|
|
end
|
|
8'd25:begin
|
|
data<=4'h8;
|
|
if(!done_writing)begin
|
|
driver_state<=8'd26;
|
|
write_req<=1'b0;
|
|
end else
|
|
write_req<=1'b1;
|
|
end
|
|
8'd26:begin
|
|
if(done_writing==1)
|
|
driver_state<=8'd27;
|
|
end
|
|
8'd27:begin
|
|
data<=4'h0;
|
|
if(!done_writing)begin
|
|
driver_state<=8'd28;
|
|
write_req<=1'b0;
|
|
end else
|
|
write_req<=1'b1;
|
|
end
|
|
8'd28:begin
|
|
if(done_writing)begin
|
|
driver_state<=8'd0;
|
|
col<=0;
|
|
line<=0;
|
|
end
|
|
end
|
|
default: begin driver_state<=0; end
|
|
endcase
|
|
end
|
|
end
|
|
|
|
endmodule
|