/*
** HDL4SE: 软件Verilog综合仿真平台
** Copyright (C) 2021-2021, raoxianhong<raoxianhong@163.net>
** LCOM: 轻量级组件对象模型
** Copyright (C) 2021-2021, raoxianhong<raoxianhong@163.net>
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
**
** * Redistributions of source code must retain the above copyright notice,
**   this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright notice,
**   this list of conditions and the following disclaimer in the documentation
**   and/or other materials provided with the distribution.
** * The name of the author may be used to endorse or promote products
**   derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
** THE POSSIBILITY OF SUCH DAMAGE.
*/

module dec2seg(input [3:0] dec, output [7:0] seg);
  wire [7:0] wire_cst0;
  hdl4se_const #(8, 8'b00111111) const_cst0(wire_cst0);
  wire [7:0] wire_cst1;
  hdl4se_const #(8, 8'b00000110) const_cst1(wire_cst1);
  wire [7:0] wire_cst2;
  hdl4se_const #(8, 8'b01011011) const_cst2(wire_cst2);
  wire [7:0] wire_cst3;
  hdl4se_const #(8, 8'b01001111) const_cst3(wire_cst3);
  wire [7:0] wire_cst4;
  hdl4se_const #(8, 8'b01100110) const_cst4(wire_cst4);
  wire [7:0] wire_cst5;
  hdl4se_const #(8, 8'b01101101) const_cst5(wire_cst5);
  wire [7:0] wire_cst6;
  hdl4se_const #(8, 8'b01111101) const_cst6(wire_cst6);
  wire [7:0] wire_cst7;
  hdl4se_const #(8, 8'b00000111) const_cst7(wire_cst7);
  wire [7:0] wire_cst8;
  hdl4se_const #(8, 8'b01111111) const_cst8(wire_cst8);
  wire [7:0] wire_cst9;
  hdl4se_const #(8, 8'b01101111) const_cst9(wire_cst9);
  wire [7:0] wire_cst10;
  hdl4se_const #(8, 8'b01111001) const_cst10(wire_cst10);

  hdl4se_mux16 #(8) mux_dec(dec, 
    wire_cst0, 
    wire_cst1, 
    wire_cst2, 
    wire_cst3, 
    wire_cst4, 
    wire_cst5, 
    wire_cst6, 
    wire_cst7, 
    wire_cst8, 
    wire_cst9, 
    wire_cst10, 
    wire_cst10, 
    wire_cst10, 
    wire_cst10, 
    wire_cst10, 
    wire_cst10, 
    wire_cst10 
    seg);
endmodule  

module counter
    #(parameter WIDTH=4, MAXVALUE=9, RESETVALUE=0)
(input wClk, nwReset, wCounterIt, 
output [WIDTH-1:0] bCouter, 
output wCounterOverflow);

/*WIDTH宽度的寄存器用来保存计数器的值*/
  wire [WIDTH-1:0] wirein_bCurrentCounter, 
                   wireout_bCurrentCounter;
  hdl4se_reg #(WIDTH) bCurrentCounter(
      wClk, 
      wirein_bCurrentCounter, 
      wireout_bCurrentCounter
    );

wire [WIDTH-1:0] bCounter;
wire wCounterOverflow;
assign bCounter = wireout_bCurrentCounter;
//assign wCounterOverflow = wireout_wOverflow;

wire [WIDTH-1:0] bConst_MAXVALUE;
/*常数 MAXVALUE*/
hdl4se_const #(WIDTH, MAXVALUE) const_MAXVALUE(bConst_MAXVALUE);
/*常数 RESETVALUE*/
wire [WIDTH-1:0] bConst_RESETVALUE;
hdl4se_const #(WIDTH, RESETVALUE) const_RESETVALUE(bConst_RESETVALUE);

wire wEQ_bCurrentCounter_MAXVALUE;
/* 比较器 bCurrentCounter == MAXVALUE */
hdl4se_binop #(WIDTH, WIDTH, 1, BINOP_EQ) 
   binop_EQ_bCurrentCounter_MAXVALUE(
      wireout_bCurrentCounter,
      bConst_MAXVALUE,
      wEQ_bCurrentCounter_MAXVALUE
    );

hdl4se_binop #(1, 1, 1, BINOP_AND) 
   binop_counter_overfloat(
      wEQ_bCurrentCounter_MAXVALUE,
      wCounterIt,
      wCounterOverflow
    );

