MIPS/resources/soc/rtl/MAC/tfifo.v

816 lines
16 KiB
Verilog

/*------------------------------------------------------------------------------
--------------------------------------------------------------------------------
Copyright (c) 2016, Loongson Technology Corporation Limited.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of Loongson Technology Corporation Limited nor the names of
its contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL LOONGSON TECHNOLOGY CORPORATION LIMITED BE LIABLE
TO ANY PARTY FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
module TFIFO (
clk,
rst,
ramwe,
ramaddr,
ramdata,
fifowe,
fifoeof,
fifobe,
fifodata,
fifonf,
fifocnf,
fifoval,
flev,
ici,
dpdi,
aci,
statadi,
cachere,
deo,
lco,
loo,
nco,
eco,
csne,
ico,
uro,
cco,
statado,
sofreq,
eofreq,
dpdo,
aco,
beo,
eofad,
wadg,
tireq,
winp,
dei,
lci,
loi,
nci,
eci,
uri,
cci,
radg,
tiack,
sf,
fdp,
tm,
pbl,
etiack,
etireq,
stopi,
stopo
);
parameter DATAWIDTH = 32;
parameter DATADEPTH = 32;
parameter FIFODEPTH = 9;
parameter CACHEDEPTH = 1;
`include "utility.v"
input clk;
input rst;
output ramwe;
wire ramwe;
output [FIFODEPTH - 1:0] ramaddr;
wire [FIFODEPTH - 1:0] ramaddr;
output [DATAWIDTH - 1:0] ramdata;
wire [DATAWIDTH - 1:0] ramdata;
input fifowe;
input fifoeof;
input [DATAWIDTH / 8 - 1:0] fifobe;
input [DATAWIDTH - 1:0] fifodata;
output fifonf;
reg fifonf;
output fifocnf;
wire fifocnf;
output fifoval;
reg fifoval;
output [FIFODEPTH - 1:0] flev;
wire [FIFODEPTH - 1:0] flev;
input ici;
input dpdi;
input aci;
input [DATADEPTH - 1:0] statadi;
input cachere;
output deo;
wire deo;
output lco;
wire lco;
output loo;
wire loo;
output nco;
wire nco;
output eco;
wire eco;
output csne;
wire csne;
output ico;
wire ico;
output uro;
wire uro;
output [3:0] cco;
wire [3:0] cco;
output [DATADEPTH - 1:0] statado;
wire [DATADEPTH - 1:0] statado;
output sofreq;
wire sofreq;
output eofreq;
reg eofreq;
output dpdo;
wire dpdo;
output aco;
wire aco;
output [DATAWIDTH / 8 - 1:0] beo;
wire [DATAWIDTH / 8 - 1:0] beo;
output [FIFODEPTH - 1:0] eofad;
reg [FIFODEPTH - 1:0] eofad;
output [FIFODEPTH - 1:0] wadg;
reg [FIFODEPTH - 1:0] wadg;
input tireq;
input winp;
input dei;
input lci;
input loi;
input nci;
input eci;
input uri;
input [3:0] cci;
input [FIFODEPTH - 1:0] radg;
output tiack;
wire tiack;
input sf;
input fdp;
input [2:0] tm;
input [5:0] pbl;
input etiack;
output etireq;
reg etireq;
input stopi;
output stopo;
reg stopo;
parameter CCWIDTH = (3 + DATADEPTH + DATAWIDTH / 8 + FIFODEPTH);
reg [CCWIDTH - 1:0] ccmem[(1'b1 << CACHEDEPTH) - 1:0];
wire ccwe;
wire ccre;
reg ccne;
reg iccnf;
wire [CACHEDEPTH - 1:0] ccwad_c;
reg [CACHEDEPTH - 1:0] ccwad;
reg [CACHEDEPTH - 1:0] ccrad;
reg [CACHEDEPTH - 1:0] ccrad_r;
wire [CCWIDTH - 1:0] ccdi;
wire [CCWIDTH - 1:0] ccdo;
parameter CSWIDTH = (DATADEPTH + 11);
reg [CSWIDTH - 1:0] csmem[(1'b1 << CACHEDEPTH) - 1:0];
wire cswe;
reg csre;
reg [CACHEDEPTH - 1:0] cswad;
wire [CACHEDEPTH - 1:0] csrad_c;
reg [CACHEDEPTH - 1:0] csrad;
reg [CACHEDEPTH - 1:0] csrad_r;
wire [CSWIDTH - 1:0] csdi;
wire [CSWIDTH - 1:0] csdo;
wire [DATADEPTH - 1:0] statad;
wire ic;
reg icsne;
reg tprog;
reg tprog_r;
reg winp_r;
reg [FIFODEPTH_MAX - 1:0] tlev_c;
reg tresh;
reg [FIFODEPTH - 1:0] stat;
reg [FIFODEPTH - 1:0] wad;
reg [FIFODEPTH - 1:0] rad_c;
reg [FIFODEPTH - 1:0] rad;
reg [FIFODEPTH - 1:0] radg_0_r;
reg [FIFODEPTH - 1:0] radg_r;
reg [FIFODEPTH - 1:0] sad;
wire [FIFODEPTH - 1:0] eofad_bin;
reg pblz;
reg [FIFODEPTH_MAX - 1:0] sflev_c;
reg tireq_r;
reg tireq_r2;
reg stop_r;
wire [FIFODEPTH - 1:0] fone;
wire [FIFODEPTH - 1:0] fzero;
always @(posedge clk)
begin : ccmem_reg_proc
if (rst)
begin : ccmem_reset
integer i;
for(i = ((1'b1 << CACHEDEPTH) - 1); i >= 0; i = i - 1)
begin
ccmem[i] <= {CCWIDTH{1'b0}};
end
ccrad_r <= {CACHEDEPTH{1'b0}} ;
end
else
begin
if (fifowe | fifoeof)
begin
ccmem[ccwad] <= ccdi ;
end
ccrad_r <= ccrad ;
end
end
assign ccwad_c = (fifoeof) ? ccwad + 1 : ccwad ;
always @(posedge clk)
begin : ccaddr_reg_proc
if (rst)
begin
ccwad <= {CACHEDEPTH{1'b0}} ;
ccrad <= {CACHEDEPTH{1'b0}} ;
end
else
begin
ccwad <= ccwad_c ;
if (ccre)
begin
ccrad <= ccrad + 1 ;
end
end
end
always @(posedge clk)
begin : ccfe_reg_proc
if (rst)
begin
iccnf <= 1'b1 ;
ccne <= 1'b0 ;
end
else
begin
if ((ccwad_c == ccrad) & ccwe)
begin
iccnf <= 1'b0 ;
end
else if (ccre)
begin
iccnf <= 1'b1 ;
end
if (ccwad == ccrad & iccnf)
begin
ccne <= 1'b0 ;
end
else
begin
ccne <= 1'b1 ;
end
end
end
assign fifocnf = iccnf ;
assign ccdo = ccmem[ccrad_r] ;
assign ccdi = {ici, aci, dpdi, wad, fifobe, statadi} ;
assign ccwe = fifoeof ;
assign ccre = tireq_r & ~tireq_r2 ;
assign ic = ccdo[CCWIDTH - 1] ;
assign aco = ccdo[CCWIDTH - 2] ;
assign dpdo = ccdo[CCWIDTH - 3] ;
assign eofad_bin = ccdo[CCWIDTH - 4:CCWIDTH - 3 - FIFODEPTH] ;
always @(posedge clk)
begin : eofad_reg_proc
if (rst)
begin
eofad <= {FIFODEPTH{1'b0}} ;
end
else
begin
eofad[FIFODEPTH - 1] <= eofad_bin[FIFODEPTH - 1] ;
begin : eofad_loop
integer i;
for(i = FIFODEPTH - 2; i >= 0; i = i - 1)
begin
eofad[i] <= eofad_bin[i] ^ eofad_bin[i + 1] ;
end
end
end
end
assign beo = ccdo[DATADEPTH + DATAWIDTH / 8 - 1:DATADEPTH] ;
assign statad = ccdo[DATADEPTH - 1:0] ;
always @(posedge clk)
begin : csmem_reg_proc
if (rst)
begin : csmem_reset
integer i;
for(i = ((1'b1 << CACHEDEPTH) - 1); i >= 0; i = i - 1)
begin
csmem[i] <= {CSWIDTH{1'b0}};
end
csrad_r <= {CACHEDEPTH{1'b0}};
end
else
begin
csmem[cswad] <= csdi ;
csrad_r <= csrad ;
end
end
always @(posedge clk)
begin : csaddr_reg_proc
if (rst)
begin
cswad <= {CACHEDEPTH{1'b0}} ;
csrad <= {CACHEDEPTH{1'b0}} ;
end
else
begin
if (cswe)
begin
cswad <= cswad + 1 ;
end
csrad <= csrad_c ;
end
end
assign csrad_c = (csre) ? csrad + 1 : csrad ;
always @(posedge clk)
begin : icsne_reg_proc
if (rst)
begin
icsne <= 1'b0 ;
end
else
begin
if (cswad == csrad | (csre & cswad == csrad_c))
begin
icsne <= 1'b0 ;
end
else
begin
icsne <= 1'b1 ;
end
end
end
assign csne = icsne;
assign csdo = csmem[csrad_r] ;
assign csdi = {dei, lci, loi, nci, eci, ic, cci, uri, statad} ;
assign deo = csdo[CSWIDTH - 1] ;
assign lco = csdo[CSWIDTH - 2] ;
assign loo = csdo[CSWIDTH - 3] ;
assign nco = csdo[CSWIDTH - 4] ;
assign eco = csdo[CSWIDTH - 5] ;
assign ico = csdo[CSWIDTH - 6] ;
assign cco = csdo[CSWIDTH - 7:CSWIDTH - 10] ;
assign uro = csdo[CSWIDTH - 11] ;
assign statado = csdo[DATADEPTH - 1:0] ;
assign cswe = tireq_r & tprog ;
always @(posedge clk)
begin : csre_reg_proc
if (rst)
begin
csre <= 1'b0 ;
end
else
begin
csre <= cachere ;
end
end
always @(posedge clk)
begin : tprog_reg_proc
if (rst)
begin
tprog <= 1'b0 ;
tprog_r <= 1'b0 ;
end
else
begin
tprog_r <= tprog ;
if (tireq_r)
begin
tprog <= 1'b0 ;
end
else if ((!sf & !tprog & !tireq_r & tresh) | ccne)
begin
tprog <= 1'b1 ;
end
end
end
always @(posedge clk)
begin : eofreq_reg_proc
if (rst)
begin
eofreq <= 1'b0 ;
end
else
begin
if (tprog & ccne)
begin
eofreq <= 1'b1 ;
end
else if (tireq_r)
begin
eofreq <= 1'b0 ;
end
end
end
always @(posedge clk)
begin : tireq_reg_proc
if (rst)
begin
tireq_r <= 1'b0 ;
tireq_r2 <= 1'b0 ;
end
else
begin
tireq_r <= tireq ;
tireq_r2 <= tireq_r ;
end
end
always @(posedge clk)
begin : etireq_reg_proc
if (rst)
begin
etireq <= 1'b0 ;
end
else
begin
if (fifoeof)
begin
etireq <= 1'b1 ;
end
else if (etiack)
begin
etireq <= 1'b0 ;
end
end
end
assign tiack = tireq_r2 ;
assign sofreq = tprog ;
always @(posedge clk)
begin : addr_reg_proc
if (rst)
begin
wad <= {FIFODEPTH{1'b0}} ;
wadg <= {FIFODEPTH{1'b0}} ;
radg_0_r <= {FIFODEPTH{1'b0}} ;
radg_r <= {FIFODEPTH{1'b0}} ;
rad <= {FIFODEPTH{1'b0}} ;
sad <= {FIFODEPTH{1'b0}} ;
end
else
begin
if (fifowe)
begin
wad <= wad + 1 ;
end
wadg[FIFODEPTH - 1] <= wad[FIFODEPTH - 1] ;
begin : wadg_loop
integer i;
for(i = FIFODEPTH - 2; i >= 0; i = i - 1)
begin
wadg[i] <= wad[i] ^ wad[i + 1] ;
end
end
radg_0_r <= radg ;
radg_r <= radg_0_r ;
rad <= rad_c ;
if (!tprog & tprog_r)
begin
sad <= eofad_bin ;
end
end
end
always @(radg_r)
begin : rad_proc
reg[FIFODEPTH - 1:0] rad_v;
rad_v[FIFODEPTH - 1] = radg_r[FIFODEPTH - 1];
begin : rad_loop
integer i;
for(i = FIFODEPTH - 2; i >= 0; i = i - 1)
begin
rad_v[i] = rad_v[i + 1] ^ radg_r[i];
end
end
rad_c = rad_v ;
end
always @(posedge clk)
begin : stat_reg_proc
if (rst)
begin
stat <= {FIFODEPTH{1'b0}} ;
end
else
begin
if ((!winp_r & !fdp & tprog & !tireq_r) | !tprog_r)
begin
stat <= wad - sad ;
end
else
begin
stat <= wad - rad ;
end
end
end
always @(posedge clk)
begin : winp_reg_proc
if (rst)
begin
winp_r <= 1'b0 ;
end
else
begin
winp_r <= winp ;
end
end
always @(tm)
begin : tresh_proc
tlev_c <= {FIFODEPTH_MAX{1'b0}} ;
case (DATAWIDTH)
8 :
begin
case (tm)
3'b000, 3'b101, 3'b110 :
begin
tlev_c[10:0] <= 11'b00010000000 ;
end
3'b001, 3'b111 :
begin
tlev_c[10:0] <= 11'b00100000000 ;
end
3'b010 :
begin
tlev_c[10:0] <= 11'b01000000000 ;
end
3'b011 :
begin
tlev_c[10:0] <= 11'b10000000000 ;
end
default :
begin
tlev_c[10:0] <= 11'b00001000000 ;
end
endcase
end
16 :
begin
case (tm)
3'b000, 3'b101, 3'b110 :
begin
tlev_c[10:0] <= 11'b00001000000 ;
end
3'b001, 3'b111 :
begin
tlev_c[10:0] <= 11'b00010000000 ;
end
3'b010 :
begin
tlev_c[10:0] <= 11'b00100000000 ;
end
3'b011 :
begin
tlev_c[10:0] <= 11'b01000000000 ;
end
default :
begin
tlev_c[10:0] <= 11'b00000100000 ;
end
endcase
end
default :
begin
case (tm)
3'b000, 3'b101, 3'b110 :
begin
tlev_c[10:0] <= 11'b00000100000 ;
end
3'b001, 3'b111 :
begin
tlev_c[10:0] <= 11'b00001000000 ;
end
3'b010 :
begin
tlev_c[10:0] <= 11'b00010000000 ;
end
3'b011 :
begin
tlev_c[10:0] <= 11'b00100000000 ;
end
default :
begin
tlev_c[10:0] <= 11'b00000010000 ;
end
endcase
end
endcase
end
always @(posedge clk)
begin : tresh_reg_proc
if (rst)
begin
tresh <= 1'b0 ;
end
else
begin
if (stat >= tlev_c[FIFODEPTH - 1:0])
begin
tresh <= 1'b1 ;
end
else
begin
tresh <= 1'b0 ;
end
end
end
always @(pbl or pblz)
begin : sflev_proc
sflev_c[FIFODEPTH_MAX - 1:6] <= {(FIFODEPTH_MAX-6){1'b1}} ;
if (pblz)
begin
sflev_c[5:0] <= 6'b000000 ;
end
else
begin
sflev_c[5:0] <= ~pbl ;
end
end
always @(posedge clk)
begin : fifoval_reg_proc
if (rst)
begin
fifoval <= 1'b0 ;
end
else
begin
if (stat <= sflev_c[FIFODEPTH - 1:0])
begin
fifoval <= 1'b1 ;
end
else
begin
fifoval <= 1'b0 ;
end
end
end
always @(posedge clk)
begin : pblz_reg_proc
if (rst)
begin
pblz <= 1'b0 ;
end
else
begin
if (pbl == 6'b000000)
begin
pblz <= 1'b1 ;
end
else
begin
pblz <= 1'b0 ;
end
end
end
always @(posedge clk)
begin : fifonf_reg_proc
if (rst)
begin
fifonf <= 1'b1 ;
end
else
begin
if ((stat == {fone[FIFODEPTH - 1:1], 1'b0} & fifowe) |
(stat == fone))
begin
fifonf <= 1'b0 ;
end
else
begin
fifonf <= 1'b1 ;
end
end
end
assign flev = stat ;
assign ramaddr = wad ;
assign ramdata = fifodata ;
assign ramwe = fifowe ;
always @(posedge clk)
begin : tstop_reg_proc
if (rst)
begin
stop_r <= 1'b1 ;
stopo <= 1'b0 ;
end
else
begin
stop_r <= stopi ;
if (stop_r & !ccne & !icsne & stat == fzero & !tprog)
begin
stopo <= 1'b1 ;
end
else
begin
stopo <= 1'b0 ;
end
end
end
assign fone = {FIFODEPTH{1'b1}} ;
assign fzero = {FIFODEPTH{1'b0}} ;
endmodule