module control ( input wire clk, output wire cfg_reset, input wire [15:0] cfg_src_data, output wire [15:0] cfg_src_addr, cfg_dst_data, cfg_dst_addr, input wire rx_empty, tx_full, input wire [7:0] rx_data, input wire [1:0] mux_max_byte, input wire [15:0] mux_min_addr, mux_max_addr, input wire [7:0] mux_q, output wire mux_reset, output wire mux_type, output wire [1:0] mux_chan, output wire [1:0] mux_byte, output wire [15:0] mux_addr, output wire rx_rdreq, output wire tx_wrreq, output wire [7:0] tx_data, output wire ram_we, output wire [19:0] ram_addr, inout wire [17:0] ram_data, output wire i2c_wrreq, output wire [15:0] i2c_data, input wire i2c_full, output wire led ); reg [23:0] led_counter; reg [18:0] ram_counter; reg [10:0] tst_counter; reg [15:0] int_addr, int_max_addr; reg int_rdreq, int_wrreq; reg int_type, int_reset; reg [1:0] int_chan, int_byte, int_max_byte; reg [7:0] int_data; reg int_led; reg [15:0] int_i2c_data; reg int_i2c_wrreq; reg int_cfg_reset; reg [15:0] int_dst_data, int_dst_addr; wire crc_error = 1'b0; reg crc_reset; reg [2:0] byte_counter; reg [4:0] idle_counter; reg [4:0] state; wire [15:0] src, dst; reg [7:0] buffer [7:0]; assign src = (buffer[0][7]) ? cfg_src_data : {buffer[2], buffer[3]}; assign dst = {1'b0, buffer[0][6:0], buffer[1]}; reg int_ram_we; reg [17:0] int_ram_data; wire [17:0] int_ram_q; wire [17:0] opt_ram_we; assign ram_we = ~int_ram_we; assign int_ram_q = ram_data; // assign ram_data = int_ram_we ? int_ram_data : 18'bz; // assign ram_addr = {ram_counter[18:5],1'd0,ram_counter[4:0]}; assign ram_addr = {1'd0, ram_counter[18:0]}; genvar j; generate for (j = 0; j < 18; j = j + 1) begin : SRAM_WE assign opt_ram_we[j] = int_ram_we; assign ram_data[j] = opt_ram_we[j] ? int_ram_data[j] : 1'bz; end endgenerate always @(posedge clk) begin if (~rx_empty) begin int_led <= 1'b0; led_counter <= 24'd0; end else begin if (&led_counter) begin int_led <= 1'b1; end else begin led_counter <= led_counter + 24'd1; end end case(state) 0: begin int_rdreq <= 1'b1; int_wrreq <= 1'b0; int_type <= 1'b0; int_chan <= 2'd0; int_byte <= 2'd0; int_reset <= 1'b0; crc_reset <= 1'b0; int_ram_we <= 1'b0; int_ram_data <= 16'd0; ram_counter <= 19'd0; idle_counter <= 5'd0; byte_counter <= 3'd0; int_cfg_reset <= 1'b0; state <= 5'd1; end 1: begin // read 8 bytes if (~rx_empty) begin idle_counter <= 5'd0; byte_counter <= byte_counter + 3'd1; buffer[byte_counter] <= rx_data; if (&byte_counter) begin int_rdreq <= 1'b0; state <= 5'd2; end end else if(|byte_counter) begin idle_counter <= idle_counter + 5'd1; if (&idle_counter) begin int_rdreq <= 1'b0; crc_reset <= 1'b1; state <= 5'd0; end end end 2: begin crc_reset <= 1'b1; if (~crc_error) begin int_dst_addr <= dst; int_dst_data <= src; // memory[dst[3:0]] <= src; case (dst) 16'h0000: begin int_cfg_reset <= 1'b1; state <= 5'd0; end 16'h0001: begin int_type <= src[4]; int_chan <= src[1:0]; int_reset <= 1'b1; state <= 5'd0; end 16'h0002: begin int_type <= src[4]; int_chan <= src[1:0]; state <= 5'd3; end 16'h0003: begin tst_counter <= 11'd0; state <= 5'd6; end 16'h0004: begin int_ram_we <= 1'b1; int_ram_data <= 18'd0; ram_counter <= 19'd0; state <= 5'd9; end 16'h0005: begin int_i2c_data <= src; int_i2c_wrreq <= 1'b1; state <= 5'd15; end default: begin state <= 5'd0; end endcase end end // mux transfer 3: begin crc_reset <= 1'b0; int_addr <= mux_min_addr; int_max_addr <= mux_min_addr + mux_max_addr; int_max_byte <= mux_max_byte; int_byte <= 2'd0; state <= 5'd4; end 4: begin int_wrreq <= 1'b0; state <= 5'd5; end 5: begin if (~tx_full) begin int_data <= mux_q; int_wrreq <= 1'b1; if ((int_byte == int_max_byte) && (int_addr == int_max_addr)) begin state <= 5'd0; end else begin state <= 5'd4; if (int_byte == int_max_byte) begin int_addr <= int_addr + 16'd1; int_byte <= 2'd0; end else begin int_byte <= int_byte + 2'd1; end end end end // tst transfer 6: begin crc_reset <= 1'b0; int_data <= tst_counter; int_wrreq <= 1'b1; tst_counter <= tst_counter + 11'd1; state <= 5'd7; end 7: begin if (~tx_full) begin int_data <= tst_counter; if (&tst_counter) begin state <= 5'd8; end else begin tst_counter <= tst_counter + 11'd1; end end end 8: begin if (~tx_full) begin int_wrreq <= 1'b0; state <= 5'd0; end end // ram transfer 9: begin crc_reset <= 1'b0; state <= 5'd10; end 10: begin int_ram_data[8:1] <= ram_counter[7:0]; // int_ram_data[8:1] <= 8'd0; if (&ram_counter) begin state <= 5'd11; end else begin state <= 5'd9; ram_counter <= ram_counter + 19'd1; end end 11: begin int_ram_we <= 1'b0; int_ram_data <= 18'd0; ram_counter <= 19'd0; state <= 5'd12; end 12: begin int_wrreq <= 1'b0; state <= 5'd13; end 13: begin state <= 5'd14; end 14: begin if (~tx_full) begin int_data <= int_ram_q[8:1]; int_wrreq <= 1'b1; if (&ram_counter) begin state <= 5'd0; end else begin state <= 5'd12; ram_counter <= ram_counter + 19'd1; end end end // i2c write 15: begin crc_reset <= 1'b0; if (~i2c_full) begin int_i2c_wrreq <= 1'b0; state <= 5'd0; end end default: begin state <= 5'd0; end endcase end assign cfg_reset = int_cfg_reset; assign cfg_src_addr = {buffer[2], buffer[3]}; assign cfg_dst_data = int_dst_data; assign cfg_dst_addr = int_dst_addr; assign mux_reset = int_reset; assign mux_type = int_type; assign mux_chan = int_chan; assign mux_byte = int_byte; assign mux_addr = int_addr; assign rx_rdreq = int_rdreq & (~rx_empty); assign tx_wrreq = int_wrreq & (~tx_full); assign tx_data = int_data; assign i2c_wrreq = int_i2c_wrreq; assign i2c_data = int_i2c_data; assign led = int_led; endmodule