/* bCurrentCounter+1 用加法器实现 */    
/*常数 1*/
wire [WIDTH-1:0] bConst_One;
wire [WIDTH-1:0] bCurrentCounterPlusOne;
hdl4se_const #(WIDTH, 1) const_One(bConst_One);    
hdl4se_binop #(WIDTH, WIDTH, 1, BINOP_ADD) 
   binop_bCurrentCounterInc(
      wireout_bCurrentCounter,
      bConst_One,
      bCurrentCounterPlusOne
    );

wire [WIDTH-1:0] bCurrentCounter_if_wCounterIt;
hdl4se_mux2 #(WIDTH) mux_bCurrentCounter_if_wCounterIt
    ( wEQ_bCurrentCounter_MAXVALUE,
      bCurrentCounterPlusOne,
      bConst_RESETVALUE,
      bCurrentCounter_if_wCounterIt);

wire wConst_1;
hdl4se_const #(1, 1) const_1(wConst_1);
wire wConst_0;
hdl4se_const #(1, 0) const_0(wConst_0);

wire wOverflow_if_wCounterIt;
hdl4se_mux2 #(1) mux_wOverflow_if_wCounterIt
    ( wEQ_bCurrentCounter_MAXVALUE,
      wConst_0,
      wConst_1,
      wOverflow_if_wCounterIt);

wire [WIDTH-1:0] bCurrentCounter_if_nwReset;
hdl4se_mux2 #(WIDTH) mux_bCurrentCounter_if_nwReset
    ( wCounterIt,
      wireout_bCurrentCounter,
      bCurrentCounter_if_wCounterIt,
      bCurrentCounter_if_nwReset);

wire wOverflow_if_nwReset;
hdl4se_mux2 #(1) mux_wOverflow_if_nwReset
    ( wCounterIt,
      wireout_wOverflow,
      wOverflow_if_wCounterIt,
      wOverflow_if_nwReset);

hdl4se_mux2 #(WIDTH) mux_bCurrentCounter
    ( nwReset,
      bConst_RESETVALUE,
      bCurrentCounter_if_nwReset,
      wirein_bCurrentCounter);

hdl4se_mux2 #(1) mux_wOverflow
    ( wCounterIt,
      const_0,
      wOverflow_if_nwReset,
      wirein_wOverflow);

endmodule

module main(input wClk, 
            input nwReset, 
            output wWrite, 
            output [31:0] bWriteAddr, 
            output [31:0] bWiteData, 
            output [3:0] bWriteMask, 
            output wRead, 
            output [31:0] bReadAddr, 
            input [31:0] bReadData);

  wire wButton0Pressed;
  wire wButton1Pressed;
  wire wButton2Pressed;
  /*我们一直在读按键的状态*/
  hdl4se_const #(1, 1) const_0_wRead(wRead);
  hdl4se_const #(32, 32'hF000_0000) const_bReadAddr(bReadAddr);
  
  hdl4se_split4
     #(INPUTWIDTH=32, 
         OUTPUTWIDTH0=1, OUTPUTFROM0=0, 
         OUTPUTWIDTH1=1, OUTPUTFROM1=1,
         OUTPUTWIDTH2=1, OUTPUTFROM2=2, 
         OUTPUTWIDTH3=1, OUTPUTFROM3=3
         ) 
  bReadData_wButton012(
      bReadData,
      wButton0Pressed,
      wButton1Pressed,
      wButton2Pressed,
      .wireout3()
    );


/* 以下是计数器连接 */
  wire nwResetCount;
wire wCounterin0, wCounterin1, wCounterin2, 
     wCounterin3, wCounterin4, wCounterin5, 
     wCounterin6, wCounterin7, wCounterin8, 
     wCounterin9;
