Added an I2C driver, a PCF8574 driver and an HD44780 display driver. Unfortunately this shows that even fibonacci doesn't run correctly. Nonetheless, I made colored_led.asm output text to the display!
This commit is contained in:
parent
e0dc7bae07
commit
a88c420ca5
@ -69,10 +69,12 @@ endif
|
|||||||
ECP5_TARGETS=synth_ecp5.json synth_ecp5_out.config synth_ecp5.bit synth_ecp5.dfu
|
ECP5_TARGETS=synth_ecp5.json synth_ecp5_out.config synth_ecp5.bit synth_ecp5.dfu
|
||||||
ECP5_TARGETS+=abc.history # created from yosys
|
ECP5_TARGETS+=abc.history # created from yosys
|
||||||
|
|
||||||
|
EXTRA_SYNTHESIS_SOURCES=peripherals/I2C_driver.v peripherals/ascii_to_HD44780_driver.v peripherals/pcf8574_for_HD44780.v
|
||||||
|
|
||||||
#TODO: we are relying on yosys to trim the input program txt file and hope its enough for the whole program...
|
#TODO: we are relying on yosys to trim the input program txt file and hope its enough for the whole program...
|
||||||
synth_ecp5.json: ${SOURCES} ${TOP_LEVEL_SOURCE} fpga_config/${FPGA_BOARD}/fpga_top.v ${INCLUDES} ../boot_code/colored_led.txt
|
synth_ecp5.json: ${SOURCES} ${TOP_LEVEL_SOURCE} fpga_config/${FPGA_BOARD}/fpga_top.v ${EXTRA_SYNTHESIS_SOURCES} ${INCLUDES} ../boot_code/colored_led.txt
|
||||||
${QUIET_YOSYS}
|
${QUIET_YOSYS}
|
||||||
${Q} yosys -q -D BUILTIN_RAM=512 -D NOT_FULL -p 'read -sv '"${SOURCES} ${TOP_LEVEL_SOURCE} fpga_config/${FPGA_BOARD}/fpga_top.v ; synth_ecp5 -json $@"
|
${Q} yosys -q -D BUILTIN_RAM=512 -D NOT_FULL -p 'read -sv '"${SOURCES} ${TOP_LEVEL_SOURCE} fpga_config/${FPGA_BOARD}/fpga_top.v ${EXTRA_SYNTHESIS_SOURCES} ; synth_ecp5 -json $@ -top fpga_top"
|
||||||
|
|
||||||
synth_ecp5_out.config:synth_ecp5.json
|
synth_ecp5_out.config:synth_ecp5.json
|
||||||
${QUIET_NEXTPNR}
|
${QUIET_NEXTPNR}
|
||||||
|
@ -28,6 +28,9 @@ module fpga_top(
|
|||||||
output rgb_led0_r,
|
output rgb_led0_r,
|
||||||
output rgb_led0_g,
|
output rgb_led0_g,
|
||||||
output rgb_led0_b,
|
output rgb_led0_b,
|
||||||
|
|
||||||
|
inout gpio_0,/*sda*/
|
||||||
|
output gpio_1 /*scl*/
|
||||||
);
|
);
|
||||||
|
|
||||||
wire HALT;
|
wire HALT;
|
||||||
@ -35,6 +38,7 @@ wire [`ERROR_BITS-1:0]ERROR;
|
|||||||
wire [19:0] address_bus;
|
wire [19:0] address_bus;
|
||||||
wire [15:0] data_bus_read,data_bus_write;
|
wire [15:0] data_bus_read,data_bus_write;
|
||||||
wire rd,wr,BHE,IOMEM;
|
wire rd,wr,BHE,IOMEM;
|
||||||
|
|
||||||
system system(
|
system system(
|
||||||
/* MISC */ clk48,reset
|
/* MISC */ clk48,reset
|
||||||
/* MEMORY / IO */ ,address_bus,data_bus_read,data_bus_write,BHE,rd,wr,IOMEM,HALT,ERROR
|
/* MEMORY / IO */ ,address_bus,data_bus_read,data_bus_write,BHE,rd,wr,IOMEM,HALT,ERROR
|
||||||
@ -45,15 +49,6 @@ assign rgb_led0_r=rgb_led_color[0];
|
|||||||
assign rgb_led0_g=rgb_led_color[1];
|
assign rgb_led0_g=rgb_led_color[1];
|
||||||
assign rgb_led0_b=rgb_led_color[2];
|
assign rgb_led0_b=rgb_led_color[2];
|
||||||
|
|
||||||
always @(negedge wr) begin
|
|
||||||
if(IOMEM==1'b1 && address_bus[7:0]==8'hB0 )begin
|
|
||||||
if(data_bus_write[0:0]==1)
|
|
||||||
rgb_led_color=3'b000;
|
|
||||||
else
|
|
||||||
rgb_led_color=3'b111;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
// A bit useless since if the cpu ERORRS out or HALTS it will continue executing anyway
|
// A bit useless since if the cpu ERORRS out or HALTS it will continue executing anyway
|
||||||
//always @(HALT or ERROR or user_button) begin
|
//always @(HALT or ERROR or user_button) begin
|
||||||
// if (HALT==1) begin
|
// if (HALT==1) begin
|
||||||
@ -68,15 +63,16 @@ end
|
|||||||
// end
|
// end
|
||||||
//end
|
//end
|
||||||
|
|
||||||
|
// Create a 27 bit register
|
||||||
|
reg [26:0] counter = 0;
|
||||||
|
|
||||||
/*** RESET CIRCUIT ***/
|
// Every positive edge increment register by 1
|
||||||
|
|
||||||
reg [3:0] counter = 0;
|
|
||||||
|
|
||||||
always @(posedge clk48) begin
|
always @(posedge clk48) begin
|
||||||
counter <= counter + 1;
|
counter <= counter + 1;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
/*** RESET CIRCUIT ***/
|
||||||
|
|
||||||
reg reset=0;
|
reg reset=0;
|
||||||
reg [1:0] state=0;
|
reg [1:0] state=0;
|
||||||
|
|
||||||
@ -97,4 +93,113 @@ always @(posedge counter[3]) begin
|
|||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
always @(negedge wr) begin
|
||||||
|
if(IOMEM==1'b1 && address_bus[7:0]==8'hA5 )begin
|
||||||
|
//disp_write_cache[disp_cache_end]<=data_bus_write[7:0];
|
||||||
|
disp_write_cache[disp_cache_end]<=data_bus_write[15:8];
|
||||||
|
disp_cache_end<=disp_cache_end+5'd1;
|
||||||
|
end else if(IOMEM==1'b1 && address_bus[7:0]==8'hB0 )begin
|
||||||
|
if(data_bus_write[0:0]==1)
|
||||||
|
rgb_led_color=3'b000;
|
||||||
|
else
|
||||||
|
rgb_led_color=3'b111;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
//------------------------------------------//
|
||||||
|
// Cache to allow the slow display to have a
|
||||||
|
// chance to keep up with the relentless CPU
|
||||||
|
|
||||||
|
reg [4:0] disp_cache_start=0;
|
||||||
|
reg [4:0] disp_cache_end=0;
|
||||||
|
reg [7:0] disp_write_cache [31:0];
|
||||||
|
reg ascii_state=0;
|
||||||
|
always @(posedge clk48)begin
|
||||||
|
case (ascii_state)
|
||||||
|
1'b0:begin
|
||||||
|
if(ascii_data_ready&disp_cache_start!=disp_cache_end)begin
|
||||||
|
ascii_data<=disp_write_cache[disp_cache_start];
|
||||||
|
disp_cache_start<=disp_cache_start+5'd1;
|
||||||
|
ascii_data_write_req<=1;
|
||||||
|
ascii_state<=1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
1'b1:begin
|
||||||
|
if(!ascii_data_ready)begin
|
||||||
|
ascii_data_write_req<=0;
|
||||||
|
ascii_state<=1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
default: begin end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
wire I2C_SPEED=counter[7];
|
||||||
|
|
||||||
|
// Display driver
|
||||||
|
|
||||||
|
wire ascii_data_ready;
|
||||||
|
reg ascii_data_write_req=0;
|
||||||
|
reg [7:0] ascii_data;
|
||||||
|
ascii_to_HD44780_driver LCD_DRIVER(
|
||||||
|
/* system */
|
||||||
|
I2C_SPEED,
|
||||||
|
1'b1,
|
||||||
|
|
||||||
|
/* Data Input */
|
||||||
|
ascii_data_ready,
|
||||||
|
ascii_data_write_req,
|
||||||
|
ascii_data,
|
||||||
|
|
||||||
|
/* write circuitry */
|
||||||
|
!pcf_busy,
|
||||||
|
pcf_write_req,
|
||||||
|
pcf_data,
|
||||||
|
pcf_command_data
|
||||||
|
);
|
||||||
|
|
||||||
|
// Port expander driver
|
||||||
|
|
||||||
|
wire pcf_write_req,pcf_command_data,pcf_busy;
|
||||||
|
wire [3:0]pcf_data;
|
||||||
|
wire [7:0]i2c_data;
|
||||||
|
|
||||||
|
pcf8574_for_HD44780 PCF8574_driver(
|
||||||
|
.clock(I2C_SPEED),
|
||||||
|
|
||||||
|
.pcf_write_req(pcf_write_req),
|
||||||
|
.pcf_command_data(pcf_command_data),
|
||||||
|
.pcf_data(pcf_data),
|
||||||
|
|
||||||
|
.pcf_busy(pcf_busy),
|
||||||
|
.new_backlight(1'b0),
|
||||||
|
.backlight_update(1'b0),
|
||||||
|
|
||||||
|
.I2C_BUSY(I2C_BUSY),
|
||||||
|
.I2C_SEND(I2C_SEND),
|
||||||
|
|
||||||
|
.i2c_data(i2c_data)
|
||||||
|
);
|
||||||
|
|
||||||
|
// I2C driver
|
||||||
|
|
||||||
|
wire SCL,SDA,I2C_BUSY,I2C_SEND;
|
||||||
|
assign gpio_1=SCL;
|
||||||
|
assign gpio_0=SDA;
|
||||||
|
reg [7:0]i2c_data;
|
||||||
|
I2C_driver i2c_driver(
|
||||||
|
.clock(I2C_SPEED),
|
||||||
|
|
||||||
|
.SDA_(SDA),
|
||||||
|
.SCL(SCL),
|
||||||
|
|
||||||
|
.address(7'h27),
|
||||||
|
.I2C_BUSY(I2C_BUSY),
|
||||||
|
.I2C_SEND(I2C_SEND),
|
||||||
|
.i2c_data(i2c_data),
|
||||||
|
);
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
258
system/peripherals/I2C_driver.v
Normal file
258
system/peripherals/I2C_driver.v
Normal file
@ -0,0 +1,258 @@
|
|||||||
|
/* I2C_driver.v - Implements an I2C interface
|
||||||
|
|
||||||
|
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 I2C_driver (
|
||||||
|
input wire clock,
|
||||||
|
inout wire SDA_,
|
||||||
|
output reg SCL,
|
||||||
|
|
||||||
|
input wire [6:0] address,
|
||||||
|
output reg I2C_BUSY=0,
|
||||||
|
input wire I2C_SEND,
|
||||||
|
input wire [7:0] i2c_data
|
||||||
|
);
|
||||||
|
|
||||||
|
reg SDA;
|
||||||
|
|
||||||
|
assign SDA_=(i2c_bus_dir==0)?SDA:1'bz;
|
||||||
|
|
||||||
|
reg i2c_bus_dir=0;
|
||||||
|
reg [5:0] i2c_state = 6'b100100;
|
||||||
|
|
||||||
|
reg [3:0] data_bit_counter;
|
||||||
|
reg [7:0] data_internal;
|
||||||
|
reg [6:0]address_internal;
|
||||||
|
|
||||||
|
always @(posedge clock) begin
|
||||||
|
case (i2c_state)
|
||||||
|
/***** start sequence ******/
|
||||||
|
6'b000000:begin
|
||||||
|
i2c_bus_dir<=0;
|
||||||
|
SDA<=1;
|
||||||
|
SCL<=1;
|
||||||
|
i2c_state<=6'b000001;
|
||||||
|
end
|
||||||
|
6'b000001:begin
|
||||||
|
SDA<=0;
|
||||||
|
SCL<=1;
|
||||||
|
i2c_state<=6'b000010;
|
||||||
|
end
|
||||||
|
6'b000010:begin
|
||||||
|
SDA<=0;
|
||||||
|
SCL<=0;
|
||||||
|
i2c_state<=6'b000011;
|
||||||
|
data_bit_counter<=0;
|
||||||
|
end
|
||||||
|
/****** Set address ********/
|
||||||
|
6'b000011:begin
|
||||||
|
SCL<=0;
|
||||||
|
i2c_state<=6'b000100;
|
||||||
|
end
|
||||||
|
6'b000100:begin
|
||||||
|
SCL<=0;
|
||||||
|
SDA<=address_internal[6:6];
|
||||||
|
address_internal[6:0]<={address_internal[5:0],1'b0};
|
||||||
|
data_bit_counter<=data_bit_counter+1;
|
||||||
|
i2c_state<=6'b000101;
|
||||||
|
end
|
||||||
|
6'b000101:begin
|
||||||
|
SCL<=1;
|
||||||
|
i2c_state<=6'b000110;
|
||||||
|
end
|
||||||
|
6'b000110:begin
|
||||||
|
SCL<=1;
|
||||||
|
if(data_bit_counter==4'd7)
|
||||||
|
i2c_state<=6'b000111;
|
||||||
|
else
|
||||||
|
i2c_state<=6'b000011;
|
||||||
|
end
|
||||||
|
/****** Read/Write *********/
|
||||||
|
6'b000111:begin
|
||||||
|
SCL<=0;
|
||||||
|
i2c_state<=6'b001000;
|
||||||
|
end
|
||||||
|
6'b001000:begin
|
||||||
|
SCL<=0;
|
||||||
|
SDA<=0;/*Write=0 Read=1*/
|
||||||
|
i2c_state<=6'b001001;
|
||||||
|
end
|
||||||
|
6'b001001:begin
|
||||||
|
SCL<=1;
|
||||||
|
i2c_state<=6'b001010;
|
||||||
|
end
|
||||||
|
6'b001010:begin
|
||||||
|
SCL<=1;
|
||||||
|
i2c_state<=6'b001011;
|
||||||
|
end
|
||||||
|
/****** Acknowledge ********/
|
||||||
|
6'b001011:begin
|
||||||
|
SCL<=0;
|
||||||
|
i2c_bus_dir<=1;
|
||||||
|
i2c_state<=6'b001100;
|
||||||
|
end
|
||||||
|
6'b001100:begin
|
||||||
|
SCL<=0;
|
||||||
|
i2c_state<=6'b001101;
|
||||||
|
end
|
||||||
|
6'b001101:begin
|
||||||
|
SCL<=1;
|
||||||
|
i2c_state<=6'b001110;
|
||||||
|
end
|
||||||
|
6'b001110:begin
|
||||||
|
SCL<=1;
|
||||||
|
// if (SDA==1)begin
|
||||||
|
// led<=1;
|
||||||
|
// i2c_state<=6'b011111;
|
||||||
|
// end else begin
|
||||||
|
i2c_state<=6'b001111;
|
||||||
|
data_bit_counter<=0;
|
||||||
|
// end
|
||||||
|
end
|
||||||
|
/****** separator ********/
|
||||||
|
6'b001111:begin
|
||||||
|
SCL<=0;
|
||||||
|
SDA<=0;
|
||||||
|
i2c_state<=6'b010000;
|
||||||
|
end
|
||||||
|
6'b010000:begin
|
||||||
|
SCL<=0;
|
||||||
|
i2c_state<=6'b010001;
|
||||||
|
end
|
||||||
|
6'b010001:begin
|
||||||
|
SCL<=0;
|
||||||
|
SDA<=1;
|
||||||
|
i2c_state<=6'b010010;
|
||||||
|
end
|
||||||
|
6'b010010:begin
|
||||||
|
SCL<=0;
|
||||||
|
SDA<=1;
|
||||||
|
i2c_state<=6'b010011;
|
||||||
|
end
|
||||||
|
6'b010011:begin
|
||||||
|
SCL<=0;
|
||||||
|
SDA<=0;
|
||||||
|
i2c_state<=6'b010100;
|
||||||
|
end
|
||||||
|
/****** Send data ********/
|
||||||
|
6'b010100:begin
|
||||||
|
SCL<=0;
|
||||||
|
i2c_bus_dir<=0;
|
||||||
|
i2c_state<=6'b010101;
|
||||||
|
end
|
||||||
|
6'b010101:begin
|
||||||
|
SCL<=0;
|
||||||
|
SDA<=data_internal[7:7];
|
||||||
|
data_internal[7:0]<={data_internal[6:0],1'b0};
|
||||||
|
data_bit_counter<=data_bit_counter+1;
|
||||||
|
i2c_state<=6'b010110;
|
||||||
|
end
|
||||||
|
6'b010110:begin
|
||||||
|
SCL<=1;
|
||||||
|
i2c_state<=6'b010111;
|
||||||
|
end
|
||||||
|
6'b010111:begin
|
||||||
|
SCL<=1;
|
||||||
|
if(data_bit_counter==4'd8)begin
|
||||||
|
i2c_state<=6'b011000;
|
||||||
|
end else
|
||||||
|
i2c_state<=6'b010100;
|
||||||
|
end
|
||||||
|
/****** Acknowledge ********/
|
||||||
|
6'b011000:begin
|
||||||
|
i2c_bus_dir<=1;
|
||||||
|
SCL<=0;
|
||||||
|
i2c_state<=6'b011001;
|
||||||
|
end
|
||||||
|
6'b011001:begin
|
||||||
|
SCL<=0;
|
||||||
|
i2c_state<=6'b011010;
|
||||||
|
end
|
||||||
|
6'b011010:begin
|
||||||
|
SCL<=1;
|
||||||
|
i2c_state<=6'b011011;
|
||||||
|
end
|
||||||
|
6'b011011:begin
|
||||||
|
SCL<=1;
|
||||||
|
// if (SDA==1)begin
|
||||||
|
// led<=1;
|
||||||
|
// i2c_state<=6'b011111;
|
||||||
|
// end else begin
|
||||||
|
i2c_state<=6'b011100;
|
||||||
|
i2c_bus_dir<=0;
|
||||||
|
// end
|
||||||
|
end
|
||||||
|
/****** separator ********/
|
||||||
|
6'b011100:begin
|
||||||
|
SCL<=0;
|
||||||
|
SDA<=0;
|
||||||
|
i2c_state<=6'b011101;
|
||||||
|
end
|
||||||
|
6'b011101:begin
|
||||||
|
SCL<=0;
|
||||||
|
i2c_state<=6'b011110;
|
||||||
|
end
|
||||||
|
6'b011110:begin
|
||||||
|
SCL<=0;
|
||||||
|
SDA<=1;
|
||||||
|
i2c_state<=6'b011111;
|
||||||
|
end
|
||||||
|
6'b011111:begin
|
||||||
|
SCL<=0;
|
||||||
|
SDA<=1;
|
||||||
|
i2c_state<=6'b100000;
|
||||||
|
end
|
||||||
|
6'b100000:begin
|
||||||
|
SCL<=0;
|
||||||
|
SDA<=0;
|
||||||
|
i2c_state<=6'b100001;
|
||||||
|
end
|
||||||
|
/****** stop bit *******/
|
||||||
|
6'b100001:begin
|
||||||
|
SCL<=1;
|
||||||
|
SDA<=0;
|
||||||
|
i2c_state<=6'b100010;
|
||||||
|
end
|
||||||
|
6'b100010:begin
|
||||||
|
SCL<=1;
|
||||||
|
SDA<=1;
|
||||||
|
i2c_state<=6'b100011;
|
||||||
|
end
|
||||||
|
6'b100011:begin
|
||||||
|
SCL<=1;
|
||||||
|
SDA<=1;
|
||||||
|
i2c_state<=6'b100100;
|
||||||
|
I2C_BUSY<=0;
|
||||||
|
end
|
||||||
|
6'b100100:begin
|
||||||
|
if(I2C_SEND==1)begin
|
||||||
|
I2C_BUSY<=1;
|
||||||
|
i2c_state<=0;
|
||||||
|
data_internal<=i2c_data;
|
||||||
|
address_internal<=address;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
default:begin
|
||||||
|
SCL<=0;
|
||||||
|
SDA<=0;
|
||||||
|
end
|
||||||
|
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
114
system/peripherals/ascii_to_HD44780_driver.v
Normal file
114
system/peripherals/ascii_to_HD44780_driver.v
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/* 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; //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 data_write_latch=0;
|
||||||
|
reg [7:0]print_data;
|
||||||
|
|
||||||
|
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;
|
||||||
|
end else if(done_writing)begin
|
||||||
|
if(init_seq!=5'd16&&data_write_wait_counter==6'd0)begin
|
||||||
|
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 (data_write_wait_counter!=6'd0) begin
|
||||||
|
data_write_wait_counter<=data_write_wait_counter-6'd1;
|
||||||
|
write_req<=1'b0;
|
||||||
|
in_data_ready<=0;
|
||||||
|
end else if(data_write_req==1&&data_write_latch==0)begin
|
||||||
|
data_write_latch<=1;
|
||||||
|
print_data<=in_ascii_data;
|
||||||
|
in_data_ready<=0;
|
||||||
|
byte_n<=0;
|
||||||
|
end else if(data_write_latch&byte_n==0)begin
|
||||||
|
data<=print_data[7:4];
|
||||||
|
write_req<=1'b1;
|
||||||
|
data_write_wait_counter<=6'd50;
|
||||||
|
byte_n<=1;
|
||||||
|
end else if(data_write_latch&byte_n==1)begin
|
||||||
|
data<=print_data[3:0];
|
||||||
|
write_req<=1'b1;
|
||||||
|
data_write_wait_counter<=6'd50;
|
||||||
|
byte_n<=0;
|
||||||
|
data_write_latch<=0;
|
||||||
|
end else begin
|
||||||
|
cmd_data<=1;
|
||||||
|
in_data_ready<=1;
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
write_req<=1'b0;
|
||||||
|
in_data_ready<=0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
endmodule
|
123
system/peripherals/pcf8574_for_HD44780.v
Normal file
123
system/peripherals/pcf8574_for_HD44780.v
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
/* pcf8574_for_HD44780.v - takes in control sequences for an HD44780 display
|
||||||
|
and outputs data that control a pcf8574 connected to a HD44780 in a standard
|
||||||
|
manner over i2c
|
||||||
|
|
||||||
|
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 pcf8574_for_HD44780(
|
||||||
|
input wire clock,
|
||||||
|
|
||||||
|
input wire pcf_write_req,
|
||||||
|
input wire pcf_command_data,
|
||||||
|
input wire [3:0]pcf_data,
|
||||||
|
output reg pcf_busy=0,
|
||||||
|
input new_backlight,
|
||||||
|
input backlight_update,
|
||||||
|
|
||||||
|
input I2C_BUSY,
|
||||||
|
output reg I2C_SEND=0,
|
||||||
|
|
||||||
|
output reg [7:0]i2c_data
|
||||||
|
);
|
||||||
|
|
||||||
|
reg backlight=1;
|
||||||
|
reg backlight_latch=0;
|
||||||
|
reg [3:0]pcf_state=0;
|
||||||
|
|
||||||
|
always @(posedge clock) begin
|
||||||
|
// [ D7 , D6 , D5 , D4 , BACKLIGHT , EN , WRITE , COMMAND/DATA ]
|
||||||
|
if(backlight_update)
|
||||||
|
backlight_latch<=1;
|
||||||
|
case(pcf_state)
|
||||||
|
4'b0000: begin /*Idle*/
|
||||||
|
if(pcf_write_req&&I2C_BUSY==0)begin
|
||||||
|
pcf_state<=4'b0001;
|
||||||
|
I2C_SEND<=0;
|
||||||
|
pcf_busy<=1;
|
||||||
|
end else if(backlight_latch&&I2C_BUSY==0)begin
|
||||||
|
pcf_state<=4'b1111;
|
||||||
|
I2C_SEND<=0;
|
||||||
|
pcf_busy<=1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
4'b0001: begin
|
||||||
|
if(I2C_BUSY==0)begin
|
||||||
|
i2c_data<={pcf_data[3:0],backlight,1'b0,1'b0,pcf_command_data};
|
||||||
|
I2C_SEND<=1;
|
||||||
|
backlight_latch<=0;
|
||||||
|
pcf_state<=4'b0010;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
4'b0010:begin
|
||||||
|
if(I2C_BUSY==1)begin
|
||||||
|
I2C_SEND<=0;
|
||||||
|
pcf_state<=4'b0011;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
4'b0011: begin
|
||||||
|
if(I2C_BUSY==0)begin
|
||||||
|
i2c_data<={pcf_data[3:0],backlight,1'b1,1'b0,pcf_command_data};
|
||||||
|
I2C_SEND<=1;
|
||||||
|
backlight_latch<=0;
|
||||||
|
pcf_state<=4'b0100;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
4'b0100:begin
|
||||||
|
if(I2C_BUSY==1)begin
|
||||||
|
I2C_SEND<=0;
|
||||||
|
pcf_state<=4'b0101;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
4'b0101: begin
|
||||||
|
if(I2C_BUSY==0)begin
|
||||||
|
i2c_data<={pcf_data[3:0],backlight,1'b0,1'b0,pcf_command_data};
|
||||||
|
I2C_SEND<=1;
|
||||||
|
pcf_state<=4'b0110;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
4'b0110: begin
|
||||||
|
if(I2C_BUSY==1)begin
|
||||||
|
I2C_SEND<=0;
|
||||||
|
pcf_state<=4'b0111;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
4'b0111:begin
|
||||||
|
if(I2C_BUSY==0)begin
|
||||||
|
pcf_state<=4'b0000;
|
||||||
|
pcf_busy<=1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
4'b1111:begin
|
||||||
|
if(I2C_BUSY==1)begin
|
||||||
|
pcf_state<=4'b0000;
|
||||||
|
I2C_SEND<=1'b0;
|
||||||
|
pcf_busy<=1'b0;
|
||||||
|
end else begin
|
||||||
|
i2c_data<={4'b0,backlight,1'b0,1'b0,1'b0};
|
||||||
|
backlight_latch<=0;
|
||||||
|
I2C_SEND<=1'b1;
|
||||||
|
pcf_busy<=1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
default:begin
|
||||||
|
pcf_state<=0;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
Loading…
Reference in New Issue
Block a user