dakies/OSS_Verilog huggingface dataset:
module ram_32_256 (
	aclr,
	clock,
	data,
	rdaddress,
	rden,
	wraddress,
	wren,
	q);

	input	  aclr;
	input	  clock;
	input	[31:0]  data;
	input	[7:0]  rdaddress;
	input	  rden;
	input	[7:0]  wraddress;
	input	  wren;
	output	[31:0]  q;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
	tri0	  aclr;
	tri1	  clock;
	tri1	  rden;
	tri0	  wren;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif

	wire [31:0] sub_wire0;
	wire [31:0] q = sub_wire0[31:0];

	altsyncram	altsyncram_component (
				.aclr0 (aclr),
				.address_a (wraddress),
				.address_b (rdaddress),
				.clock0 (clock),
				.data_a (data),
				.rden_b (rden),
				.wren_a (wren),
				.q_b (sub_wire0),
				.aclr1 (1'b0),
				.addressstall_a (1'b0),
				.addressstall_b (1'b0),
				.byteena_a (1'b1),
				.byteena_b (1'b1),
				.clock1 (1'b1),
				.clocken0 (1'b1),
				.clocken1 (1'b1),
				.clocken2 (1'b1),
				.clocken3 (1'b1),
				.data_b ({32{1'b1}}),
				.eccstatus (),
				.q_a (),
				.rden_a (1'b1),
				.wren_b (1'b0));
	defparam
		altsyncram_component.address_aclr_b = "CLEAR0",
		altsyncram_component.address_reg_b = "CLOCK0",
		altsyncram_component.clock_enable_input_a = "BYPASS",
		altsyncram_component.clock_enable_input_b = "BYPASS",
		altsyncram_component.clock_enable_output_b = "BYPASS",
		altsyncram_component.intended_device_family = "Stratix V",
		altsyncram_component.lpm_type = "altsyncram",
		altsyncram_component.numwords_a = 256,
		altsyncram_component.numwords_b = 256,
		altsyncram_component.operation_mode = "DUAL_PORT",
		altsyncram_component.outdata_aclr_b = "CLEAR0",
		altsyncram_component.outdata_reg_b = "CLOCK0",
		altsyncram_component.power_up_uninitialized = "FALSE",
		altsyncram_component.rdcontrol_reg_b = "CLOCK0",
		altsyncram_component.read_during_write_mode_mixed_ports = "DONT_CARE",
		altsyncram_component.widthad_a = 8,
		altsyncram_component.widthad_b = 8,
		altsyncram_component.width_a = 32,
		altsyncram_component.width_b = 32,
		altsyncram_component.width_byteena_a = 1;


endmodule
module EGRESS(
input clk,
input reset,

input in_tdma_pkt_wr,
input [133:0] in_tdma_pkt,
input in_tdma_valid_wr,
input in_tdma_valid,
output out_tdma_pkt_almostfull,

output  out_outputctrl_pkt_wr,
output  [133:0] out_outputctrl_pkt,
output  out_outputctrl_valid_wr,
output  out_outputctrl_valid,
input in_outputctrl_pkt_almostfull
);

EGRESS_OFFSET EGRESS_OFFSET(
.clk(clk),
.reset(reset),

.in_tdma_pkt_wr(in_tdma_pkt_wr),
.in_tdma_pkt(in_tdma_pkt),
.in_tdma_valid_wr(in_tdma_valid_wr),
.in_tdma_valid(in_tdma_valid),
.out_tdma_pkt_almostfull(out_tdma_pkt_almostfull),

.out_outputctrl_pkt_wr(out_outputctrl_pkt_wr),
.out_outputctrl_pkt(out_outputctrl_pkt),
.out_outputctrl_valid_wr(out_outputctrl_valid_wr),
.out_outputctrl_valid(out_outputctrl_valid),
.in_outputctrl_pkt_almostfull(in_outputctrl_pkt_almostfull)
);

endmodule
module INGRESS(
input clk,
input reset,

input in_inputctrl_pkt_wr,
input [133:0] in_inputctrl_pkt,
input in_inputctrl_valid_wr,
input in_inputctrl_valid,
output out_inputctrl_pkt_almostfull,

output out_class_key_wr,
output [133:0] out_class_key,
input in_class_key_almostfull,
output out_class_valid,
output out_class_valid_wr,

input in_class_key_wr,
input [133:0] in_class_key,
input in_class_valid_wr,
input in_class_valid,
output out_class_key_almostfull,

output out_dispather_pkt_wr,
output [133:0] out_dispather_pkt,
output out_dispather_valid_wr,
output out_dispather_valid,
input in_dispather_pkt_almostfull
);

wire out_offset_pkt_wr;
wire [133:0] out_offset_pkt;
wire out_offset_valid;
wire out_offset_valid_wr;
wire in_offset_pkt_almostfull;
INGRESS_CTRL INGRESS_CTRL(
.clk(clk),
.reset(reset),

.in_inputctrl_pkt_wr(in_inputctrl_pkt_wr),
.in_inputctrl_pkt(in_inputctrl_pkt),
.in_inputctrl_valid_wr(in_inputctrl_valid_wr),
.in_inputctrl_valid(in_inputctrl_valid),
.out_inputctrl_pkt_almostfull(out_inputctrl_pkt_almostfull),

.out_class_key_wr(out_class_key_wr),
.out_class_key(out_class_key),
.in_class_key_almostfull(in_class_key_almostfull),
.out_class_valid(out_class_valid),
.out_class_valid_wr(out_class_valid_wr),

.out_offset_pkt_wr(out_offset_pkt_wr),
.out_offset_pkt(out_offset_pkt),
.out_offset_valid(out_offset_valid),
.out_offset_valid_wr(out_offset_valid_wr),
.in_offset_pkt_almostfull(in_offset_pkt_almostfull)
);

INGRESS_OFFSET INGRESS_OFFSET(
.clk(clk),
.reset(reset),

.in_class_key_wr(in_class_key_wr),
.in_class_key(in_class_key),
.in_class_valid_wr(in_class_valid_wr),
.in_class_valid(in_class_valid),
.out_class_key_almostfull(out_class_key_almostfull),

.in_ingress_pkt_wr(out_offset_pkt_wr),
.in_ingress_pkt(out_offset_pkt),
.in_ingress_valid_wr(out_offset_valid_wr),
.in_ingress_valid(out_offset_valid),
.out_ingress_pkt_almostfull(in_offset_pkt_almostfull),

.out_dispather_pkt_wr(out_dispather_pkt_wr),
.out_dispather_pkt(out_dispather_pkt),
.out_dispather_valid_wr(out_dispather_valid_wr),
.out_dispather_valid(out_dispather_valid),
.in_dispather_pkt_almostfull(in_dispather_pkt_almostfull)
);

endmodule
module DISPATHER(
input clk,
input reset,

input in_ingress_pkt_wr,
input [133:0] in_ingress_pkt,
input in_ingress_valid_wr,
input in_ingress_valid,
output out_ingress_pkt_almostfull,

output out_rdma_pkt_wr,
output [133:0] out_rdma_pkt,
output out_rdma_valid_wr,
output out_rdma_valid,
input in_rdma_pkt_almostfull,
input [5:0] in_fpgaac_channel_num,
input in_fpgaac_cpuid_cs,//switch cpuid allocate mode 0:round robin   1:port bind
input [31:0] cpuid_valid,

input in_ppc_pkt_wr,
input [133:0] in_ppc_pkt,
input in_ppc_valid_wr,
input in_ppc_valid,
output out_ppc_pkt_almostfull,

output out_ppc_pkt_wr,
output [133:0] out_ppc_pkt,
output out_ppc_valid_wr,
output out_ppc_valid,
input in_ppc_pkt_almostfull
);


wire [4:0] in_cpuid;//id of cpu thread which pkt would be send to
wire in_cpuid_ack;
wire in_cpuid_valid;
wire out_cpuid_ctl;
wire [4:0] out_cpuid_key; 

wire in_input_pkt_wr;
wire [133:0] in_input_pkt;
wire in_input_valid_wr;
wire in_input_valid;
wire out_input_pkt_almostfull;
DISPATHER_INPUT DISPATHER_INPUT (
.clk(clk),
.reset(reset),

.in_cpuid(in_cpuid),//id of cpu thread which pkt would be send to
.in_cpuid_ack(in_cpuid_ack),
.in_cpuid_valid(in_cpuid_valid),
.out_cpuid_ctl(out_cpuid_ctl),
.out_cpuid_key(out_cpuid_key),

.in_ingress_pkt_wr(in_ingress_pkt_wr),
.in_ingress_pkt(in_ingress_pkt),
.in_ingress_valid_wr(in_ingress_valid_wr),
.in_ingress_valid(in_ingress_valid),
.out_ingress_pkt_almostfull(out_ingress_pkt_almostfull),

.out_output_pkt_wr(in_input_pkt_wr),
.out_output_pkt(in_input_pkt),
.out_output_valid_wr(in_input_valid_wr),
.out_output_valid(in_input_valid),
.in_output_pkt_almostfull(out_input_pkt_almostfull),

.out_ppc_pkt_wr(out_ppc_pkt_wr),
.out_ppc_pkt(out_ppc_pkt),
.out_ppc_valid_wr(out_ppc_valid_wr),
.out_ppc_valid(out_ppc_valid),
.in_ppc_pkt_almostfull(in_ppc_pkt_almostfull)
);

DISPATHER_CPUID DISPATHER_CPUID (//round robin mode & port bind mode
.clk(clk),
.reset(reset),

.in_fpgaac_cpuid_cs(in_fpgaac_cpuid_cs),
.in_fpgaac_channel_num(in_fpgaac_channel_num),
.cpuid_valid(cpuid_valid),
.out_input_cpuid(in_cpuid),//id of cpu thread which pkt would be send to
.out_input_ack(in_cpuid_ack),
.out_input_valid(in_cpuid_valid),
.in_input_ctl(out_cpuid_ctl),
.in_input_key(out_cpuid_key)
);

DISPATHER_OUTPUT DISPATHER_OUTPUT(
.clk(clk),
.reset(reset),

.in_input_pkt_wr(in_input_pkt_wr),
.in_input_pkt(in_input_pkt),
.in_input_valid_wr(in_input_valid_wr),
.in_input_valid(in_input_valid),
.out_input_pkt_almostfull(out_input_pkt_almostfull),

.in_ppc_pkt_wr(in_ppc_pkt_wr),
.in_ppc_pkt(in_ppc_pkt),
.in_ppc_valid_wr(in_ppc_valid_wr),
.in_ppc_valid(in_ppc_valid),
.out_ppc_pkt_almostfull(out_ppc_pkt_almostfull),

.out_rdma_pkt_wr(out_rdma_pkt_wr),
.out_rdma_pkt(out_rdma_pkt),
.out_rdma_valid_wr(out_rdma_valid_wr),
.out_rdma_valid(out_rdma_valid),
.in_rdma_pkt_almostfull(in_rdma_pkt_almostfull)
);
	
endmodule
module altera_tse_false_path_marker 
#(
   parameter MARKER_WIDTH = 1
)
(
   input    reset,
   input    clk,
   input    [MARKER_WIDTH - 1 : 0] data_in,
   output   [MARKER_WIDTH - 1 : 0] data_out
);

(* ALTERA_ATTRIBUTE = "-name SDC_STATEMENT \" set_false_path -to [get_registers *altera_tse_false_path_marker:*|data_out_reg*]\"" *)

(*preserve*) reg [MARKER_WIDTH - 1 : 0] data_out_reg;


assign data_out = data_out_reg;

always @(posedge clk or posedge reset) 
begin
   if (reset)
   begin
      data_out_reg <= {MARKER_WIDTH{1'b0}};
   end
   else
   begin
      data_out_reg <= data_in;
   end
end

endmodule
module altera_tse_reset_synchronizer
#(
    parameter ASYNC_RESET = 1,
    parameter DEPTH       = 2
)
(
    input   reset_in /* synthesis ALTERA_ATTRIBUTE = "SUPPRESS_DA_RULE_INTERNAL=\"R101,R105\"" */,

    input   clk,
    output  reset_out
);

    // -----------------------------------------------
    // Synchronizer register chain. We cannot reuse the
    // standard synchronizer in this implementation 
    // because our timing constraints are different.
    //
    // Instead of cutting the timing path to the d-input 
    // on the first flop we need to cut the aclr input.
    // 
    // We omit the "preserve" attribute on the final
    // output register, so that the synthesis tool can
    // duplicate it where needed.
    // -----------------------------------------------
    // Please check the false paths setting in TSE SDC
    
    (*preserve*) reg [DEPTH-1:0] altera_tse_reset_synchronizer_chain;
    reg altera_tse_reset_synchronizer_chain_out;

    generate if (ASYNC_RESET) begin

        // -----------------------------------------------
        // Assert asynchronously, deassert synchronously.
        // -----------------------------------------------
        always @(posedge clk or posedge reset_in) begin
            if (reset_in) begin
                altera_tse_reset_synchronizer_chain <= {DEPTH{1'b1}};
                altera_tse_reset_synchronizer_chain_out <= 1'b1;
            end
            else begin
                altera_tse_reset_synchronizer_chain[DEPTH-2:0] <= altera_tse_reset_synchronizer_chain[DEPTH-1:1];
                altera_tse_reset_synchronizer_chain[DEPTH-1] <= 0;
                altera_tse_reset_synchronizer_chain_out <= altera_tse_reset_synchronizer_chain[0];
            end
        end

        assign reset_out = altera_tse_reset_synchronizer_chain_out;
     
    end else begin

        // -----------------------------------------------
        // Assert synchronously, deassert synchronously.
        // -----------------------------------------------
        always @(posedge clk) begin
            altera_tse_reset_synchronizer_chain[DEPTH-2:0] <= altera_tse_reset_synchronizer_chain[DEPTH-1:1];
            altera_tse_reset_synchronizer_chain[DEPTH-1] <= reset_in;
            altera_tse_reset_synchronizer_chain_out <= altera_tse_reset_synchronizer_chain[0];
        end

        assign reset_out = altera_tse_reset_synchronizer_chain_out;
 
    end
    endgenerate

endmodule
module altera_tse_false_path_marker 
#(
   parameter MARKER_WIDTH = 1
)
(
   input    reset,
   input    clk,
   input    [MARKER_WIDTH - 1 : 0] data_in,
   output   [MARKER_WIDTH - 1 : 0] data_out
);

(*preserve*) reg [MARKER_WIDTH - 1 : 0] data_out_reg;


assign data_out = data_out_reg;

always @(posedge clk or posedge reset) 
begin
   if (reset)
   begin
      data_out_reg <= {MARKER_WIDTH{1'b0}};
   end
   else
   begin
      data_out_reg <= data_in;
   end
end

endmodule
module altera_tse_fake_master(
   // Clock and reset
   input clk,
   input reset,

   // Avalon MM master interface
   output [8:0] phy_mgmt_address,
   output phy_mgmt_read,
   input [31:0] phy_mgmt_readdata,
   output phy_mgmt_write,
   output reg [31:0] phy_mgmt_writedata,
   input phy_mgmt_waitrequest,

   // Serial data loopback control
   input sd_loopback
);

//////////////////////////////////internal registers and paramaters//////////////////////////////////
reg [1:0] state;
reg [1:0] next_state;
reg sd_loopback_r1, sd_loopback_r2;
reg bit_event;

localparam IDLE = 2'b0 ;
localparam WRITE_DATA = 2'b1;

////////////////////to detect the toggled data from sd_loopback //////////
always @ (posedge clk or posedge reset)
begin
   if (reset)
   begin
      sd_loopback_r1 <= 1'b0;
      sd_loopback_r2 <= 1'b0;
   end
   else
   begin
	   sd_loopback_r2 <= sd_loopback_r1;
	   sd_loopback_r1 <= sd_loopback;
   end
end 

// bit_event is the bit to remember there is an event happening at the sd_loopback
// and used to trigger IDLE -> WRITE_DATA state transition
// This bit is only cleared during WRITE_DATA -> IDLE transition and make sure that
// phy_mgmt_writedata[0] value is equal to sd_loopback data
// This is to ensure that our Avalon MM write transaction is always in sync with sd_loopback value
always @ (posedge clk or posedge reset)
begin 
   if (reset)
   begin
      bit_event <= 0;
   end
   else
   begin
      if ( sd_loopback_r1 != sd_loopback_r2)
      begin 
         bit_event <= 1'b1;
      end
      else
      begin
         if (next_state == IDLE && state == WRITE_DATA && phy_mgmt_writedata[0] == sd_loopback)
         begin 
            bit_event <= 1'b0;
         end
      end 
   end
end
   
// State machine
always @ (posedge clk or posedge reset)
begin 
     if (reset)
        state <= IDLE;
     else 
        state <= next_state;
end 

// next_state logic
always @ (*)
begin
	case (state)
	IDLE:
   begin
		if (bit_event)
		   next_state = WRITE_DATA;
		else 
		   next_state = IDLE;
   end
	WRITE_DATA:
   begin
		if (!phy_mgmt_waitrequest)
			next_state = IDLE;
		else
		   next_state = WRITE_DATA;
   end
	default : next_state = IDLE;
	endcase
end

// Connection to PHYIP (Avalon MM master signals)
assign phy_mgmt_write = (state == WRITE_DATA)? 1'b1 : 1'b0;
assign phy_mgmt_read = 1'b0;
assign phy_mgmt_address = (state == WRITE_DATA) ? 9'h61 : 9'h0;

always @(posedge clk or posedge reset)
begin
   if (reset)
   begin
      phy_mgmt_writedata <= 32'b0;
   end
   else
   begin
      if (state == IDLE && next_state == WRITE_DATA)
      begin
         phy_mgmt_writedata <= {31'b0, sd_loopback};
      end
      else if (state == WRITE_DATA && next_state == IDLE)
      begin
         phy_mgmt_writedata <= 32'b0;
      end
   end
end

endmodule
module  altera_wait_generate
//#(
//This code only works when wait_cycle =1, if need other case, you need to modify this code.
//please set wait_cycle default value as 1 to keep old design works.
//   parameter wait_cycle =1
//   ) 
(   
   input   wire         rst,
   input   wire         clk,
   input   wire		launch_signal,
   output   wire	wait_req
   );
reg launch_reg = 0;
reg wait_reg = 0;
always @ (posedge clk, posedge rst) begin
	if(rst) launch_reg <= 1'b0;
	else 	launch_reg <= launch_signal;
end
always @ (posedge clk, posedge rst) begin
	if(rst) wait_reg <= 1'b0;
	else 	wait_reg <= launch_signal & launch_reg & (! wait_reg & !wait_req);
end


// waitrequest should be asserted during reset - note that in the reconfig
// controller, reset is locally synchronized.  If you are using this module
// outside the reconfig controller, you may want to ensure that the reset
// signal is synchronized to prevent glitches, as waitrequest is not
// necessarily a registered output.
wire reset_sync;
alt_xcvr_resync #(.INIT_VALUE (1)) rst_sync (.clk(clk),.reset(rst),.d(1'b0),.q(reset_sync));

assign wait_req = reset_sync | (launch_signal & ~launch_reg) | (wait_reg & launch_signal ) ;
endmodule
module altera_tse_xcvr_resync #(
    parameter SYNC_CHAIN_LENGTH = 2,  // Number of flip-flops for retiming
    parameter WIDTH             = 1,  // Number of bits to resync
    parameter SLOW_CLOCK        = 0   // See description above
  ) (
  input   wire              clk,
  input   wire  [WIDTH-1:0] d,
  output  wire  [WIDTH-1:0] q
  );

localparam  INT_LEN   = (SYNC_CHAIN_LENGTH > 0) ? SYNC_CHAIN_LENGTH : 1;

genvar ig;

// Generate a synchronizer chain for each bit
generate begin
  for(ig=0;ig<WIDTH;ig=ig+1) begin : resync_chains
    wire                d_in;   // Input to sychronization chain.
    reg   [INT_LEN-1:0] r = {INT_LEN{1'b0}};
    wire  [INT_LEN  :0] next_r; // One larger real chain

    assign  q[ig]   = r[INT_LEN-1]; // Output signal
    assign  next_r  = {r,d_in};

    always @(posedge clk)
      r <= next_r[INT_LEN-1:0];

    // Generate asynchronous capture circuit if specified.
    if(SLOW_CLOCK == 0) begin
      assign  d_in = d[ig];
    end else begin
      wire  d_clk;
      reg   d_r;
      wire  clr_n;

      assign  d_clk = d[ig];
      assign  d_in  = d_r;
      assign  clr_n = ~q[ig] | d_clk; // Clear when output is logic 1 and input is logic 0

      // Asynchronously latch the input signal.
      always @(posedge d_clk or negedge clr_n)
        if(!clr_n)      d_r <= 1'b0;
        else if(d_clk)  d_r <= 1'b1;
    end // SLOW_CLOCK
  end // for loop
end // generate
endgenerate

endmodule
module  pll_vhdl_altpll
	( 
	clk,
	inclk,
	locked) /* synthesis synthesis_clearbox=1 */;
	output   [9:0]  clk;
	input   [1:0]  inclk;
	output   locked;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
	tri0   [1:0]  inclk;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif

	wire  [4:0]   wire_pll1_clk;
	wire  wire_pll1_fbout;
	wire  wire_pll1_locked;

	cycloneiv_pll   pll1
	( 
	.activeclock(),
	.clk(wire_pll1_clk),
	.clkbad(),
	.fbin(wire_pll1_fbout),
	.fbout(wire_pll1_fbout),
	.fref(),
	.icdrclk(),
	.inclk(inclk),
	.locked(wire_pll1_locked),
	.phasedone(),
	.scandataout(),
	.scandone(),
	.vcooverrange(),
	.vcounderrange()
	`ifndef FORMAL_VERIFICATION
	// synopsys translate_off
	`endif
	,
	.areset(1'b0),
	.clkswitch(1'b0),
	.configupdate(1'b0),
	.pfdena(1'b1),
	.phasecounterselect({3{1'b0}}),
	.phasestep(1'b0),
	.phaseupdown(1'b0),
	.scanclk(1'b0),
	.scanclkena(1'b1),
	.scandata(1'b0)
	`ifndef FORMAL_VERIFICATION
	// synopsys translate_on
	`endif
	);
	defparam
		pll1.bandwidth_type = "auto",
		pll1.clk0_divide_by = 1,
		pll1.clk0_duty_cycle = 50,
		pll1.clk0_multiply_by = 1,
		pll1.clk0_phase_shift = "0",
		pll1.clk1_divide_by = 5,
		pll1.clk1_duty_cycle = 50,
		pll1.clk1_multiply_by = 2,
		pll1.clk1_phase_shift = "0",
		pll1.inclk0_input_frequency = 8000,
		pll1.operation_mode = "no_compensation",
		pll1.pll_type = "auto",
		pll1.self_reset_on_loss_lock = "off",
		pll1.lpm_type = "cycloneiv_pll";
	assign
		clk = {{5{1'b0}}, wire_pll1_clk[4:0]},
		locked = wire_pll1_locked;
endmodule //pll_vhdl_altpll
module lms_ctr_sysid_qsys_0 (
               // inputs:
                address,
                clock,
                reset_n,

               // outputs:
                readdata
             )
;

  output  [ 31: 0] readdata;
  input            address;
  input            clock;
  input            reset_n;

  wire    [ 31: 0] readdata;
  //control_slave, which is an e_avalon_slave
  assign readdata = address ? 1455636742 : 4920;

endmodule
module altpcie_reconfig_3cgx (
	offset_cancellation_reset,
	reconfig_clk,
	reconfig_fromgxb,
	busy,
	reconfig_togxb)/* synthesis synthesis_clearbox = 2 */;

	input	  offset_cancellation_reset;
	input	  reconfig_clk;
	input	[4:0]  reconfig_fromgxb;
	output	  busy;
	output	[3:0]  reconfig_togxb;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
	tri0	  offset_cancellation_reset;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif

	wire [3:0] sub_wire0;
	wire  sub_wire1;
	wire [3:0] reconfig_togxb = sub_wire0[3:0];
	wire  busy = sub_wire1;

	altpcie_reconfig_3cgx_alt_c3gxb_reconfig_ffp	altpcie_reconfig_3cgx_alt_c3gxb_reconfig_ffp_component (
				.reconfig_clk (reconfig_clk),
				.offset_cancellation_reset (offset_cancellation_reset),
				.reconfig_fromgxb (reconfig_fromgxb),
				.reconfig_togxb (sub_wire0),
				.busy (sub_wire1))/* synthesis synthesis_clearbox=2
	 clearbox_macroname = alt_c3gxb_reconfig
	 clearbox_defparam = "cbx_blackbox_list=-lpm_mux;intended_device_family=Cyclone IV GX;number_of_channels=4;number_of_reconfig_ports=1;enable_buf_cal=true;reconfig_fromgxb_width=5;reconfig_togxb_width=4;" */;

endmodule
module  clkctrl_altclkctrl_0_sub
	( 
	ena,
	inclk,
	outclk) /* synthesis synthesis_clearbox=1 */;
	input   ena;
	input   [3:0]  inclk;
	output   outclk;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
	tri1   ena;
	tri0   [3:0]  inclk;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif

	wire  wire_clkctrl1_outclk;
	wire [1:0]  clkselect;
	wire  [1:0]  clkselect_wire;
	wire  [3:0]  inclk_wire;

	cycloneiv_clkctrl   clkctrl1
	( 
	.clkselect(clkselect_wire),
	.ena(ena),
	.inclk(inclk_wire),
	.outclk(wire_clkctrl1_outclk)
	// synopsys translate_off
	,
	.devclrn(1'b1),
	.devpor(1'b1)
	// synopsys translate_on
	);
	defparam
		clkctrl1.clock_type = "Global Clock",
		clkctrl1.ena_register_mode = "falling edge",
		clkctrl1.lpm_type = "cycloneiv_clkctrl";
	assign
		clkselect = {2{1'b0}},
		clkselect_wire = {clkselect},
		inclk_wire = {inclk},
		outclk = wire_clkctrl1_outclk;
endmodule //clkctrl_altclkctrl_0_sub
module tb_sdiv;
	
	reg			CLOCK100, CLOCK150, CLOCK65, RESET_N;
	
	always #1	CLOCK100 <= ~CLOCK100;
	always #1	CLOCK150 <= ~CLOCK150;
	always #2	CLOCK65 <= ~CLOCK65;
	//////////////////////////////////////////////////////////////////////
	initial
	begin
	
		#0			CLOCK100 = 0; CLOCK150 = 0; CLOCK65 = 0; RESET_N = 0; 
		#100		RESET_N = 1;
		/// 结束
		#200		$stop;
	end
	///////////////////////////////////////////////////////////////////////
	// 测试除法
	wire	signed	[31:0]	quotient;
	fixed_sdiv		fixed_sdiv_inst(.sys_clk(CLOCK100),.sys_rst_n(RESET_N),.numer(32765),.denom(-100),.quotient(quotient));
	
endmodule
module tb_cordic;
	
	reg			CLOCK100, CLOCK150, CLOCK65, RESET_N;
	
	always #1	CLOCK100 <= ~CLOCK100;
	always #1	CLOCK150 <= ~CLOCK150;
	always #2	CLOCK65 <= ~CLOCK65;
	///////////////////////////////////////////////////////////////////////
	// 首先 测试模运算
	wire					sys_clk = CLOCK100;
	wire					sys_rst_n = RESET_N;
	reg				[31:0]	mask;
	always @(posedge sys_clk)
		if(!sys_rst_n)
			mask <= 0;
		else if(mask<=200)
			mask <= mask + 1;
	reg		signed 	[63:0]	r_in_;
	reg						r_in_en_;
	always @(posedge sys_clk)
		if(mask<=200)
		begin
			r_in_ <= -65536*256;
			r_in_en_ <= 0;
		end
		else if(r_in_<65536*20000)
		begin
			r_in_ <= r_in_ + 32768;
			r_in_en_ <= 1;
		end
		else
		begin
			r_in_ <= -65536*20000;
			r_in_en_ <= 1;
		end
	
	
	wire	signed	[31:0]	ln_r_out_;	// 观察波形，ln(x)模块是11个clock的pipeline
	cordic_ln				cordic_ln_mdl(.sys_clk(sys_clk),.sys_rst_n(sys_rst_n),.r(r_in_),.ln_r(ln_r_out_));
	wire	signed	[31:0]	rho;
	wire	signed	[31:0]	phase;	// 观察波形，rotation模块是10个clock的pipeline
	cordic_rot				cordic_rot_mdl(.sys_clk(sys_clk),.sys_rst_n(sys_rst_n),.src_x(1024),.src_y(r_in_),.rho(rho),.theta(phase));
	// 验证exp指数运算函数
	wire	signed	[31:0]	rho_exp;
	cordic_exp_rtl			cordic_exp_rtl_inst(.sys_clk(sys_clk),.sys_rst_n(sys_rst_n),.src_x(r_in_),.rho(rho_exp));
	// 验证sigmoid函数
	wire	signed	[31:0]	rho_tanh_sigmoid;
	cordic_tanh_sigm_rtl	cordic_tanh_sigm_rtl(.sys_clk(sys_clk),.sys_rst_n(sys_rst_n),.src_x(r_in_), .rho(rho_tanh_sigmoid),.algorithm(2'B10));
	
	///////////////////////////////////////////////////////////////////////////
	// 记录
	reg				[15:0]	r_in_en_shifter;
	reg		signed	[31:0]	r_in_shifter	[0:15];
	integer p;
	always @(posedge sys_clk)
	begin
		r_in_en_shifter <= {r_in_en_shifter[14:0], r_in_en_};
		//
		for(p=1; p<16; p=p+1)
			r_in_shifter[p] <= r_in_shifter[p-1];
		r_in_shifter[0] <= r_in_;
	end
	
	wire	signed	[31:0]	r_in_shifter10 = r_in_shifter[10];
		
	integer	fp_ln;
	always @(posedge sys_clk)
		if(r_in_en_shifter[10])
			$fwrite(fp_ln, "%d, %d\n", r_in_shifter[10], ln_r_out_);
	//////////////////////////////////////////////////////////////////////
	initial
	begin
	
		#0			CLOCK100 = 0; CLOCK150 = 0; CLOCK65 = 0; RESET_N = 0; fp_ln = $fopen("./cordic_ln.txt", "w");
		#100		RESET_N = 1;
		/// 结束
		#1500000	$stop; $fclose(fp_ln);
	end
	
endmodule
module cordic_factor_exp_rom_ip (
	address,
	clock,
	q);

	input	[7:0]  address;
	input	  clock;
	output	[63:0]  q;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
	tri1	  clock;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif

	wire [63:0] sub_wire0;
	wire [63:0] q = sub_wire0[63:0];

	altsyncram	altsyncram_component (
				.address_a (address),
				.clock0 (clock),
				.q_a (sub_wire0),
				.aclr0 (1'b0),
				.aclr1 (1'b0),
				.address_b (1'b1),
				.addressstall_a (1'b0),
				.addressstall_b (1'b0),
				.byteena_a (1'b1),
				.byteena_b (1'b1),
				.clock1 (1'b1),
				.clocken0 (1'b1),
				.clocken1 (1'b1),
				.clocken2 (1'b1),
				.clocken3 (1'b1),
				.data_a ({64{1'b1}}),
				.data_b (1'b1),
				.eccstatus (),
				.q_b (),
				.rden_a (1'b1),
				.rden_b (1'b1),
				.wren_a (1'b0),
				.wren_b (1'b0));
	defparam
		altsyncram_component.address_aclr_a = "NONE",
		altsyncram_component.clock_enable_input_a = "BYPASS",
		altsyncram_component.clock_enable_output_a = "BYPASS",
		altsyncram_component.init_file = "../04_scripts/exp_cordic_factor_Kn.mif",
		altsyncram_component.intended_device_family = "Cyclone IV E",
		altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=YES,INSTANCE_NAME=ln",
		altsyncram_component.lpm_type = "altsyncram",
		altsyncram_component.numwords_a = 256,
		altsyncram_component.operation_mode = "ROM",
		altsyncram_component.outdata_aclr_a = "NONE",
		altsyncram_component.outdata_reg_a = "CLOCK0",
		altsyncram_component.widthad_a = 8,
		altsyncram_component.width_a = 64,
		altsyncram_component.width_byteena_a = 1;


endmodule
module cordic_factor_exp_rom_ip (
	address,
	clock,
	q);

	input	[7:0]  address;
	input	  clock;
	output	[63:0]  q;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
	tri1	  clock;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif

endmodule
module npu_inst_ram (
	data,
	rdaddress,
	rdclock,
	wraddress,
	wrclock,
	wren,
	q);

	input	[127:0]  data;
	input	[9:0]  rdaddress;
	input	  rdclock;
	input	[9:0]  wraddress;
	input	  wrclock;
	input	  wren;
	output	[127:0]  q;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
	tri1	  wrclock;
	tri0	  wren;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif

	wire [127:0] sub_wire0;
	wire [127:0] q = sub_wire0[127:0];

	altsyncram	altsyncram_component (
				.address_a (wraddress),
				.address_b (rdaddress),
				.clock0 (wrclock),
				.clock1 (rdclock),
				.data_a (data),
				.wren_a (wren),
				.q_b (sub_wire0),
				.aclr0 (1'b0),
				.aclr1 (1'b0),
				.addressstall_a (1'b0),
				.addressstall_b (1'b0),
				.byteena_a (1'b1),
				.byteena_b (1'b1),
				.clocken0 (1'b1),
				.clocken1 (1'b1),
				.clocken2 (1'b1),
				.clocken3 (1'b1),
				.data_b ({128{1'b1}}),
				.eccstatus (),
				.q_a (),
				.rden_a (1'b1),
				.rden_b (1'b1),
				.wren_b (1'b0));
	defparam
		altsyncram_component.address_aclr_b = "NONE",
		altsyncram_component.address_reg_b = "CLOCK1",
		altsyncram_component.clock_enable_input_a = "BYPASS",
		altsyncram_component.clock_enable_input_b = "BYPASS",
		altsyncram_component.clock_enable_output_b = "BYPASS",
		altsyncram_component.init_file = "../04_scripts/cnn_instruction_rom.mif",
		altsyncram_component.intended_device_family = "Cyclone IV E",
		altsyncram_component.lpm_type = "altsyncram",
		altsyncram_component.numwords_a = 1024,
		altsyncram_component.numwords_b = 1024,
		altsyncram_component.operation_mode = "DUAL_PORT",
		altsyncram_component.outdata_aclr_b = "NONE",
		altsyncram_component.outdata_reg_b = "CLOCK1",
		altsyncram_component.power_up_uninitialized = "FALSE",
		altsyncram_component.widthad_a = 10,
		altsyncram_component.widthad_b = 10,
		altsyncram_component.width_a = 128,
		altsyncram_component.width_b = 128,
		altsyncram_component.width_byteena_a = 1;


endmodule
module npu_inst_ram (
	data,
	rdaddress,
	rdclock,
	wraddress,
	wrclock,
	wren,
	q);

	input	[127:0]  data;
	input	[9:0]  rdaddress;
	input	  rdclock;
	input	[9:0]  wraddress;
	input	  wrclock;
	input	  wren;
	output	[127:0]  q;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
	tri1	  wrclock;
	tri0	  wren;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif

endmodule
module cordic_int_part_exp_rom_ip (
	address,
	clock,
	q);

	input	[7:0]  address;
	input	  clock;
	output	[31:0]  q;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
	tri1	  clock;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif

	wire [31:0] sub_wire0;
	wire [31:0] q = sub_wire0[31:0];

	altsyncram	altsyncram_component (
				.address_a (address),
				.clock0 (clock),
				.q_a (sub_wire0),
				.aclr0 (1'b0),
				.aclr1 (1'b0),
				.address_b (1'b1),
				.addressstall_a (1'b0),
				.addressstall_b (1'b0),
				.byteena_a (1'b1),
				.byteena_b (1'b1),
				.clock1 (1'b1),
				.clocken0 (1'b1),
				.clocken1 (1'b1),
				.clocken2 (1'b1),
				.clocken3 (1'b1),
				.data_a ({32{1'b1}}),
				.data_b (1'b1),
				.eccstatus (),
				.q_b (),
				.rden_a (1'b1),
				.rden_b (1'b1),
				.wren_a (1'b0),
				.wren_b (1'b0));
	defparam
		altsyncram_component.address_aclr_a = "NONE",
		altsyncram_component.clock_enable_input_a = "BYPASS",
		altsyncram_component.clock_enable_output_a = "BYPASS",
		altsyncram_component.init_file = "../04_scripts/exp_cordic_int_part.mif",
		altsyncram_component.intended_device_family = "Cyclone IV E",
		altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=YES,INSTANCE_NAME=expi",
		altsyncram_component.lpm_type = "altsyncram",
		altsyncram_component.numwords_a = 256,
		altsyncram_component.operation_mode = "ROM",
		altsyncram_component.outdata_aclr_a = "NONE",
		altsyncram_component.outdata_reg_a = "CLOCK0",
		altsyncram_component.widthad_a = 8,
		altsyncram_component.width_a = 32,
		altsyncram_component.width_byteena_a = 1;


endmodule
module cordic_int_part_exp_rom_ip (
	address,
	clock,
	q);

	input	[7:0]  address;
	input	  clock;
	output	[31:0]  q;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
	tri1	  clock;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif

endmodule
module cordic_factor_Kn_rom_ip (
	address,
	clock,
	q);

	input	[7:0]  address;
	input	  clock;
	output	[63:0]  q;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
	tri1	  clock;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif

	wire [63:0] sub_wire0;
	wire [63:0] q = sub_wire0[63:0];

	altsyncram	altsyncram_component (
				.address_a (address),
				.clock0 (clock),
				.q_a (sub_wire0),
				.aclr0 (1'b0),
				.aclr1 (1'b0),
				.address_b (1'b1),
				.addressstall_a (1'b0),
				.addressstall_b (1'b0),
				.byteena_a (1'b1),
				.byteena_b (1'b1),
				.clock1 (1'b1),
				.clocken0 (1'b1),
				.clocken1 (1'b1),
				.clocken2 (1'b1),
				.clocken3 (1'b1),
				.data_a ({64{1'b1}}),
				.data_b (1'b1),
				.eccstatus (),
				.q_b (),
				.rden_a (1'b1),
				.rden_b (1'b1),
				.wren_a (1'b0),
				.wren_b (1'b0));
	defparam
		altsyncram_component.address_aclr_a = "NONE",
		altsyncram_component.clock_enable_input_a = "BYPASS",
		altsyncram_component.clock_enable_output_a = "BYPASS",
		altsyncram_component.init_file = "../04_scripts/cordic_factor_Kn.mif",
		altsyncram_component.intended_device_family = "Cyclone IV E",
		altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=YES,INSTANCE_NAME=cort",
		altsyncram_component.lpm_type = "altsyncram",
		altsyncram_component.numwords_a = 256,
		altsyncram_component.operation_mode = "ROM",
		altsyncram_component.outdata_aclr_a = "NONE",
		altsyncram_component.outdata_reg_a = "CLOCK0",
		altsyncram_component.widthad_a = 8,
		altsyncram_component.width_a = 64,
		altsyncram_component.width_byteena_a = 1;


endmodule
module cordic_factor_Kn_rom_ip (
	address,
	clock,
	q);

	input	[7:0]  address;
	input	  clock;
	output	[63:0]  q;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
	tri1	  clock;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif

endmodule
module npu_inst_ram_bak (
	address,
	clock,
	data,
	wren,
	q);

	input	[9:0]  address;
	input	  clock;
	input	[127:0]  data;
	input	  wren;
	output	[127:0]  q;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
	tri1	  clock;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif

endmodule
module npu_inst_ram_bak (
	address,
	clock,
	data,
	wren,
	q);

	input	[9:0]  address;
	input	  clock;
	input	[127:0]  data;
	input	  wren;
	output	[127:0]  q;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
	tri1	  clock;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif

	wire [127:0] sub_wire0;
	wire [127:0] q = sub_wire0[127:0];

	altsyncram	altsyncram_component (
				.address_a (address),
				.clock0 (clock),
				.data_a (data),
				.wren_a (wren),
				.q_a (sub_wire0),
				.aclr0 (1'b0),
				.aclr1 (1'b0),
				.address_b (1'b1),
				.addressstall_a (1'b0),
				.addressstall_b (1'b0),
				.byteena_a (1'b1),
				.byteena_b (1'b1),
				.clock1 (1'b1),
				.clocken0 (1'b1),
				.clocken1 (1'b1),
				.clocken2 (1'b1),
				.clocken3 (1'b1),
				.data_b (1'b1),
				.eccstatus (),
				.q_b (),
				.rden_a (1'b1),
				.rden_b (1'b1),
				.wren_b (1'b0));
	defparam
		altsyncram_component.clock_enable_input_a = "BYPASS",
		altsyncram_component.clock_enable_output_a = "BYPASS",
		altsyncram_component.intended_device_family = "Cyclone IV E",
		altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=YES,INSTANCE_NAME=inst",
		altsyncram_component.lpm_type = "altsyncram",
		altsyncram_component.numwords_a = 1024,
		altsyncram_component.operation_mode = "SINGLE_PORT",
		altsyncram_component.outdata_aclr_a = "NONE",
		altsyncram_component.outdata_reg_a = "CLOCK0",
		altsyncram_component.power_up_uninitialized = "FALSE",
		altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ",
		altsyncram_component.widthad_a = 10,
		altsyncram_component.width_a = 128,
		altsyncram_component.width_byteena_a = 1;


endmodule
module alt_pll_ip_core (
	inclk0,
	c0,
	c1,
	c2,
	c3,
	c4);

	input	  inclk0;
	output	  c0;
	output	  c1;
	output	  c2;
	output	  c3;
	output	  c4;

endmodule
module npu_paras_rom (
	address,
	clock,
	q);

	input	[15:0]  address;
	input	  clock;
	output	[31:0]  q;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
	tri1	  clock;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif

	wire [31:0] sub_wire0;
	wire [31:0] q = sub_wire0[31:0];

	altsyncram	altsyncram_component (
				.address_a (address),
				.clock0 (clock),
				.q_a (sub_wire0),
				.aclr0 (1'b0),
				.aclr1 (1'b0),
				.address_b (1'b1),
				.addressstall_a (1'b0),
				.addressstall_b (1'b0),
				.byteena_a (1'b1),
				.byteena_b (1'b1),
				.clock1 (1'b1),
				.clocken0 (1'b1),
				.clocken1 (1'b1),
				.clocken2 (1'b1),
				.clocken3 (1'b1),
				.data_a ({32{1'b1}}),
				.data_b (1'b1),
				.eccstatus (),
				.q_b (),
				.rden_a (1'b1),
				.rden_b (1'b1),
				.wren_a (1'b0),
				.wren_b (1'b0));
	defparam
		altsyncram_component.address_aclr_a = "NONE",
		altsyncram_component.clock_enable_input_a = "BYPASS",
		altsyncram_component.clock_enable_output_a = "BYPASS",
		altsyncram_component.init_file = "../04_scripts/cnn_parameter_rom.mif",
		altsyncram_component.intended_device_family = "Cyclone IV E",
		altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=YES,INSTANCE_NAME=cpar",
		altsyncram_component.lpm_type = "altsyncram",
		altsyncram_component.numwords_a = 65536,
		altsyncram_component.operation_mode = "ROM",
		altsyncram_component.outdata_aclr_a = "NONE",
		altsyncram_component.outdata_reg_a = "CLOCK0",
		altsyncram_component.widthad_a = 16,
		altsyncram_component.width_a = 32,
		altsyncram_component.width_byteena_a = 1;


endmodule
module npu_paras_rom (
	address,
	clock,
	q);

	input	[15:0]  address;
	input	  clock;
	output	[31:0]  q;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
	tri1	  clock;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif

endmodule
module sync_dual_clock
#(
parameter	WIDTH = 6,			// 带同步的数据宽度
parameter	SYNC_STAGE = 2		// 同步的级数（级数越多，竞争冒险越少）
)
(
input	wire				clock_dst,
input	wire	[WIDTH-1:0]	src,
output	wire	[WIDTH-1:0]	dst
);

//
reg		[WIDTH-1:0]			sync_reg	[0:SYNC_STAGE-1];
integer p;
always @(posedge clock_dst)
begin
	sync_reg[0] <= src;
	for(p=1; p<SYNC_STAGE; p=p+1)
		sync_reg[p] <= sync_reg[p-1];
end

assign						dst = sync_reg[SYNC_STAGE-1];	// 输出

endmodule
module gray_enc_1p
#(
parameter	WIDTH = 6			// 宽度
)
(
input		wire					clock,	// 时钟
input		wire	[WIDTH-1:0]		src,	// 源数据
output		reg		[WIDTH-1:0]		dst		// 目标数据
);

// 
integer	p;
reg		[WIDTH-1:0]	dst_x;
always @(*)
begin
	dst_x[WIDTH-1] = src[WIDTH-1];		// g[N-1] = b[N-1]
	for(p=WIDTH-2; p>=0; p=p-1)
	begin
		dst_x[p] = src[p]^src[p+1];		// g[n] = b[n]^b[n+1]	, 0 <= n <= N-2
	end
end

// 输出打一拍
always @(posedge clock)
	dst <= dst_x;

endmodule
module gray_dec_1p
#(
parameter	WIDTH = 6			// 宽度
)
(
input		wire					clock,	// 时钟
input		wire	[WIDTH-1:0]		src,	// 源数据
output		reg		[WIDTH-1:0]		dst		// 目标数据
);

// 
integer	p;
reg		[WIDTH-1:0]	dst_x;
always @(*)
begin
	dst_x[WIDTH-1] = src[WIDTH-1];		// b[N-1] = g[N-1]
	for(p=WIDTH-2; p>=0; p=p-1)
	begin
		dst_x[p] = src[p]^dst_x[p+1];		// b[n] = g[n]^b[n+1]	, 0 <= n <= N-2
	end
end

// 输出打一拍
always @(posedge clock)
	dst <= dst_x;

endmodule
module npu_paras_config
#(parameter	DATA_WIDTH = 32,    // 数据位宽
  parameter	FRAC_WIDTH = 16,	// 小数部分
  parameter RAM_LATENCY = 2,	// ram的IP核读取需要延时
  parameter	PARA_BIAS = 32'H00010000	// CNN参数的偏移地址
)
(
	input	wire						clk, rst_n,	// 时钟和复位信号
	input	wire						npu_paras_en,	// 使能配置
	output	wire						npu_paras_ready,	// CNN参数配置空闲
	input	wire	[DATA_WIDTH-1:0]	npu_paras_q,	// CNN的参数
	output	reg		[DATA_WIDTH-1:0]	npu_paras_addr,	// CNN参数的地址
	// DDR接口
	output	wire						DDR_WRITE_CLK,
	output	wire	[DATA_WIDTH-1:0]	DDR_WRITE_ADDR,
	output	wire	[DATA_WIDTH-1:0]	DDR_WRITE_DATA,
	output	wire						DDR_WRITE_REQ,
	input	wire						DDR_WRITE_READY
);
	
	reg		[31:0]	ddr_write_addr;
	reg				ddr_write_req;
	wire			ddr_write_ready;
	reg		[31:0]	ddr_write_data;
	///////////
	assign			DDR_WRITE_CLK = clk;
	assign			DDR_WRITE_ADDR = ddr_write_addr;
	assign			DDR_WRITE_DATA = ddr_write_data;
	assign			DDR_WRITE_REQ = ddr_write_req;
	assign			ddr_write_ready = DDR_WRITE_READY;
	
	wire			ddr_write_data_valid = ddr_write_ready && ddr_write_req;	// 表示一次数据成功写入
	//
	// 检测 npu_paras_en 上升沿
	reg				npu_paras_enx;
	always @(posedge clk)
		npu_paras_enx <= npu_paras_en;
	wire			npu_paras_en_up = (!npu_paras_enx && npu_paras_en);	// 上升沿
	//
	reg		[3:0]	cstate;
	reg		[31:0]	delay;
	reg		[31:0]	total_paras_num;	// 所有的参数数量
	always @(posedge clk)
		if(!rst_n)
		begin
			cstate <= 0;
			delay <= 0;
			npu_paras_addr <= 0;
			ddr_write_req <= 0;	// 撤销DDR写入使能
		end
		else
		begin
			case(cstate)
				0: begin
					if(npu_paras_en_up)
					begin
						cstate <= 1;
						npu_paras_addr <= 0;
						delay <= 0;
					end
					//
					ddr_write_req <= 0;	// 撤销DDR写入使能
				end
				// 等待RAM读取完成
				1: begin
					if(delay>RAM_LATENCY)
					begin
						cstate <= 2;	// 进入逐步读取所有参数
						total_paras_num <= npu_paras_q;	// 获取参数数量
						delay <= 0;
						ddr_write_addr <= PARA_BIAS;
					end
					else
						delay <= delay + 1;
					///////	
					ddr_write_req <= 0;	// 撤销DDR写入使能
				end
				// 逐步读取所有的参数
				2: begin
					if(npu_paras_addr>total_paras_num)
					begin
						cstate <= 0;
						npu_paras_addr <= 0;
						delay <= 0;
					end
					else
					begin
						cstate <= 3;	// 进入读取RAM的等待阶段
						npu_paras_addr <= npu_paras_addr + 1;
						delay <= 0;
					end
					ddr_write_req <= 0;	// 撤销DDR写入使能
				end
				// 等待参数读取出来
				3: begin
					if(delay>RAM_LATENCY)
					begin
						cstate <= 4;	// 进入写入DDR的状态
						ddr_write_data <= npu_paras_q;
						ddr_write_req <= 1;	// 写入DDR，然后等待写入完成
						delay <= 0;
					end
					else
						delay <= delay + 1;
				end
				// 等待参数写入DDR完成
				4: begin
					if(ddr_write_ready)
					begin
						ddr_write_req <= 0;	// 撤销DDR写入使能
						ddr_write_addr <= ddr_write_addr + 1;	// DDR写入地址+1
						cstate <= 2;	// 进入读取下一个参数的任务
					end
				end
				//
				default: begin
					cstate <= 0;
					delay <= 0;
					npu_paras_addr <= 0;
					ddr_write_req <= 0;	// 撤销DDR写入使能
				end
				
			endcase
		
		end
	/////////////////////////////////////////////////////////
	assign	npu_paras_ready = (cstate==0);
	////////////////////////////////////////////////////
endmodule
module npu_inst_join
(
	input	wire			npu_inst_clk, npu_inst_rst_n,
	input	wire	[31:0]	npu_inst_part,
	input	wire			npu_inst_part_en,
	output	reg		[127:0]	npu_inst,
	output	reg				npu_inst_en
);

	wire	RESETN = npu_inst_rst_n;
	// 生成npu_inst/npu_inst_en
	// 要用状态机来生成
	reg		[3:0]	npu_inst_state;
	reg		[31:0]	npu_inst_delay;	// 延时计数单元，如果超时了，就说明指令传输完成
	always @(posedge npu_inst_clk)
		if(!RESETN)
		begin
			npu_inst_state <= 0;
			npu_inst <= 0;
			npu_inst_en <= 0;
			npu_inst_delay <= 0;
		end
		else
		begin
			case(npu_inst_state)
				0: begin
					if(npu_inst_part_en)
					begin
						npu_inst <= {npu_inst[95:0], npu_inst_part};
						npu_inst_en <= 0;
						npu_inst_state <= 1;
						npu_inst_delay <= 0;
					end
				end
				
				// 等待超时了，就说明指令传输完成
				1: begin
					if(npu_inst_part_en)
					begin
						npu_inst <= {npu_inst[95:0], npu_inst_part};
						npu_inst_en <= 0;
						npu_inst_delay <= 0;
					end
					else if(npu_inst_delay>=2000000)	// 40ms超时等待机制
					begin
						npu_inst_en <= 1;
						npu_inst_state <= 2;
						npu_inst_delay <= 0;
					end
					else 
						npu_inst_delay <= npu_inst_delay + 1;	// 超时等待计数器++
				end
				
				// 
				2: begin
					npu_inst_en <= 0;
					npu_inst_state <= 0;
				end
				
				default: begin
					npu_inst_state <= 0;
					npu_inst <= 0;
					npu_inst_en <= 0;
					npu_inst_delay <= 0;
				end
				
			endcase
		end
		
endmodule
module dpram_2p
#(
parameter	LOG2N = 6,				// 这是FIFO深度的对数值
parameter	N = (1<<LOG2N),			// FIFO的深度
parameter	DATA_WIDTH = 32,		// 数据宽度
parameter	ADDR_WIDTH = LOG2N 		// 地址宽度
)
(

input  	wire						aclr,			// 异步复位
// 写入端口的信号线
input	wire						wrclock,		// 写时钟
input	wire	[DATA_WIDTH-1:0]	data,			// 写数据
input	wire						wrreq,			// 写请求
input	wire	[ADDR_WIDTH-1:0]	wraddr,			// 写地址
// 读取端口的信号线
input	wire						rdclock,		// 读时钟
output	reg		[DATA_WIDTH-1:0]	q,				// 读数据
input	wire						rdreq,			// 读请求
input	wire	[ADDR_WIDTH-1:0]	rdaddr			// 读地址
);

/*-------------------------------------------------------------------------*\
	signals
\*-------------------------------------------------------------------------*/

// 首先声明一块内存空间
reg		[DATA_WIDTH-1:0]			dpram	[0:N-1];	// 内存空间，试图转换成DPRAM
reg		[ADDR_WIDTH-1:0]			wraddrx;			// 写入地址
reg		[DATA_WIDTH-1:0]			datax;
reg									wrreqx;
reg									rdreqx;
reg		[ADDR_WIDTH-1:0]			rdaddrx;			// 读取地址


/*-------------------------------------------------------------------------*\
	timing
\*-------------------------------------------------------------------------*/

/*
	for writing:
		wrclock		_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|-
		wraddr		 ____| a1| a2| a3| a4| a5| a6| a7| a8| a9|________
		data		 ____| d1| d2| d3| d4| d5| d6| d7| d8| d9|________
		wrreq		 ____|-----------------------------------|_______
		
	for reading:
		rdclock		_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|-
		rdaddr		 ____| a1| a2| a3| a4| a5| a6| a7| a8| a9|________
		rdreq		 ____|-----------------------------------|_______
		rdaddrx		_________| a1| a2| a3| a4| a5| a6| a7| a8| a9|________
		rdreqx		_________|-----------------------------------|_______
		q			 	_________| d1| d2| d3| d4| d5| d6| d7| d8| d9|___
	
*/

/*-------------------------------------------------------------------------*\
	process
\*-------------------------------------------------------------------------*/
// 首先是写入地址生成
always @(posedge wrclock or posedge aclr)
	if(aclr==1)
	begin
		wraddrx <= 0;
		wrreqx 	<= 0;
		datax 	<= 0;
	end
	else
	begin
		wraddrx <= wraddr;
		wrreqx 	<= wrreq;
		datax 	<= data;
	end
		
// 然后是读取地址生成
always @(posedge rdclock or posedge aclr)
	if(aclr==1)
	begin
		rdaddrx <= 0;
		rdreqx 	<= 0;
	end
	else
	begin
		rdaddrx <= rdaddr;
		rdreqx 	<= rdreq;
	end
		
// 现在是内存的行为
// 写入
always @(posedge wrclock)
	if(wrreqx==1)
		dpram[wraddrx[ADDR_WIDTH-1:0]] <= datax;
// 读取
always @(posedge rdclock)
	if(rdreqx==1)
		q <= dpram[rdaddrx[ADDR_WIDTH-1:0]];
//

//////////////////////////////////////////////////////////////

endmodule
module fixed_sdiv
#(parameter	DATA_WIDTH = 32,    // 数据位宽
  parameter	FRAC_WIDTH = 16,	// 小数部分
  parameter	DATA_UNIT = {{(DATA_WIDTH-FRAC_WIDTH-1){1'B0}}, 1'B1, {FRAC_WIDTH{1'B0}}}, // 固定的单位1 
  parameter	DATA_ZERO = {DATA_WIDTH{1'B0}},	// 固定的0值
  parameter	PERIOD = ((DATA_WIDTH+FRAC_WIDTH)>>1)
)
(
	input	wire	sys_clk, sys_rst_n,		// 模块的时钟、复位信号
	//
	input	wire	[DATA_WIDTH-1:0]	numer,
	input	wire	[DATA_WIDTH-1:0]	denom,
	input	wire						src_en,
	output	reg		[DATA_WIDTH-1:0]	quotient,
	output	reg							dst_en
);

	// 首先输入的翻转
	wire	[DATA_WIDTH-1:0]	numer_pos;
	wire	[DATA_WIDTH-1:0]	denom_pos;
	assign	numer_pos = numer[DATA_WIDTH-1]? (~numer+1) : numer;
	assign	denom_pos = denom[DATA_WIDTH-1]? (~denom+1) : denom;
	
	// 迭代运算
	// 考虑到radix-2算法太消耗面积，而且总的clock周期太多
	// 这里采用radix-4的算法
	reg							src_enx			[0:PERIOD];
	reg		[2*DATA_WIDTH-1:0]	denom_tmp		[0:PERIOD];
	reg		[2*DATA_WIDTH-1:0]	numer_tmp		[0:PERIOD];
	reg							result_polar	[0:PERIOD];
	reg		[2*DATA_WIDTH-1:0]	judge_0			[0:PERIOD];	// 比较numer_tmp和denom_tmp
	reg		[2*DATA_WIDTH-1:0]	judge_1			[0:PERIOD];	// 比较numer_tmp和denom_tmp
	reg		[2*DATA_WIDTH-1:0]	judge_2			[0:PERIOD];	// 比较numer_tmp和denom_tmp
	reg		[2*DATA_WIDTH-1:0]	judge_3			[0:PERIOD];	// 比较numer_tmp和denom_tmp
	reg		[3:0]				_judge_			[0:PERIOD];	// 比较numer_tmp和denom_tmp
	// 要将比较器和减法器实现资源复用（FPGA内比较器就是减法器）
	integer q;
	always @(*)
	begin
		for(q=0; q<PERIOD; q=q+1)
		begin
			judge_0[q] = ({numer_tmp[q], 2'B00}-denom_tmp[q]);
			judge_1[q] = ({numer_tmp[q], 2'B00}-(denom_tmp[q]<<1));
			judge_2[q] = ({numer_tmp[q], 2'B00}-(denom_tmp[q] + (denom_tmp[q]<<1)));
			judge_3[q] = ({numer_tmp[q], 2'B00}-(denom_tmp[q]<<2));
			_judge_[q] = {judge_3[q][2*DATA_WIDTH-1], judge_2[q][2*DATA_WIDTH-1], judge_1[q][2*DATA_WIDTH-1], judge_0[q][2*DATA_WIDTH-1]};
		end
	end
	//assign	result_polar = denom[DATA_WIDTH-1]^numer[DATA_WIDTH-1];
	integer	p;
	always @(posedge sys_clk)
	begin
		// 复位的时候不要动，控制功耗
		if(!sys_rst_n)
		begin
			for(p=PERIOD; p>=0; p=p-1)
			begin
				result_polar[p] <= 0;
				numer_tmp[p] <= 0;
				denom_tmp[p] <= 0;
			end
		end
		//
		else
		begin
			result_polar[0] <= denom[DATA_WIDTH-1]^numer[DATA_WIDTH-1];
			numer_tmp[0] <= {8'H0, numer_pos};
			denom_tmp[0] <= {8'H0, denom_pos, {(DATA_WIDTH){1'B0}}};
			// 迭代
			for(p=PERIOD; p>=1; p=p-1)
			begin
				case(_judge_[p-1])
					4'B1000: numer_tmp[p] <= judge_2[p-1]+3;
					4'B1100: numer_tmp[p] <= judge_1[p-1]+2;	
					4'B1110: numer_tmp[p] <= judge_0[p-1]+1;
					4'B1111: numer_tmp[p] <= {numer_tmp[p-1], 2'B00};	
					default: numer_tmp[p] <= {numer_tmp[p-1], 2'B00};	
				endcase
				//
				denom_tmp[p] <= denom_tmp[p-1];
				result_polar[p] <= result_polar[p-1];
			end
		end
	end

	always @(posedge sys_clk)
	begin
		if(result_polar[PERIOD])
			quotient <= ~numer_tmp[PERIOD]+1;
		else
			quotient <= numer_tmp[PERIOD];
	end
	
	integer dp;
	always @ ( posedge sys_clk) 
	begin
		for(dp=1; dp<=PERIOD; dp=dp+1)
			src_enx[dp] <= src_enx[dp-1];
		
		src_enx[0] <= src_en;
		
		dst_en <= src_enx[PERIOD];
	end
	
endmodule