//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--           		     Actel Corporation           		      --
//--                             www.actel.com				      --
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
// Verilog HDL Design :  NAND FLASH Controller                                  //
//         Design     :  ACTEL NAND FLASH IP                                    //
//         File name  :  nand_flash_interface.v                                 //
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Description: This design describes one of possible systems for interfacing // 
// NAND Flash Device using NAND_FLASH_Interface ip. This module is the top    //
// level entity which instantiates NAND_FLASH_INTERFACE ip and the 8051s      //
// microcontroller system. 8051s sends command, address, data and controls all//
// the transaction with NAND Flash memory through NAND_FLASH_Interface.       //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//-- Modification History                                                       --
//--                                                                            --
//-- Initial revision                                                           --
//--                                                                            --
//-- Revision 1.0                                                               --

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//IMPORTANT-READ THESE TERMS CAREFULLY BEFORE UTILIZING THE INFORMATION       --
//CONTAINED IN THIS DESIGN.  						      --
//YOU ARE HEREBY LICENSED TO USE THE DESIGN FILES AND DOCUMENTATION UNDER THE --
//FOLLOWING TERMS AND CONDITIONS:					      --
//USE									      --
//YOU MAY COPY AND USE THE DESIGN FILES AND DOCUMENTATION ONLY IN CONNECTION  --
//WITH ACTEL PRODUCTS, PURCHASED FROM ACTEL OR ITS AUTHORIZED DISTRIBUTORS.   --  
//NO SUPPORT/NO WARRANTY.  						      --
//THE DESIGN FILES AND DOCUMENTATION ARE PROVIDED WITHOUT SUPPORT OR WARRANTY --
//OF ANY KIND.  ACTEL IS NOT OBLIGATED TO PROVIDE UPDATES, BUG FIXES, OR      --
//TECHNICAL SUPPORT AND DISCLAIMS ALL WARRANTIES INCLUDING, WITHOUT	      --
//LIMITATION, THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR     --
//PURPOSE, AND WARRANTIES OF NON-INFRINGEMENT OF THE RIGHTS OF THIRD PARTIES  --
//(INCLUDING, WITHOUT LIMITATION, RIGHTS UNDER PATENT, COPYRIGHT, TRADE	      --
//SECRET, OR OTHER INTELLECTUAL PROPERTY RIGHTS). RECIPIENT ACCEPTS THE	      --
//DESIGN FILES AND DOCUMENTATION IN "AS-IS" CONDITION. 			      --
//EXPORT								      --
//YOU AGREE THAT YOU WILL NOT EXPORT THE DESIGN FILES OR DOCUMENTATION IN     --
//VIOLATION OF ANY UNITED STATES EXPORT CONTROL LAW OR THE EXPROT CONTROL LAW --
//OF ANY OTHER RELEVANT JURISDICTION.					      --
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//                               Module                                  //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

