272 lines
5.9 KiB
Verilog
272 lines
5.9 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) 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 <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;
|
|
|
|
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
|
|
driver_state<=8'd6;
|
|
cmd_data<=1'b0;
|
|
next_line<=1;
|
|
end else if(in_ascii_data==8'h0D)begin
|
|
driver_state<=8'd6;
|
|
cmd_data<=1'b0;
|
|
next_line<=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
|
|
|
|
////////////////////////////////////////////////
|
|
/* TODO: These are unreachable states but from
|
|
* what i assume to be a bug in yosys. They need
|
|
* to be here for brainfuck_compiled.asm to work.
|
|
* Specifically for the compiled program to not output
|
|
* random characters.
|
|
*/
|
|
8'd14:begin
|
|
data<=4'hf;
|
|
next_line<=1;
|
|
if(!done_writing)begin
|
|
driver_state<=8'd1;
|
|
write_req<=1'b0;
|
|
end else
|
|
write_req<=1'b1;
|
|
end
|
|
8'd13:begin
|
|
data<=4'hf;
|
|
if(!done_writing)begin
|
|
driver_state<=8'd1;
|
|
write_req<=1'b0;
|
|
end else
|
|
write_req<=1'b1;
|
|
end
|
|
8'd1:begin
|
|
if(done_writing==1)
|
|
driver_state<=8'd2;
|
|
end
|
|
8'd2:begin
|
|
data<=4'hE;
|
|
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;
|
|
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'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
|
|
default: begin driver_state<=0; end
|
|
endcase
|
|
|
|
end
|
|
end
|
|
|
|
|
|
|
|
endmodule
|