OpenCores
URL https://opencores.org/ocsvn/xulalx25soc/xulalx25soc/trunk

Subversion Repositories xulalx25soc

[/] [xulalx25soc/] [trunk/] [rtl/] [wbuexec.v] - Diff between revs 2 and 59

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 2 Rev 59
Line 33... Line 33...
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
 
`define WB_IDLE                 3'b000
 
`define WB_READ_REQUEST         3'b001
 
`define WB_WRITE_REQUEST        3'b010
 
`define WB_ACK                  3'b011
 
`define WB_WAIT_ON_NEXT_WRITE   3'b100
 
`define WB_FLUSH_WRITE_REQUESTS 3'b101
 
 
module  wbuexec(i_clk, i_rst, i_stb, i_codword, o_busy,
module  wbuexec(i_clk, i_rst, i_stb, i_codword, o_busy,
                o_wb_cyc, o_wb_stb, o_wb_we, o_wb_addr, o_wb_data,
                o_wb_cyc, o_wb_stb, o_wb_we, o_wb_addr, o_wb_data,
                        i_wb_ack, i_wb_stall, i_wb_err, i_wb_data,
                        i_wb_ack, i_wb_stall, i_wb_err, i_wb_data,
                o_stb, o_codword);
                o_stb, o_codword);
        input                   i_clk, i_rst;
        input                   i_clk, i_rst;
        // The command inputs
        // The command inputs
        input                   i_stb;
        input                   i_stb;
        input           [35:0]   i_codword;
        input           [35:0]   i_codword;
        output  reg     o_busy;
        output  wire            o_busy;
        // Wishbone outputs
        // Wishbone outputs
        output  reg             o_wb_cyc, o_wb_stb, o_wb_we;
        output  wire            o_wb_cyc, o_wb_stb;
 
        output  reg             o_wb_we;
        output  reg     [31:0]   o_wb_addr, o_wb_data;
        output  reg     [31:0]   o_wb_addr, o_wb_data;
        // Wishbone inputs
        // Wishbone inputs
        input                   i_wb_ack, i_wb_stall, i_wb_err;
        input                   i_wb_ack, i_wb_stall, i_wb_err;
        input           [31:0]   i_wb_data;
        input           [31:0]   i_wb_data;
        // And our codeword outputs
        // And our codeword outputs
