// (C) 2001-2015 Altera Corporation. All rights reserved. // Your use of Altera Corporation's design tools, logic functions and other // software and tools, and its AMPP partner logic functions, and any output // files any of the foregoing (including device programming or simulation // files), and any associated documentation or information are expressly subject // to the terms and conditions of the Altera Program License Subscription // Agreement, Altera MegaCore Function License Agreement, or other applicable // license agreement, including, without limitation, that your use is for the // sole purpose of programming logic devices manufactured by Altera and sold by // Altera or its authorized distributors. Please refer to the applicable // agreement for further details. // -------------------------------------------------------------------------------- //| Avalon ST Packets to MM Master Transaction Component // -------------------------------------------------------------------------------- `timescale 1ns / 100ps // -------------------------------------------------------------------------------- //| Fast Transaction Master // -------------------------------------------------------------------------------- module altera_avalon_packets_to_master ( // Interface: clk input wire clk, input wire reset_n, // Interface: ST in output wire in_ready, input wire in_valid, input wire [ 7: 0] in_data, input wire in_startofpacket, input wire in_endofpacket, // Interface: ST out input wire out_ready, output wire out_valid, output wire [ 7: 0] out_data, output wire out_startofpacket, output wire out_endofpacket, // Interface: MM out output wire [31: 0] address, input wire [31: 0] readdata, output wire read, output wire write, output wire [ 3: 0] byteenable, output wire [31: 0] writedata, input wire waitrequest, input wire readdatavalid ); wire [ 35: 0] fifo_readdata; wire fifo_read; wire fifo_empty; wire [ 35: 0] fifo_writedata; wire fifo_write; wire fifo_write_waitrequest; // --------------------------------------------------------------------- //| Parameter Declarations // --------------------------------------------------------------------- parameter EXPORT_MASTER_SIGNALS = 0; parameter FIFO_DEPTHS = 2; parameter FIFO_WIDTHU = 1; parameter FAST_VER = 0; generate if (FAST_VER) begin packets_to_fifo p2f ( .clk (clk), .reset_n (reset_n), .in_ready (in_ready), .in_valid (in_valid), .in_data (in_data), .in_startofpacket (in_startofpacket), .in_endofpacket (in_endofpacket), .address (address), .readdata (readdata), .read (read), .write (write), .byteenable (byteenable), .writedata (writedata), .waitrequest (waitrequest), .readdatavalid (readdatavalid), .fifo_writedata (fifo_writedata), .fifo_write (fifo_write), .fifo_write_waitrequest (fifo_write_waitrequest) ); fifo_to_packet f2p ( .clk (clk), .reset_n (reset_n), .out_ready (out_ready), .out_valid (out_valid), .out_data (out_data), .out_startofpacket (out_startofpacket), .out_endofpacket (out_endofpacket), .fifo_readdata (fifo_readdata), .fifo_read (fifo_read), .fifo_empty (fifo_empty) ); fifo_buffer #( .FIFO_DEPTHS(FIFO_DEPTHS), .FIFO_WIDTHU(FIFO_WIDTHU) ) fb ( .wrclock (clk), .reset_n (reset_n), .avalonmm_write_slave_writedata (fifo_writedata), .avalonmm_write_slave_write (fifo_write), .avalonmm_write_slave_waitrequest (fifo_write_waitrequest), .avalonmm_read_slave_readdata (fifo_readdata), .avalonmm_read_slave_read (fifo_read), .avalonmm_read_slave_waitrequest (fifo_empty) ); end else begin packets_to_master p2m ( .clk (clk), .reset_n (reset_n), .in_ready (in_ready), .in_valid (in_valid), .in_data (in_data), .in_startofpacket (in_startofpacket), .in_endofpacket (in_endofpacket), .address (address), .readdata (readdata), .read (read), .write (write), .byteenable (byteenable), .writedata (writedata), .waitrequest (waitrequest), .readdatavalid (readdatavalid), .out_ready (out_ready), .out_valid (out_valid), .out_data (out_data), .out_startofpacket (out_startofpacket), .out_endofpacket (out_endofpacket) ); end endgenerate endmodule module packets_to_fifo ( // Interface: clk input clk, input reset_n, // Interface: ST in output reg in_ready, input in_valid, input [ 7: 0] in_data, input in_startofpacket, input in_endofpacket, // Interface: MM out output reg [31: 0] address, input [31: 0] readdata, output reg read, output reg write, output reg [ 3: 0] byteenable, output reg [31: 0] writedata, input waitrequest, input readdatavalid, // Interface: FIFO // FIFO data format: // | sop, eop, [1:0]valid, [31:0]data | output reg [ 35: 0] fifo_writedata, output reg fifo_write, input wire fifo_write_waitrequest ); // --------------------------------------------------------------------- //| Command Declarations // --------------------------------------------------------------------- localparam CMD_WRITE_NON_INCR = 8'h00; localparam CMD_WRITE_INCR = 8'h04; localparam CMD_READ_NON_INCR = 8'h10; localparam CMD_READ_INCR = 8'h14; // --------------------------------------------------------------------- //| Signal Declarations // --------------------------------------------------------------------- reg [ 3: 0] state; reg [ 7: 0] command; reg [ 1: 0] current_byte, byte_avail; reg [ 15: 0] counter; reg [ 31: 0] read_data_buffer; reg [ 31: 0] fifo_data_buffer; reg in_ready_0; reg first_trans, last_trans, fifo_sop; reg [ 3: 0] unshifted_byteenable; wire enable; localparam READY = 4'b0000, GET_EXTRA = 4'b0001, GET_SIZE1 = 4'b0010, GET_SIZE2 = 4'b0011, GET_ADDR1 = 4'b0100, GET_ADDR2 = 4'b0101, GET_ADDR3 = 4'b0110, GET_ADDR4 = 4'b0111, GET_WRITE_DATA = 4'b1000, WRITE_WAIT = 4'b1001, READ_ASSERT = 4'b1010, READ_CMD_WAIT = 4'b1011, READ_DATA_WAIT = 4'b1100, PUSH_FIFO = 4'b1101, PUSH_FIFO_WAIT = 4'b1110, FIFO_CMD_WAIT = 4'b1111; // --------------------------------------------------------------------- //| Thingofamagick // --------------------------------------------------------------------- assign enable = (in_ready & in_valid); always @* begin in_ready = in_ready_0; end always @(posedge clk or negedge reset_n) begin if (!reset_n) begin in_ready_0 <= 1'b0; fifo_writedata <= 'b0; fifo_write <= 1'b0; fifo_sop <= 1'b0; read <= 1'b0; write <= 1'b0; byteenable <= 'b0; writedata <= 'b0; address <= 'b0; counter <= 'b0; command <= 'b0; first_trans <= 1'b0; last_trans <= 1'b0; state <= 'b0; current_byte <= 'b0; read_data_buffer <= 'b0; unshifted_byteenable <= 'b0; byte_avail <= 'b0; fifo_data_buffer <= 'b0; end else begin address[1:0] <= 'b0; in_ready_0 <= 1'b0; if (counter > 3) unshifted_byteenable <= 4'b1111; else if (counter == 3) unshifted_byteenable <= 4'b0111; else if (counter == 2) unshifted_byteenable <= 4'b0011; else if (counter == 1) unshifted_byteenable <= 4'b0001; case (state) READY : begin in_ready_0 <= !fifo_write_waitrequest; fifo_write <= 1'b0; end GET_EXTRA : begin in_ready_0 <= 1'b1; byteenable <= 'b0; if (enable) state <= GET_SIZE1; end GET_SIZE1 : begin in_ready_0 <= 1'b1; //load counter on reads only counter[15:8] <= command[4]?in_data:8'b0; if (enable) state <= GET_SIZE2; end GET_SIZE2 : begin in_ready_0 <= 1'b1; //load counter on reads only counter[7:0] <= command[4]?in_data:8'b0; if (enable) state <= GET_ADDR1; end GET_ADDR1 : begin in_ready_0 <= 1'b1; first_trans <= 1'b1; last_trans <= 1'b0; address[31:24] <= in_data; if (enable) state <= GET_ADDR2; end GET_ADDR2 : begin in_ready_0 <= 1'b1; address[23:16] <= in_data; if (enable) state <= GET_ADDR3; end GET_ADDR3 : begin in_ready_0 <= 1'b1; address[15:8] <= in_data; if (enable) state <= GET_ADDR4; end GET_ADDR4 : begin in_ready_0 <= 1'b1; address[7:2] <= in_data[7:2]; current_byte <= in_data[1:0]; if (enable) begin if (command == CMD_WRITE_NON_INCR | command == CMD_WRITE_INCR) begin state <= GET_WRITE_DATA; //writes in_ready_0 <= 1'b1; end else if (command == CMD_READ_NON_INCR | command == CMD_READ_INCR) begin state <= READ_ASSERT; //reads in_ready_0 <= 1'b0; end else begin //nops //treat all unrecognized commands as nops as well in_ready_0 <= 1'b0; state <= FIFO_CMD_WAIT; //| sop, eop, [1:0]valid, [31:0]data | //| 1 , 1 , 2'b11 ,{counter,reserved_byte}| fifo_writedata[7:0] <= (8'h80 | command); fifo_writedata[35:8]<= {4'b1111,counter[7:0],counter[15:8],8'b0}; fifo_write <= 1'b1; counter <= 0; end end end GET_WRITE_DATA : begin in_ready_0 <= 1'b1; if (enable) begin counter <= counter + 1'b1; //2 bit, should wrap by itself current_byte <= current_byte + 1'b1; if (in_endofpacket || current_byte == 3) begin in_ready_0 <= 1'b0; write <= 1'b1; state <= WRITE_WAIT; end end if (in_endofpacket) begin last_trans <= 1'b1; end // handle byte writes properly // drive data pins based on addresses case (current_byte) 0: begin writedata[7:0] <= in_data; byteenable[0] <= 1'b1; end 1: begin writedata[15:8] <= in_data; byteenable[1] <= 1'b1; end 2: begin writedata[23:16] <= in_data; byteenable[2] <= 1'b1; end 3: begin writedata[31:24] <= in_data; byteenable[3] <= 1'b1; end endcase end WRITE_WAIT : begin in_ready_0 <= 1'b0; write <= 1'b1; if (~waitrequest) begin write <= 1'b0; state <= GET_WRITE_DATA; in_ready_0 <= 1'b1; byteenable <= 'b0; if (command[2] == 1'b1) begin //increment address, but word-align it address[31:2] <= (address[31:2] + 1'b1); end if (last_trans) begin in_ready_0 <= 1'b0; state <= FIFO_CMD_WAIT; //| sop, eop, [1:0]valid, [31:0]data | //| 1 , 1 , 2'b11 ,{counter,reserved_byte}| fifo_writedata[7:0] <= (8'h80 | command); fifo_writedata[35:8]<= {4'b1111,counter[7:0],counter[15:8],8'b0}; fifo_write <= 1'b1; counter <= 0; end end end READ_ASSERT : begin if (current_byte == 3) byteenable <= unshifted_byteenable << 3; if (current_byte == 2) byteenable <= unshifted_byteenable << 2; if (current_byte == 1) byteenable <= unshifted_byteenable << 1; if (current_byte == 0) byteenable <= unshifted_byteenable; read <= 1'b1; fifo_write <= 1'b0; state <= READ_CMD_WAIT; end READ_CMD_WAIT : begin // number of valid byte case (byteenable) 4'b0000 : byte_avail <= 1'b0; 4'b0001 : byte_avail <= 1'b0; 4'b0010 : byte_avail <= 1'b0; 4'b0100 : byte_avail <= 1'b0; 4'b1000 : byte_avail <= 1'b0; 4'b0011 : byte_avail <= 1'b1; 4'b0110 : byte_avail <= 1'b1; 4'b1100 : byte_avail <= 1'b1; 4'b0111 : byte_avail <= 2'h2; 4'b1110 : byte_avail <= 2'h2; default : byte_avail <= 2'h3; endcase read_data_buffer <= readdata; read <= 1; // if readdatavalid, take the data and // go directly to READ_SEND_ISSUE. This is for fixed // latency slaves. Ignore waitrequest in this case, // since this master does not issue pipelined reads. // // For variable latency slaves, once waitrequest is low // the read command is accepted, so deassert read and // go to READ_DATA_WAIT to wait for readdatavalid if (readdatavalid) begin state <= PUSH_FIFO; read <= 0; end else begin if (~waitrequest) begin state <= READ_DATA_WAIT; read <= 0; end end end READ_DATA_WAIT : begin read_data_buffer <= readdata; if (readdatavalid) begin state <= PUSH_FIFO; end end PUSH_FIFO : begin fifo_write <= 1'b0; fifo_sop <= 1'b0; if (first_trans) begin first_trans <= 1'b0; fifo_sop <= 1'b1; end case (current_byte) 3 : begin fifo_data_buffer <= read_data_buffer >> 24; counter <= counter - 1'b1; end 2 : begin fifo_data_buffer <= read_data_buffer >> 16; if (counter == 1) counter <= 0; else counter <= counter - 2'h2; end 1 : begin fifo_data_buffer <= read_data_buffer >> 8; if (counter < 3) counter <= 0; else counter <= counter - 2'h3; end default : begin fifo_data_buffer <= read_data_buffer; if (counter < 4) counter <= 0; else counter <= counter - 3'h4; end endcase current_byte <= 0; state <= PUSH_FIFO_WAIT; end PUSH_FIFO_WAIT : begin // pushd return packet with data fifo_write <= 1'b1; fifo_writedata <= {fifo_sop,(counter == 0)?1'b1:1'b0,byte_avail,fifo_data_buffer}; // count down on the number of bytes to read // shift current byte location within word // if increment address, add it, so the next read // can use it, if more reads are required // no more bytes to send - go to READY state if (counter == 0) begin state <= FIFO_CMD_WAIT; end else if (command[2]== 1'b1) begin //increment address, but word-align it state <= FIFO_CMD_WAIT; address[31:2] <= (address[31:2] + 1'b1); end end FIFO_CMD_WAIT : begin // back pressure if fifo_write_waitrequest if (!fifo_write_waitrequest) begin if (counter == 0) begin state <= READY; end else begin state <= READ_ASSERT; end fifo_write <= 1'b0; end end endcase if (enable & in_startofpacket) begin state <= GET_EXTRA; command <= in_data; in_ready_0 <= !fifo_write_waitrequest; end end // end else end // end always block endmodule // -------------------------------------------------------------------------------- // FIFO buffer // -------------------------------------------------------------------------------- // turn off superfluous verilog processor warnings // altera message_level Level1 // altera message_off 10034 10035 10036 10037 10230 10240 10030 module fifo_buffer_single_clock_fifo ( // inputs: aclr, clock, data, rdreq, wrreq, // outputs: empty, full, q ) ; parameter FIFO_DEPTHS = 2; parameter FIFO_WIDTHU = 1; output empty; output full; output [ 35: 0] q; input aclr; input clock; input [ 35: 0] data; input rdreq; input wrreq; wire empty; wire full; wire [ 35: 0] q; scfifo single_clock_fifo ( .aclr (aclr), .clock (clock), .data (data), .empty (empty), .full (full), .q (q), .rdreq (rdreq), .wrreq (wrreq) ); defparam single_clock_fifo.add_ram_output_register = "OFF", single_clock_fifo.lpm_numwords = FIFO_DEPTHS, single_clock_fifo.lpm_showahead = "OFF", single_clock_fifo.lpm_type = "scfifo", single_clock_fifo.lpm_width = 36, single_clock_fifo.lpm_widthu = FIFO_WIDTHU, single_clock_fifo.overflow_checking = "ON", single_clock_fifo.underflow_checking = "ON", single_clock_fifo.use_eab = "OFF"; endmodule // turn off superfluous verilog processor warnings // altera message_level Level1 // altera message_off 10034 10035 10036 10037 10230 10240 10030 module fifo_buffer_scfifo_with_controls ( // inputs: clock, data, rdreq, reset_n, wrreq, // outputs: empty, full, q ) ; parameter FIFO_DEPTHS = 2; parameter FIFO_WIDTHU = 1; output empty; output full; output [ 35: 0] q; input clock; input [ 35: 0] data; input rdreq; input reset_n; input wrreq; wire empty; wire full; wire [ 35: 0] q; wire wrreq_valid; //the_scfifo, which is an e_instance fifo_buffer_single_clock_fifo #( .FIFO_DEPTHS(FIFO_DEPTHS), .FIFO_WIDTHU(FIFO_WIDTHU) ) the_scfifo ( .aclr (~reset_n), .clock (clock), .data (data), .empty (empty), .full (full), .q (q), .rdreq (rdreq), .wrreq (wrreq_valid) ); assign wrreq_valid = wrreq & ~full; endmodule // turn off superfluous verilog processor warnings // altera message_level Level1 // altera message_off 10034 10035 10036 10037 10230 10240 10030 module fifo_buffer ( // inputs: avalonmm_read_slave_read, avalonmm_write_slave_write, avalonmm_write_slave_writedata, reset_n, wrclock, // outputs: avalonmm_read_slave_readdata, avalonmm_read_slave_waitrequest, avalonmm_write_slave_waitrequest ) ; parameter FIFO_DEPTHS = 2; parameter FIFO_WIDTHU = 1; output [ 35: 0] avalonmm_read_slave_readdata; output avalonmm_read_slave_waitrequest; output avalonmm_write_slave_waitrequest; input avalonmm_read_slave_read; input avalonmm_write_slave_write; input [ 35: 0] avalonmm_write_slave_writedata; input reset_n; input wrclock; wire [ 35: 0] avalonmm_read_slave_readdata; wire avalonmm_read_slave_waitrequest; wire avalonmm_write_slave_waitrequest; wire clock; wire [ 35: 0] data; wire empty; wire full; wire [ 35: 0] q; wire rdreq; wire wrreq; //the_scfifo_with_controls, which is an e_instance fifo_buffer_scfifo_with_controls #( .FIFO_DEPTHS(FIFO_DEPTHS), .FIFO_WIDTHU(FIFO_WIDTHU) ) the_scfifo_with_controls ( .clock (clock), .data (data), .empty (empty), .full (full), .q (q), .rdreq (rdreq), .reset_n (reset_n), .wrreq (wrreq) ); //in, which is an e_avalon_slave //out, which is an e_avalon_slave assign data = avalonmm_write_slave_writedata; assign wrreq = avalonmm_write_slave_write; assign avalonmm_read_slave_readdata = q; assign rdreq = avalonmm_read_slave_read; assign clock = wrclock; assign avalonmm_write_slave_waitrequest = full; assign avalonmm_read_slave_waitrequest = empty; endmodule // -------------------------------------------------------------------------------- // fifo_buffer to Avalon-ST interface // -------------------------------------------------------------------------------- module fifo_to_packet ( // Interface: clk input clk, input reset_n, // Interface: ST out input out_ready, output reg out_valid, output reg [ 7: 0] out_data, output reg out_startofpacket, output reg out_endofpacket, // Interface: FIFO in input [ 35: 0] fifo_readdata, output reg fifo_read, input fifo_empty ); reg [ 1: 0] state; reg enable, sent_all; reg [ 1: 0] current_byte, byte_end; reg first_trans, last_trans; reg [ 23:0] fifo_data_buffer; localparam POP_FIFO = 2'b00, POP_FIFO_WAIT = 2'b01, FIFO_DATA_WAIT = 2'b10, READ_SEND_ISSUE = 2'b11; always @* begin enable = (!fifo_empty & sent_all); end always @(posedge clk or negedge reset_n) begin if (!reset_n) begin fifo_data_buffer <= 'b0; out_startofpacket <= 1'b0; out_endofpacket <= 1'b0; out_valid <= 1'b0; out_data <= 'b0; state <= 'b0; fifo_read <= 1'b0; current_byte <= 'b0; byte_end <= 'b0; first_trans <= 1'b0; last_trans <= 1'b0; sent_all <= 1'b1; end else begin if (out_ready) begin out_startofpacket <= 1'b0; out_endofpacket <= 1'b0; end case (state) POP_FIFO : begin if (out_ready) begin out_startofpacket <= 1'b0; out_endofpacket <= 1'b0; out_valid <= 1'b0; first_trans <= 1'b0; last_trans <= 1'b0; byte_end <= 'b0; fifo_read <= 1'b0; sent_all <= 1'b1; end // start poping fifo after all data sent and data available if (enable) begin fifo_read <= 1'b1; out_valid <= 1'b0; state <= POP_FIFO_WAIT; end end POP_FIFO_WAIT : begin //fifo latency of 1 fifo_read <= 1'b0; state <= FIFO_DATA_WAIT; end FIFO_DATA_WAIT : begin sent_all <= 1'b0; first_trans <= fifo_readdata[35]; last_trans <= fifo_readdata[34]; out_data <= fifo_readdata[7:0]; fifo_data_buffer <= fifo_readdata[31:8]; byte_end <= fifo_readdata[33:32]; current_byte <= 1'b1; out_valid <= 1'b1; // first byte sop eop handling if (fifo_readdata[35] & fifo_readdata[34] & (fifo_readdata[33:32] == 0)) begin first_trans <= 1'b0; last_trans <= 1'b0; out_startofpacket <= 1'b1; out_endofpacket <= 1'b1; state <= POP_FIFO; end else if (fifo_readdata[35] & (fifo_readdata[33:32] == 0)) begin first_trans <= 1'b0; out_startofpacket <= 1'b1; state <= POP_FIFO; end else if (fifo_readdata[35]) begin first_trans <= 1'b0; out_startofpacket <= 1'b1; state <= READ_SEND_ISSUE; end else if (fifo_readdata[34] & (fifo_readdata[33:32] == 0)) begin last_trans <= 1'b0; out_endofpacket <= 1'b1; state <= POP_FIFO; end else begin state <= READ_SEND_ISSUE; end end READ_SEND_ISSUE : begin out_valid <= 1'b1; sent_all <= 1'b0; if (out_ready) begin out_startofpacket <= 1'b0; // last byte if (last_trans & (current_byte == byte_end)) begin last_trans <= 1'b0; out_endofpacket <= 1'b1; state <= POP_FIFO; end case (current_byte) 3: begin out_data <= fifo_data_buffer[23:16]; end 2: begin out_data <= fifo_data_buffer[15:8]; end 1: begin out_data <= fifo_data_buffer[7:0]; end default: begin //out_data <= fifo_readdata[7:0]; end endcase current_byte <= current_byte + 1'b1; if (current_byte == byte_end) begin state <= POP_FIFO; end else begin state <= READ_SEND_ISSUE; end end end endcase end end endmodule // -------------------------------------------------------------------------------- //| Economy Transaction Master // -------------------------------------------------------------------------------- module packets_to_master ( // Interface: clk input clk, input reset_n, // Interface: ST in output reg in_ready, input in_valid, input [ 7: 0] in_data, input in_startofpacket, input in_endofpacket, // Interface: ST out input out_ready, output reg out_valid, output reg [ 7: 0] out_data, output reg out_startofpacket, output reg out_endofpacket, // Interface: MM out output reg [31: 0] address, input [31: 0] readdata, output reg read, output reg write, output reg [ 3: 0] byteenable, output reg [31: 0] writedata, input waitrequest, input readdatavalid ); // --------------------------------------------------------------------- //| Parameter Declarations // --------------------------------------------------------------------- parameter EXPORT_MASTER_SIGNALS = 0; // --------------------------------------------------------------------- //| Command Declarations // --------------------------------------------------------------------- localparam CMD_WRITE_NON_INCR = 8'h00; localparam CMD_WRITE_INCR = 8'h04; localparam CMD_READ_NON_INCR = 8'h10; localparam CMD_READ_INCR = 8'h14; // --------------------------------------------------------------------- //| Signal Declarations // --------------------------------------------------------------------- reg [ 3: 0] state; reg [ 7: 0] command; reg [ 1: 0] current_byte; //, result_byte; reg [ 15: 0] counter; reg [ 23: 0] read_data_buffer; reg in_ready_0; reg first_trans, last_trans; reg [ 3: 0] unshifted_byteenable; wire enable; localparam READY = 4'b0000, GET_EXTRA = 4'b0001, GET_SIZE1 = 4'b0010, GET_SIZE2 = 4'b0011, GET_ADDR1 = 4'b0100, GET_ADDR2 = 4'b0101, GET_ADDR3 = 4'b0110, GET_ADDR4 = 4'b0111, GET_WRITE_DATA = 4'b1000, WRITE_WAIT = 4'b1001, RETURN_PACKET = 4'b1010, READ_ASSERT = 4'b1011, READ_CMD_WAIT = 4'b1100, READ_DATA_WAIT = 4'b1101, READ_SEND_ISSUE= 4'b1110, READ_SEND_WAIT = 4'b1111; // --------------------------------------------------------------------- //| Thingofamagick // --------------------------------------------------------------------- assign enable = (in_ready & in_valid); always @* // in_ready = in_ready_0 & out_ready; in_ready = in_ready_0; always @(posedge clk or negedge reset_n) begin if (!reset_n) begin in_ready_0 <= 1'b0; out_startofpacket <= 1'b0; out_endofpacket <= 1'b0; out_valid <= 1'b0; out_data <= 'b0; read <= 1'b0; write <= 1'b0; byteenable <= 'b0; writedata <= 'b0; address <= 'b0; counter <= 'b0; command <= 'b0; first_trans <= 1'b0; last_trans <= 1'b0; state <= 'b0; current_byte <= 'b0; // result_byte <= 'b0; read_data_buffer <= 'b0; unshifted_byteenable <= 'b0; end else begin address[1:0] <= 'b0; if (out_ready) begin out_startofpacket <= 1'b0; out_endofpacket <= 1'b0; out_valid <= 1'b0; end in_ready_0 <= 1'b0; if (counter >= 3) unshifted_byteenable <= 4'b1111; else if (counter == 3) unshifted_byteenable <= 4'b0111; else if (counter == 2) unshifted_byteenable <= 4'b0011; else if (counter == 1) unshifted_byteenable <= 4'b0001; case (state) READY : begin out_valid <= 1'b0; in_ready_0 <= 1'b1; end GET_EXTRA : begin in_ready_0 <= 1'b1; byteenable <= 'b0; if (enable) state <= GET_SIZE1; end GET_SIZE1 : begin in_ready_0 <= 1'b1; //load counter on reads only counter[15:8] <= command[4]?in_data:8'b0; if (enable) state <= GET_SIZE2; end GET_SIZE2 : begin in_ready_0 <= 1'b1; //load counter on reads only counter[7:0] <= command[4]?in_data:8'b0; if (enable) state <= GET_ADDR1; end GET_ADDR1 : begin in_ready_0 <= 1'b1; first_trans <= 1'b1; last_trans <= 1'b0; address[31:24] <= in_data; if (enable) state <= GET_ADDR2; end GET_ADDR2 : begin in_ready_0 <= 1'b1; address[23:16] <= in_data; if (enable) state <= GET_ADDR3; end GET_ADDR3 : begin in_ready_0 <= 1'b1; address[15:8] <= in_data; if (enable) state <= GET_ADDR4; end GET_ADDR4 : begin in_ready_0 <= 1'b1; address[7:2] <= in_data[7:2]; current_byte <= in_data[1:0]; if (enable) begin if (command == CMD_WRITE_NON_INCR | command == CMD_WRITE_INCR) begin state <= GET_WRITE_DATA; //writes in_ready_0 <= 1'b1; end else if (command == CMD_READ_NON_INCR | command == CMD_READ_INCR) begin state <= READ_ASSERT; //reads in_ready_0 <= 1'b0; end else begin //nops //treat all unrecognized commands as nops as well state <= RETURN_PACKET; out_startofpacket <= 1'b1; out_data <= (8'h80 | command); out_valid <= 1'b1; current_byte <= 'h0; in_ready_0 <= 1'b0; end end end GET_WRITE_DATA : begin in_ready_0 <= 1; if (enable) begin counter <= counter + 1'b1; //2 bit, should wrap by itself current_byte <= current_byte + 1'b1; if (in_endofpacket || current_byte == 3) begin in_ready_0 <= 0; write <= 1'b1; state <= WRITE_WAIT; end end if (in_endofpacket) begin last_trans <= 1'b1; end // handle byte writes properly // drive data pins based on addresses case (current_byte) 0: begin writedata[7:0] <= in_data; byteenable[0] <= 1; end 1: begin writedata[15:8] <= in_data; byteenable[1] <= 1; end 2: begin writedata[23:16] <= in_data; byteenable[2] <= 1; end 3: begin writedata[31:24] <= in_data; byteenable[3] <= 1; end endcase end WRITE_WAIT : begin in_ready_0 <= 0; write <= 1'b1; if (~waitrequest) begin write <= 1'b0; state <= GET_WRITE_DATA; in_ready_0 <= 1; byteenable <= 'b0; if (command[2] == 1'b1) begin //increment address, but word-align it address[31:2] <= (address[31:2] + 1'b1); end if (last_trans) begin state <= RETURN_PACKET; out_startofpacket <= 1'b1; out_data <= (8'h80 | command); out_valid <= 1'b1; current_byte <= 'h0; in_ready_0 <= 1'b0; end end end RETURN_PACKET : begin out_valid <= 1'b1; if (out_ready) begin case (current_byte) // 0: begin // out_startofpacket <= 1'b1; // out_data <= (8'h80 | command); // end 0: begin out_data <= 8'b0; end 1: begin out_data <= counter[15:8]; end 2: begin out_endofpacket <= 1'b1; out_data <= counter[7:0]; end default: begin // out_data <= 8'b0; // out_startofpacket <= 1'b0; // out_endofpacket <= 1'b0; end endcase current_byte <= current_byte + 1'b1; if (current_byte == 3) begin state <= READY; out_valid <= 1'b0; end else state <= RETURN_PACKET; end end READ_ASSERT : begin if (current_byte == 3) byteenable <= unshifted_byteenable << 3; if (current_byte == 2) byteenable <= unshifted_byteenable << 2; if (current_byte == 1) byteenable <= unshifted_byteenable << 1; if (current_byte == 0) byteenable <= unshifted_byteenable; // byteenable <= unshifted_byteenable << current_byte; read <= 1; state <= READ_CMD_WAIT; end READ_CMD_WAIT : begin read_data_buffer <= readdata[31:8]; out_data <= readdata[7:0]; read <= 1; // if readdatavalid, take the data and // go directly to READ_SEND_ISSUE. This is for fixed // latency slaves. Ignore waitrequest in this case, // since this master does not issue pipelined reads. // // For variable latency slaves, once waitrequest is low // the read command is accepted, so deassert read and // go to READ_DATA_WAIT to wait for readdatavalid if (readdatavalid) begin state <= READ_SEND_ISSUE; read <= 0; end else begin if (~waitrequest) begin state <= READ_DATA_WAIT; read <= 0; end end end READ_DATA_WAIT : begin read_data_buffer <= readdata[31:8]; out_data <= readdata[7:0]; if (readdatavalid) begin state <= READ_SEND_ISSUE; end end READ_SEND_ISSUE : begin out_valid <= 1'b1; out_startofpacket <= 'h0; out_endofpacket <= 'h0; if (counter == 1) begin out_endofpacket <= 1'b1; end if (first_trans) begin first_trans <= 1'b0; out_startofpacket <= 1'b1; end case (current_byte) 3: begin out_data <= read_data_buffer[23:16]; end 2: begin out_data <= read_data_buffer[15:8]; end 1: begin out_data <= read_data_buffer[7:0]; end default: begin out_data <= out_data; end endcase state <= READ_SEND_WAIT; end READ_SEND_WAIT : begin out_valid <= 1'b1; if (out_ready) begin counter <= counter - 1'b1; current_byte <= current_byte + 1'b1; out_valid <= 1'b0; // count down on the number of bytes to read // shift current byte location within word // if increment address, add it, so the next read // can use it, if more reads are required // no more bytes to send - go to READY state if (counter == 1) begin state <= READY; // end of current word, but we have more bytes to // read - go back to READ_ASSERT end else if (current_byte == 3) begin if (command[2] == 1'b1) begin //increment address, but word-align it address[31:2] <= (address[31:2] + 1'b1); end state <= READ_ASSERT; // continue sending current word end else begin state <= READ_SEND_ISSUE; end //maybe add in_ready_0 here so we are ready to go //right away end end endcase if (enable & in_startofpacket) begin state <= GET_EXTRA; command <= in_data; in_ready_0 <= 1'b1; end end // end else end // end always block endmodule