--- /dev/null
+module i2c_write (
+ input clk,
+ output scl,
+ output sda,
+ input [7:0] tx_byte,
+ input transmit,
+ input [5:0] more_bytes, /* 0 or 1 or 16 are reasonable */
+ input [7:0] mb_in,
+ output [5:0] mb_addr,
+ output is_transmitting);
+
+parameter CLOCK_DIVIDE = 1;
+
+// States for the transmitting state machine.
+// We transmit a START, then the address (constant 0xE1), then
+// [tx_byte], then [more_bytes] bytes from [mb_in]
+parameter TX_IDLE = 0;
+parameter TX_ADDRESS = 1;
+parameter TX_FIRST_BYTE = 2;
+parameter TX_MORE_BYTES = 3;
+parameter TX_STOP = 4;
+
+reg [10:0] tx_clk_divider = CLOCK_DIVIDE;
+
+reg data_out = 1'b1;
+reg clk_out = 1'b1;
+
+reg [3:0] tx_state = TX_IDLE;
+reg [5:0] tx_countdown;
+reg [3:0] tx_bits_remaining;
+reg [7:0] tx_data;
+
+reg [3:0] step = 0;
+
+wire [7:0] address = {7'h70, 1'b0}; // address 0x70, write
+wire [15:0] address_data = {address, tx_data};
+
+assign sda = data_out;
+assign scl = clk_out;
+assign is_transmitting = tx_state != TX_IDLE;
+
+always @(posedge clk) begin
+ // The clk_divider counter counts down from
+ // the CLOCK_DIVIDE constant. Whenever it
+ // reaches 0, 1/16 of the bit period has elapsed.
+ // Countdown timers for the receiving and transmitting
+ // state machines are decremented.
+ tx_clk_divider = tx_clk_divider - 1;
+ if (!tx_clk_divider) begin
+ tx_clk_divider = CLOCK_DIVIDE;
+ tx_countdown = tx_countdown - 1;
+ end
+
+ // Transmit state machine
+ case (tx_state)
+ TX_IDLE: begin
+ if (transmit) begin
+ // If the transmit flag is raised in the idle
+ // state, save tx_byte for transmission
+ tx_data = tx_byte;
+ // Send the initial, low pulse of 1 bit period
+ // to signal the start, followed by the data
+ data_out = 0;
+ tx_state = TX_ADDRESS;
+ tx_bits_remaining = 8;
+ step = 0;
+ end
+ end // case: TX_IDLE
+
+ TX_ADDRESS: begin
+ if(step == 0) begin
+ clk_out <= 0;
+ step <= 1;
+ end else if (tx_bits_remaining == 0) begin
+ if(step == 1) begin
+ data_out <= 0; // really should be z, not 0
+ step <= 2;
+ end else if(step == 2)begin
+ clk_out <= 1;
+ step <= 3;
+ end else begin
+ step <= 0;
+
+ tx_state <= TX_FIRST_BYTE;
+ tx_bits_remaining <= 8;
+ end
+ end else if(step == 1) begin
+ data_out <= address[tx_bits_remaining - 1];
+ step <= 2;
+ end else if(step == 2) begin
+ clk_out <= 1;
+ step <= 3;
+ end else begin // step == 3
+ tx_bits_remaining = tx_bits_remaining - 1;
+ step <= 0;
+ end
+ end // case: TX_ADDRESS
+
+ TX_FIRST_BYTE: begin
+ if(step == 0) begin
+ clk_out <= 0;
+ step <= 1;
+ end else if (tx_bits_remaining == 0) begin
+ if(step == 1) begin
+ data_out <= 0; // really should be z, not 0
+ step <= 2;
+ end else if(step == 2)begin
+ clk_out <= 1;
+ step <= 3;
+ end else begin
+ step <= 0;
+
+ tx_state <= TX_STOP;
+ end
+ end else if(step == 1) begin
+ data_out <= tx_data[tx_bits_remaining - 1];
+ step <= 2;
+ end else if(step == 2) begin
+ clk_out <= 1;
+ step <= 3;
+ end else begin // step == 3
+ tx_bits_remaining = tx_bits_remaining - 1;
+ step <= 0;
+ end
+ end // case: TX_FIRST_BYTE
+
+ TX_STOP: begin
+ if(step == 0) begin
+ clk_out <= 0;
+ step <= 1;
+ end else if(step == 1) begin
+ step <= 2;
+ end else if(step == 2) begin
+ clk_out <= 1;
+ step <= 3;
+ end else begin
+ data_out <= 1;
+ step <= 0;
+ tx_state <= TX_IDLE;
+ end
+ end
+ endcase
+end
+endmodule // i2c_write
`include "master_rom.v"
+`include "i2c.v"
+`include "uart.v"
`ifdef SIM
`define UART_DIVIDE 1
// s/192/3/ for 19200 baud uart
`endif
-module master(input CLKin, output [4:0] led, output uart_tx, input uart_rx, output reg ready_out = 1, input ready_in);
- wire clk;
- wire clk_tmp;
+module master(input CLKin, output [4:0] led, output uart_tx, input uart_rx, output reg ready_out = 1, input ready_in, output scl, output sda);
+// wire clk;
+// wire clk_tmp;
//pll pll (.clock_in(CLKin), .clock_out(clk));
reg [20:0] counter = 0;
+`ifdef SIM
+ wire clk = CLKin;
+`else
reg clk = 0;
always @ (posedge CLKin) begin
else
counter <= counter + 1;
end
+`endif
reg [3:0] program_counter = 0;
wire [31:0] rom_output;
master_rom master_rom (.clk(clk), .addr(program_counter), .data(rom_output));
+ reg [7:0] i2c_tx_byte;
+ reg i2c_transmit = 0;
+ wire i2c_is_transmitting;
+
+ i2c_write i2c (.clk(clk), .scl(scl), .sda(sda), .tx_byte(i2c_tx_byte), .transmit(i2c_transmit), .is_transmitting(i2c_is_transmitting));
+
+ reg [3:0] i2c_init_step = 0;
+
+ always @ (posedge clk) begin
+ if(i2c_is_transmitting || i2c_transmit)
+ i2c_transmit <= 0;
+ else begin
+ if(i2c_init_step == 0) begin
+ i2c_tx_byte <= 8'h21; // turn on oscillator
+ i2c_transmit <= 1;
+ i2c_init_step <= 1;
+ end else if(i2c_init_step == 1) begin
+ i2c_tx_byte <= 8'h87; // display on, blink 0.5Hz
+ i2c_transmit <= 1;
+ i2c_init_step <= 2;
+ end else if(i2c_init_step == 2) begin
+ i2c_tx_byte <= 8'hEF; // max brightness
+ i2c_transmit <= 1;
+ i2c_init_step <= 3;
+ end
+ end
+ end
+
`define STATE_SEND 0
`define STATE_WAIT_PROPAGATE 1
reg [7:0] saved_news [3:0];
assign led[4] = state != `STATE_WASTE_TIME;
- assign led[3:0] = 0;
+ assign led[3:0] = i2c_init_step;
always @(posedge clk) begin
case(state)
- receive the instruction back
- receive the news
- propagate the news
- - go back to `STATE_SEND
+ - go to `STATE_WASTE_TIME
*/
if(uart_ptr == 8) begin
state <= `STATE_PROPAGATE_NEWS;