I2C_BOOTLOADER: Added support for error handling

This commit is contained in:
(Tim) Efthimis Kritikos 2024-02-10 22:35:33 +00:00
parent a8c29aff9b
commit aac55f7038
5 changed files with 76 additions and 55 deletions

View File

@ -20,15 +20,23 @@ mov al,#0x00
outb #0x60 outb #0x60
wait_send: inb #0x62 wait_send:
inb #0x62
test al,#0x02
jnz rom_fail
test al,#0x01 test al,#0x01
jnz wait_send jnz wait_send
mov bx,#OK_loading_txt mov bx,#OK_loading_txt
call print call print
jmp read_code
rom_fail:
call rom_fail_print
;############ READ CODE ################## ;############ READ CODE ##################
read_code:
mov bx,#0xEFFF mov bx,#0xEFFF
mov di,#0x0000 mov di,#0x0000
@ -66,9 +74,6 @@ test al,#0x01
jnz wait_send2 jnz wait_send2
inw #0x60 inw #0x60
;MOV CL,AH
;MOV AH,AL
;MOV AL,CL
STOSW STOSW
@ -135,10 +140,13 @@ call print
ret ret
;######################################### ;#########################################
include LiteDram_init.asm include LiteDram_init.asm
rom_fail_print:
mov bx,#rom_fail_txt
call print
hlt
print: print:
mov al,[bx] mov al,[bx]
cmp al,#0 cmp al,#0
@ -155,6 +163,7 @@ STACK: ; brainfuck_mandelbrot depends on stack being at the end
load_i2c_txt: .ASCII 'Read I2C EEPROM:\0' load_i2c_txt: .ASCII 'Read I2C EEPROM:\0'
OK_loading_txt: .ASCII 'OK\nLoading rom 0%\r\0' OK_loading_txt: .ASCII 'OK\nLoading rom 0%\r\0'
loading_rom_txt: .ASCII 'Loading rom \0' loading_rom_txt: .ASCII 'Loading rom \0'
rom_fail_txt: .ASCII 'FAIL\nNo i2c rom at 0x50\0'
ten_prc_txt: .ASCII '10%\r\0' ten_prc_txt: .ASCII '10%\r\0'
twenty_prc_txt: .ASCII '20%\r\0' twenty_prc_txt: .ASCII '20%\r\0'
thirty_prc_txt: .ASCII '30%\r\0' thirty_prc_txt: .ASCII '30%\r\0'

View File