wire wOverflow0, wOverflow1, wOverflow2, wOverflow3, wOverflow4;
wire wOverflow5, wOverflow6, wOverflow7, wOverflow8, wOverflow9;
assign wCounterin0 = wCounterIt;
assign wCounterin1 = wCounterin0;
assign wCounterin2 = wCounterin1;
assign wCounterin3 = wCounterin2;
assign wCounterin4 = wCounterin3;
assign wCounterin5 = wCounterin4;
assign wCounterin6 = wCounterin5;
assign wCounterin7 = wCounterin6;
assign wCounterin8 = wCounterin7;
assign wCounterin9 = wCounterin8;
  wire [3:0] bCount0, bCount1, bCount2, bCount3, bCount4,
           bCount5, bCount6, bCount7, bCount8, bCount9;
  counter #(4,9,0) counter0(wClk, nwResetCount, wCounterin0, bCount0, wOverflow0);
  counter #(4,9,0) counter1(wClk, nwResetCount, wCounterin1, bCount1, wOverflow1);
  counter #(4,9,0) counter2(wClk, nwResetCount, wCounterin2, bCount2, wOverflow2);
  counter #(4,9,0) counter3(wClk, nwResetCount, wCounterin3, bCount3, wOverflow3);
  counter #(4,9,0) counter4(wClk, nwResetCount, wCounterin4, bCount4, wOverflow4);
  counter #(4,9,0) counter5(wClk, nwResetCount, wCounterin5, bCount5, wOverflow5);
  counter #(4,9,0) counter6(wClk, nwResetCount, wCounterin6, bCount6, wOverflow6);
  counter #(4,9,0) counter7(wClk, nwResetCount, wCounterin7, bCount7, wOverflow7);
  counter #(4,9,0) counter8(wClk, nwResetCount, wCounterin8, bCount8, wOverflow8);
  counter #(4,9,0) counter9(wClk, nwResetCount, wCounterin9, bCount9, .wCounterOverflow());

  wire wirein_wCounterIt, wireout_wCounterIt;
  hdl4se_reg #(1) wCounterIt(
      wClk, 
      wirein_wCounterIt, 
      wireout_wCounterIt
    );
  wire wButton0NotPressed;
  hdl4se_unop #(1, 1, UNOP_NOT) Button0NotPressed(wButton0Pressed, wButton0NotPressed); 

  /*counterit= (~b1) & b2*/
  wire wButton1NotPressed;
  hdl4se_unop #(1, 1, UNOP_NOT) unop_Button1NotPressed(wButton1Pressed, wButton1NotPressed); 
  hdl4se_binop #(1, 1, 1, BINOP_AND) binop_counterit(wButton1NotPressed, wButton2Pressed, wirein_wCounterIt);

  /*assign nwResetCount = (~b0) & nwReset;	*/
  hdl4se_binop #(1, 1, 1, BINOP_AND) binop_resetcounter(wButton0NotPressed, nwReset, nwResetCount);

/* 以下是译码器连接，十个计数器的输出对应到十个译码器 */
wire code0[7:0];
wire code1[7:0];
wire code2[7:0];
wire code3[7:0];
wire code4[7:0];
wire code5[7:0];
wire code6[7:0];
wire code7[7:0];
wire code8[7:0];
wire code9[7:0];
dec2seg dec0(bCount0, code0);
dec2seg dec1(bCount1, code1);
dec2seg dec2(bCount2, code2);
dec2seg dec3(bCount3, code3);
dec2seg dec4(bCount4, code4);
dec2seg dec5(bCount5, code5);
dec2seg dec6(bCount6, code6);
dec2seg dec7(bCount7, code7);
dec2seg dec8(bCount8, code8);
dec2seg dec9(bCount9, code9);

