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
+