@ -441,6 +441,7 @@ wire [6:0] CPU_I2C_OUT_ADDRESS;
wire CPU_I2C_OUT_BUSY,CPU_I2C_OUT_TRANSACT,CPU_I2C_DIR; wire CPU_I2C_OUT_BUSY,CPU_I2C_OUT_TRANSACT,CPU_I2C_DIR;
wire [15:0]CPU_I2C_DATA_READ,CPU_I2C_DATA_WRITE; wire [15:0]CPU_I2C_DATA_READ,CPU_I2C_DATA_WRITE;
wire CPU_I2C_IGN_ACK; wire CPU_I2C_IGN_ACK;
wire CPU_I2C_ERROR;
CPU_to_I2C_driver_bridge CPU_to_I2C_driver_bridge ( CPU_to_I2C_driver_bridge CPU_to_I2C_driver_bridge (
.clock(CPU_SPEED), .clock(CPU_SPEED),
@ -463,7 +464,8 @@ CPU_to_I2C_driver_bridge CPU_to_I2C_driver_bridge (
.OUT_I2C_DATA_WRITE(CPU_I2C_DATA_WRITE), .OUT_I2C_DATA_WRITE(CPU_I2C_DATA_WRITE),
.TRANS_WIDTH(CPU_I2C_TRANS_WIDTH), .TRANS_WIDTH(CPU_I2C_TRANS_WIDTH),
.OUT_IGN_ACK(CPU_I2C_IGN_ACK) .OUT_IGN_ACK(CPU_I2C_IGN_ACK),
.IN_ERROR(CPU_I2C_ERROR)
); );
// Display driver // Display driver
@ -539,6 +541,7 @@ I2C_driver_multiplexer I2C_driver_multiplexer(
.IN1_I2C_DATA_WRITE({8'h0,DISP_I2C_DATA_WRITE}), .IN1_I2C_DATA_WRITE({8'h0,DISP_I2C_DATA_WRITE}),
.IN1_TRANS_WIDTH(1'b0), .IN1_TRANS_WIDTH(1'b0),
.IN1_IGN_ACK(1'b0), .IN1_IGN_ACK(1'b0),
//.IN2_ERROR(),
////// INPUT 2 /////// ////// INPUT 2 ///////
.IN2_ADDRESS(CPU_I2C_OUT_ADDRESS), .IN2_ADDRESS(CPU_I2C_OUT_ADDRESS),
@ -549,6 +552,7 @@ I2C_driver_multiplexer I2C_driver_multiplexer(
.IN2_I2C_DATA_WRITE(CPU_I2C_DATA_WRITE), .IN2_I2C_DATA_WRITE(CPU_I2C_DATA_WRITE),
.IN2_TRANS_WIDTH(CPU_I2C_TRANS_WIDTH), .IN2_TRANS_WIDTH(CPU_I2C_TRANS_WIDTH),
.IN2_IGN_ACK(CPU_I2C_IGN_ACK), .IN2_IGN_ACK(CPU_I2C_IGN_ACK),
.IN2_ERROR(CPU_I2C_ERROR),
////// OUTPUT /////// ////// OUTPUT ///////
.OUT_ADDRESS(MULT_TO_DRIV_I2C_ADDRESS), .OUT_ADDRESS(MULT_TO_DRIV_I2C_ADDRESS),
@ -558,7 +562,8 @@ I2C_driver_multiplexer I2C_driver_multiplexer(
.OUT_I2C_DATA_WRITE(MULT_TO_DRIV_DATA_WRITE), .OUT_I2C_DATA_WRITE(MULT_TO_DRIV_DATA_WRITE),
.OUT_I2C_DATA_READ(MULT_TO_DRIV_DATA_READ), .OUT_I2C_DATA_READ(MULT_TO_DRIV_DATA_READ),
.OUT_TRANS_WIDTH(MULT_TO_DRIV_TRANS_WIDTH), .OUT_TRANS_WIDTH(MULT_TO_DRIV_TRANS_WIDTH),
.OUT_IGN_ACK(MULT_TO_DRIV_IGN_ACK) .OUT_IGN_ACK(MULT_TO_DRIV_IGN_ACK),
.OUT_ERROR(MULT_TO_DRIV_ERROR)
); );
// I2C driver // I2C driver
@ -567,6 +572,7 @@ wire SDA_direction;
wire SCL,SDA_input,SDA_output; wire SCL,SDA_input,SDA_output;
wire MULT_TO_DRIV_TRANS_WIDTH; wire MULT_TO_DRIV_TRANS_WIDTH;
wire MULT_TO_DRIV_IGN_ACK; wire MULT_TO_DRIV_IGN_ACK;
wire MULT_TO_DRIV_ERROR;
I2C_driver i2c_driver( I2C_driver i2c_driver(
.clock(I2C_SPEED), .clock(I2C_SPEED),
@ -584,7 +590,9 @@ I2C_driver i2c_driver(
.i2c_data_read(MULT_TO_DRIV_DATA_READ), .i2c_data_read(MULT_TO_DRIV_DATA_READ),
.transact_width(MULT_TO_DRIV_TRANS_WIDTH), .transact_width(MULT_TO_DRIV_TRANS_WIDTH),
.ignore_ack(MULT_TO_DRIV_IGN_ACK) .ignore_ack(MULT_TO_DRIV_IGN_ACK),
.error(MULT_TO_DRIV_ERROR)
); );
`ifdef SYNTHESIS `ifdef SYNTHESIS

View File

@ -38,7 +38,9 @@ module CPU_to_I2C_driver_bridge (
output reg [15:0] OUT_I2C_DATA_WRITE, output reg [15:0] OUT_I2C_DATA_WRITE,
output reg TRANS_WIDTH, output reg TRANS_WIDTH,
output reg OUT_IGN_ACK output reg OUT_IGN_ACK,
input IN_ERROR
); );
//assign data_bus_out=((address==3'h0)&&chip_select_n==1'b0&&read_n==1'b0)? 16'h0043 : 16'h0000; //assign data_bus_out=((address==3'h0)&&chip_select_n==1'b0&&read_n==1'b0)? 16'h0043 : 16'h0000;
@ -67,7 +69,7 @@ always @( posedge clock )begin
if ( chip_select_n==0 && read_n==0 )begin if ( chip_select_n==0 && read_n==0 )begin
case (address) case (address)
3'h0: data_bus_out <= {OUT_I2C_DATA_READ}; 3'h0: data_bus_out <= {OUT_I2C_DATA_READ};
3'h2: data_bus_out <= {15'd0,OUT_BUSY|WAIT}; 3'h2: data_bus_out <= {14'd0,IN_ERROR,OUT_BUSY|WAIT};
default: data_bus_out <= 16'h0; default: data_bus_out <= 16'h0;
endcase endcase
end end

