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

Subversion Repositories xulalx25soc

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /xulalx25soc/trunk/rtl
    from Rev 58 to Rev 59
    Reverse comparison

Rev 58 → Rev 59

/wbufifo.v
5,7 → 5,7
// Project: XuLA2 board
//
// Purpose: This was once a FIFO for a UART ... but now it works as a
// synchronous FIFO for JTAG-wishbone conversion 36-bit codewords.
// synchronous FIFO for JTAG-wishbone conversion 36-bit codewords.
//
//
// Creator: Dan Gisselquist, Ph.D.
45,6 → 45,18
reg [(BW-1):0] fifo[0:(FLEN-1)];
reg [(LGFLEN-1):0] r_first, r_last;
 
reg will_overflow;
initial will_overflow = 1'b0;
always @(posedge i_clk)
if (i_rst)
will_overflow <= 1'b0;
else if (i_rd)
will_overflow <= (will_overflow)&&(i_wr);
else if (i_wr)
will_overflow <= (r_first+2 == r_last);
else if (r_first+1 == r_last)
will_overflow <= 1'b1;
 
// Write
initial r_first = 0;
always @(posedge i_clk)
52,7 → 64,7
r_first <= { (LGFLEN){1'b0} };
else if (i_wr)
begin // Cowardly refuse to overflow
if (r_first+1 != r_last)
if ((i_rd)||(~will_overflow)) // (r_first+1 != r_last)
r_first <= r_first+{{(LGFLEN-1){1'b0}},1'b1};
// else o_ovfl <= 1'b1;
end
60,7 → 72,6
if (i_wr) // Write our new value regardless--on overflow or not
fifo[r_first] <= i_data;
 
initial r_last = 0;
// Reads
// Following a read, the next sample will be available on the
// next clock
73,12 → 84,25
// 5 1 2 fifo[2]
// 6 0 3 fifo[3]
// 7 0 3 fifo[3]
reg will_underflow;
initial will_underflow = 1'b0;
always @(posedge i_clk)
if (i_rst)
will_underflow <= 1'b0;
else if (i_wr)
will_underflow <= (will_underflow)&&(i_rd);
else if (i_rd)
will_underflow <= (r_last+1==r_first);
else
will_underflow <= (r_last == r_first);
 
initial r_last = 0;
always @(posedge i_clk)
if (i_rst)
r_last <= { (LGFLEN){1'b0} };
else if (i_rd)
begin
if (r_first != r_last)
if ((i_wr)||(~will_underflow)) // (r_first != r_last)
r_last <= r_last+{{(LGFLEN-1){1'b0}},1'b1};
// Last chases first
// Need to be prepared for a possible two
92,8 → 116,8
 
wire [(LGFLEN-1):0] nxt_first;
assign nxt_first = r_first+{{(LGFLEN-1){1'b0}},1'b1};
assign o_err = ((i_wr)&&(nxt_first == r_last))
||((i_rd)&&(r_first == r_last));
assign o_err = ((i_wr)&&(will_overflow)&&(~i_rd))
||((i_rd)&&(will_underflow)&&(~i_wr));
 
// wire [(LGFLEN-1):0] fill;
// assign fill = (r_first-r_last);
/wbuexec.v
35,6 → 35,13
////////////////////////////////////////////////////////////////////////////////
//
//
`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,
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,
43,9 → 50,10
// The command inputs
input i_stb;
input [35:0] i_codword;
output reg o_busy;
output wire o_busy;
// 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;
// Wishbone inputs
input i_wb_ack, i_wb_stall, i_wb_err;
65,180 → 73,226
wire [31:0] w_cod_data;
assign w_cod_data={ i_codword[32:31], i_codword[29:0] };
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));
 
reg [2:0] wb_state;
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 wb_state = `WB_IDLE;
initial o_stb = 1'b0;
always @(posedge i_clk)
if (i_rst)
begin
wb_state <= `WB_IDLE;
o_stb <= 1'b1;
o_codword <= { 6'h3, 30'h000 };
r_wb_err <= 1'b0;
o_wb_cyc <= 1'b0;
end else if (o_wb_cyc) // In the middle of a bus transaction
begin
o_stb <= 1'b0;
o_codword <= { 6'h3, i_wb_data[29:0] };
end else case(wb_state)
`WB_IDLE: begin
// Now output codewords while we're idle,
// ... unless we get an address command (later).
o_stb <= 1'b0;
 
// Deal with bus errors
if (r_wb_err)
// The new instruction. The following
// don't matter if we're not running,
// so set them any time in this state,
// and if we move then they'll still be
// set right.
//
// Increment addresses?
r_inc <= i_codword[30];
// Will this be a write?
o_wb_we <= (~i_codword[35]);
//
// 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
if (w_eow)
o_wb_cyc <= 1'b0;
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;
o_codword <= { 6'h5, 30'h0000 };
//
end else if ((o_wb_stb)&&(~i_wb_stall))
// Deal with the strobe line
// Default is not to send any codewords
// Do we need to broadcast a new address?
// r_new_addr <= 1'b0;
//
casez(i_codword[35:32])
4'b0000: begin // Set a new (arbitrary) address
r_new_addr <= 1'b1;
o_wb_addr <= i_codword[31:0];
end
4'b001?: begin // Set a new relative address
r_new_addr <= 1'b1;
o_wb_addr <= o_wb_addr
+ { 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;
wb_state <= `WB_WRITE_REQUEST;
end
4'b11??: begin // Start a vector read
// Address is already set ...
// This also depends upon the decoder working
if (r_new_addr)
o_stb <= 1'b1;
wb_state <= `WB_READ_REQUEST;
end
default:
;
endcase
end end
`WB_READ_REQUEST: begin
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 (r_len != 0) // read
r_len <= r_len - 10'h01;
else
o_wb_stb <= 1'b0;
if (last_read_request) // (r_len != 0) // read
wb_state <= `WB_ACK;
end end
`WB_WRITE_REQUEST: begin
r_new_addr <= 1'b0;
 
if (o_wb_we)
begin // Acknowledge a write
o_stb <= 1'b1;
o_codword <= { 6'h2, 30'h0000 };
end
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)
o_wb_addr <= o_wb_addr + 32'h001;
end else if (w_newwr) begin
r_inc <= i_codword[30];
o_wb_data <= w_cod_data;
o_wb_stb <= 1'b1;
/*
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 ((r_inc)&&(~i_wb_stall))
o_wb_addr <= o_wb_addr + 32'h001;
 
if (w_eow)
r_eow <= 1'b1;
o_stb <= (i_wb_err)||(~i_wb_stall);
 
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;
// 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;
//
// Now let's process the acknowledgements
// 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.
//
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,
// 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] };
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
// 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 else if (i_stb)
//
//
//
//
//
begin
// 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?
// r_new_addr <= 1'b0;
// Errors are all clear by now
r_wb_err <= 1'b0;
// Need to be not-busy when o_wb_cyc is low
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;
o_wb_addr <= i_codword[31:0];
end else if (i_codword[35:33] == 3'b001)
begin // Set a new relative address
o_wb_addr <= o_wb_addr
+ { i_codword[32:31], i_codword[29:0] };
r_new_addr <= 1'b1;
end else if (i_codword[35:34] == 2'b11)
begin // Start a vector read
// Address is already set ...
// 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;
`WB_WAIT_ON_NEXT_WRITE: begin
r_new_addr <= 1'b0;
 
if (r_new_addr)
begin
o_stb <= 1'b1;
o_codword <= { 4'h2, o_wb_addr };
r_new_addr <= 1'b0;
end
end else if (~i_codword[35])
begin // Start a write transaction, address is alrdy set
o_wb_cyc <= 1'b1;
o_wb_stb <= 1'b1;
o_wb_data <= w_cod_data;
o_busy <= 1'b1;
r_len <= 10'h00;
r_new_addr <= 1'b1;
r_acks_needed <= 10'h01;
o_codword <= { 6'h5, i_wb_data[29:0] };
o_stb <= (i_wb_err)||(w_new_err);
 
o_wb_data <= w_cod_data;
 
if (w_new_err) // Something other than a write or EOW
wb_state <= `WB_IDLE;
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 else begin
r_wb_err <= 1'b0;
o_busy <= 1'b0;
o_stb <= 1'b0;
end
`WB_FLUSH_WRITE_REQUESTS: begin
// We come in here after an error within a write
// We need to wait until the command cycle finishes
// 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
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

powered by: WebSVN 2.1.0

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