Add verilog/dv/marmot_test1, but compilation of uart_tb.v failed
diff --git a/run_sim.csh b/run_sim.csh
new file mode 100755
index 0000000..40ccc76
--- /dev/null
+++ b/run_sim.csh
@@ -0,0 +1,20 @@
+#!/bin/csh -f
+
+#set prot = io_ports
+#set prog = la_test2
+set prog = marmot_test1
+
+set sim = RTL
+#set sim = GL
+#set sim = GL_SDF
+
+if ($sim == RTL) then
+  set target = verify-${prog}-rtl
+else if ($sim == GL) then
+  set target = verify-${prog}-gl
+else if ($sim == GL_SDF) then
+  set target = verify-${prog}-gl-sdf
+endif
+
+make SIM=$sim $target |& egrep -v '\[0\] pc=' | spike-dasm | tee sim.log
+
diff --git a/verilog/dv/marmot_test1/Makefile b/verilog/dv/marmot_test1/Makefile
new file mode 100644
index 0000000..3fd0b56
--- /dev/null
+++ b/verilog/dv/marmot_test1/Makefile
@@ -0,0 +1,32 @@
+# SPDX-FileCopyrightText: 2020 Efabless Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+
+
+ 
+PWDD := $(shell pwd)
+BLOCKS := $(shell basename $(PWDD))
+
+# ---- Include Partitioned Makefiles ----
+
+CONFIG = caravel_user_project
+
+
+include $(MCW_ROOT)/verilog/dv/make/env.makefile
+include $(MCW_ROOT)/verilog/dv/make/var.makefile
+include $(MCW_ROOT)/verilog/dv/make/cpu.makefile
+include $(MCW_ROOT)/verilog/dv/make/sim.makefile
+
+
diff --git a/verilog/dv/marmot_test1/hello_flash.mem b/verilog/dv/marmot_test1/hello_flash.mem
new file mode 100644
index 0000000..1ae2f8e
--- /dev/null
+++ b/verilog/dv/marmot_test1/hello_flash.mem
@@ -0,0 +1,4325 @@
+// spi_flash.srec
+@00000000
+13
+09
+80
+00
+73
+10
+49
+30
+93
+04
+00
+00
+73
+29
+40
+F1
+@00000010
+63
+96
+24
+03
+37
+21
+00
+08
+13
+01
+01
+FF
+EF
+00
+10
+42
+@00000020
+B7
+04
+00
+02
+13
+09
+10
+00
+23
+A0
+24
+01
+93
+84
+44
+00
+@00000030
+37
+09
+00
+02
+13
+09
+09
+08
+E3
+C6
+24
+FF
+73
+00
+50
+10
+@00000040
+73
+29
+40
+34
+13
+79
+89
+00
+E3
+0A
+09
+FE
+B7
+04
+00
+02
+@00000050
+73
+29
+40
+F1
+13
+19
+29
+00
+33
+09
+99
+00
+23
+20
+09
+00
+@00000060
+03
+A9
+04
+00
+E3
+1E
+09
+FE
+93
+84
+44
+00
+37
+09
+00
+02
+@00000070
+13
+09
+09
+08
+E3
+C6
+24
+FF
+6F
+00
+00
+00
+93
+F5
+F5
+0F
+@00000080
+33
+07
+C5
+00
+AA
+87
+63
+57
+C0
+00
+85
+07
+A3
+8F
+B7
+FE
+@00000090
+E3
+1D
+F7
+FE
+82
+80
+63
+5C
+C0
+00
+2A
+96
+AA
+87
+03
+C7
+@000000A0
+05
+00
+85
+07
+85
+05
+A3
+8F
+E7
+FE
+E3
+1A
+F6
+FE
+82
+80
+@000000B0
+63
+55
+C0
+02
+2E
+96
+19
+A0
+63
+01
+B6
+02
+83
+47
+05
+00
+@000000C0
+03
+C7
+05
+00
+05
+05
+85
+05
+E3
+88
+E7
+FE
+33
+35
+F7
+00
+@000000D0
+33
+05
+A0
+40
+09
+89
+7D
+15
+82
+80
+01
+45
+82
+80
+83
+47
+@000000E0
+05
+00
+2A
+87
+01
+45
+81
+CB
+05
+05
+B3
+07
+A7
+00
+83
+C7
+@000000F0
+07
+00
+FD
+FB
+82
+80
+82
+80
+83
+C7
+05
+00
+23
+00
+F5
+00
+@00000100
+83
+C7
+05
+00
+99
+CB
+AA
+87
+03
+C7
+15
+00
+85
+05
+85
+07
+@00000110
+23
+80
+E7
+00
+03
+C7
+05
+00
+65
+FB
+82
+80
+19
+A0
+63
+9D
+@00000120
+E7
+00
+83
+47
+05
+00
+03
+C7
+05
+00
+05
+05
+85
+05
+B3
+E6
+@00000130
+E7
+00
+F5
+F6
+01
+45
+82
+80
+33
+35
+F7
+00
+33
+05
+A0
+40
+@00000140
+09
+89
+7D
+15
+82
+80
+AA
+87
+33
+08
+C5
+00
+03
+C7
+07
+00
+@00000150
+B3
+06
+F8
+40
+19
+EB
+03
+C7
+05
+00
+0D
+C7
+32
+95
+1D
+8D
+@00000160
+33
+25
+A0
+00
+33
+05
+A0
+40
+82
+80
+63
+5D
+D0
+00
+83
+C6
+@00000170
+05
+00
+85
+07
+85
+05
+E3
+8B
+E6
+FC
+05
+45
+E3
+E6
+E6
+FE
+@00000180
+7D
+55
+82
+80
+01
+45
+82
+80
+41
+11
+22
+C4
+06
+C6
+A9
+47
+@00000190
+2A
+84
+63
+08
+F5
+00
+A2
+85
+22
+44
+B2
+40
+01
+45
+41
+01
+@000001A0
+61
+A2
+B5
+45
+01
+45
+49
+22
+A2
+85
+22
+44
+B2
+40
+01
+45
+@000001B0
+41
+01
+9D
+AA
+41
+11
+01
+45
+22
+C4
+06
+C6
+5D
+22
+B5
+47
+@000001C0
+29
+44
+63
+03
+F5
+00
+2A
+84
+22
+85
+7D
+3F
+B2
+40
+22
+85
+@000001D0
+22
+44
+41
+01
+82
+80
+41
+11
+22
+C4
+06
+C6
+2A
+84
+03
+45
+@000001E0
+05
+00
+11
+C5
+05
+04
+4D
+37
+03
+45
+04
+00
+65
+FD
+B2
+40
+@000001F0
+22
+44
+01
+45
+41
+01
+82
+80
+41
+11
+22
+C4
+26
+C2
+4A
+C0
+@00000200
+06
+C6
+29
+49
+2A
+84
+81
+44
+75
+37
+63
+0C
+25
+01
+23
+00
+@00000210
+A4
+00
+93
+87
+14
+00
+05
+04
+19
+C5
+BE
+84
+61
+3F
+E3
+18
+@00000220
+25
+FF
+23
+00
+04
+00
+B2
+40
+22
+44
+02
+49
+26
+85
+92
+44
+@00000230
+41
+01
+82
+80
+01
+11
+06
+CE
+22
+CC
+23
+06
+01
+00
+05
+ED
+@00000240
+91
+E1
+85
+45
+93
+07
+B1
+00
+13
+07
+00
+03
+91
+C5
+23
+80
+@00000250
+E7
+00
+FD
+15
+FD
+17
+E5
+FD
+03
+C5
+17
+00
+13
+84
+17
+00
+@00000260
+11
+C5
+05
+04
+15
+37
+03
+45
+04
+00
+65
+FD
+F2
+40
+62
+44
+@00000270
+01
+45
+05
+61
+82
+80
+2A
+87
+93
+77
+F7
+00
+17
+18
+00
+00
+@00000280
+13
+08
+C8
+CF
+C2
+97
+03
+C5
+07
+00
+13
+04
+B1
+00
+93
+07
+@00000290
+F4
+FF
+A3
+80
+A7
+00
+11
+83
+99
+CD
+FD
+15
+55
+D7
+3E
+84
+@000002A0
+93
+77
+F7
+00
+C2
+97
+03
+C5
+07
+00
+11
+83
+93
+07
+F4
+FF
+@000002B0
+A3
+80
+A7
+00
+FD
+F1
+93
+76
+F7
+00
+C2
+96
+13
+86
+F7
+FF
+@000002C0
+45
+D3
+03
+C5
+06
+00
+11
+83
+3E
+84
+23
+80
+A7
+00
+93
+76
+@000002D0
+F7
+00
+B2
+87
+C2
+96
+13
+86
+F7
+FF
+59
+D3
+DD
+B7
+93
+17
+@000002E0
+25
+00
+17
+15
+00
+00
+13
+05
+A5
+A6
+3E
+95
+18
+41
+85
+47
+@000002F0
+1C
+C7
+5C
+C7
+63
+8A
+F5
+00
+93
+07
+30
+36
+1C
+CF
+5C
+43
+@00000300
+E3
+DF
+07
+FE
+01
+45
+82
+80
+BD
+47
+1C
+CF
+CD
+BF
+93
+17
+@00000310
+25
+00
+17
+15
+00
+00
+13
+05
+A5
+A3
+3E
+95
+1C
+41
+88
+43
+@00000320
+13
+45
+F5
+FF
+7D
+81
+82
+80
+93
+17
+25
+00
+17
+15
+00
+00
+@00000330
+13
+05
+05
+A2
+3E
+95
+18
+41
+1C
+43
+E3
+CF
+07
+FE
+0C
+C3
+@00000340
+01
+45
+82
+80
+93
+17
+25
+00
+17
+15
+00
+00
+13
+05
+45
+A0
+@00000350
+3E
+95
+1C
+41
+DC
+43
+13
+C5
+F7
+FF
+23
+80
+F5
+00
+7D
+81
+@00000360
+82
+80
+93
+17
+25
+00
+17
+15
+00
+00
+13
+05
+65
+9E
+3E
+95
+@00000370
+1C
+41
+C8
+43
+E3
+4F
+05
+FE
+13
+75
+F5
+0F
+82
+80
+1D
+71
+@00000380
+A2
+CE
+A6
+CC
+13
+F8
+07
+04
+17
+1E
+00
+00
+13
+0E
+CE
+C2
+@00000390
+63
+16
+08
+00
+17
+1E
+00
+00
+13
+0E
+8E
+BF
+13
+F4
+07
+01
+@000003A0
+63
+02
+04
+14
+F9
+9B
+A2
+84
+13
+F8
+27
+00
+93
+0F
+00
+02
+@000003B0
+93
+F3
+07
+02
+63
+06
+08
+14
+63
+C6
+05
+14
+13
+F8
+47
+00
+@000003C0
+63
+1C
+08
+16
+A1
+8B
+81
+42
+81
+C7
+FD
+16
+93
+02
+00
+02
+@000003D0
+63
+8A
+03
+00
+C1
+47
+63
+0F
+F6
+16
+93
+07
+86
+FF
+93
+B7
+@000003E0
+17
+00
+9D
+8E
+63
+97
+05
+12
+93
+07
+00
+03
+23
+06
+F1
+00
+@000003F0
+01
+43
+13
+08
+00
+03
+85
+48
+7C
+00
+C6
+8E
+63
+D3
+E8
+00
+@00000400
+BA
+8E
+33
+8E
+D6
+41
+93
+05
+FE
+FF
+91
+EC
+B3
+06
+C5
+01
+@00000410
+13
+07
+00
+02
+63
+5A
+C0
+15
+05
+05
+A3
+0F
+E5
+FE
+E3
+1D
+@00000420
+D5
+FE
+F9
+55
+7D
+5E
+63
+85
+02
+00
+23
+00
+55
+00
+05
+05
+@00000430
+63
+88
+03
+00
+21
+47
+63
+01
+E6
+12
+41
+47
+63
+02
+E6
+10
+@00000440
+0D
+E8
+2A
+86
+05
+47
+63
+56
+C0
+13
+05
+06
+B3
+06
+C7
+40
+@00000450
+AE
+96
+AA
+96
+A3
+0F
+F6
+FF
+E3
+49
+D0
+FE
+13
+C7
+F5
+FF
+@00000460
+7D
+87
+6D
+8F
+FD
+15
+33
+8E
+E5
+40
+05
+07
+3A
+95
+93
+05
+@00000470
+FE
+FF
+33
+87
+1E
+41
+2A
+97
+93
+06
+00
+03
+63
+D4
+D8
+0F
+@00000480
+05
+05
+A3
+0F
+D5
+FE
+E3
+1D
+A7
+FE
+33
+86
+67
+00
+BA
+86
+@00000490
+05
+45
+19
+A0
+03
+48
+06
+00
+85
+06
+B3
+07
+D5
+40
+9A
+97
+@000004A0
+BA
+97
+A3
+8F
+06
+FF
+7D
+16
+E3
+46
+F0
+FE
+13
+05
+13
+00
+@000004B0
+3A
+95
+63
+55
+C0
+03
+2A
+87
+13
+06
+00
+02
+85
+46
+05
+07
+@000004C0
+B3
+87
+E6
+40
+AE
+97
+AA
+97
+A3
+0F
+C7
+FE
+E3
+49
+F0
+FE
+@000004D0
+93
+C7
+F5
+FF
+FD
+87
+FD
+8D
+85
+05
+2E
+95
+76
+44
+E6
+44
+@000004E0
+25
+61
+82
+80
+13
+F8
+17
+00
+93
+F4
+17
+01
+93
+0F
+00
+03
+@000004F0
+E3
+0C
+08
+EA
+13
+F8
+27
+00
+93
+F3
+07
+02
+E3
+1E
+08
+EA
+@00000500
+81
+42
+F9
+B5
+B3
+05
+B0
+40
+FD
+16
+93
+02
+D0
+02
+E3
+93
+@00000510
+03
+EC
+81
+48
+7C
+00
+33
+F8
+C5
+02
+46
+83
+85
+08
+33
+8F
+@00000520
+17
+01
+AE
+8E
+72
+98
+03
+48
+08
+00
+B3
+D5
+C5
+02
+A3
+0F
+@00000530
+0F
+FF
+E3
+F2
+CE
+FE
+D1
+B5
+FD
+16
+93
+02
+B0
+02
+49
+BD
+@00000540
+13
+07
+00
+03
+23
+00
+E5
+00
+13
+07
+80
+07
+A3
+00
+E5
+00
+@00000550
+09
+05
+FD
+B5
+F9
+16
+79
+B5
+13
+07
+00
+03
+23
+00
+E5
+00
+@00000560
+05
+05
+F9
+BD
+2A
+87
+15
+B7
+13
+07
+EE
+FF
+2E
+8E
+BA
+85
+@00000570
+5D
+BD
+2E
+8E
+FD
+15
+F5
+BD
+AA
+85
+01
+45
+75
+B3
+49
+71
+@00000580
+23
+28
+61
+13
+23
+26
+11
+14
+23
+24
+81
+14
+23
+22
+91
+14
+@00000590
+23
+20
+21
+15
+23
+2E
+31
+13
+23
+2C
+41
+13
+23
+2A
+51
+13
+@000005A0
+23
+26
+71
+13
+23
+24
+81
+13
+23
+22
+91
+13
+23
+20
+A1
+13
+@000005B0
+23
+2A
+B1
+14
+23
+2C
+C1
+14
+23
+2E
+D1
+14
+23
+20
+E1
+16
+@000005C0
+23
+22
+F1
+16
+23
+24
+01
+17
+23
+26
+11
+17
+83
+47
+05
+00
+@000005D0
+13
+0B
+41
+15
+5A
+C2
+63
+89
+07
+5C
+93
+09
+01
+02
+2A
+83
+@000005E0
+97
+0A
+00
+00
+93
+8A
+4A
+78
+4E
+85
+93
+0B
+E0
+02
+17
+0A
+@000005F0
+00
+00
+13
+0A
+AA
+7B
+97
+14
+00
+00
+93
+84
+64
+99
+17
+14
+@00000600
+00
+00
+13
+04
+A4
+88
+13
+07
+50
+02
+63
+84
+E7
+06
+23
+00
+@00000610
+F5
+00
+83
+47
+13
+00
+05
+05
+05
+03
+F5
+F7
+23
+00
+05
+00
+@00000620
+83
+45
+01
+02
+63
+84
+05
+12
+05
+44
+33
+04
+34
+41
+01
+45
+@00000630
+E5
+39
+83
+C5
+19
+00
+33
+85
+89
+00
+85
+09
+ED
+F9
+83
+20
+@00000640
+C1
+14
+03
+24
+81
+14
+83
+24
+41
+14
+03
+29
+01
+14
+83
+29
+@00000650
+C1
+13
+03
+2A
+81
+13
+83
+2A
+41
+13
+03
+2B
+01
+13
+83
+2B
+@00000660
+C1
+12
+03
+2C
+81
+12
+83
+2C
+41
+12
+03
+2D
+01
+12
+75
+61
+@00000670
+82
+80
+81
+47
+C1
+46
+83
+45
+13
+00
+13
+09
+13
+00
+13
+87
+@00000680
+05
+FE
+13
+77
+F7
+0F
+63
+E7
+E6
+00
+0A
+07
+56
+97
+18
+43
+@00000690
+56
+97
+02
+87
+13
+87
+05
+FD
+13
+77
+F7
+0F
+A5
+46
+63
+FB
+@000006A0
+E6
+0C
+13
+07
+A0
+02
+FD
+56
+63
+89
+E5
+0E
+7D
+57
+63
+81
+@000006B0
+75
+0B
+13
+F6
+F5
+0D
+13
+08
+C0
+04
+63
+03
+06
+05
+13
+86
+@000006C0
+F5
+FB
+13
+76
+F6
+0F
+13
+08
+70
+03
+63
+6E
+C8
+04
+0A
+06
+@000006D0
+52
+96
+10
+42
+52
+96
+02
+86
+93
+E7
+17
+00
+4A
+83
+61
+BF
+@000006E0
+93
+E7
+07
+01
+4A
+83
+41
+BF
+93
+E7
+47
+00
+4A
+83
+61
+B7
+@000006F0
+93
+E7
+07
+02
+4A
+83
+41
+B7
+93
+E7
+87
+00
+4A
+83
+A5
+BF
+@00000700
+03
+48
+19
+00
+13
+03
+70
+03
+93
+08
+19
+00
+13
+06
+F8
+FB
+@00000710
+13
+76
+F6
+0F
+63
+67
+C3
+00
+0A
+06
+22
+96
+10
+42
+22
+96
+@00000720
+02
+86
+C2
+85
+46
+89
+13
+07
+50
+02
+93
+07
+15
+00
+63
+89
+@00000730
+E5
+42
+23
+00
+E5
+00
+03
+47
+09
+00
+63
+1A
+07
+4C
+3E
+85
+@00000740
+23
+00
+05
+00
+83
+45
+01
+02
+E3
+90
+05
+EE
+01
+45
+C5
+BD
+@00000750
+83
+45
+19
+00
+25
+46
+13
+08
+19
+00
+13
+87
+05
+FD
+13
+77
+@00000760
+F7
+0F
+63
+77
+E6
+3A
+13
+07
+A0
+02
+63
+8B
+E5
+3C
+42
+89
+@00000770
+01
+47
+81
+B7
+81
+46
+25
+46
+13
+97
+26
+00
+BA
+96
+05
+09
+@00000780
+86
+06
+AE
+96
+83
+45
+09
+00
+93
+86
+06
+FD
+13
+87
+05
+FD
+@00000790
+13
+77
+F7
+0F
+E3
+72
+E6
+FE
+11
+BF
+83
+26
+0B
+00
+83
+45
+@000007A0
+23
+00
+13
+09
+23
+00
+11
+0B
+E3
+D2
+06
+F0
+B3
+06
+D0
+40
+@000007B0
+93
+E7
+07
+01
+E5
+BD
+13
+08
+4B
+00
+41
+46
+83
+25
+0B
+00
+@000007C0
+42
+8B
+75
+3E
+83
+47
+19
+00
+13
+03
+19
+00
+E3
+9D
+07
+E2
+@000007D0
+B1
+B5
+13
+08
+4B
+00
+29
+46
+D5
+B7
+46
+89
+03
+26
+0B
+00
+@000007E0
+11
+0B
+63
+01
+06
+3A
+83
+45
+06
+00
+63
+8B
+05
+3E
+63
+09
+@000007F0
+07
+3E
+B2
+85
+29
+A0
+33
+88
+E5
+40
+63
+07
+C8
+00
+03
+C8
+@00000800
+15
+00
+85
+05
+E3
+19
+08
+FE
+C1
+8B
+91
+8D
+63
+82
+07
+3A
+@00000810
+63
+5B
+B0
+40
+33
+08
+B6
+00
+AA
+87
+03
+47
+06
+00
+05
+06
+@00000820
+85
+07
+A3
+8F
+E7
+FE
+E3
+1A
+06
+FF
+33
+07
+B5
+00
+33
+85
+@00000830
+B6
+40
+13
+03
+19
+00
+3A
+95
+93
+07
+00
+02
+63
+D1
+D5
+3C
+@00000840
+05
+07
+A3
+0F
+F7
+FE
+E3
+1D
+A7
+FE
+83
+47
+19
+00
+E3
+9C
+@00000850
+07
+DA
+E9
+B3
+46
+89
+7D
+56
+63
+82
+C6
+32
+83
+25
+0B
+00
+@00000860
+41
+46
+11
+0B
+29
+3E
+83
+47
+19
+00
+13
+03
+19
+00
+E3
+9C
+@00000870
+07
+D8
+6D
+B3
+13
+08
+4B
+00
+21
+46
+89
+B7
+93
+E7
+27
+00
+@00000880
+13
+08
+4B
+00
+29
+46
+1D
+BF
+46
+89
+C1
+8B
+FD
+16
+63
+80
+@00000890
+07
+30
+03
+26
+0B
+00
+13
+07
+15
+00
+93
+87
+16
+00
+23
+00
+@000008A0
+C5
+00
+11
+0B
+3E
+95
+13
+03
+19
+00
+BA
+87
+13
+06
+00
+02
+@000008B0
+63
+57
+D0
+34
+85
+07
+A3
+8F
+C7
+FE
+E3
+9D
+A7
+FE
+83
+47
+@000008C0
+19
+00
+33
+05
+D7
+00
+E3
+90
+07
+D4
+89
+BB
+93
+E7
+07
+04
+@000008D0
+13
+08
+4B
+00
+41
+46
+DD
+B5
+03
+27
+0B
+00
+93
+E7
+07
+04
+@000008E0
+11
+0B
+83
+45
+07
+00
+01
+48
+93
+08
+47
+00
+93
+0E
+30
+06
+@000008F0
+A5
+4F
+29
+43
+13
+0F
+40
+06
+13
+0E
+00
+03
+13
+06
+18
+00
+@00000900
+9D
+E1
+0C
+12
+2E
+98
+23
+04
+C8
+EF
+05
+07
+63
+06
+17
+07
+@00000910
+0C
+12
+B2
+95
+23
+84
+75
+EF
+83
+45
+07
+00
+13
+08
+16
+00
+@00000920
+13
+06
+18
+00
+F9
+DD
+63
+D0
+BE
+1C
+33
+EC
+E5
+03
+93
+02
+@00000930
+01
+12
+33
+8D
+02
+01
+B3
+8C
+C2
+00
+93
+03
+28
+00
+13
+06
+@00000940
+38
+00
+B3
+C5
+E5
+03
+33
+48
+6C
+02
+B3
+82
+B4
+00
+83
+C5
+@00000950
+02
+00
+23
+04
+BD
+EE
+B3
+65
+6C
+02
+26
+98
+03
+48
+08
+00
+@00000960
+23
+84
+0C
+EF
+A6
+95
+03
+C8
+05
+00
+0C
+12
+9E
+95
+23
+84
+@00000970
+05
+EF
+05
+07
+E3
+1E
+17
+F9
+C1
+8B
+13
+88
+F6
+FF
+95
+E3
+@00000980
+B3
+87
+C6
+40
+AA
+97
+13
+07
+00
+02
+63
+54
+D6
+28
+05
+05
+@00000990
+A3
+0F
+E5
+FE
+E3
+9D
+A7
+FE
+B3
+06
+D6
+40
+C2
+96
+13
+88
+@000009A0
+F6
+FF
+3C
+00
+B3
+05
+C5
+00
+03
+C7
+07
+00
+05
+05
+85
+07
+@000009B0
+A3
+0F
+E5
+FE
+E3
+1A
+B5
+FE
+E3
+56
+D6
+E0
+2E
+87
+13
+05
+@000009C0
+00
+02
+85
+46
+05
+07
+B3
+87
+E6
+40
+C2
+97
+AE
+97
+A3
+0F
+@000009D0
+A7
+FE
+E3
+49
+F6
+FE
+05
+45
+63
+5F
+C8
+16
+2E
+95
+DD
+B3
+@000009E0
+93
+E7
+27
+00
+29
+46
+13
+03
+C0
+06
+13
+08
+4B
+00
+63
+9E
+@000009F0
+65
+20
+83
+25
+0B
+00
+46
+89
+42
+8B
+E1
+B3
+21
+46
+E5
+B7
+@00000A00
+93
+E7
+07
+04
+41
+46
+C5
+B7
+93
+E7
+07
+04
+13
+06
+C0
+06
+@00000A10
+03
+27
+0B
+00
+11
+0B
+63
+9F
+C5
+1A
+13
+F6
+07
+04
+A6
+88
+@00000A20
+09
+C6
+97
+08
+00
+00
+93
+88
+28
+59
+13
+03
+81
+00
+13
+0E
+@00000A30
+A1
+01
+9A
+85
+93
+0E
+A0
+03
+19
+A0
+A3
+8F
+D5
+FF
+03
+46
+@00000A40
+07
+00
+8D
+05
+05
+07
+13
+58
+46
+00
+3D
+8A
+46
+98
+46
+96
+@00000A50
+03
+48
+08
+00
+03
+46
+06
+00
+A3
+8E
+05
+FF
+23
+8F
+C5
+FE
+@00000A60
+E3
+9D
+C5
+FD
+C1
+8B
+13
+86
+F6
+FF
+9D
+E3
+93
+85
+F6
+FE
+@00000A70
+45
+48
+33
+07
+B5
+00
+93
+07
+00
+02
+63
+51
+D8
+1A
+05
+05
+@00000A80
+A3
+0F
+F5
+FE
+E3
+1D
+E5
+FE
+B3
+06
+B6
+40
+13
+86
+F6
+FF
+@00000A90
+AA
+87
+93
+05
+13
+01
+03
+47
+03
+00
+05
+03
+85
+07
+A3
+8F
+@00000AA0
+E7
+FE
+E3
+1A
+B3
+FE
+C5
+47
+45
+05
+63
+D7
+D7
+02
+2A
+87
+@00000AB0
+13
+08
+00
+02
+85
+45
+C5
+46
+05
+07
+B3
+87
+E5
+40
+B2
+97
+@00000AC0
+AA
+97
+A3
+0F
+07
+FF
+E3
+C9
+F6
+FE
+41
+47
+85
+47
+63
+54
+@00000AD0
+C7
+00
+93
+07
+06
+FF
+3E
+95
+83
+47
+29
+00
+13
+03
+29
+00
+@00000AE0
+E3
+93
+07
+B2
+25
+BE
+C2
+83
+E3
+DE
+BF
+E6
+B3
+C2
+65
+02
+@00000AF0
+93
+03
+01
+12
+33
+8C
+03
+01
+B2
+83
+13
+06
+28
+00
+33
+88
+@00000B00
+54
+00
+03
+48
+08
+00
+B3
+E5
+65
+02
+23
+04
+0C
+EF
+99
+BD
+@00000B10
+01
+47
+A5
+48
+13
+16
+27
+00
+32
+97
+05
+08
+06
+07
+2E
+97
+@00000B20
+83
+45
+08
+00
+13
+07
+07
+FD
+13
+86
+05
+FD
+13
+76
+F6
+0F
+@00000B30
+E3
+F2
+C8
+FE
+42
+89
+B5
+BE
+03
+27
+0B
+00
+11
+0B
+55
+B3
+@00000B40
+03
+27
+0B
+00
+83
+45
+29
+00
+11
+0B
+13
+46
+F7
+FF
+7D
+86
+@00000B50
+71
+8F
+09
+09
+B9
+BE
+91
+8E
+33
+85
+06
+01
+2E
+95
+9D
+B1
+@00000B60
+03
+47
+09
+00
+BE
+86
+AA
+87
+36
+85
+23
+80
+E7
+00
+83
+47
+@00000B70
+19
+00
+13
+03
+19
+00
+E3
+98
+07
+A8
+4D
+B4
+93
+E7
+17
+00
+@00000B80
+A1
+46
+E9
+B9
+17
+06
+00
+00
+13
+06
+86
+45
+8D
+B1
+33
+07
+@00000B90
+D5
+00
+93
+07
+00
+02
+63
+5B
+D0
+04
+05
+05
+A3
+0F
+F5
+FE
+@00000BA0
+E3
+1D
+E5
+FE
+FD
+56
+F5
+B1
+93
+09
+01
+02
+4E
+85
+BD
+B4
+@00000BB0
+13
+88
+F6
+FF
+63
+D2
+D5
+08
+B3
+87
+B6
+40
+AA
+97
+13
+07
+@00000BC0
+00
+02
+05
+05
+A3
+0F
+E5
+FE
+E3
+1D
+F5
+FE
+B3
+86
+D5
+40
+@00000BD0
+C2
+96
+3D
+B9
+46
+89
+31
+B3
+41
+46
+31
+B5
+29
+46
+21
+B5
+@00000BE0
+93
+F5
+07
+01
+B9
+C1
+2A
+87
+81
+45
+91
+B1
+83
+27
+0B
+00
+@00000BF0
+13
+07
+15
+00
+11
+0B
+23
+00
+F5
+00
+13
+03
+19
+00
+83
+47
+@00000C00
+19
+00
+3A
+85
+E3
+91
+07
+A0
+11
+BC
+46
+89
+45
+BE
+09
+05
+@00000C10
+A9
+BF
+93
+87
+E6
+FF
+C2
+86
+3E
+88
+61
+B3
+93
+87
+E6
+FF
+@00000C20
+B2
+86
+3E
+86
+B5
+B5
+2A
+87
+19
+B1
+13
+88
+F6
+FF
+E3
+45
+@00000C30
+D0
+F8
+C2
+86
+2A
+87
+E5
+BE
+C2
+86
+D9
+BE
+@00000C3C
+17
+F5
+FF
+E7
+13
+05
+45
+3C
+17
+F6
+FF
+E7
+13
+06
+06
+43
+@00000C4C
+41
+11
+09
+8E
+97
+05
+00
+00
+93
+85
+85
+08
+06
+C6
+EF
+F0
+@00000C5C
+CF
+C3
+17
+F5
+FF
+1F
+13
+05
+25
+3A
+17
+F6
+FF
+1F
+13
+06
+@00000C6C
+A6
+39
+09
+8E
+97
+05
+00
+00
+93
+85
+45
+37
+EF
+F0
+EF
+C1
+@00000C7C
+17
+F5
+FF
+1F
+13
+05
+45
+38
+17
+F6
+FF
+1F
+13
+06
+C6
+37
+@00000C8C
+09
+8E
+81
+45
+EF
+F0
+CF
+BE
+37
+45
+01
+10
+97
+F0
+FF
+E7
+@00000C9C
+E7
+80
+80
+36
+85
+45
+01
+45
+EF
+F0
+AF
+E3
+17
+05
+00
+00
+@00000CAC
+13
+05
+05
+2C
+EF
+F0
+6F
+D2
+B7
+27
+01
+10
+98
+5F
+B7
+06
+@00000CBC
+00
+C0
+B2
+40
+0A
+07
+09
+83
+98
+DF
+98
+47
+01
+45
+55
+8F
+@00000CCC
+98
+C7
+37
+07
+00
+80
+D8
+C7
+41
+01
+82
+80
+@00000CD8
+41
+11
+0F
+00
+F0
+0F
+0F
+10
+00
+00
+14
+41
+05
+47
+85
+47
+@00000CE8
+63
+86
+E6
+00
+1C
+C1
+18
+41
+E3
+1E
+F7
+FE
+38
+51
+93
+07
+@00000CF8
+05
+06
+09
+C7
+23
+A0
+07
+00
+98
+43
+6D
+FF
+93
+06
+85
+04
+@00000D08
+98
+42
+E3
+4F
+07
+FE
+13
+07
+50
+03
+38
+C5
+37
+37
+0B
+00
+@00000D18
+13
+07
+77
+A4
+3A
+C6
+74
+51
+32
+46
+13
+07
+45
+06
+63
+08
+@00000D28
+D6
+00
+B2
+46
+14
+C3
+10
+43
+B2
+46
+E3
+1C
+D6
+FE
+30
+51
+@00000D38
+85
+46
+05
+47
+63
+06
+D6
+00
+98
+C3
+94
+43
+E3
+9E
+E6
+FE
+@00000D48
+41
+01
+82
+80
+@00000D4C
+00
+30
+01
+10
+00
+30
+02
+10
+00
+30
+03
+10
+00
+30
+04
+10
+@00000D5C
+00
+30
+05
+10
+00
+30
+06
+10
+94
+F9
+FF
+FF
+30
+F9
+FF
+FF
+@00000D6C
+30
+F9
+FF
+FF
+8C
+F9
+FF
+FF
+30
+F9
+FF
+FF
+30
+F9
+FF
+FF
+@00000D7C
+30
+F9
+FF
+FF
+30
+F9
+FF
+FF
+30
+F9
+FF
+FF
+30
+F9
+FF
+FF
+@00000D8C
+30
+F9
+FF
+FF
+84
+F9
+FF
+FF
+30
+F9
+FF
+FF
+7C
+F9
+FF
+FF
+@00000D9C
+30
+F9
+FF
+FF
+30
+F9
+FF
+FF
+74
+F9
+FF
+FF
+30
+FB
+FF
+FF
+@00000DAC
+7E
+F9
+FF
+FF
+7E
+F9
+FF
+FF
+7E
+F9
+FF
+FF
+7E
+F9
+FF
+FF
+@00000DBC
+7E
+F9
+FF
+FF
+7E
+F9
+FF
+FF
+7E
+F9
+FF
+FF
+7E
+F9
+FF
+FF
+@00000DCC
+7E
+F9
+FF
+FF
+7E
+F9
+FF
+FF
+7E
+F9
+FF
+FF
+7E
+F9
+FF
+FF
+@00000DDC
+7E
+F9
+FF
+FF
+7E
+F9
+FF
+FF
+7E
+F9
+FF
+FF
+7E
+F9
+FF
+FF
+@00000DEC
+7E
+F9
+FF
+FF
+7E
+F9
+FF
+FF
+7E
+F9
+FF
+FF
+7E
+F9
+FF
+FF
+@00000DFC
+7E
+F9
+FF
+FF
+7E
+F9
+FF
+FF
+24
+FB
+FF
+FF
+7E
+F9
+FF
+FF
+@00000E0C
+7E
+F9
+FF
+FF
+7E
+F9
+FF
+FF
+7E
+F9
+FF
+FF
+7E
+F9
+FF
+FF
+@00000E1C
+7E
+F9
+FF
+FF
+7E
+F9
+FF
+FF
+7E
+F9
+FF
+FF
+90
+FD
+FF
+FF
+@00000E2C
+7E
+F9
+FF
+FF
+E2
+FA
+FF
+FF
+D4
+FA
+FF
+FF
+7E
+F9
+FF
+FF
+@00000E3C
+7E
+F9
+FF
+FF
+7E
+F9
+FF
+FF
+7E
+F9
+FF
+FF
+D4
+FA
+FF
+FF
+@00000E4C
+7E
+F9
+FF
+FF
+7E
+F9
+FF
+FF
+7E
+F9
+FF
+FF
+7E
+F9
+FF
+FF
+@00000E5C
+7E
+F9
+FF
+FF
+CC
+FA
+FF
+FF
+AE
+FA
+FF
+FF
+7E
+F9
+FF
+FF
+@00000E6C
+7E
+F9
+FF
+FF
+34
+FA
+FF
+FF
+7E
+F9
+FF
+FF
+2A
+FA
+FF
+FF
+@00000E7C
+7E
+F9
+FF
+FF
+7E
+F9
+FF
+FF
+0E
+FA
+FF
+FF
+80
+FB
+FF
+FF
+@00000E8C
+9A
+F8
+FF
+FF
+9A
+F8
+FF
+FF
+9A
+F8
+FF
+FF
+9A
+F8
+FF
+FF
+@00000E9C
+9A
+F8
+FF
+FF
+9A
+F8
+FF
+FF
+9A
+F8
+FF
+FF
+9A
+F8
+FF
+FF
+@00000EAC
+9A
+F8
+FF
+FF
+9A
+F8
+FF
+FF
+9A
+F8
+FF
+FF
+9A
+F8
+FF
+FF
+@00000EBC
+9A
+F8
+FF
+FF
+9A
+F8
+FF
+FF
+9A
+F8
+FF
+FF
+9A
+F8
+FF
+FF
+@00000ECC
+9A
+F8
+FF
+FF
+9A
+F8
+FF
+FF
+9A
+F8
+FF
+FF
+9A
+F8
+FF
+FF
+@00000EDC
+9A
+F8
+FF
+FF
+9A
+F8
+FF
+FF
+78
+FB
+FF
+FF
+9A
+F8
+FF
+FF
+@00000EEC
+9A
+F8
+FF
+FF
+9A
+F8
+FF
+FF
+9A
+F8
+FF
+FF
+9A
+F8
+FF
+FF
+@00000EFC
+9A
+F8
+FF
+FF
+9A
+F8
+FF
+FF
+9A
+F8
+FF
+FF
+84
+FB
+FF
+FF
+@00000F0C
+9A
+F8
+FF
+FF
+00
+FA
+FF
+FF
+58
+FB
+FF
+FF
+9A
+F8
+FF
+FF
+@00000F1C
+9A
+F8
+FF
+FF
+9A
+F8
+FF
+FF
+9A
+F8
+FF
+FF
+58
+FB
+FF
+FF
+@00000F2C
+9A
+F8
+FF
+FF
+9A
+F8
+FF
+FF
+9A
+F8
+FF
+FF
+9A
+F8
+FF
+FF
+@00000F3C
+9A
+F8
+FF
+FF
+74
+FB
+FF
+FF
+CC
+F9
+FF
+FF
+9A
+F8
+FF
+FF
+@00000F4C
+9A
+F8
+FF
+FF
+52
+F9
+FF
+FF
+9A
+F8
+FF
+FF
+54
+FD
+FF
+FF
+@00000F5C
+9A
+F8
+FF
+FF
+9A
+F8
+FF
+FF
+50
+FD
+FF
+FF
+48
+65
+6C
+6C
+@00000F6C
+6F
+2C
+20
+4D
+61
+72
+6D
+6F
+74
+2E
+0A
+00
+30
+31
+32
+33
+@00000F7C
+34
+35
+36
+37
+38
+39
+61
+62
+63
+64
+65
+66
+00
+00
+00
+00
+@00000F8C
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+61
+62
+63
+64
+65
+66
+@00000F9C
+67
+68
+69
+6A
+6B
+6C
+6D
+6E
+6F
+70
+71
+72
+73
+74
+75
+76
+@00000FAC
+77
+78
+79
+7A
+00
+00
+00
+00
+30
+31
+32
+33
+34
+35
+36
+37
+@00000FBC
+38
+39
+41
+42
+43
+44
+45
+46
+47
+48
+49
+4A
+4B
+4C
+4D
+4E
+@00000FCC
+4F
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+5A
+00
+00
+00
+00
+@00000FDC
+3C
+4E
+55
+4C
+4C
+3E
+00
+00
diff --git a/verilog/dv/marmot_test1/io_mapping.v b/verilog/dv/marmot_test1/io_mapping.v
new file mode 100644
index 0000000..fcd74b5
--- /dev/null
+++ b/verilog/dv/marmot_test1/io_mapping.v
@@ -0,0 +1,52 @@
+localparam io_TDO = 1;
+localparam io_TDI = 2;
+localparam io_TMS = 3;
+localparam io_TCK = 4;
+localparam io_uart0_rx = 5;
+localparam io_uart0_tx = 6;
+localparam io_spi1_csb_1 = 7;
+localparam io_spi0_flash_csb = 8;
+localparam io_spi0_flash_sck = 9;
+localparam io_spi0_flash_io_0 = 10;
+localparam io_spi0_flash_io_1 = 11;
+localparam io_spi0_flash_io_2 = 12;
+localparam io_spi0_flash_io_3 = 13;
+localparam io_spi1_csb_0 = 14;
+localparam io_spi1_sck = 15;
+localparam io_spi1_io_0 = 16;
+localparam io_spi1_io_1 = 17;
+localparam io_spi1_io_2 = 18;
+localparam io_spi1_io_3 = 19;
+localparam io_spi2_csb = 20;
+localparam io_spi2_sck = 21;
+localparam io_spi2_io_0 = 22;
+localparam io_spi2_io_1 = 23;
+localparam io_spi2_io_2 = 24;
+localparam io_spi2_io_3 = 25;
+localparam io_i2c0_sda = 26;
+localparam io_i2c0_scl = 27;
+localparam io_i2c1_sda = 28;
+localparam io_i2c1_scl = 29;
+localparam io_uart1_rx = 30;
+localparam io_uart1_tx = 31;
+localparam io_uart2_rx = 32;
+localparam io_uart2_tx = 33;
+localparam io_uart3_rx = 34;
+localparam io_uart3_tx = 35;
+localparam io_uart4_rx = 36;
+localparam io_uart4_tx = 37;
+
+// IOF1
+localparam io_pwm0_0 = 26;
+localparam io_pwm0_1 = 27;
+localparam io_pwm0_2 = 28;
+localparam io_pwm0_3 = 29;
+localparam io_pwm1_0 = 30;
+localparam io_pwm1_1 = 31;
+localparam io_pwm1_2 = 32;
+localparam io_pwm1_3 = 33;
+localparam io_pwm2_0 = 34;
+localparam io_pwm2_1 = 35;
+localparam io_pwm2_2 = 36;
+localparam io_pwm2_3 = 37;
+
diff --git a/verilog/dv/marmot_test1/marmot_test1.c b/verilog/dv/marmot_test1/marmot_test1.c
new file mode 100644
index 0000000..a0b745b
--- /dev/null
+++ b/verilog/dv/marmot_test1/marmot_test1.c
@@ -0,0 +1,174 @@
+/*
+ * SPDX-FileCopyrightText: 2020 Efabless Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+// This include is relative to $CARAVEL_PATH (see Makefile)
+#include <defs.h>
+#include <stub.c>
+
+#define MARMOT_ICACHE_TAG_RAM_CLK_DELAY   2
+#define MARMOT_ICACHE_DATA_RAM0_CLK_DELAY 5
+#define MARMOT_ICACHE_DATA_RAM1_CLK_DELAY 4
+#define MARMOT_ICACHE_DATA_RAM2_CLK_DELAY 1
+#define MARMOT_ICACHE_DATA_RAM3_CLK_DELAY 3
+
+void main()
+{
+  /* 
+  IO Control Registers
+  | DM     | VTRIP | SLOW  | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN |
+  | 3-bits | 1-bit | 1-bit | 1-bit  | 1-bit  | 1-bit | 1-bit   | 1-bit   | 1-bit | 1-bit | 1-bit   |
+  Output: 0000_0110_0000_1110  (0x1808) = GPIO_MODE_USER_STD_OUTPUT
+  | DM     | VTRIP | SLOW  | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN |
+  | 110    | 0     | 0     | 0      | 0      | 0     | 0       | 1       | 0     | 0     | 0       |
+  
+   
+  Input: 0000_0001_0000_1111 (0x0402) = GPIO_MODE_USER_STD_INPUT_NOPULL
+  | DM     | VTRIP | SLOW  | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN |
+  | 001    | 0     | 0     | 0      | 0      | 0     | 0       | 0       | 0     | 1     | 0       |
+  */
+
+  /* Set up the housekeeping SPI to be connected internally so  */
+  /* that external pin changes don't affect it.     */
+
+  reg_spi_enable = 1;
+  reg_wb_enable = 1;
+  //reg_spimaster_config = 0xa002; // Enable, prescaler = 2,
+                                        // connect to housekeeping SPI
+
+  // Connect the housekeeping SPI to the SPI master
+  // so that the CSB line is not left floating.  This allows
+  // all of the GPIO pins to be used for user functions.
+
+  // All GPIO pins are configured to be bi-directional for Marmot use
+  reg_mprj_io_37 = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_36 = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_35 = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_34 = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_33 = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_32 = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+
+#if 0
+  // For actual use
+  reg_mprj_io_31 = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_30 = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_29 = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_28 = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_27 = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_26 = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_25 = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_24 = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_23 = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_22 = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_21 = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_20 = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_19 = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_18 = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_17 = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_16 = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+#else
+  // For simulation
+  reg_mprj_io_31 = GPIO_MODE_MGMT_STD_OUTPUT;
+  reg_mprj_io_30 = GPIO_MODE_MGMT_STD_OUTPUT;
+  reg_mprj_io_29 = GPIO_MODE_MGMT_STD_OUTPUT;
+  reg_mprj_io_28 = GPIO_MODE_MGMT_STD_OUTPUT;
+  reg_mprj_io_27 = GPIO_MODE_MGMT_STD_OUTPUT;
+  reg_mprj_io_26 = GPIO_MODE_MGMT_STD_OUTPUT;
+  reg_mprj_io_25 = GPIO_MODE_MGMT_STD_OUTPUT;
+  reg_mprj_io_24 = GPIO_MODE_MGMT_STD_OUTPUT;
+  reg_mprj_io_23 = GPIO_MODE_MGMT_STD_OUTPUT;
+  reg_mprj_io_22 = GPIO_MODE_MGMT_STD_OUTPUT;
+  reg_mprj_io_21 = GPIO_MODE_MGMT_STD_OUTPUT;
+  reg_mprj_io_20 = GPIO_MODE_MGMT_STD_OUTPUT;
+  reg_mprj_io_19 = GPIO_MODE_MGMT_STD_OUTPUT;
+  reg_mprj_io_18 = GPIO_MODE_MGMT_STD_OUTPUT;
+  reg_mprj_io_17 = GPIO_MODE_MGMT_STD_OUTPUT;
+  reg_mprj_io_16 = GPIO_MODE_MGMT_STD_OUTPUT;
+#endif
+
+  reg_mprj_io_15 = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_14 = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_13 = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_12 = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_11 = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_10 = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_9  = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_8  = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_7  = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_6  = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  reg_mprj_io_5  = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  //reg_mprj_io_4  = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  //reg_mprj_io_3  = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  //reg_mprj_io_2  = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  //reg_mprj_io_1  = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+  //reg_mprj_io_0  = GPIO_MODE_USER_STD_BIDIRECTIONAL;
+
+  /* Apply configuration */
+  reg_mprj_xfer = 1;
+  while (reg_mprj_xfer == 1);
+
+  // Initialize LA probes [127:0]
+  //  Input:
+  //    [31: 0] <- Marmot.gpio_out[31:0]
+  //  Output:
+  //    [31: 0] -> Marmot.gpio_in[31:0]
+  //    [63:32] -> Marmot.ram_clk_delay_sel[31:0]
+  //                                       [ 4: 0] -> u_clk_skew_adjust_0.sel[4:0] (I-$ Tag RAM)
+  //                                       [ 9: 5] -> u_clk_skew_adjust_1.sel[4:0] (I-$ Data RAM0)
+  //                                       [14:10] -> u_clk_skew_adjust_1.sel[4:0] (I-$ Data RAM1)
+  //                                       [19:15] -> u_clk_skew_adjust_1.sel[4:0] (I-$ Data RAM2)
+  //                                       [24:20] -> u_clk_skew_adjust_1.sel[4:0] (I-$ Data RAM3)
+
+  reg_la0_oenb = reg_la0_iena = 0xffffffff; // [31:0]
+  reg_la1_oenb = reg_la1_iena = 0xffffffff; // [63:32]
+  reg_la2_oenb = reg_la2_iena = 0xffffffff; // [95:64]
+  reg_la3_oenb = reg_la3_iena = 0xffffffff; // [127:96]
+  reg_la0_data = 0xffffffff;
+  reg_la1_data = 0xffffffff;
+  reg_la2_data = 0xffffffff;
+  reg_la3_data = 0xffffffff;
+  reg_la0_data = 0x00000000;
+  reg_la1_data = 0x00000000;
+  reg_la2_data = 0x00000000;
+  reg_la3_data = 0x00000000;
+
+  // Configure LA probes [31:0] as inputs to mgmt_soc
+  reg_la0_iena = 0x00000000; // [31:0] <- Marmot.gpio_out[31:0]
+
+  // Set clock delay for Marmot RAMs
+  reg_la1_data =   (MARMOT_ICACHE_TAG_RAM_CLK_DELAY)
+                 | (MARMOT_ICACHE_DATA_RAM0_CLK_DELAY << 5)
+                 | (MARMOT_ICACHE_DATA_RAM1_CLK_DELAY << 10)
+                 | (MARMOT_ICACHE_DATA_RAM2_CLK_DELAY << 15)
+                 | (MARMOT_ICACHE_DATA_RAM3_CLK_DELAY << 20);
+
+  // Start Marmot
+  reg_mprj_slave = 0x00000001;
+
+  // Wait for Marmot to finish and check result
+  while (1) {
+    reg_la0_data ^= 0xffffffff;
+
+    if ((reg_la0_data_in & 0xc0000000) != 0x0) {
+      if ((reg_la0_data_in & 0xc0000000) == 0x80000000) {
+        reg_mprj_datal = 0x12340000;  // Pass
+      } else {
+        reg_mprj_datal = 0xdead0000;  // Fail
+      }
+      break;
+    }
+  }
+}
diff --git a/verilog/dv/marmot_test1/marmot_test1_tb.v b/verilog/dv/marmot_test1/marmot_test1_tb.v
new file mode 100644
index 0000000..717044e
--- /dev/null
+++ b/verilog/dv/marmot_test1/marmot_test1_tb.v
@@ -0,0 +1,368 @@
+// SPDX-FileCopyrightText: 2020 Efabless Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// SPDX-License-Identifier: Apache-2.0
+
+`default_nettype none
+
+`timescale 1 ns / 100 ps
+
+`define TB testbench
+`define CARAVEL `TB.uut
+`define USER_PROJECT_WRAPPER `CARAVEL.mprj
+`define MARMOT `USER_PROJECT_WRAPPER.Marmot
+`define CHIP `MARMOT.MarmotCaravelChip
+`define PLATFORM `CHIP.dut
+`define SYS `PLATFORM.sys
+`define TILE `SYS.tile_prci_domain.tile_reset_domain.tile
+`define CORE `TILE.core
+`define UART0 `SYS.uartClockDomainWrapper.uart_0
+`define UART1 `SYS.uartClockDomainWrapper_1.uart_1
+`define UART2 `SYS.uartClockDomainWrapper_2.uart_2
+`define UART3 `SYS.uartClockDomainWrapper_3.uart_3
+`define UART4 `SYS.uartClockDomainWrapper_4.uart_4
+`define TLSPIRAM `SYS.qspiClockDomainWrapper_1.qspi_ram_0
+
+module testbench;
+  `include "io_mapping.v"
+
+  localparam CLOCK_PERIOD = 40; // ns
+  localparam TCK_PERIOD = 100;
+  localparam MAX_CYCLE    = 200000;
+  localparam MAX_EXCEPTION_PC_COUNT = 100;
+
+  reg clock;
+  wire clock_wire = clock;
+  reg RSTB;
+  reg tck;
+  reg CSB;
+
+  reg power1, power2;
+
+  wire gpio;
+  wire [37:0] mprj_io;
+
+  wire        reset = `MARMOT.wb_rst_i;
+
+`ifdef SIM
+  wire [31:0] PC    = `CORE.coreMonitorBundle_pc;
+`else
+  wire [31:0] PC    = {`MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[31] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[30] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[29] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[28] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[27] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[26] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[25] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[24] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[23] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[22] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[21] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[20] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[19] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[18] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[17] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[16] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[15] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[14] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[13] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[12] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[11] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[10] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[9] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[8] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[7] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[6] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[5] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[4] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[3] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[2] ,
+                       `MARMOT.\MarmotCaravelChip.MarmotCaravelPlatform.sys.tile.core.coreMonitorBundle_pc[1] ,
+                       1'b0};
+`endif
+
+//-------------------------------------------------------------------------------
+// Timeformat
+  initial begin
+    $timeformat(-9, 0, " ns", 12);
+  end
+
+//-------------------------------------------------------------------------------
+// Pull-up
+`ifdef PULLUP_IO
+  genvar gen_i;
+  generate
+    for (gen_i = 0; gen_i < 38; gen_i = gen_i + 1) begin
+      pullup(mprj_io[gen_i]);
+    end
+  endgenerate
+`endif
+
+//-------------------------------------------------------------------------------
+// Clock
+  initial begin
+    clock = 0;
+    tck = 0;
+  end
+
+  always #(CLOCK_PERIOD/2) clock <= (clock === 1'b0);
+  always #(TCK_PERIOD/2) tck <= (tck === 1'b0);
+
+//-------------------------------------------------------------------------------
+// Waveform
+  initial begin
+    `ifdef WAVEFORM
+      $dumpfile("marmot_test1.vcd");
+      $dumpvars(0, `TB);
+    `endif
+  end
+
+//-------------------------------------------------------------------------------
+// Initialize FFs for gate level sim.
+`ifdef GL
+  `include "init_ff.v"
+`endif
+
+//-------------------------------------------------------------------------------
+// SDF annotate
+`ifdef ENABLE_SDF
+  initial begin
+    $sdf_annotate("../../../mgmt_core_wrapper/sdf/DFFRAM.sdf", `CARAVEL.soc.DFFRAM_0 );
+    $sdf_annotate("../../../mgmt_core_wrapper/sdf/mgmt_core.sdf", `CARAVEL.soc.core);
+    $sdf_annotate("../../../mgmt_core_wrapper/sdf/mgmt_core_wrapper.sdf", `CARAVEL.soc);
+    $sdf_annotate("../../../sdf/user_project_wrapper.sdf.gz", `USER_PROJECT_WRAPPER);
+    $sdf_annotate("../../../sdf/Marmot.sdf.gz", `MARMOT);
+    $sdf_annotate("../../../sdf/clk_skew_adjust.sdf.gz", `USER_PROJECT_WRAPPER.u_clk_skew_adjust_0);
+    $sdf_annotate("../../../sdf/clk_skew_adjust.sdf.gz", `USER_PROJECT_WRAPPER.u_clk_skew_adjust_1);
+    $sdf_annotate("../../../sdf/clk_skew_adjust.sdf.gz", `USER_PROJECT_WRAPPER.u_clk_skew_adjust_2);
+    $sdf_annotate("../../../sdf/clk_skew_adjust.sdf.gz", `USER_PROJECT_WRAPPER.u_clk_skew_adjust_3);
+    $sdf_annotate("../../../sdf/clk_skew_adjust.sdf.gz", `USER_PROJECT_WRAPPER.u_clk_skew_adjust_4);
+  end
+`endif
+
+//-------------------------------------------------------------------------------
+// Count cycle
+  reg [31:0] cycle;
+  initial begin
+    cycle = 0;
+  end
+
+  always @(posedge clock) begin
+    cycle = cycle + 1;
+  end
+
+//-------------------------------------------------------------------------------
+// Monitor PC
+  integer exception_pc_count;
+
+  always @ (posedge clock) begin
+  //if ($test$plusargs("pc_monitor")) begin
+      if (cycle % 1000 == 0) begin
+        $fwrite(32'h80000002, "[%t] %10d pc=%08x\n", $time, cycle, PC);
+      end
+  //end
+
+    // Finish on PC=x
+    if (^PC === 1'bx) begin
+      $display("[%t] PC=xxxxxxxx", $time);
+      repeat (50) @(posedge clock);
+      $finish;
+    end
+
+    // Finish on exception
+    if (PC == 32'h00000000 || PC == 32'h00000002) begin
+      exception_pc_count <= exception_pc_count + 1;
+      if (exception_pc_count > MAX_EXCEPTION_PC_COUNT) begin
+        $display("[%t] Exception occurred.", $time);
+        $finish;
+      end
+    end
+    else begin
+      exception_pc_count <= 0;
+    end
+  end
+
+//-------------------------------------------------------------------------------
+// Timeout
+  reg  [31:0] max_cycle;
+  initial begin
+    if (! $value$plusargs("max_cycle=%d", max_cycle)) begin
+      max_cycle = MAX_CYCLE;
+    end
+
+    wait (reset === 1'b0);
+    wait (cycle < 10);
+    wait (cycle >= max_cycle);
+    $display("\n*** Timeout ***");
+    $finish;
+  end
+
+//-------------------------------------------------------------------------------
+// Pass
+  initial begin
+    wait (mprj_io[31:16] == 16'h1234);
+    $display("\n*** Test Pass ***");
+    $finish;
+  end
+
+//-------------------------------------------------------------------------------
+// Fail
+  initial begin
+    wait (mprj_io[31:16] == 16'hdead);
+    $display("\n*** Test Fail ***");
+    $finish;
+  end
+
+//-------------------------------------------------------------------------------
+// Reset
+  initial begin
+    RSTB <= 1'b0;
+    #1000;
+    RSTB <= 1'b1;     // Release reset
+    #2000;
+  end
+
+//-------------------------------------------------------------------------------
+// Power-up sequence
+  initial begin
+    power1 <= 1'b0;
+    power2 <= 1'b0;
+    #200;
+    power1 <= 1'b1;
+    #200;
+    power2 <= 1'b1;
+  end
+
+  wire flash_csb;
+  wire flash_clk;
+  wire flash_io0;
+  wire flash_io1;
+
+  wire VDD1V8;
+  wire VDD3V3;
+  wire VSS;
+    
+  assign VDD3V3 = power1;
+  assign VDD1V8 = power2;
+  assign VSS = 1'b0;
+
+  assign mprj_io[3] = 1;  // Force CSB high.
+  assign mprj_io[0] = 0;  // Disable debug mode
+
+//-------------------------------------------------------------------------------
+// JTAG
+  assign mprj_io[io_TCK] = tck;
+  //assign mprj_io[io_TMS] = 1; // same pin as CSB
+  assign mprj_io[io_TDI] = 0;
+
+//-------------------------------------------------------------------------------
+// Caravel
+  caravel uut (
+    .vddio    (VDD3V3),
+    .vddio_2  (VDD3V3),
+    .vssio    (VSS),
+    .vssio_2  (VSS),
+    .vdda   (VDD3V3),
+    .vssa   (VSS),
+    .vccd   (VDD1V8),
+    .vssd   (VSS),
+    .vdda1    (VDD3V3),
+    .vdda1_2  (VDD3V3),
+    .vdda2    (VDD3V3),
+    .vssa1    (VSS),
+    .vssa1_2  (VSS),
+    .vssa2    (VSS),
+    .vccd1    (VDD1V8),
+    .vccd2    (VDD1V8),
+    .vssd1    (VSS),
+    .vssd2    (VSS),
+    .clock    (clock_wire),
+    .gpio     (gpio),
+    .mprj_io  (mprj_io),
+    .flash_csb(flash_csb),
+    .flash_clk(flash_clk),
+    .flash_io0(flash_io0),
+    .flash_io1(flash_io1),
+    .resetb   (RSTB)
+  );
+
+//-------------------------------------------------------------------------------
+// SPI Flash for Mgmt. SoC
+  spiflash #(
+    .FILENAME("marmot_test1.hex")
+  ) spiflash (
+    .csb(flash_csb),
+    .clk(flash_clk),
+    .io0(flash_io0),
+    .io1(flash_io1),
+    .io2(),
+    .io3()
+  );
+
+//-------------------------------------------------------------------------------
+// SPI Flash model for Marmot
+MX25U3235F #(.Init_File("spi_flash.mem")) spi_flash
+(
+    .SCLK   (mprj_io[io_spi0_flash_sck]),
+    .CS     (mprj_io[io_spi0_flash_csb]),
+    .SI     (mprj_io[io_spi0_flash_io_0]),
+    .SO     (mprj_io[io_spi0_flash_io_1]),
+    .WP     (mprj_io[io_spi0_flash_io_2]),
+    .SIO3   (mprj_io[io_spi0_flash_io_3])
+);
+
+//-------------------------------------------------------------------------------
+// SPI RAM model for Marmot
+`ifdef SIMULATOR_QUESTA
+// SPI RAM model (APM APS6404L-3SQN_SQPI_PSRAM)
+sqpi_model #(.VeriOutStr(1), .STOP_ON_ERROR(1)) spi_ram
+(
+    .SCK_i  (mprj_io[io_spi2_sck]),
+    .nCE_i  (mprj_io[io_spi2_csb]),
+    .SI_io  (mprj_io[io_spi2_io_0]),
+    .SO_io  (mprj_io[io_spi2_io_1]),
+    .nWP_io (mprj_io[io_spi2_io_2]),
+    .NC_io  (mprj_io[io_spi2_io_3])
+);
+`else
+// SPI Flash model
+MX25U3235F spi_ram
+(
+    .SCLK   (mprj_io[io_spi2_sck]),
+    .CS     (mprj_io[io_spi2_csb]),
+    .SI     (mprj_io[io_spi2_io_0]),
+    .SO     (mprj_io[io_spi2_io_1]),
+    .WP     (mprj_io[io_spi2_io_2]),
+    .SIO3   (mprj_io[io_spi2_io_3])
+);
+`endif
+
+//-------------------------------------------------------------------------------
+// UART model for Marmot
+`ifdef UART_HIGH_SPEED
+  `define CLKS_PER_BIT  16  // F_CLK / 16 baud
+`else
+  `define CLKS_PER_BIT ((1000/CLOCK_PERIOD)*1000000 / 115200)  // 115200 baud
+  //`define CLKS_PER_BIT 104  // 12MHz / 115200 baud
+`endif
+
+uart_tb #(.CLKS_PER_BIT(`CLKS_PER_BIT)) uart0_tb
+(
+    .clk        (clock_wire),
+    .rst        (~RSTB),
+    .rxd        (mprj_io[io_uart0_tx]),
+    .txd        (mprj_io[io_uart0_rx])
+);
+
+endmodule
+`default_nettype wire
diff --git a/verilog/dv/marmot_test1/setup.csh b/verilog/dv/marmot_test1/setup.csh
new file mode 100755
index 0000000..f429bd5
--- /dev/null
+++ b/verilog/dv/marmot_test1/setup.csh
@@ -0,0 +1,9 @@
+#!/bin/csh -f
+
+set testcase_dir = /home/shc/Development/RISC-V/freedom/sim/testcase
+
+#cp -p $testcase_dir/dhrystone-2.1/gcc_dry2reg_flash.mem .
+cp -p $testcase_dir/hello/spi_flash.mem hello_flash.mem
+
+$testcase_dir/../../script/mk_init_ff.py $MARMOT_ROOT/verilog/gl/Marmot.v > init_ff.v
+
diff --git a/verilog/dv/marmot_test1/spi_flash.mem b/verilog/dv/marmot_test1/spi_flash.mem
new file mode 120000
index 0000000..3cf3653
--- /dev/null
+++ b/verilog/dv/marmot_test1/spi_flash.mem
@@ -0,0 +1 @@
+hello_flash.mem
\ No newline at end of file
diff --git a/verilog/dv/vip/MX25U3235F.v b/verilog/dv/vip/MX25U3235F.v
new file mode 100644
index 0000000..b731310
--- /dev/null
+++ b/verilog/dv/vip/MX25U3235F.v
@@ -0,0 +1,3484 @@
+// *============================================================================================== 
+// *
+// *   MX25U3235F.v - 32M-BIT CMOS Serial Flash Memory
+// *
+// *           COPYRIGHT 2018 Macronix International Co., Ltd.
+// *
+// * Security Level: Macronix Proprietary
+// *----------------------------------------------------------------------------------------------
+// * Environment  : Cadence NC-Verilog
+// * Reference Doc: MX25U3235F REV.1.6,JUL.12,2017
+// * Creation Date: @(#)$Date: 2017/07/17 08:43:16 $
+// * Version      : @(#)$Revision: 1.21 $
+// * Description  : There is only one module in this file
+// *                module MX25U3235F->behavior model for the 32M-Bit flash
+// *----------------------------------------------------------------------------------------------
+// * Note 1:model can load initial flash data from file when parameter Init_File = "xxx" was defined; 
+// *        xxx: initial flash data file name;default value xxx = "none", initial flash data is "FF".
+// * Note 2:power setup time is tVSL = 800_000 ns, so after power up, chip can be enable.
+// * Note 3:because it is not checked during the Board system simulation the tCLQX timing is not
+// *        inserted to the read function flow temporarily.
+// * Note 4:more than one values (min. typ. max. value) are defined for some AC parameters in the
+// *        datasheet, but only one of them is selected in the behavior model, e.g. program and
+// *        erase cycle time is typical value. For the detailed information of the parameters,
+// *        please refer to datasheet and contact with Macronix.
+// * Note 5:If you have any question and suggestion, please send your mail to following email address :
+// *                                    flash_model@mxic.com.tw
+// *============================================================================================== 
+// * timescale define
+// *============================================================================================== 
+`timescale 1ns / 100ps
+
+// *============================================================================================== 
+// * product parameter define
+// *============================================================================================== 
+    /*----------------------------------------------------------------------*/
+    /* all the parameters users may need to change                          */
+    /*----------------------------------------------------------------------*/
+        `define Vtclqv 6  //30pf:8ns, 15pf:6ns
+        `define File_Name         "none"     // Flash data file name for normal array
+        `define File_Name_Secu    "none"     // Flash data file name for security region
+        `define File_Name_SFDP    "none"     // Flash data file name for SFDP region
+        `define VSEC_Pro_Reg      ~1'b0      // for protect
+        `define VSEC_Pro_Reg_TOP  16'hffff   // for top protect
+        `define VSEC_Pro_Reg_BOT  16'hffff   // for bottom protect
+        `define VSecur_Reg1_0     2'b00      // security register[1:0]
+        `define VSecur_Reg7       1'b0       // security register[7]
+        `define VStatus_Reg7_2    6'b0       // status register[7:2] are non-volatile bits
+    /*----------------------------------------------------------------------*/
+    /* Define controller STATE                                              */
+    /*----------------------------------------------------------------------*/
+        `define         STANDBY_STATE           0
+        `define         CMD_STATE               1
+        `define         BAD_CMD_STATE           2
+
+
+module MX25U3235F( SCLK, 
+                    CS, 
+                    SI, 
+                    SO, 
+                    WP, 
+                    SIO3 );
+
+// *============================================================================================== 
+// * Declaration of ports (input, output, inout)
+// *============================================================================================== 
+    input  SCLK;    // Signal of Clock Input
+    input  CS;      // Chip select (Low active)
+    inout  SI;      // Serial Input/Output SIO0
+    inout  SO;      // Serial Input/Output SIO1
+    inout  WP;      // Hardware write protection or Serial Input/Output SIO2
+    inout  SIO3;    // Serial Input/Output SIO3
+
+// *============================================================================================== 
+// * Declaration of parameter (parameter)
+// *============================================================================================== 
+    parameter   VERBOSE = 0;
+    /*----------------------------------------------------------------------*/
+    /* Density STATE parameter                                              */                  
+    /*----------------------------------------------------------------------*/
+    parameter   A_MSB           = 21,            
+                TOP_Add         = 22'h3fffff,
+                A_MSB_OTP       = 8,                
+                Secur_TOP_Add   = 9'h1ff,
+                Sector_MSB      = 9,
+                A_MSB_SFDP       = 6,
+                SFDP_TOP_Add     = 7'h7f,
+                Buffer_Num      = 256,
+                Block_MSB       = 5,
+                Block_NUM       = 64;
+  
+    /*----------------------------------------------------------------------*/
+    /* Define ID Parameter                                                  */
+    /*----------------------------------------------------------------------*/
+    parameter   ID_MXIC         = 8'hc2,
+                ID_Device       = 8'h36,
+                Memory_Type     = 8'h25,
+                Memory_Density  = 8'h36;
+
+    /*----------------------------------------------------------------------*/
+    /* Define Initial Memory File Name                                      */
+    /*----------------------------------------------------------------------*/
+    parameter   Init_File       = `File_Name;      // initial flash data
+    parameter   Init_File_Secu  = `File_Name_Secu; // initial flash data for security
+    parameter   Init_File_SFDP  = `File_Name_SFDP;  // initial flash data for SFDP
+
+    /*----------------------------------------------------------------------*/
+    /* AC Characters Parameter                                              */
+    /*----------------------------------------------------------------------*/
+    parameter   tSHQZ           = 8,        // CS High to SO Float Time [ns]
+                tCLQV           = `Vtclqv,          // Clock Low to Output Valid
+                tCLQX           = 0,        // Output hold time
+                tBP             = 12_000,      //  Byte program time
+                tSE             = 35_000_000,      // Sector erase time  
+                tBE             = 350_000_000,      // Block erase time
+                tBE32           = 200_000_000,    // Block 32KB erase time
+                tCE             = 25_000,      // unit is ms instead of ns  
+                tPP             = 500_000,      // Program time
+                tW              = 40_000_000,       // Write Status time 
+                tWPS            = 12_000,     // Write Protection Select time
+                tWP_SRAM        = 1_000, // Write protection sram time
+                tRCR            = 20_000,     // reset time from read
+                tRCP            = 20_000,     // reset time from program
+                tRCE            = 12_000_000,     // reset time from erase
+                tRHRL_E        = 12_000_000, // hardware reset recovery time for ers
+                                                // in operation phase
+                tRHRL_RP         = 20_000,  // hardware reset recovery time for
+                                                // read/pgm phase or instruction coding phase
+`ifdef SPEEDSIM
+                tVSL            = 10_000;      // Time delay to chip select allowed
+`else
+                tVSL            = 800_000;     // Time delay to chip select allowed
+`endif
+
+    parameter   tPGM_CHK        = 2_000, // 2 us
+                tERS_CHK        = 100_000; // 100 us
+    parameter   tESL            = 20_000,       // delay after erase suspend command
+                tPSL            = 20_000,       // delay after program suspend command
+                tPRS            = 100_000,      // latency between program resume and next suspend
+                tERS            = 400_000;      // latency between erase resume and next suspend
+
+    /*----------------------------------------------------------------------*/
+    /* Internal counter parameter                                           */
+    /*----------------------------------------------------------------------*/
+    parameter  Clock             = 50,      // Internal clock cycle = 100ns
+               ERS_Count_BE32K   = tBE32 / (Clock*2) / 500,   // Internal clock cycle = 50us
+               ERS_Count_SE      = tSE / (Clock*2) / 500,     // Internal clock cycle = 50us
+               ERS_Count_BE      = tBE / (Clock*2) / 500,     // Internal clock cycle = 50us
+               Echip_Count       = tCE  / (Clock*2) * 2000; 
+
+
+    specify
+        specparam   tSCLK   = 9.6,    // Clock Cycle Time [ns]
+                    fSCLK   = 104,    // Clock Frequence except READ instruction
+                    tTSCLK  = 11.9,    // Clock Cycle Time for 2XI/O READ instruction
+                    fTSCLK  = 84,    // Clock Frequence for 2XI/O READ instruction
+                    tTSCLK2 = 9.6,    // Clock Cycle Time for DREAD instruction
+                    fTSCLK2 = 104,    // Clock Frequence for  DREAD instruction
+                    tQSCLK  = 9.6,    // Clock Cycle Time for 4XI/O READ instruction
+                    fQSCLK  = 104,    // Clock Frequence for 4XI/O READ instruction
+                    tQSCLK2 = 11.9,   // Clock Cycle Time for 4XI/O READ instruction
+                    fQSCLK2 = 84,   // Clock Frequence for 4XI/O READ instruction
+                    tQSCLK3 = 9.6,   // Clock Cycle Time for QREAD instruction
+                    fQSCLK3 = 104,   // Clock Frequence for  QREAD instruction
+                    tRSCLK  = 18.5,   // Clock Cycle Time for READ instruction
+                    fRSCLK  = 54,   // Clock Frequence for READ instruction
+                    tCH     = 4.5,      // Clock High Time (min) [ns]
+                    tCL     = 4.5,      // Clock Low  Time (min) [ns]
+                    tCH_R   = 9,      // Clock High Time (min) [ns]
+                    tCL_R   = 9,      // Clock Low  Time (min) [ns]
+                    tSLCH   = 5,    // CS# Active Setup Time (relative to SCLK) (min) [ns]
+                    tCHSL   = 5,    // CS# Not Active Hold Time (relative to SCLK)(min) [ns]
+                    tSHSL_R = 5,    // CS High Time for read instruction (min) [ns]
+                    tSHSL_W = 30,    // CS High Time for write instruction (min) [ns]
+                    tDVCH   = 2,    // SI Setup Time (min) [ns]
+                    tCHDX   = 3,    // SI Hold  Time (min) [ns]
+                    tCHSH   = 2,    // CS# Active Hold Time (relative to SCLK) (min) [ns]
+                    tSHCH   = 3,    // CS# Not Active Setup Time (relative to SCLK) (min) [ns]
+                    tWHSL   = 10,    // Write Protection Setup Time                
+                    tSHWL   = 10,    // Write Protection Hold  Time   
+                    tRLRH   = 1_000,   // hardware reset pulse
+                    tRS     = 15,     // reset setup time
+                    tRH     = 15,     // reset hold time
+                    tDP     = 10_000,
+                    tRES1   = 30_000,
+                    tRES2   = 30_000;
+     endspecify
+
+    /*----------------------------------------------------------------------*/
+    /* Define Command Parameter                                             */
+    /*----------------------------------------------------------------------*/
+    parameter   WREN        = 8'h06, // WriteEnable   
+                WRDI        = 8'h04, // WriteDisable  
+                RDID        = 8'h9F, // ReadID    
+                RDSR        = 8'h05, // ReadStatus        
+                WRSR        = 8'h01, // WriteStatus   
+                READ1X      = 8'h03, // ReadData          
+                FASTREAD1X  = 8'h0b, // FastReadData  
+                SE          = 8'h20, // SectorErase   
+                BE2         = 8'h52, // 32k block erase
+                CE1         = 8'h60, // ChipErase         
+                CE2         = 8'hc7, // ChipErase         
+                PP          = 8'h02, // PageProgram   
+                DP          = 8'hb9, // DeepPowerDown
+                RDP         = 8'hab, // ReleaseFromDeepPowerDown 
+                RES         = 8'hab, // ReadElectricID 
+                REMS        = 8'h90, // ReadElectricManufacturerDeviceID
+                BE          = 8'hd8, // BlockErase        
+                READ2X      = 8'hbb, // 2X Read 
+                ENSO        = 8'hb1, // Enter secured OTP;
+                EXSO        = 8'hc1, // Exit  secured OTP;
+                RDSCUR      = 8'h2b, // Read  security  register;
+                WRSCUR      = 8'h2f, // Write security  register;
+                READ4X      = 8'heb, // 4XI/O Read;
+                FIOPGM0     = 8'h38, // 4I Page Pgm load address and data all 4io
+                SFDP_READ   = 8'h5a, // enter SFDP read mode
+                DREAD       = 8'h3b, // Fastread dual output;
+                QREAD       = 8'h6b, // Fastread quad output 1I/4O
+                WPSEL       = 8'h68, // write protection selection
+                SBLK        = 8'h36, // single block lock
+                SBULK       = 8'h39, // single block unlock
+                RDBLOCK     = 8'h3c, // block protect read
+                GBLK        = 8'h7e, // gang block lock
+                GBULK       = 8'h98; // gang block unlock
+    parameter   EQIO        = 8'h35, // enable quad I/O
+                RSTQIO      = 8'hf5, // reset quad I/O
+                QPIID       = 8'haf, // QPI ID read
+                W4READ      = 8'he7, // enable wrap quad read
+                NOP         = 8'h00, // no operation
+                RSTEN       = 8'h66, // reset enable
+                RST         = 8'h99, // reset memory
+                SUSP        = 8'hb0,
+                RESU        = 8'h30,
+                SBL         = 8'hc0; // set burst length
+
+    /*----------------------------------------------------------------------*/
+    /* Declaration of internal-signal                                       */
+    /*----------------------------------------------------------------------*/
+    reg  [7:0]           ARRAY[0:TOP_Add];  // memory array
+    reg  [7:0]           Status_Reg;        // Status Register
+    reg  [7:0]           CMD_BUS;
+    reg  [23:0]          SI_Reg;            // temp reg to store serial in
+    reg  [7:0]           Dummy_A[0:255];    // page size
+    reg  [A_MSB:0]       Address;           
+    reg  [Sector_MSB:0]  Sector;          
+    reg  [Block_MSB:0]   Block;    
+    reg  [Block_MSB+1:0] Block2;           
+    reg  [2:0]           STATE;
+    reg  [7:0]           SFDP_ARRAY[0:SFDP_TOP_Add];
+    reg  [15:0] SEC_Pro_Reg_TOP;
+    reg  [15:0] SEC_Pro_Reg_BOT;
+    reg  [Block_NUM - 2:1] SEC_Pro_Reg;
+
+    reg     SIO0_Reg;
+    reg     SIO1_Reg;
+    reg     SIO2_Reg;
+    reg     SIO3_Reg;
+    reg     SIO0_Out_Reg;
+    reg     SIO1_Out_Reg;
+    reg     SIO2_Out_Reg;
+    reg     SIO3_Out_Reg;
+    
+    reg     Chip_EN;
+    reg     DP_Mode;        // deep power down mode
+    reg     Read_Mode;
+    reg     Read_1XIO_Mode;
+    reg     Read_1XIO_Chk;
+
+    reg     tDP_Chk;
+    reg     tRES1_Chk;
+    reg     tRES2_Chk;
+
+    reg     RDID_Mode;
+    reg     RDSR_Mode;
+    reg     RDSCUR_Mode;
+    reg     FastRD_1XIO_Mode;   
+    reg     PP_1XIO_Mode;
+    reg     SE_4K_Mode;
+    reg     BE_Mode;
+    reg     BE32K_Mode;
+    reg     BE64K_Mode;
+    reg     CE_Mode;
+    reg     WRSR_Mode;
+    reg     RES_Mode;
+    reg     REMS_Mode;
+    reg     SCLK_EN;
+    reg     SO_OUT_EN;   // for SO
+    reg     SI_IN_EN;    // for SI
+    reg     SFDP_Mode;
+    reg     SEC_PROVFY_Mode;
+    reg     RST_CMD_EN;
+    reg     WRSCUR_Mode;
+    reg     WR_WPSEL_Mode;
+    reg     EN_Burst;
+    reg     W4Read_Mode;
+    reg     During_Susp_Wait;
+    reg     Susp_Ready;
+    reg     Susp_Trig;
+    reg     Resume_Trig;
+    reg     ERS_CLK;                  // internal clock register for erase timer
+    reg     PGM_CLK;                  // internal clock register for program timer
+    reg     WR2Susp;
+
+    wire    CS_INT;
+    wire    WP_B_INT;
+    wire    RESETB_INT;
+    wire    SCLK; 
+    wire    WIP;
+    wire    ESB;
+    wire    PSB;
+    wire    EPSUSP;
+    wire    WEL;
+    wire    SRWD;
+    wire    Dis_CE, Dis_WRSR;  
+    wire    WPSEL_Mode;
+    wire    Norm_Array_Mode;
+
+    wire    Pgm_Mode;
+    wire    Ers_Mode;
+
+    event   Resume_Event; 
+    event   Susp_Event; 
+    event   WRSR_Event; 
+    event   BE_Event;
+    event   SE_4K_Event;
+    event   CE_Event;
+    event   PP_Event;
+    event   BE32K_Event;
+    event   WPSEL_Event;
+    event   SBLK_Event;
+    event   SBULK_Event;
+    event   GBLK_Event;
+    event   GBULK_Event;
+    event   RST_Event;
+    event   RST_EN_Event;
+    event   HDRST_Event;
+
+    integer i;
+    integer j;
+    integer Bit; 
+    integer Bit_Tmp; 
+    integer Start_Add;
+    integer End_Add;
+    integer tWRSR;
+    integer Burst_Length;
+//    time    tRES;
+    time    ERS_Time;
+    time    tPP_Real;   //program time according to programmed byte number
+    reg Read_SHSL;
+    wire Write_SHSL;
+
+    reg  [7:0]           Secur_ARRAY[0:Secur_TOP_Add]; // Secured OTP 
+    reg  [7:0]           Secur_Reg;         // security register
+
+    reg     Secur_Mode;     // enter secured mode
+    reg     Read_2XIO_Mode;
+    reg     Read_2XIO_Chk;
+    reg     Byte_PGM_Mode;          
+    reg     SI_OUT_EN;   // for SI
+    reg     SO_IN_EN;    // for SO
+    event   WRSCUR_Event;
+   
+    reg     Read_4XIO_Mode;
+    reg     READ4X_Mode;
+    reg     FREAD4X_Mode;
+    reg     Read_4XIO_Chk;
+    reg     FastRD_2XIO_Mode;
+    reg     FastRD_2XIO_Chk;
+    reg     FastRD_4XIO_Mode;
+    reg     FastRD_4XIO_Chk;
+    reg     PP_4XIO_Mode;
+    reg     PP_4XIO_Load;
+    reg     PP_4XIO_Chk;
+    reg     EN4XIO_Read_Mode;
+    reg     Set_4XIO_Enhance_Mode;
+    reg     WP_OUT_EN;   // for WP pin
+    reg     SIO3_OUT_EN; // for SIO3 pin
+    reg     WP_IN_EN;    // for WP pin
+    reg     SIO3_IN_EN;  // for SIO3 pin
+    reg     ENQUAD;
+    reg     During_RST_REC;
+    wire    HPM_RD;
+    wire    SIO3;
+    wire    fQ_84M;
+    wire    fQ_104M;
+    assign  fQ_84M  = ((CMD_BUS == FASTREAD1X & ENQUAD ) | (CMD_BUS == W4READ) )& Read_4XIO_Chk;
+    assign  fQ_104M = !fQ_84M && Read_4XIO_Chk;
+    /*----------------------------------------------------------------------*/
+    /* initial variable value                                               */
+    /*----------------------------------------------------------------------*/
+    initial begin
+        
+        Chip_EN         = 1'b0;
+        Secur_Reg       = {`VSecur_Reg7,5'b0_0000,`VSecur_Reg1_0};
+        Status_Reg      = {`VStatus_Reg7_2,2'b00};
+        READ4X_Mode     = 1'b0;
+        reset_sm;
+    end   
+
+    task reset_sm; 
+        begin
+            SEC_Pro_Reg[Block_NUM - 2:1] = `VSEC_Pro_Reg;
+            SEC_Pro_Reg_TOP[15:0] = `VSEC_Pro_Reg_TOP;
+            SEC_Pro_Reg_BOT[15:0] = `VSEC_Pro_Reg_BOT;
+            During_RST_REC  = 1'b0;
+            WRSCUR_Mode     = 1'b0;
+            WR_WPSEL_Mode   = 1'b0;
+            SIO0_Reg        = 1'b1;
+            SIO1_Reg        = 1'b1;
+            SIO2_Reg        = 1'b1;
+            SIO3_Reg        = 1'b1;
+            SIO0_Out_Reg    = 1'b1;
+            SIO1_Out_Reg    = 1'b1;
+            SIO2_Out_Reg    = 1'b1;
+            SIO3_Out_Reg    = 1'b1;
+            RST_CMD_EN      = 1'b0;
+            ENQUAD          = 1'b0;
+            SO_OUT_EN       = 1'b0; // SO output enable
+            SI_IN_EN        = 1'b0; // SI input enable
+            CMD_BUS         = 8'b0000_0000;
+            Address         = 0;
+            i               = 0;
+            j               = 0;
+            Bit             = 0;
+            Bit_Tmp         = 0;
+            Start_Add       = 0;
+            End_Add         = 0;
+            DP_Mode         = 1'b0;
+            SCLK_EN         = 1'b1;
+            Read_Mode       = 1'b0;
+            Read_1XIO_Mode  = 1'b0;
+            Read_1XIO_Chk   = 1'b0;
+            tDP_Chk         = 1'b0;
+            tRES1_Chk       = 1'b0;
+            tRES2_Chk       = 1'b0;
+
+            RDID_Mode       = 1'b0;
+            RDSR_Mode       = 1'b0;
+            RDSCUR_Mode     = 1'b0;
+
+            PP_1XIO_Mode    = 1'b0;
+            SE_4K_Mode      = 1'b0;
+            BE_Mode         = 1'b0;
+            BE32K_Mode      = 1'b0;
+            BE64K_Mode      = 1'b0;
+            CE_Mode         = 1'b0;
+            WRSR_Mode       = 1'b0;
+            RES_Mode        = 1'b0;
+            REMS_Mode       = 1'b0;
+            Read_SHSL       = 1'b0;
+            FastRD_1XIO_Mode  = 1'b0;
+            FastRD_2XIO_Mode  = 1'b0;
+            FastRD_2XIO_Chk = 1'b0;
+            FastRD_4XIO_Mode  = 1'b0;
+            FastRD_4XIO_Chk = 1'b0;
+            SI_OUT_EN       = 1'b0; // SI output enable
+            SO_IN_EN        = 1'b0; // SO input enable
+            Secur_Mode      = 1'b0;
+            Read_2XIO_Mode  = 1'b0;
+            Read_2XIO_Chk   = 1'b0;
+            Byte_PGM_Mode   = 1'b0;
+            WP_OUT_EN       = 1'b0; // for WP pin output enable
+            SIO3_OUT_EN     = 1'b0; // for SIO3 pin output enable
+            WP_IN_EN        = 1'b0; // for WP pin input enable
+            SIO3_IN_EN      = 1'b0; // for SIO3 pin input enable
+            Read_4XIO_Mode  = 1'b0;
+            W4Read_Mode     = 1'b0;
+            FREAD4X_Mode    = 1'b0;
+            Read_4XIO_Chk   = 1'b0;
+            PP_4XIO_Mode    = 1'b0;
+            PP_4XIO_Load    = 1'b0;
+            PP_4XIO_Chk     = 1'b0;
+            EN4XIO_Read_Mode  = 1'b0;
+            Set_4XIO_Enhance_Mode = 1'b0;
+            SFDP_Mode = 1'b0;
+            SEC_PROVFY_Mode   = 1'b0;
+            EN_Burst          = 1'b0;
+            Burst_Length      = 8;
+            During_Susp_Wait  = 0;
+            Susp_Ready        = 1'b1;
+            Susp_Trig         = 1'b0;
+            Resume_Trig       = 1'b0;
+            ERS_CLK           = 1'b0;
+            PGM_CLK           = 1'b0;
+            WR2Susp          = 1'b0;
+        end
+    endtask // reset_sm
+    
+    /*----------------------------------------------------------------------*/
+    /* initial flash data                                                   */
+    /*----------------------------------------------------------------------*/
+    initial 
+    begin : memory_initialize
+        for ( i = 0; i <=  TOP_Add; i = i + 1 )
+            ARRAY[i] = 8'hff; 
+        if ( Init_File != "none" )
+            $readmemh(Init_File,ARRAY) ;
+        for( i = 0; i <=  Secur_TOP_Add; i = i + 1 ) begin
+            Secur_ARRAY[i]=8'hff;
+        end
+        if ( Init_File_Secu != "none" )
+            $readmemh(Init_File_Secu,Secur_ARRAY) ;
+        for( i = 0; i <=  SFDP_TOP_Add; i = i + 1 ) begin
+            SFDP_ARRAY[i] = 8'hff;
+        end
+        if ( Init_File_SFDP != "none" )
+            $readmemh(Init_File_SFDP,SFDP_ARRAY) ;
+        // define SFDP code
+        SFDP_ARRAY[8'h0] =  8'h53;
+        SFDP_ARRAY[8'h1] =  8'h46;
+        SFDP_ARRAY[8'h2] =  8'h44;
+        SFDP_ARRAY[8'h3] =  8'h50;
+        SFDP_ARRAY[8'h4] =  8'h00;
+        SFDP_ARRAY[8'h5] =  8'h01;
+        SFDP_ARRAY[8'h6] =  8'h01;
+        SFDP_ARRAY[8'h7] =  8'hff;
+        SFDP_ARRAY[8'h8] =  8'h00;
+        SFDP_ARRAY[8'h9] =  8'h00;
+        SFDP_ARRAY[8'ha] =  8'h01;
+        SFDP_ARRAY[8'hb] =  8'h09;
+        SFDP_ARRAY[8'hc] =  8'h30;
+        SFDP_ARRAY[8'hd] =  8'h00;
+        SFDP_ARRAY[8'he] =  8'h00;
+        SFDP_ARRAY[8'hf] =  8'hff;
+        SFDP_ARRAY[8'h10] =  8'hc2;
+        SFDP_ARRAY[8'h11] =  8'h00;
+        SFDP_ARRAY[8'h12] =  8'h01;
+        SFDP_ARRAY[8'h13] =  8'h04;
+        SFDP_ARRAY[8'h14] =  8'h60;
+        SFDP_ARRAY[8'h15] =  8'h00;
+        SFDP_ARRAY[8'h16] =  8'h00;
+        SFDP_ARRAY[8'h17] =  8'hff;
+        SFDP_ARRAY[8'h18] =  8'hff;
+        SFDP_ARRAY[8'h19] =  8'hff;
+        SFDP_ARRAY[8'h1a] =  8'hff;
+        SFDP_ARRAY[8'h1b] =  8'hff;
+        SFDP_ARRAY[8'h1c] =  8'hff;
+        SFDP_ARRAY[8'h1d] =  8'hff;
+        SFDP_ARRAY[8'h1e] =  8'hff;
+        SFDP_ARRAY[8'h1f] =  8'hff;
+        SFDP_ARRAY[8'h20] =  8'hff;
+        SFDP_ARRAY[8'h21] =  8'hff;
+        SFDP_ARRAY[8'h22] =  8'hff;
+        SFDP_ARRAY[8'h23] =  8'hff;
+        SFDP_ARRAY[8'h24] =  8'hff;
+        SFDP_ARRAY[8'h25] =  8'hff;
+        SFDP_ARRAY[8'h26] =  8'hff;
+        SFDP_ARRAY[8'h27] =  8'hff;
+        SFDP_ARRAY[8'h28] =  8'hff;
+        SFDP_ARRAY[8'h29] =  8'hff;
+        SFDP_ARRAY[8'h2a] =  8'hff;
+        SFDP_ARRAY[8'h2b] =  8'hff;
+        SFDP_ARRAY[8'h2c] =  8'hff;
+        SFDP_ARRAY[8'h2d] =  8'hff;
+        SFDP_ARRAY[8'h2e] =  8'hff;
+        SFDP_ARRAY[8'h2f] =  8'hff;
+        SFDP_ARRAY[8'h30] =  8'he5;
+        SFDP_ARRAY[8'h31] =  8'h20;
+        SFDP_ARRAY[8'h32] =  8'hf1;
+        SFDP_ARRAY[8'h33] =  8'hff;
+        SFDP_ARRAY[8'h34] =  8'hff;
+        SFDP_ARRAY[8'h35] =  8'hff;
+        SFDP_ARRAY[8'h36] =  8'hff;
+        SFDP_ARRAY[8'h37] =  8'h01;
+        SFDP_ARRAY[8'h38] =  8'h44;
+        SFDP_ARRAY[8'h39] =  8'heb;
+        SFDP_ARRAY[8'h3a] =  8'h08;
+        SFDP_ARRAY[8'h3b] =  8'h6b;
+        SFDP_ARRAY[8'h3c] =  8'h08;
+        SFDP_ARRAY[8'h3d] =  8'h3b;
+        SFDP_ARRAY[8'h3e] =  8'h04;
+        SFDP_ARRAY[8'h3f] =  8'hbb;
+        SFDP_ARRAY[8'h40] =  8'hfe;
+        SFDP_ARRAY[8'h41] =  8'hff;
+        SFDP_ARRAY[8'h42] =  8'hff;
+        SFDP_ARRAY[8'h43] =  8'hff;
+        SFDP_ARRAY[8'h44] =  8'hff;
+        SFDP_ARRAY[8'h45] =  8'hff;
+        SFDP_ARRAY[8'h46] =  8'h00;
+        SFDP_ARRAY[8'h47] =  8'hff;
+        SFDP_ARRAY[8'h48] =  8'hff;
+        SFDP_ARRAY[8'h49] =  8'hff;
+        SFDP_ARRAY[8'h4a] =  8'h44;
+        SFDP_ARRAY[8'h4b] =  8'heb;
+        SFDP_ARRAY[8'h4c] =  8'h0c;
+        SFDP_ARRAY[8'h4d] =  8'h20;
+        SFDP_ARRAY[8'h4e] =  8'h0f;
+        SFDP_ARRAY[8'h4f] =  8'h52;
+        SFDP_ARRAY[8'h50] =  8'h10;
+        SFDP_ARRAY[8'h51] =  8'hd8;
+        SFDP_ARRAY[8'h52] =  8'h00;
+        SFDP_ARRAY[8'h53] =  8'hff;
+        SFDP_ARRAY[8'h54] =  8'hff;
+        SFDP_ARRAY[8'h55] =  8'hff;
+        SFDP_ARRAY[8'h56] =  8'hff;
+        SFDP_ARRAY[8'h57] =  8'hff;
+        SFDP_ARRAY[8'h58] =  8'hff;
+        SFDP_ARRAY[8'h59] =  8'hff;
+        SFDP_ARRAY[8'h5a] =  8'hff;
+        SFDP_ARRAY[8'h5b] =  8'hff;
+        SFDP_ARRAY[8'h5c] =  8'hff;
+        SFDP_ARRAY[8'h5d] =  8'hff;
+        SFDP_ARRAY[8'h5e] =  8'hff;
+        SFDP_ARRAY[8'h5f] =  8'hff;
+        SFDP_ARRAY[8'h60] =  8'h00;
+        SFDP_ARRAY[8'h61] =  8'h20;
+        SFDP_ARRAY[8'h62] =  8'h50;
+        SFDP_ARRAY[8'h63] =  8'h16;
+        SFDP_ARRAY[8'h64] =  8'h9d;
+        SFDP_ARRAY[8'h65] =  8'hf9;
+        SFDP_ARRAY[8'h66] =  8'hc0;
+        SFDP_ARRAY[8'h67] =  8'h64;
+        SFDP_ARRAY[8'h68] =  8'hd9;
+        SFDP_ARRAY[8'h69] =  8'hc8;
+        SFDP_ARRAY[8'h6a] =  8'hff;
+        SFDP_ARRAY[8'h6b] =  8'hff;
+        SFDP_ARRAY[8'h6c] =  8'hff;
+        SFDP_ARRAY[8'h6d] =  8'hff;
+        SFDP_ARRAY[8'h6e] =  8'hff;
+        SFDP_ARRAY[8'h6f] =  8'hff;
+    end
+
+// *============================================================================================== 
+// * Input/Output bus operation 
+// *============================================================================================== 
+    assign   CS_INT     = ( During_RST_REC == 1'b0 && RESETB_INT == 1'b1 && Chip_EN ) ? CS : 1'b1;
+    assign   WP_B_INT   = (Status_Reg[6] == 1'b0 && !ENQUAD) ? WP : 1'b1;
+    assign   SO         = SO_OUT_EN ? SIO1_Out_Reg : 1'bz ;
+    assign   SI         = SI_OUT_EN ? SIO0_Out_Reg : 1'bz ;
+    assign   WP         = WP_OUT_EN   ? SIO2_Out_Reg : 1'bz ;
+    assign   SIO3       = SIO3_OUT_EN ? SIO3_Out_Reg : 1'bz ;
+    assign   RESETB_INT = (Status_Reg[6] == 1'b0 && ENQUAD == 1'b0)? ((SIO3 === 1'b1 || SIO3 === 1'b0) ? SIO3 : 1'b1): 1'b1;
+
+    /*----------------------------------------------------------------------*/
+    /* output buffer                                                        */
+    /*----------------------------------------------------------------------*/
+    always @( SIO3_Reg or SIO2_Reg or SIO1_Reg or SIO0_Reg ) begin
+        if ( SIO3_OUT_EN && WP_OUT_EN && SO_OUT_EN && SI_OUT_EN ) begin
+            SIO3_Out_Reg <= #tCLQV SIO3_Reg;
+            SIO2_Out_Reg <= #tCLQV SIO2_Reg;
+            SIO1_Out_Reg <= #tCLQV SIO1_Reg;
+            SIO0_Out_Reg <= #tCLQV SIO0_Reg;
+        end
+        else if ( SO_OUT_EN && SI_OUT_EN ) begin
+            SIO1_Out_Reg <= #tCLQV SIO1_Reg;
+            SIO0_Out_Reg <= #tCLQV SIO0_Reg;
+        end
+        else if ( SO_OUT_EN ) begin
+            SIO1_Out_Reg <= #tCLQV SIO1_Reg;
+        end
+    end
+
+// *============================================================================================== 
+// * Finite State machine to control Flash operation
+// *============================================================================================== 
+    /*----------------------------------------------------------------------*/
+    /* power on                                                             */
+    /*----------------------------------------------------------------------*/
+    initial begin 
+        Chip_EN   <= #tVSL 1'b1;// Time delay to chip select allowed 
+    end
+    
+    /*----------------------------------------------------------------------*/
+    /* Command Decode                                                       */
+    /*----------------------------------------------------------------------*/
+    assign ESB      = Secur_Reg[3] ;
+    assign PSB      = Secur_Reg[2] ;
+    assign EPSUSP   = ESB | PSB ;
+    assign WIP      = Status_Reg[0] ;
+    assign WEL      = Status_Reg[1] ;
+    assign SRWD     = Status_Reg[7] ;
+    assign Dis_CE   = Status_Reg[5] == 1'b1 || Status_Reg[4] == 1'b1 ||
+                      Status_Reg[3] == 1'b1 || Status_Reg[2] == 1'b1;
+    assign HPM_RD   = EN4XIO_Read_Mode == 1'b1 ;  
+    assign Norm_Array_Mode = ~Secur_Mode;
+    assign Dis_WRSR = (WP_B_INT == 1'b0 && Status_Reg[7] == 1'b1) || (!Norm_Array_Mode);
+    assign Pgm_Mode = PP_1XIO_Mode || PP_4XIO_Mode;
+    assign Ers_Mode = SE_4K_Mode || BE_Mode;
+    assign WPSEL_Mode = Secur_Reg[7];
+     
+    always @ ( negedge CS_INT ) begin
+        SI_IN_EN = 1'b1; 
+        if ( ENQUAD ) begin
+            SO_IN_EN    = 1'b1;
+            SI_IN_EN    = 1'b1;
+            WP_IN_EN    = 1'b1;
+            SIO3_IN_EN  = 1'b1;
+        end
+        if ( EN4XIO_Read_Mode == 1'b1 ) begin
+            if (VERBOSE) $display( $time, " Enter READX4 Function ..." );
+            Read_SHSL = 1'b1;
+            STATE   <= `CMD_STATE;
+            Read_4XIO_Mode = 1'b1; 
+        end
+        if ( HPM_RD == 1'b0 ) begin
+            Read_SHSL <= #1 1'b0;   
+        end
+        #1;
+        tDP_Chk = 1'b0;
+        tRES1_Chk = 1'b0;
+        tRES2_Chk = 1'b0;
+    end
+
+
+    always @ ( posedge SCLK or posedge CS_INT ) begin
+        #0;  
+        if ( CS_INT == 1'b0 ) begin
+            if ( ENQUAD ) begin
+                Bit_Tmp = Bit_Tmp + 4;
+                Bit     = Bit_Tmp - 1;
+            end
+            else begin
+                Bit_Tmp = Bit_Tmp + 1;
+                Bit     = Bit_Tmp - 1;
+            end
+            if ( SI_IN_EN == 1'b1 && SO_IN_EN == 1'b1 && WP_IN_EN == 1'b1 && SIO3_IN_EN == 1'b1 ) begin
+                SI_Reg[23:0] = {SI_Reg[19:0], SIO3, WP, SO, SI};
+            end 
+            else  if ( SI_IN_EN == 1'b1 && SO_IN_EN == 1'b1 ) begin
+                SI_Reg[23:0] = {SI_Reg[21:0], SO, SI};
+            end
+            else begin 
+                SI_Reg[23:0] = {SI_Reg[22:0], SI};
+            end
+
+            if ( (EN4XIO_Read_Mode == 1'b1 && ((Bit == 5 && !ENQUAD) || (Bit == 23 && ENQUAD))) ) begin
+                Address = SI_Reg[A_MSB:0];
+                load_address(Address);
+            end  
+        end     
+  
+        if ( Bit == 7 && CS_INT == 1'b0 && ~HPM_RD ) begin
+            STATE = `CMD_STATE;
+            CMD_BUS = SI_Reg[7:0];
+            if (VERBOSE) $display( $time," SI_Reg[7:0]= %h ", SI_Reg[7:0] );
+            if ( During_RST_REC )
+                $display ($time," During reset recovery time, there is command. \n");
+        end
+
+        if ( (EN4XIO_Read_Mode && (Bit == 1 || ENQUAD && Bit==7)) && CS_INT == 1'b0
+             && HPM_RD && (SI_Reg[7:0]== RSTEN || SI_Reg[7:0]== RST)) begin
+            CMD_BUS = SI_Reg[7:0];
+            if (VERBOSE) $display( $time," SI_Reg[7:0]= %h ", SI_Reg[7:0] );
+        end
+
+        if ( CS == 1'b1 && RST_CMD_EN &&
+             ( (Bit+1)%8 == 0 || (EN4XIO_Read_Mode && !ENQUAD && (Bit+1)%2 == 0) ) ) begin
+            RST_CMD_EN <= #1 1'b0;
+        end
+        
+        case ( STATE )
+            `STANDBY_STATE: 
+                begin
+                end
+        
+            `CMD_STATE: 
+                begin
+                    case ( CMD_BUS ) 
+                    WREN: 
+                        begin
+                            if ( !DP_Mode && !WIP && Chip_EN && ~HPM_RD && !PSB ) begin
+                                if ( CS_INT == 1'b1 && Bit == 7 ) begin 
+                                    // $display( $time, " Enter Write Enable Function ..." );
+                                    write_enable;
+                                end
+                                else if ( Bit > 7 )
+                                    STATE <= `BAD_CMD_STATE; 
+                            end 
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE; 
+                        end
+                     
+                    WRDI:   
+                        begin
+                            if ( !DP_Mode && ( !WIP || During_Susp_Wait ) && Chip_EN && ~HPM_RD ) begin
+                                if ( CS_INT == 1'b1 && Bit == 7 ) begin 
+                                    // $display( $time, " Enter Write Disable Function ..." );
+                                    write_disable;
+                                end
+                                else if ( Bit > 7 )
+                                    STATE <= `BAD_CMD_STATE; 
+                            end 
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE; 
+                        end 
+
+                  RDID:
+                      begin
+                          if ( !DP_Mode && !WIP && Chip_EN && ~HPM_RD && !ENQUAD ) begin
+                              if (VERBOSE) $display( $time, " Enter Read ID Function ..." );
+                               Read_SHSL = 1'b1;
+                               RDID_Mode = 1'b1;
+                           end
+                          else if ( Bit == 7 )
+                              STATE <= `BAD_CMD_STATE;
+                        end
+
+                   QPIID:
+                        begin
+                            if ( !DP_Mode && !WIP && Chip_EN && ~HPM_RD && ENQUAD ) begin
+                                if (VERBOSE) $display( $time, " Enter Read ID Function ..." );
+                                Read_SHSL = 1'b1;
+                                RDID_Mode = 1'b1;
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;
+                        end
+
+                      
+                    RDSR:
+                        begin 
+                            if ( !DP_Mode && Chip_EN && ~HPM_RD) begin 
+                                if (VERBOSE) $display( $time, " Enter Read Status Function ..." );
+                                Read_SHSL = 1'b1;
+                                RDSR_Mode = 1'b1 ;
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;        
+                        end
+
+           
+                    WRSR:
+                        begin
+                            if ( !DP_Mode && !WIP && WEL && Chip_EN && ~HPM_RD && !EPSUSP ) begin
+                                if ( CS_INT == 1'b1 && Bit == 15 ) begin
+                                    if ( Dis_WRSR ) begin 
+                                        Status_Reg[1] = 1'b0; 
+                                    end
+                                    else begin 
+                                        if (VERBOSE) $display( $time, " Enter Write Status Function ..." ); 
+                                        ->WRSR_Event;
+                                        WRSR_Mode = 1'b1;
+                                    end                  
+                                end    
+                                else if ( CS_INT == 1'b1 && Bit < 15 || Bit > 15 )
+                                    STATE <= `BAD_CMD_STATE;
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;
+                        end 
+                      
+                    SBL:
+                        begin
+                            if ( !DP_Mode && !WIP && Chip_EN && ~HPM_RD ) begin  // no WEL
+                                if ( CS_INT == 1'b1 && Bit == 15 ) begin
+                                    if (VERBOSE) $display( $time, " Enter Set Burst Length Function ..." );
+                                    EN_Burst = !SI_Reg[4];
+                                    if ( SI_Reg[7:5]==3'b000 && SI_Reg[3:2]==2'b00 ) begin
+                                        if ( SI_Reg[1:0]==2'b00 )
+                                            Burst_Length = 8;
+                                        else if ( SI_Reg[1:0]==2'b01 )
+                                            Burst_Length = 16;
+                                        else if ( SI_Reg[1:0]==2'b10 )
+                                            Burst_Length = 32;
+                                        else if ( SI_Reg[1:0]==2'b11 )
+                                            Burst_Length = 64;
+                                    end
+                                    else begin
+                                        Burst_Length = 8;
+                                    end
+                                end
+                                else if ( CS_INT == 1'b1 && Bit < 15 || Bit > 15 )
+                                    STATE <= `BAD_CMD_STATE;
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;
+                        end
+
+                    READ1X: 
+                        begin
+                            if ( !DP_Mode && !WIP && Chip_EN && ~HPM_RD && !ENQUAD ) begin
+                                if (VERBOSE) $display( $time, " Enter Read Data Function ..." );
+                                Read_SHSL = 1'b1;
+                                if ( Bit == 31 ) begin
+                                    Address = SI_Reg [A_MSB:0];
+                                    load_address(Address);
+                                end
+                                Read_1XIO_Mode = 1'b1;
+                            end 
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;                                
+                        end
+
+                    W4READ:
+                        begin
+                            if ( !DP_Mode && !WIP && Status_Reg[6] && Chip_EN && ~HPM_RD && !ENQUAD ) begin
+                                if (VERBOSE) $display( $time, " Enter Quad I/O Read Data Function ..." );
+                                Read_SHSL = 1'b1;
+                                if ( Bit == 13 ) begin
+                                    Address = SI_Reg [A_MSB:0];
+                                    load_address(Address);
+                                end
+                                Read_4XIO_Mode = 1'b1;
+                                W4Read_Mode = 1'b1;
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;
+                        end
+                     
+                    FASTREAD1X:
+                        begin
+                            if ( !DP_Mode && !WIP && Chip_EN && ~HPM_RD ) begin
+                                if (VERBOSE) $display( $time, " Enter Fast Read Data Function ..." );
+                                Read_SHSL = 1'b1;
+                                if ( Bit == 31 ) begin
+                                    Address = SI_Reg [A_MSB:0];
+                                    load_address(Address);
+                                end
+                                if (ENQUAD) begin
+                                    Read_4XIO_Mode = 1'b1;
+                                    FREAD4X_Mode   = 1'b1;
+                                end
+                                else begin
+                                    FastRD_1XIO_Mode = 1'b1;
+                                end
+                            end 
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;                                
+                        end
+                    SE: 
+                        begin
+                            if ( !DP_Mode && !WIP && WEL && !Secur_Mode &&  Chip_EN && ~HPM_RD && !EPSUSP ) begin
+                                if ( Bit == 31 ) begin
+                                    Address = SI_Reg [A_MSB:0];
+                                end
+                                if ( CS_INT == 1'b1 && Bit == 31 ) begin
+                                    if (VERBOSE) $display( $time, " Enter Sector Erase Function ..." );
+                                    ->SE_4K_Event;
+                                    SE_4K_Mode = 1'b1;
+                                end
+                                else if ( CS_INT == 1'b1 && Bit < 31 || Bit > 31 )
+                                     STATE <= `BAD_CMD_STATE;
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;
+                        end
+
+                    BE: 
+                        begin
+                            if ( !DP_Mode && !WIP && WEL && !Secur_Mode &&  Chip_EN && ~HPM_RD && !EPSUSP ) begin
+                                if ( Bit == 31 ) begin
+                                    Address = SI_Reg [A_MSB:0];
+                                end
+                                if ( CS_INT == 1'b1 && Bit == 31 ) begin
+                                    if (VERBOSE) $display( $time, " Enter Block Erase Function ..." );
+                                    ->BE_Event;
+                                    BE_Mode = 1'b1;
+                                    BE64K_Mode = 1'b1;
+                                end 
+                                else if ( CS_INT == 1'b1 && Bit < 31 || Bit > 31 )
+                                    STATE <= `BAD_CMD_STATE;
+                            end 
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;
+                        end
+
+                    BE2:
+                        begin
+                            if ( !DP_Mode && !WIP && WEL && !Secur_Mode && Chip_EN && ~HPM_RD && !EPSUSP ) begin
+                                if ( Bit == 31 ) begin
+                                    Address = SI_Reg [A_MSB:0];
+                                end
+                                if ( CS_INT == 1'b1 && Bit == 31  ) begin
+                                    if (VERBOSE) $display( $time, " Enter Block 32K Erase Function ..." );
+                                    ->BE32K_Event;
+                                    BE_Mode = 1'b1;
+                                    BE32K_Mode = 1'b1;
+                                end
+                                else if ( CS_INT == 1'b1 && Bit < 31 || Bit > 31 )
+                                    STATE <= `BAD_CMD_STATE;
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;
+                        end
+
+                    SUSP:
+                        begin
+                            if ( !DP_Mode && !Secur_Mode &&  Chip_EN && ~HPM_RD && !EPSUSP ) begin
+                                if ( CS_INT == 1'b1 && Bit == 7 ) begin
+                                    if (VERBOSE) $display( $time, " Enter Suspend Function ..." );
+                                    ->Susp_Event;
+                                end
+                                else if ( Bit > 7 )
+                                    STATE <= `BAD_CMD_STATE;
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;
+                        end
+
+                    RESU:
+                        begin
+                            if ( !DP_Mode && !WIP && Chip_EN && ~HPM_RD && EPSUSP ) begin
+                                if ( CS_INT == 1'b1 && Bit == 7 ) begin
+                                    if (VERBOSE) $display( $time, " Enter Resume Function ..." );
+                                    Secur_Mode = 1'b0;
+                                    ->Resume_Event;
+                                end
+                                else if ( Bit > 7 )
+                                    STATE <= `BAD_CMD_STATE;
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;
+                        end
+                      
+                    CE1, CE2:
+                        begin
+                            if ( !DP_Mode && !WIP && WEL && !Secur_Mode && Chip_EN && ~HPM_RD && !EPSUSP) begin
+                                if ( CS_INT == 1'b1 && Bit == 7 ) begin
+                                    if (VERBOSE) $display( $time, " Enter Chip Erase Function ..." );
+                                    ->CE_Event;
+                                    CE_Mode = 1'b1 ;
+                                end 
+                                else if ( Bit > 7 )
+                                    STATE <= `BAD_CMD_STATE;
+                            end
+                            else if ( Bit == 7 ) 
+                                STATE <= `BAD_CMD_STATE;
+                        end
+                      
+                    PP: 
+                        begin
+                            if ( !DP_Mode && !WIP && WEL && Chip_EN && ~HPM_RD && !PSB) begin
+                                if ( Bit == 31 ) begin
+                                    Address = SI_Reg [A_MSB:0];
+                                    load_address(Address);
+                                end
+
+                                if ( Bit == 31 ) begin
+                                    if (VERBOSE) $display( $time, " Enter Page Program Function ..." );
+                                    if ( CS_INT == 1'b0 ) begin
+                                        ->PP_Event;
+                                        PP_1XIO_Mode = 1'b1;
+                                    end  
+                                end
+                                else if ( CS_INT == 1 && (Bit < 31 || ((Bit + 1) % 8 !== 0)))
+                                    STATE <= `BAD_CMD_STATE;
+                                end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;
+                        end
+
+                    SFDP_READ:
+                        begin
+                            if ( !DP_Mode && !Secur_Mode && !WIP && Chip_EN ) begin
+                                if (VERBOSE) $display( $time, " Enter SFDP read mode ..." );
+                                if ( Bit == 31 ) begin
+                                    Address = SI_Reg [A_MSB:0];
+                                    load_address(Address);
+                                end
+                                if ( Bit == 7 ) begin
+                                    SFDP_Mode = 1;
+                                    if (ENQUAD) begin
+                                        Read_4XIO_Mode = 1'b1;
+                                    end
+                                    else begin
+                                        FastRD_1XIO_Mode = 1'b1;
+                                    end
+                                    Read_SHSL = 1'b1;
+                                end
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;
+                        end
+
+                    WPSEL:
+                        begin
+                            if ( !DP_Mode && !WIP && WEL && Norm_Array_Mode && Chip_EN && !EPSUSP ) begin
+                                if ( CS_INT == 1'b1 && Bit == 7 ) begin
+                                    if (VERBOSE) $display( $time, " Enter Write Protection Selection Function ..." );
+                                    ->WPSEL_Event;
+                                end
+                                else if ( Bit > 7 )
+                                    STATE <= `BAD_CMD_STATE;
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;
+                        end
+
+                    SBLK:
+                        begin
+                            if ( !DP_Mode && !WIP && WEL && Norm_Array_Mode && WPSEL_Mode && Chip_EN && !EPSUSP ) begin
+                                if ( Bit == 31 ) begin
+                                    Address = SI_Reg[A_MSB:0] ;
+                                end
+                                if ( CS_INT == 1'b1 && Bit == 31 ) begin
+                                    if (VERBOSE) $display( $time, " Enter Sector Protection Function ..." );
+                                    ->SBLK_Event;
+                                end
+                                else if ( CS_INT == 1'b1 && Bit < 31 || Bit > 31 )
+                                    STATE <= `BAD_CMD_STATE;
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;
+                        end
+
+                    SBULK:
+                        begin
+                            if ( !DP_Mode && !WIP && WEL && Norm_Array_Mode && WPSEL_Mode && Chip_EN && !EPSUSP ) begin
+                                if ( Bit == 31 ) begin
+                                    Address = SI_Reg[A_MSB:0] ;
+                                end
+                                if ( CS_INT == 1'b1 && Bit == 31 ) begin
+                                    if (VERBOSE) $display( $time, " Enter Sector Unprotection Function ..." );
+                                    ->SBULK_Event;
+                                end
+                                else if ( CS_INT == 1'b1 && Bit < 31 || Bit > 31 )
+                                    STATE <= `BAD_CMD_STATE;
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;
+                        end
+
+                    RDBLOCK:
+                        begin
+                            if ( !DP_Mode && !WIP && WPSEL_Mode && Chip_EN ) begin
+                                if (VERBOSE) $display( $time, " Enter Sector protection Read Function ..." );
+                                if ( Bit == 31 ) begin
+                                    Address = SI_Reg[A_MSB:0];
+                                end
+                                if ( Bit == 7 ) begin
+                                    SEC_PROVFY_Mode = 1'b1;
+                                    Read_SHSL = 1'b1;
+                                end
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;
+                        end
+
+                    GBLK:
+                        begin
+                            if ( !DP_Mode && !WIP && WEL && Norm_Array_Mode && WPSEL_Mode && Chip_EN && !EPSUSP ) begin
+                                if ( CS_INT == 1'b1 && Bit == 7 ) begin
+                                    if (VERBOSE) $display( $time, " Enter Chip Protection Function ..." );
+                                    ->GBLK_Event;
+                                end
+                                else if ( CS_INT == 1'b1 && Bit > 7 )
+                                    STATE <= `BAD_CMD_STATE;
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;
+                        end
+
+                    GBULK:
+                        begin
+                            if ( !DP_Mode && !WIP && WEL && Norm_Array_Mode && WPSEL_Mode && Chip_EN && !EPSUSP ) begin
+                                if ( CS_INT == 1'b1 && Bit == 7 ) begin
+                                    if (VERBOSE) $display( $time, " Enter Chip Unprotection Function ..." );
+                                    ->GBULK_Event;
+                                end
+                                else if ( CS_INT == 1'b1 && Bit > 7 )
+                                    STATE <= `BAD_CMD_STATE;
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;
+                        end
+
+                    DP:
+                        begin
+                            if ( !WIP && Chip_EN && ~HPM_RD && !EPSUSP ) begin
+                                if ( CS_INT == 1'b1 && Bit == 7 && DP_Mode == 1'b0 ) begin
+                                    if (VERBOSE) $display( $time, " Enter Deep Power Down Function ..." );
+                                    tDP_Chk = 1'b1;
+                                    DP_Mode = 1'b1;
+                                end
+                                else if ( Bit > 7 )
+                                    STATE <= `BAD_CMD_STATE;
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;
+                        end
+
+                    RDP, RES:
+                        begin
+                            if ( ( !WIP || During_Susp_Wait ) && Chip_EN && ~HPM_RD ) begin
+                                // $display( $time, " Enter Release from Deep Power Down Function ..." );
+                                RES_Mode = 1'b1;
+                                Read_SHSL = 1'b1;
+                                if ( CS_INT == 1'b1 && SCLK == 1'b0 && tRES1_Chk &&
+                                   ((Bit >= 38 && !ENQUAD) || (Bit >=38 && ENQUAD)) ) begin
+                                    tRES1_Chk = 1'b0;
+                                    tRES2_Chk = 1'b1;
+                                    DP_Mode = 1'b0;
+                                end
+                                else if ( CS_INT == 1'b1 && SCLK == 1'b1 && tRES1_Chk &&
+                                        ((Bit >= 39 && !ENQUAD) || (Bit >=39 && ENQUAD)) ) begin
+                                    tRES1_Chk = 1'b0;
+                                    tRES2_Chk = 1'b1;
+                                    DP_Mode = 1'b0;
+                                end
+                                else if ( CS_INT == 1'b1 && Bit > 0 && DP_Mode ) begin
+                                    tRES1_Chk = 1'b1;
+                                    DP_Mode = 1'b0;
+                                end
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;
+                        end
+
+
+
+                    REMS:
+                        begin
+                            if ( !DP_Mode && !WIP && Chip_EN && ~HPM_RD && !ENQUAD) begin
+                                if ( Bit == 31 ) begin
+                                    Address = SI_Reg[A_MSB:0] ;
+                                end
+                                if (VERBOSE) $display( $time, " Enter Read Electronic Manufacturer & ID Function ..." );
+                                Read_SHSL = 1'b1;
+                                REMS_Mode = 1'b1;
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;                            
+                        end
+
+                    READ2X: 
+                        begin 
+                            if ( !DP_Mode && !WIP && Chip_EN && ~HPM_RD && !ENQUAD ) begin
+                                if (VERBOSE) $display( $time, " Enter READX2 Function ..." );
+                                Read_SHSL = 1'b1;
+                                if ( Bit == 19 ) begin
+                                    Address = SI_Reg [A_MSB:0];
+                                    load_address(Address);
+                                end
+                                Read_2XIO_Mode = 1'b1;
+                            end 
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;                                
+                        end     
+
+                    ENSO: 
+                        begin
+                            if ( !DP_Mode && !WIP && Chip_EN && ~HPM_RD ) begin
+                                if ( CS_INT == 1'b1 && Bit == 7 ) begin  
+                                    if (VERBOSE) $display( $time, " Enter ENSO  Function ..." );
+                                    enter_secured_otp;
+                                end
+                                else if ( Bit > 7 )
+                                    STATE <= `BAD_CMD_STATE;
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;
+                        end
+                      
+                    EXSO: 
+                        begin
+                            if ( !DP_Mode && !WIP && Chip_EN && ~HPM_RD ) begin
+                                if ( CS_INT == 1'b1 && Bit == 7 ) begin  
+                                    if (VERBOSE) $display( $time, " Enter EXSO  Function ..." );
+                                    exit_secured_otp;
+                                end
+                                else if ( Bit > 7 )
+                                    STATE <= `BAD_CMD_STATE;
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;
+                        end
+                      
+                    RDSCUR: 
+                        begin
+                            if ( !DP_Mode && Chip_EN && ~HPM_RD) begin 
+                                // $display( $time, " Enter Read Secur_Register Function ..." );
+                                Read_SHSL = 1'b1;
+                                RDSCUR_Mode = 1'b1;
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;                                
+                        end
+                      
+                      
+                    WRSCUR: 
+                        begin
+                            if ( !DP_Mode && !WIP && WEL && !Secur_Mode && Chip_EN && ~HPM_RD && !EPSUSP ) begin
+                                if ( CS_INT == 1'b1 && Bit == 7 ) begin  
+                                    if (VERBOSE) $display( $time, " Enter WRSCUR Secur_Register Function ..." );
+                                    ->WRSCUR_Event;
+                                end
+                                else if ( Bit > 7 )
+                                    STATE <= `BAD_CMD_STATE;
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;
+                        end
+                      
+                    READ4X:
+                        begin
+                            if ( !DP_Mode && !WIP && (Status_Reg[6]|ENQUAD) && Chip_EN && ~HPM_RD ) begin
+                                if (VERBOSE) $display( $time, " Enter READX4 Function ..." );
+                                Read_SHSL = 1'b1;
+                                if ( (Bit == 13 && !ENQUAD) || (Bit == 31 && ENQUAD) ) begin
+                                    Address = SI_Reg [A_MSB:0];
+                                    load_address(Address);
+                                end
+                                Read_4XIO_Mode = 1'b1;
+                                READ4X_Mode    = 1'b1;
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;                            
+
+                        end
+
+                    DREAD:
+                        begin
+                            if ( !DP_Mode && !WIP && Chip_EN && ~HPM_RD && !ENQUAD ) begin
+                                if (VERBOSE) $display( $time, " Enter Fast Read dual output Function ..." );
+                                Read_SHSL = 1'b1;
+                                if ( Bit == 31 ) begin
+                                    Address = SI_Reg [A_MSB:0];
+                                    load_address(Address);
+                                end
+                                FastRD_2XIO_Mode =1'b1;
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;                            
+                        end
+
+                    QREAD:
+                        begin
+                            if ( !DP_Mode && !WIP && Status_Reg[6] && Chip_EN && ~HPM_RD && !ENQUAD ) begin
+                                if (VERBOSE) $display( $time, " Enter Fast Read quad output Function ..." );
+                                Read_SHSL = 1'b1;
+                                if ( Bit == 31 ) begin
+                                    Address = SI_Reg[A_MSB:0] ;
+                                    load_address(Address);
+                                end
+                                FastRD_4XIO_Mode =1'b1;
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;
+                        end
+                      
+                    FIOPGM0: 
+                        begin
+                            if ( !DP_Mode && !WIP && WEL && Status_Reg[6] && Chip_EN && ~HPM_RD && !ENQUAD && !PSB) begin
+                                if ( Bit == 13 ) begin
+                                    Address = SI_Reg [A_MSB:0];
+                                    load_address(Address);
+                                end
+                                PP_4XIO_Load= 1'b1;
+                                SO_IN_EN    = 1'b1;
+                                SI_IN_EN    = 1'b1;
+                                WP_IN_EN    = 1'b1;
+                                SIO3_IN_EN  = 1'b1;
+                                if ( Bit == 13 ) begin
+                                    if (VERBOSE) $display( $time, " Enter 4io Page Program Function ..." );
+                                    ->PP_Event;
+                                    PP_4XIO_Mode= 1'b1;
+                                end
+                                else if ( CS_INT == 1 && (Bit < 15 || (Bit + 1)%2 !== 0 ))begin
+                                    STATE <= `BAD_CMD_STATE;
+                                end    
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;
+                        end
+
+                    EQIO:
+                        begin
+                            if ( !DP_Mode && !WIP && Chip_EN && ~HPM_RD && !ENQUAD ) begin
+                                if ( CS_INT == 1'b1 && Bit == 7 ) begin
+                                    if (VERBOSE) $display( $time, " Enable Quad I/O Function ..." );
+                                    ENQUAD = 1'b1;
+                                end
+                                else if ( Bit > 7 )
+                                    STATE <= `BAD_CMD_STATE;
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;
+                        end
+
+                    RSTQIO:
+                        begin
+                            if ( !DP_Mode && !WIP && Chip_EN && ~HPM_RD && ENQUAD ) begin
+                                if ( CS_INT == 1'b1 && Bit == 7 ) begin
+                                    if (VERBOSE) $display( $time, " Exiting QPI mode ..." );
+                                    ENQUAD = 1'b0;
+                                end
+                                else if ( Bit > 7 )
+                                    STATE <= `BAD_CMD_STATE;
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;
+                        end
+
+                    RSTEN:
+                        begin
+                            if ( Chip_EN ) begin
+                                if ( CS_INT == 1'b1 && (Bit == 7 || (EN4XIO_Read_Mode && Bit == 1)) ) begin
+                                    if (VERBOSE) $display( $time, " Reset enable ..." );
+                                    ->RST_EN_Event;
+                                end
+                                else if ( Bit > 7 )
+                                    STATE <= `BAD_CMD_STATE;
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;
+                        end
+
+                    RST:
+                        begin
+                            if ( Chip_EN && RST_CMD_EN ) begin
+                                if ( CS_INT == 1'b1 && (Bit == 7 || (EN4XIO_Read_Mode && Bit == 1)) ) begin
+                                    if (VERBOSE) $display( $time, " Reset memory ..." );
+                                    ->RST_Event;
+                                end
+                                else if ( Bit > 7 )
+                                    STATE <= `BAD_CMD_STATE;
+                            end
+                            else if ( Bit == 7 )
+                                STATE <= `BAD_CMD_STATE;
+                        end
+
+                    NOP:
+                        begin
+                        end
+
+                    default: 
+                        begin
+                            STATE <= `BAD_CMD_STATE;
+                        end
+                    endcase
+                end
+                 
+            `BAD_CMD_STATE: 
+                begin
+                end
+            
+            default: 
+                begin
+                STATE =  `STANDBY_STATE;
+                end
+        endcase
+
+        if ( CS_INT == 1'b1 ) begin
+
+        end
+    end
+
+    always @ (posedge CS_INT) begin
+            SIO0_Reg <= #tSHQZ 1'bx;
+            SIO1_Reg <= #tSHQZ 1'bx;
+            SIO2_Reg <= #tSHQZ 1'bx;
+            SIO3_Reg <= #tSHQZ 1'bx;
+            SIO0_Out_Reg <= #tSHQZ 1'bx;
+            SIO1_Out_Reg <= #tSHQZ 1'bx;
+            SIO2_Out_Reg <= #tSHQZ 1'bx;
+            SIO3_Out_Reg <= #tSHQZ 1'bx;
+           
+            SO_OUT_EN    <= #tSHQZ 1'b0;
+            SI_OUT_EN    <= #tSHQZ 1'b0;
+            WP_OUT_EN    <= #tSHQZ 1'b0;
+            SIO3_OUT_EN  <= #tSHQZ 1'b0;
+
+            #1;
+            Bit         = 1'b0;
+            Bit_Tmp     = 1'b0;
+           
+            SO_IN_EN    = 1'b0;
+            SI_IN_EN    = 1'b0;
+            WP_IN_EN    = 1'b0;
+            SIO3_IN_EN  = 1'b0;
+
+            RDID_Mode   = 1'b0;
+            RDSR_Mode   = 1'b0;
+            RDSCUR_Mode = 1'b0;
+            Read_Mode   = 1'b0;
+            RES_Mode    = 1'b0;
+            REMS_Mode   = 1'b0;
+            SFDP_Mode    = 1'b0;
+            Read_1XIO_Mode  = 1'b0;
+            Read_2XIO_Mode  = 1'b0;
+            Read_4XIO_Mode  = 1'b0;
+            Read_1XIO_Chk   = 1'b0;
+            Read_2XIO_Chk   = 1'b0;
+            Read_4XIO_Chk   = 1'b0;
+            FastRD_1XIO_Mode= 1'b0;
+            FastRD_2XIO_Mode= 1'b0;
+            FastRD_2XIO_Chk= 1'b0;
+            FastRD_4XIO_Mode= 1'b0;
+            FastRD_4XIO_Chk= 1'b0;
+            PP_4XIO_Load    = 1'b0;
+            PP_4XIO_Chk     = 1'b0;
+            STATE <=  `STANDBY_STATE;
+            SEC_PROVFY_Mode = 1'b0;
+
+            disable read_id;
+            disable read_status;
+            disable read_Secur_Register;
+            disable read_1xio;
+            disable read_2xio;
+            disable read_4xio;
+            disable fastread_1xio;
+            disable fastread_2xio;
+            disable fastread_4xio;
+            disable read_electronic_id;
+            disable read_electronic_manufacturer_device_id;
+            disable read_function;
+            disable dummy_cycle;
+        end
+
+    always @ (posedge CS_INT) begin 
+
+        if ( Set_4XIO_Enhance_Mode) begin
+            EN4XIO_Read_Mode = 1'b1;
+        end
+        else begin
+            EN4XIO_Read_Mode = 1'b0;
+            W4Read_Mode      = 1'b0;
+            FREAD4X_Mode     = 1'b0;
+        end
+    end 
+
+    /*----------------------------------------------------------------------*/
+    /*  ALL function trig action                                            */
+    /*----------------------------------------------------------------------*/
+    always @ ( posedge Read_1XIO_Mode
+            or posedge FastRD_1XIO_Mode
+            or posedge REMS_Mode
+            or posedge RES_Mode
+            or posedge Read_2XIO_Mode
+            or posedge Read_4XIO_Mode 
+            or posedge PP_4XIO_Load
+            or posedge FastRD_2XIO_Mode
+            or posedge FastRD_4XIO_Mode
+           ) begin:read_function 
+        wait ( SCLK == 1'b0 );
+        if ( Read_1XIO_Mode == 1'b1 ) begin
+            Read_1XIO_Chk = 1'b1;
+            read_1xio;
+        end
+        else if ( FastRD_1XIO_Mode == 1'b1 ) begin
+            fastread_1xio;
+        end
+        else if ( FastRD_2XIO_Mode == 1'b1 ) begin
+            FastRD_2XIO_Chk = 1'b1;
+            fastread_2xio;
+        end
+        else if ( FastRD_4XIO_Mode == 1'b1 ) begin
+            FastRD_4XIO_Chk = 1'b1;
+            fastread_4xio;
+        end
+        else if ( REMS_Mode == 1'b1 ) begin
+            read_electronic_manufacturer_device_id;
+        end 
+        else if ( RES_Mode == 1'b1 ) begin
+            read_electronic_id;
+        end
+        else if ( Read_2XIO_Mode == 1'b1 ) begin
+            Read_2XIO_Chk = 1'b1;
+            read_2xio;
+        end
+        else if ( Read_4XIO_Mode == 1'b1 ) begin
+            Read_4XIO_Chk = 1'b1;
+            read_4xio;
+        end   
+        else if ( PP_4XIO_Load == 1'b1 ) begin
+            PP_4XIO_Chk = 1'b1;
+        end
+    end
+
+    always @ ( RST_EN_Event ) begin
+        RST_CMD_EN = #2 1'b1;
+    end 
+    
+    always @ ( RST_Event ) begin
+        During_RST_REC = 1;
+        if ( BE_Mode || SE_4K_Mode || CE_Mode ) begin
+            #tRCE;
+        end
+        else if ( WRSR_Mode || WRSCUR_Mode || WR_WPSEL_Mode || PP_4XIO_Mode || PP_1XIO_Mode ) begin
+            #tRCP;
+        end
+        else if ( DP_Mode == 1'b1 ) begin
+            #tRES2;
+        end
+        else begin
+            #tRCR;
+        end
+        disable write_status;
+        disable write_protection_select;
+        disable block_erase_32k;
+        disable single_block_lock;
+        disable single_block_unlock;
+        disable chip_lock;
+        disable chip_unlock;
+        disable sector_protection_read;
+        disable block_erase;
+        disable sector_erase_4k;
+        disable chip_erase;
+        disable page_program; // can deleted
+        disable update_array;
+        disable read_Secur_Register;
+        disable write_secur_register;
+        disable read_id;
+        disable read_status;
+        disable suspend_write;
+        disable resume_write;
+        disable er_timer;
+        disable pg_timer;
+        disable stimeout_cnt;
+        disable rtimeout_cnt;
+
+        disable read_1xio;
+        disable read_2xio;
+        disable read_4xio;
+        disable fastread_1xio;
+        disable fastread_2xio;
+        disable fastread_4xio;
+        disable read_electronic_id;
+        disable read_electronic_manufacturer_device_id;
+        disable read_function;
+        disable dummy_cycle;
+
+        reset_sm;
+        READ4X_Mode = 1'b0;
+        Secur_Reg[6:2]  = 5'b0;
+        Status_Reg[1:0] = 2'b0;
+
+    end
+
+// *==============================================================================================
+// * Hardware Reset Function description
+// * =============================================================================================
+    always @ ( negedge RESETB_INT ) begin
+        if (RESETB_INT == 1'b0) begin
+            disable hd_reset;
+            #0;
+            -> HDRST_Event;
+        end
+    end
+    always @ ( HDRST_Event ) begin: hd_reset
+      if (RESETB_INT == 1'b0) begin
+        During_RST_REC = 1;
+        wait ( RESETB_INT == 1'b1 );
+        if (WRSR_Mode && tWRSR==tW) begin
+            #(tRHRL_RP);
+        end
+        else if (WRSR_Mode && tWRSR==tBP) begin
+            #(tRHRL_RP);
+        end
+
+        else if ( WR_WPSEL_Mode || WRSCUR_Mode ||  PP_4XIO_Mode || PP_1XIO_Mode ) begin
+            #(tRHRL_RP);
+        end
+        else if (SE_4K_Mode || BE32K_Mode || BE64K_Mode || CE_Mode ) begin
+            #(tRHRL_E);
+        end
+
+        else if ( DP_Mode == 1'b1 ) begin
+            #(tRES2);
+        end
+        else begin
+            #(tRHRL_RP);
+        end
+        disable write_status;
+        disable write_protection_select;
+        disable block_erase_32k;
+        disable single_block_lock;
+        disable single_block_unlock;
+        disable chip_lock;
+        disable chip_unlock;
+        disable sector_protection_read;
+        disable block_erase;
+        disable sector_erase_4k;
+        disable chip_erase;
+        disable page_program; // can deleted
+        disable update_array;
+        disable read_Secur_Register;
+        disable write_secur_register;
+        disable read_id;
+        disable read_status;
+        disable suspend_write;
+        disable resume_write;
+        disable er_timer;
+        disable pg_timer;
+        disable stimeout_cnt;
+        disable rtimeout_cnt;
+
+        disable read_1xio;
+        disable read_2xio;
+        disable read_4xio;
+        disable fastread_1xio;
+        disable fastread_2xio;
+        disable fastread_4xio;
+        disable read_electronic_id;
+        disable read_electronic_manufacturer_device_id;
+        disable read_function;
+        disable dummy_cycle;
+
+        reset_sm;
+        READ4X_Mode = 1'b0;
+        FREAD4X_Mode = 1'b0;
+        Secur_Reg[6:2]  = 5'b0;
+        Status_Reg[1:0] = 2'b0;
+      end
+    end
+
+
+    always @ ( posedge Susp_Trig ) begin:stimeout_cnt
+        Susp_Trig <= #1 1'b0;
+    end
+
+    always @ ( posedge Resume_Trig ) begin:rtimeout_cnt
+        Resume_Trig <= #1 1'b0;
+    end
+
+    always @ ( posedge W4Read_Mode or posedge FREAD4X_Mode ) begin
+        READ4X_Mode = 1'b0;
+    end
+
+    always @ ( WRSR_Event ) begin
+        write_status;
+    end
+
+    always @ ( BE_Event ) begin
+        block_erase;
+    end
+
+    always @ ( CE_Event ) begin
+        chip_erase;
+    end
+    
+    always @ ( PP_Event ) begin:page_program_mode
+        page_program( Address );
+    end
+   
+    always @ ( SE_4K_Event ) begin
+        sector_erase_4k;
+    end
+
+    always @ ( posedge RDID_Mode ) begin
+        read_id;
+    end
+
+    always @ ( posedge RDSR_Mode ) begin
+        read_status;
+    end
+
+    always @ ( posedge RDSCUR_Mode ) begin
+        read_Secur_Register;
+    end
+
+    always @ ( WRSCUR_Event ) begin
+        write_secur_register;
+    end
+
+    always @ ( Susp_Event ) begin
+        suspend_write;
+    end
+
+    always @ ( Resume_Event ) begin
+        resume_write;
+    end
+
+    always @ ( BE32K_Event ) begin
+        block_erase_32k;
+    end
+
+    always @ ( SBLK_Event ) begin
+        single_block_lock;
+    end
+
+    always @ ( SBULK_Event ) begin
+        single_block_unlock;
+    end
+
+    always @ ( GBLK_Event ) begin
+        chip_lock;
+    end
+
+    always @ ( GBULK_Event ) begin
+        chip_unlock;
+    end
+
+    always @ ( WPSEL_Event ) begin
+        write_protection_select;
+    end
+
+    always @ ( posedge SEC_PROVFY_Mode ) begin
+        sector_protection_read;
+    end
+
+// *========================================================================================== 
+// * Module Task Declaration
+// *========================================================================================== 
+    /*----------------------------------------------------------------------*/
+    /*  Description: define a wait dummy cycle task                         */
+    /*  INPUT                                                               */
+    /*      Cnum: cycle number                                              */
+    /*----------------------------------------------------------------------*/
+    task dummy_cycle;
+        input [31:0] Cnum;
+        begin
+            repeat( Cnum ) begin
+                @ ( posedge SCLK );
+            end
+        end
+    endtask // dummy_cycle
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: define a write enable task                             */
+    /*----------------------------------------------------------------------*/
+    task write_enable;
+        begin
+            if (VERBOSE) $display( $time, " Old Status Register = %b", Status_Reg );
+            Status_Reg[1] = 1'b1; 
+            // $display( $time, " New Status Register = %b", Status_Reg );
+        end
+    endtask // write_enable
+    
+    /*----------------------------------------------------------------------*/
+    /*  Description: define a write disable task (WRDI)                     */
+    /*----------------------------------------------------------------------*/
+    task write_disable;
+        begin
+            if (VERBOSE) $display( $time, " Old Status Register = %b", Status_Reg );
+            Status_Reg[1]  = 1'b0;
+            if (VERBOSE) $display( $time, " New Status Register = %b", Status_Reg );
+        end
+    endtask // write_disable
+    
+    /*----------------------------------------------------------------------*/
+    /*  Description: define a read id task (RDID)                           */
+    /*----------------------------------------------------------------------*/
+    task read_id;
+        reg  [23:0] Dummy_ID;
+        integer Dummy_Count;
+        begin
+            Dummy_ID    = {ID_MXIC, Memory_Type, Memory_Density};
+            Dummy_Count = 0;
+            forever begin
+                @ ( negedge SCLK or posedge CS_INT );
+                if ( CS_INT == 1'b1 ) begin
+                    disable read_id;
+                end
+                else begin
+                    if (ENQUAD) begin
+                        SI_OUT_EN    = 1'b1;
+                        WP_OUT_EN    = 1'b1;
+                        SIO3_OUT_EN  = 1'b1;
+                    end
+                    SO_OUT_EN = 1'b1;
+                    SO_IN_EN  = 1'b0;
+                    SI_IN_EN  = 1'b0;
+                    WP_IN_EN  = 1'b0;
+                    SIO3_IN_EN= 1'b0;
+                    if (ENQUAD)
+                        {SIO3_Reg, SIO2_Reg, SIO1_Reg, SIO0_Reg, Dummy_ID} <=  {Dummy_ID, Dummy_ID[23:20]};
+                    else
+                        {SIO1_Reg, Dummy_ID} <=  {Dummy_ID, Dummy_ID[23]};
+                end
+            end  // end forever
+        end
+    endtask // read_id
+    
+    /*----------------------------------------------------------------------*/
+    /*  Description: define a read status task (RDSR)                       */
+    /*----------------------------------------------------------------------*/
+    task read_status;
+        reg [7:0] Status_Reg_Int;
+        integer Dummy_Count;
+        begin
+            Status_Reg_Int = Status_Reg;
+            if (ENQUAD) begin
+                Dummy_Count = 2;
+            end
+            else begin
+                Dummy_Count = 8;
+            end
+            forever begin
+                @ ( negedge SCLK or posedge CS_INT );
+                if ( CS_INT == 1'b1 ) begin
+                    disable read_status;
+                end
+                else begin
+                    if (ENQUAD) begin
+                        SI_OUT_EN    = 1'b1;
+                        WP_OUT_EN    = 1'b1;
+                        SIO3_OUT_EN  = 1'b1;
+                    end
+                    SO_OUT_EN = 1'b1;
+                    SO_IN_EN  = 1'b0;
+                    SI_IN_EN  = 1'b0;
+                    WP_IN_EN  = 1'b0;
+                    SIO3_IN_EN= 1'b0;
+                    if ( Dummy_Count ) begin
+                        Dummy_Count = Dummy_Count - 1;
+                        if (ENQUAD) begin
+                            {SIO3_Reg, SIO2_Reg, SIO1_Reg, SIO0_Reg} <=  Dummy_Count ?
+                                                          Status_Reg_Int[7:4] : Status_Reg_Int[3:0];
+                        end
+                        else begin
+                            SIO1_Reg    <=  Status_Reg_Int[Dummy_Count];
+                        end
+                    end
+                    else begin
+                        if (ENQUAD) begin
+                            Dummy_Count = 1;
+                            Status_Reg_Int = Status_Reg;
+                            {SIO3_Reg, SIO2_Reg, SIO1_Reg, SIO0_Reg} <=  Status_Reg_Int[7:4];
+                        end
+                        else begin
+                            Dummy_Count = 7;
+                            Status_Reg_Int = Status_Reg;
+                            SIO1_Reg    <=  Status_Reg_Int[Dummy_Count];
+                        end
+                    end          
+                end
+            end  // end forever
+        end
+    endtask // read_status
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: define a write status task                             */
+    /*----------------------------------------------------------------------*/
+    task write_status;
+    reg [7:0] Status_Reg_Up;
+        begin
+            if (VERBOSE) $display( $time, " Old Status Register = %b", Status_Reg );
+            Status_Reg_Up = SI_Reg[7:0] ;
+                tWRSR = tW;
+                Secur_Reg[5] = 1'b0;
+                if ( (Status_Reg[7] == 1'b1 && Status_Reg_Up[7] == 1'b0 ) ||
+                     (Status_Reg[6] == 1'b1 && Status_Reg_Up[6] == 1'b0 ) ||
+                     (Status_Reg[5] == 1'b1 && Status_Reg_Up[5] == 1'b0 ) ||
+                     (Status_Reg[4] == 1'b1 && Status_Reg_Up[4] == 1'b0 ) ||
+                     (Status_Reg[3] == 1'b1 && Status_Reg_Up[3] == 1'b0 ) ||
+                     (Status_Reg[2] == 1'b1 && Status_Reg_Up[2] == 1'b0 ))
+                begin
+                    Secur_Reg[6] = 1'b0;
+                end
+                //SRWD:Status Register Write Protect
+                Status_Reg[0]   = 1'b1;
+                #tWRSR;
+                Status_Reg[7]   =  Status_Reg_Up[7];
+                Status_Reg[6:2] =  Status_Reg_Up[6:2];
+                //WIP : write in process Bit
+                Status_Reg[0]   = 1'b0;
+                //WEL:Write Enable Latch
+                Status_Reg[1]   = 1'b0;
+                WRSR_Mode       = 1'b0;
+        end
+    endtask // write_status
+   
+    /*----------------------------------------------------------------------*/
+    /*  Description: define a read data task                                */
+    /*               03 AD1 AD2 AD3 X                                       */
+    /*----------------------------------------------------------------------*/
+    task read_1xio;
+        integer Dummy_Count, Tmp_Int;
+        reg  [7:0]       OUT_Buf;
+        begin
+            Dummy_Count = 8;
+            dummy_cycle(24);
+            #1; 
+            read_array(Address, OUT_Buf);
+            forever begin
+                @ ( negedge SCLK or posedge CS_INT );
+                if ( CS_INT == 1'b1 ) begin
+                    disable read_1xio;
+                end 
+                else  begin 
+                    Read_Mode   = 1'b1;
+                    SO_OUT_EN   = 1'b1;
+                    SI_IN_EN    = 1'b0;
+                    if ( Dummy_Count ) begin
+                        {SIO1_Reg, OUT_Buf} <=  {OUT_Buf, OUT_Buf[7]};
+                        Dummy_Count = Dummy_Count - 1;
+                    end
+                    else begin
+                        Address = Address + 1;
+                        load_address(Address);
+                        read_array(Address, OUT_Buf);
+                        {SIO1_Reg, OUT_Buf} <=   {OUT_Buf, OUT_Buf[7]};
+                        Dummy_Count = 7 ;
+                    end
+                end 
+            end  // end forever
+        end   
+    endtask // read_1xio
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: define a fast read data task                           */
+    /*               0B AD1 AD2 AD3 X                                       */
+    /*----------------------------------------------------------------------*/
+    task fastread_1xio;
+        integer Dummy_Count, Tmp_Int;
+        reg  [7:0]       OUT_Buf;
+        begin
+            Dummy_Count = 8;
+            dummy_cycle(32);
+            read_array(Address, OUT_Buf);
+            forever begin
+                @ ( negedge SCLK or posedge CS_INT );
+                if ( CS_INT == 1'b1 ) begin
+                    disable fastread_1xio;
+                end 
+                else begin 
+                    Read_Mode = 1'b1;
+                    SO_OUT_EN = 1'b1;
+                    SI_IN_EN  = 1'b0;
+                    if ( Dummy_Count ) begin
+                        {SIO1_Reg, OUT_Buf} <=  {OUT_Buf, OUT_Buf[7]};
+                        Dummy_Count = Dummy_Count - 1;
+                    end
+                    else begin
+                        Address = Address + 1;
+                        load_address(Address);
+                        read_array(Address, OUT_Buf);
+                        {SIO1_Reg, OUT_Buf} <=  {OUT_Buf, OUT_Buf[7]};
+                        Dummy_Count = 7 ;
+                    end
+                end    
+            end  // end forever
+        end   
+    endtask // fastread_1xio
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: Execute Write protection select                        */
+    /*----------------------------------------------------------------------*/
+    task write_protection_select;
+        begin
+            Secur_Reg [5] = 1'b0;
+            WR_WPSEL_Mode = 1'b1;
+            Status_Reg[0] = 1'b1;
+            #tWPS;
+            WR_WPSEL_Mode = 1'b0;
+            Secur_Reg [7] = 1'b1;
+            Status_Reg[0] = 1'b0;
+            Status_Reg[1] = 1'b0;
+            Status_Reg[7] = 1'b0;
+        end
+    endtask // write_protection_select
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: define a block erase task                              */
+    /*               52 AD1 AD2 AD3                                         */
+    /*----------------------------------------------------------------------*/
+    task block_erase_32k;
+        integer i, i_tmp;
+        //time ERS_Time;
+        integer Start_Add;
+        integer End_Add;
+        begin
+            Block       =  Address[A_MSB:16];
+            Block2      =  Address[A_MSB:15];
+            Start_Add   = (Address[A_MSB:15]<<15) + 16'h0;
+            End_Add     = (Address[A_MSB:15]<<15) + 16'h7fff;
+            //WIP : write in process Bit
+            Status_Reg[0] =  1'b1;
+            Secur_Reg[6]  =  1'b0;
+            if ( write_protect(Address) == 1'b0 &&
+                 !(WPSEL_Mode == 1'b1 && Block[Block_MSB:0] == 0 && ((Address[15]&&SEC_Pro_Reg_BOT[15:8]) || (!Address[15]&&SEC_Pro_Reg_BOT[7:0]))) &&
+                 !(WPSEL_Mode == 1'b1 && Block[Block_MSB:0]  == Block_NUM-1 && ((Address[15]&&SEC_Pro_Reg_TOP[15:8]) || (!Address[15]&&SEC_Pro_Reg_TOP[7:0]))) ) begin
+               for( i = Start_Add; i <= End_Add; i = i + 1 )
+               begin
+                   ARRAY[i] = 8'hxx;
+               end
+               ERS_Time = ERS_Count_BE32K;
+               fork
+                   er_timer;
+                   begin
+                       for( i = 0; i < ERS_Time; i = i + 1 ) begin
+                           @ ( negedge ERS_CLK or posedge Susp_Trig );
+                           if ( Susp_Trig == 1'b1 ) begin
+                               if( Susp_Ready == 0 ) i = i_tmp;
+                               i_tmp = i;
+                               wait( Resume_Trig );
+                               $display ( $time, " Resume BE32K Erase ..." );
+                           end
+                       end
+                       //#tBE32 ;
+                       for( i = Start_Add; i <= End_Add; i = i + 1 )
+                       begin
+                           ARRAY[i] = 8'hff;
+                       end
+                       disable er_timer;
+                       disable resume_write;
+                       Susp_Ready = 1'b1;
+                   end
+               join
+               //WIP : write in process Bit
+               Status_Reg[0] =  1'b0;//WIP
+               //WEL : write enable latch
+               Status_Reg[1] =  1'b0;//WEL
+               BE_Mode = 1'b0;
+               BE32K_Mode = 1'b0;
+            end
+            else begin
+                #tERS_CHK;
+                Secur_Reg[6]  = 1'b1;
+                Status_Reg[0] = 1'b0;//WIP
+                Status_Reg[1] = 1'b0;//WEL
+                BE_Mode = 1'b0;
+                BE32K_Mode = 1'b0;
+            end
+        end
+    endtask // block_erase_32k
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: define an suspend task                                 */
+    /*----------------------------------------------------------------------*/
+    task suspend_write;
+        begin
+            disable resume_write;
+            Susp_Ready = 1'b1;
+
+            if ( Pgm_Mode ) begin
+                Susp_Trig = 1;
+                During_Susp_Wait = 1'b1;
+                #tPSL;
+                $display ( $time, " Suspend Program ..." );
+                Secur_Reg[2]  = 1'b1;//PSB
+                Status_Reg[0] = 1'b0;//WIP
+                Status_Reg[1] = 1'b0;//WEL
+                WR2Susp = 0;
+                During_Susp_Wait = 1'b0;
+            end
+            else if ( Ers_Mode ) begin
+                Susp_Trig = 1;
+                During_Susp_Wait = 1'b1;
+                #tESL;
+                $display ( $time, " Suspend Erase ..." );
+                Secur_Reg[3]  = 1'b1;//ESB
+                Status_Reg[0] = 1'b0;//WIP
+                Status_Reg[1] = 1'b0;//WEL
+                WR2Susp = 0;
+                During_Susp_Wait = 1'b0;
+            end
+        end
+    endtask // suspend_write
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: define an resume task                                  */
+    /*----------------------------------------------------------------------*/
+    task resume_write;
+        begin
+            if ( Pgm_Mode ) begin
+                Susp_Ready    = 1'b0;
+                Status_Reg[0] = 1'b1;//WIP
+                Status_Reg[1] = 1'b1;//WEL
+                Secur_Reg[2]  = 1'b0;//PSB
+                Resume_Trig = 1;
+                #tPRS;
+                Susp_Ready    = 1'b1;
+            end
+            else if ( Ers_Mode ) begin
+                Susp_Ready    = 1'b0;
+                Status_Reg[0] = 1'b1;//WIP
+                Status_Reg[1] = 1'b1;//WEL
+                Secur_Reg[3]  = 1'b0;//ESB
+                Resume_Trig = 1;
+                #tERS;
+                Susp_Ready    = 1'b1;
+            end
+        end
+    endtask // resume_write
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: define a timer to count erase time                     */
+    /*----------------------------------------------------------------------*/
+    task er_timer;
+        begin
+            ERS_CLK = 1'b0;
+            forever
+                begin
+                    #(Clock*500) ERS_CLK = ~ERS_CLK;    // erase timer period is 50us
+                end
+        end
+    endtask // er_timer
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: Execute  Single Block Lock                             */
+    /*----------------------------------------------------------------------*/
+    task single_block_lock;
+        reg [A_MSB:0] Address_Int;
+        reg  [Block_MSB:0] Block;          
+        begin
+            Address_Int = Address;
+            Block  =  Address_Int [A_MSB:16];
+            Status_Reg[0] = 1'b1;
+            #tWP_SRAM;
+            if (Block[Block_MSB:0] == 0) begin
+                SEC_Pro_Reg_BOT[Address_Int[15:12]] = 1'b1;
+            end
+            else if (Block[Block_MSB:0] == (Block_NUM-1)) begin
+                SEC_Pro_Reg_TOP[Address_Int[15:12]] = 1'b1;
+            end
+            else
+                SEC_Pro_Reg[Block] = 1'b1;
+            Status_Reg[0] = 1'b0;
+            Status_Reg[1] = 1'b0;
+        end
+    endtask // single_block_lock
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: Execute  Single Block Unlock                           */
+    /*----------------------------------------------------------------------*/
+    task single_block_unlock;
+        reg [A_MSB:0] Address_Int;
+        reg  [Block_MSB:0] Block;          
+        begin
+            Address_Int = Address;
+            Block  =  Address_Int [A_MSB:16];
+            Status_Reg[0] = 1'b1;
+            #tWP_SRAM;
+            if (Block[Block_MSB:0] == 0) begin
+                SEC_Pro_Reg_BOT[Address_Int[15:12]] = 1'b0;
+            end
+            else if (Block[Block_MSB:0] == (Block_NUM-1)) begin
+                SEC_Pro_Reg_TOP[Address_Int[15:12]] = 1'b0;
+            end
+            else
+                SEC_Pro_Reg[Block] = 1'b0;
+            Status_Reg[0] = 1'b0;
+            Status_Reg[1] = 1'b0;
+        end
+    endtask // single_block_unlock
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: Execute  Chip Lock                                     */
+    /*----------------------------------------------------------------------*/
+    task chip_lock;
+        begin
+            Status_Reg[0] = 1'b1;
+            //#(tWP_SRAM*Block_NUM);
+            #(tWP_SRAM);
+            SEC_Pro_Reg   = ~1'b0;
+            SEC_Pro_Reg_BOT = ~1'b0;
+            SEC_Pro_Reg_TOP = ~1'b0;
+            Status_Reg[0] = 1'b0;
+            Status_Reg[1] = 1'b0;
+        end
+    endtask // chip_lock
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: Execute Chip Block Unlock                              */
+    /*----------------------------------------------------------------------*/
+    task chip_unlock;
+        begin
+            Status_Reg[0] = 1'b1;
+            #(tWP_SRAM);
+            SEC_Pro_Reg   = 1'b0;
+            SEC_Pro_Reg_BOT = 1'b0;
+            SEC_Pro_Reg_TOP = 1'b0;
+            Status_Reg[0] = 1'b0;
+            Status_Reg[1] = 1'b0;
+        end
+    endtask // chip_unlock
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: Execute Block Lock  Protection Read                    */
+    /*----------------------------------------------------------------------*/
+    task sector_protection_read;
+        reg [Block_MSB:0] Block;
+        begin
+            if (ENQUAD) begin
+                dummy_cycle(6);
+            end
+            else begin
+                dummy_cycle(24);
+            end
+            #1;
+            Block    =  Address[A_MSB:16];
+            forever begin
+                @ ( negedge SCLK or posedge CS_INT );
+                if ( CS_INT == 1'b1 ) begin
+                    disable sector_protection_read;
+                end
+                else begin
+                    if (ENQUAD) begin
+                        SI_OUT_EN    = 1'b1;
+                        WP_OUT_EN    = 1'b1;
+                        SIO3_OUT_EN  = 1'b1;
+                    end
+                    SO_OUT_EN   = 1'b1;
+                    SO_IN_EN    = 1'b0;
+                    SI_IN_EN    = 1'b0;
+                    WP_IN_EN    = 1'b0;
+                    SIO3_IN_EN  = 1'b0;
+                    if (Block[Block_MSB:0] == 0) begin
+                        {SIO3_Reg,SIO2_Reg,SIO1_Reg,SIO0_Reg} <=  {4{SEC_Pro_Reg_BOT[Address[15:12]]}} ;
+                    end
+                    else if (Block[Block_MSB:0] == (Block_NUM-1)) begin
+                        {SIO3_Reg,SIO2_Reg,SIO1_Reg,SIO0_Reg} <=  {4{SEC_Pro_Reg_TOP[Address[15:12]]}} ;
+                    end
+                    else
+                        {SIO3_Reg,SIO2_Reg,SIO1_Reg,SIO0_Reg} <=  {4{SEC_Pro_Reg[Block]}} ;
+                end
+            end  // end forever
+        end
+     endtask // sector_protection_read
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: define a block erase task                              */
+    /*               D8 AD1 AD2 AD3                                         */
+    /*----------------------------------------------------------------------*/
+    task block_erase;
+        integer i, i_tmp;
+        //time ERS_Time;
+        integer Start_Add;
+        integer End_Add;
+        begin
+            Block       =  Address[A_MSB:16];
+            Block2      =  Address[A_MSB:15];
+            Start_Add   = (Address[A_MSB:16]<<16) + 16'h0;
+            End_Add     = (Address[A_MSB:16]<<16) + 16'hffff;
+            //WIP : write in process Bit
+            Status_Reg[0] =  1'b1;
+            Secur_Reg[6]  =  1'b0;
+            if ( write_protect(Address) == 1'b0 &&
+                 !(WPSEL_Mode == 1'b1 && Block[Block_MSB:0] == 0 && SEC_Pro_Reg_BOT) &&
+                 !(WPSEL_Mode == 1'b1 && Block[Block_MSB:0] == Block_NUM-1 && SEC_Pro_Reg_TOP) ) begin
+               for( i = Start_Add; i <= End_Add; i = i + 1 )
+               begin
+                   ARRAY[i] = 8'hxx;
+               end
+               ERS_Time = ERS_Count_BE;
+               fork
+                   er_timer;
+                   begin
+                       for( i = 0; i < ERS_Time; i = i + 1 ) begin
+                           @ ( negedge ERS_CLK or posedge Susp_Trig );
+                           if ( Susp_Trig == 1'b1 ) begin
+                               if( Susp_Ready == 0 ) i = i_tmp;
+                               i_tmp = i;
+                               wait( Resume_Trig );
+                               $display ( $time, " Resume BE Erase ..." );
+                           end
+                       end
+                       //#tBE ;
+                       for( i = Start_Add; i <= End_Add; i = i + 1 )
+                       begin
+                           ARRAY[i] = 8'hff;
+                       end
+                       disable er_timer;
+                       disable resume_write;
+                       Susp_Ready = 1'b1;
+                   end
+               join
+            end
+            else begin
+                #tERS_CHK;
+                Secur_Reg[6] = 1'b1;
+            end   
+                //WIP : write in process Bit
+                Status_Reg[0] =  1'b0;//WIP
+                //WEL : write enable latch
+                Status_Reg[1] =  1'b0;//WEL
+                BE_Mode = 1'b0;
+                BE64K_Mode = 1'b0;
+        end
+    endtask // block_erase
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: define a sector 4k erase task                          */
+    /*               20 AD1 AD2 AD3                                         */
+    /*----------------------------------------------------------------------*/
+    task sector_erase_4k;
+        integer i, i_tmp;
+        //time ERS_Time;
+        integer Start_Add;
+        integer End_Add;
+        begin
+            Sector      =  Address[A_MSB:12]; 
+            Start_Add   = (Address[A_MSB:12]<<12) + 12'h000;
+            End_Add     = (Address[A_MSB:12]<<12) + 12'hfff;          
+            //WIP : write in process Bit
+            Status_Reg[0] =  1'b1;
+            Secur_Reg[6]  =  1'b0;
+            if ( write_protect(Address) == 1'b0 ) begin
+               for( i = Start_Add; i <= End_Add; i = i + 1 )
+               begin
+                   ARRAY[i] = 8'hxx;
+               end
+               ERS_Time = ERS_Count_SE;
+               fork
+                   er_timer;
+                   begin
+                       for( i = 0; i < ERS_Time; i = i + 1 ) begin
+                           @ ( negedge ERS_CLK or posedge Susp_Trig );
+                           if ( Susp_Trig == 1'b1 ) begin
+                               if( Susp_Ready == 0 ) i = i_tmp;
+                               i_tmp = i;
+                               wait( Resume_Trig );
+                               $display ( $time, " Resume SE Erase ..." );
+                           end
+                       end
+                       for( i = Start_Add; i <= End_Add; i = i + 1 )
+                       begin
+                           ARRAY[i] = 8'hff;
+                       end
+                       disable er_timer;
+                       disable resume_write;
+                       Susp_Ready = 1'b1;
+                   end
+               join
+            end
+            else begin
+                #tERS_CHK;
+                Secur_Reg[6] = 1'b1;
+            end
+                //WIP : write in process Bit
+                Status_Reg[0] = 1'b0;//WIP
+                //WEL : write enable latch
+                Status_Reg[1] = 1'b0;//WEL
+                SE_4K_Mode = 1'b0;
+         end
+    endtask // sector_erase_4k
+    
+    /*----------------------------------------------------------------------*/
+    /*  Description: define a chip erase task                               */
+    /*               60(C7)                                                 */
+    /*----------------------------------------------------------------------*/
+    task chip_erase;
+        reg [A_MSB:0] Address_Int;
+        integer i;
+        begin
+            Address_Int = Address;
+            Status_Reg[0] =  1'b1;
+            Secur_Reg[6]  =  1'b0;
+            if ( (Dis_CE == 1'b1 && WPSEL_Mode == 1'b0) ||
+                ((SEC_Pro_Reg || SEC_Pro_Reg_BOT || SEC_Pro_Reg_TOP || (WP_B_INT == 1'b0)) && WPSEL_Mode == 1'b1)) begin
+                #tERS_CHK;
+                Secur_Reg[6] = 1'b1;
+            end
+            else begin
+                for ( i = 0;i<tCE/100;i = i + 1) begin
+                    #100_000_000;
+                end
+                for( i = 0; i <Block_NUM; i = i+1 ) begin
+                    Address_Int = (i<<16) + 16'h0;
+                    Start_Add = (i<<16) + 16'h0;
+                    End_Add   = (i<<16) + 16'hffff;     
+                    for( j = Start_Add; j <=End_Add; j = j + 1 )
+                    begin
+                        ARRAY[j] =  8'hff;
+                    end
+                end
+            end
+            //WIP : write in process Bit
+            Status_Reg[0] = 1'b0;//WIP
+            //WEL : write enable latch
+            Status_Reg[1] = 1'b0;//WEL
+            CE_Mode = 1'b0;
+        end
+    endtask // chip_erase       
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: define a page program task                             */
+    /*               02 AD1 AD2 AD3                                         */
+    /*----------------------------------------------------------------------*/
+    task page_program;
+        input  [A_MSB:0]  Address;
+        reg    [7:0]      Offset;
+        integer Dummy_Count, Tmp_Int, i;
+        begin
+            Dummy_Count = Buffer_Num;    // page size
+            Tmp_Int = 0;
+            Offset  = Address[7:0];
+            /*------------------------------------------------*/
+            /*  Store 256 bytes into a temp buffer - Dummy_A  */
+            /*------------------------------------------------*/
+            for (i = 0; i < Dummy_Count ; i = i + 1 ) begin
+                Dummy_A[i]  = 8'hff;
+            end
+            forever begin
+                @ ( posedge SCLK or posedge CS_INT );
+                if ( CS_INT == 1'b1 ) begin
+                    if ( (Tmp_Int % 8 !== 0) || (Tmp_Int == 1'b0) ) begin
+                        PP_4XIO_Mode = 0;
+                        PP_1XIO_Mode = 0;
+                        disable page_program;
+                    end
+                    else begin
+                        tPP_Real = pgm_time_cal(Tmp_Int/8);
+
+                        if ( Tmp_Int > 8 )
+                            Byte_PGM_Mode = 1'b0;
+                        else 
+                            Byte_PGM_Mode = 1'b1;
+                        update_array ( Address );
+                    end
+                    disable page_program;
+                end
+                else begin  // count how many Bits been shifted
+                    Tmp_Int = ( PP_4XIO_Mode | ENQUAD ) ? Tmp_Int + 4 : Tmp_Int + 1;
+                    if ( Tmp_Int % 8 == 0) begin
+                        #1;
+                        Dummy_A[Offset] = SI_Reg [7:0];
+                        Offset = Offset + 1;   
+                        Offset = Offset[7:0];   
+                    end  
+                end
+            end  // end forever
+        end
+    endtask // page_program
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: define a program time calculation function             */
+    /*  INPUT: program number                                               */
+    /*----------------------------------------------------------------------*/ 
+    function time pgm_time_cal;
+        input pgm_num;
+        integer pgm_num;
+        time  pgm_time_tmp;
+
+        begin
+            pgm_time_tmp = ( 8 + pgm_num * 4 ) * 1000;
+
+            if ( pgm_num == 1 ) begin
+                pgm_time_cal = tBP;
+            end
+            else if ( pgm_num >= Buffer_Num || pgm_time_tmp > tPP ) begin
+                pgm_time_cal = tPP;
+            end
+            else begin
+                pgm_time_cal = pgm_time_tmp;
+            end
+        end
+    endfunction
+
+    
+    /*----------------------------------------------------------------------*/
+    /*  Description: define a read electronic ID (RES)                      */
+    /*               AB X X X                                               */
+    /*----------------------------------------------------------------------*/
+    task read_electronic_id;
+        reg  [7:0] Dummy_ID;
+        begin
+            if (VERBOSE) $display( $time, " Old DP Mode Register = %b", DP_Mode );
+            if (ENQUAD) begin
+                dummy_cycle(5);
+            end
+            else begin
+                dummy_cycle(23);
+            end
+            Dummy_ID = ID_Device;
+            dummy_cycle(1);
+
+            forever begin
+                @ ( negedge SCLK or posedge CS_INT );
+                if ( CS_INT == 1'b1 ) begin
+                    disable read_electronic_id;
+                end 
+                else begin  
+                    if (ENQUAD) begin
+                        SI_OUT_EN    = 1'b1;
+                        WP_OUT_EN    = 1'b1;
+                        SIO3_OUT_EN  = 1'b1;
+                    end
+                    SO_OUT_EN = 1'b1;
+                    SO_IN_EN  = 1'b0;
+                    SI_IN_EN  = 1'b0;
+                    WP_IN_EN  = 1'b0;
+                    SIO3_IN_EN= 1'b0;
+                    if (ENQUAD) begin
+                        {SIO3_Reg, SIO2_Reg, SIO1_Reg, SIO0_Reg, Dummy_ID} <=   {Dummy_ID, Dummy_ID[7:4]};
+                    end
+                    else begin
+                        {SIO1_Reg, Dummy_ID} <=   {Dummy_ID, Dummy_ID[7]};
+                    end
+                end
+            end // end forever   
+        end
+    endtask // read_electronic_id
+            
+    /*----------------------------------------------------------------------*/
+    /*  Description: define a read electronic manufacturer & device ID      */
+    /*----------------------------------------------------------------------*/
+    task read_electronic_manufacturer_device_id;
+        reg  [15:0] Dummy_ID;
+        integer Dummy_Count;
+        begin
+            dummy_cycle(24);
+            #1;
+            if ( Address[0] == 1'b0 ) begin
+                Dummy_ID = {ID_MXIC,ID_Device};
+            end
+            else begin
+                Dummy_ID = {ID_Device,ID_MXIC};
+            end
+            Dummy_Count = 0;
+            forever begin
+                @ ( negedge SCLK or posedge CS_INT );
+                if ( CS_INT == 1'b1 ) begin
+                    disable read_electronic_manufacturer_device_id;
+                end
+                else begin
+                    SO_OUT_EN =  1'b1;
+                    SI_IN_EN  =  1'b0;
+                    {SIO1_Reg, Dummy_ID} <=   {Dummy_ID, Dummy_ID[15]};
+                end
+            end // end forever
+        end
+    endtask // read_electronic_manufacturer_device_id
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: define a program chip task                             */
+    /*  INPUT:address                                                       */
+    /*----------------------------------------------------------------------*/
+    task update_array;
+        input [A_MSB:0] Address;
+        integer Dummy_Count, i, i_tmp;
+        integer program_time;
+        reg [7:0]  ori [0:Buffer_Num-1];
+        begin
+            Dummy_Count = Buffer_Num;
+            Address = { Address [A_MSB:8], 8'h0 };
+            program_time = tPP_Real;
+            Status_Reg[0]= 1'b1;
+            Secur_Reg[5] = 1'b0;
+            if ( write_protect(Address) == 1'b0 && add_in_erase(Address) == 1'b0 ) begin
+                for ( i = 0; i < Dummy_Count; i = i + 1 ) begin
+                    if ( Secur_Mode == 1'b1) begin
+                        ori[i] = Secur_ARRAY[Address + i];
+                        Secur_ARRAY[Address + i] = Secur_ARRAY[Address + i] & 8'bx;
+                    end
+                    else begin
+                        ori[i] = ARRAY[Address + i];
+                        ARRAY[Address+ i] = ARRAY[Address + i] & 8'bx;
+                    end
+                end
+                fork
+                    pg_timer;
+                    begin
+                        for( i = 0; i*2 < program_time; i = i + 1 ) begin
+                            @ ( negedge PGM_CLK or posedge Susp_Trig );
+                            if ( Susp_Trig == 1'b1 ) begin
+                                if( Susp_Ready == 0 ) i = i_tmp;
+                                i_tmp = i;
+                                wait( Resume_Trig );
+                                $display ( $time, " Resume program ..." );
+                            end
+                        end
+                        //#program_time ;
+                        for ( i = 0; i < Dummy_Count; i = i + 1 ) begin
+                            if ( Secur_Mode == 1'b1)
+                                Secur_ARRAY[Address + i] = ori[i] & Dummy_A[i];
+                            else
+                                ARRAY[Address+ i] = ori[i] & Dummy_A[i];
+                        end
+                        disable pg_timer;
+                        disable resume_write;
+                        Susp_Ready = 1'b1;
+                    end
+                join
+            end
+            else begin
+                #tPGM_CHK ;
+                Secur_Reg[5] = 1'b1;
+            end
+            Status_Reg[0] = 1'b0;
+            Status_Reg[1] = 1'b0;
+            PP_4XIO_Mode = 1'b0;
+            PP_1XIO_Mode = 1'b0;
+            Byte_PGM_Mode = 1'b0;
+        end
+    endtask // update_array
+
+    /*----------------------------------------------------------------------*/
+    /*Description: find out whether the address is selected for erase       */
+    /*----------------------------------------------------------------------*/
+    function add_in_erase;
+        input [A_MSB:0] Address;
+        begin
+            if( Secur_Mode == 1'b0 ) begin
+                if (( ERS_Time == ERS_Count_BE32K && Address[A_MSB:15] == Block2 && ESB ) ||
+                   ( ERS_Time == ERS_Count_BE && Address[A_MSB:16] == Block && ESB ) ||
+                   ( ERS_Time == ERS_Count_SE && Address[A_MSB:12] == Sector && ESB ) ) begin
+                    add_in_erase = 1'b1;
+                    $display ( $time," Failed programing,address is in erase" );
+                end
+                else begin
+                    add_in_erase = 1'b0;
+                end
+            end
+            else if( Secur_Mode == 1'b1 ) begin
+                    add_in_erase = 1'b0;
+            end
+        end
+    endfunction // add_in_erase
+
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: define a timer to count program time                   */
+    /*----------------------------------------------------------------------*/
+    task pg_timer;
+        begin
+            PGM_CLK = 1'b0;
+            forever
+                begin
+                    #1 PGM_CLK = ~PGM_CLK;    // program timer period is 2ns
+                end
+        end
+    endtask // pg_timer
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: define a enter secured OTP task                        */
+    /*----------------------------------------------------------------------*/
+    task enter_secured_otp;
+        begin
+            if (VERBOSE) $display( $time, " Enter secured OTP mode  = %b",  Secur_Mode );
+            Secur_Mode= 1;
+            if (VERBOSE) $display( $time, " New Enter  secured OTP mode  = %b",  Secur_Mode );
+        end
+    endtask // enter_secured_otp
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: define a exit secured OTP task                         */
+    /*----------------------------------------------------------------------*/
+    task exit_secured_otp;
+        begin
+            if (VERBOSE) $display( $time, " Enter secured OTP mode  = %b",  Secur_Mode );
+            Secur_Mode = 0;
+            if (VERBOSE) $display( $time,  " New Enter secured OTP mode  = %b",  Secur_Mode );
+        end
+    endtask
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: Execute Reading Security Register                      */
+    /*----------------------------------------------------------------------*/
+    task read_Secur_Register;
+        integer Dummy_Count;
+        begin
+            if (ENQUAD) begin
+                Dummy_Count = 2;
+            end
+            else begin
+                Dummy_Count = 8;
+            end
+            forever @ ( negedge SCLK or posedge CS_INT ) begin // output security register info
+                if ( CS_INT == 1 ) begin
+                    disable     read_Secur_Register;
+                end
+                else  begin   
+                    if (ENQUAD) begin
+                        SI_OUT_EN    = 1'b1;
+                        WP_OUT_EN    = 1'b1;
+                        SIO3_OUT_EN  = 1'b1;
+                    end
+                    SO_OUT_EN = 1'b1;
+                    SO_IN_EN  = 1'b0;
+                    SI_IN_EN  = 1'b0;
+                    WP_IN_EN  = 1'b0;
+                    SIO3_IN_EN= 1'b0;
+                    if ( Dummy_Count ) begin
+                        Dummy_Count = Dummy_Count - 1;
+                        if (ENQUAD) begin
+                            {SIO3_Reg, SIO2_Reg, SIO1_Reg, SIO0_Reg} <=  Dummy_Count ?
+                                                          Secur_Reg[7:4] : Secur_Reg[3:0];
+                        end
+                        else begin
+                            SIO1_Reg    <=  Secur_Reg[Dummy_Count];
+                        end
+                    end
+                    else begin
+                        if (ENQUAD) begin
+                            Dummy_Count = 1;
+                            {SIO3_Reg, SIO2_Reg, SIO1_Reg, SIO0_Reg} <=  Secur_Reg[7:4];
+                        end
+                        else begin
+                            Dummy_Count = 7;
+                            SIO1_Reg    <=  Secur_Reg[Dummy_Count];
+                        end
+                    end          
+                end      
+            end
+        end  
+    endtask // read_Secur_Register
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: Execute Write Security Register                        */
+    /*----------------------------------------------------------------------*/
+    task write_secur_register;
+        begin
+            WRSCUR_Mode = 1'b1;
+            Status_Reg[0] = 1'b1;
+            #tBP; 
+            WRSCUR_Mode = 1'b0;
+            Secur_Reg [1] = 1'b1;
+            Status_Reg[0] = 1'b0;
+            Status_Reg[1] = 1'b0;
+        end
+    endtask // write_secur_register
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: Execute 2X IO Read Mode                                */
+    /*----------------------------------------------------------------------*/
+    task read_2xio;
+        reg  [7:0]  OUT_Buf;
+        integer     Dummy_Count;
+        begin
+            Dummy_Count=4;
+            SI_IN_EN = 1'b1;
+            SO_IN_EN = 1'b1;
+            SI_OUT_EN = 1'b0;
+            SO_OUT_EN = 1'b0;
+            dummy_cycle(12);
+            dummy_cycle(2);
+            #1;
+            dummy_cycle(2);
+            read_array(Address, OUT_Buf);
+          
+            forever @ ( negedge SCLK or  posedge CS_INT ) begin
+                if ( CS_INT == 1'b1 ) begin
+                    disable read_2xio;
+                end
+                else begin
+                    Read_Mode   = 1'b1;
+                    SO_OUT_EN   = 1'b1;
+                    SI_OUT_EN   = 1'b1;
+                    SI_IN_EN    = 1'b0;
+                    SO_IN_EN    = 1'b0;
+                    if ( Dummy_Count ) begin
+                        {SIO1_Reg, SIO0_Reg, OUT_Buf} <=  {OUT_Buf, OUT_Buf[1:0]};
+                        Dummy_Count = Dummy_Count - 1;
+                    end
+                    else begin
+                        Address = Address + 1;
+                        load_address(Address);
+                        read_array(Address, OUT_Buf);
+                        {SIO1_Reg, SIO0_Reg, OUT_Buf} <=  {OUT_Buf, OUT_Buf[1:0]};
+                        Dummy_Count = 3 ;
+                    end
+                end
+            end//forever  
+        end
+    endtask // read_2xio
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: Execute 4X IO Read Mode                                */
+    /*----------------------------------------------------------------------*/
+    task read_4xio;
+        //reg [A_MSB:0] Address;
+        reg [7:0]   OUT_Buf ;
+        integer     Dummy_Count;
+        begin
+            Dummy_Count = 2;
+            SI_OUT_EN    = 1'b0;
+            SO_OUT_EN    = 1'b0;
+            WP_OUT_EN    = 1'b0;
+            SIO3_OUT_EN  = 1'b0;
+            SI_IN_EN    = 1'b1;
+            SO_IN_EN    = 1'b1;
+            WP_IN_EN    = 1'b1;
+            SIO3_IN_EN   = 1'b1;
+            dummy_cycle(6); // for address
+            dummy_cycle(2);
+            #1;
+            if ( ((SI_Reg[0] === 1'hz) ||
+                 (SI_Reg[1] === 1'hz) ||
+                 (SI_Reg[2] === 1'hz) ||
+                 (SI_Reg[3] === 1'hz) ||
+                 (SI_Reg[4] === 1'hz) || 
+                 (SI_Reg[5] === 1'hz) ||  
+                 (SI_Reg[6] === 1'hz) ||
+                 (SI_Reg[7] === 1'hz) ) &&
+                 (SFDP_Mode  !== 1) ) begin
+                 $display("Warning: Hi-impedance is inhibited for the two clock cycles.");
+                 STATE = `BAD_CMD_STATE;
+                 disable read_4xio;
+            end
+            else if ((SI_Reg[0] !== SI_Reg[4]) &&
+                 (SI_Reg[1]!= SI_Reg[5]) &&
+                 (SI_Reg[2]!= SI_Reg[6]) &&
+                 (SI_Reg[3]!= SI_Reg[7]) ) begin
+                Set_4XIO_Enhance_Mode = 1'b1;
+            end
+            else  begin 
+                Set_4XIO_Enhance_Mode = 1'b0;
+            end
+            if ( CMD_BUS == FASTREAD1X || CMD_BUS == W4READ || (!READ4X_Mode && (CMD_BUS == RSTEN || CMD_BUS == RST) && EN4XIO_Read_Mode == 1'b1) )
+                dummy_cycle(2);
+            else if ( SFDP_Mode == 1 )
+                dummy_cycle(6);
+            else
+                dummy_cycle(4);
+            read_array(Address, OUT_Buf);
+
+
+            forever @ ( negedge SCLK or  posedge CS_INT ) begin
+                if ( CS_INT == 1'b1 ) begin
+                    disable read_4xio;
+                end
+                  
+                else begin
+                    SO_OUT_EN   = 1'b1;
+                    SI_OUT_EN   = 1'b1;
+                    WP_OUT_EN   = 1'b1;
+                    SIO3_OUT_EN = 1'b1;
+                    SO_IN_EN    = 1'b0;
+                    SI_IN_EN    = 1'b0;
+                    WP_IN_EN    = 1'b0;
+                    SIO3_IN_EN  = 1'b0;
+                    Read_Mode  = 1'b1;
+                    if ( Dummy_Count ) begin
+                        {SIO3_Reg, SIO2_Reg, SIO1_Reg, SIO0_Reg, OUT_Buf} <=  {OUT_Buf, OUT_Buf[3:0]};
+                        Dummy_Count = Dummy_Count - 1;
+                    end
+                    else begin
+                        if ( EN_Burst && Burst_Length==8 && Address[2:0]==3'b111 )
+                            Address = {Address[A_MSB:3], 3'b000};
+                        else if ( EN_Burst && Burst_Length==16 && Address[3:0]==4'b1111 )
+                            Address = {Address[A_MSB:4], 4'b0000};
+                        else if ( EN_Burst && Burst_Length==32 && Address[4:0]==5'b1_1111 )
+                            Address = {Address[A_MSB:5], 5'b0_0000};
+                        else if ( EN_Burst && Burst_Length==64 && Address[5:0]==6'b11_1111 )
+                            Address = {Address[A_MSB:6], 6'b00_0000};
+                        else
+                            Address = Address + 1;
+                        load_address(Address);
+                        read_array(Address, OUT_Buf);
+                        {SIO3_Reg, SIO2_Reg, SIO1_Reg, SIO0_Reg, OUT_Buf} <=  {OUT_Buf, OUT_Buf[3:0]};
+                        Dummy_Count = 1 ;
+                    end
+                end
+            end//forever  
+        end
+    endtask // read_4xio
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: define a fast read dual output data task               */
+    /*               3B AD1 AD2 AD3 X                                       */
+    /*----------------------------------------------------------------------*/
+    task fastread_2xio;
+        integer Dummy_Count;
+        reg  [7:0] OUT_Buf;
+        begin
+            Dummy_Count = 4 ;
+            dummy_cycle(32);
+            read_array(Address, OUT_Buf);
+            forever @ ( negedge SCLK or  posedge CS_INT ) begin
+                if ( CS_INT == 1'b1 ) begin
+                    disable fastread_2xio;
+                end
+                else begin
+                    Read_Mode= 1'b1;
+                    SO_OUT_EN = 1'b1;
+                    SI_OUT_EN = 1'b1;
+                    SI_IN_EN  = 1'b0;
+                    SO_IN_EN  = 1'b0;
+                    if ( Dummy_Count ) begin
+                        {SIO1_Reg, SIO0_Reg, OUT_Buf} <=  {OUT_Buf, OUT_Buf[1:0]};
+                        Dummy_Count = Dummy_Count - 1;
+                    end
+                    else begin
+                        Address = Address + 1;
+                        load_address(Address);
+                        read_array(Address, OUT_Buf);
+                        {SIO1_Reg, SIO0_Reg, OUT_Buf} <=  {OUT_Buf, OUT_Buf[1:0]};
+                        Dummy_Count = 3 ;
+                    end
+                end
+            end//forever  
+        end
+    endtask // fastread_2xio
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: define a fast read quad output data task               */
+    /*               6B AD1 AD2 AD3 X                                       */
+    /*----------------------------------------------------------------------*/
+    task fastread_4xio;
+        integer Dummy_Count;
+        reg  [7:0]  OUT_Buf;
+        begin
+            Dummy_Count = 2 ;
+            dummy_cycle(32);
+            read_array(Address, OUT_Buf);
+            forever @ ( negedge SCLK or  posedge CS ) begin
+                if ( CS ==      1'b1 ) begin
+                    disable fastread_4xio;
+                end
+                else begin
+                    SI_IN_EN    = 1'b0;
+                    SI_OUT_EN   = 1'b1;
+                    SO_OUT_EN   = 1'b1;
+                    WP_OUT_EN   = 1'b1;
+                    SIO3_OUT_EN = 1'b1;
+                    if ( Dummy_Count ) begin
+                        {SIO3_Reg, SIO2_Reg, SIO1_Reg, SIO0_Reg, OUT_Buf} <=  {OUT_Buf, OUT_Buf[3:0]};                       
+                         Dummy_Count = Dummy_Count - 1;
+                    end
+                    else begin
+                        Address = Address + 1;
+                        load_address(Address);
+                        read_array(Address, OUT_Buf);
+                        {SIO3_Reg, SIO2_Reg, SIO1_Reg, SIO0_Reg, OUT_Buf} <=  {OUT_Buf, OUT_Buf[3:0]};
+                        Dummy_Count = 1 ;
+                    end
+                end
+            end//forever
+        end
+    endtask // fastread_4xio
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: define read array output task                          */
+    /*----------------------------------------------------------------------*/
+    task read_array;
+        input [A_MSB:0] Address;
+        output [7:0]    OUT_Buf;
+        begin
+            if ( Secur_Mode == 1 ) begin
+                OUT_Buf = Secur_ARRAY[Address];
+            end
+            else if ( SFDP_Mode == 1 ) begin
+                OUT_Buf = SFDP_ARRAY[Address];
+            end
+            else begin
+                OUT_Buf = ARRAY[Address] ;
+            end
+        end
+    endtask //  read_array
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: define read array output task                          */
+    /*----------------------------------------------------------------------*/
+    task load_address;
+        inout [A_MSB:0] Address;
+        begin
+            if ( Secur_Mode == 1 ) begin
+                Address = Address[A_MSB_OTP:0] ;
+            end
+            else if ( SFDP_Mode == 1 ) begin
+                Address = Address[A_MSB_SFDP:0] ;
+            end
+        end
+    endtask //  load_address
+
+    /*----------------------------------------------------------------------*/
+    /*  Description: define a write_protect area function                   */
+    /*  INPUT: address                                                      */
+    /*----------------------------------------------------------------------*/ 
+    function write_protect;
+        input [A_MSB:0] Address;
+        reg [Block_MSB:0] Block;
+        begin
+            //protect_define
+            if( Secur_Mode == 1'b0 ) begin
+                Block  =  Address [A_MSB:16];
+                if ( WPSEL_Mode == 1'b0 ) begin
+                    if (Status_Reg[5:2] == 4'b0000) begin
+                        write_protect = 1'b0;
+                    end
+                    else if (Status_Reg[5:2] == 4'b0001) begin
+                        if (Block[Block_MSB:0] == 63) begin
+                                  write_protect = 1'b1;
+                        end
+                        else begin
+                            write_protect = 1'b0;
+                        end
+                    end
+                    else if (Status_Reg[5:2] == 4'b0010) begin
+                        if (Block[Block_MSB:0] >= 62 && Block[Block_MSB:0] <= 63) begin
+                            write_protect = 1'b1;
+                        end
+                        else begin
+                            write_protect = 1'b0;
+                        end
+                    end
+                    else if (Status_Reg[5:2] == 4'b0011) begin
+                        if (Block[Block_MSB:0] >= 60 && Block[Block_MSB:0] <= 63) begin
+                            write_protect = 1'b1;
+                        end
+                        else begin
+                            write_protect = 1'b0;
+                        end
+                    end
+                    else if (Status_Reg[5:2] == 4'b0100) begin
+                        if (Block[Block_MSB:0] >= 56 && Block[Block_MSB:0] <= 63) begin
+                            write_protect = 1'b1;
+                        end
+                        else begin
+                            write_protect = 1'b0;
+                        end
+                    end
+                    else if (Status_Reg[5:2] == 4'b0101) begin
+                        if (Block[Block_MSB:0] >= 48 && Block[Block_MSB:0] <= 63) begin
+                            write_protect = 1'b1;
+                        end
+                        else begin
+                            write_protect = 1'b0;
+                        end
+                    end
+                    else if (Status_Reg[5:2] == 4'b0110) begin
+                        if (Block[Block_MSB:0] >= 32 && Block[Block_MSB:0] <= 63) begin
+                            write_protect = 1'b1;
+                        end
+                        else begin
+                            write_protect = 1'b0;
+                        end
+                    end
+                    else if (Status_Reg[5:2] == 4'b0111) begin
+                          write_protect = 1'b1;
+                      end
+                    else if (Status_Reg[5:2] == 4'b1000) begin
+                          write_protect = 1'b1;
+                      end
+                    else if (Status_Reg[5:2] == 4'b1001) begin
+                        if (Block[Block_MSB:0] >= 0  && Block[Block_MSB:0] <= 31) begin
+                            write_protect = 1'b1;
+                        end
+                        else begin
+                            write_protect = 1'b0;
+                        end
+                    end
+                    else if (Status_Reg[5:2] == 4'b1010) begin
+                        if (Block[Block_MSB:0] >= 0  && Block[Block_MSB:0] <= 47) begin
+                            write_protect = 1'b1;
+                        end
+                        else begin
+                            write_protect = 1'b0;
+                        end
+                    end
+                    else if (Status_Reg[5:2] == 4'b1011) begin
+                        if (Block[Block_MSB:0] >= 0 && Block[Block_MSB:0] <= 55) begin
+                            write_protect = 1'b1;
+                        end
+                        else begin
+                            write_protect = 1'b0;
+                        end
+                    end
+                    else if (Status_Reg[5:2] == 4'b1100) begin
+                        if (Block[Block_MSB:0] >= 0 && Block[Block_MSB:0] <= 59) begin
+                            write_protect = 1'b1;
+                        end
+                        else begin
+                            write_protect = 1'b0;
+                        end
+                    end
+                    else if (Status_Reg[5:2] == 4'b1101) begin
+                        if (Block[Block_MSB:0] >= 0 && Block[Block_MSB:0] <= 61) begin
+                            write_protect = 1'b1;
+                        end
+                        else begin
+                            write_protect = 1'b0;
+                        end
+                    end
+                    else if (Status_Reg[5:2] == 4'b1110) begin
+                        if (Block[Block_MSB:0] >= 0 && Block[Block_MSB:0] <= 62) begin
+                            write_protect = 1'b1;
+                        end
+                        else begin
+                            write_protect = 1'b0;
+                        end
+                    end
+                    else if (Status_Reg[5:2] == 4'b1111) begin
+                        write_protect = 1'b1;
+                    end
+                end
+                else begin
+                    if (Block[Block_MSB:0] == 0) begin
+                        if ( SEC_Pro_Reg_BOT[Address[15:12]] == 1'b0 ) begin
+                            write_protect = 1'b0;
+                        end
+                        else begin
+                            write_protect = 1'b1;
+                        end
+                    end
+                    else if (Block[Block_MSB:0] == 63) begin
+                        if ( SEC_Pro_Reg_TOP[Address[15:12]] == 1'b0 ) begin
+                            write_protect = 1'b0;
+                        end
+                        else begin
+                            write_protect = 1'b1;
+                        end
+                    end
+                    else begin
+                        if ( SEC_Pro_Reg[Address[A_MSB:16]] == 1'b0 ) begin
+                            write_protect = 1'b0;
+                        end
+                        else begin
+                            write_protect = 1'b1;
+                        end
+                    end
+                    if( WP_B_INT == 1'b0 )
+                        write_protect = 1'b1;
+                end
+            end
+            else if( Secur_Mode == 1'b1 ) begin
+                if ( Secur_Reg [1] == 1'b0 && Secur_Reg [0] == 1'b0 ) begin
+                    write_protect = 1'b0;
+                end
+                else begin
+                    write_protect = 1'b1;
+                end
+            end 
+        end
+    endfunction // write_protect
+
+
+// *============================================================================================== 
+// * AC Timing Check Section
+// *==============================================================================================
+    wire SIO3_EN;
+    wire WP_EN;
+    assign SIO3_EN = !Status_Reg[6];
+    assign WP_EN = !Status_Reg[6] && !ENQUAD && SRWD;
+
+    assign  Write_SHSL = !Read_SHSL;
+
+    wire Read_1XIO_Chk_W;
+    assign Read_1XIO_Chk_W = Read_1XIO_Chk;
+    wire Read_2XIO_Chk_W;
+    assign Read_2XIO_Chk_W = Read_2XIO_Chk;
+    wire Read_2XIO_Chk_W2;
+    assign Read_2XIO_Chk_W2 = FastRD_2XIO_Chk;
+    wire Read_4XIO_Chk_W2;
+    assign Read_4XIO_Chk_W2 = FastRD_4XIO_Chk;
+    wire tDP_Chk_W;
+    assign tDP_Chk_W = tDP_Chk;
+    wire tRES1_Chk_W;
+    assign tRES1_Chk_W = tRES1_Chk;
+    wire tRES2_Chk_W;
+    assign tRES2_Chk_W = tRES2_Chk;
+    wire PP_4XIO_Chk_W;
+    assign PP_4XIO_Chk_W = PP_4XIO_Chk;
+    wire Read_SHSL_W;
+    assign Read_SHSL_W = Read_SHSL;
+    wire SI_IN_EN_W;
+    assign SI_IN_EN_W = SI_IN_EN;
+    wire SO_IN_EN_W;
+    assign SO_IN_EN_W = SO_IN_EN;
+    wire WP_IN_EN_W;
+    assign WP_IN_EN_W = WP_IN_EN;
+    wire SIO3_IN_EN_W;
+    assign SIO3_IN_EN_W = SIO3_IN_EN;
+
+    specify
+        /*----------------------------------------------------------------------*/
+        /*  Timing Check                                                        */
+        /*----------------------------------------------------------------------*/
+        $period( posedge  SCLK &&& ~CS, tSCLK  );       // SCLK _/~ ->_/~
+        $period( negedge  SCLK &&& ~CS, tSCLK  );       // SCLK ~\_ ->~\_
+        $period( posedge  SCLK &&& Read_1XIO_Chk_W , tRSCLK ); // SCLK _/~ ->_/~
+        $period( posedge  SCLK &&& Read_2XIO_Chk_W , tTSCLK ); // SCLK _/~ ->_/~
+        $period( posedge  SCLK &&& Read_2XIO_Chk_W2 , tTSCLK2 ); // SCLK _/~ ->_/~
+        $period( posedge  SCLK &&& fQ_104M , tQSCLK ); // SCLK _/~ ->_/~
+        $period( posedge  SCLK &&& fQ_84M , tQSCLK2 ); // SCLK _/~ ->_/~
+        $period( posedge  SCLK &&& Read_4XIO_Chk_W2 , tQSCLK3 ); // SCLK _/~ ->_/~
+
+        $width ( posedge  CS  &&& tDP_Chk_W, tDP );       // CS _/~\_
+        $width ( posedge  CS  &&& tRES1_Chk_W, tRES1 );   // CS _/~\_
+        $width ( posedge  CS  &&& tRES2_Chk_W, tRES2 );   // CS _/~\_
+
+        $width ( posedge  SCLK &&& ~CS, tCH   );       // SCLK _/~~\_
+        $width ( negedge  SCLK &&& ~CS, tCL   );       // SCLK ~\__/~
+        $width ( posedge  SCLK &&& Read_1XIO_Chk_W, tCH_R   );       // SCLK _/~~\_
+        $width ( negedge  SCLK &&& Read_1XIO_Chk_W, tCL_R   );       // SCLK ~\__/~
+        $width ( posedge  SCLK &&& PP_4XIO_Chk_W, tCH   );       // SCLK _/~~\_
+        $width ( negedge  SCLK &&& PP_4XIO_Chk_W, tCL   );       // SCLK ~\__/~
+
+        $width ( posedge  CS  &&& Read_SHSL_W, tSHSL_R );       // CS _/~\_
+        $width ( posedge  CS  &&& Write_SHSL, tSHSL_W );// CS _/~\_
+        $setup ( SI &&& ~CS, posedge SCLK &&& SI_IN_EN_W,  tDVCH );
+        $hold  ( posedge SCLK &&& SI_IN_EN_W, SI &&& ~CS,  tCHDX );
+
+        $setup ( SO &&& ~CS, posedge SCLK &&& SO_IN_EN_W,  tDVCH );
+        $hold  ( posedge SCLK &&& SO_IN_EN_W, SO &&& ~CS,  tCHDX );
+        $setup ( WP &&& ~CS, posedge SCLK &&& WP_IN_EN_W,  tDVCH );
+        $hold  ( posedge SCLK &&& WP_IN_EN_W, WP &&& ~CS,  tCHDX );
+
+        $setup ( SIO3 &&& ~CS, posedge SCLK &&& SIO3_IN_EN_W,  tDVCH );
+        $hold  ( posedge SCLK &&& SIO3_IN_EN_W, SIO3 &&& ~CS,  tCHDX );
+
+        $setup    ( negedge CS, posedge SCLK &&& ~CS, tSLCH );
+        $hold     ( posedge SCLK &&& ~CS, posedge CS, tCHSH );
+     
+        $setup    ( posedge CS, posedge SCLK &&& CS, tSHCH );
+        $hold     ( posedge SCLK &&& CS, negedge CS, tCHSL );
+
+        $setup ( posedge WP &&& WP_EN, negedge CS,  tWHSL );
+        $hold  ( posedge CS, negedge WP &&& WP_EN,  tSHWL );
+
+        $width ( negedge  RESETB_INT, tRLRH   );      // RESET ~\__/~
+        $setup ( posedge CS, negedge RESETB_INT ,  tRS );
+        $hold  ( negedge RESETB_INT, posedge CS ,  tRH );
+
+     endspecify
+
+    integer AC_Check_File;
+    // timing check module 
+    initial 
+    begin 
+        AC_Check_File= $fopen ("ac_check.err" );    
+    end
+
+    realtime  T_CS_P , T_CS_N;
+    realtime  T_WP_P , T_WP_N;
+    realtime  T_SCLK_P , T_SCLK_N;
+    realtime  T_SIO3_P , T_SIO3_N;
+    realtime  T_SI;
+    realtime  T_SO;
+    realtime  T_WP;
+    realtime  T_SIO3;
+    realtime  T_RESET_N, T_RESET_P;                    
+
+    initial 
+    begin
+        T_CS_P = 0; 
+        T_CS_N = 0;
+        T_WP_P = 0;  
+        T_WP_N = 0;
+        T_SCLK_P = 0;  
+        T_SCLK_N = 0;
+        T_SIO3_P = 0;  
+        T_SIO3_N = 0;
+        T_SI = 0;
+        T_SO = 0;
+        T_WP = 0;
+        T_SIO3 = 0;
+        T_RESET_N = 0;
+        T_RESET_P = 0;              
+    end
+
+    always @ ( posedge SCLK ) begin
+        //tSCLK
+        if ( $realtime - T_SCLK_P < tSCLK && $realtime > 0 && ~CS ) 
+            $fwrite (AC_Check_File, "Clock Frequence for except READ instruction fSCLK =%f Mhz, fSCLK timing violation at %f \n", fSCLK, $realtime );
+        //fRSCLK
+        if ( $realtime - T_SCLK_P < tRSCLK && Read_1XIO_Chk && $realtime > 0 && ~CS )
+            $fwrite (AC_Check_File, "Clock Frequence for READ instruction fRSCLK =%f Mhz, fRSCLK timing violation at %f \n", fRSCLK, $realtime );
+        //fTSCLK
+        if ( $realtime - T_SCLK_P < tTSCLK && Read_2XIO_Chk && $realtime > 0 && ~CS )
+            $fwrite (AC_Check_File, "Clock Frequence for 2XI/O instruction fTSCLK =%f Mhz, fTSCLK timing violation at %f \n", fTSCLK, $realtime );
+        //fTSCLK2
+        if ( $realtime - T_SCLK_P < tTSCLK2 && FastRD_2XIO_Chk && $realtime > 0 && ~CS )
+            $fwrite (AC_Check_File, "Clock Frequence for 2XI/O instruction fTSCLK2 =%f Mhz, fTSCLK2 timing violation at %f \n", fTSCLK2, $realtime );
+        //fQSCLK
+        if ( $realtime - T_SCLK_P < tQSCLK && Read_4XIO_Chk && fQ_104M && $realtime > 0 && ~CS )
+            $fwrite (AC_Check_File, "Clock Frequence for 4XI/O instruction fQSCLK =%f Mhz, fQSCLK timing violation at %f \n", fQSCLK, $realtime );
+        //fQSCLK2
+        if ( $realtime - T_SCLK_P < tQSCLK2 && Read_4XIO_Chk && fQ_84M && $realtime > 0 && ~CS )
+            $fwrite (AC_Check_File, "Clock Frequence for 4XI/O instruction fQSCLK2 =%f Mhz, fQSCLK2 timing violation at %f \n", fQSCLK2, $realtime );
+        //fQSCLK3
+        if ( $realtime - T_SCLK_P < tQSCLK3 && FastRD_4XIO_Chk && $realtime > 0 && ~CS )
+            $fwrite (AC_Check_File, "Clock Frequence for 4XI/O instruction fQSCLK3 =%f Mhz, fQSCLK3 timing violation at %f \n", fQSCLK3, $realtime );
+
+
+        T_SCLK_P = $realtime; 
+        #0;  
+        //tDVCH
+        if ( T_SCLK_P - T_SI < tDVCH && SI_IN_EN && T_SCLK_P > 0 )
+            $fwrite (AC_Check_File, "minimum Data SI setup time tDVCH=%f ns, tDVCH timing violation at %f \n", tDVCH, $realtime );
+        if ( T_SCLK_P - T_SO < tDVCH && SO_IN_EN && T_SCLK_P > 0 )
+            $fwrite (AC_Check_File, "minimum Data SO setup time tDVCH=%f ns, tDVCH timing violation at %f \n", tDVCH, $realtime );
+        if ( T_SCLK_P - T_WP < tDVCH && WP_IN_EN && T_SCLK_P > 0 )
+            $fwrite (AC_Check_File, "minimum Data WP setup time tDVCH=%f ns, tDVCH timing violation at %f \n", tDVCH, $realtime );
+
+        if ( T_SCLK_P - T_SIO3 < tDVCH && SIO3_IN_EN && T_SCLK_P > 0 )
+            $fwrite (AC_Check_File, "minimum Data SIO3 setup time tDVCH=%f ns, tDVCH timing violation at %f \n", tDVCH, $realtime );
+        //tCL
+        if ( T_SCLK_P - T_SCLK_N < tCL && ~CS && T_SCLK_P > 0 )
+            $fwrite (AC_Check_File, "minimum SCLK Low time tCL=%f ns, tCL timing violation at %f \n", tCL, $realtime );
+        //tCL_R
+        if ( T_SCLK_P - T_SCLK_N < tCL_R && Read_1XIO_Chk && T_SCLK_P > 0 )
+            $fwrite (AC_Check_File, "minimum SCLK Low time tCL=%f ns, tCL timing violation at %f \n", tCL_R, $realtime );
+        if ( T_SCLK_P - T_SCLK_N < tCL && PP_4XIO_Chk && T_SCLK_P > 0 )
+            $fwrite (AC_Check_File, "minimum SCLK Low time tCL=%f ns, tCL timing violation at %f \n", tCL, $realtime );
+        #0;
+        // tSLCH
+        if ( T_SCLK_P - T_CS_N < tSLCH  && T_SCLK_P > 0 )
+            $fwrite (AC_Check_File, "minimum CS# active setup time tSLCH=%f ns, tSLCH timing violation at %f \n", tSLCH, $realtime );
+
+        // tSHCH
+        if ( T_SCLK_P - T_CS_P < tSHCH  && T_SCLK_P > 0 )
+            $fwrite (AC_Check_File, "minimum CS# not active setup time tSHCH=%f ns, tSHCH timing violation at %f \n", tSHCH, $realtime );
+    end
+
+    always @ ( negedge SCLK ) begin
+        T_SCLK_N = $realtime;
+        #0; 
+        //tCH
+        if ( T_SCLK_N - T_SCLK_P < tCH && ~CS && T_SCLK_N > 0 )
+            $fwrite (AC_Check_File, "minimum SCLK High time tCH=%f ns, tCH timing violation at %f \n", tCH, $realtime );
+        //tCH_R
+        if ( T_SCLK_N - T_SCLK_P < tCH_R && Read_1XIO_Chk && T_SCLK_N > 0 )
+            $fwrite (AC_Check_File, "minimum SCLK High time tCH=%f ns, tCH timing violation at %f \n", tCH_R, $realtime );
+        if ( T_SCLK_N - T_SCLK_P < tCH && PP_4XIO_Chk && T_SCLK_N > 0 )
+            $fwrite (AC_Check_File, "minimum SCLK High time tCH=%f ns, tCH timing violation at %f \n", tCH, $realtime );
+    end
+
+
+    always @ ( SI ) begin
+        T_SI = $realtime; 
+        #0;  
+        //tCHDX
+        if ( T_SI - T_SCLK_P < tCHDX && SI_IN_EN && T_SI > 0 )
+            $fwrite (AC_Check_File, "minimum Data SI hold time tCHDX=%f ns, tCHDX timing violation at %f \n", tCHDX, $realtime );
+    end
+
+    always @ ( SO ) begin
+        T_SO = $realtime; 
+        #0;  
+        //tCHDX
+        if ( T_SO - T_SCLK_P < tCHDX && SO_IN_EN && T_SO > 0 )
+            $fwrite (AC_Check_File, "minimum Data SO hold time tCHDX=%f ns, tCHDX timing violation at %f \n", tCHDX, $realtime );
+    end
+
+    always @ ( WP ) begin
+        T_WP = $realtime; 
+        #0;  
+        //tCHDX
+        if ( T_WP - T_SCLK_P < tCHDX && WP_IN_EN && T_WP > 0 )
+            $fwrite (AC_Check_File, "minimum Data WP hold time tCHDX=%f ns, tCHDX timing violation at %f \n", tCHDX, $realtime );
+    end
+
+    always @ ( SIO3 ) begin
+        T_SIO3 = $realtime; 
+        #0;  
+        //tCHDX
+       if ( T_SIO3 - T_SCLK_P < tCHDX && SIO3_IN_EN && T_SIO3 > 0 )
+            $fwrite (AC_Check_File, "minimum Data SIO3 hold time tCHDX=%f ns, tCHDX timing violation at %f \n", tCHDX, $realtime );
+    end
+
+    always @ ( posedge CS ) begin
+        T_CS_P = $realtime;
+        #0;  
+        // tCHSH 
+        if ( T_CS_P - T_SCLK_P < tCHSH  && T_CS_P > 0 )
+            $fwrite (AC_Check_File, "minimum CS# active hold time tCHSH=%f ns, tCHSH timing violation at %f \n", tCHSH, $realtime );
+       // tRH
+       if ( T_CS_P - T_RESET_N < tRH  && T_CS_P > 0 )
+            $fwrite (AC_Check_File, "minimum hold time tRH=%f ns, tRH timing violation at %f \n", tRH, $realtime );
+    end
+
+    always @ ( negedge CS ) begin
+        T_CS_N = $realtime;
+        #0;
+        //tCHSL
+        if ( T_CS_N - T_SCLK_P < tCHSL  && T_CS_N > 0 )
+            $fwrite (AC_Check_File, "minimum CS# not active hold time tCHSL=%f ns, tCHSL timing violation at %f \n", tCHSL, $realtime );
+        //tSHSL
+        if ( T_CS_N - T_CS_P < tSHSL_R && T_CS_N > 0 && Read_SHSL)
+            $fwrite (AC_Check_File, "minimum CS# deselect  time tSHSL_R=%f ns, tSHSL timing violation at %f \n", tSHSL_R, $realtime );
+        if ( T_CS_N - T_CS_P < tSHSL_W && T_CS_N > 0 && Write_SHSL)
+            $fwrite (AC_Check_File, "minimum CS# deselect  time tSHSL_W=%f ns, tSHSL timing violation at %f \n", tSHSL_W, $realtime );
+
+        //tWHSL
+        if ( T_CS_N - T_WP_P < tWHSL && WP_EN  && T_CS_N > 0 )
+            $fwrite (AC_Check_File, "minimum WP setup  time tWHSL=%f ns, tWHSL timing violation at %f \n", tWHSL, $realtime );
+
+
+        //tDP
+        if ( T_CS_N - T_CS_P < tDP && T_CS_N > 0 && tDP_Chk)
+            $fwrite (AC_Check_File, "when transit from Standby Mode to Deep-Power Mode, CS# must remain high for at least tDP =%f ns, tDP timing violation at %f \n", tDP, $realtime );
+
+
+        //tRES1/2
+        if ( T_CS_N - T_CS_P < tRES1 && T_CS_N > 0 && tRES1_Chk)
+            $fwrite (AC_Check_File, "when transit from Deep-Power Mode to Standby Mode, CS# must remain high for at least tRES1 =%f ns, tRES1 timing violation at %f \n", tRES1, $realtime );
+
+        if ( T_CS_N - T_CS_P < tRES2 && T_CS_N > 0 && tRES2_Chk)
+            $fwrite (AC_Check_File, "when transit from Deep-Power Mode to Standby Mode, CS# must remain high for at least tRES2 =%f ns, tRES2 timing violation at %f \n", tRES2, $realtime );
+
+    end
+
+    always @ ( posedge WP ) begin
+        T_WP_P = $realtime;
+        #0;  
+    end
+
+    always @ ( negedge WP ) begin
+        T_WP_N = $realtime;
+        #0;
+        //tSHWL
+        if ( ((T_WP_N - T_CS_P < tSHWL) || ~CS) && WP_EN && T_WP_N > 0 )
+            $fwrite (AC_Check_File, "minimum WP hold time tSHWL=%f ns, tSHWL timing violation at %f \n", tSHWL, $realtime );
+    end
+
+    always @ ( negedge RESETB_INT ) begin
+        T_RESET_N = $realtime;
+        #0;
+        //tRS
+        if ( (T_RESET_N - T_CS_P < tRS) && T_RESET_N > 0 )
+            $fwrite (AC_Check_File, "minimum setup time tRS=%f ns, tRS timing violation at %f \n", tRS, $realtime );
+    end
+
+    always @ ( posedge RESETB_INT ) begin
+        T_RESET_P = $realtime;
+        #0;
+        //tRLRH
+        if ( (T_RESET_P - T_RESET_N < tRLRH) && T_RESET_P > 0 )
+            $fwrite (AC_Check_File, "minimum reset pulse width tRLRH=%f ns, tRLRH timing violation at %f \n", tRLRH, $realtime );
+    end
+endmodule
diff --git a/verilog/dv/vip/uart/uart_rx.v b/verilog/dv/vip/uart/uart_rx.v
new file mode 100644
index 0000000..e1e3aab
--- /dev/null
+++ b/verilog/dv/vip/uart/uart_rx.v
@@ -0,0 +1,150 @@
+//////////////////////////////////////////////////////////////////////
+// File Downloaded from http://www.nandland.com
+//////////////////////////////////////////////////////////////////////
+// This file contains the UART Receiver.  This receiver is able to
+// receive 8 bits of serial data, one start bit, one stop bit,
+// and no parity bit.  When receive is complete o_rx_dv will be
+// driven high for one clock cycle.
+// 
+// Set Parameter CLKS_PER_BIT as follows:
+// CLKS_PER_BIT = (Frequency of i_Clock)/(Frequency of UART)
+// Example: 10 MHz Clock, 115200 baud UART
+// (10000000)/(115200) = 87
+  
+module uart_rx 
+  (
+   input        i_Clock,
+   input        i_Rx_Serial,
+   output       o_Rx_DV,
+   output [7:0] o_Rx_Byte
+  );
+    
+  parameter CLKS_PER_BIT    = 87;
+
+  localparam s_IDLE         = 3'b000;
+  localparam s_RX_START_BIT = 3'b001;
+  localparam s_RX_DATA_BITS = 3'b010;
+  localparam s_RX_STOP_BIT  = 3'b011;
+  localparam s_CLEANUP      = 3'b100;
+   
+  reg           r_Rx_Data_R = 1'b1;
+  reg           r_Rx_Data   = 1'b1;
+   
+  reg [31:0]    r_Clock_Count = 0;
+  reg [2:0]     r_Bit_Index   = 0; //8 bits total
+  reg [7:0]     r_Rx_Byte     = 0;
+  reg           r_Rx_DV       = 0;
+  reg [2:0]     r_SM_Main     = 0;
+   
+  // Purpose: Double-register the incoming data.
+  // This allows it to be used in the UART RX Clock Domain.
+  // (It removes problems caused by metastability)
+  always @(posedge i_Clock)
+    begin
+      r_Rx_Data_R <= i_Rx_Serial;
+      r_Rx_Data   <= r_Rx_Data_R;
+    end
+   
+   
+  // Purpose: Control RX state machine
+  always @(posedge i_Clock)
+    begin
+       
+      case (r_SM_Main)
+        s_IDLE :
+          begin
+            r_Rx_DV       <= 1'b0;
+            r_Clock_Count <= 0;
+            r_Bit_Index   <= 0;
+             
+            if (r_Rx_Data == 1'b0)          // Start bit detected
+              r_SM_Main <= s_RX_START_BIT;
+            else
+              r_SM_Main <= s_IDLE;
+          end
+         
+        // Check middle of start bit to make sure it's still low
+        s_RX_START_BIT :
+          begin
+            if (r_Clock_Count == (CLKS_PER_BIT-1)/2)
+              begin
+                if (r_Rx_Data == 1'b0)
+                  begin
+                    r_Clock_Count <= 0;  // reset counter, found the middle
+                    r_SM_Main     <= s_RX_DATA_BITS;
+                  end
+                else
+                  r_SM_Main <= s_IDLE;
+              end
+            else
+              begin
+                r_Clock_Count <= r_Clock_Count + 1;
+                r_SM_Main     <= s_RX_START_BIT;
+              end
+          end // case: s_RX_START_BIT
+         
+         
+        // Wait CLKS_PER_BIT-1 clock cycles to sample serial data
+        s_RX_DATA_BITS :
+          begin
+            if (r_Clock_Count < CLKS_PER_BIT-1)
+              begin
+                r_Clock_Count <= r_Clock_Count + 1;
+                r_SM_Main     <= s_RX_DATA_BITS;
+              end
+            else
+              begin
+                r_Clock_Count          <= 0;
+                r_Rx_Byte[r_Bit_Index] <= r_Rx_Data;
+                 
+                // Check if we have received all bits
+                if (r_Bit_Index < 7)
+                  begin
+                    r_Bit_Index <= r_Bit_Index + 1;
+                    r_SM_Main   <= s_RX_DATA_BITS;
+                  end
+                else
+                  begin
+                    r_Bit_Index <= 0;
+                    r_SM_Main   <= s_RX_STOP_BIT;
+                  end
+              end
+          end // case: s_RX_DATA_BITS
+     
+     
+        // Receive Stop bit.  Stop bit = 1
+        s_RX_STOP_BIT :
+          begin
+            // Wait CLKS_PER_BIT-1 clock cycles for Stop bit to finish
+            if (r_Clock_Count < CLKS_PER_BIT-1)
+              begin
+                r_Clock_Count <= r_Clock_Count + 1;
+                r_SM_Main     <= s_RX_STOP_BIT;
+              end
+            else
+              begin
+                r_Rx_DV       <= 1'b1;
+                r_Clock_Count <= 0;
+                r_SM_Main     <= s_CLEANUP;
+              end
+          end // case: s_RX_STOP_BIT
+     
+         
+        // Stay here 1 clock
+        s_CLEANUP :
+          begin
+            r_SM_Main <= s_IDLE;
+            r_Rx_DV   <= 1'b0;
+          end
+         
+         
+        default :
+          r_SM_Main <= s_IDLE;
+         
+      endcase
+    end   
+   
+  assign o_Rx_DV   = r_Rx_DV;
+  assign o_Rx_Byte = r_Rx_Byte;
+   
+endmodule // uart_rx
diff --git a/verilog/dv/vip/uart/uart_tb.v b/verilog/dv/vip/uart/uart_tb.v
new file mode 100644
index 0000000..4dc9950
--- /dev/null
+++ b/verilog/dv/vip/uart/uart_tb.v
@@ -0,0 +1,243 @@
+//////////////////////////////////////////////////////////////////////
+// File Downloaded from http://www.nandland.com
+//////////////////////////////////////////////////////////////////////
+ 
+// This testbench will exercise both the UART Tx and Rx.
+
+`include "uart_tx.v"
+`include "uart_rx.v"
+
+`define XMODEM_SOH 8'h01
+`define XMODEM_STX 8'h02
+`define XMODEM_EOT 8'h04
+`define XMODEM_ACK 8'h06
+`define XMODEM_NAK 8'h15
+`define XMODEM_CAN 8'h18
+`define XMODEM_EOF 8'h1a /* Ctrl-Z */
+`define XMODEM_BLOCK_SIZE 128
+`define LF 8'h0a
+
+`define PROMPT  "kzload> "
+`define EXIT    "exit."
+ 
+module uart_tb
+(
+  input     clk,
+  input     rst,
+  input     rxd,
+  output    txd
+);
+ 
+  parameter CLKS_PER_BIT = 87;  // # of clocks(clk) per bit
+
+  logic       r_Tx_DV;
+  logic [7:0] r_Tx_Byte;
+  logic       w_Tx_Active;
+  logic       w_Tx_Done;
+
+  logic       w_Rx_DV;
+  logic [7:0] w_Rx_Byte;
+  logic [8*50-1:0] recieved_data;
+  logic       run;
+  event       ev_prompt;
+  event       ev_exit;
+   
+  uart_rx #(.CLKS_PER_BIT(CLKS_PER_BIT)) UART_RX_INST
+    (.i_Clock(clk),
+     .i_Rx_Serial(rxd),
+     .o_Rx_DV(w_Rx_DV),
+     .o_Rx_Byte(w_Rx_Byte)
+    );
+   
+  uart_tx #(.CLKS_PER_BIT(CLKS_PER_BIT)) UART_TX_INST
+    (.i_Clock(clk),
+     .i_Tx_DV(r_Tx_DV),
+     .i_Tx_Byte(r_Tx_Byte),
+     .o_Tx_Active(w_Tx_Active),
+     .o_Tx_Serial(txd),
+     .o_Tx_Done(w_Tx_Done)
+    );
+ 
+//-------------------------------------------------------------
+// Record & Display recieved data
+string recieved_str;
+
+initial begin
+  recieved_str = "";
+end
+
+always @(posedge w_Rx_DV) begin
+  if (~rst) begin
+    recieved_str = {recieved_str, w_Rx_Byte};
+    if (w_Rx_Byte == `LF) begin
+      $fwrite(32'h80000002, "%s", recieved_str);
+      recieved_str = "";
+    end
+
+    recieved_data = {recieved_data[8*49-1:0], w_Rx_Byte};
+    //$display("[%d] recieved_data[8*8-1:0] = %s", testbench.cycle, string'(recieved_data[8*8-1:0]));
+    if (recieved_data[8*8-1:0] == `PROMPT) -> ev_prompt;
+    if (recieved_data[5*8-1:0] == `EXIT)   -> ev_exit;
+  end
+end
+
+//-------------------------------------------------------------
+// Send data
+integer     i;
+string      prog_hex;
+integer     fd;
+integer     not_eof;
+string      line;
+reg [31:0]  send_data;
+reg [7:0]   block_number;
+reg [7:0]   check_sum;
+
+initial begin
+  r_Tx_DV   = 1'b0;
+  r_Tx_Byte = 8'h00;
+  run = 0;
+
+`ifdef HOGE
+  if ($value$plusargs("TLRAM_PROG=%s", prog_hex)) begin
+    fd = $fopen(prog_hex, "r");
+
+    if (fd == 0) begin
+      $display("Error: cannot open %s", prog_hex);
+      $finish;
+    end
+
+    @ev_prompt;
+    tsk_send_string("load\n");  // start XMODEM
+
+    not_eof = 1;
+
+    for (block_number = 1; not_eof; block_number = block_number + 1) begin
+    //for (block_number = 1; block_number < 2; block_number = block_number + 1) begin
+      $display("[%d] XMODEM: Sending block %d", testbench.cycle, block_number);
+
+      if (block_number == 1) begin
+        wait(recieved_data[7:0] == `XMODEM_NAK);
+      end
+      else begin
+        wait(recieved_data[7:0] == `XMODEM_ACK);
+      end
+
+      tsk_send_byte(`XMODEM_SOH);   // SOH
+      tsk_send_byte(block_number);  // block number
+      tsk_send_byte(~block_number); // ~block number
+
+      check_sum = 0;
+
+      for (i = 0; i < `XMODEM_BLOCK_SIZE / 4; i = i + 1 ) begin  // send 1 block (128B) data
+        not_eof = $fgets(line, fd);
+
+        if (not_eof) begin
+          line = line.substr(1,8);
+          send_data = line.atohex;
+        end
+        else begin
+          send_data = 0;
+        end
+
+        tsk_send_byte(send_data[7:0]);
+        check_sum = check_sum + send_data[7:0];
+
+        tsk_send_byte(send_data[15:8]);
+        check_sum = check_sum + send_data[15:8];
+
+        tsk_send_byte(send_data[23:16]);
+        check_sum = check_sum + send_data[23:16];
+
+        tsk_send_byte(send_data[31:24]);
+        check_sum = check_sum + send_data[31:24];
+      end
+
+      tsk_send_byte(check_sum);     // check sum
+      wait(recieved_data[7:0] == `XMODEM_ACK);
+    end
+
+    tsk_send_byte(`XMODEM_EOT); // EOT
+    wait(recieved_data[7:0] == `XMODEM_ACK);
+
+    @ev_prompt;
+    tsk_send_string("run\n");  // run
+    run = 1;
+
+    @ev_exit;
+    $finish;
+  end
+
+`ifdef XMODEM_SIMPLE_TEST
+  @ev_prompt;
+  tsk_send_string("load\n");  // start XMODEM
+
+  wait(recieved_data[7:0] == `XMODEM_NAK);
+  tsk_send_byte(`XMODEM_SOH);   // SOH
+  tsk_send_byte(8'h01);         // block number
+  tsk_send_byte(8'hfe);         // !(block number)
+
+  // send 128byte data
+  check_sum = 0;
+  for (i = 0; i < `XMODEM_BLOCK_SIZE; i = i + 1) begin
+    tsk_send_byte(i);
+    check_sum = check_sum + i;
+  end
+
+  tsk_send_byte(check_sum);     // check sum
+  wait(recieved_data[7:0] == `XMODEM_ACK);
+  tsk_send_byte(`XMODEM_EOT);   // EOT
+  wait(recieved_data[7:0] == `XMODEM_ACK);
+
+  @ev_prompt;
+  tsk_send_string("dump\n");  // dump sent data
+
+  @ev_prompt;
+  repeat (100) @(posedge clk);
+  $finish;
+`endif  // XMODEM_SIMPLE_TEST
+`endif  // HOGE
+
+end
+
+`ifdef HOGE
+//-------------------------------------------------------------
+// Task: send string
+task tsk_send_string (
+  input string data
+);
+int i;
+begin
+  wait (w_Tx_Active == 1'b0);
+
+  // send data
+  for (i = 0; i < data.len(); i = i + 1) begin
+    r_Tx_Byte = data[i];
+    r_Tx_DV = 1'b1;
+    @(posedge clk);
+    r_Tx_DV = 1'b0;
+    @(posedge w_Tx_Done);
+    @(negedge w_Tx_Done);
+  end
+end
+endtask
+
+//-------------------------------------------------------------
+// Task: send byte
+task tsk_send_byte (
+  input [7:0] data
+);
+begin
+  wait (w_Tx_Active == 1'b0);
+
+  // send data
+  r_Tx_Byte = data;
+  r_Tx_DV = 1'b1;
+  @(posedge clk);
+  r_Tx_DV = 1'b0;
+  @(posedge w_Tx_Done);
+  @(negedge w_Tx_Done);
+end
+endtask
+`endif  // HOGE
+
+endmodule
diff --git a/verilog/dv/vip/uart/uart_tx.v b/verilog/dv/vip/uart/uart_tx.v
new file mode 100644
index 0000000..f307f3f
--- /dev/null
+++ b/verilog/dv/vip/uart/uart_tx.v
@@ -0,0 +1,147 @@
+//////////////////////////////////////////////////////////////////////
+// File Downloaded from http://www.nandland.com
+//////////////////////////////////////////////////////////////////////
+// This file contains the UART Transmitter.  This transmitter is able
+// to transmit 8 bits of serial data, one start bit, one stop bit,
+// and no parity bit.  When transmit is complete o_Tx_done will be
+// driven high for one clock cycle.
+//
+// Set Parameter CLKS_PER_BIT as follows:
+// CLKS_PER_BIT = (Frequency of i_Clock)/(Frequency of UART)
+// Example: 10 MHz Clock, 115200 baud UART
+// (10000000)/(115200) = 87
+  
+module uart_tx 
+  (
+   input       i_Clock,
+   input       i_Tx_DV,
+   input [7:0] i_Tx_Byte, 
+   output      o_Tx_Active,
+   output reg  o_Tx_Serial,
+   output      o_Tx_Done
+  );
+  
+  parameter CLKS_PER_BIT    = 87;
+
+  localparam s_IDLE         = 3'b000;
+  localparam s_TX_START_BIT = 3'b001;
+  localparam s_TX_DATA_BITS = 3'b010;
+  localparam s_TX_STOP_BIT  = 3'b011;
+  localparam s_CLEANUP      = 3'b100;
+   
+  reg [2:0]    r_SM_Main     = 0;
+  reg [31:0]   r_Clock_Count = 0;
+  reg [2:0]    r_Bit_Index   = 0;
+  reg [7:0]    r_Tx_Data     = 0;
+  reg          r_Tx_Done     = 0;
+  reg          r_Tx_Active   = 0;
+     
+  always @(posedge i_Clock)
+    begin
+       
+      case (r_SM_Main)
+        s_IDLE :
+          begin
+            o_Tx_Serial   <= 1'b1;         // Drive Line High for Idle
+            r_Tx_Done     <= 1'b0;
+            r_Clock_Count <= 0;
+            r_Bit_Index   <= 0;
+             
+            if (i_Tx_DV == 1'b1)
+              begin
+                r_Tx_Active <= 1'b1;
+                r_Tx_Data   <= i_Tx_Byte;
+                r_SM_Main   <= s_TX_START_BIT;
+              end
+            else
+              r_SM_Main <= s_IDLE;
+          end // case: s_IDLE
+         
+         
+        // Send out Start Bit. Start bit = 0
+        s_TX_START_BIT :
+          begin
+            o_Tx_Serial <= 1'b0;
+             
+            // Wait CLKS_PER_BIT-1 clock cycles for start bit to finish
+            if (r_Clock_Count < CLKS_PER_BIT-1)
+              begin
+                r_Clock_Count <= r_Clock_Count + 1;
+                r_SM_Main     <= s_TX_START_BIT;
+              end
+            else
+              begin
+                r_Clock_Count <= 0;
+                r_SM_Main     <= s_TX_DATA_BITS;
+              end
+          end // case: s_TX_START_BIT
+         
+         
+        // Wait CLKS_PER_BIT-1 clock cycles for data bits to finish         
+        s_TX_DATA_BITS :
+          begin
+            o_Tx_Serial <= r_Tx_Data[r_Bit_Index];
+             
+            if (r_Clock_Count < CLKS_PER_BIT-1)
+              begin
+                r_Clock_Count <= r_Clock_Count + 1;
+                r_SM_Main     <= s_TX_DATA_BITS;
+              end
+            else
+              begin
+                r_Clock_Count <= 0;
+                 
+                // Check if we have sent out all bits
+                if (r_Bit_Index < 7)
+                  begin
+                    r_Bit_Index <= r_Bit_Index + 1;
+                    r_SM_Main   <= s_TX_DATA_BITS;
+                  end
+                else
+                  begin
+                    r_Bit_Index <= 0;
+                    r_SM_Main   <= s_TX_STOP_BIT;
+                  end
+              end
+          end // case: s_TX_DATA_BITS
+         
+         
+        // Send out Stop bit.  Stop bit = 1
+        s_TX_STOP_BIT :
+          begin
+            o_Tx_Serial <= 1'b1;
+             
+            // Wait CLKS_PER_BIT-1 clock cycles for Stop bit to finish
+            if (r_Clock_Count < CLKS_PER_BIT-1)
+              begin
+                r_Clock_Count <= r_Clock_Count + 1;
+                r_SM_Main     <= s_TX_STOP_BIT;
+              end
+            else
+              begin
+                r_Tx_Done     <= 1'b1;
+                r_Clock_Count <= 0;
+                r_SM_Main     <= s_CLEANUP;
+                r_Tx_Active   <= 1'b0;
+              end
+          end // case: s_Tx_STOP_BIT
+         
+         
+        // Stay here 1 clock
+        s_CLEANUP :
+          begin
+            r_Tx_Done <= 1'b1;
+            r_SM_Main <= s_IDLE;
+          end
+         
+         
+        default :
+          r_SM_Main <= s_IDLE;
+         
+      endcase
+    end
+ 
+  assign o_Tx_Active = r_Tx_Active;
+  assign o_Tx_Done   = r_Tx_Done;
+   
+endmodule
diff --git a/verilog/includes/includes.rtl.caravel_user_project b/verilog/includes/includes.rtl.caravel_user_project
index 31ab09b..0fc9ef2 100644
--- a/verilog/includes/includes.rtl.caravel_user_project
+++ b/verilog/includes/includes.rtl.caravel_user_project
@@ -1,5 +1,34 @@
++define+PRINTF_COND=1
++define+RANDOMIZE_MEM_INIT
++define+RANDOMIZE_REG_INIT
++define+RANDOMIZE_DELAY=1
++define+UART_HIGH_SPEED
++define+WAVEFORM
++define+RAM_ON_TOP
+
 # Caravel user project includes
 -v $(USER_PROJECT_VERILOG)/rtl/user_project_wrapper.v	     
--v $(USER_PROJECT_VERILOG)/rtl/user_proj_example.v
 
- 
\ No newline at end of file
++incdir+$(USER_PROJECT_VERILOG)/rtl/marmot_no_sram
+-v $(USER_PROJECT_VERILOG)/rtl/marmot_no_sram/Marmot.v
+-v $(USER_PROJECT_VERILOG)/rtl/marmot_no_sram/shc.marmotcaravel.MarmotCaravelChip.MarmotCaravelConfig.top.no_sram.v
+-v $(USER_PROJECT_VERILOG)/rtl/marmot_no_sram/shc.marmotcaravel.MarmotCaravelChip.MarmotCaravelConfig.top.mems.sky130.no_sram.v
+-v $(USER_PROJECT_VERILOG)/rtl/marmot_no_sram/SRLatch.v
+-v $(USER_PROJECT_VERILOG)/rtl/marmot_no_sram/plusarg_reader.v
+ 
+#-v $(USER_PROJECT_VERILOG)/lib/clk_skew_adjust.gv
+#-v $(USER_PROJECT_VERILOG)/lib/ctech_cells.sv
+-v $(USER_PROJECT_VERILOG)/lib/sky130_sram_1kbyte_1rw1r_32x256_8.v
+#-v $(USER_PROJECT_VERILOG)/lib/sky130_sram_2kbyte_1rw1r_32x512_8.v
+
+// SPI Flash model
++define+SPEEDSIM
+-v $(USER_PROJECT_VERILOG)/dv/vip/MX25U3235F.v
+
+// SPI RAM model (protected, Questa is needed)
+//-v $(USER_PROJECT_VERILOG)/dv/vip/APM_APS6404L-3SQN_SQPI_PSRAM_model_v2.9_encrypt.vp_modelsim
+
+// UART model
++incdir+$(USER_PROJECT_VERILOG)/dv/vip/uart
+-v $(USER_PROJECT_VERILOG)/dv/vip/uart/uart_tb.v
+