View File

@ -20,7 +20,7 @@
module I2C_driver ( module I2C_driver (
input wire clock, input wire clock,
input wire SDA_input, input wire SDA_input,
output wire SDA_output, output reg SDA_output,
output reg SDA_direction, //1:output 0:input output reg SDA_direction, //1:output 0:input
output reg SCL, output reg SCL,
@ -31,17 +31,15 @@ module I2C_driver (
input wire [15:0] i2c_data_write, input wire [15:0] i2c_data_write,
input wire transact_width, /* 0=byte 1=word */ input wire transact_width, /* 0=byte 1=word */
input wire ignore_ack, input wire ignore_ack,
output reg [15:0] i2c_data_read=16'h4141 output reg [15:0] i2c_data_read=16'h4141,
output reg error=0,
); );
//assign i2c_data_read=16'h0042; //assign i2c_data_read=16'h0042;
reg DIR_latched; reg DIR_latched;
reg SDA; // TODO make SDA_output a reg and rename everything
assign SDA_output=SDA;
reg [5:0] i2c_state = 6'b100100; reg [5:0] i2c_state = 6'b100100;
reg [3:0] data_bit_counter; reg [3:0] data_bit_counter;
@ -55,17 +53,17 @@ always @(posedge clock) begin
/***** start sequence ******/ /***** start sequence ******/
6'b000000:begin 6'b000000:begin
SDA_direction<=1; SDA_direction<=1;
SDA<=1; SDA_output<=1;
SCL<=1; SCL<=1;
i2c_state<=6'b000001; i2c_state<=6'b000001;
end end
6'b000001:begin 6'b000001:begin
SDA<=0; SDA_output<=0;
SCL<=1; SCL<=1;
i2c_state<=6'b000010; i2c_state<=6'b000010;
end end
6'b000010:begin 6'b000010:begin
SDA<=0; SDA_output<=0;
SCL<=0; SCL<=0;
i2c_state<=6'b000011; i2c_state<=6'b000011;
data_bit_counter<=0; data_bit_counter<=0;
@ -77,7 +75,7 @@ always @(posedge clock) begin
end end
6'b000100:begin 6'b000100:begin
SCL<=0; SCL<=0;
SDA<=address_internal[6:6]; SDA_output<=address_internal[6:6];
address_internal[6:0]<={address_internal[5:0],1'b0}; address_internal[6:0]<={address_internal[5:0],1'b0};
data_bit_counter<=data_bit_counter+1; data_bit_counter<=data_bit_counter+1;
i2c_state<=6'b000101; i2c_state<=6'b000101;
@ -100,7 +98,7 @@ always @(posedge clock) begin
end end
6'b001000:begin 6'b001000:begin
SCL<=0; SCL<=0;
SDA<=DIR_latched;/*Write=0 Read=1*/ SDA_output<=DIR_latched;/*Write=0 Read=1*/
i2c_state<=6'b001001; i2c_state<=6'b001001;
end end
6'b001001:begin 6'b001001:begin
@ -128,16 +126,16 @@ always @(posedge clock) begin
6'b001110:begin 6'b001110:begin
SCL<=1; SCL<=1;
if (SDA_input==1)begin if (SDA_input==1)begin
i2c_state<=6'b111111; //TODO: Don't freeze the entire driver if a single error occurs!! (here and on the second ack as well) error<=1'b1;
end else begin i2c_state<=6'b100100;
i2c_state<=6'b001111;
data_bit_counter<=0;
end end
i2c_state<=6'b001111;
data_bit_counter<=0;
end end
/****** separator ********/ /****** separator ********/
6'b001111:begin 6'b001111:begin
SCL<=0; SCL<=0;
SDA<=0; SDA_output<=0;
i2c_state<=6'b010000; i2c_state<=6'b010000;
end end
6'b010000:begin 6'b010000:begin
@ -146,17 +144,17 @@ always @(posedge clock) begin
end end
6'b010001:begin 6'b010001:begin
SCL<=0; SCL<=0;
SDA<=1; SDA_output<=1;
i2c_state<=6'b010010; i2c_state<=6'b010010;
end end
6'b010010:begin 6'b010010:begin
SCL<=0; SCL<=0;
SDA<=1; SDA_output<=1;
i2c_state<=6'b010011; i2c_state<=6'b010011;
end end
6'b010011:begin 6'b010011:begin
SCL<=0; SCL<=0;
SDA<=0; SDA_output<=0;
i2c_state<=6'b010100; i2c_state<=6'b010100;
end end
/****** Send data ********/ /****** Send data ********/
@ -172,7 +170,7 @@ always @(posedge clock) begin
6'b010101:begin 6'b010101:begin
SCL<=0; SCL<=0;
if(DIR_latched==1'b0)begin if(DIR_latched==1'b0)begin
SDA<=data_internal[7:7]; SDA_output<=data_internal[7:7];
data_internal[7:0]<={data_internal[6:0],1'b0}; data_internal[7:0]<={data_internal[6:0],1'b0};
end end
data_bit_counter<=data_bit_counter+1; data_bit_counter<=data_bit_counter+1;
@ -208,7 +206,7 @@ always @(posedge clock) begin
6'b011001:begin 6'b011001:begin
SCL<=0; SCL<=0;
if(DIR_latched==1'b1)begin if(DIR_latched==1'b1)begin
SDA<=1'b0; SDA_output<=1'b0;
end end
i2c_state<=6'b011010; i2c_state<=6'b011010;
end end
@ -218,15 +216,14 @@ always @(posedge clock) begin
end end
6'b011011:begin 6'b011011:begin
SCL<=1; SCL<=1;
if (SDA_input==0||DIR_latched==1'b1)begin if (SDA_input==1 && DIR_latched==1'b0)begin
if(trans_width_latch==1'b1)begin error<=1'b1;
i2c_state<=6'b100101;
data_bit_counter<=4'd0;
end else
i2c_state<=6'b011100;
end else begin
i2c_state<=6'b111111;
end end
if(trans_width_latch==1'b1)begin
i2c_state<=6'b100101;
data_bit_counter<=4'd0;
end else
i2c_state<=6'b011100;
end end
/****** Send data (16bit) ********/ /****** Send data (16bit) ********/
6'b100101:begin 6'b100101:begin
@ -241,7 +238,7 @@ always @(posedge clock) begin
6'b100110:begin 6'b100110:begin
SCL<=0; SCL<=0;
if(DIR_latched==1'b0)begin if(DIR_latched==1'b0)begin
SDA<=data_internal[15:15]; SDA_output<=data_internal[15:15];
data_internal[15:8]<={data_internal[14:8],1'b0}; data_internal[15:8]<={data_internal[14:8],1'b0};
end end
data_bit_counter<=data_bit_counter+1; data_bit_counter<=data_bit_counter+1;
@ -277,17 +274,16 @@ always @(posedge clock) begin
end end
6'b101100:begin 6'b101100:begin
SCL<=1; SCL<=1;
if (SDA_input==0||ignore_ack==1'b1)begin if ( SDA_input==1 && DIR_latched==1'b0 ) begin
i2c_state<=6'b011100; error<=1'b1;
SDA_direction<=1;
end else begin
i2c_state<=6'b111111;
end end
i2c_state<=6'b011100;
SDA_direction<=1;
end end
/****** separator ********/ /****** separator ********/
6'b011100:begin 6'b011100:begin
SCL<=0; SCL<=0;
SDA<=0; SDA_output<=0;
i2c_state<=6'b011101; i2c_state<=6'b011101;
end end
6'b011101:begin 6'b011101:begin
@ -296,33 +292,33 @@ always @(posedge clock) begin
end end
6'b011110:begin 6'b011110:begin
SCL<=0; SCL<=0;
SDA<=1; SDA_output<=1;
i2c_state<=6'b011111; i2c_state<=6'b011111;
end end
6'b011111:begin 6'b011111:begin
SCL<=0; SCL<=0;
SDA<=1; SDA_output<=1;
i2c_state<=6'b100000; i2c_state<=6'b100000;
end end
6'b100000:begin 6'b100000:begin
SCL<=0; SCL<=0;
SDA<=0; SDA_output<=0;
i2c_state<=6'b100001; i2c_state<=6'b100001;
end end
/****** stop bit *******/ /****** stop bit *******/
6'b100001:begin 6'b100001:begin
SCL<=1; SCL<=1;
SDA<=0; SDA_output<=0;
i2c_state<=6'b100010; i2c_state<=6'b100010;
end end
6'b100010:begin 6'b100010:begin
SCL<=1; SCL<=1;
SDA<=1; SDA_output<=1;
i2c_state<=6'b100011; i2c_state<=6'b100011;
end end
6'b100011:begin 6'b100011:begin
SCL<=1; SCL<=1;
SDA<=1; SDA_output<=1;
i2c_state<=6'b100100; i2c_state<=6'b100100;
I2C_BUSY<=0; I2C_BUSY<=0;
end end
@ -334,11 +330,12 @@ always @(posedge clock) begin
address_internal<=address; address_internal<=address;
trans_width_latch<=transact_width; trans_width_latch<=transact_width;
DIR_latched<=DIR; DIR_latched<=DIR;
error<=1'b0;
end end
end end
default:begin default:begin
SCL<=0; SCL<=0;
SDA<=0; SDA_output<=0;
end end
endcase endcase

View File

@ -30,6 +30,7 @@ module I2C_driver_multiplexer (
input wire [15:0] IN1_I2C_DATA_WRITE, input wire [15:0] IN1_I2C_DATA_WRITE,
input IN1_TRANS_WIDTH, input IN1_TRANS_WIDTH,
input IN1_IGN_ACK, input IN1_IGN_ACK,
output reg IN1_ERROR,
////// INPUT 2 /////// ////// INPUT 2 ///////
input wire [6:0] IN2_ADDRESS, input wire [6:0] IN2_ADDRESS,
@ -40,6 +41,7 @@ module I2C_driver_multiplexer (
input wire [15:0] IN2_I2C_DATA_WRITE, input wire [15:0] IN2_I2C_DATA_WRITE,
input IN2_TRANS_WIDTH, input IN2_TRANS_WIDTH,
input IN2_IGN_ACK, input IN2_IGN_ACK,
output reg IN2_ERROR,
////// OUTPUT /////// ////// OUTPUT ///////
output wire [6:0] OUT_ADDRESS, output wire [6:0] OUT_ADDRESS,
@ -49,7 +51,8 @@ module I2C_driver_multiplexer (
input wire [15:0] OUT_I2C_DATA_READ, input wire [15:0] OUT_I2C_DATA_READ,
output wire [15:0] OUT_I2C_DATA_WRITE, output wire [15:0] OUT_I2C_DATA_WRITE,
output OUT_TRANS_WIDTH, output OUT_TRANS_WIDTH,
output wire OUT_IGN_ACK output wire OUT_IGN_ACK,
input wire OUT_ERROR
); );
reg select; reg select;
@ -110,8 +113,10 @@ end
always @(negedge OUT_BUSY)begin always @(negedge OUT_BUSY)begin
if(select)begin if(select)begin
IN1_I2C_DATA_READ<=OUT_I2C_DATA_READ; IN1_I2C_DATA_READ<=OUT_I2C_DATA_READ;
IN1_ERROR<=OUT_ERROR;
end else begin end else begin
IN2_I2C_DATA_READ<=OUT_I2C_DATA_READ; IN2_I2C_DATA_READ<=OUT_I2C_DATA_READ;
IN2_ERROR<=OUT_ERROR;
end end
end end