Commit ed3c435f authored by Jens Korinth's avatar Jens Korinth
Browse files

Add IP for BlueDMA

parent 55e97aec
This diff is collapsed.
// Copyright (c) 2000-2012 Bluespec, Inc.
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// $Revision: 29755 $
// $Date: 2012-10-22 13:58:12 +0000 (Mon, 22 Oct 2012) $
`ifdef BSV_ASSIGNMENT_DELAY
`else
`define BSV_ASSIGNMENT_DELAY
`endif
`ifdef BSV_POSITIVE_RESET
`define BSV_RESET_VALUE 1'b1
`define BSV_RESET_EDGE posedge
`else
`define BSV_RESET_VALUE 1'b0
`define BSV_RESET_EDGE negedge
`endif
`ifdef BSV_ASYNC_RESET
`define BSV_ARESET_EDGE_META or `BSV_RESET_EDGE RST
`else
`define BSV_ARESET_EDGE_META
`endif
`ifdef BSV_RESET_FIFO_HEAD
`define BSV_ARESET_EDGE_HEAD `BSV_ARESET_EDGE_META
`else
`define BSV_ARESET_EDGE_HEAD
`endif
// Depth 1 FIFO
module FIFO1(CLK,
RST,
D_IN,
ENQ,
FULL_N,
D_OUT,
DEQ,
EMPTY_N,
CLR
);
parameter width = 1;
parameter guarded = 1;
input CLK;
input RST;
input [width - 1 : 0] D_IN;
input ENQ;
input DEQ;
input CLR ;
output FULL_N;
output [width - 1 : 0] D_OUT;
output EMPTY_N;
reg [width - 1 : 0] D_OUT;
reg empty_reg ;
assign EMPTY_N = empty_reg ;
`ifdef BSV_NO_INITIAL_BLOCKS
`else // not BSV_NO_INITIAL_BLOCKS
// synopsys translate_off
initial
begin
D_OUT = {((width + 1)/2) {2'b10}} ;
empty_reg = 1'b0 ;
end // initial begin
// synopsys translate_on
`endif // BSV_NO_INITIAL_BLOCKS
assign FULL_N = !empty_reg;
always@(posedge CLK `BSV_ARESET_EDGE_META)
begin
if (RST == `BSV_RESET_VALUE)
begin
empty_reg <= `BSV_ASSIGNMENT_DELAY 1'b0;
end // if (RST == `BSV_RESET_VALUE)
else
begin
if (CLR)
begin
empty_reg <= `BSV_ASSIGNMENT_DELAY 1'b0;
end // if (CLR)
else if (ENQ)
begin
empty_reg <= `BSV_ASSIGNMENT_DELAY 1'b1;
end // if (ENQ)
else if (DEQ)
begin
empty_reg <= `BSV_ASSIGNMENT_DELAY 1'b0;
end // if (DEQ)
end // else: !if(RST == `BSV_RESET_VALUE)
end // always@ (posedge CLK or `BSV_RESET_EDGE RST)
always@(posedge CLK `BSV_ARESET_EDGE_HEAD)
begin
`ifdef BSV_RESET_FIFO_HEAD
if (RST == `BSV_RESET_VALUE)
begin
D_OUT <= `BSV_ASSIGNMENT_DELAY {width {1'b0}} ;
end
else
`endif
begin
if (ENQ)
D_OUT <= `BSV_ASSIGNMENT_DELAY D_IN;
end // else: !if(RST == `BSV_RESET_VALUE)
end // always@ (posedge CLK or `BSV_RESET_EDGE RST)
// synopsys translate_off
always@(posedge CLK)
begin: error_checks
reg deqerror, enqerror ;
deqerror = 0;
enqerror = 0;
if (RST == ! `BSV_RESET_VALUE)
begin
if ( ! empty_reg && DEQ )
begin
deqerror = 1 ;
$display( "Warning: FIFO1: %m -- Dequeuing from empty fifo" ) ;
end
if ( ! FULL_N && ENQ && (!DEQ || guarded) )
begin
enqerror = 1 ;
$display( "Warning: FIFO1: %m -- Enqueuing to a full fifo" ) ;
end
end // if (RST == ! `BSV_RESET_VALUE)
end
// synopsys translate_on
endmodule
// Copyright (c) 2000-2012 Bluespec, Inc.
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// $Revision: 29755 $
// $Date: 2012-10-22 13:58:12 +0000 (Mon, 22 Oct 2012) $
`ifdef BSV_ASSIGNMENT_DELAY
`else
`define BSV_ASSIGNMENT_DELAY
`endif
`ifdef BSV_POSITIVE_RESET
`define BSV_RESET_VALUE 1'b1
`define BSV_RESET_EDGE posedge
`else
`define BSV_RESET_VALUE 1'b0
`define BSV_RESET_EDGE negedge
`endif
`ifdef BSV_ASYNC_RESET
`define BSV_ARESET_EDGE_META or `BSV_RESET_EDGE RST
`else
`define BSV_ARESET_EDGE_META
`endif
`ifdef BSV_RESET_FIFO_HEAD
`define BSV_ARESET_EDGE_HEAD `BSV_ARESET_EDGE_META
`else
`define BSV_ARESET_EDGE_HEAD
`endif
// Depth 2 FIFO
module FIFO2(CLK,
RST,
D_IN,
ENQ,
FULL_N,
D_OUT,
DEQ,
EMPTY_N,
CLR);
parameter width = 1;
parameter guarded = 1;
input CLK ;
input RST ;
input [width - 1 : 0] D_IN;
input ENQ;
input DEQ;
input CLR ;
output FULL_N;
output EMPTY_N;
output [width - 1 : 0] D_OUT;
reg full_reg;
reg empty_reg;
reg [width - 1 : 0] data0_reg;
reg [width - 1 : 0] data1_reg;
assign FULL_N = full_reg ;
assign EMPTY_N = empty_reg ;
assign D_OUT = data0_reg ;
// Optimize the loading logic since state encoding is not power of 2!
wire d0di = (ENQ && ! empty_reg ) || ( ENQ && DEQ && full_reg ) ;
wire d0d1 = DEQ && ! full_reg ;
wire d0h = ((! DEQ) && (! ENQ )) || (!DEQ && empty_reg ) || ( ! ENQ &&full_reg) ;
wire d1di = ENQ & empty_reg ;
`ifdef BSV_NO_INITIAL_BLOCKS
`else // not BSV_NO_INITIAL_BLOCKS
// synopsys translate_off
initial
begin
data0_reg = {((width + 1)/2) {2'b10}} ;
data1_reg = {((width + 1)/2) {2'b10}} ;
empty_reg = 1'b0;
full_reg = 1'b1;
end // initial begin
// synopsys translate_on
`endif // BSV_NO_INITIAL_BLOCKS
always@(posedge CLK `BSV_ARESET_EDGE_META)
begin
if (RST == `BSV_RESET_VALUE)
begin
empty_reg <= `BSV_ASSIGNMENT_DELAY 1'b0;
full_reg <= `BSV_ASSIGNMENT_DELAY 1'b1;
end // if (RST == `BSV_RESET_VALUE)
else
begin
if (CLR)
begin
empty_reg <= `BSV_ASSIGNMENT_DELAY 1'b0;
full_reg <= `BSV_ASSIGNMENT_DELAY 1'b1;
end // if (CLR)
else if ( ENQ && ! DEQ ) // just enq
begin
empty_reg <= `BSV_ASSIGNMENT_DELAY 1'b1;
full_reg <= `BSV_ASSIGNMENT_DELAY ! empty_reg ;
end
else if ( DEQ && ! ENQ )
begin
full_reg <= `BSV_ASSIGNMENT_DELAY 1'b1;
empty_reg <= `BSV_ASSIGNMENT_DELAY ! full_reg;
end // if ( DEQ && ! ENQ )
end // else: !if(RST == `BSV_RESET_VALUE)
end // always@ (posedge CLK or `BSV_RESET_EDGE RST)
always@(posedge CLK `BSV_ARESET_EDGE_HEAD)
begin
`ifdef BSV_RESET_FIFO_HEAD
if (RST == `BSV_RESET_VALUE)
begin
data0_reg <= `BSV_ASSIGNMENT_DELAY {width {1'b0}} ;
data1_reg <= `BSV_ASSIGNMENT_DELAY {width {1'b0}} ;
end
else
`endif
begin
data0_reg <= `BSV_ASSIGNMENT_DELAY
{width{d0di}} & D_IN | {width{d0d1}} & data1_reg | {width{d0h}} & data0_reg ;
data1_reg <= `BSV_ASSIGNMENT_DELAY
d1di ? D_IN : data1_reg ;
end // else: !if(RST == `BSV_RESET_VALUE)
end // always@ (posedge CLK or `BSV_RESET_EDGE RST)
// synopsys translate_off
always@(posedge CLK)
begin: error_checks
reg deqerror, enqerror ;
deqerror = 0;
enqerror = 0;
if (RST == ! `BSV_RESET_VALUE)
begin
if ( ! empty_reg && DEQ )
begin
deqerror = 1;
$display( "Warning: FIFO2: %m -- Dequeuing from empty fifo" ) ;
end
if ( ! full_reg && ENQ && (!DEQ || guarded) )
begin
enqerror = 1;
$display( "Warning: FIFO2: %m -- Enqueuing to a full fifo" ) ;
end
end
end // always@ (posedge CLK)
// synopsys translate_on
endmodule
// Copyright (c) 2000-2012 Bluespec, Inc.
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// $Revision$
// $Date$
`ifdef BSV_ASSIGNMENT_DELAY
`else
`define BSV_ASSIGNMENT_DELAY
`endif
`ifdef BSV_POSITIVE_RESET
`define BSV_RESET_VALUE 1'b1
`define BSV_RESET_EDGE posedge
`else
`define BSV_RESET_VALUE 1'b0
`define BSV_RESET_EDGE negedge
`endif
`ifdef BSV_ASYNC_RESET
`define BSV_ARESET_EDGE_META or `BSV_RESET_EDGE RST
`else
`define BSV_ARESET_EDGE_META
`endif
`ifdef BSV_RESET_FIFO_HEAD
`define BSV_ARESET_EDGE_HEAD `BSV_ARESET_EDGE_META
`else
`define BSV_ARESET_EDGE_HEAD
`endif
`ifdef BSV_RESET_FIFO_ARRAY
`define BSV_ARESET_EDGE_ARRAY `BSV_ARESET_EDGE_META
`else
`define BSV_ARESET_EDGE_ARRAY
`endif
// Sized fifo. Model has output register which improves timing
module SizedFIFO(CLK, RST, D_IN, ENQ, FULL_N, D_OUT, DEQ, EMPTY_N, CLR);
parameter p1width = 1; // data width
parameter p2depth = 3;
parameter p3cntr_width = 1; // log(p2depth-1)
// The -1 is allowed since this model has a fast output register
parameter guarded = 1;
localparam p2depth2 = (p2depth >= 2) ? (p2depth -2) : 0 ;
input CLK;
input RST;
input CLR;
input [p1width - 1 : 0] D_IN;
input ENQ;
input DEQ;
output FULL_N;
output EMPTY_N;
output [p1width - 1 : 0] D_OUT;
reg not_ring_full;
reg ring_empty;
reg [p3cntr_width-1 : 0] head;
wire [p3cntr_width-1 : 0] next_head;
reg [p3cntr_width-1 : 0] tail;
wire [p3cntr_width-1 : 0] next_tail;
// if the depth is too small, don't create an ill-sized array;
// instead, make a 1-sized array and let the initial block report an error
(* RAM_STYLE = "DISTRIBUTED" *)
reg [p1width - 1 : 0] arr[0: p2depth2];
reg [p1width - 1 : 0] D_OUT;
reg hasodata;
wire [p3cntr_width-1:0] depthLess2 = p2depth2[p3cntr_width-1:0] ;
wire [p3cntr_width-1 : 0] incr_tail;
wire [p3cntr_width-1 : 0] incr_head;
assign incr_tail = tail + 1'b1 ;
assign incr_head = head + 1'b1 ;
assign next_head = (head == depthLess2 ) ? {p3cntr_width{1'b0}} : incr_head ;
assign next_tail = (tail == depthLess2 ) ? {p3cntr_width{1'b0}} : incr_tail ;
assign EMPTY_N = hasodata;
assign FULL_N = not_ring_full;
`ifdef BSV_NO_INITIAL_BLOCKS
`else // not BSV_NO_INITIAL_BLOCKS
// synopsys translate_off
initial
begin : initial_block
integer i;
D_OUT = {((p1width + 1)/2){2'b10}} ;
ring_empty = 1'b1;
not_ring_full = 1'b1;
hasodata = 1'b0;
head = {p3cntr_width {1'b0}} ;
tail = {p3cntr_width {1'b0}} ;
for (i = 0; i <= p2depth2; i = i + 1)
begin
arr[i] = D_OUT ;
end
end
// synopsys translate_on
`endif // BSV_NO_INITIAL_BLOCKS
always @(posedge CLK `BSV_ARESET_EDGE_META)
begin
if (RST == `BSV_RESET_VALUE)
begin
head <= `BSV_ASSIGNMENT_DELAY {p3cntr_width {1'b0}} ;
tail <= `BSV_ASSIGNMENT_DELAY {p3cntr_width {1'b0}} ;
ring_empty <= `BSV_ASSIGNMENT_DELAY 1'b1;
not_ring_full <= `BSV_ASSIGNMENT_DELAY 1'b1;
hasodata <= `BSV_ASSIGNMENT_DELAY 1'b0;
end // if (RST == `BSV_RESET_VALUE)
else
begin
casez ({CLR, DEQ, ENQ, hasodata, ring_empty})
// Clear operation
5'b1????: begin
head <= `BSV_ASSIGNMENT_DELAY {p3cntr_width {1'b0}} ;
tail <= `BSV_ASSIGNMENT_DELAY {p3cntr_width {1'b0}} ;
ring_empty <= `BSV_ASSIGNMENT_DELAY 1'b1;
not_ring_full <= `BSV_ASSIGNMENT_DELAY 1'b1;
hasodata <= `BSV_ASSIGNMENT_DELAY 1'b0;
end
// -----------------------
// DEQ && ENQ case -- change head and tail if added to ring
5'b011?0: begin
tail <= `BSV_ASSIGNMENT_DELAY next_tail;
head <= `BSV_ASSIGNMENT_DELAY next_head;
end
// -----------------------
// DEQ only and NO data is in ring
5'b010?1: begin
hasodata <= `BSV_ASSIGNMENT_DELAY 1'b0;
end
// DEQ only and data is in ring (move the head pointer)
5'b010?0: begin
head <= `BSV_ASSIGNMENT_DELAY next_head;
not_ring_full <= `BSV_ASSIGNMENT_DELAY 1'b1;
ring_empty <= `BSV_ASSIGNMENT_DELAY next_head == tail ;
end
// -----------------------
// ENQ only when empty
5'b0010?: begin
hasodata <= `BSV_ASSIGNMENT_DELAY 1'b1;
end
// ENQ only when not empty
5'b0011?: begin
if ( not_ring_full ) // Drop this test to save redundant test
// but be warnned that with test fifo overflow causes loss of new data
// while without test fifo drops all but head entry! (pointer overflow)
begin
tail <= `BSV_ASSIGNMENT_DELAY next_tail;
ring_empty <= `BSV_ASSIGNMENT_DELAY 1'b0;
not_ring_full <= `BSV_ASSIGNMENT_DELAY ! (next_tail == head) ;
end
end
endcase
end // else: !if(RST == `BSV_RESET_VALUE)
end // always @ (posedge CLK)
// Update the fast data out register
always @(posedge CLK `BSV_ARESET_EDGE_HEAD)
begin
`ifdef BSV_RESET_FIFO_HEAD
if (RST == `BSV_RESET_VALUE)
begin
D_OUT <= `BSV_ASSIGNMENT_DELAY {p1width {1'b0}} ;
end // if (RST == `BSV_RESET_VALUE)
else
`endif
begin
casez ({CLR, DEQ, ENQ, hasodata, ring_empty})
// DEQ && ENQ cases
5'b011?0: begin D_OUT <= `BSV_ASSIGNMENT_DELAY arr[head]; end
5'b011?1: begin D_OUT <= `BSV_ASSIGNMENT_DELAY D_IN; end
// DEQ only and data is in ring
5'b010?0: begin D_OUT <= `BSV_ASSIGNMENT_DELAY arr[head]; end
// ENQ only when empty
5'b0010?: begin D_OUT <= `BSV_ASSIGNMENT_DELAY D_IN; end
endcase
end // else: !if(RST == `BSV_RESET_VALUE)
end // always @ (posedge CLK)
// Update the memory array reset is OFF
always @(posedge CLK `BSV_ARESET_EDGE_ARRAY)
begin: array
`ifdef BSV_RESET_FIFO_ARRAY
if (RST == `BSV_RESET_VALUE)
begin: rst_array
integer i;
for (i = 0; i <= p2depth2 && p2depth > 2; i = i + 1)
begin
arr[i] <= `BSV_ASSIGNMENT_DELAY {p1width {1'b0}} ;
end
end // if (RST == `BSV_RESET_VALUE)
else
`endif
begin
if (!CLR && ENQ && ((DEQ && !ring_empty) || (!DEQ && hasodata && not_ring_full)))
begin
arr[tail] <= `BSV_ASSIGNMENT_DELAY D_IN;
end
end // else: !if(RST == `BSV_RESET_VALUE)
end // always @ (posedge CLK)
// synopsys translate_off
always@(posedge CLK)
begin: error_checks
reg deqerror, enqerror ;
deqerror = 0;
enqerror = 0;
if (RST == ! `BSV_RESET_VALUE)
begin
if ( ! EMPTY_N && DEQ )
begin
deqerror = 1 ;
$display( "Warning: SizedFIFO: %m -- Dequeuing from empty fifo" ) ;
end
if ( ! FULL_N && ENQ && (!DEQ || guarded) )
begin
enqerror = 1 ;
$display( "Warning: SizedFIFO: %m -- Enqueuing to a full fifo" ) ;
end
end
end // block: error_checks
// synopsys translate_on
// synopsys translate_off
// Some assertions about parameter values
initial
begin : parameter_assertions
integer ok ;
ok = 1 ;
if ( p2depth <= 1)
begin
ok = 0;
$display ( "Warning SizedFIFO: %m -- depth parameter increased from %0d to 2", p2depth);
end
if ( p3cntr_width <= 0 )
begin
ok = 0;
$display ( "ERROR SizedFIFO: %m -- width parameter must be greater than 0" ) ;
end
if ( ok == 0 ) $finish ;
end // initial begin
// synopsys translate_on
endmodule