dakies/OSS_Verilog huggingface dataset:
module
    propagateFloatNaN_divSqrt#(parameter sigWidth = 3) (
        input [(`floatControlWidth - 1):0] control,
        input sqrtOp,
        input isNaNA,
        input signA,
        input [(sigWidth - 2):0] fractA,
        input isNaNB,
        input signB,
        input [(sigWidth - 2):0] fractB,
        output signNaN,
        output [(sigWidth - 2):0] fractNaN
    );

    wire isTrueNaNB = !sqrtOp && isNaNB;
    assign signNaN = isNaNA ? signA : isTrueNaNB ? signB : 1;
    assign fractNaN =
        {1'b1,
         isNaNA ? fractA[(sigWidth - 3):0]
             : isTrueNaNB ? fractB[(sigWidth - 3):0] : 1'b0};

endmodule
module chacha_qr(
                 input wire [31 : 0]  a,
                 input wire [31 : 0]  b,
                 input wire [31 : 0]  c,
                 input wire [31 : 0]  d,

                 output wire [31 : 0] a_prim,
                 output wire [31 : 0] b_prim,
                 output wire [31 : 0] c_prim,
                 output wire [31 : 0] d_prim
                );

  //----------------------------------------------------------------
  // Wires.
  //----------------------------------------------------------------
  reg [31 : 0] internal_a_prim;
  reg [31 : 0] internal_b_prim;
  reg [31 : 0] internal_c_prim;
  reg [31 : 0] internal_d_prim;


  //----------------------------------------------------------------
  // Concurrent connectivity for ports.
  //----------------------------------------------------------------
  assign a_prim = internal_a_prim;
  assign b_prim = internal_b_prim;
  assign c_prim = internal_c_prim;
  assign d_prim = internal_d_prim;


  //----------------------------------------------------------------
  // qr
  //
  // The actual quarterround function.
  //----------------------------------------------------------------
  always @*
    begin : qr
      reg [31 : 0] a0;
      reg [31 : 0] a1;

      reg [31 : 0] b0;
      reg [31 : 0] b1;
      reg [31 : 0] b2;
      reg [31 : 0] b3;

      reg [31 : 0] c0;
      reg [31 : 0] c1;

      reg [31 : 0] d0;
      reg [31 : 0] d1;
      reg [31 : 0] d2;
      reg [31 : 0] d3;

      a0 = a + b;
      d0 = d ^ a0;
      d1 = {d0[15 : 0], d0[31 : 16]};
      c0 = c + d1;
      b0 = b ^ c0;
      b1 = {b0[19 : 0], b0[31 : 20]};
      a1 = a0 + b1;
      d2 = d1 ^ a1;
      d3 = {d2[23 : 0], d2[31 : 24]};
      c1 = c0 + d3;
      b2 = b1 ^ c1;
      b3 = {b2[24 : 0], b2[31 : 25]};

      internal_a_prim = a1;
      internal_b_prim = b3;
      internal_c_prim = c1;
      internal_d_prim = d3;
    end // qr
endmodule // chacha_qr
module Sort8TestBench();
reg req=1'b0;
wire fin;
reg [15:0] inputNumber[0:7];
wire [127:0] inputNumberLine;
wire [127:0] outputNumberLine;
wire [15:0] outputNumber[0:7];

initial begin
#10;
inputNumber[0] = $random;
inputNumber[1] = $random;
inputNumber[2] = $random;
inputNumber[3] = $random;
inputNumber[4] = $random;
inputNumber[5] = $random;
inputNumber[6] = $random;
inputNumber[7] = $random;
end

genvar i;
generate 
for(i=0;i<8;i=i+1)
begin
   assign inputNumberLine[16*i+15:i*16]=inputNumber[7-i];
   assign outputNumber[7-i]=outputNumberLine[16*i+15:i*16];
end
endgenerate 

initial begin
#400 req=1'b1;
end

sort8 #(32) sort8 (req,fin,inputNumberLine,outputNumberLine);

endmodule
module FibonacciTestBench();
reg req=1'b0;
wire fin;
wire [31:0] result;
reg [31:0] N=32'd44;  // fibonacci[]={1,1,2,3,5,8...}, starts numbering from 0

initial begin
#100 req=1'b1;
end

fibonacci #(32) fibonacci (req,fin,N,result);

endmodule
module addTest(
    input clk,
    input req_in,
    output fin,
    input [31:0] a_in,
    input [31:0] b_in,
    output wire [31:0] s1,
    output wire cout1,
    output wire [31:0] s2,
    output wire cout2
    );
    reg req=1'b0;
    reg [31:0] a=0,b=0;
    always@(posedge clk) begin
        if(req_in) begin
            req<=1'b1;
            a<=a_in;
            b<=b_in;
        end
    end
    
    assign {cout1,s1}=a+b;
    add #(32) add (req,fin,a,b,s2,cout2);
       
endmodule
module SqrtTestBench();
reg req=1'b0;
//reg clk=1'b1;
wire fin;
reg [31:0] in=32'd10454520;  // change the input number as you like
wire [31:0] out; 

initial begin
#100 req=1'b1;
end
/*
always begin
#5 clk=~clk;
end
*/
sqrt #(32) sqrt (req,fin,in,out);
//sqrtIP sqrtIP (clk,req,in,fin,out);
endmodule
module compareTest(
    input clk,
    input [31:0] a_in,
    input [31:0] b_in,
    input req_in,
    output wire fin,
    output wire [2:0] resultNormal,
    output wire [2:0] resultKarin
    );
    reg req=1'b0;
    reg [31:0] a=0;
    reg [31:0] b=0;
    always@(posedge clk) begin
        if(req_in) begin
            req<=1'b1;
            a<=a_in;
            b<=b_in;
        end
    end
    assign resultNormal[2] = a>b;
    assign resultNormal[1] = a==b;
    assign resultNormal[0] = a<b;
    comparator #(32) comparator (req,fin,a,b,resultKarin[2],resultKarin[1],resultKarin[0]);
endmodule
module functionChooser #(parameter N=2) (reqs,sets,fin,rst);
input [N-1:0] reqs;
output reg [N-1:0] sets=0;
output reg fin=1'b0;
input rst;
reg reset=1'b1;
reg [N-1:0] reqSave=0;
wire [N-1:0] reqAnd;
wire [N:0] reqAndOr;
assign reqAndOr[0]=reqAnd[0];

always@(posedge rst or posedge reqAndOr[N]) begin
    if(reqAndOr[N]) reset<=1'b0;
    else reset<=1'b1;
end

always@(posedge reqAndOr[N] or posedge fin) begin
    if(fin) fin<=1'b0;
    else fin<=1'b1;
end

genvar i;
generate
for(i=0;i<N;i=i+1)
begin: functionChooserSub
    always@(posedge reqs[i] or posedge reqAndOr[N]) begin
        if(reqAndOr[N]) reqSave[i]<=1'b0;
        else reqSave[i]<=1'b1;
    end
    always@(posedge reqAndOr[N]) begin
        sets[i]<=reqAnd[i];
    end
    assign reqAndOr[i+1]=reqAndOr[i]|reqAnd[i];
    assign reqAnd[i]=reqSave[i]&reset;
end
endgenerate


endmodule
module reqAndSimple #(parameter reqNumber=3) (reqs,fin);
input [reqNumber-1:0] reqs;
output wire fin;

wire [reqNumber:0] reqsConnect;
assign reqsConnect[0]=reqs[0];
assign fin=reqsConnect[reqNumber];

genvar i;
generate
for(i=0;i<reqNumber;i=i+1)
begin:reqTogetherSimple
    assign reqsConnect[i+1]=reqsConnect[i]&reqs[i];
end
endgenerate



endmodule
module compareSwap #(parameter Width=32) (req,fin,a,b,smaller,bigger);

input [Width-1:0] a,b;
output wire [Width-1:0] smaller,bigger;
input req;
output wire fin;
wire compareFin,biggerSign,equalSign,smallerSign;
wire biggerFin,smallerFin;

comparator  #(Width) comparator (req,compareFin,a,b,biggerSign,equalSign,smallerSign);
chooseFrom2 #(Width) chooseSmaller (compareFin,smallerFin,a,b,smaller,smallerSign);
chooseFrom2 #(Width) chooseBigger  (compareFin,biggerFin,b,a,bigger,smallerSign);
reqAnd      #(2) finAnd ({smallerFin,biggerFin},fin);

endmodule
module reqRst (req,rst,fin);
input req,rst;
output wire fin;

reg reqBuf=1'b0;
reg rstBuf=1'b1;
assign fin=reqBuf&rstBuf;

always@(posedge req or posedge fin) begin
    if(fin) reqBuf<=1'b0;
    else reqBuf<=1'b1;
end

always@(posedge rst or posedge fin) begin
    if(fin) rstBuf<=1'b0;
    else rstBuf<=1'b1;
end

endmodule
module counter #(parameter N=10) (addReq,addFin,fin);
input addReq;
output reg addFin=1'b0;
output wire fin;

reg [N-1:0] out=1;
assign fin=out[N-1]; 
 
always@(posedge addReq or posedge addFin or posedge fin) begin
    if(fin) begin
        out<=1;
        addFin<=1'b0;
    end
    else if(addFin) begin
        out<=out;
        addFin<=1'b0;
    end
    else begin
        out<={out<<1,1'b1};
        addFin<=1'b1;
    end
end

endmodule
module delay #(parameter N=10) (req,fin);
input req;
output wire fin;

(* dont_touch="true" *) wire [N-1:0] c /*synthesis noprune*/;  
// (* dont_touch="true" *) and /*synthesis noprune*/ make it work on both Xilinx platform and Altera platform. 

reg rec=1'b0;
assign c[0]=rec;
assign fin = c[N-1];

always@(posedge req or posedge fin) begin
	if(fin) rec<=1'b0;
	else rec<=1'b1;
end

genvar i;
generate 
	for(i=1;i<N;i=i+1)
	begin:delays
		assign c[i]=rec&(c[i-1]);
	end
endgenerate

endmodule
module functionChooserFast #(parameter N=2) (reqs,sets,fin,rst);
input [N-1:0] reqs;
output reg [N-1:0] sets=0;
output wire fin;
input rst;

reg reset=1'b0;
wire [N:0] reqAndOr;

assign reqAndOr[0]=sets[0];
assign fin=reqAndOr[N];

always@(posedge rst or posedge reset) begin
    if(reset) reset<=1'b0;
    else reset<=1'b1;
end

genvar i;
generate
for(i=0;i<N;i=i+1)
begin: functionChooserFastSub
    always@(posedge reqs[i] or posedge reset) begin
        if(reset) sets[i]<=1'b0;
        else sets[i]<=1'b1;
    end
    assign reqAndOr[i+1]=reqAndOr[i]|sets[i];
end
endgenerate


endmodule
module delayOne(req,fin);
input req;
(* dont_touch="true" *) output reg fin=1'b0;
// (* dont_touch="true" *) makes it work on Xilinx platform. 

always@(posedge req or posedge fin) begin
    if(fin) fin<=1'b0;
    else fin<=1'b1;
end

endmodule
module reqAnd #(parameter reqNumber=2) (reqs,fin);
input [reqNumber-1:0] reqs;
output wire fin;

reg [reqNumber-1:0] reqsSave=0;
reg [reqNumber-1:0] zeros=0;

assign fin=(reqsSave==~zeros);

genvar i;
generate
for(i=0;i<reqNumber;i=i+1)
begin:reqTogether
    always@(posedge reqs[i] or posedge fin) begin
        if(fin) reqsSave[i]<=1'b0;
        else reqsSave[i]<=1'b1;
    end 
end
endgenerate 


endmodule
module MUX2 #(parameter Width=32,parameter defaultValue=0) (req1,req2,in1,in2,out);
input req1,req2;
input [Width-1:0] in1,in2;
output wire [Width-1:0] out;
wire req;
wire sel;
reg sel1=1'b0,sel2=defaultValue;  // 0:choose in1, 1:choose in2

assign out=sel?in1:in2;
assign sel=(sel1==sel2);

always@(posedge req1) sel1<=sel2;
always@(posedge req2) sel2<=~sel1;

endmodule
module reqOr #(parameter reqNumber=2) (reqs,fin);
input [reqNumber-1:0] reqs;
output reg fin=1'b0;

reg [reqNumber-1:0] finBuf=0;
reg [reqNumber-1:0] zeros=0;
wire finAll;

assign finAll = (finBuf!=zeros);

always@(posedge finAll or posedge fin) begin
    if(fin) fin<=1'b0;
    else fin<=1'b1;
end

genvar i;
generate
for(i=0;i<reqNumber;i=i+1)
begin:ipp
always@(posedge reqs[i] or posedge fin) begin
    if(fin) finBuf[i]<=1'b0;
    else finBuf[i]<=1'b1;
end
end

endgenerate

endmodule
module once (req1,req2,fin,rstReq,rstFin);
input req1,req2,rstReq;
output wire fin;
output wire rstFin;

reg first=1'b1;
reg rst=1'b0;
reg req1Buf=1'b0;

assign fin=(first&req1Buf)|(!first&req2);
assign rstFin=first;

always@(posedge req1 or posedge fin) begin
    if(fin) req1Buf<=1'b0;
    else req1Buf<=1'b1;
end

always@(posedge rstReq or posedge first) begin
    if(first) rst<=1'b0;
    else rst<=1'b1;
end

always@(posedge req1Buf or posedge rst) begin
    if(rst) first<=1'b1;
    else first<=1'b0;
end
    
endmodule
module chooseFrom2 #(parameter N=32) (req,fin,a,b,out,sel);
input req;
input [N-1:0] a,b;
output reg [N-1:0] out=0;
output reg fin=1'b1;
input sel;
reg finBuf=1'b0;

always@(posedge req or posedge finBuf) begin
    if(finBuf) begin
        if(sel) out<=a;
        else out<=b;  
        fin<=1'b1;
        finBuf<=1'b0;
     end
     else begin
        finBuf<=1'b1;
        fin<=1'b0;
        out<=0;
     end
end


endmodule
module branch (req,finTrue,finFalse,boolIn);

input req,boolIn;
output wire finTrue,finFalse;

assign finTrue=req&boolIn;
assign finFalse=req&!boolIn;

endmodule
module comparator #(parameter Width=32) (req,fin,x,y,bigger,equal,smaller);
input req;
input [Width-1:0] x,y;
output wire fin;
output wire bigger,equal,smaller;

wire start;
reg [2:0] result=3'b000;
reg rec=1'b0;

assign fin = (result==3'b100)|(result==3'b010)|(result==3'b001);
assign start = rec&(~fin);
assign {bigger,equal,smaller} = result;

always@(posedge req or posedge start) begin
   if(start) begin
        rec<=1'b0;
		if(x>y) result<=3'b100;
		else if(x<y) result<=3'b001;
		else result<=3'b010;
	end
	else begin
	    rec<=1'b1;
		result<=3'b000;
	end
end

endmodule
module equalOrNot #(parameter Width=32) (req,fin,equal,notEqual,x,y);
input req;
input [Width-1:0] x,y;
output wire equal,notEqual,fin;

reg [1:0] result=2'b00;

assign equal = result[1];
assign notEqual = result[0];
assign fin = (result==2'b01)|(result==2'b10);
wire start = ~fin;

always@(posedge req or posedge start) begin
	if(start) begin
		if(x==y) result<=2'b10;
		else result<=2'b01;
	end
	else result<=2'b00;
end

endmodule
module minus #(parameter Width=32) (req,fin,x,y,so,couto);
input req;
input [Width-1:0] x,y;
output reg fin=1'b0;
output reg [Width-1:0] so=0;
output reg couto=0;

wire [Width-1:0]s;
wire cout;
wire [Width:0] result;
assign result = {x,1'b1}-{y,1'b0};
assign s = result[Width:1];
assign cout = ~result[0];
wire req2;

delayOne delay1 (req,req2);

always@(posedge req2 or posedge fin) begin
	if(fin) begin
		fin<=1'b0;
		so<=so;
		couto<=couto;
	end
	else begin
		fin<=1'b1;
		so<=s;
		couto<=cout;
	end
end	

endmodule
module sqrt #(parameter Width=32)(req,fin,x,y);
input req;
output wire fin;
input [Width-1:0] x;
output wire [Width-1:0] y;

wire [Width:0] x1In;
wire [Width-1:0] xInitial,xOut,xDxOut; 
wire xFin,xFin1,xFin2,xReq,addFin,divideFin,req2,continues,equalFin,notEqual,equal; 

assign y=xOut;
assign continues = equalFin&notEqual;
assign fin = equalFin&equal;

reqOr #(2) reqOrFin ({xFin1,xFin2},xFin);
sqrtInitialValue #(Width) sqrtInitialValue (req,req2,x,xInitial);
var2 #(Width,1) xVar (req2,continues,xFin1,xFin2,xInitial,x1In[Width:1],xOut);
divide #(Width,Width) divide (xFin,divideFin,x,xOut,xDxOut,);
add #(Width+1) add (divideFin,addFin,{1'b0,xOut},{1'b0,xDxOut},x1In,);
equalOrNot #(Width) equalOr (addFin,equalFin,equal,notEqual,x1In[Width:1],xOut);

endmodule
module add #(parameter Width=32) (req,fin,x,y,so,couto);
input req;
input [Width-1:0] x,y;
output reg fin=1'b0;
output reg [Width-1:0] so=0;
output reg couto=1'b0;

wire [Width-1:0]s;
wire cout;
assign {cout,s} = x+y;

wire req2;

delayOne delay1 (req,req2);

always@(posedge req2 or posedge fin) begin
	if(fin) begin
		fin<=1'b0;
		so<=so;
		couto<=couto;
	end
	else begin
		fin<=1'b1;
		so<=s;
		couto<=cout;
	end
end	

endmodule
module sqrtInitialValue #(parameter Width=32) (req,fin,x,yo);
input req;
output reg fin=1'b0;
input [Width-1:0] x;
output reg [Width-1:0] yo=0;

reg finish=1'b0;
reg reqBuf=1'b0;
wire [Width:0] x0;
wire [Width-1:0] y;
assign x0={1'b0,x};

always@(posedge finish or posedge fin) begin
    if(fin) fin<=1'b0;
    else fin<=1'b1;
end

genvar i;
generate 
for(i=0;i<Width;i=i+1)
begin:sqrti

    if(i%2==1) begin
         assign y[(i-1)/2]=x0[i]|x0[i+1];
    end
    
    if(Width%2==0) begin
        if(i>=Width/2) assign y[i]=1'b0; 
    end 
    else begin        
        if(i>=(Width-1)/2) assign y[i]=1'b0; 
    end  
end
endgenerate

always@(posedge req or posedge reqBuf) begin
    if(reqBuf) begin
       yo<=y;
       reqBuf<=1'b0;
       finish<=1'b1;
    end
    else begin
       yo<=0;
       reqBuf<=1'b1;
       finish<=1'b0;
    end
end

endmodule
module registerLeft #(parameter Width=32) (saveReq,saveFin,leftReq,leftFin,in,out);
input saveReq,leftReq;
output reg saveFin=1'b0, leftFin=1'b0;
input [Width-1:0] in;
output reg [Width-1:0] out=0;

reg leftReqBuf=1'b0,leftFinBuf=1'b0,saveReqBuf=1'b0,saveFinBuf=1'b0;
wire eventFin=leftFinBuf|saveFinBuf;

always@(posedge leftReq or posedge leftFinBuf) begin
    if(leftFinBuf) begin 
        leftReqBuf<=1'b0;
        leftFin<=1'b1;
    end
    else begin
        leftReqBuf<=1'b1;
        leftFin<=1'b0;
    end
end

always@(posedge saveReq or posedge saveFinBuf) begin
    if(saveFinBuf) begin
        saveReqBuf<=1'b0;
        saveFin<=1'b1;
    end
    else begin
        saveReqBuf<=1'b1;
        saveFin<=1'b0;
    end
end

always@(posedge saveReqBuf or posedge leftReqBuf or posedge eventFin) begin
if(eventFin) begin
    saveFinBuf<=1'b0;
    leftFinBuf<=1'b0;
    out<=out;
end
else if(saveReqBuf) begin
    saveFinBuf<=1'b1;
    leftFinBuf<=1'b0;
    out<=in;
end
else if(leftReqBuf) begin
    leftFinBuf<=1'b1;
    saveFinBuf<=1'b0;
    out<={out<<1,1'b0};
end
else begin
    leftFinBuf<=1'b0;
    saveFinBuf<=1'b0;
    out<=out;
end
end

endmodule
module registerRight #(parameter Width=32) (saveReq,saveFin,rightReq,rightFin,in,out);
input saveReq,rightReq;
output reg saveFin=1'b0, rightFin=1'b0;
input [Width-1:0] in;
output reg [Width-1:0] out=0;

reg rightReqBuf=1'b0,rightFinBuf=1'b0,saveReqBuf=1'b0,saveFinBuf=1'b0;
wire eventFin=rightFinBuf|saveFinBuf;

always@(posedge rightReq or posedge rightFinBuf) begin
    if(rightFinBuf) begin 
        rightReqBuf<=1'b0;
        rightFin<=1'b1;
    end
    else begin
        rightReqBuf<=1'b1;
        rightFin<=1'b0;
    end
end

always@(posedge saveReq or posedge saveFinBuf) begin
    if(saveFinBuf) begin
        saveReqBuf<=1'b0;
        saveFin<=1'b1;
    end
    else begin
        saveReqBuf<=1'b1;
        saveFin<=1'b0;
    end
end

always@(posedge saveReqBuf or posedge rightReqBuf or posedge eventFin) begin
if(eventFin) begin
    saveFinBuf<=1'b0;
    rightFinBuf<=1'b0;
    out<=out;
end
else if(saveReqBuf) begin
    saveFinBuf<=1'b1;
    rightFinBuf<=1'b0;
    out<=in;
end
else if(rightReqBuf) begin
    rightFinBuf<=1'b1;
    saveFinBuf<=1'b0;
    out<={1'b0,out>>1};
end
else begin
    rightFinBuf<=1'b0;
    saveFinBuf<=1'b0;
    out<=out;
end
end

endmodule
module var2 #(parameter Width=32, parameter InitialValue=0) (req1,req2,fin1,fin2,dataIn1,dataIn2,dataOut);
input req1,req2;
input [Width-1:0] dataIn1,dataIn2;
output reg fin1=1'b0,fin2=1'b0;
output reg [Width-1:0] dataOut=InitialValue;

reg req1Buf=1'b0;
reg fin1Buf=1'b0;
reg req2Buf=1'b0;
reg fin2Buf=1'b0;
wire eventFin;
assign eventFin=fin1Buf|fin2Buf;

always@(posedge req1 or posedge fin1Buf) begin
    if(fin1Buf) begin 
        req1Buf<=1'b0;
        fin1<=1'b1;
    end
    else begin
        req1Buf<=1'b1;
        fin1<=1'b0;
    end
end

always@(posedge req2 or posedge fin2Buf) begin
    if(fin2Buf) begin
        req2Buf<=1'b0;
        fin2<=1'b1;
    end
    else begin
        req2Buf<=1'b1;
        fin2<=1'b0;
    end
end

always@(posedge req2Buf or posedge req1Buf or posedge eventFin) begin
if(eventFin) begin
    fin2Buf<=1'b0;
    fin1Buf<=1'b0;
    dataOut<=dataOut;
end
else begin
if(req1Buf) begin
    fin1Buf<=1'b1;
    fin2Buf<=1'b0;
    dataOut<=dataIn1;
end
else if(req2Buf) begin
    fin2Buf<=1'b1;
    fin1Buf<=1'b0;
    dataOut<=dataIn2;
end
else begin
    fin1Buf<=fin1Buf;
    fin2Buf<=fin2Buf;
    dataOut<=dataOut;
end
end
end

endmodule
module usb_reset_det (
  input clk,
  output reset,

  input usb_p_rx,
  input usb_n_rx
);
  // reset detection
  reg [16:0] reset_timer = 0;
  reg reset_i = 0;


  wire timer_expired = reset_timer > 16'd30000;
  always @(posedge clk) reset_i <= timer_expired;
  assign reset = reset_i;
 
  
  always @(posedge clk) begin
    if (usb_p_rx || usb_n_rx) begin
      reset_timer <= 0;
    end else begin
      // SE0 detected from host
      if (!timer_expired) begin
        // timer not expired yet, keep counting
        reset_timer <= reset_timer + 1;
      end
    end
  end
  
endmodule
module usb_uart (
  input  clk_48mhz,
  input reset,

  // USB pins
  inout  pin_usb_p,
  inout  pin_usb_n,

  // uart pipeline in (out of the device, into the host)
  input [7:0] uart_in_data,
  input       uart_in_valid,
  output      uart_in_ready,

  // uart pipeline out (into the device, out of the host)
  output [7:0] uart_out_data,
  output       uart_out_valid,
  input        uart_out_ready,

  output [11:0] debug
);

    wire usb_p_tx;
    wire usb_n_tx;
    wire usb_p_rx;
    wire usb_n_rx;
    wire usb_tx_en;

    //wire [3:0] debug;

    usb_uart_core uart (
        .clk_48mhz  (clk_48mhz),
        .reset      (reset),

        // pins - these must be connected properly to the outside world.  See below.
        .usb_p_tx(usb_p_tx),
        .usb_n_tx(usb_n_tx),
        .usb_p_rx(usb_p_rx),
        .usb_n_rx(usb_n_rx),
        .usb_tx_en(usb_tx_en),

        // uart pipeline in
        .uart_in_data( uart_in_data ),
        .uart_in_valid( uart_in_valid ),
        .uart_in_ready( uart_in_ready ),

        // uart pipeline out
        .uart_out_data( uart_out_data ),
        .uart_out_valid( uart_out_valid ),
        .uart_out_ready( uart_out_ready ),

        .debug( debug )
    );

    wire usb_p_in;
    wire usb_n_in;

    assign usb_p_rx = usb_tx_en ? 1'b1 : usb_p_in;
    assign usb_n_rx = usb_tx_en ? 1'b0 : usb_n_in;

    SB_IO #(
        .PIN_TYPE(6'b 1010_01), // PIN_OUTPUT_TRISTATE - PIN_INPUT
        .PULLUP(1'b 0)
    ) iobuf_usbp (
        .PACKAGE_PIN(pin_usb_p),
        .OUTPUT_ENABLE(usb_tx_en),
        .D_OUT_0(usb_p_tx),
        .D_IN_0(usb_p_in)
    );

    SB_IO #(
        .PIN_TYPE(6'b 1010_01), // PIN_OUTPUT_TRISTATE - PIN_INPUT
        .PULLUP(1'b 0)
    ) iobuf_usbn (
        .PACKAGE_PIN(pin_usb_n),
        .OUTPUT_ENABLE(usb_tx_en),
        .D_OUT_0(usb_n_tx),
        .D_IN_0(usb_n_in)
    );

endmodule
module usb_uart (
        input  clk_48mhz,
        input reset,

        // USB pins
        inout  pin_usb_p,
        inout  pin_usb_n,

        // uart pipeline in (out of the device, into the host)
        input [7:0] uart_in_data,
        input       uart_in_valid,
        output      uart_in_ready,

        // uart pipeline out (into the device, out of the host)
        output [7:0] uart_out_data,
        output       uart_out_valid,
        input        uart_out_ready,

        output [11:0] debug
    );

    wire usb_p_tx;
    wire usb_n_tx;
    wire usb_p_rx;
    wire usb_n_rx;
    wire usb_tx_en;

    //wire [3:0] debug;

    usb_uart_core_np u_u_c_np (
        .clk_48mhz  (clk_48mhz),
        .reset      (reset),

        // pins - these must be connected properly to the outside world.  See below.
        .usb_p_tx(usb_p_tx),
        .usb_n_tx(usb_n_tx),
        .usb_p_rx(usb_p_rx),
        .usb_n_rx(usb_n_rx),
        .usb_tx_en(usb_tx_en),

        // uart pipeline in
        .uart_in_data( uart_in_data ),
        .uart_in_valid( uart_in_valid ),
        .uart_in_ready( uart_in_ready ),

        // uart pipeline out
        .uart_out_data( uart_out_data ),
        .uart_out_valid( uart_out_valid ),
        .uart_out_ready( uart_out_ready ),

        .debug( debug )
    );

    wire usb_p_in;
    wire usb_n_in;

    assign usb_p_rx = usb_tx_en ? 1'b1 : usb_p_in;
    assign usb_n_rx = usb_tx_en ? 1'b0 : usb_n_in;

    IOBUF #(
        .DRIVE(16), // Specify the output drive strength
        .IBUF_LOW_PWR("FALSE"),  // Low Power - "TRUE", High Performance = "FALSE"
        .IOSTANDARD("DEFAULT"), // Specify the I/O standard
        .SLEW("FAST") // Specify the output slew rate
    ) iobuf_p (
        .O( usb_p_in  ),       // Buffer output
        .I( usb_p_tx ),       // Buffer input
        .IO( pin_usb_p ),     // Buffer inout port (connect directly to top-level port)
        .T( !usb_tx_en )      // 3-state enable input, high=input, low=output
    );

    IOBUF #(
        .DRIVE(16), // Specify the output drive strength
        .IBUF_LOW_PWR("FALSE"),  // Low Power - "TRUE", High Performance = "FALSE"
        .IOSTANDARD("DEFAULT"), // Specify the I/O standard
        .SLEW("FAST") // Specify the output slew rate
    ) iobuf_n (
        .O( usb_n_in  ),      // Buffer output
        .I( usb_n_tx ),       // Buffer input
        .IO( pin_usb_n ),     // Buffer inout port (connect directly to top-level port)
        .T( !usb_tx_en )      // 3-state enable input, high=input, low=output
    );

endmodule
module shift_16(
		input wire clk,
		input wire reset,
		input wire in_valid,
		input wire signed [23:0] din_r,
		input wire signed [23:0] din_i,
		output wire signed [23:0] dout_r,
		output wire signed [23:0] dout_i
	);
	integer i ;
	reg [383:0] shift_reg_r ;
	reg [383:0] shift_reg_i ;
	reg [383:0] tmp_reg_r ;
	reg [383:0] tmp_reg_i ;
	reg [5:0] counter_16,next_counter_16;
	reg valid,next_valid;

	assign dout_r    = shift_reg_r[383:360];
	assign dout_i    = shift_reg_i[383:360];

	always@(posedge clk or posedge reset)begin
		if(reset)begin
			shift_reg_r <= 0;
			shift_reg_i <= 0;
			counter_16  <= 0;
			valid       <= 0;
		end
		else 
		if (in_valid)begin
			counter_16       <= next_counter_16;
			shift_reg_r      <= (tmp_reg_r<<24) + din_r;
			shift_reg_i      <= (tmp_reg_i<<24) + din_i;
			valid            <= in_valid;
		end
		else if (valid)begin
			counter_16       <= next_counter_16;
			shift_reg_r      <= (tmp_reg_r<<24) + din_r;
			shift_reg_i      <= (tmp_reg_i<<24) + din_i;
			valid            <= next_valid;
		end
	end
	
	
	always@(*)begin
		next_counter_16 = counter_16 + 5'd1;
		tmp_reg_r = shift_reg_r;
		tmp_reg_i = shift_reg_i;
		next_valid = valid;
	end
	

endmodule
module ROM_8(
		input wire clk,
		input wire in_valid,
		input wire reset,
		output reg [23:0] w_r,
		output reg [23:0] w_i,
		output reg[1:0] state
	);

	reg valid,next_valid;
	reg [5:0] count,next_count;
	reg [3:0] s_count,next_s_count;

	always@(posedge clk or posedge reset)begin
		if(reset)begin
			count <= 0;
			s_count <= 0;
		end
		else begin
			count <= next_count;
			s_count <= next_s_count;
		end
	end
	
	always @(*) begin
		if(in_valid || valid)
		begin 
			next_count = count + 1;
			next_s_count = s_count;
		end
		else begin
			next_count = count;
			next_s_count = s_count;  
		end
		
		if (count<6'd8) 
			state = 2'd0;
		else if (count >= 6'd8 && s_count < 4'd8)begin
			state = 2'd1;
			next_s_count = s_count + 1;
		end
		else if (count >= 6'd8 && s_count >= 4'd8)begin
			state = 2'd2;
			next_s_count = s_count + 1;
		end
		case(s_count)
		4'd8: begin
			w_r = 24'b 00000000_00000001_00000000;
			w_i = 24'b 00000000_00000000_00000000;
			end
		4'd9: begin
			w_r = 24'b 00000000_00000000_11101101;
			w_i = 24'b 11111111_11111111_10011110;
			end
		4'd10: begin
			w_r = 24'b 00000000_00000000_10110101;
			w_i = 24'b 11111111_11111111_01001011;
			end
		4'd11: begin
			w_r = 24'b 00000000_00000000_01100010;
			w_i = 24'b 11111111_11111111_00010011;
			end
		4'd12: begin
			w_r = 24'b 00000000_00000000_00000000;
			w_i = 24'b 11111111_11111111_00000000;
			end
		4'd13: begin
			w_r = 24'b 11111111_11111111_10011110;
			w_i = 24'b 11111111_11111111_00010011;
			end
		4'd14: begin
			w_r = 24'b 11111111_11111111_01001011;
			w_i = 24'b 11111111_11111111_01001011;
			end
		4'd15: begin
			w_r = 24'b 11111111_11111111_00010011;
			w_i = 24'b 11111111_11111111_10011110;
			end
		default: begin
			w_r = 24'b 00000000_00000001_00000000;
			w_i = 24'b 00000000_00000000_00000000;
			end
		endcase
	end	
endmodule
module ROM_2(
		input wire clk,
		input wire in_valid,
		input wire reset,
		output reg [23:0] w_r,
		output reg [23:0] w_i,
		output reg[1:0] state
	);

	reg valid,next_valid;
	reg [5:0] count,next_count;
	reg [1:0] s_count,next_s_count;

	always@(posedge clk or posedge reset)begin
		if(reset)begin
			count <= 0;
			s_count <= 0;
		end
		else begin
			count <= next_count;
			s_count <= next_s_count;
		end
	end
	
		always @(*) begin
		state = 2'd0;
		if(in_valid || valid)
		begin 
			next_count = count + 1;
			next_s_count = s_count;
		end
		else begin
			next_count = count;
			next_s_count = s_count;  
		end

		if (count<6'd2) 
			state = 2'd0;
		else if (count >= 6'd2 && s_count < 2'd2)begin
			state = 2'd1;
			next_s_count = s_count + 1;
		end else if (count >= 6'd2 && s_count >= 2'd2)begin
			state = 2'd2;
			next_s_count = s_count + 1;
		end
		case(s_count)
		2'd2: begin
			w_r = 24'b 00000000_00000001_00000000;
			w_i = 24'b 00000000_00000000_00000000;
			end
		2'd3: begin
			w_r = 24'b 00000000_00000000_00000000;
			w_i = 24'b 11111111_11111111_00000000;
			end
		default: begin
			w_r = 24'b 00000000_00000001_00000000;
			w_i = 24'b 00000000_00000000_00000000;
			end
		endcase
	end
endmodule
module ROM_4(
		input wire clk,
		input wire in_valid,
		input wire reset,
		output reg [23:0] w_r,
		output reg [23:0] w_i,
		output reg[1:0] state
	);

	reg valid,next_valid;
	reg [5:0] count,next_count;
	reg [2:0] s_count,next_s_count;

	always@(posedge clk or posedge reset)begin
		if(reset)begin
			count <= 0;
			s_count <= 0;
		end
		else begin
			count <= next_count;
			s_count <= next_s_count;
		end
	end
	
		always @(*) begin
		if(in_valid || valid)
		begin 
			next_count = count + 1;
			next_s_count = s_count;
		end
		else begin
			next_count = count;
			next_s_count = s_count;  
		end

		if (count<6'd4) 
			state = 2'd0;
		else if (count >= 6'd4 && s_count < 3'd4)begin
			state = 2'd1;
			next_s_count = s_count + 1;
		end
		else if (count >= 6'd4 && s_count >= 3'd4)begin
			state = 2'd2;
			next_s_count = s_count + 1;
		end
		case(s_count)
		3'd4: begin
			w_r = 24'b 00000000_00000001_00000000;
			w_i = 24'b 00000000_00000000_00000000;
			end
		3'd5: begin
			w_r = 24'b 00000000_00000000_10110101;
			w_i = 24'b 11111111_11111111_01001011;
			end
		3'd6: begin
			w_r = 24'b 00000000_00000000_00000000;
			w_i = 24'b 11111111_11111111_00000000;
			end
		3'd7: begin
			w_r = 24'b 11111111_11111111_01001011;
			w_i = 24'b 11111111_11111111_01001011;
			end
		default: begin
			w_r = 24'b 00000000_00000001_00000000;
			w_i = 24'b 00000000_00000000_00000000;
			end
		endcase
	end
endmodule
module shift_8(
		input wire clk,
		input wire reset,
		input wire in_valid,
		input wire signed [23:0] din_r,
		input wire signed [23:0] din_i,
		output wire signed [23:0] dout_r,
		output wire signed [23:0] dout_i
	);
	integer i ;
	reg [191:0] shift_reg_r ;
	reg [191:0] shift_reg_i ;
	reg [191:0] tmp_reg_r ;
	reg [191:0] tmp_reg_i ;
	reg [4:0] counter_8,next_counter_8;
	reg valid,next_valid;

	assign dout_r    = shift_reg_r[191:168];
	assign dout_i    = shift_reg_i[191:168];

	always@(posedge clk or posedge reset)begin
		if(reset)begin
			shift_reg_r <= 0;
			shift_reg_i <= 0;
			counter_8   <= 0;
			valid       <= 0;
		end
		else 
		if (in_valid)begin
			counter_8        <= next_counter_8;
			shift_reg_r      <= (tmp_reg_r<<24) + din_r;
			shift_reg_i      <= (tmp_reg_i<<24) + din_i;
			valid            <= in_valid;
		end else if(valid)begin
			counter_8        <= next_counter_8;
			shift_reg_r      <= (tmp_reg_r<<24) + din_r;
			shift_reg_i      <= (tmp_reg_i<<24) + din_i;
			valid            <= next_valid;
		end
	end


	always@(*)begin
		next_counter_8 = counter_8 + 4'd1;
		tmp_reg_r = shift_reg_r;
		tmp_reg_i = shift_reg_i;
		next_valid = valid;
	end
endmodule
module shift_4(
		input wire clk,
		input wire reset,
		input wire in_valid,
		input wire signed [23:0] din_r,
		input wire signed [23:0] din_i,
		output wire signed [23:0] dout_r,
		output wire signed [23:0] dout_i
	);
	integer i ;
	reg [95:0] shift_reg_r ;
	reg [95:0] shift_reg_i ;
	reg [95:0] tmp_reg_r ;
	reg [95:0] tmp_reg_i ;
	reg [3:0] counter_4,next_counter_4;
	reg valid,next_valid;

	assign dout_r    = shift_reg_r[95:72];
	assign dout_i    = shift_reg_i[95:72];

	always@(posedge clk or posedge reset)begin
		if(reset)begin
			shift_reg_r <= 0;
			shift_reg_i <= 0;
			counter_4  <= 0;
			valid <= 0;
		end
		else 
		if (in_valid)begin
			counter_4        <= next_counter_4;
			shift_reg_r      <= (tmp_reg_r<<24) + din_r;
			shift_reg_i      <= (tmp_reg_i<<24) + din_i;
			valid            <= in_valid;
		end else if(valid)begin
			counter_4        <= next_counter_4;
			shift_reg_r      <= (tmp_reg_r<<24) + din_r;
			shift_reg_i      <= (tmp_reg_i<<24) + din_i;
			valid            <= next_valid;        
		end
	end
	
		always@(*)begin
		next_counter_4 = counter_4 + 3'd1;
		tmp_reg_r = shift_reg_r;
		tmp_reg_i = shift_reg_i;
		next_valid = valid;
	end


endmodule
module shift_2(
		input wire clk,
		input wire reset,
		input wire in_valid,
		input wire signed [23:0] din_r,
		input wire signed [23:0] din_i,
		output wire signed [23:0] dout_r,
		output wire signed [23:0] dout_i
	);
	integer i ;
	reg [47:0] shift_reg_r ;
	reg [47:0] shift_reg_i ;
	reg [47:0] tmp_reg_r ;
	reg [47:0] tmp_reg_i ;
	reg [2:0] counter_2,next_counter_2;
	reg valid,next_valid;

	assign dout_r    = shift_reg_r[47:24];
	assign dout_i    = shift_reg_i[47:24];

	always@(posedge clk or posedge reset)begin
		if(reset)begin
			shift_reg_r <= 0;
			shift_reg_i <= 0;
			counter_2  <= 0;
			valid <= 0;
		end
		else 
		if (in_valid)begin
			counter_2        <= next_counter_2;
			shift_reg_r      <= (tmp_reg_r<<24) + din_r;
			shift_reg_i      <= (tmp_reg_i<<24) + din_i;
			valid            <= in_valid;
		end else if(valid)begin
			counter_2        <= next_counter_2;
			shift_reg_r      <= (tmp_reg_r<<24) + din_r;
			shift_reg_i      <= (tmp_reg_i<<24) + din_i;
			valid            <= next_valid;
		end
	end
	
		always@(*)begin
		next_counter_2 = counter_2 + 2'd1;
		tmp_reg_r = shift_reg_r;
		tmp_reg_i = shift_reg_i;
		next_valid = valid;
	end

endmodule
module ROM_16(
		input wire clk,
		input wire in_valid,
		input wire reset,
		output reg [23:0] w_r,
		output reg [23:0] w_i,
		output reg[1:0] state
	);

	reg valid,next_valid;
	reg [5:0] count,next_count;

	always@(posedge clk or posedge reset)begin
		if(reset)begin
			count <= 0;
			valid <= 0;
		end
		else if(in_valid)
		begin
			count <= next_count;
			valid <= in_valid;
		end
		else if (valid)
		begin
			count <= next_count;
			valid <= next_valid;
		end
	end
	
		always @(*) begin
		if(in_valid || valid)next_count = count + 1;
		else next_count = count;
		
		if (count<6'd16) 
			state = 2'd0;
		else if (count >= 6'd16 && count < 6'd32)
			state = 2'd1;
		else if (count >= 6'd32 && count < 6'd48)
			state = 2'd2;
		else state = 2'd3;
		case(count)
		6'd32: begin
			w_r = 24'b 00000000_00000001_00000000;
			w_i = 24'b 00000000_00000000_00000000;
			next_valid = 1'b1;
			end
		6'd33: begin
			w_r = 24'b 00000000_00000000_11111011;
			w_i = 24'b 11111111_11111111_11001110;
			next_valid = 1'b1;
			end
		6'd34: begin
			w_r = 24'b 00000000_00000000_11101101;
			w_i = 24'b 11111111_11111111_10011110;
			next_valid = 1'b1;
			end
		6'd35: begin
			w_r = 24'b 00000000_00000000_11010101;
			w_i = 24'b 11111111_11111111_01110010;
			next_valid = 1'b1;
			end
		6'd36: begin
			w_r = 24'b 00000000_00000000_10110101;
			w_i = 24'b 11111111_11111111_01001011;
			next_valid = 1'b1;
			end
		6'd37: begin
			w_r = 24'b 00000000_00000000_10001110;
			w_i = 24'b 11111111_11111111_00101011;
			next_valid = 1'b1;
			end
		6'd38: begin
			w_r = 24'b 00000000_00000000_01100010;
			w_i = 24'b 11111111_11111111_00010011;
			next_valid = 1'b1;
			end
		6'd39: begin
			w_r = 24'b 00000000_00000000_00110010;
			w_i = 24'b 11111111_11111111_00000101;
			next_valid = 1'b1;
			end
		6'd40: begin
			w_r = 24'b 00000000_00000000_00000000;
			w_i = 24'b 11111111_11111111_00000000;
			next_valid = 1'b1;
			end
		6'd41: begin
			w_r = 24'b 11111111_11111111_11001110;
			w_i = 24'b 11111111_11111111_00000101;
			next_valid = 1'b1;
			end
		6'd42: begin
			w_r = 24'b 11111111_11111111_10011110;
			w_i = 24'b 11111111_11111111_00010011;
			next_valid = 1'b1;
			end
		6'd43: begin
			w_r = 24'b 11111111_11111111_01110010;
			w_i = 24'b 11111111_11111111_00101011;
			next_valid = 1'b1;
			end
		6'd44: begin
			w_r = 24'b 11111111_11111111_01001011;
			w_i = 24'b 11111111_11111111_01001011;
			next_valid = 1'b1;
			end
		6'd45: begin
			w_r = 24'b 11111111_11111111_00101011;
			w_i = 24'b 11111111_11111111_01110010;
			next_valid = 1'b1;
			end
		6'd46: begin
			w_r = 24'b 11111111_11111111_00010011;
			w_i = 24'b 11111111_11111111_10011110;
			next_valid = 1'b1;
			end
		6'd47: begin
			w_r = 24'b 11111111_11111111_00000101;
			w_i = 24'b 11111111_11111111_11001110;
			next_valid = 1'b0;
			end
		default: begin
			w_r = 24'b 00000000_00000001_00000000;
			w_i = 24'b 00000000_00000000_00000000;
			next_valid = 1'b1;
			end
		endcase
	end
endmodule
module radix2(
		input wire [1:0] state,
		input wire signed [23:0] din_a_r,
		input wire signed [23:0] din_a_i,
		input wire signed [23:0] din_b_r,//a
		input wire signed [23:0] din_b_i,//b
		input wire signed [23:0] w_r,//c
		input wire signed [23:0] w_i,//d
		output reg signed[23:0] op_r,
		output reg signed[23:0] op_i,
		output reg signed[23:0] delay_r,
		output reg signed[23:0] delay_i,
		output reg outvalid
	);

	reg signed [41:0] inter,mul_r,mul_i;//was 27
	reg signed [23:0] a,b,c,d;

	always@(*)begin
		op_r = 0;
		op_i = 0;
		delay_r = din_b_r;
		delay_i = din_b_i;
		case(state)
		2'b00:begin
		//waiting
		delay_r = din_b_r;
		delay_i = din_b_i;
		outvalid = 1'b0;
		end
		2'b01:begin
		//first half
		a = din_a_r + din_b_r;
		b = din_a_i + din_b_i;
		
		c = (din_a_r - din_b_r);//a-b
		d = (din_a_i - din_b_i);//a-b

		op_r = a;
		op_i = b;
		delay_r = c;
		delay_i = d;
		outvalid = 1'b1;
		end
		2'b10:begin
		//second half
		a = din_a_r;
		b = din_a_i;
		delay_r = din_b_r;
		delay_i = din_b_i;

		inter = b * (w_r - w_i); //b(c-d)
		mul_r  = w_r * (a - b) + inter;
		mul_i  = w_i * (a + b) + inter;

		op_r = (mul_r[31:8]);
		op_i = (mul_i[31:8]);
		outvalid = 1'b1;
		end
		2'b11:begin
		//disable
		outvalid = 1'b0;
		end
		default:begin
		delay_r = din_b_r;
		delay_i = din_b_i;
		end
		endcase
		
	end


endmodule
module shift_1(
		input wire clk,
		input wire reset,
		input wire in_valid,
		input signed [23:0] din_r,
		input signed [23:0] din_i,
		output signed [23:0] dout_r,
		output signed [23:0] dout_i
	);
	integer i ;
	reg [23:0] shift_reg_r ;
	reg [23:0] shift_reg_i ;
	reg [23:0] tmp_reg_r ;
	reg [23:0] tmp_reg_i ;
	reg [1:0] counter_1,next_counter_1;
	reg valid,next_valid;

	assign dout_r    = shift_reg_r[23:0];
	assign dout_i    = shift_reg_i[23:0];

	always@(posedge clk or posedge reset)begin
		if(reset)begin
			shift_reg_r <= 0;
			shift_reg_i <= 0;
			counter_1  <= 0;
			valid      <= 0;
		end
		else 
		if (in_valid)begin
			counter_1        <= next_counter_1;
			shift_reg_r      <= (tmp_reg_r<<24) + din_r;
			shift_reg_i      <= (tmp_reg_i<<24) + din_i;
			valid            <= in_valid;
		end else if(valid)begin
			counter_1        <= next_counter_1;
			shift_reg_r      <= (tmp_reg_r<<24) + din_r;
			shift_reg_i      <= (tmp_reg_i<<24) + din_i;
			valid            <= next_valid;
		end
	end
	
		always@(*)begin
		next_counter_1 = counter_1 + 2'd1;
		tmp_reg_r = shift_reg_r;
		tmp_reg_i = shift_reg_i;
		next_valid = valid;
	end

endmodule
module chip #
(
  parameter DMA_RX_INTERVAL = 32'd1999999,
  parameter UART_BAUD       = 32'd434
)(
  // input [31:0] test,
  input        FCLKIN_P,
  input        FCLKIN_N,
  input        FPGA_RESET,
  output [3:0] F_LED,

  output       PHY_RESET,
  // output       PHY_INT,

  output       PHY_TXC_GTXCLK,
  output       PHY_TXCLK,
  output [7:0] PHY_TXD,
  output       PHY_TXCTL_TXEN,
  output       PHY_TXER,

  input  [7:0] PHY_RXD,
  input        PHY_RXCTL_RXDV,
  input        PHY_RXER,
  input        PHY_RXCLK
);
	wire LOCKED;

  wire clk_125mhz;
  wire clk_200mhz;
  wire resetn_125mhz;
  wire resetn_200mhz;
	dcm _pll(.CLK_IN1_P(FCLKIN_P),.CLK_IN1_N(FCLKIN_N),
    .CLK_OUT1(clk_125mhz), .CLK_OUT2(clk_200mhz),.RESET(1'b0), .LOCKED(LOCKED)); 
	 
  reset_gen _reset_gen_125mhz
    (
    .clk(clk_125mhz), 
    .reset_async(FPGA_RESET & LOCKED), 
    .resetn(resetn_125mhz)
    );

  reset_gen _reset_gen_200mhz
    (
    .clk(clk_200mhz), 
    .reset_async(FPGA_RESET & LOCKED), 
    .resetn(resetn_200mhz)
    );

  wire [1:0] led;
  wire _tx;
  top #
    (
      .DMA_RX_INTERVAL (DMA_RX_INTERVAL),
      .UART_BAUD       (UART_BAUD)
    )
  _top
    (
      // .test        (test),
      .clk_125mhz         (clk_125mhz),
      .resetn_125mhz      (resetn_125mhz),

      .clk_200mhz         (clk_200mhz),
      .resetn_200mhz      (resetn_200mhz),

      .led         ({led, F_LED[1:0]}),
      .rxd         (1'b1),
      .txd         (_tx),

      .phy_rx_clk  (PHY_RXCLK),
      .phy_rxd     (PHY_RXD),
      .phy_rx_dv   (PHY_RXCTL_RXDV),
      .phy_rx_er   (PHY_RXER),

      .phy_gtx_clk (PHY_TXC_GTXCLK),
      .phy_tx_clk  (PHY_TXCLK),
      .phy_txd     (PHY_TXD),
      .phy_tx_en   (PHY_TXCTL_TXEN),
      .phy_tx_er   (PHY_TXER),

      .phy_reset_n (PHY_RESET)
    );

  assign F_LED[3] = _tx;
  assign F_LED[2] = 0;
endmodule
module reset_gen(
  input clk,
  input reset_async,
  output resetn
);

  reg [7:0] x = 8'hff;

  always @(posedge clk) begin
    if (!reset_async)
		x <= 8'hff;
	 else
      x <= {x[6:0], 1'b0};
  end
    
  assign resetn = !x[7];

endmodule
module mux_heap(
	input clk, resetn,

	output            mux_heap_valid,
	input             mux_heap_ready,
	output     [31:0] mux_heap_addr ,
	output     [31:0] mux_heap_wdata,
	output     [ 3:0] mux_heap_wstrb,
	input      [31:0] mux_heap_rdata,

	input    	      BUS_valid,
	output reg        BUS_ready,

	input             DMA_heap_valid,
	output            DMA_heap_ready,
	input      [31:0] DMA_heap_addr ,
	input      [31:0] DMA_heap_wdata,
	input      [ 3:0] DMA_heap_wstrb,
	output     [31:0] DMA_heap_rdata, 

	input             CPU_heap_valid,
	output            CPU_heap_ready,
	input      [31:0] CPU_heap_addr ,
	input      [31:0] CPU_heap_wdata,
	input      [ 3:0] CPU_heap_wstrb,
	output     [31:0] CPU_heap_rdata
);

	// reg BUS_valid_m1;
	always @(posedge clk) begin
		if (!resetn) begin
			// reset
			BUS_ready <= 0;
			// BUS_valid_m1 <= 0;
		end else begin
			// BUS_valid_m1 <= BUS_valid;
			if ((BUS_valid == 1) && (CPU_heap_valid == 0)) begin
				BUS_ready <= 1;
			end else if (BUS_valid == 0) begin
				BUS_ready <= 0;
			end
		end
	end

	assign mux_heap_valid = BUS_ready ? DMA_heap_valid : CPU_heap_valid;
	assign mux_heap_addr  = BUS_ready ? DMA_heap_addr  : CPU_heap_addr ;
	assign mux_heap_wdata = BUS_ready ? DMA_heap_wdata : CPU_heap_wdata;
	assign mux_heap_wstrb = BUS_ready ? DMA_heap_wstrb : CPU_heap_wstrb;

	assign DMA_heap_ready = BUS_ready ? mux_heap_ready : 0;
	assign CPU_heap_ready = BUS_ready ? 0 : mux_heap_ready;

	assign DMA_heap_rdata = BUS_ready ? mux_heap_rdata : 0;
	assign CPU_heap_rdata = BUS_ready ? 0 : mux_heap_rdata;

endmodule
module RAM_64KB(
  input clk, resetn,

  input            mem_valid,
  output reg          mem_ready,

  input     [31:0] mem_addr,
  input     [31:0] mem_wdata,
  input     [ 3:0] mem_wstrb,
  output reg   [31:0] mem_rdata
);

  wire [31:0] ram_rdata_0;
  wire [31:0] ram_rdata_1;
  wire [31:0] ram_rdata_2;
  wire [31:0] ram_rdata_3;

  wire [ 3:0] ram_wstrb0_w = (mem_addr[15:14] == 2'b00) ? mem_wstrb : 4'b0;
  wire [ 3:0] ram_wstrb1_w = (mem_addr[15:14] == 2'b01) ? mem_wstrb : 4'b0;
  wire [ 3:0] ram_wstrb2_w = (mem_addr[15:14] == 2'b10) ? mem_wstrb : 4'b0;
  wire [ 3:0] ram_wstrb3_w = (mem_addr[15:14] == 2'b11) ? mem_wstrb : 4'b0;

  reg  [ 3:0] ram_wstrb0;
  reg  [ 3:0] ram_wstrb1;
  reg  [ 3:0] ram_wstrb2;
  reg  [ 3:0] ram_wstrb3;

  reg  [ 3:0] ram_wstrb0_r;
  reg  [ 3:0] ram_wstrb1_r;
  reg  [ 3:0] ram_wstrb2_r;
  reg  [ 3:0] ram_wstrb3_r;

  reg ram_ready1, ram_ready2;
  reg mem_valid_reg;
  reg [31:0] mem_addr_reg0;
  reg [31:0] mem_addr_reg1;

  always @(posedge clk) begin
    ram_wstrb0_r <= ram_wstrb0_w ;
    ram_wstrb1_r <= ram_wstrb1_w ;
    ram_wstrb2_r <= ram_wstrb2_w ;
    ram_wstrb3_r <= ram_wstrb3_w ;
    ram_wstrb0 <= mem_valid_reg ? ram_wstrb0_r : 4'b0000;
    ram_wstrb1 <= mem_valid_reg ? ram_wstrb1_r : 4'b0000;
    ram_wstrb2 <= mem_valid_reg ? ram_wstrb2_r : 4'b0000;
    ram_wstrb3 <= mem_valid_reg ? ram_wstrb3_r : 4'b0000;
  end

  ram_4k_32 _ram_4k_32_0(clk, mem_addr[13:2],
    mem_wdata, ram_rdata_0, 
    ram_wstrb0,
    mem_valid);
  ram_4k_32 _ram_4k_32_1(clk, mem_addr[13:2],
    mem_wdata, ram_rdata_1, 
    ram_wstrb1,
    mem_valid);
  ram_4k_32 _ram_4k_32_2(clk, mem_addr[13:2],
    mem_wdata, ram_rdata_2, 
    ram_wstrb2,
    mem_valid);
  ram_4k_32 _ram_4k_32_3(clk, mem_addr[13:2],
    mem_wdata, ram_rdata_3, 
    ram_wstrb3,
    mem_valid);

  always @(posedge clk) begin
      if (!resetn) begin
        ram_ready2 <= 0;
        ram_ready1 <= 0;
        mem_valid_reg <= 0;
        mem_addr_reg0 <= 0;
        mem_addr_reg1 <= 0;
      end else begin
        if ((mem_valid == 1) && (mem_valid_reg == 0))
          ram_ready1 <= 1;
        if (ram_ready1)
          ram_ready1 <= 0;

        mem_valid_reg <= mem_valid;
        ram_ready2 <= ram_ready1;
        mem_addr_reg0 <= mem_addr;
        mem_addr_reg1 <= mem_addr_reg0;
      end
  end

  wire        mem_ready_w;
  wire [31:0] mem_rdata_w;

  assign mem_ready_w = (|mem_wstrb == 1) ? ram_ready1 : ram_ready2;

  reg [31:0] ram_rdata_0_reg0;
  reg [31:0] ram_rdata_1_reg0;
  reg [31:0] ram_rdata_2_reg0;
  reg [31:0] ram_rdata_3_reg0;

  always @(posedge clk) begin
    ram_rdata_0_reg0 <= ram_rdata_0;
    ram_rdata_1_reg0 <= ram_rdata_1;
    ram_rdata_2_reg0 <= ram_rdata_2;
    ram_rdata_3_reg0 <= ram_rdata_3;
  end

  assign mem_rdata_w =
              (mem_addr_reg1[15:14] == 2'b00) ? ram_rdata_0_reg0 : 
              (mem_addr_reg1[15:14] == 2'b01) ? ram_rdata_1_reg0 : 
              (mem_addr_reg1[15:14] == 2'b10) ? ram_rdata_2_reg0 : 
              (mem_addr_reg1[15:14] == 2'b11) ? ram_rdata_3_reg0 : 32'h 0000_0000 ;

  always @(posedge clk) begin
    mem_rdata <= mem_rdata_w;
    mem_ready <= mem_ready_w;
  end

endmodule
module IO(
  input clk, resetn,

  input            mem_valid,
  output reg       mem_ready,

  input     [31:0] mem_addr,
  input     [31:0] mem_wdata,
  input     [ 3:0] mem_wstrb,
  output reg   [31:0] mem_rdata,
  output    [ 3:0] io
);
  assign io = io_int;
  
  reg [3:0] io_int;
  reg       mem_valid_reg;

  always @(posedge clk) begin
    if (!resetn) begin
      io_int <= 0;
      mem_ready <= 0;
      mem_rdata <= 0;
      mem_valid_reg <= 0;
    end else begin
      if ((mem_valid == 1) && (mem_valid_reg == 0))
        mem_ready <= 1;
      if (mem_ready)
        mem_ready <= 0;

      mem_valid_reg <= mem_valid;

      if ((mem_valid == 1) && (mem_valid_reg == 0)) begin
        // rx_BD_adr
        if (mem_addr[7:2] == 6'h10) begin
          mem_rdata <= {28'd0, io_int};
          if (mem_wstrb==4'hF) io_int <= mem_wdata[3:0];
        end
      end
    end
  end

endmodule
module ram_4k_32(
  input clk,
  input [11:0] addr,
  input [31:0] din,
  output [31:0] dout,
  input [3:0] we,
  input en
);

  bram_4k_8 _bram0(clk, addr, din[7:0], dout[7:0], we[0], en);
  bram_4k_8 _bram1(clk, addr, din[15:8], dout[15:8], we[1], en);
  bram_4k_8 _bram2(clk, addr, din[23:16], dout[23:16], we[2], en);
  bram_4k_8 _bram3(clk, addr, din[31:24], dout[31:24], we[3], en);

endmodule
module bram_4k_8(
  input clk,
  input [11:0] addr,
  input [7:0] din,
  output reg [7:0] dout,
  input we,
  input en
);
  (* ram_style = "block" *)
  reg [7:0] mem[0:4095];
    always @(posedge clk)
    begin
        if (en)
        begin
            if (we)
            begin
                mem[addr] <= din;
                dout <= din;
            end
            else
                dout <= mem[addr];
        end
    end

endmodule
module testbench;
	reg clk = 1;
	reg resetn = 0;
	wire trap;

	always #5 clk = ~clk;

	initial begin
		repeat (100) @(posedge clk);
		resetn <= 1;
	end

	wire mem_valid;
	wire mem_instr;
	wire mem_ready;
	wire [31:0] mem_addr;
	wire [31:0] mem_wdata;
	wire [3:0] mem_wstrb;
	reg  [31:0] mem_rdata;

	wire mem_la_read;
	wire mem_la_write;
	wire [31:0] mem_la_addr;
	wire [31:0] mem_la_wdata;
	wire [3:0] mem_la_wstrb;

	picorv32 #(
		.BARREL_SHIFTER(1),
		.ENABLE_FAST_MUL(1),
		.ENABLE_DIV(1),
		.PROGADDR_RESET('h10000),
		.STACKADDR('h10000)
	) uut (
		.clk         (clk        ),
		.resetn      (resetn     ),
		.trap        (trap       ),
		.mem_valid   (mem_valid  ),
		.mem_instr   (mem_instr  ),
		.mem_ready   (mem_ready  ),
		.mem_addr    (mem_addr   ),
		.mem_wdata   (mem_wdata  ),
		.mem_wstrb   (mem_wstrb  ),
		.mem_rdata   (mem_rdata  ),
		.mem_la_read (mem_la_read ),
		.mem_la_write(mem_la_write),
		.mem_la_addr (mem_la_addr ),
		.mem_la_wdata(mem_la_wdata),
		.mem_la_wstrb(mem_la_wstrb)
	);

	reg [7:0] memory [0:256*1024-1];
	initial $readmemh("dhry.hex", memory);

	assign mem_ready = 1;

	always @(posedge clk) begin
		mem_rdata[ 7: 0] <= mem_la_read ? memory[mem_la_addr + 0] : 'bx;
		mem_rdata[15: 8] <= mem_la_read ? memory[mem_la_addr + 1] : 'bx;
		mem_rdata[23:16] <= mem_la_read ? memory[mem_la_addr + 2] : 'bx;
		mem_rdata[31:24] <= mem_la_read ? memory[mem_la_addr + 3] : 'bx;
		if (mem_la_write) begin
			case (mem_la_addr)
				32'h1000_0000: begin
`ifndef TIMING
					$write("%c", mem_la_wdata);
					$fflush();
`endif
				end
				default: begin
					if (mem_la_wstrb[0]) memory[mem_la_addr + 0] <= mem_la_wdata[ 7: 0];
					if (mem_la_wstrb[1]) memory[mem_la_addr + 1] <= mem_la_wdata[15: 8];
					if (mem_la_wstrb[2]) memory[mem_la_addr + 2] <= mem_la_wdata[23:16];
					if (mem_la_wstrb[3]) memory[mem_la_addr + 3] <= mem_la_wdata[31:24];
				end
			endcase
		end
	end

	initial begin
		$dumpfile("testbench.vcd");
		$dumpvars(0, testbench);
	end

	always @(posedge clk) begin
		if (resetn && trap) begin
			repeat (10) @(posedge clk);
			$display("TRAP");
			$finish;
		end
	end

`ifdef TIMING
	initial begin
		repeat (100000) @(posedge clk);
		$finish;
	end
	always @(posedge clk) begin
		if (uut.dbg_next)
			$display("## %-s %d", uut.dbg_ascii_instr ? uut.dbg_ascii_instr : "pcpi", uut.count_cycle);
	end
`endif
endmodule