Line 63... Line 71...
        assign  w_eow    = (w_accept)&&(i_codword[35:30] == 6'h2e);
        assign  w_eow    = (w_accept)&&(i_codword[35:30] == 6'h2e);
        // assign       w_newrd  = (w_accept)&&(i_codword[35:34] == 2'b11);
        // assign       w_newrd  = (w_accept)&&(i_codword[35:34] == 2'b11);
        wire    [31:0]   w_cod_data;
        wire    [31:0]   w_cod_data;
        assign  w_cod_data={ i_codword[32:31], i_codword[29:0] };
        assign  w_cod_data={ i_codword[32:31], i_codword[29:0] };
        assign  w_new_err = ((w_accept)
        assign  w_new_err = ((w_accept)
                                &&((i_codword[35:33] != 3'h3)||(~o_wb_we))
                                &&(i_codword[35:33] != 3'h3)
                                &&(i_codword[35:30] != 6'h2e));
                                &&(i_codword[35:30] != 6'h2e));
 
 
 
        reg     [2:0]    wb_state;
        reg     [9:0]    r_acks_needed, r_len;
        reg     [9:0]    r_acks_needed, r_len;
 
        reg     r_inc, r_new_addr, last_read_request, last_ack, zero_acks;
 
 
        reg     r_inc, r_wb_err, r_new_addr, r_eow;
 
        initial r_wb_err = 1'b0;
 
        initial r_new_addr = 1'b1;
        initial r_new_addr = 1'b1;
 
        initial wb_state = `WB_IDLE;
 
        initial o_stb = 1'b0;
        always @(posedge i_clk)
        always @(posedge i_clk)
                if (i_rst)
                if (i_rst)
                begin
                begin
 
                        wb_state <= `WB_IDLE;
                        o_stb <= 1'b1;
                        o_stb <= 1'b1;
                        o_codword <= { 6'h3, 30'h000 };
                        o_codword <= { 6'h3, i_wb_data[29:0] };
                        r_wb_err <= 1'b0;
                end else case(wb_state)
                        o_wb_cyc <= 1'b0;
                `WB_IDLE: begin
                end else if (o_wb_cyc) // In the middle of a bus transaction
                        // Now output codewords while we're idle,
                begin
                        //    ... unless we get an address command (later).
                        o_stb <= 1'b0;
                        o_stb <= 1'b0;
 
 
                        // Deal with bus errors
                        // The new instruction.  The following
                        if (r_wb_err)
                        // don't matter if we're not running,
                        begin
                        // so set them any time in this state,
                                if (w_eow)
                        // and if we move then they'll still be
                                        o_wb_cyc <= 1'b0;
                        // set right.
                                o_wb_stb <= 1'b0;
 
                        end else if ((i_wb_err)||(w_new_err))
 
                        begin
 
                                o_wb_cyc <= (~o_busy);
 
                                o_wb_stb <= 1'b0;
 
                                r_wb_err <= 1'b1;
 
                                //
                                //
                                o_stb <= 1'b1;
                        // Increment addresses?
                                o_codword <= { 6'h5, 30'h0000 };
 
                                //
 
                        end else if ((o_wb_stb)&&(~i_wb_stall))
 
                        // Deal with the strobe line
 
                        begin // Strobe was accepted, busy should be '1' here
 
                                if (r_len != 0) // read
 
                                        r_len <= r_len - 10'h01;
 
                                else
 
                                        o_wb_stb <= 1'b0;
 
 
 
                                if (o_wb_we)
 
                                begin // Acknowledge a write
 
                                        o_stb <= 1'b1;
 
                                        o_codword <= { 6'h2, 30'h0000 };
 
                                end
 
 
 
                                if (r_inc)
 
                                        o_wb_addr <= o_wb_addr + 32'h001;
 
                        end else if (w_newwr) begin
 
                                r_inc <= i_codword[30];
                                r_inc <= i_codword[30];
                                o_wb_data <= w_cod_data;
                        // Will this be a write?
                                o_wb_stb <= 1'b1;
                        o_wb_we <= (~i_codword[35]);
                        /*
 
                        end else if (w_newrd)
 
                        begin // This seems good, but it would stall the bus
 
                                // BUS ERROR!
 
                                o_wb_cyc <= 1'b0;
 
                                o_stb <= 1'b1;
 
                                o_codword <= { 4'h5, 32'h0000 };
 
                        */
 
                        end
 
 
 
                        if (w_eow)
 
                                r_eow <= 1'b1;
 
 
 
                        if ((r_wb_err)||(i_wb_err)||(w_new_err))
 
                                // On an error, flush any inputs ...
 
                                o_busy <= 1'b0;
 
                        else if ((w_eow)||(w_newwr)||(r_eow))
 
                                // On a new command, we're busy again
 
                                o_busy <= 1'b1;
 
                        else if((o_wb_we)&&(o_wb_stb)&&(~i_wb_stall)&&(r_len==0))
 
                                // Once our command completes, if it was a write
 
                                // command, then 
 
                                o_busy <= 1'b0;
 
                        else if ((o_wb_we)&&(~o_wb_stb))
 
                                o_busy <= 1'b0;
 
 
 
                        //
 
                        // Now let's process the acknowledgements
 
                        //
 
                        if ((r_wb_err)||(i_wb_err))
 
                        begin
 
                                // Acks are irrelevant here
 
                        end else if (r_acks_needed != 10'h00)
 
                        begin
 
                                if ((i_wb_ack)&&(~o_wb_we))
 
                                begin // Return a read result
 
                                o_stb <= 1'b1;
 
                                o_codword <= { 3'h7, i_wb_data[31:30], r_inc,
 
                                        i_wb_data[29:0] };
 
                                end
 
 
 
                                if ((i_wb_ack)&&(~w_newwr))
 
                                        r_acks_needed <= r_acks_needed - 10'h001;
 
                                else if ((~i_wb_ack)&&(w_newwr))
 
                                        r_acks_needed <= r_acks_needed + 10'h001;
 
                        end else if (r_acks_needed == 10'h0)
 
                        begin
 
                                if ((~o_wb_we)||(r_eow)||(w_eow)) // End our bus cycle
 
                                        o_wb_cyc <= 1'b0;
 
                                else if (w_newwr)
 
                                begin
 
                                        r_acks_needed <= r_acks_needed + 10'h001;
 
                                        o_wb_data <= w_cod_data;
 
                                end
 
                        end
 
                //
 
                //
 
                //
 
                //
 
                //
 
                end else if (i_stb)
 
                //
                //
 
                        // Our next codeword will be the new address (if there
 
                        // is one).  Set it here.  The o_stb line will determine
 
                        // if this codeword is actually sent out.
                //
                //
 
                        o_codword <= { 4'h2, o_wb_addr };
 
                        o_wb_we <= (i_codword[35:34] != 2'b11);
                //
                //
 
                        // The output data is a don't care, unless we are
 
                        // starting a write.  Hence, let's always set it as
 
                        // though we were about to start a write.
                //
                //
 
                        o_wb_data <= w_cod_data;
                //
                //
 
                        if (i_stb)
                begin
                begin
                        // Default is not to send any codewords
                        // Default is not to send any codewords
                        o_stb    <= 1'b0;
 
                        // Increment addresses?
 
                        r_inc <= i_codword[30];
 
                        // Will this be a write?
 
                        o_wb_we <= (~i_codword[35]);
 
                        // Do we need to broadcast a new address?
                        // Do we need to broadcast a new address?
                        // r_new_addr <= 1'b0;
                        // r_new_addr <= 1'b0;
                        // Errors are all clear by now
                                // 
                        r_wb_err <= 1'b0;
                                casez(i_codword[35:32])
                        // Need to be not-busy when o_wb_cyc is low
                                4'b0000: begin // Set a new (arbitrary) address
                        o_busy   <= 1'b0;
 
                        // 
 
                        r_eow <= 1'b0;
 
                        if (i_codword[35:32] == 4'h0)
 
                        begin // Set a new address
 
                                r_new_addr <= 1'b1;
                                r_new_addr <= 1'b1;
                                o_wb_addr <= i_codword[31:0];
                                o_wb_addr <= i_codword[31:0];
                        end else if (i_codword[35:33] == 3'b001)
                                        end
                        begin // Set a new relative address
                                4'b001?: begin // Set a new relative address
 
                                        r_new_addr <= 1'b1;
                                o_wb_addr <= o_wb_addr
                                o_wb_addr <= o_wb_addr
                                        + { i_codword[32:31], i_codword[29:0] };
                                        + { i_codword[32:31], i_codword[29:0] };
 
                                        end
 
                                4'b01??: begin // Start a write transaction,
 
                                        // address is alrdy set
                                r_new_addr <= 1'b1;
                                r_new_addr <= 1'b1;
                        end else if (i_codword[35:34] == 2'b11)
                                        wb_state <= `WB_WRITE_REQUEST;
                        begin // Start a vector read
                                        end
 
                                4'b11??: begin // Start a vector read
                                // Address is already set ...
                                // Address is already set ...
                                // This also depends upon the decoder working
                                // This also depends upon the decoder working
                                r_len <= i_codword[9:0] - 10'h01;
 
                                o_wb_cyc <= 1'b1;
 
                                o_wb_stb <= 1'b1;
 
                                r_acks_needed <= i_codword[9:0];
 
                                o_busy   <= 1'b1;
 
 
 
                                if (r_new_addr)
                                if (r_new_addr)
                                begin
 
                                        o_stb <= 1'b1;
                                        o_stb <= 1'b1;
                                        o_codword <= { 4'h2, o_wb_addr };
                                        wb_state <= `WB_READ_REQUEST;
 
                                        end
 
                                default:
 
                                        ;
 
                                endcase
 
                        end end
 
                `WB_READ_REQUEST: begin
                                        r_new_addr <= 1'b0;
                                        r_new_addr <= 1'b0;
 
 
 
                        if (i_wb_err)
 
                                wb_state <= `WB_IDLE;
 
 
 
                        o_stb <= (i_wb_err)||(i_wb_ack);
 
 
 
                        if (i_wb_err)
 
                                o_codword <= { 6'h5, i_wb_data[29:0] };
 
                        else
 
                                o_codword <= { 3'h7, i_wb_data[31:30], r_inc,
 
                                        i_wb_data[29:0] };
 
 
 
                        if ((r_inc)&&(~i_wb_stall))
 
                                o_wb_addr <= o_wb_addr + 32'h001;
 
 
 
 
 
                        if (~i_wb_stall) // Deal with the strobe line
 
                        begin // Strobe was accepted, busy should be '1' here
 
                                if (last_read_request) // (r_len != 0) // read
 
                                        wb_state <= `WB_ACK;
 
                        end end
 
                `WB_WRITE_REQUEST: begin
 
                        r_new_addr <= 1'b0;
 
 
 
                        if (i_wb_err)
 
                                o_codword <= { 6'h5, i_wb_data[29:0] };
 
                        else
 
                                o_codword <= { 6'h2, i_wb_data[29:0] };
 
 
 
                        if ((r_inc)&&(~i_wb_stall))
 
                                o_wb_addr <= o_wb_addr + 32'h001;
 
 
 
                        o_stb <= (i_wb_err)||(~i_wb_stall);
 
 
 
                        // Don't need to worry about accepting anything new
 
                        // here, since we'll always be busy while in this state.
 
                        // Hence, we cannot accept new write requests.
 
                        //
 
 
 
                        if (i_wb_err)
 
                        begin
 
                                wb_state <= `WB_FLUSH_WRITE_REQUESTS;
 
                                //
 
                        end else if (~i_wb_stall)
 
                                wb_state <= `WB_WAIT_ON_NEXT_WRITE;
 
                        end
 
                `WB_ACK: begin
 
                        r_new_addr <= 1'b0;
 
                        //
 
                        // No strobes are being sent out.  No further
 
                        // bus transactions are requested.  We only need
 
                        // to finish processing the last one(s) by waiting
 
                        // for (and recording?) their acks.
 
                        //
 
                        // Process acknowledgements
 
                        if (i_wb_err)
 
                                o_codword <= { 6'h5, i_wb_data[29:0] };
 
                        else
 
                                o_codword <= { 3'h7, i_wb_data[31:30], r_inc,
 
                                        i_wb_data[29:0] };
 
 
 
                        // Return a read result, or (possibly) an error
 
                        // notification
 
                        o_stb <= (((i_wb_ack)&&(~o_wb_we)) || (i_wb_err));
 
 
 
                        if (((last_ack)&&(i_wb_ack))||(zero_acks)||(i_wb_err))
 
                                wb_state <= `WB_IDLE;
                                end
                                end
                        end else if (~i_codword[35])
                `WB_WAIT_ON_NEXT_WRITE: begin
                        begin // Start a write transaction, address is alrdy set
                        r_new_addr <= 1'b0;
                                o_wb_cyc <= 1'b1;
 
                                o_wb_stb <= 1'b1;
                        o_codword <= { 6'h5, i_wb_data[29:0] };
 
                        o_stb <= (i_wb_err)||(w_new_err);
 
 
                                o_wb_data <= w_cod_data;
                                o_wb_data <= w_cod_data;
                                o_busy   <= 1'b1;
 
                                r_len <= 10'h00;
                        if (w_new_err) // Something other than a write or EOW
                                r_new_addr <= 1'b1;
                                wb_state <= `WB_IDLE;
                                r_acks_needed <= 10'h01;
                        else if (i_wb_err) // Bus returns an error
 
                                wb_state <= `WB_FLUSH_WRITE_REQUESTS;
 
                        else if (w_newwr) // Need to make a new write request
 
                                wb_state <= `WB_WRITE_REQUEST;
 
                        else if (w_eow) // All done writing, wait for last ack
 
                                wb_state <= `WB_ACK;
                        end
                        end
                end else begin
                `WB_FLUSH_WRITE_REQUESTS: begin
                        r_wb_err <= 1'b0;
                        // We come in here after an error within a write
                        o_busy   <= 1'b0;
                        // We need to wait until the command cycle finishes
                        o_stb    <= 1'b0;
                        // issuing all its write commands before we can go back
 
                        // to idle.
 
                        //
 
                        // In the off chance that we are in here in error, or
 
                        // out of sync, we'll transition to WB_IDLE and just
 
                        // issue a second error token.
 
                        r_new_addr <= 1'b0;
 
 
 
                        o_codword <= { 6'h5, i_wb_data[29:0] };
 
                        o_stb <= (w_new_err);
 
 
 
                        if ((w_eow)||(w_new_err))
 
                                wb_state <= `WB_IDLE;
 
                        end
 
                default: begin
 
                        o_stb <= 1'b1;
 
                        o_codword <= { 6'h3, i_wb_data[29:0] };
 
                        wb_state <= `WB_IDLE;
                end
                end
 
                endcase
 
 
 
        assign o_busy = (wb_state != `WB_IDLE)
 
                        &&(wb_state != `WB_WAIT_ON_NEXT_WRITE)
 
                        &&(wb_state != `WB_FLUSH_WRITE_REQUESTS);
 
        assign o_wb_cyc = (wb_state == `WB_READ_REQUEST)
 
                        ||(wb_state == `WB_WRITE_REQUEST)
 
                        ||(wb_state == `WB_ACK)
 
                        ||(wb_state == `WB_WAIT_ON_NEXT_WRITE);
 
        assign o_wb_stb = (wb_state == `WB_READ_REQUEST)
 
                                ||(wb_state == `WB_WRITE_REQUEST);
 
 
 
        always @(posedge i_clk)
 
                if (wb_state == `WB_IDLE)
 
                        r_acks_needed <= 10'h00; // (i_codword[35])?i_codword[9:0]:10'h00;
 
                else if ((o_wb_stb)&&(~i_wb_stall)&&(~i_wb_ack))
 
                        r_acks_needed <= r_acks_needed + 10'h01;
 
                else if (((~o_wb_stb)||(i_wb_stall))&&(i_wb_ack))
 
                        r_acks_needed <= r_acks_needed - 10'h01;
 
 
 
        always @(posedge i_clk)
 
                last_ack <= (~o_wb_stb)&&(r_acks_needed == 10'h01);
 
 
 
        always @(posedge i_clk)
 
                zero_acks <= (~o_wb_stb)&&(r_acks_needed == 10'h00);
 
 
 
        always @(posedge i_clk)
 
                if ((wb_state == `WB_IDLE)&&(i_codword[35:34] == 2'b11))
 
                        r_len <= i_codword[9:0] - 10'h01;
 
                else if ((o_wb_stb)&&(~i_wb_stall)&&(|r_len))
 
                        r_len <= r_len - 10'h01;
 
 
 
        always @(posedge i_clk)
 
                last_read_request <= (r_len[9:0] == 10'h000);
 
 
endmodule
endmodule
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.