/*下面将译码器输出写到外面去，控制数码管显示*/

  
  wire wCounterin98, wCounterin76, wCounterin54, wCounterin32, wCounterin10, 
       wCounterin7654, wCounterin3210;
  hdl4se_binop #(1, 1, 1, BINOP_OR) or98(wCounterin9, wCounterin8, wCounterin98); 
  hdl4se_binop #(1, 1, 1, BINOP_OR) or76(wCounterin7, wCounterin6, wCounterin76); 
  hdl4se_binop #(1, 1, 1, BINOP_OR) or54(wCounterin5, wCounterin4, wCounterin54); 
  hdl4se_binop #(1, 1, 1, BINOP_OR) or32(wCounterin3, wCounterin2, wCounterin32); 
  hdl4se_binop #(1, 1, 1, BINOP_OR) or10(wCounterin1, wCounterin0, wCounterin10); 
  hdl4se_binop #(1, 1, 1, BINOP_OR) or32(wCounterin76, wCounterin54, wCounterin7654); 
  hdl4se_binop #(1, 1, 1, BINOP_OR) or10(wCounterin32, wCounterin10, wCounterin3210); 

  wire[2:0] wirein_bCounterChanged, wireout_bCounterChanged;
  hdl4se_reg #(3) reg_bCounterChanged(
     wClk,
     wirein_bCounterChanged, 
     wireout_bCounterChanged);

  wire [2:0] bChanged_if_nwReset;
  hdl4se_bind3 #(1, 1, 1) bind_wCounterin(wCounterin98, wCounterin7654, wCounterin3210, bChanged_if_nwReset);

  wire [2:0] b3b0;
  hdl4se_const #(3, 0) const_b3b0(b3b0);
  hdl4se_mux2 #(3) mux_if_nwReset(nwReset, 
            b3b0,
            bChanged_if_nwReset,
            wirein_bCounterChanged
            );

  wire wCounterChanged0, wCounterChanged1, wCounterChanged2;
  hdl4se_split4 #(INPUTWIDTH=3, 
         OUTPUTWIDTH0=1, OUTPUTFROM0=0, 
         OUTPUTWIDTH1=1, OUTPUTFROM1=1
         OUTPUTWIDTH2=1, OUTPUTFROM2=2, 
         OUTPUTWIDTH3=1, OUTPUTFROM3=2)
         split4_bCounterChanged
         (wireout_bCounterChanged, 
           wCounterChanged0,
           wCounterChanged1,
           wCounterChanged2,
           .wireout3(),
         );

  wire wirein_wWrite, wireout_wWrite;
  hdl4se_reg #(1) reg_wWrite(
      wClk, 
      wirein_wWrite, 
      wireout_wWrite
    );

  wire [31:0] wirein_bWriteAddr, wireout_bWriteAddr;
  hdl4se_reg #(32) reg_bWriteAddr(
      wClk, 
      wirein_bWriteAddr, 
      wireout_bWriteAddr
    );

  wire [31:0] wirein_bWriteData, wireout_bWriteData;
  hdl4se_reg #(32) reg_bWriteData(
      wClk, 
      wirein_bWriteData, 
      wireout_bWriteData
    );

  wire [3:0] wirein_bWriteMask, wireout_bWriteMask;
  hdl4se_reg #(4) reg_bWriteMask(
      wClk, 
      wirein_bWriteMask, 
      wireout_bWriteMask
    );

  wire [7:0] b8b0;
  hdl4se_const #(8, 0) const_b8b0(b8b0);
  wire [3:0] b4b0000;
  hdl4se_const #(4, 0) const_b4b0000(b4b0000);
  wire [3:0] b4b1100;
  hdl4se_const #(4, 4'b1100) const_b4b1100(b4b1100);
  wire [31:0] b32b0;
  hdl4se_const #(32, 0) const_b32b0(b32b0);
  wire [31:0] b32hf0000018;
  hdl4se_const #(32, 32'hf0000018) const_b32hf0000018(b32hf0000018);
  wire [31:0] b32hf0000014;
  hdl4se_const #(32, 32'hf0000014) const_b32hf0000014(b32hf0000014);
  wire [31:0] b32hf0000010;
  hdl4se_const #(32, 32'hf0000010) const_b32hf0000018(b32hf0000010);
  wire [31:0] b0098;
  wire [31:0] b7654;
  wire [31:0] b3210;
  hdl4se_bind4(8,8,8,8) bind_0098(code8, code9, b8b0, b8b0, b0098);
  hdl4se_bind4(8,8,8,8) bind_7654(code4, code5, code6, code7, b7654);
  hdl4se_bind4(8,8,8,8) bind_3210(code0, code1, code2, code3, b3210);

  wire [3:0] wire_bWriteMask_if_bCounterChanged0;
  hdl4se_mux2 #(4) mux_bWriteMask_if_bCounterChanged0(wCounterChanged0,
                    wireout_bWriteMask,
                    b4b0000,
                    wire_bWriteMask_if_bCounterChanged0
                    );

  wire [31:0] wire_bWriteAddr_if_bCounterChanged0;
  hdl4se_mux2 #(32) mux_bWriteAddr_if_bCounterChanged0(wCounterChanged0,
                    wireout_bWriteAddr,
                    b32hf0000010,
                    wire_bWriteAddr_if_bCounterChanged0
                    );

  wire [31:0] wire_bWriteData_if_bCounterChanged0;
  hdl4se_mux2 #(32) mux_bWriteData_if_bCounterChanged0(wCounterChanged0,
                    wireout_bWriteData,
                    ,b3210
                    wire_bWriteData_if_bCounterChanged0
                    );

  wire [3:0] wire_bWriteMask_if_bCounterChanged1;
  hdl4se_mux2 #(4) mux_bWriteMask_if_bCounterChanged1(wCounterChanged1,
                    wire_bWriteMask_if_bCounterChanged0,
                    b4b0000,
                    wire_bWriteMask_if_bCounterChanged1
                    );

  wire [31:0] wire_bWriteAddr_if_bCounterChanged1;
  hdl4se_mux2 #(32) mux_bWriteAddr_if_bCounterChanged1(wCounterChanged1,
                    wire_bWriteAddr_if_bCounterChanged0,
                    b32hf0000014,
                    wire_bWriteAddr_if_bCounterChanged1
                    );

  wire [31:0] wire_bWriteData_if_bCounterChanged1;
  hdl4se_mux2 #(32) mux_bWriteData_if_bCounterChanged1(wCounterChanged1,
                    wire_bWriteData_if_bCounterChanged0,
                    b7654,
                    wire_bWriteData_if_bCounterChanged1
                    );

  wire [3:0] wire_bWriteMask_if_bCounterChanged2;
  hdl4se_mux2 #(4) mux_bWriteMask_if_bCounterChanged2(wCounterChanged2,
                    wire_bWriteMask_if_bCounterChanged1,
                    b4b1100,
                    wire_bWriteMask_if_bCounterChanged2
                    );

  wire [31:0] wire_bWriteAddr_if_bCounterChanged2;
  hdl4se_mux2 #(32) mux_bWriteAddr_if_bCounterChanged1(wCounterChanged2,
                    wire_bWriteAddr_if_bCounterChanged1,
                    ,b32hf0000018
                    wire_bWriteAddr_if_bCounterChanged2
                    );

  wire [31:0] wire_bWriteData_if_bCounterChanged2;
  hdl4se_mux2 #(32) mux_bWriteData_if_bCounterChanged2(wCounterChanged2,
                    wire_bWriteData_if_bCounterChanged1,
                    b0098,
                    wire_bWriteData_if_bCounterChanged2
                    );

  wire [3:0] wire_bWriteMask_if_nwReset;
  hdl4se_mux2 #(4) mux_bWriteMask_if_nwReset(nwReset,
                    wire_bWriteMask_if_bCounterChanged2,
                    b4b0000,
                    wirein_bWriteMask
                    );

  wire [31:0] wire_bWriteAddr_if_nwReset;
  hdl4se_mux2 #(32) mux_bWriteAddr_if_nwReset(nwReset,
                    wire_bWriteAddr_if_bCounterChanged2,
                    b32b0,
                    wirein_bWriteAddr
                    );

  wire [31:0] wire_bWriteData_if_nwReset;
  hdl4se_mux2 #(32) mux_bWriteData_if_nwReset(nwReset,
                    wire_bWriteData_if_bCounterChanged2,
                    b32b0,
                    wirein_bWriteData
                    );
  wire wire_or_bCounterChanged;
  hdl4se_unop #(3, 1, UNOP_OR) or_bCounterChanged(wireout_bCounterChanged, wire_or_bCounterChanged)
  hdl4se_binop #(1, 1, 1, BINOP_AND) and_nwReset_bCounterChanged(nwReset, wire_or_bCounterChanged, wirein_wWrite);
 
/*
wWrite <= nwReset & (bCounterChanged[0] | bCounterChanged[1] | bCounterChanged[2]) 
  nwReset==0 :: 
     bWriteMask <= 4'b0000; bWriteAddr <= 32'b0; bWriteData <= 32'b0; 
  nwReset & bCounterChanged[2] : 
     bWriteMask <= 4'b1100; bWriteAddr <= 32'hf0000018; bWriteData <= {16'b0, code9, code8};
  nwReset & ~bCounterChanged[2] & bCounterChanged[1]:
    bWriteMask <= 4'b0000; bWriteAddr <= 32'hf0000014; bWriteData <= {code7, code6, code5, code4};
  nwReset & ~bCounterChanged[2] & ~bCounterChanged[1] & bCounterChanged[0]:
    bWriteMask <= 4'b0000; bWriteAddr <= 32'hf0000010; bWriteData <= {code3, code2, code1, code0};
  nwReset & ~bCounterChanged[2] & ~bCounterChanged[1] & ~bCounterChanged[0]
    bWriteMask <= bWriteMask; bWriteAddr <= bWriteAddr; bWriteData <= bWriteData;
*/



endmodule