`timescale 1 ns/1 ns
module nand_flash_interface (//Active low Reset signal aborts the current operation and resets all the control siganls
                   nreset, 
                   // System Clock
                   clk, 
                   //Chip enable,it controls the active vs standby mode of the device 
                   ce_n, 
                   //Read enable,it controls the data and status output on the I/O lines
                   re_n, 
                   //Address latch enable,it controls the writing to the address register 
                   ale, 
                   //Command latch enable,it controls the writing to the command register
                   cle, 
                   //Spare area enable,it controls the access to the 16 byte of spare area on each page
                   se_n, 
                   //Write enable,it controls the data and command on the I/O lines during a write sequence
                   we_n, 
                   //Write protect,it provides the protection when programming or erasing the device 
                   wp_n, 
                   // IO_bus for command, address and data transaction with NAND Flash memory
                   io_bus, 
                   // Input indicates Ready/ Busy status of NAND Flash memory
                   ry_by,
                   // Uart Serial receive
                   rxd,
                   // Uart Serial transmit
                   txd,
                   //oci JTAG signals
                   // Clock
                   TCK, 
                   // Test Data Input
                   TDI, 
                   // Test Mode Select
                   TMS, 
                   // Reset
                   TRSTB, 
                   // Test Data Output
                   TDO
                   );

input nreset,clk,ry_by, TCK, TDI, TMS, TRSTB, rxd;


output ce_n,re_n,ale, TDO, txd;
output cle,se_n,we_n,wp_n;

inout [7:0] io_bus ;

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//                         A R C H I T E C T U R E                            //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
reg [2:0] cmd_cntrl_reg	;

wire [2:0] 	cmd_cntrl = cmd_cntrl_reg		;

wire rd_wr_sig ; 

// Program Memory interface name directions relative to Core8051
reg [7:0] memdatai_reg	;
wire [7:0] memdatai	= memdatai_reg;

wire [15:0] memaddr	;
wire [7:0] memdatao ; 
wire dbgmempswr ;

// Program store read enable
wire mempsrd, ramwe, ramoe;  

wire [7:0]  ip_data, mem_data, ramaddr, ramdatao, ramdatai ;

wire memrd, memwr ;

reg wr_sel_sig, wr_en_sig ;

// misc. signals
wire nclk	;
wire clk8051;
reg [1:0] clk_divider	;

wire         and_l ;

wire rb_n = ry_by;

reg  and_l_sig ;

reg  [7:0] io_wbus_reg_sig ;
reg  [7:0] io_rbus_reg_sig ;

wire [7:0] 	io_wbus_sig		;
wire [7:0] 	io_rbus_sig		;
wire [7:0] 	ry_by_sig		;

reg csn_reg ;
reg rxd_reg ;

wire csn_s =  csn_reg;
wire oen_s, oen_sig, wen_sig ;
wire wen_s ;
wire rxrdy_f ;
wire txrdy_f ;
wire new_data ;
wire rxd_s = rxd_reg;


wire [7:0] data_uart, data_in_s ;
reg [7:0] data_oled  ;

reg oen1_s ;
reg oen2_s ;
reg wen1_s ;
reg wen2_s ;

wire [7:0] p1i;
wire [7:0] p2i;
wire [7:0] p3i;

wire [7:0] p0o;
wire [7:0] p2o;
wire [7:0] p3o;

nand_interface_core nand_interface_core_inst
               (
 					.h_wr (rd_wr_sig),
 					.h_cntrl (cmd_cntrl),
 					.e_d ({1{1'b1}}),
 					.nreset (nreset),
 					.clk (clk),
 					.ce_n (ce_n),
 					.re_n (re_n),
 					.ale (ale),
 					.cle (cle),
 					.se_n (se_n),
 					.we_n (we_n),
 					.wp_n (wp_n)
				);



//////////////////////
// Program Ram8kx8 
//////////////////////
Ram8kx8 Ram8kx8_inst
           (
            .WD (memdatao),
            .RD (mem_data),
            .WEN (dbgmempswr),
            .REN (mempsrd),
            .WADDR (memaddr[12 : 0]),
            .RADDR (memaddr[12 : 0]),
            .WCLK (clk8051),
            .RCLK (nclk)
           
           );

////////////////////////
//// Data Ram256x8 inst
////////////////////////
Ram256x8 Ram256x8_inst
           (
            .WD (ramdatao),
            .RD (ramdatai),
            .WEN (ramwe),
            .REN (ramoe),
            .WADDR (ramaddr),
            .RADDR (ramaddr),
            .WCLK (clk8051),
            .RCLK (nclk)
           
           );

//////////////////////
// microcontroller 8051 system
//////////////////////

CORE8051 #(1,1,0,0,1,0)
CORE8051_inst (
.nreset(nreset),
.clk(clk8051),
.clkcpu(clk8051),
.clkper(clk8051),
.port0i(ry_by_sig),
.port1i(p1i),
.port2i(p2i),
.port3i(p3i),
.int0({1{1'b0}}),
.int1({1{1'b0}}),
.int0a({1{1'b0}}),
.int1a({1{1'b0}}),
.int2({1{1'b0}}),
.int3({1{1'b0}}),
.int4({1{1'b0}}),
.int5({1{1'b0}}),
.int6({1{1'b0}}),
.int7({1{1'b0}}),
.rxd0i({1{1'b0}}),
.t0({1{1'b0}}),
.t1({1{1'b0}}),
.nrsto(open),
.nrsto_nc(open),
.clkcpu_en(open),
.clkper_en(open),
.movx(open),
.port0o(p0o),
.port1o(open),
.port2o(p2o),
.port3o(p3o),
.rxd0o(open),
.txd0(open),
.mempsacki({1{1'b1}}),
.memacki({1{1'b1}}),
.memdatai(memdatai),
.mempsacko(open),
.memdatao(memdatao),
.memaddr(memaddr),
.mempsrd(mempsrd),
.memwr(memwr),
.memrd(memrd),
.ramdatai(ramdatai),
.ramdatao(ramdatao),
.ramaddr(ramaddr),
.ramwe(ramwe),
.ramoe(ramoe),
.sfrdatai({8{1'b0}}),
.sfrdatao(open),
.sfraddr(open),
.sfrwe(open),
.sfroe(open),
.TCK(TCK),
.TMS(TMS),
.TDI(TDI),
.TDO(TDO),
.TRSTB(TRSTB),
.BreakIn({1{1'b0}}),
.BreakOut(open),
.membank({4{1'b0}}),
.dbgmempswr(dbgmempswr),
.TrigOut(open),
.AuxOut(open),
.TraceA(open),
.TraceDI(open),
.TraceDO({20{1'b0}}),
.TraceWr(open)
);

// APB slave signals

always @(posedge clk)
begin 
    if (~nreset)begin
        io_wbus_reg_sig <= 8'b0;
    end else if (memwr) begin
        io_wbus_reg_sig <= memdatao; 
    end
end

assign ry_by_sig[0] = rb_n ;

assign ry_by_sig[7 : 1] = {7{1'b0}};

assign rd_wr_sig = wr_en_sig ;

always @(posedge clk)
begin 
    if (~nreset)begin
        cmd_cntrl_reg <= 3'b0;
    end else if (memwr || memrd || wr_sel_sig)  begin
        cmd_cntrl_reg <= memaddr[2 : 0] ;
    end else  begin
        cmd_cntrl_reg <= 3'h6;
    end
end

assign and_l = memwr | wr_sel_sig;

always @(posedge clk)
begin 
    if (~nreset)begin
        wr_sel_sig <= 1'b0;
    end else  begin
        wr_sel_sig <= memwr ;
    end
end

always @(posedge clk)
begin 
    if (~nreset)begin
        wr_en_sig <= 1'b1;
    end else  begin
        wr_en_sig <= ~memwr ;
    end
end

assign io_bus = and_l ? io_wbus_reg_sig : {8{1'bZ}} ;

assign io_rbus_sig =  io_bus;

always @(posedge clk)
begin 
    if (~nreset)begin
        clk_divider <= 2'b0;
    end else begin
        clk_divider <= clk_divider + 1 ;
    end
end

assign clk8051 = clk_divider[1] ;
assign nclk = ~(clk_divider[1]);

always @(posedge clk)
begin 
    if (~nreset)begin
        memdatai_reg <= 8'b0;
    end else if (memrd)begin
          memdatai_reg <= io_rbus_sig; 
    end
    else 
    begin
          memdatai_reg <= mem_data;
    end
	
end

//////////////////////////////////
// UART inst
//////////////////////////////////


always @(posedge clk)
begin 
    if (~nreset)begin
        csn_reg <= 1'b1;
    end else begin
        csn_reg <= 1'b0;
    end
end

always @(posedge clk)
begin 
    if (~nreset)begin
        rxd_reg <= 1'b1;
    end else begin
        rxd_reg <= rxd;
    end
end

CoreUART_cmp  CoreUART_cmp_inst(
        // Inputs
        .BAUD_VAL({8'h4E}),
        .BIT8({1{1'b1}}),
        .CLK(clk8051),
        .CSN(csn_s),
        .DATA_IN(data_in_s),
        .ODD_N_EVEN({1{1'b0}}),
        .OEN(oen_s),
        .PARITY_EN({1{1'b0}}),
        .RESET_N(nreset),
        .RX(rxd_s),
        .WEN(wen_s),
        // Outputs
        .DATA_OUT(data_uart),
        .OVERFLOW(open),
        .PARITY_ERR(open),
        .RXRDY(rxrdy_f),
        .TX(txd),
        .TXRDY(txrdy_f)
    );

always @(negedge clk)
begin 
    if (~nreset)begin
        data_oled <= 8'b0;
    end else if (~oen_s) begin
        data_oled <= data_uart;
    end
end


always @(negedge clk8051)
begin 
    if (~nreset)begin
        oen1_s <= 1'b1;
        oen2_s <= 1'b1;
    end else begin
        oen1_s <= p2o[0];
        oen2_s <= oen1_s;
    end
end

assign oen_sig = (~oen1_s) & oen2_s ;

assign oen_s = oen_sig ? {1{1'b0}} : {1{1'b1}} ;

always @(negedge clk8051)
begin 
    if (~nreset)begin
        wen1_s <= 1'b1;
        wen2_s <= 1'b1;
    end else begin
        wen1_s <= p3o[0];
        wen2_s <= wen1_s;
    end
end

assign wen_sig = (~wen1_s) & wen2_s ;

assign wen_s = wen_sig ? {1{1'b0}} : {1{1'b1}} ;

assign p1i = data_oled ;

assign p2i[0] = rxrdy_f ;

assign p2i[7 : 1] = {7{1'b0}} ;

assign p3i[0] = txrdy_f ;

assign p3i[7 : 1] = {7{1'b0}} ;

assign data_in_s = p0o;

endmodule

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//                               END OF FILE                                  //
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
