-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrss2.xml
294 lines (147 loc) · 544 KB
/
rss2.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
<title>Switch</title>
<link>https://xidianswq.github.io/</link>
<atom:link href="https://xidianswq.github.io/rss2.xml" rel="self" type="application/rss+xml"/>
<description>舟遥遥以轻扬,风飘飘而吹衣</description>
<pubDate>Tue, 11 Feb 2025 09:04:16 GMT</pubDate>
<generator>http://hexo.io/</generator>
<item>
<title>使用Hexo部署NexT主题网站</title>
<link>https://xidianswq.github.io/2025/02/11/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/%E4%BD%BF%E7%94%A8Hexo%E9%83%A8%E7%BD%B2NexT%E4%B8%BB%E4%BD%93%E7%BD%91%E7%AB%99/</link>
<guid>https://xidianswq.github.io/2025/02/11/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/%E4%BD%BF%E7%94%A8Hexo%E9%83%A8%E7%BD%B2NexT%E4%B8%BB%E4%BD%93%E7%BD%91%E7%AB%99/</guid>
<pubDate>Tue, 11 Feb 2025 08:37:17 GMT</pubDate>
<description><h1 id="一-使用git提交文件"><a href="#一-使用git提交文件" class="headerlink" title="一.使用git提交文件"></a>一.使用git提交文件</h1></description>
<content:encoded><![CDATA[<h1 id="一-使用git提交文件"><a href="#一-使用git提交文件" class="headerlink" title="一.使用git提交文件"></a>一.使用git提交文件</h1><blockquote><p>参考: <a href="https://zhuanlan.zhihu.com/p/102592286">从零开始搭建个人博客(超详细) - 知乎</a> <em><strong>致谢!</strong></em></p></blockquote><h2 id="第一种:本地没有-git-仓库"><a href="#第一种:本地没有-git-仓库" class="headerlink" title="第一种:本地没有 git 仓库"></a>第一种:本地没有 git 仓库</h2><ul><li>直接将远程仓库 clone 到本地;</li><li>将文件添加并 commit 到本地仓库;</li><li>将本地仓库的内容push到远程仓库。</li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line">$ ssh -T [email protected]</span><br><span class="line">Hi xidianswq! You've successfully authenticated, but GitHub does not provide shell access.</span><br><span class="line">$ git clone [email protected]:xidianswq/switch_homepage.git</span><br><span class="line">Cloning into 'switch_homepage'...</span><br><span class="line">remote: Enumerating objects: 3, done.</span><br><span class="line">remote: Counting objects: 100% (3/3), done.</span><br><span class="line">remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)</span><br><span class="line">Receiving objects: 100% (3/3), done.</span><br><span class="line">$ cd ./switch_homepage</span><br><span class="line">$ git status</span><br><span class="line">On branch main</span><br><span class="line">Your branch is up to date with 'origin/main'.</span><br><span class="line">Untracked files:</span><br><span class="line"> (use "git add <file>..." to include in what will be committed)</span><br><span class="line"> test.txt</span><br><span class="line"></span><br><span class="line">nothing added to commit but untracked files present (use "git add" to track)</span><br><span class="line">$ git add test.txt</span><br><span class="line">$ git commit -m test.txt "test.txt"</span><br><span class="line">[main 4463650] test.txt</span><br><span class="line"> 1 file changed, 0 insertions(+), 0 deletions(-)</span><br><span class="line"> create mode 100644 test.txt</span><br><span class="line">$ git log</span><br><span class="line">commit 4463650540e1bc66dc16aedc8b132e11b5e469ed (HEAD -> main)</span><br><span class="line">Author: xidianswq <[email protected]></span><br><span class="line">Date: Thu Feb 6 22:31:41 2025 +0800</span><br><span class="line"></span><br><span class="line"> test.txt</span><br><span class="line"></span><br><span class="line">commit 8f09f668066393a7b16b2c8c5df31e0d6a64eaa1 (origin/main, origin/HEAD)</span><br><span class="line">Author: xidianswq <[email protected]></span><br><span class="line">Date: Thu Feb 6 21:32:08 2025 +0800</span><br><span class="line"></span><br><span class="line"> Initial commit</span><br><span class="line">$ git push origin main</span><br><span class="line">Enumerating objects: 4, done.</span><br><span class="line">Counting objects: 100% (4/4), done.</span><br><span class="line">Delta compression using up to 16 threads</span><br><span class="line">Compressing objects: 100% (2/2), done.</span><br><span class="line">Writing objects: 100% (3/3), 269 bytes | 269.00 KiB/s, done.</span><br><span class="line">Total 3 (delta 0), reused 0 (delta 0), pack-reused 0</span><br><span class="line">To github.com:xidianswq/switch_homepage.git</span><br><span class="line"> 8f09f66..4463650 main -> main</span><br></pre></td></tr></table></figure><hr><h2 id="第二种:本地有-Git-仓库,并且我们已经进行了多次-commit-操作"><a href="#第二种:本地有-Git-仓库,并且我们已经进行了多次-commit-操作" class="headerlink" title="第二种:本地有 Git 仓库,并且我们已经进行了多次 commit 操作"></a>第二种:本地有 Git 仓库,并且我们已经进行了多次 commit 操作</h2><ul><li>建立一个本地仓库进入,init 初始化;</li><li>关联远程仓库;</li><li>同步远程仓库和本地仓库;</li><li>将文件添加提交到本地仓库;</li><li>将本地仓库的内容 push 到远程仓库。</li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">$ ssh -T [email protected]</span><br><span class="line">Hi xidianswq! You've successfully authenticated, but GitHub does not provide shell access.</span><br><span class="line">$ cd switch_homepage/public/switch_homepage/</span><br><span class="line">$ git remote add origin [email protected]:xidianswq/switch_homepage.git</span><br><span class="line">$ git add test2.txt</span><br><span class="line">$ git commit -m "test2.txt"</span><br><span class="line">$ git push origin master</span><br><span class="line">Enumerating objects: 3, done.</span><br><span class="line">Counting objects: 100% (3/3), done.</span><br><span class="line">Writing objects: 100% (3/3), 207 bytes | 207.00 KiB/s, done.</span><br><span class="line">Total 3 (delta 0), reused 0 (delta 0), pack-reused 0</span><br><span class="line">remote:</span><br><span class="line">remote: Create a pull request for 'master' on GitHub by visiting:</span><br><span class="line">remote: https://github.com/xidianswq/switch_homepage/pull/new/master</span><br><span class="line">remote:</span><br><span class="line">To github.com:xidianswq/switch_homepage.git</span><br><span class="line"> * [new branch] master -> master/</span><br></pre></td></tr></table></figure><p><em>两种由于创建的主体不同,如果关联同一仓库即会产生分支Branches,例如main和master两个版本</em></p><hr><h1 id="二-Hexo部署个人博客"><a href="#二-Hexo部署个人博客" class="headerlink" title="二.Hexo部署个人博客"></a>二.Hexo部署个人博客</h1><blockquote><p>参考: <a href="https://zhuanlan.zhihu.com/p/105715224">个人博客第5篇——安装node.js和Hexo - 知乎</a> <em><strong>致谢!</strong></em></p></blockquote><h2 id="1-本地静态部署"><a href="#1-本地静态部署" class="headerlink" title="1.本地静态部署"></a>1.本地静态部署</h2><ul><li>完成git通过ssh连接github步骤</li><li>node官网下载安装</li><li>用 node -v 和 npm -v 命令检查版本</li><li>设置npm在安装全局模块时的路径和环境变量(npm install X -g时的安装目录):</li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npm config set prefix "D:\nodejs\node_global"</span><br><span class="line">npm config set cache "D:\nodejs\node_cache"</span><br></pre></td></tr></table></figure><ul><li>设置环境变量</li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">npm install webpack -g</span><br><span class="line">github创建XXX.github.io仓库</span><br><span class="line">npm install -g hexo-cli</span><br><span class="line">hexo init</span><br><span class="line">hexo g</span><br><span class="line">hexo s#static deploy</span><br></pre></td></tr></table></figure><blockquote><p><strong>解决 bash: hexo: command not found:</strong><br>参考: <a href="https://blog.csdn.net/qq_36759224/article/details/100411949?spm=1001.2014.3001.550">完美解决 bash: hexo: command not found-CSDN博客</a> </p></blockquote><hr><h2 id="2-动态部署及后续更新"><a href="#2-动态部署及后续更新" class="headerlink" title="2.动态部署及后续更新"></a>2.动态部署及后续更新</h2><ul><li>修改hexo根目录_config.yml文件</li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">deploy:</span><br><span class="line">type: git</span><br><span class="line"> repository: XXX.github.io.git #你的仓库地址</span><br><span class="line"> branch: master</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-deployer-git --save</span><br></pre></td></tr></table></figure><p>重新部署网页三条指令:</p><ul><li>hexo clean #清除缓存文件 db.json 和已生成的静态文件 public(同时检查语法)</li><li>hexo g #生成网站静态文件到默认设置的 public 文件夹(hexo generate 的缩写)</li><li>hexo d #自动生成网站静态文件,并部署到设定的仓库(hexo deploy 的缩写)</li></ul><blockquote><p><strong>注:打开XXX.github.io网页时使用默认分支branch,可在设置内设置默认分支</strong><br>(参考: <a href="https://blog.csdn.net/Zero_Wong/article/details/123882159?spm=1001.2014.3001.5506">github:master提交项目到远程仓库出现“There isn’t anything to compare.”_there isn鈥檛 anything to compare.-CSDN博客</a> )。</p></blockquote><hr><h1 id="三-安装及优化NexT主题"><a href="#三-安装及优化NexT主题" class="headerlink" title="三.安装及优化NexT主题"></a>三.安装及优化NexT主题</h1><h2 id="1-安装NexT主题"><a href="#1-安装NexT主题" class="headerlink" title="1.安装NexT主题"></a>1.安装NexT主题</h2><blockquote><p>参考目录:<br> <a href="https://zhuanlan.zhihu.com/p/105584373">个人博客第7篇——设置next主题 - 知乎</a> ;<br> <a href="https://zhuanlan.zhihu.com/p/106060640">个人博客第8篇——优化主题(持续更新) - 知乎</a><br><em><strong>致谢!</strong></em></p></blockquote><ul><li>在网页根目录:<code>git clone https://github.com/theme-next/hexo-theme-next themes/next</code> 下载主题</li><li>打开根目录下的<code>\_config.yml</code>(称为站点配置文件),修改主题(注意冒号后都要有空格):</li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"># Site</span><br><span class="line">title: XXX #标题</span><br><span class="line">subtitle: ''</span><br><span class="line">description: 选择有时候比努力更重要 #简介或者格言</span><br><span class="line">keywords:</span><br><span class="line">author: XX #作者</span><br><span class="line">language: zh-CN #主题语言</span><br><span class="line">timezone: Asia/Shanghai #中国的时区</span><br><span class="line"></span><br><span class="line"># Extensions</span><br><span class="line">## Plugins: https://hexo.io/plugins/</span><br><span class="line">## Themes: https://hexo.io/themes/</span><br><span class="line">theme: next #主题改为next</span><br></pre></td></tr></table></figure><ul><li>打开目录Blog/themes/next/下的_config.yml(称为主题配置文件),选择需要使用的主题,注释其他的</li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"># Schemes</span><br><span class="line">#scheme: Muse</span><br><span class="line">#scheme: Mist</span><br><span class="line">#scheme: Pisces</span><br><span class="line">scheme: Gemini #这是我选的主题</span><br></pre></td></tr></table></figure><ul><li>回到根目录打开Git Bash,输入如下三条命令:</li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo clean & hexo g & hexo d</span><br></pre></td></tr></table></figure><hr><h2 id="2-优化主题"><a href="#2-优化主题" class="headerlink" title="2.优化主题"></a>2.优化主题</h2><blockquote><p>参考: </p><p>[1] <a href="https://zhuanlan.zhihu.com/p/106060640">个人博客第8篇——优化主题(持续更新) - 知乎</a><br>[2] <a href="https://blog.csdn.net/2301_77285173/article/details/130189857">在hexo博客中插入图片的方法_hexo插入图片-CSDN博客</a> </p><p><em><strong>致谢!</strong></em></p></blockquote><ul><li>下载主题next:</li></ul><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone https://github.com/theme-next/hexo-theme-next themes/next</span><br></pre></td></tr></table></figure><ul><li>参考博客中错误:<ul><li>第6个,设置背景图片,添加内容的时候,url(/images/…),斜杠一定不要漏加</li></ul></li></ul><p><strong>其他</strong>:</p><ul><li><p>新建文章时,在相同目录下创建同名文件夹(便于图片管理)</p><ul><li>打开站点配置文件_config.yml,搜索post_asset_folder字段,设置其值为true</li><li>安装hexo-asset-image:<code>npm install hexo-asset-image --save</code></li><li>此时hexo new “fileName”会在/source/_posts 目录下创建同名的文件夹</li><li>只需在 md 文件里使用  ,无需路径名就可以插入图片。</li></ul><blockquote><p>原文链接: <a href="https://blog.csdn.net/weixin_39345384/article/details/80785373">Hexo框架下用NexT(v7.0+)主题美化博客_next主题魔改教程-CSDN博客</a> </p></blockquote></li><li><p>其他参考:</p><blockquote><p> <a href="https://blog.csdn.net/qq_40590778/article/details/104662040">hexo+next添加鼠标点击和打字特效-CSDN博客</a> </p><p> <a href="https://blog.csdn.net/weixin_43988498/article/details/122434344">hexo博客工具屏蔽上传一些私人文章_hexo markdown设定文章不发布-CSDN博客</a> </p><p> <a href="http://shijivk.cn/2021/07/23/hexo-deploy-issue/">Hexo本地预览与部署样式不统一的几种可能的解决思路 | 云上时记</a> </p><p> <a href="https://zsyyblog.com/dd40c9f4.html#%E5%90%84%E7%A7%8D%E7%96%91%E9%9A%BE%E6%9D%82%E7%97%87">Hexo 博客上手入门指南、性能优化、界面美化、扩展功能、各种疑难杂症等解决方案全系列合辑 | 竹山一叶</a></p></blockquote></li></ul><h2 id="3-NexT主体颜色更改"><a href="#3-NexT主体颜色更改" class="headerlink" title="3.NexT主体颜色更改"></a>3.NexT主体颜色更改</h2><ul><li>在网页上右键想要更改的样式,点击检查(或F12,在网页元素 “flex” 中寻找对应 html 代码)</li><li>在样式中找到对应规则,复制关键字,在vscode中寻找对应段代码,进行相应修改</li><li>一些常用的样式配置文件:<ul><li><code>~\themes\next\source\css\\variables\base.styl</code></li><li><code>~\themes\next\source\css\\variables\Pisces.styl</code></li><li><code>~\themes\next\layout\macro\post.swig</code></li><li><code>~\themes\next\layout\\partials\footer.swig</code></li></ul></li><li><code>themes\next\source\css\_common\outline\header\site-meta.styl</code></li></ul><h2 id="4-侧边栏“当前位置”显示样式更改"><a href="#4-侧边栏“当前位置”显示样式更改" class="headerlink" title="4.侧边栏“当前位置”显示样式更改"></a>4.侧边栏“当前位置”显示样式更改</h2><ul><li>vscode搜索<code>.sidebar-nav-active</code>,此为点击后的显示效果,可更改颜色与字体</li></ul> <figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">.sidebar-nav-active {</span><br><span class="line"> border-bottom-color: $sidebar-highlight;</span><br><span class="line"> color: $sidebar-highlight;</span><br><span class="line"></span><br><span class="line"> font-weight: bold;</span><br><span class="line"> font-size: 1.05em;</span><br><span class="line"> font-style: italic;</span><br><span class="line"></span><br><span class="line"> &:hover {</span><br><span class="line"> color: $sidebar-highlight;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><ul><li>同理,更改<code>.active-current > a</code>,如下:</li></ul> <figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">.active-current > a {</span><br><span class="line"> color: $sidebar-highlight;</span><br><span class="line"></span><br><span class="line"> font-weight: bold;</span><br><span class="line"> font-size: 1.25em;</span><br><span class="line"> font-style: italic;</span><br><span class="line"> </span><br><span class="line"> &:hover {</span><br><span class="line"> color: $sidebar-highlight;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="5-更改字体"><a href="#5-更改字体" class="headerlink" title="5.更改字体"></a>5.更改字体</h2><blockquote><p>(参考: <strong><a href="https://hexo-next.readthedocs.io/zh-cn/latest/next/advanced/%E5%AD%97%E4%BD%93%E8%AE%BE%E7%BD%AE/">字体设置 - Hexo-NexT</a></strong> )</p></blockquote><ul><li><p>在 <a href="https://fonts.google.com/">Browse Fonts - Google Fonts</a> 网站点击想使用的字体</p><ul><li>点击<code> Get font</code>、<code> Get embed code</code></li><li>复制<code>Embed code in the <head> of your html</code>内的内容</li><li>复制<code>字体: CSS class</code>内的内容</li></ul></li><li><p>修改<code>~\themes\next\layout\_partials\head\head.swig</code>,在<code>{{ next_font() }}</code>下添加之前复制的内容</p><p><code> <link href="https://fonts.googleapis.com/css?family=Noto+Serif+SC|Roboto&display=swap" rel="stylesheet"></code></p></li><li><p>在需要修改字体的地方添加或修改<code>font-style</code>,如何搜索修改位置见上<em><strong>NexT主体颜色更改</strong></em></p></li></ul>]]></content:encoded>
<category domain="https://xidianswq.github.io/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">学习笔记</category>
<category domain="https://xidianswq.github.io/tags/Hexo/">Hexo</category>
<category domain="https://xidianswq.github.io/tags/%E7%BD%91%E7%AB%99/">网站</category>
<category domain="https://xidianswq.github.io/tags/html/">html</category>
<comments>https://xidianswq.github.io/2025/02/11/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/%E4%BD%BF%E7%94%A8Hexo%E9%83%A8%E7%BD%B2NexT%E4%B8%BB%E4%BD%93%E7%BD%91%E7%AB%99/#disqus_thread</comments>
</item>
<item>
<title>CSDN博客导出为Hexo的MD文件</title>
<link>https://xidianswq.github.io/2025/02/08/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/CSDN%E5%8D%9A%E5%AE%A2%E5%AF%BC%E5%87%BA%E4%B8%BAHexo%E7%9A%84MD%E6%96%87%E4%BB%B6/</link>
<guid>https://xidianswq.github.io/2025/02/08/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/CSDN%E5%8D%9A%E5%AE%A2%E5%AF%BC%E5%87%BA%E4%B8%BAHexo%E7%9A%84MD%E6%96%87%E4%BB%B6/</guid>
<pubDate>Sat, 08 Feb 2025 05:13:00 GMT</pubDate>
<description><h1 id="CSDN博客导出为Hexo的MD文件"><a href="#CSDN博客导出为Hexo的MD文件" class="headerlink" title="CSDN博客导出为Hexo的MD文件"></a>CSDN博客导出为Hexo的MD文件</h1></description>
<content:encoded><![CDATA[<h1 id="CSDN博客导出为Hexo的MD文件"><a href="#CSDN博客导出为Hexo的MD文件" class="headerlink" title="CSDN博客导出为Hexo的MD文件"></a>CSDN博客导出为Hexo的MD文件</h1><p>一.获取所有文章地址、 二.使用脚本进行采集 </p><blockquote><p>参考:<a href="https://www.cnblogs.com/air/p/18429617">CSDN文章导出md并迁移至博客园 - lytcreate - 博客园</a> </p></blockquote><p>部分代码修正:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line"></span><br><span class="line"> url_list = [{<span class="string">'url'</span>: item[<span class="string">'url'</span>], <span class="string">'title'</span>: item[<span class="string">'title'</span>]} <span class="keyword">for</span> item <span class="keyword">in</span> data]</span><br><span class="line"> <span class="comment"># 解析地址</span></span><br><span class="line"> base_url = <span class="string">'https://www.helloworld.net/getUrlHtml?url='</span></span><br><span class="line"> <span class="comment"># 解析错误的url</span></span><br><span class="line"> err_list = []</span><br><span class="line"> <span class="keyword">for</span> item <span class="keyword">in</span> url_list:</span><br><span class="line"> <span class="keyword">try</span>:</span><br><span class="line"> <span class="built_in">print</span>(item[<span class="string">'url'</span>])</span><br><span class="line"> res = requests.get(base_url + item[<span class="string">'url'</span>])</span><br><span class="line"> content = res.json().get(<span class="string">'html'</span>)</span><br><span class="line"> title = item[<span class="string">'title'</span>]</span><br><span class="line"> <span class="built_in">print</span>(title+<span class="string">'已完成'</span>)</span><br><span class="line"> <span class="comment"># 调用函数,将HTML转换为Markdown并保存为文件</span></span><br><span class="line"> html_to_md(content, os.path.join(<span class="string">'md'</span>, <span class="string">f'<span class="subst">{title}</span>.md'</span>)) </span><br><span class="line"> <span class="keyword">except</span> Exception <span class="keyword">as</span> e: </span><br><span class="line"> <span class="built_in">print</span>(e) </span><br><span class="line"> err_list.append(item[<span class="string">'url'</span>]) </span><br><span class="line"> <span class="keyword">if</span> err_list: </span><br><span class="line"> <span class="built_in">print</span>(err_list) </span><br><span class="line"> df = pd.DataFrame([{<span class="string">'name'</span>: err_list}]) </span><br><span class="line"> df.to_csv(<span class="string">'err.csv'</span>, index=<span class="literal">False</span>)</span><br></pre></td></tr></table></figure><p><em><strong>注:可能出现的问题:博客名不合规无法保存——修改文件名</strong></em></p><hr><h2 id="三-批量给md文件增加hexo识别码"><a href="#三-批量给md文件增加hexo识别码" class="headerlink" title="三.批量给md文件增加hexo识别码"></a>三.批量给md文件增加hexo识别码</h2><p>hexo识别文章需要添加如下信息:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">---</span><br><span class="line">title: "XXX"</span><br><span class="line">date: 20XX-XX-XX XX:XX:XX</span><br><span class="line">tags: ['AA', 'BB',...]</span><br><span class="line">......(依据manu设置)</span><br><span class="line">---</span><br></pre></td></tr></table></figure><p>对于CSDN批量导出文章,采用以下方法快速增加相关信息:</p><ul><li>创建 <em>CSDN_INFO.txt</em> 保存之前在浏览器console导出的文章信息</li><li>使用脚本 <em>AddInfo_CSDN.py</em> 将信息自动添加到对应md文件中,将需要转换的 <em>.md</em> 文件保存在同目录的 <em>md</em> 文件夹中</li></ul><p><em>AddInfo_CSDN.py</em> 内容如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 为所有md文件开头添加对应CSDN_INFO.txt中的信息</span></span><br><span class="line"><span class="comment"># ---</span></span><br><span class="line"><span class="comment"># title: "标题"</span></span><br><span class="line"><span class="comment"># date: 2020-01-01 00:00:00</span></span><br><span class="line"><span class="comment"># tags: ["标签1", "标签2"...]</span></span><br><span class="line"><span class="comment"># ---</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">import</span> re</span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"></span><br><span class="line"><span class="comment"># 读取CSDN_INFO.txt,提取每篇文章对应的文章标题title、日期postTime、标签tags</span></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">readCSDNInfo</span>():</span><br><span class="line"> CSDNInfo = {}</span><br><span class="line"> <span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">"CSDN_INFO.txt"</span>, <span class="string">"r"</span>, encoding=<span class="string">"utf-8"</span>) <span class="keyword">as</span> f:</span><br><span class="line"> <span class="comment"># 字符匹配title、postTime、tags</span></span><br><span class="line"> title = re.findall(<span class="string">r"title\": \"(.*?)\""</span>, f.read())</span><br><span class="line"> f.seek(<span class="number">0</span>)<span class="comment">#文件指针重置</span></span><br><span class="line"> postTime = re.findall(<span class="string">r"postTime\": \"(.*?)\""</span>, f.read())</span><br><span class="line"> f.seek(<span class="number">0</span>)</span><br><span class="line"> all_tags = re.findall(<span class="string">r'"tags":\s*\[([^\]]+)\]'</span>, f.read())</span><br><span class="line"> tags = [<span class="literal">None</span>] * <span class="built_in">len</span>(title)</span><br><span class="line"> <span class="comment"># 进一步提取每个标签</span></span><br><span class="line"> <span class="keyword">for</span> tag_group <span class="keyword">in</span> all_tags:</span><br><span class="line"> <span class="comment"># 提取双引号中的内容</span></span><br><span class="line"> tags[all_tags.index(tag_group)] = re.findall(<span class="string">r'"([^"]+)"'</span>, tag_group)</span><br><span class="line"> <span class="comment"># 提取title、postTime、tags</span></span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="built_in">len</span>(title)):</span><br><span class="line"> CSDNInfo[title[i]] = {}</span><br><span class="line"> CSDNInfo[title[i]][<span class="string">"postTime"</span>] = postTime[i]</span><br><span class="line"> CSDNInfo[title[i]][<span class="string">"tags"</span>] = tags[i]</span><br><span class="line"> <span class="keyword">return</span> CSDNInfo</span><br><span class="line"> </span><br><span class="line"><span class="comment"># 为md文件开头添加对应CSDN_INFO.txt中的信息</span></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">addInfo2MD</span>(<span class="params">mdPath, CSDNInfo</span>):</span><br><span class="line"> title = os.path.basename(mdPath).split(<span class="string">"."</span>)[<span class="number">0</span>]</span><br><span class="line"> <span class="keyword">if</span> title <span class="keyword">in</span> CSDNInfo:</span><br><span class="line"> <span class="keyword">with</span> <span class="built_in">open</span>(mdPath, <span class="string">"r"</span>, encoding=<span class="string">"utf-8"</span>) <span class="keyword">as</span> f:</span><br><span class="line"> lines = f.readlines()</span><br><span class="line"> <span class="keyword">if</span> lines[<span class="number">0</span>].startswith(<span class="string">"---"</span>):</span><br><span class="line"> <span class="keyword">return</span></span><br><span class="line"> <span class="keyword">with</span> <span class="built_in">open</span>(mdPath, <span class="string">"r"</span>, encoding=<span class="string">"utf-8"</span>) <span class="keyword">as</span> f:</span><br><span class="line"> content = f.read()</span><br><span class="line"> <span class="keyword">with</span> <span class="built_in">open</span>(mdPath, <span class="string">"w"</span>, encoding=<span class="string">"utf-8"</span>) <span class="keyword">as</span> f:</span><br><span class="line"> f.write(<span class="string">"---\n"</span>)</span><br><span class="line"> f.write(<span class="string">f"title: \"<span class="subst">{title}</span>\"\n"</span>)</span><br><span class="line"> f.write(<span class="string">f"date: <span class="subst">{CSDNInfo[title][<span class="string">'postTime'</span>]}</span>\n"</span>)</span><br><span class="line"> f.write(<span class="string">f"tags: <span class="subst">{CSDNInfo[title][<span class="string">'tags'</span>]}</span>\n"</span>)</span><br><span class="line"> f.write(<span class="string">"---\n"</span>)</span><br><span class="line"> f.write(content)</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">f"AddInfo: <span class="subst">{title}</span>"</span>)</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">f"Error: <span class="subst">{title}</span> not in CSDN_INFO.txt"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 遍历所有md文件</span></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">traverseMDFiles</span>(<span class="params">mdDir, CSDNInfo</span>):</span><br><span class="line"> <span class="keyword">for</span> root, dirs, files <span class="keyword">in</span> os.walk(mdDir):</span><br><span class="line"> <span class="keyword">for</span> file <span class="keyword">in</span> files:</span><br><span class="line"> <span class="keyword">if</span> file.endswith(<span class="string">".md"</span>):</span><br><span class="line"> mdPath = os.path.join(root, file)</span><br><span class="line"> addInfo2MD(mdPath, CSDNInfo)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">"__main__"</span>:</span><br><span class="line"> mdDir = <span class="string">"md"</span></span><br><span class="line"> CSDNInfo = readCSDNInfo()</span><br><span class="line"> traverseMDFiles(mdDir, CSDNInfo)</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">"Done!"</span>)</span><br></pre></td></tr></table></figure>]]></content:encoded>
<category domain="https://xidianswq.github.io/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">学习笔记</category>
<category domain="https://xidianswq.github.io/tags/Hexo/">Hexo</category>
<category domain="https://xidianswq.github.io/tags/python/">python</category>
<category domain="https://xidianswq.github.io/tags/%E7%BD%91%E7%AB%99/">网站</category>
<comments>https://xidianswq.github.io/2025/02/08/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/CSDN%E5%8D%9A%E5%AE%A2%E5%AF%BC%E5%87%BA%E4%B8%BAHexo%E7%9A%84MD%E6%96%87%E4%BB%B6/#disqus_thread</comments>
</item>
<item>
<title>Hello World</title>
<link>https://xidianswq.github.io/2025/02/08/hello-world/</link>
<guid>https://xidianswq.github.io/2025/02/08/hello-world/</guid>
<pubDate>Fri, 07 Feb 2025 16:33:48 GMT</pubDate>
<description><p>Welcome to <a href="https://hexo.io/">Hexo</a>! This is your very first post. Check <a href="https://hexo.io/docs/">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href="https://hexo.io/docs/troubleshooting.html">troubleshooting</a> or you can ask me on <a href="https://github.com/hexojs/hexo/issues">GitHub</a>.</p></description>
<content:encoded><![CDATA[<p>Welcome to <a href="https://hexo.io/">Hexo</a>! This is your very first post. Check <a href="https://hexo.io/docs/">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href="https://hexo.io/docs/troubleshooting.html">troubleshooting</a> or you can ask me on <a href="https://github.com/hexojs/hexo/issues">GitHub</a>.</p><h2 id="Quick-Start"><a href="#Quick-Start" class="headerlink" title="Quick Start"></a>Quick Start</h2><h3 id="Create-a-new-post"><a href="#Create-a-new-post" class="headerlink" title="Create a new post"></a>Create a new post</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo new <span class="string">"My New Post"</span></span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/writing.html">Writing</a></p><h3 id="Run-server"><a href="#Run-server" class="headerlink" title="Run server"></a>Run server</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo server</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/server.html">Server</a></p><h3 id="Generate-static-files"><a href="#Generate-static-files" class="headerlink" title="Generate static files"></a>Generate static files</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo generate</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/generating.html">Generating</a></p><h3 id="Deploy-to-remote-sites"><a href="#Deploy-to-remote-sites" class="headerlink" title="Deploy to remote sites"></a>Deploy to remote sites</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo deploy</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/one-command-deployment.html">Deployment</a></p>]]></content:encoded>
<comments>https://xidianswq.github.io/2025/02/08/hello-world/#disqus_thread</comments>
</item>
<item>
<title>RANSAC算法的FPGA实现</title>
<link>https://xidianswq.github.io/2024/05/27/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/RANSAC%E7%AE%97%E6%B3%95%E7%9A%84FPGA%E5%AE%9E%E7%8E%B0/</link>
<guid>https://xidianswq.github.io/2024/05/27/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/RANSAC%E7%AE%97%E6%B3%95%E7%9A%84FPGA%E5%AE%9E%E7%8E%B0/</guid>
<pubDate>Mon, 27 May 2024 04:18:23 GMT</pubDate>
<description><p><strong>目录</strong></p></description>
<content:encoded><![CDATA[<p><strong>目录</strong></p><p><a href="about:blank#%E4%B8%80.%E7%AE%97%E6%B3%95%E5%8E%9F%E7%90%86">一.算法原理</a></p><p><a href="about:blank#1.%E5%8F%82%E6%95%B0%E5%8F%98%E9%87%8F">1.参数变量</a></p><p><a href="about:blank#2.%E7%AE%97%E6%B3%95%E6%B5%81%E7%A8%8B">2.算法流程</a></p><p><a href="about:blank#%3C1%3E%E9%9A%8F%E6%9C%BA%E8%AF%BB%E5%8F%96%E6%95%B0%E6%8D%AE"><1>随机读取数据</a></p><p><a href="about:blank#%3C2%3E%E6%8B%9F%E5%90%88%E6%A8%A1%E5%9E%8B"><2>拟合模型</a></p><p><a href="about:blank#%3C3%3E%E6%A3%80%E9%AA%8C%E6%A8%A1%E5%9E%8B"><3>检验模型</a></p><p><a href="about:blank#%3C4%3E%E5%BE%AA%E7%8E%AF%E9%81%8D%E5%8E%86"><4>循环遍历</a></p><p><a href="about:blank#%E4%BA%8C.%E8%AE%BE%E8%AE%A1%E6%80%9D%E8%B7%AF">二.设计思路</a></p><p><a href="about:blank#1.%E8%AE%BE%E8%AE%A1%E7%9B%AE%E6%A0%87">1.设计目标</a></p><p><a href="about:blank#2.%E6%A8%A1%E5%9D%97%E8%AE%BE%E8%AE%A1">2.模块设计</a></p><p><a href="about:blank#%3C1%3E%E9%9A%8F%E6%9C%BA%E6%95%B0%E4%BA%A7%E7%94%9F%E6%A8%A1%E5%9D%97"><1>随机数产生模块</a></p><p><a href="about:blank#%3C2%3E%E6%9A%82%E5%AD%98%E5%AF%84%E5%AD%98%E5%99%A8"><2>暂存寄存器</a></p><p><a href="about:blank#%3C3%3E%E8%AE%A1%E7%AE%97%E6%A8%A1%E5%9D%97"><3>计算模块</a></p><p><a href="about:blank#%3C4%3E%E6%A8%A1%E5%9E%8B%E8%AF%84%E4%BC%B0%E6%A8%A1%E5%9D%97"><4>模型评估模块</a></p><p><a href="about:blank#%3C5%3E%E4%B8%BB%E4%BD%93%E6%8E%A7%E5%88%B6%E4%B8%8E%E8%BE%93%E5%87%BA%E6%A8%A1%E5%9D%97"><5>主体控制与输出模块</a></p><p><a href="about:blank#%3C6%3E%E6%95%B4%E5%90%88"><6>整合</a></p><p><a href="about:blank#%E4%B8%89.%E5%85%B7%E4%BD%93%E5%AE%9E%E7%8E%B0">三.具体实现</a></p><p><a href="about:blank#1.Python%E6%95%B0%E6%8D%AE%E7%94%9F%E6%88%90%E6%A8%A1%E5%9D%97">1.Python数据生成模块</a></p><p><a href="about:blank#2.Verilog%20RANSAC%E7%AE%97%E6%B3%95%E4%BB%BF%E7%9C%9F%E7%BB%93%E6%9E%9C">2.Verilog<br>RANSAC算法仿真结果</a></p><p><a href="about:blank#%E5%9B%9B.%E6%80%A7%E8%83%BD%E5%88%86%E6%9E%90">四.性能分析</a></p><p><a href="about:blank#1.%E8%B5%84%E6%BA%90%E5%88%86%E6%9E%90">1.资源分析</a></p><p><a href="about:blank#2.%E9%80%9F%E5%BA%A6%E5%88%86%E6%9E%90">2.速度分析</a></p><p><a href="about:blank#3.%E9%80%89%E6%8B%A9%E4%B8%8D%E5%90%8C%E9%9A%8F%E6%9C%BA%E6%95%B0%E7%A7%8D%E5%AD%90%E4%B8%8B%E7%9A%84%E7%BB%93%E6%9E%9C">3.选择不同随机数种子下的结果</a></p><p><a href="about:blank#4.%E4%B8%8D%E5%90%8C%E9%A2%84%E8%AE%BE%E7%9B%B4%E7%BA%BF%E5%8F%82%E6%95%B0%E4%B8%8B%E7%9A%84%E6%8B%9F%E5%90%88%E7%BB%93%E6%9E%9C">4.不同预设直线参数下的拟合结果</a></p><p><a href="about:blank#%E4%BA%94.%E6%80%9D%E8%80%83%E4%B8%8E%E6%94%B9%E8%BF%9B">五.思考与改进</a></p><p><a href="about:blank#1.%E6%8F%90%E9%80%9F%E7%93%B6%E9%A2%88">1.提速瓶颈</a></p><p><a href="about:blank#2.%E5%A2%9E%E5%8A%A0%E5%B9%B6%E8%A1%8C%E7%A8%8B%E5%BA%A6">2.增加并行程度</a></p><p><a href="about:blank#3.%E7%AE%97%E6%B3%95%E6%B5%81%E7%A8%8B%E6%94%B9%E8%BF%9B">3.算法流程改进</a></p><p><a href="about:blank#%E5%85%AD.%E9%99%84%E5%BD%95">六.附录</a></p><p><a href="about:blank#1.vivado%E5%B7%A5%E7%A8%8B%E6%BA%90%E7%A0%81%E9%83%A8%E5%88%86">1.vivado工程源码部分</a></p><p><a href="about:blank#%3C1%3E%E4%B8%BB%E4%BD%93%E6%8E%A7%E5%88%B6%E9%83%A8%E5%88%86"><1>主体控制部分</a></p><p><a href="about:blank#%E4%B8%83.%E5%8F%82%E8%80%83%E6%96%87%E7%8C%AE">七.参考文献</a></p><p><a href="about:blank#%E5%85%AB.%E8%AE%BE%E8%AE%A1%E6%94%B9%E8%BF%9B">八.设计改进</a></p><p><a href="about:blank#1.%E4%B8%8D%E5%8F%AF%E7%BB%BC%E5%90%88%E8%AF%AD%E5%8F%A5">1.不可综合语句</a></p><p><a href="about:blank#2.%E4%BF%AE%E6%AD%A3%E7%A8%8B%E5%BA%8F%E8%AF%AD%E5%8F%A5">2.修正程序语句</a></p><p><a href="about:blank#3.%E6%97%B6%E9%92%9F%E6%A8%A1%E5%9D%97">3.时钟模块</a></p><p><a href="about:blank#%E4%B9%9D.%E8%AE%BE%E8%AE%A1%E5%AE%9E%E7%8E%B0%E5%88%86%E6%9E%90">九.设计实现分析</a></p><p><a href="about:blank#1.%E9%9D%99%E6%80%81%E6%97%B6%E5%BA%8F%E5%88%86%E6%9E%90">1.静态时序分析</a></p><p><a href="about:blank#%E5%8D%81.%E4%B8%8B%E8%BD%BD%E9%AA%8C%E8%AF%81">十.下载验证</a></p><hr><p>参考:</p><p><a href="https://blog.csdn.net/Graduate2015/article/details/113133919" title="伪随机序列:LFSR Sequence、m-Sequence和Gold Code/Sequence-CSDN博客">伪随机序列:LFSR Sequence、m-Sequence和Gold Code/Sequence-<br>CSDN博客</a><a href="https://blog.csdn.net/xijuezhu8128/article/details/122930455" title="RANSAC算法(附RANSAC直线拟合C++与Python版本)-CSDN博客">RANSAC算法(附RANSAC直线拟合C++与Python版本)-CSDN博客</a></p><p><a href="https://blog.csdn.net/zhoucoolqi/article/details/105497572?spm=1001.2014.3001.5506" title="RANSAC算法——看完保证你理解-CSDN博客">RANSAC算法——看完保证你理解-<br>CSDN博客</a><a href="https://blog.csdn.net/Graduate2015/article/details/113133919" title="伪随机序列:LFSR Sequence、m-Sequence和Gold Code/Sequence-CSDN博客">伪随机序列:LFSR Sequence、m-Sequence和Gold Code/Sequence-<br>CSDN博客</a></p><h2 id="一-算法原理"><a href="#一-算法原理" class="headerlink" title="一.算法原理"></a>一.算法原理</h2><h3 id="1-参数变量"><a href="#1-参数变量" class="headerlink" title="1.参数变量"></a>1.参数变量</h3><p>输入:数据集data、拟合模型model</p><p>中间参数:一次拟合需要的数据量n;算法最大遍历次数k;计算匹配阈值t;最小匹配数据数d</p><p>输出:完成信号done、最匹配的模型model参数</p><p>模型:二元一次线性模型,二元多次非线性模型,任意函数…</p><h3 id="2-算法流程"><a href="#2-算法流程" class="headerlink" title="2.算法流程"></a>2.算法流程</h3><h4 id="随机读取数据"><a href="#随机读取数据" class="headerlink" title="<1>随机读取数据"></a><1>随机读取数据</h4><p>随机数生成模块生成n个随机地址,取出存储器对应地址数据。</p><h4 id="拟合模型"><a href="#拟合模型" class="headerlink" title="<2>拟合模型"></a><2>拟合模型</h4><p>由读出的n个数据拟合出相应模型</p><h4 id="检验模型"><a href="#检验模型" class="headerlink" title="<3>检验模型"></a><3>检验模型</h4><p>检验存储器中所有数据对于该模型的拟合程度</p><h4 id="循环遍历"><a href="#循环遍历" class="headerlink" title="<4>循环遍历"></a><4>循环遍历</h4><p>每次循环评价随机拟合的模型,当遍历k次后结束拟合,得到最佳模型</p><h2 id="二-设计思路"><a href="#二-设计思路" class="headerlink" title="二.设计思路"></a>二.设计思路</h2><h3 id="1-设计目标"><a href="#1-设计目标" class="headerlink" title="1.设计目标"></a>1.设计目标</h3><pre><code> 工程能够完成一组坐标点集的线性拟合。输入坐标数据(x,y)的值为8bit 无符号整数数据类型,输出拟合直线参数,包括斜率k和y轴截距b,为8bit 有符号整数。</code></pre><h3 id="2-模块设计"><a href="#2-模块设计" class="headerlink" title="2.模块设计"></a>2.模块设计</h3><h4 id="随机数产生模块"><a href="#随机数产生模块" class="headerlink" title="<1>随机数产生模块"></a><1>随机数产生模块</h4><pre><code> 利用线性反馈移位寄存器(Linear Feedback Shift Register,LFSR)产生随机数,对于反馈移位寄存器和异或门构成的电路,可以按下面的关系式生成序列[1]:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/a2ef04e43713d49cbd2d77c4b3b13d13.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/e1a40e9fb00f3d512134c9efbe023418.png"></p><pre><code> 对于m位的线性反馈移位寄存器,最多可以产生2^m-1个不同状态。如果一个序列发生器正好生产这 2^m-1个不同状态之后才重复此序列。随机数产生器的初始队列成为种子(seed),随后队列对种子进行移位运算生成新队列。 工程中采用32位随机数产生模块,每次取前14位分别作为两随机点的地址(128个数据对应7位地址)。</code></pre><h4 id="暂存寄存器"><a href="#暂存寄存器" class="headerlink" title="<2>暂存寄存器"></a><2>暂存寄存器</h4><pre><code> 通过rom读取文件内数据信息,存入相关数据。Rom深度为128,对应7位地址线,宽度为16位数据前8位为x,后8位为y。采用组合逻辑电路直接输出对应地址数据。</code></pre><h4 id="计算模块"><a href="#计算模块" class="headerlink" title="<3>计算模块"></a><3>计算模块</h4><pre><code> 通过所给数据拟合出模型。输入为32位数据,前16位和后16位分别是(x1,y1)和(x2,y2)。实现的组合电路结构如下:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/c14f200db8d3e933e48fbe49a193f1fc.png"></p><p>K=(y2-y1)/(x2-x1) b=y2-k*x2</p><h4 id="模型评估模块"><a href="#模型评估模块" class="headerlink" title="<4>模型评估模块"></a><4>模型评估模块</h4><pre><code> 给定参数T_RANGE,表示允许残差平方RSS的最大值(RSS=(y-k*x-b)^2,表示期望值与实际值只差的平方),当RSS<T_RANGE时,表示该点在允许范围之内。Fit信号输出为1。实现的组合电路结构如下:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/fab333897437b774df5bb4bc2a42adc5.png"></p><h4 id="主体控制与输出模块"><a href="#主体控制与输出模块" class="headerlink" title="<5>主体控制与输出模块"></a><5>主体控制与输出模块</h4><pre><code> 用于控制迭代次数K,以及产生随机数产生模块时钟和rom地址更新。每次迭代重新生成随机数以产生新模型。遍历rom检验后比较最大线内点数fit_num,如果大于最大值则更新模型参数</code></pre><h4 id="整合"><a href="#整合" class="headerlink" title="<6>整合"></a><6>整合</h4><p><img src="https://i-blog.csdnimg.cn/blog_migrate/7d6b9180c527cfd5d39786f27076598b.png"></p><table><thead><tr><th>NAME</th><th>ADDR_WIDTH</th><th>DATA_WIDTH</th><th>INPUTDATA_WIDTH</th><th>PARA_WIDTH</th><th>T_WIDTH</th></tr></thead><tbody><tr><td>WIDTH/BITS</td><td>7</td><td>16</td><td>32</td><td>16</td><td>16</td></tr><tr><td>DETAILS</td><td></td><td>x(h_8b)</td><td>y(l_8b)</td><td>x1(h_8b)</td><td>y1(l_8b)</td></tr></tbody></table><h2 id="三-具体实现"><a href="#三-具体实现" class="headerlink" title="三.具体实现"></a>三.具体实现</h2><h3 id="1-Python数据生成模块"><a href="#1-Python数据生成模块" class="headerlink" title="1.Python数据生成模块"></a>1.Python数据生成模块</h3><pre><code> 使用python编写代码生成十六进制数据集,包含线内点和噪声点,并给出python实现ransac和最小二乘法的拟合结果。如下:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/f8b333fec06e0a78982e2978f077efd7.png"></p><pre><code> 设定直线的参数:斜率k=2,截距b=25,最小二乘法和ransac拟合参数结果如下:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/aa641fc13e378827a3ed2d7763b60aab.png"></p><pre><code> 其中红色线是最小二乘法的拟合结果,绿色线是ransac在迭代1000次,允许误差为5的拟合结果。 将产生数据以16进制形式保存,并存储于data.mem文件中在vivado中读取。</code></pre><h3 id="2-Verilog-RANSAC算法仿真结果"><a href="#2-Verilog-RANSAC算法仿真结果" class="headerlink" title="2.Verilog RANSAC算法仿真结果"></a>2.Verilog RANSAC算法仿真结果</h3><pre><code> 工程拟合结果直线参数为:斜率k=2(0x02),b=24(0x18),完全符合设定值。符合误差范围的点数最多为47个(0x2F),并在第450代(0x01C2)时随机产生的地址拟合出了最佳参数。此时的残差平方和RSS为2086(0x826)。 由于拟合和评估部分皆为组合逻辑电路,算法完成的速度取决于迭代次数K和时钟频率CLK_FRE。仿真采用100MHZ时钟,K取1000次,每次迭代遍历128个点需要128个时钟周期,故算法每次执行需要:128*K/CLK_FRE秒。本次仿真算法在0.00128s(128*1k/1M)左右结束,done信号置高电平有效,故算法频率为781.25HZ。</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/face361f9b63a0ff29ebaa18ae4d4d2f.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/4f39ebf2287ecd3f78f9f303dcd7d844.png"></p><h2 id="四-性能分析"><a href="#四-性能分析" class="headerlink" title="四.性能分析"></a>四.性能分析</h2><h3 id="1-资源分析"><a href="#1-资源分析" class="headerlink" title="1.资源分析"></a>1.资源分析</h3><p><img src="https://i-blog.csdnimg.cn/blog_migrate/2b5db5cfbb3689bbf2b38712717330ee.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/332a59e94e620fbd13c87aa0a98f3baa.png"></p><pre><code> 设计使用到的查找表、IO、缓存器等资源均较少,满足设计的资源限制。</code></pre><h3 id="2-速度分析"><a href="#2-速度分析" class="headerlink" title="2.速度分析"></a>2.速度分析</h3><pre><code> 下表给出不同迭代次数和时钟频率下的算法频率F=CLK_FRE/(128*K):</code></pre><h2 id="F-CLK-FRE-128-K"><a href="#F-CLK-FRE-128-K" class="headerlink" title="F=CLK_FRE/(128*K) "></a>F=CLK_FRE/(128*K) </h2><p>CLK_FRE(/M) | K | frequency(/Hz)<br>100 | 1000 | 781.25<br>100 | 10000 | 78.125<br>100 | 500 | 1562.5<br>80 | 1000 | 625<br>15 | 1000 | 117.1875 </p><h3 id="3-选择不同随机数种子下的结果"><a href="#3-选择不同随机数种子下的结果" class="headerlink" title="3.选择不同随机数种子下的结果"></a>3.选择不同随机数种子下的结果</h3><pre><code> 在迭代次数k=1000次下,不同随机数种子下最终结果出现的时机(其中k是代数,para是拟合参数):</code></pre><table><thead><tr><th>seed</th><th>0x12345678</th><th>0xFFFFFFFF</th><th>0x11111111</th><th>0xcd62f912</th><th>0x63e8c090</th></tr></thead><tbody><tr><td>K</td><td>450</td><td>403</td><td>13</td><td>524</td><td>360</td></tr><tr><td>PARA</td><td>0x0218</td><td>0x0218</td><td>0x0218</td><td>0x0218</td><td>0x0218</td></tr></tbody></table><h3 id="4-不同预设直线参数下的拟合结果"><a href="#4-不同预设直线参数下的拟合结果" class="headerlink" title="4.不同预设直线参数下的拟合结果"></a>4.不同预设直线参数下的拟合结果</h3><pre><code> 在seed=0x12345678下,不同预设直线参数下的拟合结果如下,其中k,b为设定值,ransac_k、ransac_b为拟合值,fit_num为检测为线内的点数(实际为128):</code></pre><table><thead><tr><th>k</th><th>2</th><th>3</th><th>4</th><th>2.5</th></tr></thead><tbody><tr><td>ransac_k</td><td>2</td><td>3</td><td>4</td><td>2</td></tr><tr><td>b</td><td>25</td><td>10</td><td>77</td><td>16</td></tr><tr><td>ransac_b</td><td>24</td><td>11</td><td>51</td><td>41</td></tr><tr><td>fit_num</td><td>47</td><td>64</td><td>25</td><td>39</td></tr></tbody></table><h2 id="五-思考与改进"><a href="#五-思考与改进" class="headerlink" title="五.思考与改进"></a>五.思考与改进</h2><h3 id="1-提速瓶颈"><a href="#1-提速瓶颈" class="headerlink" title="1.提速瓶颈"></a>1.提速瓶颈</h3><pre><code> 在算法的实现流程中,计算和评估模块均采用组合逻辑电路,而 控制部分电路采用循环遍历的方式,依次选取rom中数据对模型进行检验,大大降低了算法的速度。</code></pre><h3 id="2-增加并行程度"><a href="#2-增加并行程度" class="headerlink" title="2.增加并行程度"></a>2.增加并行程度</h3><pre><code> 在检验阶段,设计一寄存器组,提前将rom中所有数据存储至寄存器组后并行输出,连接至同等数量的evaluate_kernel模块同时进行检验。实现由之前的循环遍历校验转化为同时并行检验:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/bb02859e4670ee07014b6af6ab546d75.png"></p><h3 id="3-算法流程改进"><a href="#3-算法流程改进" class="headerlink" title="3.算法流程改进"></a>3.算法流程改进</h3><p><1>工程中模型的拟合采用直接随机选取n个数据进行拟合的方法,进而确定线内点。可以改进为最后增加一个步骤,由已经确定的线内点重新使用最小二乘法拟合参数,减小拟合参数的残差平方和RSS。</p><p><2>线内点的确定可改进为投票式,即由k个模型共同投票符合要求的片内点,选取票数最高的点作为真正的片内点[2]。</p><h2 id="六-附录"><a href="#六-附录" class="headerlink" title="六.附录"></a>六.附录</h2><h3 id="1-vivado工程源码部分"><a href="#1-vivado工程源码部分" class="headerlink" title="1.vivado工程源码部分"></a>1.vivado工程源码部分</h3><h4 id="主体控制部分"><a href="#主体控制部分" class="headerlink" title="<1>主体控制部分"></a><1>主体控制部分</h4><p><br> `timescale 1ns / 1ps<br> //<br> // Engineer: switch_swq<br> // Create Date: 2024/05/20 10:48:12<br> //<br> module evaluate<br> #(<br> parameter ADDR_WIDTH = 7,<br> parameter DATA_WIDTH = 16,<br> parameter INPUTDATA_WIDTH = 32,<br> parameter PARA_WIDTH = 16,<br> parameter T_WIDTH = 18,<br> parameter T_RANGE = 10,<br> parameter K_RANGE = 1000,<br> parameter DATA_FILE = “data.mem”<br> )<br> (<br> input wire clk_in,<br> input wire rst_in,<br> output reg done,<br> //output reg [PARA_WIDTH-1:0]best_para<br> output wire [5:0]sel,<br> output wire [7:0]seg<br> );<br><br> wire clk,rst;<br> wire [31:0]random_num;<br> wire [PARA_WIDTH-1:0] para;<br> wire [DATA_WIDTH-1:0] data;<br> wire [INPUTDATA_WIDTH-1:0]input_data;<br> wire fit;<br> wire [T_WIDTH-1:0]RSS;<br> reg random_clk;<br> reg [ADDR_WIDTH-1:0] addr,fit_count,fit_max;<br> reg [T_WIDTH-1:0]rss_num,rss_min;<br> reg [15:0]k_num;<br> reg [PARA_WIDTH-1:0]best_para;<br> wire [23:0]output_data;<br> wire [5:0]point;</p><pre><code>assign rst=~rst_in;always@(posedge clk or posedge rst)if(rst==1'b1) addr<=1'b0;else addr<=addr+1; always@(posedge clk or posedge rst)if(rst==1'b1) k_num<=1'b0;else if(k_num<=K_RANGE && addr==1'b0) k_num<=k_num+1; always@(posedge clk or posedge rst)if(rst==1'b1) random_clk<=1'b0;else if(k_num<=K_RANGE && addr==1'b0) random_clk<=1'b1;else random_clk<=1'b0; always@(posedge clk or posedge rst)if(rst==1'b1) done<=1'b0;else if(k_num>K_RANGE) done<=1'b1;else done<=1'b0;always@(posedge clk or posedge rst)begin if(rst==1'b1)begin rss_num<='b0; fit_count<='b0; fit_max<='b0; best_para<='b0; end else if(k_num<=K_RANGE)begin if(fit==1'b1)begin fit_count<=fit_count+1; rss_num<=rss_num+RSS; end if(addr==1'b0)begin if(fit_count>fit_max)begin best_para<=para; fit_max<=fit_count; rss_min<=rss_num; end rss_num<='b0; fit_count<=1'b0; end endendassign output_data={8'b0,best_para};assign point=6'b0;clk_wiz_0 clk_wiz_0_inst ( // Clock out ports .clk_out1(clk), // output clk_out1 // Clock in ports .clk_in1(clk_in) // input clk_in1);blk_mem_gen_0 blk_mem_gen_0_inst1 ( .clka(clk), // input wire clka .addra(addr), // input wire [6 : 0] addra .douta(data) // output wire [15 : 0] douta);blk_mem_gen_0 blk_mem_gen_0_inst2 ( .clka(clk), // input wire clka .addra(random_num[6:0]), // input wire [6 : 0] addra .douta(input_data[INPUTDATA_WIDTH-1:INPUTDATA_WIDTH/2]) // output wire [15 : 0] douta);blk_mem_gen_0 blk_mem_gen_0_inst3 ( .clka(clk), // input wire clka .addra(random_num[13:7]), // input wire [6 : 0] addra .douta(input_data[INPUTDATA_WIDTH/2-1:0]) // output wire [15 : 0] douta);evaluate__kernel#( .DATA_WIDTH(DATA_WIDTH), .PARA_WIDTH(PARA_WIDTH), .T_WIDTH (T_WIDTH ), .T_RANGE (T_RANGE ) )evaluate__kernel_inst( .data(data), .para(para), .RSS(RSS), .fit(fit));calculate_kernel#( .INPUTDATA_WIDTH(INPUTDATA_WIDTH), .PARA_WIDTH(PARA_WIDTH))calculate_kernel_inst( .input_data(input_data), .para(para));random_num random_num_inst( .clk (random_clk) , .rst (rst ) , .data (random_num));seg_dynamic seg_dynamic_inst( .sys_clk (clk ) , .sys_rst_n(rst ) , .data (output_data) , .point (point), .sel (sel ) , .seg (seg ) );endmodule</code></pre><h2 id="七-参考文献"><a href="#七-参考文献" class="headerlink" title="七.参考文献"></a>七.参考文献</h2><p>[1]束礼宝,宋克柱,王砚方.伪随机数发生器的FPGA实现与研究[J].电路与系统学报,2003(03):121-124.</p><p>[2]江洁,凌思睿.一种投票式并行RANSAC算法及其FPGA实现[J].电子与信息学报,2014,36(05):1145-1150.</p><h2 id="八-设计改进"><a href="#八-设计改进" class="headerlink" title="八.设计改进"></a>八.设计改进</h2><h3 id="1-不可综合语句"><a href="#1-不可综合语句" class="headerlink" title="1.不可综合语句"></a>1.不可综合语句</h3><pre><code> 原代码中夹杂着不可综合语句,如rom中的initial语句。现将数据存储器使用xilinx block memory generator ip核替换原本不可综合的rom模块。</code></pre><h3 id="2-修正程序语句"><a href="#2-修正程序语句" class="headerlink" title="2.修正程序语句"></a>2.修正程序语句</h3><p>(1)原程序出现阻塞赋值和非阻塞赋值语句混用情况,现对evaluate、evaluate_kernel、calculate_kernel相关语句进行了修正。(说明:控制模块evaluate和随机数生成模块random_num采用时序逻辑,计算和评估模块_kernel仍使用组合逻辑)</p><p>(2)原程序的控制模块evaluate中语句较为混乱,现依据信号划分语句,使结构更为清晰。</p><h3 id="3-时钟模块"><a href="#3-时钟模块" class="headerlink" title="3.时钟模块"></a>3.时钟模块</h3><pre><code> 添加xilinx clocking wizard ip核代替原硬件时钟直连,方便后续进行时序分析和调试。</code></pre><h2 id="九-设计实现分析"><a href="#九-设计实现分析" class="headerlink" title="九.设计实现分析"></a>九.设计实现分析</h2><h3 id="1-静态时序分析"><a href="#1-静态时序分析" class="headerlink" title="1.静态时序分析"></a>1.静态时序分析</h3><pre><code> 在vivado设计实现中,观察“Timing Summary”内的时钟域内路径“intra-clock paths”以确定时钟频率。可以看到路径上的时序要求“requirement”为30.303ns,数据信号在时钟周期内稳定下来的最长时间在path1上,如下图:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/8479c74fa867c5f9ca2329e5ac82e282.png"></p><pre><code> 该路径是从存储器blk_mem_gen0至寄存器fit_count_reg,即对应从随机从存储器中取数至模型遍历评估一个数结束。</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/462f462ef19b1e592eaa28041ca7d0d8.png"></p><pre><code> 按照信号稳定的最长时间为30.303ns,计算出的最大频率约为33.00MHz。在时钟约束中设置时钟的输出频率为33MHz,implement后的结果如下:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/91c5ac678cde8f1b0bf32fa7ae06f688.png"></p><pre><code> 可以看到系统的最差负时序裕量“WNS”和最差保持时序裕量“WHS”均为正;总的负时序裕量“TNS”和保持时序裕量“THS”为零,即所有的时序路径都能满足这些要求。</code></pre><h2 id="十-下载验证"><a href="#十-下载验证" class="headerlink" title="十.下载验证"></a>十.下载验证</h2><pre><code> 在工程中添加数码管显示模块,并生成比特流对工程进行下载验证。使用开发板芯片型号为xc7a35tfgg484-2,资源使用情况如下:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/32d8e202d68c50edda80d9e40a9f5d36.png"></p><pre><code> 实际运行情况如下:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/dd0a71b7d0b73f5101eb227302152b34.png"></p><h2 id="十一-后续改进"><a href="#十一-后续改进" class="headerlink" title="十一.后续改进"></a>十一.后续改进</h2><h3 id="1-时序电路设计"><a href="#1-时序电路设计" class="headerlink" title="1.时序电路设计"></a>1.时序电路设计</h3><pre><code> 将模型拟合模块和评估模块(calculate_kernel和evaluate__kernel模块)由组合逻辑改为时序逻辑,减小了信号传递的长度,从而减少线路上信号稳定所需要的时间。</code></pre><h3 id="2-流水线改进"><a href="#2-流水线改进" class="headerlink" title="2.流水线改进"></a>2.流水线改进</h3><pre><code> 在拟合和评估模块将相关计算步骤分解成流水线。</code></pre><p><img src="https://i-blog.csdnimg.cn/direct/7cc6346feffd47fbb37c328f1ba6f213.png"></p><p><img src="https://i-blog.csdnimg.cn/direct/b4d02ced10924951b3a607efb1514515.png"></p><p><img src="https://i-blog.csdnimg.cn/direct/1d33919743cf4a19a82137d91e857368.png"></p><p><img src="https://i-blog.csdnimg.cn/direct/c561475921714635b0cce41ba03c8ab0.png"></p><h3 id="3-数值精度提升"><a href="#3-数值精度提升" class="headerlink" title="3.数值精度提升"></a>3.数值精度提升</h3><pre><code> 提升线路宽度从原来8位提高到16位,并使用定点小数表示数值。高8位为整数部分,低8位为小数部分。</code></pre><h3 id="4-算法结构改进"><a href="#4-算法结构改进" class="headerlink" title="4.算法结构改进"></a>4.算法结构改进</h3><pre><code> 将评估模块由原先循环取数评估改为并行评估(evaluate_parralle模块),将评估所需时钟周期数由128变为1,以适配流水线周期长度。</code></pre><p><img src="https://i-blog.csdnimg.cn/direct/4fda9ff18bf140c6a740e791e136710a.png"></p><p><img src="https://i-blog.csdnimg.cn/direct/d00fb992865d4c92bf86772ec2471575.png"></p><p><img src="https://i-blog.csdnimg.cn/direct/7a1311448ae04201b9232d675c8a8c9a.png"></p><h3 id="5-改进后性能"><a href="#5-改进后性能" class="headerlink" title="5.改进后性能"></a>5.改进后性能</h3><pre><code> 最高时钟频率约72.4MHz(最长路径时间为12.002ns)</code></pre><h3 id="6-现存问题"><a href="#6-现存问题" class="headerlink" title="6.现存问题"></a>6.现存问题</h3><p><1>评估模块(evaluate_parralle模块)以空间换速度,占用资源较多</p><p><2>使用vivado提供的除法运算“/”所综合的器件导致该路径用时(logic delay)过长,成为时钟频率无法提升的主要问题,需进行改进。</p><p><img src="https://i-blog.csdnimg.cn/direct/c3fd17c5f6ca4efabdd1acaaab26491f.png"></p><p><img src="https://i-blog.csdnimg.cn/direct/5c821beb009e40e3b2ad1ac4a359fe48.png"></p><pre><code> 另一方面系统布线时延(net delay)也较长,表现在参数计算模块calculate_kernel的b_reg到并行评估模块kxb_reg上,仍在探索优化方法。</code></pre><p>本文转自 <a href="https://blog.csdn.net/qq_32971095/article/details/139198487">https://blog.csdn.net/qq_32971095/article/details/139198487</a>,如有侵权,请联系删除。</p>]]></content:encoded>
<category domain="https://xidianswq.github.io/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">学习笔记</category>
<category domain="https://xidianswq.github.io/tags/fpga%E5%BC%80%E5%8F%91/">fpga开发</category>
<category domain="https://xidianswq.github.io/tags/opencv/">opencv</category>
<category domain="https://xidianswq.github.io/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">学习笔记</category>
<category domain="https://xidianswq.github.io/tags/%E7%AE%97%E6%B3%95/">算法</category>
<category domain="https://xidianswq.github.io/tags/%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%A7%86%E8%A7%89/">计算机视觉</category>
<comments>https://xidianswq.github.io/2024/05/27/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/RANSAC%E7%AE%97%E6%B3%95%E7%9A%84FPGA%E5%AE%9E%E7%8E%B0/#disqus_thread</comments>
</item>
<item>
<title>西电计科大三下SOC微体系结构设计实验合集</title>
<link>https://xidianswq.github.io/2024/05/23/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/%E8%A5%BF%E7%94%B5%E8%AE%A1%E7%A7%91%E5%A4%A7%E4%B8%89%E4%B8%8BSOC%E5%BE%AE%E4%BD%93%E7%B3%BB%E7%BB%93%E6%9E%84%E8%AE%BE%E8%AE%A1%E5%AE%9E%E9%AA%8C%E5%90%88%E9%9B%86/</link>
<guid>https://xidianswq.github.io/2024/05/23/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/%E8%A5%BF%E7%94%B5%E8%AE%A1%E7%A7%91%E5%A4%A7%E4%B8%89%E4%B8%8BSOC%E5%BE%AE%E4%BD%93%E7%B3%BB%E7%BB%93%E6%9E%84%E8%AE%BE%E8%AE%A1%E5%AE%9E%E9%AA%8C%E5%90%88%E9%9B%86/</guid>
<pubDate>Thu, 23 May 2024 03:46:02 GMT</pubDate>
<description><p><strong>目录</strong></p></description>
<content:encoded><![CDATA[<p><strong>目录</strong></p><p><a href="about:blank#%E4%BA%8C.%E7%BA%BF%E4%B8%8B%E5%AE%9E%E9%AA%8C">二.线下实验</a></p><p><a href="about:blank#%E7%AE%A1%E8%84%9A%E7%BB%91%E5%AE%9A%E6%A8%A1%E7%89%88">管脚绑定模版</a></p><p><a href="about:blank#%E9%80%9A%E7%94%A8%E6%A8%A1%E5%9D%97%E6%A8%A1%E7%89%88">通用模块模版</a></p><p><a href="about:blank#%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9">注意事项</a></p><p><a href="about:blank#1.%E8%B7%91%E9%A9%AC%E7%81%AF%E6%8E%A7%E5%88%B6%E8%AE%BE%E8%AE%A1">1.跑马灯控制设计</a></p><p><a href="about:blank#2.8%20%E4%BD%8D%E5%B9%B6%E8%A1%8C%E5%85%A8%E5%8A%A0%E5%99%A8%E8%AE%BE%E8%AE%A1%2B%E6%95%B0%E7%A0%81%E7%AE%A1%E6%98%BE%E7%A4%BA%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1">2.8<br>位并行全加器设计+数码管显示程序设计</a></p><p><a href="about:blank#3.%E9%98%B5%E5%88%97%E4%B9%98%E6%B3%95%E5%99%A8%E8%AE%BE%E8%AE%A1">3.阵列乘法器设计</a></p><p><a href="about:blank#4.%E5%85%88%E8%BF%9B%E5%85%88%E5%87%BA%20FIFO%20%E7%9A%84%E8%AE%BE%E8%AE%A1">4.先进先出 FIFO<br>的设计</a></p><p><a href="about:blank#5.PC%20%E7%A8%8B%E5%BA%8F%E8%AE%A1%E6%95%B0%E5%99%A8%E8%AE%BE%E8%AE%A1">5.PC<br>程序计数器设计</a></p><p><a href="about:blank#6.%E7%A8%8B%E5%BA%8F%E5%AD%98%E5%82%A8%E5%99%A8%20ROM%20%E8%AE%BE%E8%AE%A1">6.程序存储器 ROM<br>设计</a></p><p><a href="about:blank#7.%E5%8A%A0%E5%87%8F%E4%BA%A4%E6%9B%BF%E9%99%A4%E6%B3%95%E5%99%A8">7.加减交替除法器</a></p><p><a href="about:blank#8.%E6%8C%87%E4%BB%A4%E5%AD%98%E5%82%A8%E5%99%A8%20IR%20%E8%AE%BE%E8%AE%A1">8.指令存储器 IR<br>设计</a></p><p><a href="about:blank#9.%E5%AF%84%E5%AD%98%E5%99%A8%20RN%20%E8%AE%BE%E8%AE%A1">9.寄存器 RN<br>设计</a></p><p><a href="about:blank#10.ALU%E7%AE%97%E6%9C%AF%E9%80%BB%E8%BE%91%E5%8D%95%E5%85%83%E8%AE%BE%E8%AE%A1">10.ALU算术逻辑单元设计</a></p><p><a href="about:blank#11.%E6%95%B0%E6%8D%AE%E5%AD%98%E5%82%A8%E5%99%A8%20RAM%20%E8%AE%BE%E8%AE%A1">11.数据存储器 RAM<br>设计</a></p><p><a href="about:blank#12.%E5%A0%86%E6%A0%88%E6%8C%87%E9%92%88%20SP%20%E8%AE%BE%E8%AE%A1">12.堆栈指针 SP<br>设计</a></p><p><a href="about:blank#13.%E9%87%87%E7%94%A8%E7%A1%AC%E4%BB%B6%E6%8F%8F%E8%BF%B0%E8%AF%AD%E8%A8%80%E8%AF%AD%E8%A8%80%E8%AE%BE%E8%AE%A1%20IO%20%E6%A8%A1%E5%9D%97">13.采用硬件描述语言语言设计 IO<br>模块</a></p><p><a href="about:blank#14.%E5%BE%AE%E6%8E%A7%E5%88%B6%E5%99%A8%E8%AE%BE%E8%AE%A1">14.微控制器设计</a></p><p><a href="about:blank#15.8%20%E4%BD%8D%20SOC%20%E7%BB%BC%E5%90%88%E8%AE%BE%E8%AE%A1">15.8 位 SOC<br>综合设计</a></p><p><a href="about:blank#1.%E5%AE%9E%E9%AA%8C%E7%BB%93%E6%9E%9C%E5%88%86%E6%9E%90">1.实验结果分析</a></p><p><a href="about:blank#%3C1%3E%E6%A8%A1%E5%9D%97%E5%B7%A5%E4%BD%9C%E9%A1%BA%E5%BA%8F%E5%88%86%E6%9E%90"><1>模块工作顺序分析</a></p><p><a href="about:blank#%3C2%3E%E2%80%8B%E2%80%8B%E2%80%8B%E6%8C%87%E4%BB%A4%E6%89%A7%E8%A1%8C%E8%BF%87%E7%A8%8B%E5%88%86%E6%9E%90"><2>指令执行过程分析</a></p><p><a href="about:blank#2.%E5%85%B6%E4%BB%96">2.其他</a></p><p><a href="about:blank#%3C1%3ESOC%E6%A8%A1%E5%9D%97%E9%9B%86%E6%88%90%E8%AE%BE%E8%AE%A1%E7%BB%8F%E9%AA%8C"><1>SOC模块集成设计经验</a></p><p><a href="about:blank#%3C2%3E%E2%80%8B%E2%80%8B%E2%80%8B%E2%80%8B%E2%80%8B%E2%80%8B%E2%80%8BSOC%E9%9B%86%E6%88%90%E5%85%B3%E9%94%AE"><2>SOC集成关键</a></p><hr><h2 id="二-线下实验"><a href="#二-线下实验" class="headerlink" title="二.线下实验"></a>二.线下实验</h2><h3 id="管脚绑定模版"><a href="#管脚绑定模版" class="headerlink" title="管脚绑定模版"></a>管脚绑定模版</h3><p><br> #———————————————————————————-<br> #– Engineer: switch_swq<br> #– Create Date: 2024/04/18 13:02:24<br> #———————————————————————————-<br> #CLK_100M<br> set_property PACKAGE_PIN E10 [get_ports clk]<br> set_property IOSTANDARD LVCMOS18 [get_ports clk]</p><pre><code>#SW0~15set_property IOSTANDARD LVCMOS18 [get_ports {a_in[0]}]set_property IOSTANDARD LVCMOS18 [get_ports {a_in[1]}]set_property IOSTANDARD LVCMOS18 [get_ports {a_in[2]}]set_property IOSTANDARD LVCMOS18 [get_ports {a_in[3]}]set_property IOSTANDARD LVCMOS18 [get_ports {a_in[4]}]set_property IOSTANDARD LVCMOS18 [get_ports {a_in[5]}]set_property IOSTANDARD LVCMOS18 [get_ports {a_in[6]}]set_property IOSTANDARD LVCMOS18 [get_ports {a_in[7]}]set_property PACKAGE_PIN C9 [get_ports {a_in[0]}]set_property PACKAGE_PIN B9 [get_ports {a_in[1]}]set_property PACKAGE_PIN G11 [get_ports {a_in[2]}]set_property PACKAGE_PIN F10 [get_ports {a_in[3]}]set_property PACKAGE_PIN D10 [get_ports {a_in[4]}]set_property PACKAGE_PIN E11 [get_ports {a_in[5]}]set_property PACKAGE_PIN D11 [get_ports {a_in[6]}]set_property PACKAGE_PIN A14 [get_ports {a_in[7]}]set_property IOSTANDARD LVCMOS18 [get_ports {b_in[0]}]set_property IOSTANDARD LVCMOS18 [get_ports {b_in[1]}]set_property IOSTANDARD LVCMOS18 [get_ports {b_in[2]}]set_property IOSTANDARD LVCMOS18 [get_ports {b_in[3]}]set_property IOSTANDARD LVCMOS18 [get_ports {b_in[4]}]set_property IOSTANDARD LVCMOS18 [get_ports {b_in[5]}]set_property IOSTANDARD LVCMOS18 [get_ports {b_in[6]}]set_property IOSTANDARD LVCMOS18 [get_ports {b_in[7]}]set_property PACKAGE_PIN B10 [get_ports {b_in[0]}]set_property PACKAGE_PIN A10 [get_ports {b_in[1]}]set_property PACKAGE_PIN B15 [get_ports {b_in[2]}]set_property PACKAGE_PIN A15 [get_ports {b_in[3]}]set_property PACKAGE_PIN A13 [get_ports {b_in[4]}]set_property PACKAGE_PIN A12 [get_ports {b_in[5]}]set_property PACKAGE_PIN D8 [get_ports {b_in[6]}]set_property PACKAGE_PIN D9 [get_ports {b_in[7]}]#SW16~23set_property IOSTANDARD LVCMOS18 [get_ports {c_in[0]}]set_property IOSTANDARD LVCMOS18 [get_ports {c_in[1]}]set_property IOSTANDARD LVCMOS18 [get_ports {c_in[2]}]set_property IOSTANDARD LVCMOS18 [get_ports {c_in[3]}]set_property IOSTANDARD LVCMOS18 [get_ports {c_in[4]}]set_property IOSTANDARD LVCMOS18 [get_ports {c_in[5]}]set_property IOSTANDARD LVCMOS18 [get_ports {c_in[6]}]set_property IOSTANDARD LVCMOS18 [get_ports {c_in[7]}]set_property PACKAGE_PIN F8 [get_ports {c_in[0]}]set_property PACKAGE_PIN F9 [get_ports {c_in[1]}]set_property PACKAGE_PIN H11 [get_ports {c_in[2]}]set_property PACKAGE_PIN H12 [get_ports {c_in[3]}]set_property PACKAGE_PIN G14 [get_ports {c_in[4]}]set_property PACKAGE_PIN J10 [get_ports {c_in[5]}]set_property PACKAGE_PIN H14 [get_ports {c_in[6]}]set_property PACKAGE_PIN J11 [get_ports {c_in[7]}]#sw31~24set_property PACKAGE_PIN J8 [get_ports rst]set_property IOSTANDARD LVCMOS18 [get_ports rst]set_property PACKAGE_PIN J14 [get_ports key_in]set_property IOSTANDARD LVCMOS18 [get_ports key_in]set_property PACKAGE_PIN H9 [get_ports wr]set_property IOSTANDARD LVCMOS18 [get_ports wr]set_property PACKAGE_PIN H8 [get_ports rd]set_property IOSTANDARD LVCMOS18 [get_ports rd]set_property PACKAGE_PIN G10 [get_ports a]set_property IOSTANDARD LVCMOS18 [get_ports a]set_property PACKAGE_PIN G9 [get_ports b]set_property IOSTANDARD LVCMOS18 [get_ports b]set_property PACKAGE_PIN J13 [get_ports c]set_property IOSTANDARD LVCMOS18 [get_ports c]set_property PACKAGE_PIN H13 [get_ports d]set_property IOSTANDARD LVCMOS18 [get_ports d]#SEG_DIG1~16set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[15]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[14]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[13]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[12]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[11]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[10]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[9]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[8]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[7]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[6]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[5]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[4]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[3]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[2]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[1]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[0]}]set_property PACKAGE_PIN A23 [get_ports {seg_dig[15]}]set_property PACKAGE_PIN A24 [get_ports {seg_dig[14]}]set_property PACKAGE_PIN D26 [get_ports {seg_dig[13]}]set_property PACKAGE_PIN C26 [get_ports {seg_dig[12]}]set_property PACKAGE_PIN A20 [get_ports {seg_dig[11]}]set_property PACKAGE_PIN J25 [get_ports {seg_dig[10]}]set_property PACKAGE_PIN J24 [get_ports {seg_dig[9]}]set_property PACKAGE_PIN H22 [get_ports {seg_dig[8]}]set_property PACKAGE_PIN K21 [get_ports {seg_dig[7]}]set_property PACKAGE_PIN L23 [get_ports {seg_dig[6]}]set_property PACKAGE_PIN B25 [get_ports {seg_dig[5]}]set_property PACKAGE_PIN B26 [get_ports {seg_dig[4]}]set_property PACKAGE_PIN C24 [get_ports {seg_dig[3]}]set_property PACKAGE_PIN D21 [get_ports {seg_dig[2]}]set_property PACKAGE_PIN C22 [get_ports {seg_dig[1]}]set_property PACKAGE_PIN B20 [get_ports {seg_dig[0]}]#seg_dataset_property PACKAGE_PIN E26 [get_ports {seg_data[7]}]set_property PACKAGE_PIN J26 [get_ports {seg_data[6]}]set_property PACKAGE_PIN H26 [get_ports {seg_data[5]}]set_property PACKAGE_PIN H21 [get_ports {seg_data[4]}]set_property PACKAGE_PIN G21 [get_ports {seg_data[3]}]set_property PACKAGE_PIN H23 [get_ports {seg_data[2]}]set_property PACKAGE_PIN H24 [get_ports {seg_data[1]}]set_property PACKAGE_PIN J21 [get_ports {seg_data[0]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[7]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[6]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[5]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[4]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[3]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[2]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[1]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[0]}]#LEDset_property IOSTANDARD LVCMOS33 [get_ports {data_out[0]}]set_property IOSTANDARD LVCMOS33 [get_ports {data_out[1]}]set_property IOSTANDARD LVCMOS33 [get_ports {data_out[2]}]set_property IOSTANDARD LVCMOS33 [get_ports {data_out[3]}]set_property IOSTANDARD LVCMOS33 [get_ports {data_out[4]}]set_property IOSTANDARD LVCMOS33 [get_ports {data_out[5]}]set_property IOSTANDARD LVCMOS33 [get_ports {data_out[6]}]set_property IOSTANDARD LVCMOS33 [get_ports {data_out[7]}]set_property PACKAGE_PIN G16[get_ports {data_out[0]}]set_property PACKAGE_PIN H16 [get_ports {data_out[1]}]set_property PACKAGE_PIN D16 [get_ports {data_out[2]}]set_property PACKAGE_PIN D15 [get_ports {data_out[3]}]set_property PACKAGE_PIN C18 [get_ports {data_out[4]}]set_property PACKAGE_PIN C17 [get_ports {data_out[5]}]set_property PACKAGE_PIN B19 [get_ports {data_out[6]}]set_property PACKAGE_PIN C19 [get_ports {data_out[7]}]#led15set_property PACKAGE_PIN L20 [get_ports empty]set_property IOSTANDARD LVCMOS33 [get_ports empty]#led11set_property PACKAGE_PIN J20 [get_ports full]set_property IOSTANDARD LVCMOS33 [get_ports full]</code></pre><h3 id="通用模块模版"><a href="#通用模块模版" class="headerlink" title="通用模块模版"></a>通用模块模版</h3><p>时钟分频:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 13:02:24<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity clk_div is generic( DIV_NUM:integer:=10000 ); Port ( rst:in std_logic; clk_in:in std_logic; clk_out:out std_logic );end clk_div;architecture Behavioral of clk_div isbeginprocess(rst,clk_in)variable count:integer:=0;begin if(rst='1')then count:=0; elsif(clk_in='1'and clk_in'event)then count:=count+1; if(count<=DIV_NUM/2)then clk_out<='1'; elsif(count>DIV_NUM/2 and count<DIV_NUM)then clk_out<='0'; elsif(count>=DIV_NUM)then count:=0; end if; end if;end process;end Behavioral;</code></pre><p>按键消抖:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 13:02:24<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity key_stroke is generic(CLK_FRE:integer:=100000000); Port ( clk:in std_logic; reset:in std_logic; key_in:in std_logic; output:out std_logic );end key_stroke;architecture Behavioral of key_stroke istype states is(s0,s1,s2,s3);signal state:states;beginprocess(reset,clk,key_in)variable count_num:integer:=3*CLK_FRE/1000;--delay 3msvariable count:integer:=0; begin if reset='0'then state<=s0; count:=0; output<='0'; elsif(clk='1'and clk'event)then case state is when s0=>if(key_in='1')then count:=0;output<='0';state<=s1;end if; when s1=> count:=count+1; if (count>=count_num) then state<=s2; end if; when s2=> if(key_in='1')then output<='1';state<=s3; --if(key_in='1')then output<='1';state<=s0;--one clk cycle elsif(key_in='0')then state<=s0; end if; when s3=>if(key_in='0')then state<=s0;end if; end case; end if; end process;end Behavioral;</code></pre><p> 数码管显示:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 13:02:24<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;</p><pre><code>entity seg_dis is port( rst,clk:in std_logic; data_in_A,data_in_B,data_in_C,data_in_D:in std_logic_vector(15 downto 0); seg_dig:out std_logic_vector(15 downto 0); seg_data:out std_logic_vector(7 downto 0)--管脚连接顺序:dp,g,f,e,d,c,b,a );end seg_dis;architecture Behavioral of seg_dis issignal data_in_line: std_logic_vector(3 downto 0);type states is(s0,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11,s12,s13,s14,s15);signal state,next_state:states;begin process(rst,clk)begin if(rst='1')then state<=s0; elsif(clk='1'and clk'event)then state<=next_state; end if;end process;</code></pre><p><br> process(state)<br> begin<br> case state is<br> when s0 => seg_dig<=not”0000000000000001”; data_in_line<=data_in_A(3 downto 0); next_state<=s1;<br> when s1 => seg_dig<=not”0000000000000010”; data_in_line<=data_in_A(7 downto 4); next_state<=s2;<br> when s2 => seg_dig<=not”0000000000000100”; data_in_line<=data_in_A(11 downto 8); next_state<=s3;<br> when s3 => seg_dig<=not”0000000000001000”; data_in_line<=data_in_A(15 downto 12); next_state<=s4;<br> when s4 => seg_dig<=not”0000000000010000”; data_in_line<=data_in_B(3 downto 0); next_state<=s5;<br> when s5 => seg_dig<=not”0000000000100000”; data_in_line<=data_in_B(7 downto 4); next_state<=s6;<br> when s6 => seg_dig<=not”0000000001000000”; data_in_line<=data_in_B(11 downto 8); next_state<=s7;<br> when s7 => seg_dig<=not”0000000010000000”; data_in_line<=data_in_B(15 downto 12); next_state<=s8;<br> when s8 => seg_dig<=not”0000000100000000”; data_in_line<=data_in_C(3 downto 0); next_state<=s9;<br> when s9 => seg_dig<=not”0000001000000000”; data_in_line<=data_in_C(7 downto 4); next_state<=s10;<br> when s10=> seg_dig<=not”0000010000000000”; data_in_line<=data_in_C(11 downto 8); next_state<=s11;<br> when s11=> seg_dig<=not”0000100000000000”; data_in_line<=data_in_C(15 downto 12); next_state<=s12;<br> when s12=> seg_dig<=not”0001000000000000”; data_in_line<=data_in_D(3 downto 0); next_state<=s13;<br> when s13=> seg_dig<=not”0010000000000000”; data_in_line<=data_in_D(7 downto 4); next_state<=s14;<br> when s14=> seg_dig<=not”0100000000000000”; data_in_line<=data_in_D(11 downto 8); next_state<=s15;<br> when s15=> seg_dig<=not”1000000000000000”; data_in_line<=data_in_D(15 downto 12); next_state<=s0;<br> when others=>next_state<=s0;<br> end case;<br> end process;</p><pre><code>process(data_in_line)begin case data_in_line is when "0000"=>seg_data<=not"00111111"; when "0001"=>seg_data<=not"00000110"; when "0010"=>seg_data<=not"01011011"; when "0011"=>seg_data<=not"01001111"; when "0100"=>seg_data<=not"01100110"; when "0101"=>seg_data<=not"01101101"; when "0110"=>seg_data<=not"01111101"; when "0111"=>seg_data<=not"00000111"; when "1000"=>seg_data<=not"01111111"; when "1001"=>seg_data<=not"01101111"; when "1010"=>seg_data<=not"01110111"; when "1011"=>seg_data<=not"01111100"; when "1100"=>seg_data<=not"00111001"; when "1101"=>seg_data<=not"01011110"; when "1110"=>seg_data<=not"01111001"; when "1111"=>seg_data<=not"01110001"; when others=>seg_data<=not"11111111"; end case;end process;end Behavioral;</code></pre><h3 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a><strong>注意事项</strong></h3><p>1.器件型号:xc7k160tfbg676-2</p><p>2.输入一般cmos18 输出cmos33</p><p>3.输入数码管的时钟需分频</p><p>4.按键加消抖</p><p>5.程序的运行结合.xdc文件进行理解</p><h3 id="1-跑马灯控制设计"><a href="#1-跑马灯控制设计" class="headerlink" title="1.跑马灯控制设计"></a>1.跑马灯控制设计</h3><pre><code> 功能叙述:初始情况下 Y0=‘1’,其它为‘0’。然后,在 en 为高电平的情况下,在时钟信 号 clk 的下降沿进行移位。当 dir=‘1’时,每来一个时钟信号,循环左移一位,当 dir=‘0’时, 每来一个时钟,循环右移一位。 另外,移位控制时钟可以选择为按键,即每按键一次相当于一个时钟信号,系统可以在 按键和系统分频时钟之间进行选择。</code></pre><p>资源使用:</p><p>1)用 LED0~LED7 作为跑马灯输出显示,LED7 为高位,LED0 为低位;</p><p>2)SW0 为循环方向控制;</p><p>3)SW1 为工作允许 EN 控制端;</p><p>4)计数时钟频率为 1Hz,通过对 50Mhz 系统时钟分频得到;</p><p>5)扩展:可以由按键来控制循环(按键为 BTN_SOUTH),即每按一次 BTN_SOUTH, 则完成一次移位。通过 SW2 选择移位控制时钟沿。</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/fbc0bb7faf453566ef923063e4d002fb.png"></p><p>源文件:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 13:02:24<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity run_led is Port( en,dir,sel,clk,con:in std_logic; y:out std_logic_vector(7 downto 0) );end run_led;architecture Behavioral of run_led issignal input:std_logic;signal clk_div:std_logic;beginprocess(clk)variable clk_cnt:integer:=0;variable clk_cnt_2:integer:=0;begin if(clk='1'and clk'event)then clk_cnt_2:=clk_cnt_2+1; if(clk_cnt_2>=10000)then clk_cnt:=clk_cnt+1; clk_cnt_2:=0; end if; if(clk_cnt<5000)then clk_div<='1'; elsif(clk_cnt>=5000)then clk_div<='0'; end if; if(clk_cnt>=10000)then clk_cnt:=0; end if; end if;end process;process(clk,en,clk_div,con,sel) begin if(en='1')then if(sel='0')then input<=clk_div; elsif(sel='1')then input<=con; end if; elsif(en='0')then input<='0'; end if;end process;process(input,dir)variable count:integer:=0;beginif(input='1'and input'event)then if(dir='1')then count:=count+1; if(count>7)then count:=0;end if; elsif(dir='0')then count:=count-1; if(count<0)then count:=7;end if; end if; if(count=0)then y<="00000001"; elsif(count=1)then y<="00000010"; elsif(count=2)then y<="00000100"; elsif(count=3)then y<="00001000"; elsif(count=4)then y<="00010000"; elsif(count=5)then y<="00100000"; elsif(count=6)then y<="01000000"; elsif(count=7)then y<="10000000"; else y<="11111111"; end if; end if; end process;end Behavioral;</code></pre><p>testbench:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 13:02:24<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><p><br> entity run_led_tb is<br> end run_led_tb;</p><pre><code>architecture Behavioral of run_led_tb iscomponent run_led Port( en,dir,sel,clk,con:in std_logic; y:out std_logic_vector(7 downto 0) );end component;SIGNAL en,dir,sel,clk,con: std_logic;SIGNAL y: std_logic_vector(7 downto 0);beginrun_led_inst:run_led port map(en=>en,dir=>dir,sel=>sel,clk=>clk,con=>con,y=>y); clock:processbegin clk<='1'; wait for 5ns; clk<='0'; wait for 5ns;end process;key:processbegin con<='1'; wait for 25ns; con<='0'; wait for 25ns;end process;test:processbegin en<='0'; sel<='1'; dir<='1'; wait for 25ns; en<='1'; wait;end process;</code></pre><p><br> end Behavioral;</p><p>xdc:</p><p><br> #———————————————————————————-<br> #– Engineer: switch_swq<br> #– Create Date: 2024/04/18 13:02:24<br> #———————————————————————————-<br> set_property PACKAGE_PIN C9 [get_ports dir]<br> set_property PACKAGE_PIN AF12 [get_ports con]<br> set_property PACKAGE_PIN B9 [get_ports en]<br> set_property PACKAGE_PIN E10 [get_ports clk]<br> set_property PACKAGE_PIN G11 [get_ports sel]<br> set_property PACKAGE_PIN G16 [get_ports {y[0]}]<br> set_property PACKAGE_PIN H16 [get_ports {y[1]}]<br> set_property PACKAGE_PIN D16 [get_ports {y[2]}]<br> set_property PACKAGE_PIN D15 [get_ports {y[3]}]<br> set_property PACKAGE_PIN C18 [get_ports {y[4]}]<br> set_property PACKAGE_PIN C17 [get_ports {y[5]}]<br> set_property PACKAGE_PIN B19 [get_ports {y[6]}]<br> set_property PACKAGE_PIN C19 [get_ports {y[7]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {y[4]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {y[5]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {y[0]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {y[6]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {y[1]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {y[7]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {y[2]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {y[3]}]</p><pre><code>set_property DRIVE 12 [get_ports {y[4]}]set_property DRIVE 12 [get_ports {y[5]}]set_property DRIVE 12 [get_ports {y[0]}]set_property DRIVE 12 [get_ports {y[6]}]set_property DRIVE 12 [get_ports {y[1]}]set_property DRIVE 12 [get_ports {y[7]}]set_property DRIVE 12 [get_ports {y[2]}]set_property DRIVE 12 [get_ports {y[3]}]set_property IOSTANDARD LVCMOS18 [get_ports dir]set_property IOSTANDARD LVCMOS18 [get_ports con]set_property IOSTANDARD LVCMOS18 [get_ports en]set_property IOSTANDARD LVCMOS18 [get_ports clk]set_property IOSTANDARD LVCMOS18 [get_ports sel]</code></pre><p><br> </p><h3 id="2-8-位并行全加器设计-数码管显示程序设计"><a href="#2-8-位并行全加器设计-数码管显示程序设计" class="headerlink" title="2.8 位并行全加器设计+数码管显示程序设计"></a>2.8 位并行全加器设计+数码管显示程序设计</h3><p><strong>注:数码管部分未使用优化代码</strong></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/ce6fd932b35130aa5e27c5aed20ea4d1.png"></p><pre><code> 其中 a_in,b_in:数据输入,使用板上开关(SW0~SW15); sum_out:运算结果输出,使用 LED 显示运算结果。</code></pre><p>(1)用硬件描述语言实现 16 个七段数码管扫描显示模块</p><pre><code> 七段数码管扫描显示模块电路如图所示,主要包括顶层的数码管扫描显示模块,以及输入数据向七段数码管进行译码的模块。</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/c7d8f4a915fe5bd8c1ead81f14b23a98.png"></p><pre><code> 该模块实现数码管扫描显示功能,扩展板上的 16 个数码管四个一组,分为 A,B,C,D 四组。模块管脚说明如下:clk 为系统的时钟输入,rst 信号为复位信号,data_in_A(15:0)为 A 组四个数码管的输入显示值,其中,data_in_A(3:0)对应于第一个数码管的输入显示值; data_in_A(7:4)对应第二个数码管的输入显示值;data_in_A(11:8)对应第三个数码管的输入显 示值;data_in_A(15:12)对应第四个数码管的输入显示值,其它各组与 A 组分配一致; data_in_B(15:0)为 B 组四个数码管的输入显示值;data_in_C(15:0)为 C 组四个数码管的输入显 示值;data_in_D(15:0)为 D 组四个数码管的输入显示值;seg_sel(3:0)为数码管选择编码输出 信号,seg_data(7:0)为数码管显示数据输出。 </code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/80cc88d89b55bfa5281ac1e8bd0b69bc.png"></p><pre><code> 该模块实现将输入的 4 为二进制数转换为数码管显示的数据;其中,data_in(3:0)为输入 值,seg_data(7:0)为数码管编码的输出值。</code></pre><p>源码:</p><p>顶层:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 13:02:24<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;<br> entity adder is<br> Port (<br> clk,rst:in std_logic;<br> a,b:in std_logic_vector(7 downto 0);<br> c:in std_logic;</p><pre><code> c_out:out std_logic; sel_out:out std_logic_vector(15 downto 0); seg_data:out std_logic_vector(7 downto 0) );end adder;architecture Behavioral of adder iscomponent clk_div generic( DIV_NUM:integer:=10000 ); Port ( clk_in:in std_logic; clk_out:out std_logic );end component;component seg_dis port( rst,clk:in std_logic; data_in_A,data_in_B,data_in_C,data_in_D:in std_logic_vector(15 downto 0); seg_sel:out std_logic_vector(3 downto 0); seg_data:out std_logic_vector(7 downto 0) );end component;component decoder4_16 Port ( sel_in:in std_logic_vector(3 downto 0); sel_out:out std_logic_vector(15 downto 0) );end component;signal clk_out_line:std_logic;signal sum_line:std_logic_vector(16 downto 0);signal data_line:std_logic_vector(15 downto 0);signal c_line:std_logic;signal sel_out_line:std_logic_vector(3 downto 0);beginclk_div_inst:clk_div generic map(10000)port map(clk,clk_out_line);seg_dis_inst:seg_dis port map(rst,clk_out_line,data_line,"0000000000000000","0000000000000000","0000000000000000",sel_out_line,seg_data);decoder4_16_inst:decoder4_16 port map(sel_out_line,sel_out);process(a,b,c)begin sum_line<=("00000000"&a)+("00000000"&b)+("0000000000000000"&c); data_line<=sum_line(15 downto 0); c_out<=sum_line(16);end process;</code></pre><p><br> end Behavioral;</p><p>模块:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 13:02:24<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity decoder4_16 is Port ( sel_in:in std_logic_vector(3 downto 0); sel_out:out std_logic_vector(15 downto 0) );end decoder4_16;architecture Behavioral of decoder4_16 isbeginprocess(sel_in)begin case sel_in is when "0000"=>sel_out<=not"0000000000000001"; when "0001"=>sel_out<=not"0000000000000010"; when "0010"=>sel_out<=not"0000000000000100"; when "0011"=>sel_out<=not"0000000000001000"; when "0100"=>sel_out<=not"0000000000010000"; when "0101"=>sel_out<=not"0000000000100000"; when "0110"=>sel_out<=not"0000000001000000"; when "0111"=>sel_out<=not"0000000010000000"; when "1000"=>sel_out<=not"0000000100000000"; when "1001"=>sel_out<=not"0000001000000000"; when "1010"=>sel_out<=not"0000010000000000"; when "1011"=>sel_out<=not"0000100000000000"; when "1100"=>sel_out<=not"0001000000000000"; when "1101"=>sel_out<=not"0010000000000000"; when "1110"=>sel_out<=not"0100000000000000"; when "1111"=>sel_out<=not"1000000000000000"; when others=>sel_out<=not"1111111111111111"; end case;end process;end Behavioral;</code></pre><p><br><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 13:02:24<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;</p><pre><code>entity seg_dis is port( rst,clk:in std_logic; data_in_A,data_in_B,data_in_C,data_in_D:in std_logic_vector(15 downto 0); seg_sel:out std_logic_vector(3 downto 0); seg_data:out std_logic_vector(7 downto 0) );end seg_dis;architecture Behavioral of seg_dis iscomponent data2seg port( data_in:in std_logic_vector(3 downto 0); seg_data:out std_logic_vector(7 downto 0) );end component;signal data_in_line: std_logic_vector(3 downto 0);type states is(s0,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11,s12,s13,s14,s15);signal state,next_state:states;begin data2seg_inst:data2seg port map(data_in_line,seg_data);process(rst,clk)begin if(rst='1')then state<=s0; elsif(clk='1'and clk'event)then state<=next_state; end if;end process;</code></pre><p><br> process(state)<br> begin<br> case state is<br> when s0=><br> seg_sel<=”0000”;<br> data_in_line<=data_in_A(3 downto 0);<br> next_state<=s1;<br> when s1=><br> seg_sel<=”0001”;<br> data_in_line<=data_in_A(7 downto 4);<br> next_state<=s2;<br> when s2=><br> seg_sel<=”0010”;<br> data_in_line<=data_in_A(11 downto 8);<br> next_state<=s3;<br> when s3=><br> seg_sel<=”0011”;<br> data_in_line<=data_in_A(15 downto 12);<br> next_state<=s4;</p><pre><code> when s4=>seg_sel<="0100";data_in_line<=data_in_B(3 downto 0);next_state<=s5; when s5=>seg_sel<="0101";data_in_line<=data_in_B(7 downto 4);next_state<=s6; when s6=>seg_sel<="0110";data_in_line<=data_in_B(11 downto 8);next_state<=s7; when s7=>seg_sel<="0111";data_in_line<=data_in_B(15 downto 12);next_state<=s8; when s8=>seg_sel<="1000";data_in_line<=data_in_C(3 downto 0);next_state<=s9; when s9=>seg_sel<="1001";data_in_line<=data_in_C(7 downto 4);next_state<=s10; when s10=>seg_sel<="1010";data_in_line<=data_in_C(11 downto 8);next_state<=s11; when s11=>seg_sel<="1011";data_in_line<=data_in_C(15 downto 12);next_state<=s12; when s12=>seg_sel<="1100";data_in_line<=data_in_D(3 downto 0);next_state<=s13; when s13=>seg_sel<="1101";data_in_line<=data_in_D(7 downto 4);next_state<=s14; when s14=>seg_sel<="1110";data_in_line<=data_in_D(11 downto 8);next_state<=s15; when s15=>seg_sel<="1111";data_in_line<=data_in_D(15 downto 12);next_state<=s0; when others=>state<=next_state; end case;end process;end Behavioral;</code></pre><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 13:02:24<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;</p><pre><code>entity data2seg is port( data_in:in std_logic_vector(3 downto 0); seg_data:out std_logic_vector(7 downto 0) );end data2seg;architecture Behavioral of data2seg isbegin process(data_in)begin case data_in is when "0000"=>seg_data<=not"00111111"; when "0001"=>seg_data<=not"00000110"; when "0010"=>seg_data<=not"01011011"; when "0011"=>seg_data<=not"01001111"; when "0100"=>seg_data<=not"01100110"; when "0101"=>seg_data<=not"00110111"; when "0110"=>seg_data<=not"01111101"; when "0111"=>seg_data<=not"00000111"; when "1000"=>seg_data<=not"01111111"; when "1001"=>seg_data<=not"01101111"; when "1010"=>seg_data<=not"01110111"; when "1011"=>seg_data<=not"01111100"; when "1100"=>seg_data<=not"00111000"; when "1101"=>seg_data<=not"01011110"; when "1110"=>seg_data<=not"01111001"; when "1111"=>seg_data<=not"01110001"; when others=>seg_data<=not"11111111"; end case; end process;end Behavioral;</code></pre><p>testbench:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 13:02:24<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity adder_tb is-- Port ( );end adder_tb;architecture Behavioral of adder_tb iscomponent adder Port ( clk,rst:in std_logic; a,b:in std_logic_vector(7 downto 0); c:in std_logic; c_out:out std_logic; sel_out:out std_logic_vector(15 downto 0); seg_data:out std_logic_vector(7 downto 0) );end component;signal clk,rst :std_logic;signal a,b :std_logic_vector(7 downto 0);signal c :std_logic;signal c_out : std_logic;signal sel_out : std_logic_vector(15 downto 0);signal seg_data: std_logic_vector(7 downto 0);beginadder_inst:adder port map(clk,rst,a,b,c,c_out,sel_out,seg_data);clock:processbegin clk<='1'; wait for 5ns; clk<='0'; wait for 5ns;end process;restart:processbegin rst<='1'; wait for 25ns; rst<='0'; wait;end process;test:processbegin a<="00100010"; b<="01000100"; c<='1'; wait for 100ns; a<="11111111"; b<="11111111"; c<='1'; wait;end process;end Behavioral;</code></pre><p>xdc:</p><p><br> set_property PACKAGE_PIN E26 [get_ports {seg_data[7]}]<br> set_property PACKAGE_PIN J26 [get_ports {seg_data[6]}]<br> set_property PACKAGE_PIN H26 [get_ports {seg_data[5]}]<br> set_property PACKAGE_PIN H21 [get_ports {seg_data[4]}]<br> set_property PACKAGE_PIN G21 [get_ports {seg_data[3]}]<br> set_property PACKAGE_PIN H23 [get_ports {seg_data[2]}]<br> set_property PACKAGE_PIN H24 [get_ports {seg_data[1]}]<br> set_property PACKAGE_PIN J21 [get_ports {seg_data[0]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[7]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[6]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[5]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[4]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[3]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[2]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[1]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[0]}]</p><pre><code>set_property PACKAGE_PIN E10 [get_ports clk]set_property PACKAGE_PIN C9 [get_ports {a[0]}]set_property PACKAGE_PIN B9 [get_ports {a[1]}]set_property PACKAGE_PIN G11 [get_ports {a[2]}]set_property PACKAGE_PIN F10 [get_ports {a[3]}]set_property PACKAGE_PIN D10 [get_ports {a[4]}]set_property PACKAGE_PIN E11 [get_ports {a[5]}]set_property PACKAGE_PIN D11 [get_ports {a[6]}]set_property PACKAGE_PIN A14 [get_ports {a[7]}]set_property PACKAGE_PIN B10 [get_ports {b[0]}]set_property PACKAGE_PIN A10 [get_ports {b[1]}]set_property PACKAGE_PIN B15 [get_ports {b[2]}]set_property PACKAGE_PIN A15 [get_ports {b[3]}]set_property PACKAGE_PIN A13 [get_ports {b[4]}]set_property PACKAGE_PIN A12 [get_ports {b[5]}]set_property PACKAGE_PIN D8 [get_ports {b[6]}]set_property PACKAGE_PIN D9 [get_ports {b[7]}]set_property IOSTANDARD LVCMOS18 [get_ports {b[0]}]set_property IOSTANDARD LVCMOS18 [get_ports {b[1]}]set_property IOSTANDARD LVCMOS18 [get_ports {b[2]}]set_property IOSTANDARD LVCMOS18 [get_ports {b[3]}]set_property IOSTANDARD LVCMOS18 [get_ports {b[4]}]set_property IOSTANDARD LVCMOS18 [get_ports {b[5]}]set_property IOSTANDARD LVCMOS18 [get_ports {b[6]}]set_property IOSTANDARD LVCMOS18 [get_ports {b[7]}]set_property IOSTANDARD LVCMOS18 [get_ports {a[0]}]set_property IOSTANDARD LVCMOS18 [get_ports {a[1]}]set_property IOSTANDARD LVCMOS18 [get_ports {a[2]}]set_property IOSTANDARD LVCMOS18 [get_ports {a[3]}]set_property IOSTANDARD LVCMOS18 [get_ports {a[4]}]set_property IOSTANDARD LVCMOS18 [get_ports {a[5]}]set_property IOSTANDARD LVCMOS18 [get_ports {a[6]}]set_property IOSTANDARD LVCMOS18 [get_ports {a[7]}]</code></pre><p><br> set_property IOSTANDARD LVCMOS18 [get_ports clk]<br> set_property IOSTANDARD LVCMOS18 [get_ports rst]<br> set_property IOSTANDARD LVCMOS33 [get_ports c_out]<br> set_property IOSTANDARD LVCMOS18 [get_ports c]</p><pre><code>set_property PACKAGE_PIN J14 [get_ports c]set_property PACKAGE_PIN G16 [get_ports c_out]set_property PACKAGE_PIN J8 [get_ports rst]#set_property IOSTANDARD LVCMOS18 [get_ports {sel_in[0]}]#set_property IOSTANDARD LVCMOS18 [get_ports {sel_in[1]}]#set_property IOSTANDARD LVCMOS18 [get_ports {sel_in[2]}]#set_property IOSTANDARD LVCMOS18 [get_ports {sel_in[3]}]#set_property PACKAGE_PIN F8 [get_ports {sel_in[0]}]#set_property PACKAGE_PIN F9 [get_ports {sel_in[1]}]#set_property PACKAGE_PIN H11 [get_ports {sel_in[2]}]#set_property PACKAGE_PIN H12 [get_ports {sel_in[3]}]set_property IOSTANDARD LVCMOS33 [get_ports {sel_out[7]}]set_property IOSTANDARD LVCMOS33 [get_ports {sel_out[10]}]set_property IOSTANDARD LVCMOS33 [get_ports {sel_out[4]}]set_property IOSTANDARD LVCMOS33 [get_ports {sel_out[1]}]set_property IOSTANDARD LVCMOS33 [get_ports {sel_out[15]}]set_property IOSTANDARD LVCMOS33 [get_ports {sel_out[12]}]set_property IOSTANDARD LVCMOS33 [get_ports {sel_out[6]}]set_property IOSTANDARD LVCMOS33 [get_ports {sel_out[0]}]set_property IOSTANDARD LVCMOS33 [get_ports {sel_out[13]}]set_property IOSTANDARD LVCMOS33 [get_ports {sel_out[5]}]set_property IOSTANDARD LVCMOS33 [get_ports {sel_out[2]}]set_property IOSTANDARD LVCMOS33 [get_ports {sel_out[8]}]set_property IOSTANDARD LVCMOS33 [get_ports {sel_out[11]}]set_property IOSTANDARD LVCMOS33 [get_ports {sel_out[14]}]set_property IOSTANDARD LVCMOS33 [get_ports {sel_out[3]}]set_property IOSTANDARD LVCMOS33 [get_ports {sel_out[9]}]set_property PACKAGE_PIN A23 [get_ports {sel_out[15]}]set_property PACKAGE_PIN A24 [get_ports {sel_out[14]}]set_property PACKAGE_PIN D26 [get_ports {sel_out[13]}]set_property PACKAGE_PIN C26 [get_ports {sel_out[12]}]set_property PACKAGE_PIN A20 [get_ports {sel_out[11]}]set_property PACKAGE_PIN J25 [get_ports {sel_out[10]}]set_property PACKAGE_PIN J24 [get_ports {sel_out[9]}]set_property PACKAGE_PIN H22 [get_ports {sel_out[8]}]set_property PACKAGE_PIN K21 [get_ports {sel_out[7]}]set_property PACKAGE_PIN L23 [get_ports {sel_out[6]}]set_property PACKAGE_PIN B25 [get_ports {sel_out[5]}]set_property PACKAGE_PIN B26 [get_ports {sel_out[4]}]set_property PACKAGE_PIN C24 [get_ports {sel_out[3]}]set_property PACKAGE_PIN D21 [get_ports {sel_out[2]}]set_property PACKAGE_PIN C22 [get_ports {sel_out[1]}]set_property PACKAGE_PIN B20 [get_ports {sel_out[0]}]</code></pre><h3 id="3-阵列乘法器设计"><a href="#3-阵列乘法器设计" class="headerlink" title="3.阵列乘法器设计"></a>3.阵列乘法器设计</h3><p><img src="https://i-blog.csdnimg.cn/blog_migrate/d9b23c4e7c365f7e9bd09cd34b890dbe.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/b8ebdee3a1727312ec82f82a48997c04.png"></p><p>源码:</p><p>顶层:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 13:02:24<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity array_multiplier_seg is Port ( rst,clk:in std_logic; a_in,b_in:in std_logic_vector(7 downto 0); seg_dig:out std_logic_vector(15 downto 0); seg_data:out std_logic_vector(7 downto 0) );end array_multiplier_seg;architecture Behavioral of array_multiplier_seg iscomponent clk_div generic( DIV_NUM:integer:=10000 ); Port ( clk_in:in std_logic; clk_out:out std_logic );end component;component array_multiplier Port ( clk:in std_logic; a_in,b_in:in std_logic_vector(7 downto 0); sum_out:out std_logic_vector(15 downto 0) );end component;component seg_dis port( rst,clk:in std_logic; data_in_A,data_in_B,data_in_C,data_in_D:in std_logic_vector(15 downto 0); seg_sel:out std_logic_vector(3 downto 0); seg_data:out std_logic_vector(7 downto 0) );end component;component decoder4_16 Port ( sel_in:in std_logic_vector(3 downto 0); sel_out:out std_logic_vector(15 downto 0) );end component;signal clk_out_line:std_logic;signal sum_out_line:std_logic_vector(15 downto 0);signal seg_dig_line:std_logic_vector(3 downto 0);beginclk_div_inst:clk_div generic map(10000)port map(clk,clk_out_line);array_multiplier_inst:array_multiplier port map(clk_out_line,a_in,b_in,sum_out_line);seg_dis_inst:seg_dis port map(rst,clk_out_line,sum_out_line,"0000000000000000","0000000000000000","0000000000000000",seg_dig_line,seg_data);decoder4_16_inst:decoder4_16 port map(seg_dig_line,seg_dig);end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/48f312e41997369070448630c369ef88.png"></p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 13:02:24<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity array_multiplier is Port ( clk:in std_logic; a_in,b_in:in std_logic_vector(7 downto 0); sum_out:out std_logic_vector(15 downto 0) );end array_multiplier;architecture Behavioral of array_multiplier iscomponent array_multiplier_top Port ( a_in:in std_logic; b_in:in std_logic_vector(7 downto 0); s:out std_logic_vector(7 downto 0) );end component;component array_multiplier_unit Port ( x_in:in std_logic; y_in:in std_logic_vector(7 downto 0); c_in:in std_logic_vector(6 downto 0); z_in:in std_logic_vector(7 downto 0); c_out:out std_logic_vector(6 downto 0); z_out:out std_logic_vector(7 downto 0) );end component;component array_multiplier_low Port ( z_in,c_in:in std_logic_vector(6 downto 0); s_out:out std_logic_vector(7 downto 0) );end component;signal z_in0:std_logic_vector(7 downto 0);signal z_in1:std_logic_vector(7 downto 0);signal z_in2:std_logic_vector(7 downto 0);signal z_in3:std_logic_vector(7 downto 0);signal z_in4:std_logic_vector(7 downto 0);signal z_in5:std_logic_vector(7 downto 0);signal z_in6:std_logic_vector(7 downto 0);signal z_in7:std_logic_vector(7 downto 0);signal c_in1:std_logic_vector(6 downto 0);signal c_in2:std_logic_vector(6 downto 0);signal c_in3:std_logic_vector(6 downto 0);signal c_in4:std_logic_vector(6 downto 0);signal c_in5:std_logic_vector(6 downto 0);signal c_in6:std_logic_vector(6 downto 0);signal c_in7:std_logic_vector(6 downto 0);beginarray_multiplier_top_inst:array_multiplier_top port map(a_in(0),b_in,z_in0);array_multiplier_unit_inst1:array_multiplier_unit port map(a_in(1),b_in,"0000000",z_in0,c_in1,z_in1);array_multiplier_unit_inst2:array_multiplier_unit port map(a_in(2),b_in,c_in1,z_in1,c_in2,z_in2);array_multiplier_unit_inst3:array_multiplier_unit port map(a_in(3),b_in,c_in2,z_in2,c_in3,z_in3);array_multiplier_unit_inst4:array_multiplier_unit port map(a_in(4),b_in,c_in3,z_in3,c_in4,z_in4);array_multiplier_unit_inst5:array_multiplier_unit port map(a_in(5),b_in,c_in4,z_in4,c_in5,z_in5);array_multiplier_unit_inst6:array_multiplier_unit port map(a_in(6),b_in,c_in5,z_in5,c_in6,z_in6);array_multiplier_unit_inst7:array_multiplier_unit port map(a_in(7),b_in,c_in6,z_in6,c_in7,z_in7);array_multiplier_low_inst:array_multiplier_low port map(z_in7(7 downto 1),c_in7,sum_out(15 downto 8));process(clk,a_in,b_in)begin sum_out(0)<=z_in0(0); sum_out(1)<=z_in1(0); sum_out(2)<=z_in2(0); sum_out(3)<=z_in3(0); sum_out(4)<=z_in4(0); sum_out(5)<=z_in5(0); sum_out(6)<=z_in6(0); sum_out(7)<=z_in7(0);end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/b2b81a5e7b42395fba8c9fb656d835fd.png"></p><p>模块:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 13:02:24<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity array_multiplier_top is Port ( a_in:in std_logic; b_in:in std_logic_vector(7 downto 0); s:out std_logic_vector(7 downto 0) );end array_multiplier_top;architecture Behavioral of array_multiplier_top isbeginprocess(a_in,b_in)begin for i in 0 to 7 loop s(i)<=a_in and b_in(i); end loop;end process;end Behavioral;</code></pre><p><br><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 13:02:24<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity array_multiplier_unit is Port ( x_in:in std_logic; y_in:in std_logic_vector(7 downto 0); c_in:in std_logic_vector(6 downto 0); z_in:in std_logic_vector(7 downto 0); c_out:out std_logic_vector(6 downto 0); z_out:out std_logic_vector(7 downto 0) );end array_multiplier_unit;architecture Behavioral of array_multiplier_unit iscomponent adder_1bit Port ( a,b,c_in:in std_logic; s,c_out:out std_logic );end component;signal a_line:std_logic_vector(7 downto 0);beginadder_1bit_inst1:adder_1bit port map(a_line(0),c_in(0),z_in(1),z_out(0),c_out(0));adder_1bit_inst2:adder_1bit port map(a_line(1),c_in(1),z_in(2),z_out(1),c_out(1));adder_1bit_inst3:adder_1bit port map(a_line(2),c_in(2),z_in(3),z_out(2),c_out(2));adder_1bit_inst4:adder_1bit port map(a_line(3),c_in(3),z_in(4),z_out(3),c_out(3));adder_1bit_inst5:adder_1bit port map(a_line(4),c_in(4),z_in(5),z_out(4),c_out(4));adder_1bit_inst6:adder_1bit port map(a_line(5),c_in(5),z_in(6),z_out(5),c_out(5));adder_1bit_inst7:adder_1bit port map(a_line(6),c_in(6),z_in(7),z_out(6),c_out(6));process(x_in,y_in)begin z_out(7)<=x_in and y_in(7); for i in 0 to 7 loop a_line(i)<=x_in and y_in(i); end loop;end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/a2c62b9b632c261aa03fc7767147d496.png"></p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 13:02:24<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity array_multiplier_low is Port ( z_in,c_in:in std_logic_vector(6 downto 0); s_out:out std_logic_vector(7 downto 0) );end array_multiplier_low;architecture Behavioral of array_multiplier_low iscomponent adder_1bit Port ( a,b,c_in:in std_logic; s,c_out:out std_logic );end component;signal c_line:std_logic_vector(5 downto 0);beginadder_1bit_inst0:adder_1bit port map(z_in(0),c_in(0),'0',s_out(0),c_line(0));adder_1bit_inst1:adder_1bit port map(z_in(1),c_in(1),c_line(0),s_out(1),c_line(1));adder_1bit_inst2:adder_1bit port map(z_in(2),c_in(2),c_line(1),s_out(2),c_line(2));adder_1bit_inst3:adder_1bit port map(z_in(3),c_in(3),c_line(2),s_out(3),c_line(3));adder_1bit_inst4:adder_1bit port map(z_in(4),c_in(4),c_line(3),s_out(4),c_line(4));adder_1bit_inst5:adder_1bit port map(z_in(5),c_in(5),c_line(4),s_out(5),c_line(5));adder_1bit_inst6:adder_1bit port map(z_in(6),c_in(6),c_line(5),s_out(6),s_out(7));end Behavioral;</code></pre><p><br><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 13:02:24<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity adder_1bit is Port ( a,b,c_in:in std_logic; s,c_out:out std_logic );end adder_1bit;architecture Behavioral of adder_1bit isbeginprocess(a,b,c_in)begin s<=a xor b xor c_in; c_out<=(a and b)or((a xor b)and c_in);end process;end Behavioral;</code></pre><p>testbench:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 13:02:24<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity array_multiplier_tb is-- Port ( );end array_multiplier_tb;architecture Behavioral of array_multiplier_tb iscomponent array_multiplier_seg Port ( rst,clk:in std_logic; a_in,b_in:in std_logic_vector(7 downto 0); seg_dig:out std_logic_vector(15 downto 0); seg_data:out std_logic_vector(7 downto 0) );end component;signal rst,clk:std_logic;signal a_in,b_in:std_logic_vector(7 downto 0);signal seg_dig:std_logic_vector(15 downto 0);signal seg_data:std_logic_vector(7 downto 0);</code></pre><p><br> begin</p><pre><code>array_multiplier_seg_inst:array_multiplier_seg port map(rst,clk,a_in,b_in,seg_dig,seg_data);clock:processbegin clk<='1'; wait for 5ns; clk<='0'; wait for 5ns;end process;restart:processbegin rst<='1'; wait for 25ns; rst<='0'; wait;end process;test:processbegin a_in<="10111101"; b_in<="11001010"; wait;end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/4c1acafbbcf9f2fcb9878c936a3f2244.png"></p><p>xdc:</p><p><br> #———————————————————————————-<br> #– Engineer: switch_swq<br> #– Create Date: 2024/04/18 13:02:24<br> #———————————————————————————-<br> #CLK_100M<br> set_property PACKAGE_PIN E10 [get_ports clk]<br> set_property IOSTANDARD LVCMOS18 [get_ports clk]</p><pre><code>#SW0~15set_property IOSTANDARD LVCMOS18 [get_ports {a_in[0]}]set_property IOSTANDARD LVCMOS18 [get_ports {a_in[1]}]set_property IOSTANDARD LVCMOS18 [get_ports {a_in[2]}]set_property IOSTANDARD LVCMOS18 [get_ports {a_in[3]}]set_property IOSTANDARD LVCMOS18 [get_ports {a_in[4]}]set_property IOSTANDARD LVCMOS18 [get_ports {a_in[5]}]set_property IOSTANDARD LVCMOS18 [get_ports {a_in[6]}]set_property IOSTANDARD LVCMOS18 [get_ports {a_in[7]}]set_property PACKAGE_PIN C9 [get_ports {a_in[0]}]set_property PACKAGE_PIN B9 [get_ports {a_in[1]}]set_property PACKAGE_PIN G11 [get_ports {a_in[2]}]set_property PACKAGE_PIN F10 [get_ports {a_in[3]}]set_property PACKAGE_PIN D10 [get_ports {a_in[4]}]set_property PACKAGE_PIN E11 [get_ports {a_in[5]}]set_property PACKAGE_PIN D11 [get_ports {a_in[6]}]set_property PACKAGE_PIN A14 [get_ports {a_in[7]}]set_property IOSTANDARD LVCMOS18 [get_ports {b_in[0]}]set_property IOSTANDARD LVCMOS18 [get_ports {b_in[1]}]set_property IOSTANDARD LVCMOS18 [get_ports {b_in[2]}]set_property IOSTANDARD LVCMOS18 [get_ports {b_in[3]}]set_property IOSTANDARD LVCMOS18 [get_ports {b_in[4]}]set_property IOSTANDARD LVCMOS18 [get_ports {b_in[5]}]set_property IOSTANDARD LVCMOS18 [get_ports {b_in[6]}]set_property IOSTANDARD LVCMOS18 [get_ports {b_in[7]}]set_property PACKAGE_PIN B10 [get_ports {b_in[0]}]set_property PACKAGE_PIN A10 [get_ports {b_in[1]}]set_property PACKAGE_PIN B15 [get_ports {b_in[2]}]set_property PACKAGE_PIN A15 [get_ports {b_in[3]}]set_property PACKAGE_PIN A13 [get_ports {b_in[4]}]set_property PACKAGE_PIN A12 [get_ports {b_in[5]}]set_property PACKAGE_PIN D8 [get_ports {b_in[6]}]set_property PACKAGE_PIN D9 [get_ports {b_in[7]}]#SEG_DIG1~16set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[15]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[14]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[13]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[12]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[11]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[10]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[9]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[8]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[7]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[6]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[5]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[4]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[3]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[2]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[1]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[0]}]set_property PACKAGE_PIN A23 [get_ports {seg_dig[15]}]set_property PACKAGE_PIN A24 [get_ports {seg_dig[14]}]set_property PACKAGE_PIN D26 [get_ports {seg_dig[13]}]set_property PACKAGE_PIN C26 [get_ports {seg_dig[12]}]set_property PACKAGE_PIN A20 [get_ports {seg_dig[11]}]set_property PACKAGE_PIN J25 [get_ports {seg_dig[10]}]set_property PACKAGE_PIN J24 [get_ports {seg_dig[9]}]set_property PACKAGE_PIN H22 [get_ports {seg_dig[8]}]set_property PACKAGE_PIN K21 [get_ports {seg_dig[7]}]set_property PACKAGE_PIN L23 [get_ports {seg_dig[6]}]set_property PACKAGE_PIN B25 [get_ports {seg_dig[5]}]set_property PACKAGE_PIN B26 [get_ports {seg_dig[4]}]set_property PACKAGE_PIN C24 [get_ports {seg_dig[3]}]set_property PACKAGE_PIN D21 [get_ports {seg_dig[2]}]set_property PACKAGE_PIN C22 [get_ports {seg_dig[1]}]set_property PACKAGE_PIN B20 [get_ports {seg_dig[0]}]#seg_dataset_property PACKAGE_PIN E26 [get_ports {seg_data[7]}]set_property PACKAGE_PIN J26 [get_ports {seg_data[6]}]set_property PACKAGE_PIN H26 [get_ports {seg_data[5]}]set_property PACKAGE_PIN H21 [get_ports {seg_data[4]}]set_property PACKAGE_PIN G21 [get_ports {seg_data[3]}]set_property PACKAGE_PIN H23 [get_ports {seg_data[2]}]set_property PACKAGE_PIN H24 [get_ports {seg_data[1]}]set_property PACKAGE_PIN J21 [get_ports {seg_data[0]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[7]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[6]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[5]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[4]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[3]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[2]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[1]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[0]}]</code></pre><p><br> set_property PACKAGE_PIN J8 [get_ports rst]<br> set_property IOSTANDARD LVCMOS18 [get_ports rst]</p><h3 id="4-先进先出-FIFO-的设计"><a href="#4-先进先出-FIFO-的设计" class="headerlink" title="4.先进先出 FIFO 的设计"></a>4.先进先出 FIFO 的设计</h3><p><img src="https://i-blog.csdnimg.cn/blog_migrate/311aeef9dede913202b7df632c3aa302.png"></p><p>源码:</p><p>顶层:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 13:02:24<br> – Module Name: FIFO_ring_test - Behavioral<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;</p><pre><code>entity FIFO_ring_test isgeneric( CLK_FRE:integer:=100000000; cycle_max:positive:=3;--最大读写圈数 depth:positive:=3; width:positive:=8); Port( clk:in std_logic; rst:in std_logic; key_in:in std_logic; data_in:in std_logic_vector(7 downto 0); wr:in std_logic; rd:in std_logic; empty:out std_logic; full:out std_logic; data_out:out std_logic_vector(7 downto 0) );end FIFO_ring_test;architecture Behavioral of FIFO_ring_test iscomponent key_stroke generic(CLK_FRE:integer:=100000000); Port ( clk:in std_logic; reset:in std_logic; key_in:in std_logic; output:out std_logic );end component;component FIFO_ringgeneric( cycle_max:positive:=3;--最大读写圈数 depth:positive:=3; width:positive:=8); Port( clk,clk_rd,clk_wr:in std_logic; rst:in std_logic; data_in:in std_logic_vector(7 downto 0); wr:in std_logic; rd:in std_logic; empty:out std_logic; full:out std_logic; data_out:out std_logic_vector(7 downto 0) );end component;signal out_put:std_logic;beginkey_stroke_inst:key_stroke generic map(CLK_FRE)port map(clk=>clk,reset=>rst,key_in=>key_in,output=>out_put);FIFO_ring_inst:FIFO_ring generic map(cycle_max,depth,width)port map(rst=>rst,clk=>clk,clk_rd=>out_put,clk_wr=>out_put,wr=>wr,rd=>rd,data_in=>data_in,full=>full,empty=>empty,data_out=>data_out);end Behavioral;</code></pre><p><br><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 13:02:24<br> – Module Name: FIFO_ring - Behavioral<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;</p><pre><code>entity FIFO_ring isgeneric( cycle_max:positive:=3;--最大读写圈数 depth:positive:=3; width:positive:=8); Port( clk,clk_rd,clk_wr:in std_logic; rst:in std_logic; data_in:in std_logic_vector(7 downto 0); wr:in std_logic; rd:in std_logic; empty:out std_logic; full:out std_logic; data_out:out std_logic_vector(7 downto 0) );end FIFO_ring;architecture Behavioral of FIFO_ring iscomponent duaramgeneric( depth:positive:=3; width:positive:=8);Port( clka:in std_logic; wr:in std_logic; wr_en:in std_logic; addra:in std_logic_vector(depth-1 downto 0); datain:in std_logic_vector(width-1 downto 0); clkb:in std_logic; rd:in std_logic; rd_en:in std_logic; addrb:in std_logic_vector(depth-1 downto 0); dataout:out std_logic_vector(width-1 downto 0)); end component;component FIFO_ring_duaram_controllergeneric( cycle_max:positive;--最大读写圈数 depth:positive);Port( rst:in std_logic; clk,clka,clkb:in std_logic; wq:in std_logic; rq:in std_logic; full:out std_logic; empty:out std_logic; wr_pt:out std_logic_vector(depth-1 downto 0); rd_pt:out std_logic_vector(depth-1 downto 0));end component;signal rp_line:std_logic_vector(depth-1 downto 0);signal wp_line:std_logic_vector(depth-1 downto 0);signal empty_line:std_logic;signal full_line:std_logic;beginduaram_inst:duaram generic map(depth,width)port map(clka=>clk_wr,clkb=>clk_rd,datain=>data_in,dataout=>data_out,addra=>wp_line,addrb=>rp_line,rd=>rd,wr=>wr,rd_en=>empty_line,wr_en=>full_line);FIFO_ring_duaram_controller_inst:FIFO_ring_duaram_controller generic map(cycle_max,depth)port map(rst=>rst,clk=>clk,clkb=>clk_rd,clka=>clk_wr,wq=>wr,rq=>rd,full=>full_line,empty=>empty_line,wr_pt=>wp_line,rd_pt=>rp_line);process(empty_line,full_line)begin empty<=empty_line; full<=full_line;end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/a99a9296939596a5890faf5f0a592e12.png"></p><p>模块:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 13:02:24<br> – Module Name: FIFO_ring - Behavioral<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;</p><pre><code>entity duaram is generic( depth:positive; width:positive ); Port( clka:in std_logic; wr:in std_logic; wr_en:in std_logic; addra:in std_logic_vector(depth-1 downto 0); datain:in std_logic_vector(width-1 downto 0); clkb:in std_logic; rd:in std_logic; rd_en:in std_logic; addrb:in std_logic_vector(depth-1 downto 0); dataout:out std_logic_vector(width-1 downto 0) );end duaram;architecture Behavioral of duaram istype ram is array(2**depth-1 downto 0)of std_logic_vector(width-1 downto 0);signal dualram:ram;begin process(clka) begin if(clka'event and clka='1')then if(wr='0'and wr_en='0')then dualram(conv_integer(addra))<=datain;end if; end if; end process; process(clkb) begin if(clkb'event and clkb='1')then if(rd='0'and rd_en='0')then dataout<=dualram(conv_integer(addrb));end if; end if; end process;end Behavioral;</code></pre><p><br><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 13:02:24<br> – Module Name: FIFO_ring_duaram_controller - Behavioral<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;</p><pre><code>entity FIFO_ring_duaram_controller isgeneric( cycle_max:positive;--最大读写圈数 depth:positive);Port( rst:in std_logic; clk,clka,clkb:in std_logic; wq:in std_logic; rq:in std_logic; full:out std_logic; empty:out std_logic; wr_pt:out std_logic_vector(depth-1 downto 0); rd_pt:out std_logic_vector(depth-1 downto 0));end FIFO_ring_duaram_controller;architecture Behavioral of FIFO_ring_duaram_controller issignal wr_pt_t:std_logic_vector(depth+cycle_max-1 downto 0);signal rd_pt_t:std_logic_vector(depth+cycle_max-1 downto 0);signal full_line:std_logic;signal empty_line:std_logic;begin--write_pointerprocess(rst,clka)begin if(rst='0')then wr_pt_t<=(others=>'0'); elsif(clka'event and clka='1')then if (wq='0'and full_line='0')then wr_pt_t<=wr_pt_t+1;end if; end if; end process;--read_pointerprocess(rst,clkb)begin if(rst='0')then rd_pt_t<=(others=>'0'); elsif(clkb'event and clkb='1')then if (rq='0'and empty_line='0')then rd_pt_t<=rd_pt_t+1;end if; end if;end process;--judge_statusprocess(rst,clk)begin if(rst='0')then empty_line<='1';full_line<='0'; elsif(clk'event and clk='1')then if(wr_pt_t=rd_pt_t)then empty_line<='1';full_line<='0'; elsif(wr_pt_t=rd_pt_t+2**depth)then empty_line<='0';full_line<='1'; else empty_line<='0';full_line<='0'; end if; end if; end process;process(wr_pt_t)begin wr_pt<=wr_pt_t(depth-1 downto 0);end process;process(rd_pt_t)begin rd_pt<=rd_pt_t(depth-1 downto 0);end process;process(empty_line)begin empty<=empty_line;end process;process(full_line)begin full<=full_line;end process;end Behavioral;</code></pre><p>testbench:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 13:02:24<br> – Module Name: FIFO_ring_tb - Behavioral<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity FIFO_ring_tb is-- Port ( );end FIFO_ring_tb;architecture Behavioral of FIFO_ring_tb iscomponent FIFO_ring_testgeneric( CLK_FRE:integer:=100000000; cycle_max:positive:=3;--最大读写圈数 depth:positive:=3; width:positive:=8); Port( clk:in std_logic; rst:in std_logic; key_in:in std_logic; data_in:in std_logic_vector(7 downto 0); wr:in std_logic; rd:in std_logic; empty:out std_logic; full:out std_logic; data_out:out std_logic_vector(7 downto 0) );end component;signal clk:std_logic;signal rst:std_logic;signal key_in:std_logic;signal data_in:std_logic_vector(7 downto 0);signal wr:std_logic;signal rd:std_logic;signal empty:std_logic;signal full:std_logic;signal data_out:std_logic_vector(7 downto 0);beginFIFO_ring_test_inst:FIFO_ring_test generic map(100000000,3,8)port map(clk,rst,key_in,data_in,wr,rd,empty,full,data_out);clock:processbegin clk<='0'; wait for 5ns; clk<='1'; wait for 5ns;end process;reset:processbegin rst<='0'; wait for 25ns; rst<='1'; wait;end process;test:processbegin rd<='1'; wr<='1'; data_in<="00000000"; key_in<='0'; wait for 4ms; rd<='1'; wr<='0'; data_in<="00000001"; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; data_in<="00000010"; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; data_in<="00000100"; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; data_in<="00001000"; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; data_in<="00010000"; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; data_in<="00100000"; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; data_in<="01000000"; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; data_in<="10000000"; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; data_in<="11111111"; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; data_in<="00001111"; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; data_in<="11110000"; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; wr<='1'; rd<='0'; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; rd<='1'; wr<='0'; data_in<=not"00000001"; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; data_in<=not"00000010"; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; data_in<=not"00000100"; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; data_in<=not"00001000"; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; data_in<=not"00010000"; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; data_in<=not"00100000"; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; data_in<=not"01000000"; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; data_in<=not"10000000"; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; data_in<=not"11111111"; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; data_in<=not"00001111"; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; data_in<=not"11110000"; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; wr<='1'; rd<='0'; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; wait for 4ms; key_in<='1'; wait for 4ms; key_in<='0'; wait for 4ms; wait;end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/36a731b3be24e70c8626b6c8ffc27d7b.png"></p><p>xdc:</p><p><br> #———————————————————————————-<br> #– Engineer: switch_swq<br> #– Create Date: 2024/04/18 13:02:24<br> #———————————————————————————-<br> set_property IOSTANDARD LVCMOS18 [get_ports {data_in[0]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {data_in[1]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {data_in[2]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {data_in[3]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {data_in[4]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {data_in[5]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {data_in[6]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {data_in[7]}]<br> set_property PACKAGE_PIN C9 [get_ports {data_in[0]}]<br> set_property PACKAGE_PIN B9 [get_ports {data_in[1]}]<br> set_property PACKAGE_PIN G11 [get_ports {data_in[2]}]<br> set_property PACKAGE_PIN F10 [get_ports {data_in[3]}]<br> set_property PACKAGE_PIN D10 [get_ports {data_in[4]}]<br> set_property PACKAGE_PIN E11 [get_ports {data_in[5]}]<br> set_property PACKAGE_PIN D11 [get_ports {data_in[6]}]<br> set_property PACKAGE_PIN A14 [get_ports {data_in[7]}]</p><pre><code>set_property PACKAGE_PIN E10 [get_ports clk]set_property IOSTANDARD LVCMOS18 [get_ports clk]#sw31set_property PACKAGE_PIN J8 [get_ports rst]set_property IOSTANDARD LVCMOS18 [get_ports rst]#sw30set_property PACKAGE_PIN J14 [get_ports key_in]set_property IOSTANDARD LVCMOS18 [get_ports key_in]#sw29set_property PACKAGE_PIN H9 [get_ports wr]set_property IOSTANDARD LVCMOS18 [get_ports wr]#sw28set_property PACKAGE_PIN H8 [get_ports rd]set_property IOSTANDARD LVCMOS18 [get_ports rd]#led15set_property PACKAGE_PIN L20 [get_ports empty]set_property IOSTANDARD LVCMOS33 [get_ports empty]#led11set_property PACKAGE_PIN J20 [get_ports full]set_property IOSTANDARD LVCMOS33 [get_ports full]#led0-7set_property IOSTANDARD LVCMOS33 [get_ports {data_out[0]}]set_property IOSTANDARD LVCMOS33 [get_ports {data_out[1]}]set_property IOSTANDARD LVCMOS33 [get_ports {data_out[2]}]set_property IOSTANDARD LVCMOS33 [get_ports {data_out[3]}]set_property IOSTANDARD LVCMOS33 [get_ports {data_out[4]}]set_property IOSTANDARD LVCMOS33 [get_ports {data_out[5]}]set_property IOSTANDARD LVCMOS33 [get_ports {data_out[6]}]set_property IOSTANDARD LVCMOS33 [get_ports {data_out[7]}]set_property PACKAGE_PIN G16[get_ports {data_out[0]}]set_property PACKAGE_PIN H16 [get_ports {data_out[1]}]set_property PACKAGE_PIN D16 [get_ports {data_out[2]}]set_property PACKAGE_PIN D15 [get_ports {data_out[3]}]set_property PACKAGE_PIN C18 [get_ports {data_out[4]}]set_property PACKAGE_PIN C17 [get_ports {data_out[5]}]set_property PACKAGE_PIN B19 [get_ports {data_out[6]}]set_property PACKAGE_PIN C19 [get_ports {data_out[7]}]</code></pre><h3 id="5-PC-程序计数器设计"><a href="#5-PC-程序计数器设计" class="headerlink" title="5.PC 程序计数器设计"></a>5.PC 程序计数器设计</h3><p> PC 功能分析 加 1 功能、更新地址功能、PC 数值送到数据总线</p><p> PC 功能实现</p><p>1)全局异步复位功能</p><pre><code> ADDR<=“000000000000”; 数据总线高阻态;</code></pre><p>2)加 1 功能</p><pre><code> clk_PC 上升沿有效; M_PC 高电平有效,PC+1=>ADDR;</code></pre><p>3)地址更新功能</p><pre><code> clk_PC 上升沿有效,nLD_PC 低电平有效,新的 PC=>ADDR; PC 数值送到数据总线,nPCH 和 nPCL 低电平有效,注意分两次输出到总线上,先高 8 位后低 8 位。</code></pre><p><strong>注:自行添加按键消抖模块</strong></p><p>源码:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 13:02:24<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;</p><pre><code>entity pc is Port ( rst,clk_PC,M_PC,nLD_PC:in std_logic; PC_in:in std_logic_vector(11 downto 0); DATA_BUS:inout std_logic_vector(7 downto 0); nPCH,nPCL:out std_logic );end pc;architecture Behavioral of pc issignal pc_count:std_logic_vector(11 downto 0);signal ADDR:std_logic_vector(11 downto 0);</code></pre><p><br> begin</p><pre><code>process(rst,clk_PC)variable addr_count:integer:=0;begin if(rst='1')then pc_count<=PC_in; ADDR<=pc_count; DATA_BUS<="XXXXXXXX"; nPCH<='1';nPCL<='1'; elsif(clk_PC='1'and clk_PC'event)then if(addr_count=0)then pc_count<=pc_count+1;end if; if(M_PC='1')then ADDR<=pc_count;end if; if(nLD_PC='0')then if(addr_count=0)then DATA_BUS<="0000"& ADDR(11 downto 8);addr_count:=addr_count+1;nPCH<='0';nPCL<='1'; elsif(addr_count=1)then DATA_BUS<=ADDR(7 downto 0);addr_count:=addr_count-1;nPCH<='1';nPCL<='0'; end if; end if; end if;end process;</code></pre><p><br><br> end Behavioral;</p><p>xdc:</p><p><br> #———————————————————————————-<br> #– Engineer: switch_swq<br> #– Create Date: 2024/04/18 13:02:24<br> #———————————————————————————-<br> set_property IOSTANDARD LVCMOS18 [get_ports {PC_in[0]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {PC_in[1]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {PC_in[2]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {PC_in[3]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {PC_in[4]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {PC_in[5]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {PC_in[6]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {PC_in[7]}]<br> set_property PACKAGE_PIN C9 [get_ports {PC_in[0]}]<br> set_property PACKAGE_PIN B9 [get_ports {PC_in[1]}]<br> set_property PACKAGE_PIN G11 [get_ports {PC_in[2]}]<br> set_property PACKAGE_PIN F10 [get_ports {PC_in[3]}]<br> set_property PACKAGE_PIN D10 [get_ports {PC_in[4]}]<br> set_property PACKAGE_PIN E11 [get_ports {PC_in[5]}]<br> set_property PACKAGE_PIN D11 [get_ports {PC_in[6]}]<br> set_property PACKAGE_PIN A14 [get_ports {PC_in[7]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {PC_in[8]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {PC_in[9]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {PC_in[10]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {PC_in[11]}]<br> set_property PACKAGE_PIN B10 [get_ports {PC_in[8]}]<br> set_property PACKAGE_PIN A10 [get_ports {PC_in[9]}]<br> set_property PACKAGE_PIN B15 [get_ports {PC_in[10]}]<br> set_property PACKAGE_PIN A15 [get_ports {PC_in[11]}]</p><p><br> set_property IOSTANDARD LVCMOS33 [get_ports {DATA_BUS[0]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {DATA_BUS[1]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {DATA_BUS[2]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {DATA_BUS[3]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {DATA_BUS[4]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {DATA_BUS[5]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {DATA_BUS[6]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {DATA_BUS[7]}]<br> set_property PACKAGE_PIN G16[get_ports {DATA_BUS[0]}]<br> set_property PACKAGE_PIN H16 [get_ports {DATA_BUS[1]}]<br> set_property PACKAGE_PIN D16 [get_ports {DATA_BUS[2]}]<br> set_property PACKAGE_PIN D15 [get_ports {DATA_BUS[3]}]<br> set_property PACKAGE_PIN C18 [get_ports {DATA_BUS[4]}]<br> set_property PACKAGE_PIN C17 [get_ports {DATA_BUS[5]}]<br> set_property PACKAGE_PIN B19 [get_ports {DATA_BUS[6]}]<br> set_property PACKAGE_PIN C19 [get_ports {DATA_BUS[7]}]</p><pre><code>#sw31set_property PACKAGE_PIN J8 [get_ports rst]set_property IOSTANDARD LVCMOS18 [get_ports rst]#sw30set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets clk_PC]set_property PACKAGE_PIN J14 [get_ports clk_PC]set_property IOSTANDARD LVCMOS18 [get_ports clk_PC]#sw29set_property PACKAGE_PIN H9 [get_ports M_PC]set_property IOSTANDARD LVCMOS18 [get_ports M_PC]#sw28set_property PACKAGE_PIN H8 [get_ports nLD_PC]set_property IOSTANDARD LVCMOS18 [get_ports nLD_PC]#led15set_property PACKAGE_PIN L20 [get_ports nPCH]set_property IOSTANDARD LVCMOS33 [get_ports nPCH]#led11set_property PACKAGE_PIN J20 [get_ports nPCL]set_property IOSTANDARD LVCMOS33 [get_ports nPCL]</code></pre><h3 id="6-程序存储器-ROM-设计"><a href="#6-程序存储器-ROM-设计" class="headerlink" title="6.程序存储器 ROM 设计"></a>6.程序存储器 ROM 设计</h3><p><img src="https://i-blog.csdnimg.cn/blog_migrate/ca1179f853bd18943bce21382adae2c2.png"></p><p>源码:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 13:02:24<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_unsigned.ALL;<br> use IEEE.STD_LOGIC_textio.ALL;<br> use std.textio.all;</p><pre><code>entity ROM is generic( depth:positive:=12; width:positive:=8 ); Port ( clk_ROM,M_ROM,ROM_EN:in std_logic; addr:in std_logic_vector(11 downto 0); DATA_BUS:inout std_logic_vector(7 downto 0) );end ROM;architecture Behavioral of ROM istype matrix is array (integer range<>)of std_logic_vector(width-1 downto 0);signal rom:matrix(0 to 2**depth-1);procedure load_rom (signal data_word:out matrix)isfile romfile:text open read_mode is "romfile.dat";variable lbuf:line;variable i:integer:=0;variable fdata:std_logic_vector(7 downto 0);begin while(not endfile(romfile)and i<2**depth)loop readline(romfile,lbuf); read(lbuf,fdata); data_word(i)<=fdata; i:=i+1; end loop;end procedure;beginload_rom(rom);process(clk_ROM)begin if(clk_ROM='1'and clk_ROM'event)then if(ROM_EN='0'and M_ROM='1')then DATA_BUS<=rom(conv_integer(addr)); else DATA_BUS<=(others=>'Z'); end if; end if;end process; end Behavioral;</code></pre><p>testbench:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 13:02:24<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;</p><pre><code>entity ROM_tb is-- Port ( );end ROM_tb;architecture Behavioral of ROM_tb iscomponent ROM generic( depth:positive:=12; width:positive:=8 ); Port ( clk_ROM,M_ROM,ROM_EN:in std_logic; addr:in std_logic_vector(11 downto 0); DATA_BUS:inout std_logic_vector(7 downto 0) );end component;signal rst:std_logic;signal clk_ROM,M_ROM,ROM_EN:std_logic;signal addr:std_logic_vector(11 downto 0);signal DATA_BUS:std_logic_vector(7 downto 0);beginROM_inst:ROM generic map(12,8)port map(clk_ROM,M_ROM,ROM_EN,addr,DATA_BUS);clock:processbegin clk_ROM<='1'; wait for 5ns; clk_ROM<='0'; wait for 5ns;end process;test:processbegin M_ROM<='0'; ROM_EN<='1'; addr<=(others=>'0'); wait for 25ns; M_ROM<='1'; wait for 25ns; ROM_EN<='0'; wait for 5ns; addr<="000000000000"; wait for 20ns; wait for 5ns; addr<="000000000001"; wait for 20ns; wait for 5ns; addr<="000000000010"; wait for 20ns; wait for 5ns; addr<="000000000011"; wait for 20ns; wait;end process;end Behavioral;</code></pre><p>xdc:</p><p><br> set_property IOSTANDARD LVCMOS18 [get_ports {addr[0]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {addr[1]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {addr[2]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {addr[3]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {addr[4]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {addr[5]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {addr[6]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {addr[7]}]<br> set_property PACKAGE_PIN C9 [get_ports {addr[0]}]<br> set_property PACKAGE_PIN B9 [get_ports {addr[1]}]<br> set_property PACKAGE_PIN G11 [get_ports {addr[2]}]<br> set_property PACKAGE_PIN F10 [get_ports {addr[3]}]<br> set_property PACKAGE_PIN D10 [get_ports {addr[4]}]<br> set_property PACKAGE_PIN E11 [get_ports {addr[5]}]<br> set_property PACKAGE_PIN D11 [get_ports {addr[6]}]<br> set_property PACKAGE_PIN A14 [get_ports {addr[7]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {addr[8]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {addr[9]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {addr[10]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {addr[11]}]<br> set_property PACKAGE_PIN B10 [get_ports {addr[8]}]<br> set_property PACKAGE_PIN A10 [get_ports {addr[9]}]<br> set_property PACKAGE_PIN B15 [get_ports {addr[10]}]<br> set_property PACKAGE_PIN A15 [get_ports {addr[11]}]</p><pre><code>set_property IOSTANDARD LVCMOS33 [get_ports {DATA_BUS[0]}]set_property IOSTANDARD LVCMOS33 [get_ports {DATA_BUS[1]}]set_property IOSTANDARD LVCMOS33 [get_ports {DATA_BUS[2]}]set_property IOSTANDARD LVCMOS33 [get_ports {DATA_BUS[3]}]set_property IOSTANDARD LVCMOS33 [get_ports {DATA_BUS[4]}]set_property IOSTANDARD LVCMOS33 [get_ports {DATA_BUS[5]}]set_property IOSTANDARD LVCMOS33 [get_ports {DATA_BUS[6]}]set_property IOSTANDARD LVCMOS33 [get_ports {DATA_BUS[7]}]set_property PACKAGE_PIN G16 [get_ports {DATA_BUS[0]}]set_property PACKAGE_PIN H16 [get_ports {DATA_BUS[1]}]set_property PACKAGE_PIN D16 [get_ports {DATA_BUS[2]}]set_property PACKAGE_PIN D15 [get_ports {DATA_BUS[3]}]set_property PACKAGE_PIN C18 [get_ports {DATA_BUS[4]}]set_property PACKAGE_PIN C17 [get_ports {DATA_BUS[5]}]set_property PACKAGE_PIN B19 [get_ports {DATA_BUS[6]}]set_property PACKAGE_PIN C19 [get_ports {DATA_BUS[7]}]#sw30set_property PACKAGE_PIN J14 [get_ports ROM_EN]set_property IOSTANDARD LVCMOS18 [get_ports ROM_EN]#sw31set_property PACKAGE_PIN J8 [get_ports M_ROM]set_property IOSTANDARD LVCMOS18 [get_ports M_ROM]set_property PACKAGE_PIN E10 [get_ports clk_ROM]set_property IOSTANDARD LVCMOS18 [get_ports clk_ROM]</code></pre><h3 id="7-加减交替除法器"><a href="#7-加减交替除法器" class="headerlink" title="7.加减交替除法器"></a>7.加减交替除法器</h3><p><img src="https://i-blog.csdnimg.cn/blog_migrate/36f7c7ddcdd765b4f80b09904c236f2c.png"></p><p>原码加减交替除法器的运算法则:</p><p>1)除法运算前,应满足条件:X*<Y*,且 Y*≠0,否则,按溢出或非法除数处理;</p><p>2)符号位不参与运算,单独处理:qf= xf xor yf ;</p><p>3)部分余数采用单符号位或双符号位;</p><p>4)每步部分余数运算规则:</p><pre><code> ①若余数 R≥0, 则商上 1,左移一次,减除数; ②若余数 R<0, 则商上 0,左移一次,加除数。</code></pre><p>源码:</p><p>顶层:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 19:49:35<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity divider_origin_test is Port( rst,clk,start:in std_logic; ain:in std_logic_vector(15 downto 0);--除数(要求除数大于被除数!) bin:in std_logic_vector(7 downto 0);--被除数 done:out std_logic; seg_dig:out std_logic_vector(15 downto 0); seg_data:out std_logic_vector(7 downto 0)--管脚连接顺序:dp,g,f,e,d,c,b,a );end divider_origin_test;architecture Behavioral of divider_origin_test iscomponent clk_div generic( DIV_NUM:integer:=10000 ); Port ( rst:in std_logic; clk_in:in std_logic; clk_out:out std_logic );end component;component seg_dis port( rst,clk:in std_logic; data_in_A,data_in_B,data_in_C,data_in_D:in std_logic_vector(15 downto 0); sel_out:out std_logic_vector(15 downto 0); seg_data:out std_logic_vector(7 downto 0)--管脚连接顺序:dp,g,f,e,d,c,b,a );end component;component divider_origin Port( clk,start:in std_logic; ain:in std_logic_vector(15 downto 0);--除数(要求除数大于被除数!) bin:in std_logic_vector(7 downto 0);--被除数 done:out std_logic; s,r:out std_logic_vector(7 downto 0) );end component;signal clk_line:std_logic;signal s,r:std_logic_vector(7 downto 0);signal data_in_A,data_in_B,data_in_C,data_in_D:std_logic_vector(15 downto 0);beginclk_div_inst:clk_div generic map(10000)port map(rst,clk,clk_line);seg_dis_inst:seg_dis port map(rst,clk_line,data_in_A,data_in_B,data_in_C,data_in_D,seg_dig,seg_data);divider_origin_inst:divider_origin port map(clk,start,ain,bin,done,s,r);process(s,r,ain,bin)begin data_in_A<="00000000"&s; data_in_B<="00000000"&r; data_in_C<="00000000"&bin; data_in_D<=ain;end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/3579eeb2efc9ed74282411d3cc4a7c43.png"></p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 19:49:35<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;</p><pre><code>entity divider_origin is Port( clk,start:in std_logic; ain:in std_logic_vector(15 downto 0);--除数(要求除数大于被除数!) bin:in std_logic_vector(7 downto 0);--被除数 done:out std_logic; s,r:out std_logic_vector(7 downto 0) );end divider_origin;architecture Behavioral of divider_origin iscomponent divider_origin_ctrl Port ( clk,start:in std_logic; clkout,rstall,done:out std_logic );end component;component divider_origin_16bitreg Port ( clk,rst:in std_logic; ain:in std_logic_vector(15 downto 0); d:in std_logic_vector(8 downto 0); c_out:out std_logic; q:out std_logic_vector(15 downto 0) );end component;component divider_origin_selector Port ( clk,rst:in std_logic; a0:in std_logic; din:in std_logic_vector(7 downto 0); cout:out std_logic; dout:out std_logic_vector(7 downto 0) );end component;component divider_origin_8bitadder Port ( clk,rst:in std_logic; cina,cinb:in std_logic; ain,bin:in std_logic_vector(7 downto 0); sout:out std_logic_vector(8 downto 0) );end component;signal clk_line:std_logic;signal rst_line:std_logic;signal cina_line,cinb_line:std_logic;signal bin_line:std_logic_vector(7 downto 0);signal sout_line:std_logic_vector(8 downto 0);signal q_line:std_logic_vector(15 downto 0);begindivider_origin_ctrl_inst:divider_origin_ctrl port map(clk=>clk,start=>start,clkout=>clk_line,rstall=>rst_line,done=>done);divider_origin_16bitreg_inst:divider_origin_16bitreg port map(clk=>clk_line,rst=>rst_line,ain=>ain,d=>sout_line,c_out=>cina_line,q=>q_line);divider_origin_selector_inst:divider_origin_selector port map(clk=>clk_line,rst=>rst_line,a0=>q_line(0),din=>bin,cout=>cinb_line,dout=>bin_line);divider_origin_8bitadder_inst:divider_origin_8bitadder port map(clk=>clk_line,rst=>rst_line,cina=>cina_line,cinb=>cinb_line,ain=>q_line(15 downto 8),bin=>bin_line,sout=>sout_line);process(q_line)begin s<=q_line(7 downto 0);--&not sout_line(8); r<=cina_line&q_line(15 downto 9); --r<=q_line(15 downto 8);end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/19d7c0eaa963aceabd7b7c37f2e266a9.png"></p><p>模块:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 19:49:35<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;<br> entity divider_origin_ctrl is<br> Port (<br> clk,start:in std_logic;<br> clkout,rstall,done:out std_logic<br> );<br> end divider_origin_ctrl;</p><pre><code>architecture Behavioral of divider_origin_ctrl issignal cnt4b:std_logic_vector(3 downto 0);beginprocess(clk,start)begin rstall<=start; if(start='1')then cnt4b<="0000"; elsif clk'event and clk='1'then if cnt4b<=7 then cnt4b<=cnt4b+1;end if; end if;end process;process(clk,cnt4b,start)begin if (start='1')then clkout<='0';done<='0'; elsif(start='0')then if cnt4b<=7 then clkout<=clk; else clkout<='0';done<='1'; end if; end if;end process;end Behavioral;</code></pre><p><br><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 19:49:35<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;<br> entity divider_origin_16bitreg is<br> Port (<br> clk,rst:in std_logic;<br> ain:in std_logic_vector(15 downto 0);<br> d:in std_logic_vector(8 downto 0);<br> c_out:out std_logic;<br> q:out std_logic_vector(15 downto 0)<br> );<br> end divider_origin_16bitreg;</p><pre><code>architecture Behavioral of divider_origin_16bitreg isbeginprocess(clk,rst)variable sr16b:std_logic_vector(15 downto 0);begin if rst='1'then sr16b:=ain; c_out<=sr16b(15);--发送符号位 sr16b(15 downto 1):=sr16b(14 downto 0);--左移一位 sr16b(0):='0';--上0 elsif(clk='1'and clk'event)then sr16b(15 downto 8):=d(7 downto 0); c_out<=sr16b(15);--发送符号位 sr16b(15 downto 1):=sr16b(14 downto 0);--左移一位 sr16b(0):=not d(8); --上商取反符号位 end if; q<=sr16b;end process;end Behavioral;</code></pre><p><br><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 19:49:35<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;<br> entity divider_origin_selector is<br> Port (<br> clk,rst:in std_logic;<br> a0:in std_logic;<br> din:in std_logic_vector(7 downto 0);<br> cout:out std_logic;<br> dout:out std_logic_vector(7 downto 0)<br> );<br> end divider_origin_selector;</p><pre><code>architecture Behavioral of divider_origin_selector issignal complement_x_negative:std_logic_vector(7 downto 0);beginprocess(din)begin complement_x_negative<=(not din)+1;end process;process(clk,rst,a0,din)begin if(rst='1')then dout<=complement_x_negative;cout<='1'; elsif(clk'event and clk='0')then if(a0='1')then dout<=complement_x_negative;cout<='1';--输出加数和其符号位 else dout<=din;cout<='0'; end if; end if; end process;end Behavioral;</code></pre><p><br><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 19:49:35<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;<br> entity divider_origin_8bitadder is<br> Port (<br> clk,rst:in std_logic;<br> cina,cinb:in std_logic;<br> ain,bin:in std_logic_vector(7 downto 0);<br> sout:out std_logic_vector(8 downto 0)<br> );<br> end divider_origin_8bitadder;</p><pre><code>architecture Behavioral of divider_origin_8bitadder isbeginprocess(rst,clk,ain,bin,cina,cinb)begin if(rst='1')then sout<=(cina & ain)+(cinb & bin); elsif(clk='0')then sout<=(cina & ain)+(cinb & bin); end if;end process;end Behavioral;</code></pre><p>testbench:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/18 19:49:35<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity divider_origin_tb is-- Port ( );end divider_origin_tb;architecture Behavioral of divider_origin_tb iscomponent divider_origin Port( clk,start:in std_logic; ain:in std_logic_vector(15 downto 0);--除数 bin:in std_logic_vector(7 downto 0);--被除数 done:out std_logic; s,r:out std_logic_vector(7 downto 0) );end component;signal clk,start: std_logic;signal ain: std_logic_vector(15 downto 0);signal bin: std_logic_vector(7 downto 0);signal done: std_logic;signal s,r: std_logic_vector(7 downto 0);begindivider_origin_inst:divider_origin port map(clk,start,ain,bin,done,s,r);clock_gen:processbegin clk<='1'; wait for 5ns; clk<='0'; wait for 5ns;end process;test:processbegin --09 0d ain<=x"008B"; bin<=x"0E"; wait for 25ns; start<='1'; wait for 25ns; start<='0'; wait for 100ns; --00 ff ain<=x"0001"; bin<=x"02"; wait for 25ns; start<='1'; wait for 25ns; start<='0'; wait for 100ns; --01 33 ain<=x"00AB"; bin<=x"78"; wait for 25ns; start<='1'; wait for 25ns; start<='0'; wait for 100ns; --ad 27 ain<=x"ABCD"; bin<=x"FE"; wait for 25ns; start<='1'; wait for 25ns; start<='0'; wait for 100ns; --01 01 ain<=x"0100"; bin<=x"FF"; wait for 25ns; start<='1'; wait for 25ns; start<='0'; wait for 100ns; wait;end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/bb48954106bbd0bf39a333bc9517b390.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/8445a0d3d348041fe6fd9b83e6bbab68.png"></p><p>xdc:</p><p><br> #———————————————————————————-<br> #– Engineer: switch_swq<br> #– Create Date: 2024/04/23 21:55:51<br> #———————————————————————————-<br> #CLK_100M<br> set_property PACKAGE_PIN E10 [get_ports clk]<br> set_property IOSTANDARD LVCMOS18 [get_ports clk]<br> #SW0<del>15<br> set_property IOSTANDARD LVCMOS18 [get_ports {ain[0]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {ain[1]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {ain[2]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {ain[3]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {ain[4]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {ain[5]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {ain[6]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {ain[7]}]<br> set_property PACKAGE_PIN C9 [get_ports {ain[0]}]<br> set_property PACKAGE_PIN B9 [get_ports {ain[1]}]<br> set_property PACKAGE_PIN G11 [get_ports {ain[2]}]<br> set_property PACKAGE_PIN F10 [get_ports {ain[3]}]<br> set_property PACKAGE_PIN D10 [get_ports {ain[4]}]<br> set_property PACKAGE_PIN E11 [get_ports {ain[5]}]<br> set_property PACKAGE_PIN D11 [get_ports {ain[6]}]<br> set_property PACKAGE_PIN A14 [get_ports {ain[7]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {ain[8]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {ain[9]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {ain[10]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {ain[11]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {ain[12]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {ain[13]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {ain[14]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {ain[15]}]<br> set_property PACKAGE_PIN B10 [get_ports {ain[8]}]<br> set_property PACKAGE_PIN A10 [get_ports {ain[9]}]<br> set_property PACKAGE_PIN B15 [get_ports {ain[10]}]<br> set_property PACKAGE_PIN A15 [get_ports {ain[11]}]<br> set_property PACKAGE_PIN A13 [get_ports {ain[12]}]<br> set_property PACKAGE_PIN A12 [get_ports {ain[13]}]<br> set_property PACKAGE_PIN D8 [get_ports {ain[14]}]<br> set_property PACKAGE_PIN D9 [get_ports {ain[15]}]<br> #SW16</del>SW23<br> set_property IOSTANDARD LVCMOS18 [get_ports {bin[0]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {bin[1]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {bin[2]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {bin[3]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {bin[4]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {bin[5]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {bin[6]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {bin[7]}]<br> set_property PACKAGE_PIN F8 [get_ports {bin[0]}]<br> set_property PACKAGE_PIN F9 [get_ports {bin[1]}]<br> set_property PACKAGE_PIN H11 [get_ports {bin[2]}]<br> set_property PACKAGE_PIN H12 [get_ports {bin[3]}]<br> set_property PACKAGE_PIN G14 [get_ports {bin[4]}]<br> set_property PACKAGE_PIN J10 [get_ports {bin[5]}]<br> set_property PACKAGE_PIN H14 [get_ports {bin[6]}]<br> set_property PACKAGE_PIN J11 [get_ports {bin[7]}]</p><p><br> #SEG_DIG1~16<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[15]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[14]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[13]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[12]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[11]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[10]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[9]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[8]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[7]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[6]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[5]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[4]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[3]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[2]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[1]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[0]}]<br> set_property PACKAGE_PIN A23 [get_ports {seg_dig[15]}]<br> set_property PACKAGE_PIN A24 [get_ports {seg_dig[14]}]<br> set_property PACKAGE_PIN D26 [get_ports {seg_dig[13]}]<br> set_property PACKAGE_PIN C26 [get_ports {seg_dig[12]}]<br> set_property PACKAGE_PIN A20 [get_ports {seg_dig[11]}]<br> set_property PACKAGE_PIN J25 [get_ports {seg_dig[10]}]<br> set_property PACKAGE_PIN J24 [get_ports {seg_dig[9]}]<br> set_property PACKAGE_PIN H22 [get_ports {seg_dig[8]}]<br> set_property PACKAGE_PIN K21 [get_ports {seg_dig[7]}]<br> set_property PACKAGE_PIN L23 [get_ports {seg_dig[6]}]<br> set_property PACKAGE_PIN B25 [get_ports {seg_dig[5]}]<br> set_property PACKAGE_PIN B26 [get_ports {seg_dig[4]}]<br> set_property PACKAGE_PIN C24 [get_ports {seg_dig[3]}]<br> set_property PACKAGE_PIN D21 [get_ports {seg_dig[2]}]<br> set_property PACKAGE_PIN C22 [get_ports {seg_dig[1]}]<br> set_property PACKAGE_PIN B20 [get_ports {seg_dig[0]}]</p><pre><code>#seg_dataset_property PACKAGE_PIN E26 [get_ports {seg_data[7]}]set_property PACKAGE_PIN J26 [get_ports {seg_data[6]}]set_property PACKAGE_PIN H26 [get_ports {seg_data[5]}]set_property PACKAGE_PIN H21 [get_ports {seg_data[4]}]set_property PACKAGE_PIN G21 [get_ports {seg_data[3]}]set_property PACKAGE_PIN H23 [get_ports {seg_data[2]}]set_property PACKAGE_PIN H24 [get_ports {seg_data[1]}]set_property PACKAGE_PIN J21 [get_ports {seg_data[0]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[7]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[6]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[5]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[4]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[3]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[2]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[1]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[0]}]set_property PACKAGE_PIN J8 [get_ports rst]set_property IOSTANDARD LVCMOS18 [get_ports rst]set_property PACKAGE_PIN J14 [get_ports start]set_property IOSTANDARD LVCMOS18 [get_ports start]#LEDset_property IOSTANDARD LVCMOS33 [get_ports done]set_property PACKAGE_PIN G16[get_ports done]</code></pre><h3 id="8-指令存储器-IR-设计"><a href="#8-指令存储器-IR-设计" class="headerlink" title="8.指令存储器 IR 设计"></a>8.指令存储器 IR 设计</h3><p> IR 功能分析</p><pre><code> 传送指令编码到微控制器 生成 PC 的新地址 生成 RAM 的读写地址</code></pre><p> IR 功能实现</p><pre><code> 传送指令编码到微控制器 clk_IR 上升沿有效,LD_IR1 高电平有效, data->IR。 寄存器地址操作 Data[0]-> RS;Data[1]->RD; 生成 PC 的新地址 clk_IR 上升沿有效,LD_IR2 高电平有效,data[3..0]->PC[11..8]; clk_IR 上升沿有效,LD_IR3 高电平有效,data[7..0]->PC[7..0]。 生成 RAM 的读写地址 clk_IR 上升沿有效,LD_IR3 高电平有效 data[7..0]->PC[7..0]; nARen 低电平有效, PC[6..0]->AR[6..0]。</code></pre><p>源码: </p><p><br><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/20 10:29:36<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity IR_test is port ( rst,clk_IR,LD_IR1,LD_IR2,LD_IR3,nARen:in std_logic; RS,RD:out std_logic;--传送操作寄存器(寄存器地址) seg_dig:out std_logic_vector(15 downto 0); seg_data:out std_logic_vector(7 downto 0)--管脚连接顺序:dp,g,f,e,d,c,b,a );end IR_test;architecture Behavioral of IR_test iscomponent IR Port ( rst,clk_IR,LD_IR1,LD_IR2,LD_IR3,nARen:in std_logic; DATA_BUS:in std_logic_vector(7 downto 0); IR_out:out std_logic_vector(7 downto 0);--传送指令到指令寄存器 RS,RD:out std_logic;--传送操作寄存器(寄存器地址) PC_out:out std_logic_vector(11 downto 0);--PC地址总线 AR:out std_logic_vector(6 downto 0) );end component;component clk_div generic( DIV_NUM:integer:=10000 ); Port ( rst:in std_logic; clk_in:in std_logic; clk_out:out std_logic );end component;component seg_dis port( rst,clk:in std_logic; data_in_A,data_in_B,data_in_C,data_in_D:in std_logic_vector(15 downto 0); sel_out:out std_logic_vector(15 downto 0); seg_data:out std_logic_vector(7 downto 0)--管脚连接顺序:dp,g,f,e,d,c,b,a );end component;signal clk_line: std_logic;signal data_in_A,data_in_B,data_in_C,data_in_D:std_logic_vector(15 downto 0);signal DATA_BUS_line :std_logic_vector(7 downto 0);signal IR_line_line :std_logic_vector(7 downto 0);--传送指令到指令寄存器signal PC_out_line :std_logic_vector(11 downto 0);--PC地址总线signal AR_line :std_logic_vector(6 downto 0);beginclk_div_inst:clk_div generic map(10000)port map(rst,clk_IR,clk_line);sig_dis_inst:seg_dis port map(rst,clk_line,data_in_A,data_in_B,data_in_C,data_in_D,seg_dig,seg_data);IR_inst:IR port map(rst,clk_IR,LD_IR1,LD_IR2,LD_IR3,nARen,DATA_BUS_line,IR_line_line,RS,RD,PC_out_line,AR_line);process(DATA_BUS_line,IR_line_line,PC_out_line,AR_line)begin data_in_A<="00000000"&DATA_BUS_line; data_in_B<="00000000"&IR_line_line; data_in_C<="0000"&PC_out_line; data_in_D<="000000000"&AR_line;end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/9b9e9bdcb11e643277242864ba0880d9.png"></p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/20 10:29:36<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity IR is Port ( rst,clk_IR,LD_IR1,LD_IR2,LD_IR3,nARen:in std_logic; DATA_BUS:in std_logic_vector(7 downto 0); IR_out:out std_logic_vector(7 downto 0);--传送指令到指令寄存器 RS,RD:out std_logic;--传送操作寄存器(寄存器地址) PC_out:out std_logic_vector(11 downto 0);--PC地址总线 AR:out std_logic_vector(6 downto 0) );end IR;architecture Behavioral of IR isbeginprocess(rst,clk_IR,LD_IR1,LD_IR2,LD_IR3,nARen)begin if(rst='1')then IR_out<=(others=>'0'); PC_out<=(others=>'0'); RS<='0';RD<='0'; elsif(clk_IR='1' and clk_IR'event)then if(LD_IR1='1')then IR_out<=DATA_BUS;end if; RS<=DATA_BUS(0);RD<=DATA_BUS(1); if(LD_IR2='1')then PC_out(11 downto 8)<=DATA_BUS(3 downto 0); elsif(LD_IR3='1')then PC_out(7 downto 0)<=DATA_BUS(7 downto 0); if(nARen='0')then AR<=DATA_BUS(6 downto 0);end if; end if; end if;end process;end Behavioral;</code></pre><p>testbench:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/20 10:29:36<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity IR_tb is-- Port ( );end IR_tb;architecture Behavioral of IR_tb iscomponent IR Port ( rst,clk_IR,LD_IR1,LD_IR2,LD_IR3,nARen:in std_logic; DATA_BUS:in std_logic_vector(7 downto 0); IR_out:out std_logic_vector(7 downto 0);--传送指令到指令寄存器 RS,RD:out std_logic;--传送操作寄存器(寄存器地址) PC_out:out std_logic_vector(11 downto 0);--PC地址总线 AR:out std_logic_vector(6 downto 0) );end component;signal rst,clk_IR,LD_IR1,LD_IR2,LD_IR3,nARen,RS,RD: std_logic;signal DATA_BUS :std_logic_vector(7 downto 0);signal IR_line :std_logic_vector(7 downto 0);--传送指令到指令寄存器signal PC_out :std_logic_vector(11 downto 0);--PC地址总线signal AR :std_logic_vector(6 downto 0);beginIR_inst:IR port map(rst=>rst,clk_IR=>clk_IR,LD_IR1=>LD_IR1,LD_IR2=>LD_IR2,LD_IR3=>LD_IR3,nARen=>nARen,DATA_BUS=>DATA_BUS,IR_out=>IR_line,RS=>RS,RD=>RD,PC_out=>PC_out,AR=>AR);clock:processbegin clk_IR<='1'; wait for 5ns; clk_IR<='0'; wait for 5ns;end process;test:processbegin rst<='1'; --DATA_BUS<=x"EE"; DATA_BUS<="11111111"; LD_IR1<='1'; LD_IR2<='0'; LD_IR3<='0'; nARen<='1'; wait for 25ns; rst<='0'; wait for 20ns; DATA_BUS<=x"FA"; LD_IR1<='0'; LD_IR2<='1'; LD_IR3<='0'; nARen<='1'; wait for 20ns; DATA_BUS<=x"BC"; LD_IR1<='0'; LD_IR2<='0'; LD_IR3<='1'; nARen<='0'; wait;end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/366b42fa88d3bab2b3d92539815238d9.png"></p><p>xdc:</p><p><br> #———————————————————————————-<br> #– Engineer: switch_swq<br> #– Create Date: 2024/04/23 21:55:51<br> #———————————————————————————-<br> #SEG_DIG1~16<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[15]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[14]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[13]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[12]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[11]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[10]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[9]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[8]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[7]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[6]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[5]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[4]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[3]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[2]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[1]}]<br> set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[0]}]<br> set_property PACKAGE_PIN A23 [get_ports {seg_dig[15]}]<br> set_property PACKAGE_PIN A24 [get_ports {seg_dig[14]}]<br> set_property PACKAGE_PIN D26 [get_ports {seg_dig[13]}]<br> set_property PACKAGE_PIN C26 [get_ports {seg_dig[12]}]<br> set_property PACKAGE_PIN A20 [get_ports {seg_dig[11]}]<br> set_property PACKAGE_PIN J25 [get_ports {seg_dig[10]}]<br> set_property PACKAGE_PIN J24 [get_ports {seg_dig[9]}]<br> set_property PACKAGE_PIN H22 [get_ports {seg_dig[8]}]<br> set_property PACKAGE_PIN K21 [get_ports {seg_dig[7]}]<br> set_property PACKAGE_PIN L23 [get_ports {seg_dig[6]}]<br> set_property PACKAGE_PIN B25 [get_ports {seg_dig[5]}]<br> set_property PACKAGE_PIN B26 [get_ports {seg_dig[4]}]<br> set_property PACKAGE_PIN C24 [get_ports {seg_dig[3]}]<br> set_property PACKAGE_PIN D21 [get_ports {seg_dig[2]}]<br> set_property PACKAGE_PIN C22 [get_ports {seg_dig[1]}]<br> set_property PACKAGE_PIN B20 [get_ports {seg_dig[0]}]</p><pre><code>#seg_dataset_property PACKAGE_PIN E26 [get_ports {seg_data[7]}]set_property PACKAGE_PIN J26 [get_ports {seg_data[6]}]set_property PACKAGE_PIN H26 [get_ports {seg_data[5]}]set_property PACKAGE_PIN H21 [get_ports {seg_data[4]}]set_property PACKAGE_PIN G21 [get_ports {seg_data[3]}]set_property PACKAGE_PIN H23 [get_ports {seg_data[2]}]set_property PACKAGE_PIN H24 [get_ports {seg_data[1]}]set_property PACKAGE_PIN J21 [get_ports {seg_data[0]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[7]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[6]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[5]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[4]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[3]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[2]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[1]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[0]}]#sw31~24set_property PACKAGE_PIN J8 [get_ports rst]set_property IOSTANDARD LVCMOS18 [get_ports rst]set_property PACKAGE_PIN J14 [get_ports LD_IR1]set_property IOSTANDARD LVCMOS18 [get_ports LD_IR1]set_property PACKAGE_PIN H9 [get_ports LD_IR2]set_property IOSTANDARD LVCMOS18 [get_ports LD_IR2]set_property PACKAGE_PIN H8 [get_ports LD_IR3]set_property IOSTANDARD LVCMOS18 [get_ports LD_IR3]set_property PACKAGE_PIN G10 [get_ports nARen]set_property IOSTANDARD LVCMOS18 [get_ports nARen]#CLK_100Mset_property PACKAGE_PIN E10 [get_ports clk_IR]set_property IOSTANDARD LVCMOS18 [get_ports clk_IR]#LED0~1set_property IOSTANDARD LVCMOS33 [get_ports RS]set_property IOSTANDARD LVCMOS33 [get_ports RD]set_property PACKAGE_PIN G16[get_ports RS]set_property PACKAGE_PIN H16 [get_ports RD]#SW0~15set_property IOSTANDARD LVCMOS18 [get_ports {data_in[0]}]set_property IOSTANDARD LVCMOS18 [get_ports {data_in[1]}]set_property IOSTANDARD LVCMOS18 [get_ports {data_in[2]}]set_property IOSTANDARD LVCMOS18 [get_ports {data_in[3]}]set_property IOSTANDARD LVCMOS18 [get_ports {data_in[4]}]set_property IOSTANDARD LVCMOS18 [get_ports {data_in[5]}]set_property IOSTANDARD LVCMOS18 [get_ports {data_in[6]}]set_property IOSTANDARD LVCMOS18 [get_ports {data_in[7]}]set_property PACKAGE_PIN C9 [get_ports {data_in[0]}]set_property PACKAGE_PIN B9 [get_ports {data_in[1]}]set_property PACKAGE_PIN G11 [get_ports {data_in[2]}]set_property PACKAGE_PIN F10 [get_ports {data_in[3]}]set_property PACKAGE_PIN D10 [get_ports {data_in[4]}]set_property PACKAGE_PIN E11 [get_ports {data_in[5]}]set_property PACKAGE_PIN D11 [get_ports {data_in[6]}]set_property PACKAGE_PIN A14 [get_ports {data_in[7]}]</code></pre><h3 id="9-寄存器-RN-设计"><a href="#9-寄存器-RN-设计" class="headerlink" title="9.寄存器 RN 设计"></a>9.寄存器 RN 设计</h3><p>RN 功能分析:</p><p> 数据锁存功能</p><p> 读写功能</p><pre><code> 读寄存器操作 clk_RN 上升沿有效,Ri_EN 低电平有效,读信号 RDRi 高电平有效,选择 RS 寄存器, 输出 data[7..0]。 写寄存器操作 clk_RN 上升沿有效,Ri_EN 低电平有效,写信号 WRRi 高电平有效,选择 RD 寄存器, data[7..0] RD 。</code></pre><p>源码:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/20 17:36:21<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;</p><pre><code>entity RN is generic( depth:integer:=1 ); Port( clk_RN,Ri_EN,RDRi,WRRi:in std_logic; RS,RD:in std_logic_vector(depth-1 downto 0); data_in:in std_logic_vector(7 downto 0); data_out:out std_logic_vector(7 downto 0) --DATA_BUS:inout std_logic_vector(7 downto 0) );end RN;architecture Behavioral of RN istype RN is array(2**depth-1 downto 0)of std_logic_vector(7 downto 0);signal RN_in:RN;beginprocess(clk_RN)begin if(Ri_EN='1')then data_out<=(others=>'Z'); elsif(clk_RN='1'and clk_RN'event)then if(RDRi='1')then data_out<=RN_in(conv_integer(RS)); elsif(WRRi='1')then RN_in(conv_integer(RD))<=data_in; else data_out<=(others=>'Z'); end if; end if;end process;end Behavioral;</code></pre><p>testbench:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/22 09:34:26<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity RN_tb is-- Port ( );end RN_tb;architecture Behavioral of RN_tb iscomponent RN generic( depth:integer:=1 ); Port( clk_RN,Ri_EN,RDRi,WRRi:in std_logic; RS,RD:in std_logic_vector(depth-1 downto 0); data_in:in std_logic_vector(7 downto 0); data_out:out std_logic_vector(7 downto 0) --DATA_BUS:inout std_logic_vector(7 downto 0) );end component;signal clk_RN,Ri_EN,RDRi,WRRi:std_logic;signal RS,RD:std_logic_vector(0 downto 0);signal DATA_BUS:std_logic_vector(7 downto 0);signal data_in:std_logic_vector(7 downto 0);signal data_out:std_logic_vector(7 downto 0);beginRN_inst:RN generic map(1)port map(clk_RN,Ri_EN,RDRi,WRRi,RS,RD,data_in,data_out);--RN_inst:RN generic map(1)port map(clk_RN,Ri_EN,RDRi,WRRi,RS,RD,DATA_BUS);clock:processbegin clk_RN<='1'; wait for 5ns; clk_RN<='0'; wait for 5ns;end process;test:processbegin Ri_EN<='1'; wait for 25ns; Ri_EN<='0'; RDRi<='0'; WRRi<='1'; RS<="0"; RD<="0"; data_in<=x"FF"; wait for 25ns; RDRi<='0'; WRRi<='1'; RS<="0"; RD<="1"; data_in<=x"EE"; wait for 25ns; RDRi<='1'; WRRi<='0'; RS<="0"; RD<="0"; wait for 25ns; RDRi<='1'; WRRi<='0'; RS<="1"; RD<="0"; wait for 25ns; Ri_EN<='1'; wait;end process;end Behavioral;</code></pre><p>xdc:</p><p><br> #———————————————————————————-<br> #– Engineer: switch_swq<br> #– Create Date: 2024/04/23 21:55:51<br> #———————————————————————————-<br> #SW0~15<br> set_property IOSTANDARD LVCMOS18 [get_ports {data_in[0]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {data_in[1]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {data_in[2]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {data_in[3]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {data_in[4]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {data_in[5]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {data_in[6]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {data_in[7]}]<br> set_property PACKAGE_PIN C9 [get_ports {data_in[0]}]<br> set_property PACKAGE_PIN B9 [get_ports {data_in[1]}]<br> set_property PACKAGE_PIN G11 [get_ports {data_in[2]}]<br> set_property PACKAGE_PIN F10 [get_ports {data_in[3]}]<br> set_property PACKAGE_PIN D10 [get_ports {data_in[4]}]<br> set_property PACKAGE_PIN E11 [get_ports {data_in[5]}]<br> set_property PACKAGE_PIN D11 [get_ports {data_in[6]}]<br> set_property PACKAGE_PIN A14 [get_ports {data_in[7]}]</p><pre><code>#LEDset_property IOSTANDARD LVCMOS33 [get_ports {data_out[0]}]set_property IOSTANDARD LVCMOS33 [get_ports {data_out[1]}]set_property IOSTANDARD LVCMOS33 [get_ports {data_out[2]}]set_property IOSTANDARD LVCMOS33 [get_ports {data_out[3]}]set_property IOSTANDARD LVCMOS33 [get_ports {data_out[4]}]set_property IOSTANDARD LVCMOS33 [get_ports {data_out[5]}]set_property IOSTANDARD LVCMOS33 [get_ports {data_out[6]}]set_property IOSTANDARD LVCMOS33 [get_ports {data_out[7]}]set_property PACKAGE_PIN G16[get_ports {data_out[0]}]set_property PACKAGE_PIN H16 [get_ports {data_out[1]}]set_property PACKAGE_PIN D16 [get_ports {data_out[2]}]set_property PACKAGE_PIN D15 [get_ports {data_out[3]}]set_property PACKAGE_PIN C18 [get_ports {data_out[4]}]set_property PACKAGE_PIN C17 [get_ports {data_out[5]}]set_property PACKAGE_PIN B19 [get_ports {data_out[6]}]set_property PACKAGE_PIN C19 [get_ports {data_out[7]}]#CLK_100Mset_property PACKAGE_PIN E10 [get_ports clk_RN]set_property IOSTANDARD LVCMOS18 [get_ports clk_RN]#sw31~24set_property PACKAGE_PIN J8 [get_ports Ri_EN]set_property IOSTANDARD LVCMOS18 [get_ports Ri_EN]set_property PACKAGE_PIN J14 [get_ports RDRi]set_property IOSTANDARD LVCMOS18 [get_ports RDRi]set_property PACKAGE_PIN H9 [get_ports WRRi]set_property IOSTANDARD LVCMOS18 [get_ports WRRi]set_property PACKAGE_PIN H8 [get_ports {RS[0]}]set_property IOSTANDARD LVCMOS18 [get_ports {RS[0]}]set_property PACKAGE_PIN G10 [get_ports {RD[0]}]set_property IOSTANDARD LVCMOS18 [get_ports {RD[0]}]</code></pre><h3 id="10-ALU算术逻辑单元设计"><a href="#10-ALU算术逻辑单元设计" class="headerlink" title="10.ALU算术逻辑单元设计"></a>10.ALU算术逻辑单元设计</h3><p>算术逻辑单元(ALU):执行各种算术和逻辑运算。</p><p> 算术运算操作 :加、减、乘、除</p><p> 逻辑运算操作:与、或、非、异或</p><p> ALU 输入:操作数以及来自控制单元的控制命令</p><p> ALU 输出:运算结果,以及状态信息</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/43bde231cdd8555e9e66b22f437d9014.png"></p><p>源码:</p><p>顶层;</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/23 12:35:51<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> USE IEEE.STD_LOGIC_UNSIGNED.ALL;</p><pre><code>entity ALU_test is port( clk : in std_logic; --全局时钟和ALU时钟 nreset : in std_logic; --全局复位信号 M_A,M_B : in std_logic; --暂存器控制信号 M_F : in std_logic; --程序状态字控制信号 nALU_EN : in std_logic; --alu运算结果输出使能 nPSW_EN : in std_logic; --psw输出使能 C0 : in std_logic; --进位输入 S : in std_logic_vector(4 downto 0); --运算类型和操作选择,M为最高位S(4),其余在低四位 F_in : in std_logic_vector(1 downto 0); --移位功能选择 DATA_BUS : inout std_logic_vector(7 downto 0); --数据总线 seg_dig:out std_logic_vector(15 downto 0); seg_data:out std_logic_vector(7 downto 0)--管脚连接顺序:dp,g,f,e,d,c,b,a );end ALU_test;architecture Behavioral of ALU_test iscomponent clock Port( clk,rst:in std_logic; clk1,nclk1:out std_logic; --clk clk2,nclk2:out std_logic; --clk二分频 w0,w1,w2,w3:out std_logic --节拍信号 );end component;component clk_div generic( DIV_NUM:integer:=10000 ); Port ( rst:in std_logic; clk_in:in std_logic; clk_out:out std_logic );end component;component seg_dis port( rst,clk:in std_logic; data_in_A,data_in_B,data_in_C,data_in_D:in std_logic_vector(15 downto 0); seg_dig:out std_logic_vector(15 downto 0); seg_data:out std_logic_vector(7 downto 0)--管脚连接顺序:dp,g,f,e,d,c,b,a );end component;component ALU port( clk,clk_ALU : in std_logic; --全局时钟和ALU时钟 nreset : in std_logic; --全局复位信号 M_A,M_B : in std_logic; --暂存器控制信号 M_F : in std_logic; --程序状态字控制信号 nALU_EN : in std_logic; --alu运算结果输出使能 nPSW_EN : in std_logic; --psw输出使能 C0 : in std_logic; --进位输入 S : in std_logic_vector(4 downto 0); --运算类型和操作选择,M为最高位S(4),其余在低四位 F_in : in std_logic_vector(1 downto 0); --移位功能选择 regA_out,regB_out,result_out:out std_logic_vector(7 downto 0); DATA_BUS : inout std_logic_vector(7 downto 0); --数据总线 AC : out std_logic; --半进位标志 CY : out std_logic; --进位标志 ZN : out std_logic; --零标志 OV : out std_logic --溢出标志 );end component;signal nclk2,clk_line:std_logic;signal data_in_A,data_in_B,data_in_C,data_in_D:std_logic_vector(15 downto 0);signal regA_out,regB_out,result_out:std_logic_vector(7 downto 0);signal AC : std_logic; --半进位标志signal CY : std_logic; --进位标志signal ZN : std_logic; --零标志signal OV : std_logic; --溢出标志beginclock_inst:clock port map(clk=>clk,rst=>nreset,nclk2=>nclk2);clk_div_inst:clk_div generic map(10000)port map(nreset,clk,clk_line);seg_dis_inst:seg_dis port map(nreset,clk_line,data_in_A,data_in_B,data_in_C,data_in_D,seg_dig,seg_data);ALU_inst:ALU port map(clk,nclk2,nreset,m_A,m_B,m_F,nALU_EN,nPSW_EN,C0,S,F_in,regA_out,regB_out,result_out,DATA_BUS,AC,CY,ZN,OV);process(DATA_BUS,AC,CY,ZN,OV,regA_out,regB_out,result_out)begin data_in_A<="00000000"&DATA_BUS; data_in_B<="000"& AC & "000" & CY & "000" & ZN & "000" & OV; data_in_C<=regA_out&regB_out; data_in_D<=result_out&"00000000";end process;end Behavioral;</code></pre><p><br><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/22 11:58:10<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> USE IEEE.STD_LOGIC_UNSIGNED.ALL;</p><pre><code>entity ALU is port( clk,clk_ALU : in std_logic; --全局时钟和ALU时钟 nreset : in std_logic; --全局复位信号 M_A,M_B : in std_logic; --暂存器控制信号 M_F : in std_logic; --程序状态字控制信号 nALU_EN : in std_logic; --alu运算结果输出使能 nPSW_EN : in std_logic; --psw输出使能 C0 : in std_logic; --进位输入 S : in std_logic_vector(4 downto 0); --运算类型和操作选择,M为最高位S(4),其余在低四位 F_in : in std_logic_vector(1 downto 0); --移位功能选择 regA_out,regB_out,result_out:out std_logic_vector(7 downto 0); DATA_BUS : inout std_logic_vector(7 downto 0); --数据总线 AC : out std_logic; --半进位标志 CY : out std_logic; --进位标志 ZN : out std_logic; --零标志 OV : out std_logic --溢出标志 );end ALU;architecture Behavioral of ALU iscomponent array_multiplier Port ( clk:in std_logic; a_in,b_in:in std_logic_vector(7 downto 0); sum_out:out std_logic_vector(15 downto 0) );end component;component divider_origin Port( clk,start:in std_logic; ain:in std_logic_vector(15 downto 0);--除数(要求除数大于被除数!) bin:in std_logic_vector(7 downto 0);--被除数 done:out std_logic; s,r:out std_logic_vector(7 downto 0) );end component;signal regA:std_logic_vector(8 downto 0);signal regB:std_logic_vector(8 downto 0);signal result:std_logic_vector(8 downto 0);signal PSW_reg:std_logic_vector(7 downto 0); --pws(0):CY psw(1):ZNsignal AC_signal :std_logic;signal CY_signal :std_logic;signal ZN_signal :std_logic;signal OV_signal :std_logic;signal multiplier_out:std_logic_vector(15 downto 0);signal start,done:std_logic;signal divider_ina:std_logic_vector(15 downto 0);signal divider_r:std_logic_vector(7 downto 0);beginarray_multiplier_inst:array_multiplier port map(clk_ALU,regA(7 downto 0),regB(7 downto 0),multiplier_out);--divider_origin_inst:divider_origin port map(clk,start,divider_ina,DATA_BUS,done,result(7 downto 0),divider_r);process(clk_ALU,nreset) variable count:integer:=0;begin if(nreset = '1')then start<='1'; regA <= "000000000"; regA <= "000000000"; result <= "000000000"; DATA_BUS <= "ZZZZZZZZ"; AC<= '0';CY<= '0';ZN<= '0';OV<= '0'; elsif(clk_ALU'event and clk_ALU = '1')then if(M_A='1'and M_B='0')then --锁存到A regA(7 downto 0) <= DATA_BUS; regA(8) <= '0'; elsif(M_A='0'and M_B='1')then --锁存到B regB(7 downto 0) <= DATA_BUS; regB(8) <= '0'; elsif(nALU_EN = '0')then case S is when "00000" => --直传 result <= regA; CY_signal <= result(8); when "00001" => --加法 result <= regA+regB+C0; CY_signal <= result(8); when "00010" => --减法 result <= regA - regB; CY_signal <= result(8); if(regA<regB)then OV_signal<='1';end if; when "00100" => --乘法 result(7 downto 0) <= multiplier_out(7 downto 0); CY_signal <= regA(8)xor regB(8); if(regA*regB>x"FF")then OV_signal<='1';end if; when "01000" => --除法 case count is when 0=> divider_ina<=regA(7 downto 0)&regB(7 downto 0); start<='0'; count:=count+1; when others=>null; end case; CY_signal <= regA(8)xor regB(8); when "10000" => --清零 regA <= "000000000"; result <= regA; CY_signal <= '0'; when "10001" => --与 result <= regA and regB; CY_signal <= '0'; when "10010" => --或 result <= regA or regB; CY_signal <= '0'; when "10100" => --A取非 result <= not regA; CY_signal <= '0'; when "11000" => --异或 result <= regA xor regB; CY_signal <= '0'; when others => result <= "000000000"; end case; case F_in is when "00" => DATA_BUS<= result(7 downto 0);--直接传送 when "01" => DATA_BUS<= result(8 downto 1);--带C右移 when "10" => DATA_BUS<= result(6 downto 0)&CY_signal;--循环左移 when "11" => DATA_BUS<= result(6 downto 0)&'0';--逻辑左移 when others => DATA_BUS<=(others=>'Z'); end case; CY <= CY_signal; if(result="000000000")then ZN_signal<='1';else ZN_signal<='0';end if; ZN<=ZN_signal; elsif(nPSW_EN = '0')then PSW_reg(0) <= CY_signal; PSW_reg(1) <= ZN_signal; DATA_BUS<= PSW_reg; else DATA_BUS <= "ZZZZZZZZ"; end if; end if;end process;process(regA,regB,result)begin regA_out<=regA(7 downto 0); regB_out<=regB(7 downto 0); result_out<=result(7 downto 0);end process;end Behavioral;</code></pre><p>testbench:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/23 13:34:13<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity ALU_tb is-- Port ( );end ALU_tb;architecture Behavioral of ALU_tb iscomponent ALU port( clk,clk_ALU : in std_logic; --全局时钟和ALU时钟 nreset : in std_logic; --全局复位信号 M_A,M_B : in std_logic; --暂存器控制信号 M_F : in std_logic; --程序状态字控制信号 nALU_EN : in std_logic; --alu运算结果输出使能 nPSW_EN : in std_logic; --psw输出使能 C0 : in std_logic; --进位输入 S : in std_logic_vector(4 downto 0); --运算类型和操作选择,M为最高位S(4),其余在低四位 F_in : in std_logic_vector(1 downto 0); --移位功能选择 DATA_BUS : inout std_logic_vector(7 downto 0); --数据总线 AC : out std_logic; --半进位标志 CY : out std_logic; --进位标志 ZN : out std_logic; --零标志 OV : out std_logic --溢出标志 );end component;signal clk,nclk2,nreset,m_A,m_B,m_F,nALU_EN,nPSW_EN,C0:std_logic;signal S :std_logic_vector(4 downto 0);signal F_in :std_logic_vector(1 downto 0); signal DATA_BUS:std_logic_vector(7 downto 0); signal AC : std_logic; --半进位标志signal CY : std_logic; --进位标志signal ZN : std_logic; --零标志signal OV : std_logic; --溢出标志beginALU_inst:ALU port map(clk,nclk2,nreset,m_A,m_B,m_F,nALU_EN,nPSW_EN,C0,S,F_in,DATA_BUS,AC,CY,ZN,OV);clock:processbegin clk<='1'; wait for 5ns; clk<='0'; wait for 5ns;end process;clock_nclk2:processbegin nclk2<='0'; wait for 10ns; nclk2<='1'; wait for 10ns;end process;test:processbegin nreset<='1'; M_A<='0'; M_B<='0'; M_F<='0'; nALU_EN<='1'; nPSW_EN<='1'; C0<='0'; S<="10010"; F_in<="00"; wait for 25ns; nreset<='0'; DATA_BUS<=X"04"; M_A<='1'; M_B<='0'; wait for 25ns; DATA_BUS<=X"02"; M_A<='0'; M_B<='1'; wait for 25ns;-- DATA_BUS<="ZZZZZZZZ"; M_A<='0'; M_B<='0'; nALU_EN<='0'; wait for 50ns; nALU_EN<='1'; nPSW_EN<='0'; wait; end process;end Behavioral;</code></pre><p>xdc:</p><p><br> #———————————————————————————-<br> #– Engineer: switch_swq<br> #– Create Date: 2024/04/23 21:55:51<br> #———————————————————————————-<br> #CLK_100M<br> set_property PACKAGE_PIN E10 [get_ports clk]<br> set_property IOSTANDARD LVCMOS18 [get_ports clk]</p><pre><code>#seg_dataset_property PACKAGE_PIN E26 [get_ports {seg_data[7]}]set_property PACKAGE_PIN J26 [get_ports {seg_data[6]}]set_property PACKAGE_PIN H26 [get_ports {seg_data[5]}]set_property PACKAGE_PIN H21 [get_ports {seg_data[4]}]set_property PACKAGE_PIN G21 [get_ports {seg_data[3]}]set_property PACKAGE_PIN H23 [get_ports {seg_data[2]}]set_property PACKAGE_PIN H24 [get_ports {seg_data[1]}]set_property PACKAGE_PIN J21 [get_ports {seg_data[0]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[7]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[6]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[5]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[4]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[3]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[2]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[1]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[0]}]#SW0~15set_property IOSTANDARD LVCMOS18 [get_ports {DATA_BUS[0]}]set_property IOSTANDARD LVCMOS18 [get_ports {DATA_BUS[1]}]set_property IOSTANDARD LVCMOS18 [get_ports {DATA_BUS[2]}]set_property IOSTANDARD LVCMOS18 [get_ports {DATA_BUS[3]}]set_property IOSTANDARD LVCMOS18 [get_ports {DATA_BUS[4]}]set_property IOSTANDARD LVCMOS18 [get_ports {DATA_BUS[5]}]set_property IOSTANDARD LVCMOS18 [get_ports {DATA_BUS[6]}]set_property IOSTANDARD LVCMOS18 [get_ports {DATA_BUS[7]}]set_property PACKAGE_PIN C9 [get_ports {DATA_BUS[0]}]set_property PACKAGE_PIN B9 [get_ports {DATA_BUS[1]}]set_property PACKAGE_PIN G11 [get_ports {DATA_BUS[2]}]set_property PACKAGE_PIN F10 [get_ports {DATA_BUS[3]}]set_property PACKAGE_PIN D10 [get_ports {DATA_BUS[4]}]set_property PACKAGE_PIN E11 [get_ports {DATA_BUS[5]}]set_property PACKAGE_PIN D11 [get_ports {DATA_BUS[6]}]set_property PACKAGE_PIN A14 [get_ports {DATA_BUS[7]}]#sw31~23set_property PACKAGE_PIN J8 [get_ports nreset]set_property IOSTANDARD LVCMOS18 [get_ports nreset]set_property PACKAGE_PIN J14 [get_ports nALU_EN]set_property IOSTANDARD LVCMOS18 [get_ports nALU_EN]set_property PACKAGE_PIN H9 [get_ports nPSW_EN]set_property IOSTANDARD LVCMOS18 [get_ports nPSW_EN]set_property PACKAGE_PIN H8 [get_ports M_A]set_property IOSTANDARD LVCMOS18 [get_ports M_A]set_property PACKAGE_PIN G10 [get_ports M_B]set_property IOSTANDARD LVCMOS18 [get_ports M_B]set_property PACKAGE_PIN G9 [get_ports M_F]set_property IOSTANDARD LVCMOS18 [get_ports M_F]set_property PACKAGE_PIN J13 [get_ports C0]set_property IOSTANDARD LVCMOS18 [get_ports C0]#SW16~20set_property IOSTANDARD LVCMOS18 [get_ports {S[0]}]set_property IOSTANDARD LVCMOS18 [get_ports {S[1]}]set_property IOSTANDARD LVCMOS18 [get_ports {S[2]}]set_property IOSTANDARD LVCMOS18 [get_ports {S[3]}]set_property IOSTANDARD LVCMOS18 [get_ports {S[4]}]set_property PACKAGE_PIN F8 [get_ports {S[0]}]set_property PACKAGE_PIN F9 [get_ports {S[1]}]set_property PACKAGE_PIN H11 [get_ports {S[2]}]set_property PACKAGE_PIN H12 [get_ports {S[3]}]set_property PACKAGE_PIN G14 [get_ports {S[4]}]#SW22~23set_property IOSTANDARD LVCMOS18 [get_ports {F_in[0]}]set_property IOSTANDARD LVCMOS18 [get_ports {F_in[1]}]set_property PACKAGE_PIN H14 [get_ports {F_in[0]}]set_property PACKAGE_PIN J11 [get_ports {F_in[1]}]#SEG_DIG1~16set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[15]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[14]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[13]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[12]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[11]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[10]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[9]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[8]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[7]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[6]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[5]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[4]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[3]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[2]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[1]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[0]}]set_property PACKAGE_PIN A23 [get_ports {seg_dig[15]}]set_property PACKAGE_PIN A24 [get_ports {seg_dig[14]}]set_property PACKAGE_PIN D26 [get_ports {seg_dig[13]}]set_property PACKAGE_PIN C26 [get_ports {seg_dig[12]}]set_property PACKAGE_PIN A20 [get_ports {seg_dig[11]}]set_property PACKAGE_PIN J25 [get_ports {seg_dig[10]}]set_property PACKAGE_PIN J24 [get_ports {seg_dig[9]}]set_property PACKAGE_PIN H22 [get_ports {seg_dig[8]}]set_property PACKAGE_PIN K21 [get_ports {seg_dig[7]}]set_property PACKAGE_PIN L23 [get_ports {seg_dig[6]}]set_property PACKAGE_PIN B25 [get_ports {seg_dig[5]}]set_property PACKAGE_PIN B26 [get_ports {seg_dig[4]}]set_property PACKAGE_PIN C24 [get_ports {seg_dig[3]}]set_property PACKAGE_PIN D21 [get_ports {seg_dig[2]}]set_property PACKAGE_PIN C22 [get_ports {seg_dig[1]}]set_property PACKAGE_PIN B20 [get_ports {seg_dig[0]}]</code></pre><h3 id="11-数据存储器-RAM-设计"><a href="#11-数据存储器-RAM-设计" class="headerlink" title="11.数据存储器 RAM 设计"></a>11.数据存储器 RAM 设计</h3><p><img src="https://i-blog.csdnimg.cn/blog_migrate/b0f5ae5f7d65bf36add50df2465e24d2.png"></p><p>高电平写操作有效,低电平读有效。其中 clk_RAM=nclk1 & W1,在组建 CPU 模块时使用。</p><p>1)读数据操作:clk_RAM 上升沿有效,RAM_CS 高电平,wr_nRD 低电平,nRAM_EN 低 电平,[AR] -> data 。</p><p>2)写数据操作:clk_RAM 上升沿有效,RAM_CS 高电平,wr_nRD 高电平有效,data->[AR]。</p><p>源码:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/23 21:55:51<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;</p><pre><code>entity RAM is generic( depth:integer:=7; width:integer:=8 ); port( clk_RAM:in STD_LOGIC; --RAM时钟信号 n_reset:in STD_LOGIC; --RAM选择信号 RAM_CS:in STD_LOGIC; --RAM片选信号 nRAM_EN:in STD_LOGIC; --RAM输出使能 Wr_nRD :in STD_LOGIC; --RAM读写信号 AR:in STD_LOGIC_VECTOR (depth-1 downto 0); --RAM地址信号 --DATA_BUS: inout STD_LOGIC_VECTOR (width-1 downto 0) --数据总线 data_in:in STD_LOGIC_VECTOR (width-1 downto 0); data_out:out STD_LOGIC_VECTOR (width-1 downto 0) );end RAM;architecture Behavioral of RAM istype ram_array is array(0 to 2**depth) of STD_LOGIC_VECTOR (width-1 downto 0);signal index : integer range 0 to 2**depth;signal SRAM:ram_array;beginprocess (n_reset,clk_RAM) begin index<=conv_integer(AR); if(n_reset='1') then --DATA_BUS<=(others=>'Z'); data_out<=(others=>'Z'); elsif(clk_RAM'event and clk_RAM='1') then if(RAM_CS='1')then if(Wr_nRD='1')then --SRAM(index)<=DATA_BUS; SRAM(index)<=data_in; elsif(nRAM_EN='0')then --DATA_BUS<=SRAM(index); data_out<=SRAM(index); else --DATA_BUS<=(others=>'Z'); data_out<=(others=>'Z'); end if; else --DATA_BUS<=(others=>'Z'); data_out<=(others=>'Z'); end if; end if;end process;end Behavioral;</code></pre><p>testbench:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/23 21:55:51<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;</p><pre><code>entity RAM_tb is-- Port ( );end RAM_tb;architecture Behavioral of RAM_tb iscomponent RAM generic( depth:positive:=7; width:positive:=8 ); Port ( clk_RAM:in STD_LOGIC; --RAM时钟信号 n_reset:in STD_LOGIC; --RAM选择信号 RAM_CS:in STD_LOGIC; --RAM片选信号 nRAM_EN:in STD_LOGIC; --RAM输出使能 Wr_nRD :in STD_LOGIC; --RAM读写信号 AR:in STD_LOGIC_VECTOR (depth-1 downto 0); --RAM地址信号 DATA_BUS: inout STD_LOGIC_VECTOR (width-1 downto 0) --数据总线 --data_in:in STD_LOGIC_VECTOR (width-1 downto 0); --data_out:out STD_LOGIC_VECTOR (width-1 downto 0)) );end component;signal clk_RAM,n_reset,RAM_CS,nRAM_EN,Wr_nRD:std_logic;signal AR:std_logic_vector(6 downto 0);signal DATA_BUS:std_logic_vector(7 downto 0);signal data_in,data_out:std_logic_vector(7 downto 0);beginRAM_inst:RAM generic map(7,8)port map(clk_RAM=>clk_RAM,n_reset=>n_reset,RAM_CS=>RAM_CS,nRAM_EN=>nRAM_EN,Wr_nRD=>Wr_nRD,AR=>AR,DATA_BUS=>DATA_BUS);--RAM_inst:RAM generic map(7,8)port map(clk_RAM=>clk_RAM,n_reset=>n_reset,RAM_CS=>RAM_CS,nRAM_EN=>nRAM_EN,Wr_nRD=>Wr_nRD,AR=>AR,data_in=>data_in,data_out=>data_out);clock:processbegin clk_RAM<='1'; wait for 5ns; clk_RAM<='0'; wait for 5ns;end process;test:processbegin n_reset<='1'; wait for 25ns; n_reset<='0'; RAM_CS<='1'; nRAM_EN<='1'; Wr_nRD<='1'; AR<="0000000"; wait for 25ns; DATA_BUS<=x"FF"; wait for 25ns; AR<="0000001"; wait for 25ns; DATA_BUS<=x"EE"; wait for 25ns; nRAM_EN<='0'; Wr_nRD<='0'; AR<="0000000"; wait for 25ns; AR<="0000001"; wait;end process;end Behavioral;</code></pre><p>xdc:</p><p><br> #———————————————————————————-<br> #– Engineer: switch_swq<br> #– Create Date: 2024/04/23 21:55:51<br> #———————————————————————————-<br> #sw0~6<br> set_property IOSTANDARD LVCMOS18 [get_ports {AR[0]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {AR[1]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {AR[2]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {AR[3]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {AR[4]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {AR[5]}]<br> set_property IOSTANDARD LVCMOS18 [get_ports {AR[6]}]<br> set_property PACKAGE_PIN C9 [get_ports {AR[0]}]<br> set_property PACKAGE_PIN B9 [get_ports {AR[1]}]<br> set_property PACKAGE_PIN G11 [get_ports {AR[2]}]<br> set_property PACKAGE_PIN F10 [get_ports {AR[3]}]<br> set_property PACKAGE_PIN D10 [get_ports {AR[4]}]<br> set_property PACKAGE_PIN E11 [get_ports {AR[5]}]<br> set_property PACKAGE_PIN D11 [get_ports {AR[6]}]</p><pre><code>#LED#set_property IOSTANDARD LVCMOS33 [get_ports {DATA_BUS[0]}]#set_property IOSTANDARD LVCMOS33 [get_ports {DATA_BUS[1]}]#set_property IOSTANDARD LVCMOS33 [get_ports {DATA_BUS[2]}]#set_property IOSTANDARD LVCMOS33 [get_ports {DATA_BUS[3]}]#set_property IOSTANDARD LVCMOS33 [get_ports {DATA_BUS[4]}]#set_property IOSTANDARD LVCMOS33 [get_ports {DATA_BUS[5]}]#set_property IOSTANDARD LVCMOS33 [get_ports {DATA_BUS[6]}]#set_property IOSTANDARD LVCMOS33 [get_ports {DATA_BUS[7]}]#set_property PACKAGE_PIN G16 [get_ports {DATA_BUS[0]}]#set_property PACKAGE_PIN H16 [get_ports {DATA_BUS[1]}]#set_property PACKAGE_PIN D16 [get_ports {DATA_BUS[2]}]#set_property PACKAGE_PIN D15 [get_ports {DATA_BUS[3]}]#set_property PACKAGE_PIN C18 [get_ports {DATA_BUS[4]}]#set_property PACKAGE_PIN C17 [get_ports {DATA_BUS[5]}]#set_property PACKAGE_PIN B19 [get_ports {DATA_BUS[6]}]#set_property PACKAGE_PIN C19 [get_ports {DATA_BUS[7]}]#sw31set_property PACKAGE_PIN J8 [get_ports n_reset]set_property IOSTANDARD LVCMOS18 [get_ports n_reset]#sw30~28set_property PACKAGE_PIN J14 [get_ports RAM_CS]set_property IOSTANDARD LVCMOS18 [get_ports RAM_CS]set_property PACKAGE_PIN H9 [get_ports nRAM_EN]set_property IOSTANDARD LVCMOS18 [get_ports nRAM_EN]set_property PACKAGE_PIN H8 [get_ports Wr_nRD]set_property IOSTANDARD LVCMOS18 [get_ports Wr_nRD]#clkset_property PACKAGE_PIN E10 [get_ports clk_RAM]set_property IOSTANDARD LVCMOS18 [get_ports clk_RAM]#LEDset_property IOSTANDARD LVCMOS33 [get_ports {data_out[0]}]set_property IOSTANDARD LVCMOS33 [get_ports {data_out[1]}]set_property IOSTANDARD LVCMOS33 [get_ports {data_out[2]}]set_property IOSTANDARD LVCMOS33 [get_ports {data_out[3]}]set_property IOSTANDARD LVCMOS33 [get_ports {data_out[4]}]set_property IOSTANDARD LVCMOS33 [get_ports {data_out[5]}]set_property IOSTANDARD LVCMOS33 [get_ports {data_out[6]}]set_property IOSTANDARD LVCMOS33 [get_ports {data_out[7]}]set_property PACKAGE_PIN G16[get_ports {data_out[0]}]set_property PACKAGE_PIN H16 [get_ports {data_out[1]}]set_property PACKAGE_PIN D16 [get_ports {data_out[2]}]set_property PACKAGE_PIN D15 [get_ports {data_out[3]}]set_property PACKAGE_PIN C18 [get_ports {data_out[4]}]set_property PACKAGE_PIN C17 [get_ports {data_out[5]}]set_property PACKAGE_PIN B19 [get_ports {data_out[6]}]set_property PACKAGE_PIN C19 [get_ports {data_out[7]}]set_property IOSTANDARD LVCMOS18 [get_ports {data_in[0]}]set_property IOSTANDARD LVCMOS18 [get_ports {data_in[1]}]set_property IOSTANDARD LVCMOS18 [get_ports {data_in[2]}]set_property IOSTANDARD LVCMOS18 [get_ports {data_in[3]}]set_property IOSTANDARD LVCMOS18 [get_ports {data_in[4]}]set_property IOSTANDARD LVCMOS18 [get_ports {data_in[5]}]set_property IOSTANDARD LVCMOS18 [get_ports {data_in[6]}]set_property IOSTANDARD LVCMOS18 [get_ports {data_in[7]}]set_property PACKAGE_PIN B10 [get_ports {data_in[0]}]set_property PACKAGE_PIN A10 [get_ports {data_in[1]}]set_property PACKAGE_PIN B15 [get_ports {data_in[2]}]set_property PACKAGE_PIN A15 [get_ports {data_in[3]}]set_property PACKAGE_PIN A13 [get_ports {data_in[4]}]set_property PACKAGE_PIN A12 [get_ports {data_in[5]}]set_property PACKAGE_PIN D8 [get_ports {data_in[6]}]set_property PACKAGE_PIN D9 [get_ports {data_in[7]}]</code></pre><h3 id="12-堆栈指针-SP-设计"><a href="#12-堆栈指针-SP-设计" class="headerlink" title="12.堆栈指针 SP 设计"></a>12.堆栈指针 SP 设计</h3><p><img src="https://i-blog.csdnimg.cn/blog_migrate/450ff7787e4fbc15befc93420b279e3f.png"></p><p>其中 clk_SP=nclk2,在组建 CPU 模块时使用。</p><p>1)数据存储功能:clk_SP 上升沿有效,SP_CS 高电平,nSP_EN 高电平,data->SP。</p><p>2)加 1 功能:clk_SP 上升沿有效,SP_CS 高电平,SP_UP 高电平,nSP_EN 低电平有效,SP+1->SP,SP->AR。</p><p>3)减 1 功能:clk_SP 上升沿有效,SP_CS 高电平,SP_DN 高电平,nSP_EN 低电平有效, SP-1->SP,SP->AR。</p><p>源码:</p><p>顶层:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/24 13:45:37<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity SP_test is Port( clk:in std_logic; --时钟信号 nreset:in std_logic; --复位信号 SP_CS:in std_logic; --SP选择信号 SP_UP:in std_logic; --SP+1控制 SP_DN:in std_logic; --SP-1控制 nSP_EN:in std_logic; --SP输出使能 key_in:in std_logic; --按键时钟 AR:out std_logic_vector(6 downto 0);--SP指向RAM地址 --data_in:in std_logic_vector(7 downto 0); --data_out:out std_logic_vector(7 downto 0) DATA_BUS:inout std_logic_vector(7 downto 0) --数据总线 );end SP_test;architecture Behavioral of SP_test iscomponent SP Port( clk_SP:in std_logic; --SP时钟信号 nreset:in std_logic; --复位信号 SP_CS:in std_logic; --SP选择信号 SP_UP:in std_logic; --SP+1控制 SP_DN:in std_logic; --SP-1控制 nSP_EN:in std_logic; --SP输出使能 AR:out std_logic_vector(6 downto 0);--SP指向RAM地址 --data_in:in std_logic_vector(7 downto 0); --data_out:out std_logic_vector(7 downto 0) DATA_BUS:inout std_logic_vector(7 downto 0) --数据总线 );end component;component key_stroke generic(CLK_FRE:integer:=100000000); Port ( clk:in std_logic; reset:in std_logic; key_in:in std_logic; output:out std_logic );end component;signal clk_line:STD_LOGIC;beginkey_stroke_inst:key_stroke generic map(100000000)port map(clk,nreset,key_in,clk_line);SP_inst:SP PORT MAP(clk_line,nreset,SP_CS,SP_UP,SP_DN,nSP_EN,AR,DATA_BUS);</code></pre><p><br> end Behavioral;</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/4ca7b953040d5420bd324dcceae3363c.png"></p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/24 10:52:17<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;</p><pre><code>entity SP is Port( clk_SP:in std_logic; --SP时钟信号 nreset:in std_logic; --复位信号 SP_CS:in std_logic; --SP选择信号 SP_UP:in std_logic; --SP+1控制 SP_DN:in std_logic; --SP-1控制 nSP_EN:in std_logic; --SP输出使能 AR:out std_logic_vector(6 downto 0);--SP指向RAM地址 --data_in:in std_logic_vector(7 downto 0); --data_out:out std_logic_vector(7 downto 0) DATA_BUS:inout std_logic_vector(7 downto 0) --数据总线 );end SP;architecture Behavioral of SP issignal SP_p:std_logic_vector(6 downto 0);--指向RAM地址beginprocess(clk_SP,nreset)begin if(nreset='0')then AR<=(others=>'Z'); elsif(clk_SP='1'and clk_SP'event)then if(SP_CS='1')then if(nSP_EN='1')then --SP_p<=data_in; SP_p<=DATA_BUS(6 downto 0); else if(SP_UP='1'and SP_DN='0')then SP_p<=SP_p+1; elsif(SP_UP='0'and SP_DN='1')then SP_p<=SP_p-1; end if; --data_out<=SP_p; AR<=SP_p; end if; else AR<=(others=>'Z'); end if; end if;end process;end Behavioral;</code></pre><p>testbench:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/24 13:29:19<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity SP_tb is-- Port ( );end SP_tb;architecture Behavioral of SP_tb iscomponent SP Port( clk_SP:in std_logic; --SP时钟信号 nreset:in std_logic; --复位信号 SP_CS:in std_logic; --SP选择信号 SP_UP:in std_logic; --SP+1控制 SP_DN:in std_logic; --SP-1控制 nSP_EN:in std_logic; --SP输出使能 AR:out std_logic_vector(6 downto 0);--SP指向RAM地址 --data_in:in std_logic_vector(7 downto 0); --data_out:out std_logic_vector(7 downto 0) DATA_BUS:inout std_logic_vector(7 downto 0) --数据总线 );end component;signal clk_SP,nreset,SP_CS,SP_UP,SP_DN,nSP_EN:STD_LOGIC;signal AR:std_logic_vector(6 downto 0);signal DATA_BUS:std_logic_vector(7 downto 0);beginSP_inst:SP PORT MAP(clk_SP,nreset,SP_CS,SP_UP,SP_DN,nSP_EN,AR,DATA_BUS);clock:processbegin clk_SP<='1'; wait for 5ns; clk_SP<='0'; wait for 5ns;end process;test:processbegin nreset<='0'; SP_CS<='1'; SP_UP<='0'; SP_DN<='0'; nSP_EN<='1'; DATA_BUS<="ZZZZZZZZ"; wait for 25ns; DATA_BUS<=x"0F"; nreset<='1'; wait for 25ns; SP_UP<='1'; SP_DN<='0'; nSP_EN<='0'; wait for 25ns; SP_UP<='1'; SP_DN<='0'; nSP_EN<='0'; wait for 25ns; SP_UP<='0'; SP_DN<='1'; nSP_EN<='0'; wait for 25ns; wait; end process;end Behavioral;</code></pre><p>xdc:</p><p><br> #clk<br> set_property PACKAGE_PIN E10 [get_ports clk]<br> set_property IOSTANDARD LVCMOS18 [get_ports clk]</p><pre><code>#sw31~28set_property PACKAGE_PIN J8 [get_ports nreset]set_property IOSTANDARD LVCMOS18 [get_ports nreset]set_property PACKAGE_PIN J14 [get_ports SP_CS]set_property IOSTANDARD LVCMOS18 [get_ports SP_CS]set_property PACKAGE_PIN H9 [get_ports key_in]set_property IOSTANDARD LVCMOS18 [get_ports key_in]set_property PACKAGE_PIN H8 [get_ports nSP_EN]set_property IOSTANDARD LVCMOS18 [get_ports nSP_EN]set_property PACKAGE_PIN G10 [get_ports SP_UP ]set_property IOSTANDARD LVCMOS18 [get_ports SP_UP ]set_property PACKAGE_PIN G9 [get_ports SP_DN ]set_property IOSTANDARD LVCMOS18 [get_ports SP_DN ]#LED0~6set_property IOSTANDARD LVCMOS33 [get_ports {AR[0]}]set_property IOSTANDARD LVCMOS33 [get_ports {AR[1]}]set_property IOSTANDARD LVCMOS33 [get_ports {AR[2]}]set_property IOSTANDARD LVCMOS33 [get_ports {AR[3]}]set_property IOSTANDARD LVCMOS33 [get_ports {AR[4]}]set_property IOSTANDARD LVCMOS33 [get_ports {AR[5]}]set_property IOSTANDARD LVCMOS33 [get_ports {AR[6]}]set_property PACKAGE_PIN G16[get_ports {AR[0]}]set_property PACKAGE_PIN H16 [get_ports {AR[1]}]set_property PACKAGE_PIN D16 [get_ports {AR[2]}]set_property PACKAGE_PIN D15 [get_ports {AR[3]}]set_property PACKAGE_PIN C18 [get_ports {AR[4]}]set_property PACKAGE_PIN C17 [get_ports {AR[5]}]set_property PACKAGE_PIN B19 [get_ports {AR[6]}]#SW0~7set_property IOSTANDARD LVCMOS18 [get_ports {DATA_BUS[0]}]set_property IOSTANDARD LVCMOS18 [get_ports {DATA_BUS[1]}]set_property IOSTANDARD LVCMOS18 [get_ports {DATA_BUS[2]}]set_property IOSTANDARD LVCMOS18 [get_ports {DATA_BUS[3]}]set_property IOSTANDARD LVCMOS18 [get_ports {DATA_BUS[4]}]set_property IOSTANDARD LVCMOS18 [get_ports {DATA_BUS[5]}]set_property IOSTANDARD LVCMOS18 [get_ports {DATA_BUS[6]}]set_property IOSTANDARD LVCMOS18 [get_ports {DATA_BUS[7]}]set_property PACKAGE_PIN C9 [get_ports {DATA_BUS[0]}]set_property PACKAGE_PIN B9 [get_ports {DATA_BUS[1]}]set_property PACKAGE_PIN G11 [get_ports {DATA_BUS[2]}]set_property PACKAGE_PIN F10 [get_ports {DATA_BUS[3]}]set_property PACKAGE_PIN D10 [get_ports {DATA_BUS[4]}]set_property PACKAGE_PIN E11 [get_ports {DATA_BUS[5]}]set_property PACKAGE_PIN D11 [get_ports {DATA_BUS[6]}]set_property PACKAGE_PIN A14 [get_ports {DATA_BUS[7]}]</code></pre><h3 id="13-采用硬件描述语言语言设计-IO-模块"><a href="#13-采用硬件描述语言语言设计-IO-模块" class="headerlink" title="13.采用硬件描述语言语言设计 IO 模块"></a>13.采用硬件描述语言语言设计 IO 模块</h3><p><img src="https://i-blog.csdnimg.cn/blog_migrate/de38a24f3d908b663a479d455c4f613d.png"></p><p>其中 clk_P0=nclk2,在组建 CPU 模块时使用。</p><p>1)输入锁存:</p><pre><code> clk_PO 上升沿有效,P0_CS 高电平,P0_IEN 低电平, P0_IN-> 暂存器,RIEN 低电平, 暂存器 ->数据总线(data)。</code></pre><p>2)输出锁存:</p><pre><code> clk_PO 上升沿有效,P0_CS 高电平,P0_OEN 低电平, 数据总线(data)->暂存器,ROEN 低电平,暂存器 ->P0_OUT。</code></pre><p>源码:</p><p>顶层:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/24 14:37:22<br> ———————————————————————————-</p><pre><code>library IEEE;use IEEE.STD_LOGIC_1164.ALL;entity IO_test is Port( clk:in std_logic; --IO时钟信号 nreset:in std_logic; --IO复位信号 IO_CS:in std_logic; --IO选择信号 IO_IEN:in std_logic; --IO输入使能 IO_OEN:in std_logic; --IO输出使能 RI_EN:in std_logic; --IO缓存器输入使能 RO_EN:in std_logic; --IO缓存器输出使能 IO_in:in std_logic_vector(7 downto 0); --IO输入 seg_dig:out std_logic_vector(15 downto 0); seg_data:out std_logic_vector(7 downto 0)--管脚连接顺序:dp,g,f,e,d,c,b,a );end IO_test;architecture Behavioral of IO_test iscomponent IO Port( clk_IO:in std_logic; --IO时钟信号 nreset:in std_logic; --IO复位信号 IO_CS:in std_logic; --IO选择信号 IO_IEN:in std_logic; --IO输入使能 IO_OEN:in std_logic; --IO输出使能 RI_EN:in std_logic; --IO缓存器输入使能 RO_EN:in std_logic; --IO缓存器输出使能 IO_in:in std_logic_vector(7 downto 0); --IO输入 IO_out:out std_logic_vector(7 downto 0); --IO输出 DATA_BUS:inout std_logic_vector(7 downto 0) --数据总线 );end component;component clk_div generic( DIV_NUM:integer:=10000 ); Port ( rst:in std_logic; clk_in:in std_logic; clk_out:out std_logic );end component;component seg_dis port( rst,clk:in std_logic; data_in_A,data_in_B,data_in_C,data_in_D:in std_logic_vector(15 downto 0); seg_dig:out std_logic_vector(15 downto 0); seg_data:out std_logic_vector(7 downto 0)--管脚连接顺序:dp,g,f,e,d,c,b,a );end component;signal clk_line,rst_seg:std_logic;signal data_in_A,data_in_B,data_in_C,data_in_D:std_logic_vector(15 downto 0); signal IO_out,DATA_BUS:std_logic_vector(7 downto 0);beginIO_inst:IO port map(clk,nreset,IO_CS,IO_IEN,IO_OEN,RI_EN,RO_EN,IO_in,IO_out,DATA_BUS);clk_div_inst:clk_div generic map(10000)port map(nreset,clk,clk_line);seg_dis_inst:seg_dis port map(nreset,clk_line,data_in_A,data_in_B,data_in_C,data_in_D,seg_dig,seg_data);process(IO_in,IO_out,DATA_BUS)begin data_in_A<="00000000"&IO_in; data_in_B<="00000000"&DATA_BUS; data_in_C<="00000000"&IO_out; data_in_D<="0000000000000000";end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/7c0424c57486f62ce1df707bbc1d0f14.png"></p><p><br> ———————————————————————————-<br> – Engineer:<br> – Create Date: 2024/04/24 14:06:31<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity IO is Port( clk_IO:in std_logic; --IO时钟信号 nreset:in std_logic; --IO复位信号 IO_CS:in std_logic; --IO选择信号 IO_IEN:in std_logic; --IO输入使能 IO_OEN:in std_logic; --IO输出使能 RI_EN:in std_logic; --IO缓存器输入使能 RO_EN:in std_logic; --IO缓存器输出使能 IO_in:in std_logic_vector(7 downto 0); --IO输入 IO_out:out std_logic_vector(7 downto 0); --IO输出 DATA_BUS:inout std_logic_vector(7 downto 0) --数据总线 );end IO;architecture Behavioral of IO issignal reg:std_logic_vector(7 downto 0);beginprocess(nreset,clk_IO)begin if(nreset='0')then IO_out<="ZZZZZZZZ";DATA_BUS<="ZZZZZZZZ"; elsif(clk_IO='1'and clk_IO'event)then if(IO_CS='1')then if(IO_IEN='0')then reg<=IO_in; if(RI_EN='0')then DATA_BUS<=reg;end if; elsif(IO_OEN='0')then reg<=DATA_BUS; if(RO_EN='0')then IO_out<=reg;END IF; end if; else IO_out<="ZZZZZZZZ";DATA_BUS<="ZZZZZZZZ"; end if; end if;end process;end Behavioral;</code></pre><p>xdc:</p><p><br> #———————————————————————————-<br> #– Engineer: switch_swq<br> #– Create Date: 2024/04/24 15:50:00<br> #———————————————————————————-<br> #CLK_100M<br> set_property PACKAGE_PIN E10 [get_ports clk]<br> set_property IOSTANDARD LVCMOS18 [get_ports clk]</p><pre><code>#seg_dataset_property PACKAGE_PIN E26 [get_ports {seg_data[7]}]set_property PACKAGE_PIN J26 [get_ports {seg_data[6]}]set_property PACKAGE_PIN H26 [get_ports {seg_data[5]}]set_property PACKAGE_PIN H21 [get_ports {seg_data[4]}]set_property PACKAGE_PIN G21 [get_ports {seg_data[3]}]set_property PACKAGE_PIN H23 [get_ports {seg_data[2]}]set_property PACKAGE_PIN H24 [get_ports {seg_data[1]}]set_property PACKAGE_PIN J21 [get_ports {seg_data[0]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[7]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[6]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[5]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[4]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[3]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[2]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[1]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[0]}]#SEG_DIG1~16set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[15]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[14]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[13]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[12]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[11]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[10]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[9]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[8]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[7]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[6]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[5]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[4]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[3]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[2]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[1]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[0]}]set_property PACKAGE_PIN A23 [get_ports {seg_dig[15]}]set_property PACKAGE_PIN A24 [get_ports {seg_dig[14]}]set_property PACKAGE_PIN D26 [get_ports {seg_dig[13]}]set_property PACKAGE_PIN C26 [get_ports {seg_dig[12]}]set_property PACKAGE_PIN A20 [get_ports {seg_dig[11]}]set_property PACKAGE_PIN J25 [get_ports {seg_dig[10]}]set_property PACKAGE_PIN J24 [get_ports {seg_dig[9]}]set_property PACKAGE_PIN H22 [get_ports {seg_dig[8]}]set_property PACKAGE_PIN K21 [get_ports {seg_dig[7]}]set_property PACKAGE_PIN L23 [get_ports {seg_dig[6]}]set_property PACKAGE_PIN B25 [get_ports {seg_dig[5]}]set_property PACKAGE_PIN B26 [get_ports {seg_dig[4]}]set_property PACKAGE_PIN C24 [get_ports {seg_dig[3]}]set_property PACKAGE_PIN D21 [get_ports {seg_dig[2]}]set_property PACKAGE_PIN C22 [get_ports {seg_dig[1]}]set_property PACKAGE_PIN B20 [get_ports {seg_dig[0]}]#SW0~7set_property IOSTANDARD LVCMOS18 [get_ports {IO_in[0]}]set_property IOSTANDARD LVCMOS18 [get_ports {IO_in[1]}]set_property IOSTANDARD LVCMOS18 [get_ports {IO_in[2]}]set_property IOSTANDARD LVCMOS18 [get_ports {IO_in[3]}]set_property IOSTANDARD LVCMOS18 [get_ports {IO_in[4]}]set_property IOSTANDARD LVCMOS18 [get_ports {IO_in[5]}]set_property IOSTANDARD LVCMOS18 [get_ports {IO_in[6]}]set_property IOSTANDARD LVCMOS18 [get_ports {IO_in[7]}]set_property PACKAGE_PIN C9 [get_ports {IO_in[0]}]set_property PACKAGE_PIN B9 [get_ports {IO_in[1]}]set_property PACKAGE_PIN G11 [get_ports {IO_in[2]}]set_property PACKAGE_PIN F10 [get_ports {IO_in[3]}]set_property PACKAGE_PIN D10 [get_ports {IO_in[4]}]set_property PACKAGE_PIN E11 [get_ports {IO_in[5]}]set_property PACKAGE_PIN D11 [get_ports {IO_in[6]}]set_property PACKAGE_PIN A14 [get_ports {IO_in[7]}]#sw31~24set_property PACKAGE_PIN J8 [get_ports nreset]set_property IOSTANDARD LVCMOS18 [get_ports nreset]set_property PACKAGE_PIN J14 [get_ports IO_CS]set_property IOSTANDARD LVCMOS18 [get_ports IO_CS]set_property PACKAGE_PIN H9 [get_ports IO_IEN]set_property IOSTANDARD LVCMOS18 [get_ports IO_IEN]set_property PACKAGE_PIN H8 [get_ports IO_OEN]set_property IOSTANDARD LVCMOS18 [get_ports IO_OEN]set_property PACKAGE_PIN G10 [get_ports RI_EN]set_property IOSTANDARD LVCMOS18 [get_ports RI_EN]set_property PACKAGE_PIN G9 [get_ports RO_EN]set_property IOSTANDARD LVCMOS18 [get_ports RO_EN]</code></pre><p><br> </p><h3 id="14-微控制器设计"><a href="#14-微控制器设计" class="headerlink" title="14.微控制器设计"></a>14.微控制器设计</h3><p>微程序控制器基本原理:</p><pre><code> 1)将指令分解为基本的微命令序列,把操作控制信号编制成微指令,存放到控制存储器 (CM)。 2)运行时,从控存中取出微指令,产生指令运行所需的操作控制信号。</code></pre><p>微程序控制器基本结构:</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/3df769d2ac5eb7d9b1a2a850829c1e56.png"></p><p> 控制存储器 CM –存放微程序</p><p> 微指令寄存器 µIR –存放现行微指令</p><p> 微地址形成电路–提供下一条微地址</p><p> 微地址寄存器 µAR–存放现在微地址</p><p>控制信号设计:</p><pre><code> • 39 条控制信号(39 位编码) • 27 条指令(5 位编码)->8 位微地址</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/29292e122740addc20eb4a530ec67bd0.png"></p><p>其中 clk_MC=clk2 & W0,在组建 CPU 模块时使用。</p><p>源码:</p><p>顶层:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/25 16:09:02<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity uC_test is Port( clk:in std_logic; --微程序控制器时钟信号 nreset:in std_logic; --复位信号 M_uA:in std_logic; --微地址控制信号 IR:in std_logic_vector(7 downto 2); --IR操作码信息 CMROM_CS:in std_logic; --控制存储器选通信号 seg_dig : out std_logic_vector(15 downto 0); seg_data : out std_logic_vector(7 downto 0) );end uC_test;architecture Behavioral of uC_test iscomponent uC Port( clk_uC:in std_logic; --微程序控制器时钟信号 nreset:in std_logic; --复位信号 M_uA:in std_logic; --微地址控制信号 IR:in std_logic_vector(7 downto 2); --IR操作码信息 CMROM_CS:in std_logic; --控制存储器选通信号 CM:out std_logic_vector(47 downto 8) --控制信号输出 );end component;component clock Port( clk,rst:in std_logic; clk1,nclk1:out std_logic; --clk clk2,nclk2:out std_logic; --clk二分频 w0,w1,w2,w3:out std_logic --节拍信号 );end component;component clk_div generic( DIV_NUM:integer:=10000 ); Port ( rst:in std_logic; clk_in:in std_logic; clk_out:out std_logic );end component;component seg_dis port( rst,clk:in std_logic; data_in_A,data_in_B,data_in_C,data_in_D:in std_logic_vector(15 downto 0); seg_dig:out std_logic_vector(15 downto 0); seg_data:out std_logic_vector(7 downto 0)--管脚连接顺序:dp,g,f,e,d,c,b,a );end component;signal clk_line,clk_line2,clk_uC,clk2,w0:std_logic;signal data_in_A,data_in_B,data_in_C,data_in_D:std_logic_vector(15 downto 0); signal CM_line:std_logic_vector(47 downto 8);beginuC_inst:uC port map(clk_uC,nreset,M_uA,IR,CMROM_CS,CM_line);clock_inst:clock port map(clk=>clk_line2,rst=>nreset,clk2=>clk2,w0=>w0);clk_div_inst:clk_div generic map(10000)port map(nreset,clk,clk_line);clk_div_inst2:clk_div generic map(10000000)port map(nreset,clk,clk_line2);seg_dis_inst:seg_dis port map(nreset,clk_line,data_in_A,data_in_B,data_in_C,data_in_D,seg_dig,seg_data);process(clk2,w0)begin clk_uC<=clk2 and w0;end process;process(IR,CM_line)begin data_in_A<="0000000000"&IR; data_in_B<=CM_line(15 downto 8)&"00000000"; data_in_C<=CM_line(31 downto 16); data_in_D<=CM_line(47 downto 32);end process;end Behavioral;</code></pre><p> </p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/ef02d5402b0594182dafe67debe07644.png"></p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/24 16:22:50<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity uC is Port( clk_uC:in std_logic; --微程序控制器时钟信号 nreset:in std_logic; --复位信号 M_uA:in std_logic; --微地址控制信号 IR:in std_logic_vector(7 downto 2); --IR操作码信息 CMROM_CS:in std_logic; --控制存储器选通信号 CM:out std_logic_vector(47 downto 8) --控制信号输出 );end uC;architecture Behavioral of uC iscomponent uC_uA Port( clk:in std_logic; nreset:in std_logic; --复位信号 M_uA:in std_logic; IR:in std_logic_vector(7 downto 2); --IR操作码信息 uA_in:in std_logic_vector(7 downto 0); --uIR传送的微地址 uA_out:out std_logic_vector(7 downto 0) --下一条微指令的地址 );end component;component uC_uAR Port( clk:in std_logic; nreset: in std_logic; uAR_in:in std_logic_vector(7 downto 0); --uA传送的微地址 uAR_out:out std_logic_vector(7 downto 0) --送至uCM的地址 );end component;component uC_CM generic( width:integer := 48; --位宽 depth:integer := 8 --深度 ); port( clk:in std_logic; addr:in std_logic_vector(depth-1 downto 0); ----uC_ROM地址 CMROM_CS:in std_logic; --uC_ROM输出使能 data_out:out std_logic_vector(width-1 downto 0) --uC_ROM输出 );end component;component uC_uIR Port ( clk:in std_logic; CM:in std_logic_vector(47 downto 0); uA:out std_logic_vector(7 downto 0); uI:out std_logic_vector(47 downto 8) );end component;signal uA_in,uA_out,uAR_out:std_logic_vector(7 downto 0); signal CM_line:std_logic_vector(47 downto 0);beginuC_uA_inst:uC_uA port map(clk_uC,nreset,M_uA,IR,uA_in,uA_out);uC_uAR_inst:uC_uAR port map(clk_uC,nreset,uA_out,uAR_out);uC_uCM_inst:uC_CM generic map(48,8)port map(clk_uC,uAR_out,CMROM_CS,CM_line);uC_uIR_inst:uC_uIR port map(clk_uC,CM_line,uA_in,CM);end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/63008edd2b3325b6e6ef2c8e700998d8.png"></p><p><img src="https://img-blog.csdnimg.cn/direct/e135b733d411449797e2018f91c18b99.png"></p><p> 模块:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/24 16:22:50<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.std_logic_unsigned.all;<br> use IEEE.std_logic_textio.all;<br> use STD.textio.all;</p><pre><code>entity uC_CM is generic( width:integer := 48; --位宽 depth:integer := 8 --深度 ); port( clk:in std_logic; addr:in std_logic_vector(depth-1 downto 0); ----uC_ROM地址 CMROM_CS:in std_logic; --uC_ROM输出使能 data_out:out std_logic_vector(width-1 downto 0) --uC_ROM输出 );end uC_CM;architecture Behavioral of uC_CM istype matrix is array(integer range<>) of std_logic_vector(width-1 downto 0);signal uC_ROM : matrix(0 to 2**depth-1);procedure load_rom(signal data_word:out matrix) is file romfile:text open read_mode is "uC_ROM.txt"; variable lbuf:line; variable i:integer := 0; --循环变量 variable fdata:std_logic_vector(width-1 downto 0);begin while(not endfile(romfile) and i<2**depth) loop readline(romfile,lbuf); -- 逐行读数据 read(lbuf,fdata); -- 将行数据保存到变量fdata data_word(i)<=fdata; -- 将fdata保存到内存信号量中 i := i+1; end loop;end procedure;beginload_rom(uC_ROM);data_out <= uC_ROM(conv_integer(addr)) when CMROM_CS='1'else(others=>'0');end Behavioral;</code></pre><p><br><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/24 16:22:50<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity uC_uA is Port( clk:in std_logic; nreset:in std_logic; --复位信号 M_uA:in std_logic; IR:in std_logic_vector(7 downto 2); --IR操作码信息 uA_in:in std_logic_vector(7 downto 0); --uIR传送的微地址 uA_out:out std_logic_vector(7 downto 0) --下一条微指令的地址 );end uC_uA;architecture Behavioral of uC_uA isbeginprocess(clk,nreset)begin if(nreset='0')then uA_out<=(others=>'0'); elsif(clk='1'and clk'event)then if(M_uA='1')then uA_out<=IR&"00"; else uA_out<=uA_in; end if; end if;end process;end Behavioral;</code></pre><p><br><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/24 16:22:50<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity uC_uAR is Port( clk:in std_logic; nreset: in std_logic; uAR_in:in std_logic_vector(7 downto 0); --uA传送的微地址 uAR_out:out std_logic_vector(7 downto 0) --送至uCM的地址 );end uC_uAR;architecture Behavioral of uC_uAR isbeginprocess(clk,nreset)begin if(nreset='0')then uAR_out<=(others=>'0'); elsif(clk='1'and clk'event)then uAR_out<=uAR_in; end if;end process;end Behavioral;</code></pre><p><br><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/24 16:22:50<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity uC_uIR is Port ( clk:in std_logic; CM:in std_logic_vector(47 downto 0); uA:out std_logic_vector(7 downto 0); uI:out std_logic_vector(47 downto 8) );end uC_uIR;architecture Behavioral of uC_uIR isbeginuA<=CM(7 downto 0);uI<=CM(47 downto 8);end Behavioral;</code></pre><p> uC_ROM.txt:</p><p><br> 100000000000000000000000000000000000000000000001<br> 010000000000000000000000000000000000000000000010<br> 001000000000000000000000000000000000000000000011<br> 000100000000000000000000000000000000000000000100<br> 000010000000000000000000000000000000000000000101<br> 000001000000000000000000000000000000000000000110<br> 000000100000000000000000000000000000000000000111<br> 000000010000000000000000000000000000000000000000</p><p>xdc:</p><p><br> #CLK_100M<br> set_property PACKAGE_PIN E10 [get_ports clk]<br> set_property IOSTANDARD LVCMOS18 [get_ports clk]</p><pre><code>#SW0~15set_property IOSTANDARD LVCMOS18 [get_ports {IR[2]}]set_property IOSTANDARD LVCMOS18 [get_ports {IR[3]}]set_property IOSTANDARD LVCMOS18 [get_ports {IR[4]}]set_property IOSTANDARD LVCMOS18 [get_ports {IR[5]}]set_property IOSTANDARD LVCMOS18 [get_ports {IR[6]}]set_property IOSTANDARD LVCMOS18 [get_ports {IR[7]}]set_property PACKAGE_PIN G11 [get_ports {IR[2]}]set_property PACKAGE_PIN F10 [get_ports {IR[3]}]set_property PACKAGE_PIN D10 [get_ports {IR[4]}]set_property PACKAGE_PIN E11 [get_ports {IR[5]}]set_property PACKAGE_PIN D11 [get_ports {IR[6]}]set_property PACKAGE_PIN A14 [get_ports {IR[7]}]#sw31~24set_property PACKAGE_PIN J8 [get_ports nreset]set_property IOSTANDARD LVCMOS18 [get_ports nreset]set_property PACKAGE_PIN J14 [get_ports CMROM_CS]set_property IOSTANDARD LVCMOS18 [get_ports CMROM_CS]set_property PACKAGE_PIN H9 [get_ports M_uA]set_property IOSTANDARD LVCMOS18 [get_ports M_uA]#SEG_DIG1~16set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[15]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[14]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[13]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[12]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[11]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[10]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[9]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[8]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[7]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[6]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[5]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[4]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[3]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[2]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[1]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[0]}]set_property PACKAGE_PIN A23 [get_ports {seg_dig[15]}]set_property PACKAGE_PIN A24 [get_ports {seg_dig[14]}]set_property PACKAGE_PIN D26 [get_ports {seg_dig[13]}]set_property PACKAGE_PIN C26 [get_ports {seg_dig[12]}]set_property PACKAGE_PIN A20 [get_ports {seg_dig[11]}]set_property PACKAGE_PIN J25 [get_ports {seg_dig[10]}]set_property PACKAGE_PIN J24 [get_ports {seg_dig[9]}]set_property PACKAGE_PIN H22 [get_ports {seg_dig[8]}]set_property PACKAGE_PIN K21 [get_ports {seg_dig[7]}]set_property PACKAGE_PIN L23 [get_ports {seg_dig[6]}]set_property PACKAGE_PIN B25 [get_ports {seg_dig[5]}]set_property PACKAGE_PIN B26 [get_ports {seg_dig[4]}]set_property PACKAGE_PIN C24 [get_ports {seg_dig[3]}]set_property PACKAGE_PIN D21 [get_ports {seg_dig[2]}]set_property PACKAGE_PIN C22 [get_ports {seg_dig[1]}]set_property PACKAGE_PIN B20 [get_ports {seg_dig[0]}]#seg_dataset_property PACKAGE_PIN E26 [get_ports {seg_data[7]}]set_property PACKAGE_PIN J26 [get_ports {seg_data[6]}]set_property PACKAGE_PIN H26 [get_ports {seg_data[5]}]set_property PACKAGE_PIN H21 [get_ports {seg_data[4]}]set_property PACKAGE_PIN G21 [get_ports {seg_data[3]}]set_property PACKAGE_PIN H23 [get_ports {seg_data[2]}]set_property PACKAGE_PIN H24 [get_ports {seg_data[1]}]set_property PACKAGE_PIN J21 [get_ports {seg_data[0]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[7]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[6]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[5]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[4]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[3]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[2]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[1]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[0]}]</code></pre><h3 id="15-8-位-SOC-综合设计"><a href="#15-8-位-SOC-综合设计" class="headerlink" title="15.8 位 SOC 综合设计"></a>15.8 位 SOC 综合设计</h3><p>根据以上所设计的功能模块连接成完整的 8 位 SOC 结构。</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/cfdc1dbc85d346b9c3541e7e13e4fd2f.png"></p><p>模块修改记录:</p><p><br> SOC:<br> 修改PC/ROM<br> *修改各模块时钟<br> 修改各模块总线输出时机提高片选及使能优先级,并加入到敏感检测列表<br> 修改uC使能:M_uA和CMROM_CS低电平有效(根据指令知)<br> uC输入输出冲突,同时输入输出控制信号<br> 修改微指令34H:IO_CS位<br> 修改微指令38H:IO_CS位<br> 修改微指令24H:Ri_EN错误<br> 修改微指令8AH:M_PC位<br> 修改微指令65H: RDRi位<br> PC不再产生nPCL和nPCH信号并修改PC模块<br> ADD微程序增加一条微指令</p><p>源码:</p><p>顶层测试:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/27 20:08:24<br> ———————————————————————————-</p><p><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity CPU_test is generic( CLK_FRE:integer:=100000000 ); Port( clk:in std_logic; nreset:in std_logic; data_in:in std_logic_vector(7 downto 0); seg_dig:out std_logic_vector(15 downto 0); seg_data:out std_logic_vector(7 downto 0)--管脚连接顺序:dp,g,f,e,d,c,b,a );end CPU_test;architecture Behavioral of CPU_test iscomponent CPU generic( CLK_FRE:integer:=100000000 ); Port( clk:in std_logic; nreset:in std_logic; data_in:in std_logic_vector(7 downto 0); regA_out,regB_out,result_out:out std_logic_vector(7 downto 0); data_out:out std_logic_vector(7 downto 0) );end component;component clk_div generic( DIV_NUM:integer:=10000 ); Port ( rst:in std_logic; clk_in:in std_logic; clk_out:out std_logic );end component;component seg_dis port( rst,clk:in std_logic; data_in_A,data_in_B,data_in_C,data_in_D:in std_logic_vector(15 downto 0); seg_dig:out std_logic_vector(15 downto 0); seg_data:out std_logic_vector(7 downto 0)--管脚连接顺序:dp,g,f,e,d,c,b,a );end component;signal clk_line:std_logic;signal data_in_A,data_in_B,data_in_C,data_in_D:std_logic_vector(15 downto 0);signal regA_out,regB_out,result_out,data_out:std_logic_vector(7 downto 0);beginclk_div_inst:clk_div generic map(1000000)port map(nreset,clk,clk_line);seg_dis_inst:seg_dis port map(nreset,clk_line,data_in_A,data_in_B,data_in_C,data_in_D,seg_dig,seg_data);CPU_inst:CPU generic map(100000000)port map(clk_line,nreset,data_in,regA_out,regB_out,result_out,data_out);process(regA_out,regB_out,result_out,data_out)begin data_in_A<="00000000"&result_out; data_in_B<="00000000"&regB_out; data_in_C<="00000000"&regA_out; data_in_D<="00000000"&data_out;end process;end Behavioral;</code></pre><p>顶层:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/25 17:50:57<br> ———————————————————————————-<br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;</p><pre><code>entity CPU is generic( CLK_FRE:integer:=100000000 ); Port( clk:in std_logic; nreset:in std_logic; data_in:in std_logic_vector(7 downto 0); regA_out,regB_out,result_out:out std_logic_vector(7 downto 0); data_out:out std_logic_vector(7 downto 0) );end CPU;architecture Behavioral of CPU issignal clk1,nclk1:std_logic; --clksignal clk2,nclk2:std_logic; --clk二分频signal w0,w1,w2,w3:std_logic; --节拍信号component clock Port( clk,rst:in std_logic; clk1,nclk1:out std_logic; --clk clk2,nclk2:out std_logic; --clk二分频 w0,w1,w2,w3:out std_logic --节拍信号 );end component;signal clk_uC,M_uA,CMROM_CS:std_logic;signal IR_line:std_logic_vector(7 downto 0);signal CTR_BUS:std_logic_vector(47 downto 8);component uC Port( clk_uC:in std_logic; --微程序控制器时钟信号 nreset:in std_logic; --复位信号 M_uA:in std_logic; --微地址控制信号 IR:in std_logic_vector(7 downto 2); --IR操作码信息 CMROM_CS:in std_logic; --控制存储器选通信号 CM:out std_logic_vector(47 downto 8) --控制信号输出 );end component;signal clk_SP,SP_CS,SP_UP,SP_DN,nSP_EN:STD_LOGIC;signal AR:std_logic_vector(6 downto 0);signal DATA_BUS:std_logic_vector(7 downto 0);component SP Port( clk_SP:in std_logic; --SP时钟信号 nreset:in std_logic; --复位信号 SP_CS:in std_logic; --SP选择信号 SP_UP:in std_logic; --SP+1控制 SP_DN:in std_logic; --SP-1控制 nSP_EN:in std_logic; --SP输出使能 AR:out std_logic_vector(6 downto 0);--SP指向RAM地址 DATA_BUS:inout std_logic_vector(7 downto 0) --数据总线 );end component;signal clk_IO,IO_CS,IO_IEN,IO_OEN,RI_EN,RO_EN:std_logic;signal IO_in,IO_out:std_logic_vector(7 downto 0);component IO Port( clk_IO:in std_logic; --IO时钟信号 nreset:in std_logic; --IO复位信号 IO_CS:in std_logic; --IO选择信号 IO_IEN:in std_logic; --IO输入使能 IO_OEN:in std_logic; --IO输出使能 RI_EN:in std_logic; --IO缓存器输入使能 RO_EN:in std_logic; --IO缓存器输出使能 IO_in:in std_logic_vector(7 downto 0); --IO输入 IO_out:out std_logic_vector(7 downto 0); --IO输出 DATA_BUS:inout std_logic_vector(7 downto 0) --数据总线 );end component;signal clk_RAM,RAM_CS,nRAM_EN,Wr_nRD:std_logic;component RAM generic( depth:positive:=7; width:positive:=8 ); Port ( clk_RAM:in STD_LOGIC; --RAM时钟信号 n_reset:in STD_LOGIC; --RAM选择信号 RAM_CS:in STD_LOGIC; --RAM片选信号 nRAM_EN:in STD_LOGIC; --RAM输出使能 Wr_nRD :in STD_LOGIC; --RAM读写信号 AR:in STD_LOGIC_VECTOR (depth-1 downto 0); --RAM地址信号 DATA_BUS: inout STD_LOGIC_VECTOR (width-1 downto 0) --数据总线 );end component;signal clk_ALU,m_A,m_B,m_F,nALU_EN,nPSW_EN,C0:std_logic;signal S :std_logic_vector(4 downto 0);signal F_in :std_logic_vector(1 downto 0); --signal regA_out,regB_out,result_out:std_logic_vector(7 downto 0);signal AC : std_logic; --半进位标志signal CY : std_logic; --进位标志signal ZN : std_logic; --零标志signal OV : std_logic; --溢出标志component ALU port( clk,clk_ALU : in std_logic; --全局时钟和ALU时钟 nreset : in std_logic; --全局复位信号 M_A,M_B : in std_logic; --暂存器控制信号 M_F : in std_logic; --程序状态字控制信号 nALU_EN : in std_logic; --alu运算结果输出使能 nPSW_EN : in std_logic; --psw输出使能 C0 : in std_logic; --进位输入 S : in std_logic_vector(4 downto 0); --运算类型和操作选择,M为最高位S(4),其余在低四位 F_in : in std_logic_vector(1 downto 0); --移位功能选择 regA_out,regB_out,result_out:out std_logic_vector(7 downto 0); DATA_BUS : inout std_logic_vector(7 downto 0); --数据总线 AC : out std_logic; --半进位标志 CY : out std_logic; --进位标志 ZN : out std_logic; --零标志 OV : out std_logic --溢出标志 );end component;signal clk_RN,Rn_CS,nRi_EN,RDRi,WRRi:std_logic;signal RS,RD:std_logic;component RN Port( clk_RN,Rn_CS,nRi_EN,RDRi,WRRi:in std_logic; RS,RD:in std_logic; DATA_BUS:inout std_logic_vector(7 downto 0) );end component;signal clk_IR,LD_IR1,LD_IR2,LD_IR3,nARen: std_logic;signal IR_AR :std_logic_vector(6 downto 0);component IR Port ( rst,clk_IR,LD_IR1,LD_IR2,LD_IR3,nARen:in std_logic; DATA_BUS:in std_logic_vector(7 downto 0); IR_out:out std_logic_vector(7 downto 0);--传送指令到指令寄存器 RS,RD:out std_logic;--传送操作寄存器(寄存器地址) PC_out:out std_logic_vector(11 downto 0);--PC地址总线 AR:out std_logic_vector(6 downto 0) );end component;signal clk_ROM,M_ROM,ROM_EN:std_logic;signal ROM_PC:std_logic_vector(11 downto 0);component ROM generic( depth:positive:=12; width:positive:=8 ); Port ( clk_ROM,M_ROM,ROM_EN:in std_logic; addr:in std_logic_vector(11 downto 0); DATA_BUS:inout std_logic_vector(7 downto 0) );end component;signal clk_PC,M_PC,nLD_PC,nPCH,nPCL:std_logic;signal PC_in:std_logic_vector(11 downto 0):=(others=>'0');component pc Port ( rst,clk_PC,M_PC,nLD_PC:in std_logic; nPCH,nPCL:in std_logic; PC_in:in std_logic_vector(11 downto 0); PC_out:out std_logic_vector(11 downto 0); DATA_BUS:inout std_logic_vector(7 downto 0) );end component;signal test_line:std_logic_vector(7 downto 0);beginclock_inst:clock port map(clk,nreset,clk1,nclk1,clk2,nclk2,w0,w1,w2,w3);PC_inst:PC port map(nreset,clk_PC,M_PC,nLD_PC,nPCH,nPCL,PC_in,ROM_PC,DATA_BUS);ROM_inst:ROM generic map(12,8)port map(clk_ROM,M_ROM,ROM_EN,ROM_PC,DATA_BUS);uC_inst:uC port map(clk_uC,nreset,M_uA,IR_line(7 downto 2),CMROM_CS,CTR_BUS);IR_inst:IR port map(rst=>nreset,clk_IR=>clk_IR,LD_IR1=>LD_IR1,LD_IR2=>LD_IR2,LD_IR3=>LD_IR3,nARen=>nARen,DATA_BUS=>DATA_BUS,IR_out=>IR_line,RS=>RS,RD=>RD,PC_out=>PC_in,AR=>AR(6 downto 0));RAM_inst:RAM generic map(7,8)port map(clk_RAM=>clk_RAM,n_reset=>nreset,RAM_CS=>RAM_CS,nRAM_EN=>nRAM_EN,Wr_nRD=>Wr_nRD,AR=>AR,DATA_BUS=>DATA_BUS);IO_inst:IO port map(clk_IO,nreset,IO_CS,IO_IEN,IO_OEN,RI_EN,RO_EN,data_in,data_out,DATA_BUS);--SP_inst:SP PORT MAP(clk_SP,nreset,SP_CS,SP_UP,SP_DN,nSP_EN,AR,DATA_BUS);ALU_inst:ALU port map(clk,clk_ALU,nreset,m_A,m_B,m_F,nALU_EN,nPSW_EN,C0,S,F_in,regA_out,regB_out,result_out,DATA_BUS,AC,CY,ZN,OV);RN_inst:RN port map(clk_RN,Rn_CS,nRi_EN,RDRi,WRRi,RS,RD,DATA_BUS);clk_PC<=clk1 and clk2;clk_ROM<=nclk1 and clk2;clk_IR<=clk1 and nclk2;clk_uC<=nclk1 and nclk2;clk_RN<=clk1 and nclk2;clk_ALU<=nclk1 and nclk2;--clk_IO<=clk2;--(LED程序使用)clk_IO<=nclk1 and clk2;--(ADD程序使用)clk_RAM<=nclk1 and w1;clk_SP<=clk1 and clk2 and w1;M_A <= CTR_BUS(47);M_B <= CTR_BUS(46);M_F <= CTR_BUS(45);S(4) <= CTR_BUS(44);S(3) <= CTR_BUS(43);S(2) <= CTR_BUS(42);S(1) <= CTR_BUS(41);S(0) <= CTR_BUS(40);F_in(1) <= CTR_BUS(39);F_in(0) <= CTR_BUS(38);nALU_EN <= CTR_BUS(37);nPSW_EN <= CTR_BUS(36);C0 <= CTR_BUS(35);RAM_CS <= CTR_BUS(34);Wr_nRD <= CTR_BUS(33); nRAM_EN <= CTR_BUS(32);Rn_CS <= CTR_BUS(31);RDRi <= CTR_BUS(30);WRRi <= CTR_BUS(29);nRi_EN <= CTR_BUS(28);LD_IR1 <= CTR_BUS(27);LD_IR2 <= CTR_BUS(26);LD_IR3 <= CTR_BUS(25);nAREN <= CTR_BUS(24);M_PC <= CTR_BUS(23);nLD_PC <= CTR_BUS(22); nPCH <= CTR_BUS(21); nPCL <= CTR_BUS(20); SP_UP <= CTR_BUS(19);SP_DN <= CTR_BUS(18);SP_CS <= CTR_BUS(17); nSP_EN <= CTR_BUS(16); IO_CS <= CTR_BUS(15);IO_IEN <= CTR_BUS(14);IO_OEN <= CTR_BUS(13);RI_EN<='0';RO_EN<='0';-- <= CTR_BUS(12);M_ROM <= CTR_BUS(11);ROM_EN <= CTR_BUS(10);M_uA <= CTR_BUS(9);CMROM_CS <= CTR_BUS(8);process(nPCH,nPCL)begin if(nPCH='0')then PC_in(11 downto 8)<=DATA_BUS(3 downto 0); elsif(nPCL='0')then PC_in(7 downto 0)<=DATA_BUS; end if;end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/b870e7e63c2438527c9603091d047576.png"></p><p>时钟:</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/5bd3c1b7d51ed7ee02fd3b42b4c4ba89.png"></p><p>ADD微程序:</p><p><br> 00111000 –IR:38H MOV Ri,IO<br> 00111011 –IR:38H MOV Ri,IO<br> 00001000 –ADD R0,R1<br> 00000100 –JMP addr12<br> 00000000 –addr1:00H<br> 00000000 –addr2:00H</p><p>LED微程序:</p><p><br> 00100100 –IR:24H MOV Ri,#data<br> 00000001 –data:01H<br> 00110100 –IR:34H MOV IO,Ri<br> 00100100 –IR:24H<br> 00000010 –data:02H<br> 00110100 –IR:34H<br> 00100100 –IR:24H<br> 00000100 –data:04H<br> 00110100 –IR:34H<br> 00100100 –IR:24H<br> 00001000 –data:08H<br> 00110100 –IR:34H<br> 00100100 –IR:24H<br> 00010000 –data:10H<br> 00110100 –IR:34H<br> 00100100 –IR:24H<br> 00100000 –data:20H<br> 00110100 –IR:34H<br> 00100100 –IR:24H<br> 01000000 –data:40H<br> 00110100 –IR:34H<br> 00100100 –IR:24H<br> 10000000 –data:80H<br> 00110100 –IR:34H<br> 00000100 –JMP addr12<br> 00000000 –addr:00H<br> 00000000 –addr:00H<br> 00000000</p><p> 程序:</p><p><br> 000000000011000100011001111100110111100100000000–00H<br> 000000000000000000000000000000000000000000000000–01H<br> 000000000000000000000000000000000000000000000000–02H<br> 000000000000000000000000000000000000000000000000–03H<br> 000000000011000100010101111100110111101100000101–04H JMP addr12<br> 000000000011000100010011111100110111101100000110–05H<br> 000000000011000100010001101100110111011100000000–06H<br> 000000000000000000000000000000000000000000000000–07H<br> 010000000011000101000001011100110111011100001001–08H ADD Ri,Rj<br> 100000000011000101000001011100110111011100001010–09H<br> 001000010001000100110001011100110111011100000000–0AH<br> 000000000001000100100001111100110111011100000000–0BH<br> 000000000000000000000000000000000000000000000000–0CH<br> 000000000000000000000000000000000000000000000000–0DH<br> 000000000000000000000000000000000000000000000000–0EH<br> 000000000000000000000000000000000000000000000000–0FH<br> 000000000000000000000000000000000000000000000000–10H<br> 000000000000000000000000000000000000000000000000–11H<br> 000000000000000000000000000000000000000000000000–12H<br> 000000000000000000000000000000000000000000000000–13H<br> 000000000000000000000000000000000000000000000000–14H<br> 000000000000000000000000000000000000000000000000–15H<br> 000000000000000000000000000000000000000000000000–16H<br> 000000000000000000000000000000000000000000000000–17H<br> 000000000000000000000000000000000000000000000000–18H<br> 000000000000000000000000000000000000000000000000–19H<br> 000000000000000000000000000000000000000000000000–1AH<br> 000000000000000000000000000000000000000000000000–1BH<br> 000000000000000000000000000000000000000000000000–1CH<br> 000000000000000000000000000000000000000000000000–1DH<br> 000000000000000000000000000000000000000000000000–1EH<br> 000000000000000000000000000000000000000000000000–1FH<br> 000000000000000000000000000000000000000000000000–20H<br> 000000000000000000000000000000000000000000000000–21H<br> 000000000000000000000000000000000000000000000000–22H<br> 000000000000000000000000000000000000000000000000–23H<br> 000000000011000100100001111100110111101100100101–24H MOV Ri,#data <em><strong>修改</strong></em><br> 000000000011000100010001011100110111011100100110–25H<br> 000000000011000100010001011100110111011100000000–26H<br> 000000000000000000000000000000000000000000000000–27H<br> 000000000011000101100001011100110111011100101001–28H<br> 000000000011000101100001011100110111011100101010–29H<br> 000000000011000100010001011100110111011100000000–2AH<br> 000000000000000000000000000000000000000000000000–2BH<br> 000000000011000100010010111100110111101100101101–2CH<br> 000000000011010000100000011100110111011100101110–2DH<br> 000000000011000100010001011100110111011100000000–2EH<br> 000000000000000000000000000000000000000000000000–2FH<br> 000000000011000100010010111100110111101100110001–30H<br> 000000000011011101000000011100110111011100110010–31H<br> 000000000011000100010001011100110111011100000000–32H<br> 000000000000000000000000000000000000000000000000–33H<br> 000000000011000101000001011100111101011100110101–34H MOV IO,Ri<br> 000000000011000100010001011100110101011100110110–35H<br> 000000000011000100010001011100110111011100000000–36H<br> 000000000000000000000000000000000000000000000000–37H<br> 000000000011000100010001011100111011011100111001–38H MOV Ri,IO<br> 000000000011000100100001011100111001011100111010–39H<br> 000000000011000100010001011100110111011100000000–3AH<br> 000000000000000000000000000000000000000000000000–3BH<br> 000000000011000100010001111100010111101100111101–3CH<br> 000000000011000100010001011100110111011100111110–3DH<br> 000000000011000100010001011100110111011100000000–3EH<br> 000000000000000000000000000000000000000000000000–3FH<br> 010000010011000101000001011100110111011101000001–40H<br> 000000000011000101100001011100110111011101000010–41H<br> 100000000011000111000001011100110111011101000011–42H<br> 001000010001000100110001111100110111011101000100–43H<br> 000000000011000100010001011100110111011100000000–44H<br> 000000000000000000000000000000000000000000000000–45H</p><p>testbench:</p><p><br> ———————————————————————————-<br> – Engineer: switch_swq<br> – Create Date: 2024/04/26 08:47:54<br> ———————————————————————————-</p><pre><code>library IEEE;use IEEE.STD_LOGIC_1164.ALL;entity CPU_tb isend CPU_tb;architecture Behavioral of CPU_tb iscomponent CPU generic( CLK_FRE:integer:=100000000 ); Port( clk:in std_logic; nreset:in std_logic; data_in:in std_logic_vector(7 downto 0); data_out:out std_logic_vector(7 downto 0) );end component;signal clk,nreset:std_logic;signal data_in,data_out:std_logic_vector(7 downto 0);beginCPU_inst:CPU generic map(100000000)port map(clk,nreset,data_in,data_out);clock:processbegin clk<='1'; wait for 5ns; clk<='0'; wait for 5ns;end process;reset:processbegin nreset<='0'; wait for 15ns; nreset<='1'; wait;end process;test:processbegin data_in<=x"FF"; wait;end process;end Behavioral;</code></pre><p>LED结果:</p><p>整体:</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/0f9cfb770135c8cd06409fe765cdb265.png"></p><p>取数(00100100 –IR:24H MOV Ri,#data 00000001 –data:01H):</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/595f539ee9983cb3ad064110256b9d3d.png"></p><p>IO输出(00110100 –IR:34H MOV IO,Ri):</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/deb8630114a8896456e6eea801735970.png"></p><p>ADD结果:</p><p>整体:</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/08792675191fd507e190b166618ace0c.png"></p><p>IO输入(00111000 –IR:38H MOV Ri,IO):</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/b48d14803e3b211bfb14f2d81f5dc40a.png"></p><p>加法(00001000 –ADD R0,R1):</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/5399cba63467fb5d837fe1e49c0adb02.png"></p><p>xdc:</p><p><br> #CLK_100M<br> set_property PACKAGE_PIN E10 [get_ports clk]<br> set_property IOSTANDARD LVCMOS18 [get_ports clk]</p><pre><code>#sw31~24set_property PACKAGE_PIN J8 [get_ports nreset]set_property IOSTANDARD LVCMOS18 [get_ports nreset]#SW0~7set_property IOSTANDARD LVCMOS18 [get_ports {data_in[0]}]set_property IOSTANDARD LVCMOS18 [get_ports {data_in[1]}]set_property IOSTANDARD LVCMOS18 [get_ports {data_in[2]}]set_property IOSTANDARD LVCMOS18 [get_ports {data_in[3]}]set_property IOSTANDARD LVCMOS18 [get_ports {data_in[4]}]set_property IOSTANDARD LVCMOS18 [get_ports {data_in[5]}]set_property IOSTANDARD LVCMOS18 [get_ports {data_in[6]}]set_property IOSTANDARD LVCMOS18 [get_ports {data_in[7]}]set_property PACKAGE_PIN C9 [get_ports {data_in[0]}]set_property PACKAGE_PIN B9 [get_ports {data_in[1]}]set_property PACKAGE_PIN G11 [get_ports {data_in[2]}]set_property PACKAGE_PIN F10 [get_ports {data_in[3]}]set_property PACKAGE_PIN D10 [get_ports {data_in[4]}]set_property PACKAGE_PIN E11 [get_ports {data_in[5]}]set_property PACKAGE_PIN D11 [get_ports {data_in[6]}]set_property PACKAGE_PIN A14 [get_ports {data_in[7]}]#SEG_DIG1~16set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[15]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[14]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[13]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[12]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[11]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[10]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[9]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[8]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[7]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[6]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[5]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[4]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[3]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[2]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[1]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_dig[0]}]set_property PACKAGE_PIN A23 [get_ports {seg_dig[15]}]set_property PACKAGE_PIN A24 [get_ports {seg_dig[14]}]set_property PACKAGE_PIN D26 [get_ports {seg_dig[13]}]set_property PACKAGE_PIN C26 [get_ports {seg_dig[12]}]set_property PACKAGE_PIN A20 [get_ports {seg_dig[11]}]set_property PACKAGE_PIN J25 [get_ports {seg_dig[10]}]set_property PACKAGE_PIN J24 [get_ports {seg_dig[9]}]set_property PACKAGE_PIN H22 [get_ports {seg_dig[8]}]set_property PACKAGE_PIN K21 [get_ports {seg_dig[7]}]set_property PACKAGE_PIN L23 [get_ports {seg_dig[6]}]set_property PACKAGE_PIN B25 [get_ports {seg_dig[5]}]set_property PACKAGE_PIN B26 [get_ports {seg_dig[4]}]set_property PACKAGE_PIN C24 [get_ports {seg_dig[3]}]set_property PACKAGE_PIN D21 [get_ports {seg_dig[2]}]set_property PACKAGE_PIN C22 [get_ports {seg_dig[1]}]set_property PACKAGE_PIN B20 [get_ports {seg_dig[0]}]#seg_dataset_property PACKAGE_PIN E26 [get_ports {seg_data[7]}]set_property PACKAGE_PIN J26 [get_ports {seg_data[6]}]set_property PACKAGE_PIN H26 [get_ports {seg_data[5]}]set_property PACKAGE_PIN H21 [get_ports {seg_data[4]}]set_property PACKAGE_PIN G21 [get_ports {seg_data[3]}]set_property PACKAGE_PIN H23 [get_ports {seg_data[2]}]set_property PACKAGE_PIN H24 [get_ports {seg_data[1]}]set_property PACKAGE_PIN J21 [get_ports {seg_data[0]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[7]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[6]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[5]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[4]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[3]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[2]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[1]}]set_property IOSTANDARD LVCMOS33 [get_ports {seg_data[0]}]</code></pre><h4 id="1-实验结果分析"><a href="#1-实验结果分析" class="headerlink" title="1.实验结果分析"></a>1.实验结果分析</h4><h5 id="模块工作顺序分析"><a href="#模块工作顺序分析" class="headerlink" title="<1>模块工作顺序分析"></a><1><strong>模块工作顺序分析</strong></h5><pre><code> 各个模块工作的逻辑顺序如上时钟时序图所示,每条指令执行则可分为m0~3四个阶段。在m0阶段首先由PC发送地址至ROM,然后ROM输出该地址的指令或数据,传送至IR,IR经过简单处理后继续传送至UC,UC产生各个模块的控制信号。在m1~3阶段,依据微程序产生3次控制信号,实现相应指令功能(注意ALU、RN、IO时钟不同,后面有相关解释)。</code></pre><h5 id="指令执行过程分析"><a href="#指令执行过程分析" class="headerlink" title="<2>指令执行过程分析"></a><2><strong>指令执行过程分析</strong></h5><ul><li><strong><strong>以ADD加法为例:</strong></strong></li></ul><p><strong><strong>MOV Ri,IO:</strong></strong></p><pre><code> m1~3——执行38H MOV Ri,IO:在m1使能IO相关信号使IO_IN->REG,在m2时,REG->DATA_BUS->Ri(IO的时钟先于RN,使数据在DATA_BUS刚好能传送至RN)</code></pre><p><strong><strong>ADD R0,R1:</strong></strong></p><pre><code> m1~3——执行08H ADD R0,R1:由于无法在计算出结果的同时将结果通过数据总线DATA_BUS传送至RN,所以在一条指令中,我的ADD指令只能实现计算功能,计算结果由ALU另行输出至result总线。在m1和m2分别实现RN->DATA_BUS->regA/B(其中regA/B为ALU内部缓冲器),在m3实现计算和UC地址回到00H操作。</code></pre><p><strong><strong>以LED流水灯为例:</strong></strong></p><pre><code> m0——取指令:PC->ROM->DATA_BUS->IR->UC,微指令为0x003119f37900H 注意到ROM将地址信息输出到总线,IR接收并传递地址到UC,从而执行24H地址的微程序。</code></pre><p><strong><strong>MOV Ri,#data:</strong></strong></p><pre><code> m1~3——执行24H MOV Ri,#data:在m1将ROM中的立即数输出至</code></pre><p>DATA_BUS,在m2传输至Ri之中,在m3阶段UC地址回到00H准备进入下一条指令,即取值公操作。</p><p><strong><strong>MOV IO,Ri:</strong></strong></p><pre><code> m1~3——执行34H MOV IO,Ri:在m1将Ri->DATA_BUS,在m2,DATA_BUS->REG->IO_OUT(REG是IO内暂存器,由于UC控制信号不包含RI_EN和RO_EN,一直使能,即DATA_BUS<->IO直接完成),在m3阶段UC地址回到00H准备进入下一条指令,即取值公操作。</code></pre><p><strong><strong>JMP addr12</strong></strong><strong><strong>:</strong></strong></p><pre><code> m1~3——执行04H JMP addr12:在m1、m2依次将立即数加载至IR中,对应LD_IR2和LD_IR3分别有效,IR将新地址传送至PC。</code></pre><ul><li><strong><strong>以ADD加法为例:</strong></strong></li></ul><p><strong><strong>MOV Ri,IO:</strong></strong></p><pre><code> m1~3——执行38H MOV Ri,IO:在m1使能IO相关信号使IO_IN->REG,在m2时,REG->DATA_BUS->Ri(IO的时钟先于RN,使数据在DATA_BUS刚好能传送至RN)</code></pre><p><strong><strong>ADD R0,R1:</strong></strong></p><pre><code> m1~3——执行08H ADD R0,R1:由于无法在计算出结果的同时将结果通过数据总线DATA_BUS传送至RN,所以在一条指令中,我的ADD指令只能实现计算功能,计算结果由ALU另行输出至result总线。在m1和m2分别实现RN->DATA_BUS->regA/B(其中regA/B为ALU内部缓冲器),在m3实现计算和UC地址回到00H操作。</code></pre><h4 id="2-其他"><a href="#2-其他" class="headerlink" title="2.其他"></a>2.其他</h4><h5 id="SOC-模块集成设计经验"><a href="#SOC-模块集成设计经验" class="headerlink" title="<1>SOC****模块集成设计经验"></a><1><strong>SOC****模块集成设计经验</strong></h5><pre><code> 在集成各个组成模块时,为避免总线冲突以及方便调试,采用各个模块依次添加测试的方法。 首先测试PC、ROM、IR、UC组成的系统,要求取指令时4个模块的运行顺序为:PC发送ROM地址->ROM输出指令/数据->IR传送指令->UC解析执行微程序。随后依次加入IO、RN、ALU、RAM模块进行调试(按照指令执行逻辑顺序)。</code></pre><h5 id="SOC集成关键"><a href="#SOC集成关键" class="headerlink" title="<2>SOC集成关键"></a><2><strong>SOC集成关键</strong></h5><p>在集成各个模块时,关键在于:</p><ul><li><p>清楚模块工作逻辑顺序</p><pre><code>需清楚知晓各个模块工作先后关系,理清数据/控制/地址信号流的传递顺序,以避免读写顺序出错,出现写未读到的情况。</code></pre></li><li><p>避免总线冲突</p><pre><code>主要是DATA_BUS数据总线使用的原子性,各模块严格按照时钟时序进行输出,在允许输出时输入/出数据到数据总线,其他时刻不要忘记将数据总线置高阻态。</code></pre></li><li><p>考虑信号的建立、保持</p><pre><code>在课程参考资料中,ALU、IO、RN的时钟都是nclk2,但是对于任意一条微指令,如果涉及到上述3个模块的协作,如将RN中数据传送至ALU中缓存器regA,由于时钟相同,且都在上升沿工作,则在同一时刻,RN中数据传输到数据总线,上一时刻数据总线的数值传送至regA,并不能实现RN->DATA_BUS->regA这一连贯操作。解决方法在于错开操作时间,即RN->DATA_BUS先于DATA_BUS->regA,需要修改模块时钟,故出现了上面仿真图中的时钟。</code></pre></li></ul><p><3>反思与改进</p><ul><li><p>对数据不能在总线上连续传递的思考</p><pre><code>考虑上面“考虑信号的建立、保持”部分产生的问题,问题产生的原因在于组合逻辑电路和时序逻辑电路的区别,如果将信号的触发条件由时钟的上升沿改为高电平(类似于使能信号),则将时序逻辑转变为组合逻辑,可能解决上述问题,使得ALU、IO、RN等模块的时钟可以都是nclk2。</code></pre></li><li><p>ADD指令的改进</p><pre><code>上述实现的ADD指令在有限的m1~3阶段内计算完结果无法实现结果存储至RN(在上面ADD指令时序图可观测到计算结果曾短时间内输出到数据总线DATA_BUS上),仅一个指令周期无法实现,可以扩展成两个,即在第二个指令周期的m0~3阶段实现指令存储至RN。</code></pre></li></ul><p><img src="https://i-blog.csdnimg.cn/blog_migrate/999503810dc63f0f906be47e3bbaca66.png"></p><p>本文转自 <a href="https://blog.csdn.net/qq_32971095/article/details/139143519">https://blog.csdn.net/qq_32971095/article/details/139143519</a>,如有侵权,请联系删除。</p>]]></content:encoded>
<category domain="https://xidianswq.github.io/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">学习笔记</category>
<category domain="https://xidianswq.github.io/tags/fpga%E5%BC%80%E5%8F%91/">fpga开发</category>
<category domain="https://xidianswq.github.io/tags/%E4%BD%9C%E4%B8%9A%E8%A7%A3%E7%AD%94/">作业解答</category>
<category domain="https://xidianswq.github.io/tags/vhdl/">vhdl</category>
<category domain="https://xidianswq.github.io/tags/soc/">soc</category>
<category domain="https://xidianswq.github.io/tags/cpu/">cpu</category>
<comments>https://xidianswq.github.io/2024/05/23/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/%E8%A5%BF%E7%94%B5%E8%AE%A1%E7%A7%91%E5%A4%A7%E4%B8%89%E4%B8%8BSOC%E5%BE%AE%E4%BD%93%E7%B3%BB%E7%BB%93%E6%9E%84%E8%AE%BE%E8%AE%A1%E5%AE%9E%E9%AA%8C%E5%90%88%E9%9B%86/#disqus_thread</comments>
</item>
<item>
<title>西电计科大三下SOC微体系结构设计作业合集</title>
<link>https://xidianswq.github.io/2024/04/03/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/%E8%A5%BF%E7%94%B5%E8%AE%A1%E7%A7%91%E5%A4%A7%E4%B8%89%E4%B8%8BSOC%E5%BE%AE%E4%BD%93%E7%B3%BB%E7%BB%93%E6%9E%84%E8%AE%BE%E8%AE%A1%E4%BD%9C%E4%B8%9A%E5%90%88%E9%9B%86/</link>
<guid>https://xidianswq.github.io/2024/04/03/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/%E8%A5%BF%E7%94%B5%E8%AE%A1%E7%A7%91%E5%A4%A7%E4%B8%89%E4%B8%8BSOC%E5%BE%AE%E4%BD%93%E7%B3%BB%E7%BB%93%E6%9E%84%E8%AE%BE%E8%AE%A1%E4%BD%9C%E4%B8%9A%E5%90%88%E9%9B%86/</guid>
<pubDate>Wed, 03 Apr 2024 11:33:51 GMT</pubDate>
<description><p><strong>目录</strong></p></description>
<content:encoded><![CDATA[<p><strong>目录</strong></p><p><a href="about:blank#%E4%B8%80.VHDL%E8%AE%BE%E8%AE%A1%E4%BD%9C%E4%B8%9A">一.VHDL设计作业</a></p><p><a href="about:blank#1.%E5%9F%BA%E4%BA%8E%E7%A1%AC%E4%BB%B6%E6%8F%8F%E8%BF%B0%E8%AF%AD%E8%A8%80%E7%9A%843-8%E8%AF%91%E7%A0%81%E5%99%A8%E9%80%BB%E8%BE%91%E7%94%B5%E8%B7%AF%E8%AE%BE%E8%AE%A1">1.基于硬件描述语言的3-8译码器逻辑电路设计</a></p><p><a href="about:blank#2.8%E4%BD%8D%E5%8F%8C%E5%90%91%E7%A7%BB%E4%BD%8D%E5%AF%84%E5%AD%98%E5%99%A8%E8%AE%BE%E8%AE%A1">2.8位双向移位寄存器设计</a></p><p><a href="about:blank#3.%E5%9F%BA%E4%BA%8E%E6%9C%89%E9%99%90%E7%8A%B6%E6%80%81%E6%9C%BA%E7%9A%84%E8%87%AA%E5%8A%A9%E5%94%AE%E7%A5%A8%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1">3.基于有限状态机的自助售票系统设计</a></p><p><a href="about:blank#4.%E6%8C%89%E9%94%AE%E6%B6%88%E6%8A%96%E7%94%B5%E8%B7%AF%E8%AE%BE%E8%AE%A1">4.按键消抖电路设计</a></p><p><a href="about:blank#5.%E5%90%8C%E6%AD%A5%E7%8E%AF%E5%BD%A2FIFO%E8%AE%BE%E8%AE%A1">5.同步环形FIFO设计</a></p><p><a href="about:blank#6.%E7%BA%BF%E4%B8%8A%E5%AE%9E%E9%AA%8C%E2%80%94%E2%80%94%E6%97%B6%E9%92%9F%E6%A8%A1%E5%9D%97%E8%AE%BE%E8%AE%A1">6.线上实验——时钟模块设计</a></p><p><a href="about:blank#7.%E7%BA%BF%E4%B8%8A%E5%AE%9E%E9%AA%8C%E2%80%94%E2%80%94%E5%8E%9F%E7%A0%81%E4%BA%8C%E4%BD%8D%E4%B9%98%E6%B3%95%E5%99%A8%E8%AE%BE%E8%AE%A1%C2%A0">7.线上实验——原码二位乘法器设计</a></p><p><a href="about:blank#8.%E7%BA%BF%E4%B8%8A%E5%AE%9E%E9%AA%8C%E2%80%94%E2%80%94%E5%B8%83%E6%96%AF%E4%B9%98%E6%B3%95%E5%99%A8%E8%AE%BE%E8%AE%A1">8.线上实验——布斯乘法器设计</a></p><hr><h2 id="一-VHDL设计作业"><a href="#一-VHDL设计作业" class="headerlink" title="一.VHDL设计作业"></a>一.VHDL设计作业</h2><p>源文件、测试文件及仿真结果</p><h3 id="1-基于硬件描述语言的3-8译码器逻辑电路设计"><a href="#1-基于硬件描述语言的3-8译码器逻辑电路设计" class="headerlink" title="1.基于硬件描述语言的3-8译码器逻辑电路设计"></a>1.基于硬件描述语言的3-8译码器逻辑电路设计</h3><p>根据3-8译码器基本原理,采用硬件描述语言设计一个3-8译码器逻辑电路,并给出仿真结果。</p><p><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br><br> entity decoder3_8 is<br> Port (<br> OE: in std_logic;<br> X: in std_logic_vector(2 downto 0);<br> Y: out std_logic_vector(7 downto 0)<br> );<br> end decoder3_8;</p><pre><code>architecture Behavioral of decoder3_8 isbeginprocess(OE,X)begin if OE='0' then Y<="00000000"; elsif OE='1'then Case X is When "000" =>Y<="11111110"; When "001" =>Y<="11111101"; When "010" =>Y<="11111011"; When "011" =>Y<="11110111"; When "100" =>Y<="11101111"; When "101" =>Y<="11011111"; When "110" =>Y<="10111111"; When "111" =>Y<="01111111"; When others =>Y<="11111111"; END CASE; end if;end process;end Behavioral;</code></pre><p>testbench:</p><p><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br><br> entity decoder3_8_tb is<br> – Port ( );<br> end decoder3_8_tb;</p><pre><code>architecture structural of decoder3_8_tb iscomponent decoder3_8 port( OE: in std_logic; X: in std_logic_vector(2 downto 0); Y: out std_logic_vector(7 downto 0) );end component;signal oe:std_logic;signal input:std_logic_vector(2 downto 0);signal output:std_logic_vector(7 downto 0);begind1:decoder3_8 port map(oe,input,output);ensure:process begin oe<='0'; wait for 50ns; oe<='1'; wait;end process;sel:process begin input<="000"; wait for 20ns; input<="001"; wait for 20ns; input<="010"; wait for 20ns; input<="011"; wait for 20ns; input<="100"; wait for 20ns; input<="101"; wait for 20ns; input<="110"; wait for 20ns; input<="111"; wait for 20ns;end process;end structural;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/2cdaef1463aa82317fd6029b8c7bb08e.png"></p><h3 id="2-8位双向移位寄存器设计"><a href="#2-8位双向移位寄存器设计" class="headerlink" title="2.8位双向移位寄存器设计"></a>2.8位双向移位寄存器设计</h3><p>采用硬件描述语言实现8位双向移位寄存器,其功能包括异步置零,同步置数,左移,右移和保持状态不变等5种功能。其中输入端口包括8位并行数据、两位的选择信号和两个1位串行数据,输出是8位并行数据。当RESET信号为低电平时,寄存器的输出被异步置零;否则当RESET=1时,与时钟有关的四种功能由输入信号MODE决定。请给出仿真结果。</p><p><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br><br> entity shift_register is<br> Port (<br> clk,reset,left,right:in std_logic;<br> mode:in std_logic_vector(1 downto 0);<br> input_data:in std_logic_vector(7 downto 0);<br> output_data:inout std_logic_vector(7 downto 0)<br> );<br> end shift_register;</p><pre><code>architecture Behavioral of shift_register isbeginprocess(reset,clk,mode)begin if (reset='0')then output_data<="00000000"; elsif(reset='1'and clk='1')then case mode is when "00"=>output_data<=output_data; when "01"=>output_data<=input_data; when "10"=> output_data(0)<=left; output_data(7)<=output_data(6); output_data(6)<=output_data(5); output_data(5)<=output_data(4); output_data(4)<=output_data(3); output_data(3)<=output_data(2); output_data(2)<=output_data(1); output_data(1)<=output_data(0); when "11"=> output_data(0)<=output_data(1); output_data(1)<=output_data(2); output_data(2)<=output_data(3); output_data(3)<=output_data(4); output_data(4)<=output_data(5); output_data(5)<=output_data(6); output_data(6)<=output_data(7); output_data(7)<=right; when others=>output_data<=output_data; end case; end if;end process;end Behavioral;</code></pre><p>testbench:</p><p><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br><br> entity shift_register_tb is<br> – Port ( );<br> end shift_register_tb;</p><pre><code>architecture Behavioral of shift_register_tb iscomponent shift_registerport( clk,reset,left,right:in std_logic; mode:in std_logic_vector(1 downto 0); input_data:in std_logic_vector(7 downto 0); output_data:inout std_logic_vector(7 downto 0) );end component;signal clk,reset,left,right:std_logic;signal mode:std_logic_vector(1 downto 0);signal input_data:std_logic_vector(7 downto 0);signal output_data:std_logic_vector(7 downto 0); beginsr1:shift_register port map(clk,reset,left,right,mode,input_data,output_data);clock_gen:process begin left<=output_data(7); right<=output_data(0); clk<='0'; wait for 10ns; clk<='1'; wait for 10ns;end process;reset_gen:process begin reset<='0'; wait for 25ns; reset<='1'; wait;end process;mode_test:process begin mode<="00"; wait for 30ns; mode<="01"; input_data<="00001111"; wait for 30ns; mode<="10"; wait for 200ns; mode<="01"; input_data<="00001111"; wait for 30ns; mode<="11"; wait for 200ns;end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/5dcfe13e83a9275011aae48f12d1be1c.png"></p><h3 id="3-基于有限状态机的自助售票系统设计"><a href="#3-基于有限状态机的自助售票系统设计" class="headerlink" title="3.基于有限状态机的自助售票系统设计"></a>3.基于有限状态机的自助售票系统设计</h3><p>某自助售票系统只能接收 5元和10元纸币,若一张票的价格设定为 25元。<br>请利用有限状态机设计该售票系统,<br>1. 首先给出状态说明,然后画出具体的状态图及说明状态转移关系。<br>2. 并完成硬件描述语言程序设计。</p><p>3.将第1和2题的答案做成word文档上传。</p><p>4.扩展要求(加分10分):增加20元纸币输入。</p><p><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br><br> entity ticket_state_machine is<br> Port (<br> clk,reset:in std_logic;<br> input_money:in std_logic_vector(2 downto 0);<br> return_money:out std_logic_vector(2 downto 0);<br> output_ticket:out std_logic<br> );<br> end ticket_state_machine;</p><pre><code>architecture Behavioral of ticket_state_machine istype states is (m0,m5,m10,m15,m20,m25,m30,m35,m40);signal current_state,next_state:states;beginstart:process(reset,clk) begin if(reset='1')then current_state<=m0; elsif(reset='0'and clk='1'and clk'event)then current_state<=next_state; end if; end process;state_machine:process(current_state,input_money) begin case current_state is when m0=> output_ticket<='0'; return_money<="000"; case input_money is when"000"=>next_state<=m0; when"001"=>next_state<=m5; when"010"=>next_state<=m10; when"100"=>next_state<=m20; when others=>next_state<=current_state; end case; when m5=> output_ticket<='0'; return_money<="000"; case input_money is when"000"=>next_state<=m5; when"001"=>next_state<=m10; when"010"=>next_state<=m15; when"100"=>next_state<=m25; when others=>next_state<=current_state; end case; when m10=> output_ticket<='0'; return_money<="000"; case input_money is when"000"=>next_state<=m10; when"001"=>next_state<=m15; when"010"=>next_state<=m20; when"100"=>next_state<=m30; when others=>next_state<=current_state; end case; when m15=> output_ticket<='0'; return_money<="000"; case input_money is when"000"=>next_state<=m15; when"001"=>next_state<=m20; when"010"=>next_state<=m25; when"100"=>next_state<=m35; when others=>next_state<=current_state; end case; when m20=> output_ticket<='0'; return_money<="000"; case input_money is when"000"=>next_state<=m20; when"001"=>next_state<=m25; when"010"=>next_state<=m30; when"100"=>next_state<=m40; when others=>next_state<=current_state; end case; when m25=> output_ticket<='1'; return_money<="000"; case input_money is when"000"=>next_state<=m0; when"001"=>next_state<=m5; when"010"=>next_state<=m10; when"100"=>next_state<=m20; when others=>next_state<=current_state; end case; when m30=> output_ticket<='1'; return_money<="001"; case input_money is when"000"=>next_state<=m0; when"001"=>next_state<=m5; when"010"=>next_state<=m10; when"100"=>next_state<=m20; when others=>next_state<=current_state; end case; when m35=> output_ticket<='1'; return_money<="010"; case input_money is when"000"=>next_state<=m0; when"001"=>next_state<=m5; when"010"=>next_state<=m10; when"100"=>next_state<=m20; when others=>next_state<=current_state; end case; when m40=> output_ticket<='1'; return_money<="011"; case input_money is when"000"=>next_state<=m0; when"001"=>next_state<=m5; when"010"=>next_state<=m10; when"100"=>next_state<=m20; when others=>next_state<=current_state; end case; end case; end process;end Behavioral;</code></pre><p>testbench:</p><p><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br><br> entity ticket_state_machine_tb is<br> – Port ( );<br> end ticket_state_machine_tb;</p><pre><code>architecture Behavioral of ticket_state_machine_tb iscomponent ticket_state_machine Port ( clk,reset:in std_logic; input_money:in std_logic_vector(2 downto 0); return_money:out std_logic_vector(2 downto 0); output_ticket:out std_logic );end component;signal clk,reset: std_logic;signal input_money: std_logic_vector(2 downto 0);signal return_money: std_logic_vector(2 downto 0);signal output_ticket: std_logic;begintsm:ticket_state_machine port map(clk,reset,input_money,return_money,output_ticket);clock:process begin clk<='0'; wait for 10ns; clk<='1'; wait for 10ns;end process;start:process begin reset<='1'; wait for 20ns; reset<='0'; wait;end process;test:process begin wait for 50ns; input_money<="001"; wait for 20ns; input_money<="000"; wait for 50ns; input_money<="010"; wait for 20ns; input_money<="000"; wait for 50ns; input_money<="100"; wait for 20ns; input_money<="000"; wait for 50ns; input_money<="010"; wait for 20ns; input_money<="000";end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/711bd6d2672a650569b2474d89e3f38e.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/dfad20f27e654f243f373cfb9b80256c.png"></p><h3 id="4-按键消抖电路设计"><a href="#4-按键消抖电路设计" class="headerlink" title="4.按键消抖电路设计"></a>4.按键消抖电路设计</h3><p>请使用硬件描述语言设计一个按键消抖电路,假设输入时钟频率为50MHZ。请给出设计方案及仿真验证结果。</p><p><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br><br> entity key_stroke is<br> generic(CLK_FRE:integer:=50000000);<br> Port (<br> clk:in std_logic;<br> reset:in std_logic;<br> key_in:in std_logic;<br> output:out std_logic<br> );<br> end key_stroke;</p><pre><code>architecture Behavioral of key_stroke istype states is(s0,s1,s2,s3,s4);signal state:states;beginprocess(reset,clk,key_in)variable count_num:integer:=3*CLK_FRE/1000;variable count:integer:=0; begin if reset='1'then state<=s0; count:=0; output<='0'; elsif reset='0'then case state is when s0=>if key_in='1' then state<=s1;end if; when s1=> if clk='1' then count:=count+1;end if; if count=count_num then state<=s2; end if; when s2=> if(key_in='1')then output<='1';state<=s3; elsif(key_in='0')then output<='0';state<=s4; end if; when s3=> output<='0'; if(key_in='0')then state<=s4;end if; when s4=> state<=s0; count:=0; output<='0'; end case; end if; end process;</code></pre><p><br><br> end Behavioral;</p><p>testbench:</p><p><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br><br> entity key_stroke_tb is<br> – Port ( );<br> end key_stroke_tb;</p><pre><code>architecture Behavioral of key_stroke_tb iscomponent key_stroke generic(CLK_FRE:integer:=50000000); port( clk:in std_logic; reset:in std_logic; key_in:in std_logic; output:out std_logic ); end component;signal clk:std_logic;signal reset:std_logic;signal key_in:std_logic;signal output:std_logic;beginks:key_stroke generic map(50000000)port map(clk,reset,key_in,output);clock:processbegin clk<='0'; wait for 10ns; clk<='1'; wait for 10ns;end process;rst:processbegin reset<='1'; wait for 25ns; reset<='0'; wait;end process;test:processbegin key_in<='1'; wait for 50ns; key_in<='0'; wait for 70ns; key_in<='1'; wait for 100ns; key_in<='0'; wait for 40ns; key_in<='1'; wait for 120ns; key_in<='0'; wait for 30ns; key_in<='1'; wait for 40ns; key_in<='0'; wait for 70ns; key_in<='1'; wait for 30ns; key_in<='0'; wait for 100ns; key_in<='1'; wait for 50ns; key_in<='0'; wait for 20ns; key_in<='1'; wait for 1000ns; key_in<='0'; wait for 2000ns;end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/2b1e4d12b3c904bbdb1f64914294b450.png"></p><h3 id="5-同步环形FIFO设计"><a href="#5-同步环形FIFO设计" class="headerlink" title="5.同步环形FIFO设计"></a>5.同步环形FIFO设计</h3><p>请采用硬件描述语言设计实现一个存储深度M和数据宽度N可以用户配置的同步FIFO存储器,请给出仿真结果。</p><p><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;<br><br> entity FIFO_ring is<br> generic(<br> depth:positive :=8;<br> width:positive:=8<br> );<br> Port(<br> clk:in std_logic;<br> rst:in std_logic;<br> data_in:in std_logic_vector(7 downto 0);<br> wr:in std_logic;<br> rd:in std_logic;<br> – wr_clr:in std_logic;<br> – wr_en:in std_logic;<br> – rd_clr:in std_logic;<br> – rd_en:in std_logic;</p><pre><code> empty:out std_logic; full:out std_logic; data_out:out std_logic_vector(7 downto 0) );end FIFO_ring;architecture Behavioral of FIFO_ring iscomponent duaramgeneric( depth:positive :=8; width:positive:=8);Port( clka:in std_logic; wr:in std_logic; addra:in std_logic_vector(depth-1 downto 0); datain:in std_logic_vector(width-1 downto 0); clkb:in std_logic; rd:in std_logic; addrb:in std_logic_vector(depth-1 downto 0); dataout:out std_logic_vector(width-1 downto 0)); end component;component write_pointer generic( depth:positive ); Port( clk:in std_logic; rst:in std_logic; wq:in std_logic; wr_pt:out std_logic_vector(depth-1 downto 0) );end component;component read_pointer generic( depth:positive ); Port( clk:in std_logic; rst:in std_logic; rq:in std_logic; rd_pt:out std_logic_vector(depth-1 downto 0) );end component;component judge_status generic( depth:positive ); port( clk:in std_logic; rst:in std_logic; wr_pt:in std_logic_vector(depth-1 downto 0); rd_pt:in std_logic_vector(depth-1 downto 0); empty:out std_logic; full:out std_logic );end component;signal rp_line:std_logic_vector(depth-1 downto 0);signal wp_line:std_logic_vector(depth-1 downto 0);beginduaram_inst:duaram generic map(depth,width)port map(clka=>clk,clkb=>clk,datain=>data_in,dataout=>data_out,addra=>wp_line,addrb=>rp_line,rd=>rd,wr=>wr);write_pointer_inst:write_pointer generic map(depth)port map(clk=>clk,rst=>rst,wq=>wr,wr_pt=>wp_line);read_pointer_inst:read_pointer generic map(depth)port map(clk=>clk,rst=>rst,rq=>rd,rd_pt=>rp_line);judge_status_inst:judge_status generic map(depth)port map(clk=>clk,rst=>rst,wr_pt=>wp_line,rd_pt=>rp_line,full=>full,empty=>empty);</code></pre><p><br> end Behavioral;</p><p><br><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;<br><br> entity duaram is<br> generic(<br> depth:positive :=8;<br> width:positive:=8<br> );<br> Port(<br> clka:in std_logic;<br> wr:in std_logic;<br> addra:in std_logic_vector(depth-1 downto 0);<br> datain:in std_logic_vector(width-1 downto 0);</p><pre><code> clkb:in std_logic; rd:in std_logic; addrb:in std_logic_vector(depth-1 downto 0); dataout:out std_logic_vector(width-1 downto 0));end duaram;architecture Behavioral of duaram istype ram is array(2**depth-1 downto 0)of std_logic_vector(width-1 downto 0);signal dualram:ram;beginprocess(clka,clkb)begin if(clka'event and clka='1')then if(wr='0')then dualram(conv_integer(addra))<=datain;end if; end if;end process;process(clkb)begin if(clkb'event and clkb='1')then if(rd='0')then dataout<=dualram(conv_integer(addrb));end if; end if;end process;end Behavioral;</code></pre><p><br><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;<br><br> entity write_pointer is<br> generic(<br> depth:positive<br> );<br> Port(<br> clk:in std_logic;<br> rst:in std_logic;<br> wq:in std_logic;<br> wr_pt:out std_logic_vector(depth-1 downto 0)<br> );<br> end write_pointer;</p><pre><code>architecture Behavioral of write_pointer issignal wr_pt_t:std_logic_vector(depth-1 downto 0);beginprocess(rst,clk)begin if(rst='0')then wr_pt_t<=(others=>'0'); elsif(clk'event and clk='1')then if wq='0'then wr_pt_t<=wr_pt_t+1;end if; end if; end process;wr_pt<=wr_pt_t;end Behavioral;</code></pre><p><br><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;<br><br> entity read_pointer is<br> generic(<br> depth:positive<br> );<br> Port(<br> clk:in std_logic;<br> rst:in std_logic;<br> rq:in std_logic;<br> rd_pt:out std_logic_vector(depth-1 downto 0)<br> );<br> end read_pointer;</p><pre><code>architecture Behavioral of read_pointer issignal rd_pt_t:std_logic_vector(depth-1 downto 0);beginprocess(rst,clk)begin if(rst='0')then rd_pt_t<=(others=>'0'); elsif(clk'event and clk='1')then if rq='0'then rd_pt_t<=rd_pt_t+1;end if; end if; end process;rd_pt<=rd_pt_t;end Behavioral;</code></pre><p><br><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;<br><br> entity judge_status is<br> generic(<br> depth:positive<br> );<br> port(<br> clk:in std_logic;<br> rst:in std_logic;<br> wr_pt:in std_logic_vector(depth-1 downto 0);<br> rd_pt:in std_logic_vector(depth-1 downto 0);<br> empty:out std_logic;<br> full:out std_logic<br> );<br> end entity judge_status;</p><pre><code>architecture Behavioral of judge_status isbeginprocess(rst,clk)begin if(rst='0')then empty<='1'; elsif clk'event and clk='1'then if wr_pt=rd_pt then empty<='1'; else empty<='0'; end if; end if; end process;process(rst,clk)begin if(rst='0')then full<='0'; elsif clk'event and clk='1'then if wr_pt>rd_pt then if(depth+rd_pt)=wr_pt then full<='1';else full<='0';end if; end if; end if; end process;end Behavioral;</code></pre><p>testbench:</p><p><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br><br> entity FIFO_ring_tb is<br> – Port ( );<br> end FIFO_ring_tb;</p><pre><code>architecture Behavioral of FIFO_ring_tb iscomponent FIFO_ringgeneric( depth:positive :=8; width:positive:=8); Port( clk:in std_logic; rst:in std_logic; data_in:in std_logic_vector(7 downto 0); wr:in std_logic; rd:in std_logic;-- wr_clr:in std_logic;-- wr_en:in std_logic;-- rd_clr:in std_logic;-- rd_en:in std_logic; empty:out std_logic; full:out std_logic; data_out:out std_logic_vector(7 downto 0) );end component;signal clk:std_logic;signal rst:std_logic;signal data_in:std_logic_vector(7 downto 0);signal wr:std_logic;signal rd:std_logic;signal empty:std_logic;signal full:std_logic;signal data_out:std_logic_vector(7 downto 0);beginFIFO_ring_inst:FIFO_ring generic map(8,8)port map(clk,rst,data_in,wr,rd,empty,full,data_out);clock:processbegin clk<='0'; wait for 10ns; clk<='1'; wait for 10ns;end process;reset:processbegin rst<='0'; wait for 25ns; rst<='1'; wait;end process;test:processbegin rd<='1'; wr<='1'; data_in<="00000000"; wait for 50ns; data_in<="00000001"; wr<='0'; wait for 20ns; wr<='1'; wait for 30ns; data_in<="00000010"; wr<='0'; wait for 20ns; wr<='1'; wait for 30ns; data_in<="00000100"; wr<='0'; wait for 20ns; wr<='1'; wait for 30ns; data_in<="00001000"; wr<='0'; wait for 20ns; wr<='1'; wait for 30ns; data_in<="00010000"; wr<='0'; wait for 20ns; wr<='1'; wait for 30ns; data_in<="00100000"; wr<='0'; wait for 20ns; wr<='1'; wait for 30ns; data_in<="01000000"; wr<='0'; wait for 20ns; wr<='1'; wait for 30ns; data_in<="10000000"; wr<='0'; wait for 20ns; wr<='1'; wait for 50ns; rd<='0'; wait for 20ns; rd<='1'; wait for 30ns; rd<='0'; wait for 20ns; rd<='1'; wait for 30ns; rd<='0'; wait for 20ns; rd<='1'; wait for 30ns; rd<='0'; wait for 20ns; rd<='1'; wait for 30ns; rd<='0'; wait for 20ns; rd<='1'; wait for 30ns; rd<='0'; wait for 20ns; rd<='1'; wait for 30ns; rd<='0'; wait for 20ns; rd<='1'; wait for 30ns; rd<='0'; wait for 20ns; rd<='1'; wait for 30ns; wait; end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/9085cd14c31cada75062d36a643fb2b5.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/4dbe7b6e7886a88433a6fb76f77ee7f8.png"></p><h3 id="6-线上实验——时钟模块设计"><a href="#6-线上实验——时钟模块设计" class="headerlink" title="6.线上实验——时钟模块设计"></a>6.线上实验——时钟模块设计</h3><p>采用硬件描述语言设计实现CPU时钟模块,输出信号包括四个节拍信号(每两个时钟周期一个节拍),时钟反相信号,时钟2分频信号及其反相信号,完成逻辑功能设计及仿真验证,并给出仿真结果。</p><p><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br><br> entity clock is<br> Port(<br> clk,rst:in std_logic;<br> clk1,nclk1:out std_logic; –clk<br> clk2,nclk2:out std_logic; –clk二分频<br> w0,w1,w2,w3:out std_logic –节拍信号<br> );<br> end clock;</p><pre><code>architecture Behavioral of clock isbeginprocess(clk)variable count_clk2:integer:=0;variable count_w:integer:=0;begin if(rst='0')then w0<='0'; w1<='0'; w2<='0'; w3<='0'; clk1<='0'; nclk1<='1'; clk2<='0'; nclk2<='1'; count_clk2:=0; count_w:=0; elsif(rst='1')then clk1<=clk; nclk1<=not clk; if(clk'event and clk='1')then if(count_clk2=0)then count_clk2:=1;clk2<='1';nclk2<='0'; elsif(count_clk2=1)then count_clk2:=0;clk2<='0';nclk2<='1'; end if; if(count_w>=0 and count_w<=3)then w0<='1';else w0<='0';end if; if(count_w>=4 and count_w<=7)then w1<='1';else w1<='0';end if; if(count_w>=8 and count_w<=11)then w2<='1';else w2<='0';end if; if(count_w>=12 and count_w<=15)then w3<='1';else w3<='0';end if; if(count_w<15)then count_w:=count_w+1;else count_w:=0;end if; end if; end if;end process;end Behavioral;</code></pre><p>testbench:</p><p><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br><br> entity clock_tb is<br> – Port ( );<br> end clock_tb;</p><pre><code>architecture Behavioral of clock_tb iscomponent clock Port( clk,rst:in std_logic; clk1,nclk1:out std_logic; --clk clk2,nclk2:out std_logic; --clk二分频 w0,w1,w2,w3:out std_logic --节拍信号 );end component;signal clk,rst:std_logic;signal clk1,nclk1:std_logic; --clksignal clk2,nclk2:std_logic; --clk二分频signal w0,w1,w2,w3:std_logic; --节拍信号beginclock_inst:clock port map(clk,rst,clk1,nclk1,clk2,nclk2,w0,w1,w2,w3);clock_gen:processbegin clk<='0'; wait for 10ns; clk<='1'; wait for 10ns;end process;reset_gen:processbegin rst<='0'; wait for 25ns; rst<='1'; wait;end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/adec0f2295677479c7321988b4b0f166.png"></p><h3 id="7-线上实验——原码二位乘法器设计"><a href="#7-线上实验——原码二位乘法器设计" class="headerlink" title="7.线上实验——原码二位乘法器设计"></a>7.线上实验——原码二位乘法器设计</h3><p>请用硬件描述语言设计一个原码二位乘法器,其中两个操作数位宽为8,请给出仿真结果。</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/7bb5fc46ac6d878964e59ddeb1fe803c.png"></p><p>顶层——multiplier_2bit:</p><p><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br><br> entity multiplier_2bit is<br> Port(<br> clk,start:in std_logic;<br> ain,bin:in std_logic_vector(7 downto 0);<br> done:out std_logic;<br> sout:inout std_logic_vector(15 downto 0)<br> );<br> end multiplier_2bit;</p><pre><code>architecture Behavioral of multiplier_2bit iscomponent multiplier_ctrl Port ( clk,start:in std_logic; clkout,rstall,done:out std_logic );end component;component multiplier_8bitshiftreg Port ( clk,load:in std_logic; din:in std_logic_vector(7 downto 0); qb0,qb1:out std_logic );end component;component multiplier_16bitreg Port ( clk,clr:in std_logic; d:in std_logic_vector(8 downto 0); q:out std_logic_vector(15 downto 0) );end component;component multiplier_selector Port ( clk,rst:in std_logic; a0,a1,cin:in std_logic; din:in std_logic_vector(7 downto 0); cout:out std_logic; dout:out std_logic_vector(7 downto 0) );end component;component multiplier_8bitadder Port ( clk,rst:in std_logic; cin:in std_logic; ain,bin:in std_logic_vector(7 downto 0); sout:out std_logic_vector(8 downto 0) );end component;signal clk_line:std_logic;signal rst_line:std_logic;signal cin_line:std_logic;signal qb1_line,qb0_line:std_logic;signal bin_line:std_logic_vector(7 downto 0);signal sout_line:std_logic_vector(8 downto 0);signal test_line:std_logic_vector(8 downto 0);beginmultiplier_ctrl_inst:multiplier_ctrl port map(clk=>clk,start=>start,clkout=>clk_line,rstall=>rst_line,done=>done);multiplier_8bitshiftreg_inst:multiplier_8bitshiftreg port map(clk=>clk_line,load=>rst_line,din=>ain,qb0=>qb0_line,qb1=>qb1_line);multiplier_16bitreg_inst:multiplier_16bitreg port map(clk=>clk_line,clr=>rst_line,d=>sout_line,q=>sout);multiplier_selector_inst:multiplier_selector port map(clk=>clk_line,rst=>rst_line,a0=>qb0_line,a1=>qb1_line,cin=>sout_line(8),din=>bin,cout=>cin_line,dout=>bin_line);multiplier_8bitadder_inst:multiplier_8bitadder port map(clk=>clk_line,rst=>rst_line,cin=>cin_line,ain=>sout(15 downto 8),bin=>bin_line,sout=>sout_line);end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/8f30332a988566f33bab93454ab0c0ca.png"></p><p>testbench:</p><p><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br><br> entity multiplier_2bit_tb is<br> – Port ( );<br> end multiplier_2bit_tb;</p><pre><code>architecture Behavioral of multiplier_2bit_tb iscomponent multiplier_2bit Port( clk,start:in std_logic; ain,bin:in std_logic_vector(7 downto 0); done:out std_logic; sout:inout std_logic_vector(15 downto 0) );end component;signal clk,start: std_logic;signal ain,bin: std_logic_vector(7 downto 0);signal done: std_logic;signal sout: std_logic_vector(15 downto 0);beginmultiplier_2bit_inst:multiplier_2bit port map(clk,start,ain,bin,done,sout);clock_gen:processbegin clk<='1'; wait for 10ns; clk<='0'; wait for 10ns;end process;test:processbegin ain<="10011010"; bin<="01100101"; wait for 25ns; start<='1'; wait for 25ns; start<='0'; wait for 150ns;end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/559a1c00923a7cda00c06f63c6dec1cc.png"></p><p>模块:</p><p>multiplier_2bit_ctrl :</p><p><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;<br> entity multiplier_ctrl is<br> Port (<br> clk,start:in std_logic;<br> clkout,rstall,done:out std_logic<br> );<br> end multiplier_ctrl;<br><br> architecture Behavioral of multiplier_ctrl is</p><pre><code>signal cnt3b:std_logic_vector(2 downto 0);beginprocess(clk,start)begin rstall<=start; if(start='1')then cnt3b<="000"; elsif clk'event and clk='1'then if cnt3b<=4 then cnt3b<=cnt3b+1;end if; end if;end process;process(clk,cnt3b,start)begin if (start='1')then clkout<='0';done<='0'; elsif(start='0')then if cnt3b<=4 then clkout<=clk; else clkout<='0';done<='1'; end if; end if;end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/920cb7c013bd5af2e09bc59aafba028c.png"></p><p>multiplier_2bit_8bitshiftreg:</p><p><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;<br> entity multiplier_8bitshiftreg is<br> Port (<br> clk,load:in std_logic;<br> din:in std_logic_vector(7 downto 0);<br> qb0,qb1:out std_logic<br> );<br> end multiplier_8bitshiftreg;<br><br> architecture Behavioral of multiplier_8bitshiftreg is</p><pre><code>signal reg8b:std_logic_vector(7 downto 0);beginprocess(clk,load)begin if load='1'then reg8b<=din;qb0<='0';qb1<='0';end if; if(load='0'and clk='1')then qb0<=reg8b(0); qb1<=reg8b(1); reg8b(5 downto 0)<=reg8b(7 downto 2); reg8b(7 downto 6)<="00"; end if; end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/d171f9dc0e6d54b72cf1ffe1f8c759ec.png"></p><p>multiplier_2bit_16bitreg:</p><p><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;<br> entity multiplier_16bitreg is<br> Port (<br> clk,clr:in std_logic;<br> d:in std_logic_vector(8 downto 0);<br> q:out std_logic_vector(15 downto 0)<br> );<br> end multiplier_16bitreg;<br><br> architecture Behavioral of multiplier_16bitreg is</p><pre><code>beginprocess(clk,clr)variable sr16b:std_logic_vector(15 downto 0);begin if clr='1'then sr16b:="0000000000000000"; elsif(clr='0'and clk'event and clk='1')then sr16b(15 downto 8):=d(7 downto 0); sr16b(13 downto 0):=sr16b(15 downto 2); sr16b(15):=d(8); sr16b(14):=d(8); end if; q<=sr16b;end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/08847d6e576be1f9f61c68f8d15899b6.png"></p><p>multiplier_2bit_selector:</p><p><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;<br> entity multiplier_selector is<br> Port (<br> clk,rst:in std_logic;<br> a0,a1,cin:in std_logic;<br> din:in std_logic_vector(7 downto 0);<br> cout:out std_logic;<br> dout:out std_logic_vector(7 downto 0)<br> );<br> end multiplier_selector;<br><br> architecture Behavioral of multiplier_selector is</p><pre><code>beginprocess(clk,a0,a1,cin,din)begin if(rst='1')then cout<='0';dout<="00000000"; elsif(rst='0'and clk'event and clk='0')then if(a0=a1 and a0=cin)then dout<="00000000";cout<=cin; elsif(a1='0'and (a0 xor cin)='1')then dout<=din;cout<='0'; elsif((a1 xor a0)='1'and a0=cin)then dout(7 downto 1)<=din(6 downto 0); dout(0)<='0'; cout<='0'; elsif(a1='1'and(a0 xor cin)='1')then dout<=(not din)+1; cout<='1'; end if; end if; end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/e286d15abce298cf0b629350ba7e076e.png"></p><p>multiplier_2bit_8bitadder:</p><p><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;<br> entity multiplier_8bitadder is<br> Port (<br> clk,rst:in std_logic;<br> cin:in std_logic;<br> ain,bin:in std_logic_vector(7 downto 0);<br> sout:out std_logic_vector(8 downto 0)<br> );<br> end multiplier_8bitadder;<br><br> architecture Behavioral of multiplier_8bitadder is<br> begin</p><pre><code>process(clk,rst,ain,bin,cin)begin if(rst='1')then sout<="000000000"; elsif(rst='0'and clk='0')then sout<=('0'& ain)+(cin & bin); end if;end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/cdd818c3fea80ef3bef0a36c7c6ab446.png"></p><p><strong>设计注意点:</strong></p><p>0.设计顺序:控制器-8b移位寄存器-16位缓存器-选择器-加法器</p><p>1.输入位8位无符号数,若输入有符号数需修改位宽并另外计算符号位。</p><p>2.共用总线需注意时序,防止总线冲突以及数据读取错误</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/b25fa007565503bdd4b69b5d6c31496d.png"></p><p>共用总线sout时序设计:</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/daac7ca07dca672e89a3e831d4b8bd9a.png"></p><p>3.process内语句顺序执行的次序。</p><p>4.变量的使用:mulitiplier_16bitreg中</p><p><br> variable sr16b:std_logic_vector(15 downto 0);</p><p>若使用 signal sr16b,则 q<=sr16b; 无效</p><p>5.位拓展:</p><p><br> sout<=(‘0’& ain)+(cin & bin); </p><p>使用 & 符拓展位宽</p><h3 id="8-线上实验——布斯乘法器设计"><a href="#8-线上实验——布斯乘法器设计" class="headerlink" title="8.线上实验——布斯乘法器设计"></a>8.线上实验——布斯乘法器设计</h3><p>采用硬件描述语言设计实现布斯乘法器,完成逻辑功能设计及仿真验证,并给出仿真结果。</p><p>按照7中的设计顺序对7中设计文件进行修改:</p><pre><code> ctrl模块发出时钟周期数改为8;8bitshiftreg和16bitreg模块每个时钟周期移动1位,且8;8bitshiftreg输出的是a0和a-1;16bitreg和selector模块载入数值后求补;selector模块删去cin和cout信号并修改规则;adder无cin...</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/8c09ab4e531a18f069ba4afb9e18d438.png"></p><p>顶层模块——multiplier_booth:</p><p><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br><br> entity multiplier_booth is<br> Port(<br> clk,start:in std_logic;<br> ain,bin:in std_logic_vector(7 downto 0);<br> done:out std_logic;<br> sout:inout std_logic_vector(15 downto 0)<br> );<br> end multiplier_booth;</p><pre><code>architecture Behavioral of multiplier_booth iscomponent multiplier_booth_ctrl Port ( clk,start:in std_logic; clkout,rstall,done:out std_logic );end component;component multiplier_booth_8bitshiftreg Port ( clk,load:in std_logic; din:in std_logic_vector(7 downto 0); qb0,qb1:out std_logic );end component;component multiplier_booth_16bitreg Port ( clk,clr:in std_logic; d:in std_logic_vector(8 downto 0); q:out std_logic_vector(15 downto 0) );end component;component multiplier_booth_selector Port ( clk,rst:in std_logic; a0,a1:in std_logic; din:in std_logic_vector(7 downto 0); dout:out std_logic_vector(7 downto 0) );end component;component multiplier_booth_8bitadder Port ( clk,rst:in std_logic; ain,bin:in std_logic_vector(7 downto 0); sout:out std_logic_vector(8 downto 0) );end component;signal clk_line:std_logic;signal rst_line:std_logic;signal qb1_line,qb0_line:std_logic;signal bin_line:std_logic_vector(7 downto 0);signal sout_line:std_logic_vector(8 downto 0);signal test_line:std_logic_vector(8 downto 0);beginmultiplier_booth_ctrl_inst:multiplier_booth_ctrl port map(clk=>clk,start=>start,clkout=>clk_line,rstall=>rst_line,done=>done);multiplier_booth_8bitshiftreg_inst:multiplier_booth_8bitshiftreg port map(clk=>clk_line,load=>rst_line,din=>ain,qb0=>qb0_line,qb1=>qb1_line);multiplier_booth_16bitreg_inst:multiplier_booth_16bitreg port map(clk=>clk_line,clr=>rst_line,d=>sout_line,q=>sout);multiplier_booth_selector_inst:multiplier_booth_selector port map(clk=>clk_line,rst=>rst_line,a0=>qb0_line,a1=>qb1_line,din=>bin,dout=>bin_line);multiplier_booth_8bitadder_inst:multiplier_booth_8bitadder port map(clk=>clk_line,rst=>rst_line,ain=>sout(15 downto 8),bin=>bin_line,sout=>sout_line);end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/d3e67513e1e27963a8e15f23f6a8cc7c.png"></p><p>testbench:</p><p><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br><br> entity multiplier_booth_tb is<br> – Port ( );<br> end multiplier_booth_tb;</p><pre><code>architecture Behavioral of multiplier_booth_tb iscomponent multiplier_booth Port( clk,start:in std_logic; ain,bin:in std_logic_vector(7 downto 0); done:out std_logic; sout:inout std_logic_vector(15 downto 0) );end component;signal clk,start: std_logic;signal ain,bin: std_logic_vector(7 downto 0);signal done: std_logic;signal sout: std_logic_vector(15 downto 0);beginmultiplier_booth_inst:multiplier_booth port map(clk,start,ain,bin,done,sout);clock_gen:processbegin clk<='1'; wait for 10ns; clk<='0'; wait for 10ns;end process;test:processbegin ain<="00000010"; bin<="10000010"; wait for 25ns; start<='1'; wait for 25ns; start<='0'; wait for 200ns;end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/4cd31e8dc5958ee6e4b4eedfd590f2fa.png"></p><p>模块:</p><p>multiplier_booth_ctrl:</p><p><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;<br> entity multiplier_booth_ctrl is<br> Port (<br> clk,start:in std_logic;<br> clkout,rstall,done:out std_logic<br> );<br> end multiplier_booth_ctrl;<br><br> architecture Behavioral of multiplier_booth_ctrl is</p><pre><code>signal cnt4b:std_logic_vector(3 downto 0);beginprocess(clk,start)begin rstall<=start; if(start='1')then cnt4b<="0000"; elsif clk'event and clk='1'then if cnt4b<=8 then cnt4b<=cnt4b+1;end if; end if;end process;process(clk,cnt4b,start)begin if (start='1')then clkout<='0';done<='0'; elsif(start='0')then if cnt4b<=8 then clkout<=clk; else clkout<='0';done<='1'; end if; end if;end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/83c13baff1be05be6cda0e582d59099f.png"></p><p>multiplier_booth_8bitshiftreg:</p><p><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;<br> entity multiplier_booth_8bitshiftreg is<br> Port (<br> clk,load:in std_logic;<br> din:in std_logic_vector(7 downto 0);<br> qb0,qb1:out std_logic<br> );<br> end multiplier_booth_8bitshiftreg;<br><br> architecture Behavioral of multiplier_booth_8bitshiftreg is</p><pre><code>signal reg8b:std_logic_vector(8 downto 0);beginprocess(clk,load)begin if load='1'then if(din(7)='1')then reg8b(8 downto 1)<=(din(7)&(not din(6 downto 0)))+1;else reg8b(8 downto 1)<=din;end if; --取补码 reg8b(0)<='0'; qb0<='0';qb1<='0'; end if; if(load='0'and clk='1')then qb0<=reg8b(0); qb1<=reg8b(1); reg8b(7 downto 0)<=reg8b(8 downto 1); reg8b(8)<='0'; end if; end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/61bbc405e10beaea2c2635a94871b4cb.png"></p><p>multiplier_booth_16bitreg:</p><p><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;<br> entity multiplier_booth_16bitreg is<br> Port (<br> clk,clr:in std_logic;<br> d:in std_logic_vector(8 downto 0);<br> q:out std_logic_vector(15 downto 0)<br> );<br> end multiplier_booth_16bitreg;<br><br> architecture Behavioral of multiplier_booth_16bitreg is</p><pre><code>beginprocess(clk,clr)variable sr16b:std_logic_vector(15 downto 0);begin if clr='1'then sr16b:="0000000000000000"; elsif(clr='0'and clk'event and clk='1')then sr16b(15 downto 8):=d(7 downto 0); sr16b(14 downto 0):=sr16b(15 downto 1); sr16b(15):=d(8); --移位复制符号位 end if; q<=sr16b;end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/78e8dae445e0aa8620fd29c657228abd.png"></p><p>multiplier_booth_selector:</p><p><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;<br> entity multiplier_booth_selector is<br> Port (<br> clk,rst:in std_logic;<br> a0,a1:in std_logic;<br> din:in std_logic_vector(7 downto 0);<br> dout:out std_logic_vector(7 downto 0)<br> );<br> end multiplier_booth_selector;<br><br> architecture Behavioral of multiplier_booth_selector is</p><pre><code>beginprocess(clk,a0,a1,din)variable complement_x:std_logic_vector(7 downto 0);variable complement_x_negative:std_logic_vector(7 downto 0);begin if(rst='1')then dout<="00000000"; elsif(rst='0'and clk'event and clk='0')then if(din(7)='1')then complement_x:=(din(7)&(not din(6 downto 0)))+1;else complement_x:=din;end if; --取X补码 if((not din(7))='1')then complement_x_negative:=((not din(7))&(not din(6 downto 0)))+1;else complement_x_negative:=(not din(7))&din(6 downto 0);end if; --取-X补码 if(a1=a0)then dout<="00000000"; elsif(a0='1'and a1='0')then dout<=complement_x; elsif(a0='0'and a1='1')then dout<=complement_x_negative; end if; end if; end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/9597c2a19cccbc17358d377d0ee32df8.png"></p><p>multiplier_booth_8bitadder:</p><p><br> library IEEE;<br> use IEEE.STD_LOGIC_1164.ALL;<br> use IEEE.STD_LOGIC_UNSIGNED.ALL;<br> entity multiplier_booth_8bitadder is<br> Port (<br> clk,rst:in std_logic;<br> ain,bin:in std_logic_vector(7 downto 0);<br> sout:out std_logic_vector(8 downto 0)<br> );<br> end multiplier_booth_8bitadder;<br><br> architecture Behavioral of multiplier_booth_8bitadder is<br> begin</p><pre><code>process(clk,rst,ain,bin)begin if(rst='1')then sout<="000000000"; elsif(rst='0'and clk='0')then sout<=(ain(7) & ain)+(bin(7) & bin); --符号位扩展加法 end if;end process;end Behavioral;</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/d7c983ed1ce45af2d329d820c088e9dd.png"></p><p><strong>设计注意点:</strong></p><p>1.求补码的方法:</p><p><br> if(din(7)=’1’)then<br> reg8b(8 downto 1)<=(din(7)&(not din(6 downto 0)))+1;<br> else reg8b(8 downto 1)<=din;<br> end if;<br> –取补码</p><p>2.求和时符号位拓展:</p><p><br> sout<=(ain(7) & ain)+(bin(7) & bin); –符号位扩展加法</p><p>本文转自 <a href="https://blog.csdn.net/qq_32971095/article/details/137247923">https://blog.csdn.net/qq_32971095/article/details/137247923</a>,如有侵权,请联系删除。</p>]]></content:encoded>
<category domain="https://xidianswq.github.io/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">学习笔记</category>
<category domain="https://xidianswq.github.io/tags/fpga%E5%BC%80%E5%8F%91/">fpga开发</category>
<category domain="https://xidianswq.github.io/tags/%E4%BD%9C%E4%B8%9A%E8%A7%A3%E7%AD%94/">作业解答</category>
<category domain="https://xidianswq.github.io/tags/vhdl/">vhdl</category>
<comments>https://xidianswq.github.io/2024/04/03/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/%E8%A5%BF%E7%94%B5%E8%AE%A1%E7%A7%91%E5%A4%A7%E4%B8%89%E4%B8%8BSOC%E5%BE%AE%E4%BD%93%E7%B3%BB%E7%BB%93%E6%9E%84%E8%AE%BE%E8%AE%A1%E4%BD%9C%E4%B8%9A%E5%90%88%E9%9B%86/#disqus_thread</comments>
</item>
<item>
<title>FPGA学习笔记(50)——Vitis AI</title>
<link>https://xidianswq.github.io/2024/03/29/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/FPGA%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0(50)%E2%80%94%E2%80%94Vitis%20AI/</link>
<guid>https://xidianswq.github.io/2024/03/29/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/FPGA%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0(50)%E2%80%94%E2%80%94Vitis%20AI/</guid>
<pubDate>Fri, 29 Mar 2024 09:29:19 GMT</pubDate>
<description><p>参考资料:</p></description>
<content:encoded><“)</p><p><a href="https://github.com/Xilinx/Vitis-AI" title="Xilinx/Vitis-AI: Vitis AI is Xilinx’s development stack for AI inference on Xilinx hardwareplatforms">Xilinx/Vitis-AI: Vitis AI is Xilinx’s development stack for AI inference on<br>Xilinx hardware platforms</a></p><p><a href="https://www.bilibili.com/video/BV1iR4y1k7wn/?spm_id_from=333.788&vd_source=01cde8042a76495bf513aa4407a56cd6" title="【03】ALINX Zynq UltraScale+ MPSoC XILINX FPGA视频教程Vitis AI开发">【03】ALINX Zynq UltraScale+ MPSoC XILINX FPGA视频教程Vitis<br>AI开发</a></p><h2 id="一-简介"><a href="#一-简介" class="headerlink" title="一. 简介"></a>一. 简介</h2><h3 id="1-简介"><a href="#1-简介" class="headerlink" title="1.简介"></a>1.简介</h3><p>边缘计算edge-ai;cloud-computing-edge-computing</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/089f9efe7c54689a339a571239a84873.png"></p><p>edge端inference全栈部署方案</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/966474c137754c658fddaa07152e7ef2.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/319a2ebc600fdfb819856d52d5825acc.png"></p><h4 id="安装vitis-ai的准备"><a href="#安装vitis-ai的准备" class="headerlink" title="安装vitis-ai的准备"></a>安装vitis-ai的准备</h4><p>In addition, Vitis AI supports three host types(对于三种类型的机器,安装vitis-ai需做一定准备:</p><blockquote><blockquote><ul><li>CPU-only with no GPU acceleration:CPU hosts require no special<br>preparation.<blockquote><ul><li>CUDA-capable GPUs</li></ul></blockquote></li></ul></blockquote></blockquote><blockquote><blockquote><ul><li>AMD ROCm™ GPUs:见[Vitis-<br>AI/docs/_sources/docs/install/install.rst.txt](<a href="https://github.com/Xilinx/Vitis-">https://github.com/Xilinx/Vitis-</a><br>AI/blob/master/docs/_sources/docs/install/install.rst.txt#id3 “Vitis-<br>AI/docs/_sources/docs/install/install.rst.txt”)</li></ul></blockquote></blockquote><blockquote><blockquote></blockquote></blockquote><p><1>安装docker、Clone github Repository:</p><p><br> git clone <a href="https://github.com/Xilinx/Vitis-AI">https://github.com/Xilinx/Vitis-AI</a><br> cd Vitis-AI</p><p>注:You are now ready to start working with the Vitis AI Docker container. At<br>this stage you will choose whether you wish to <strong>use the pre-built container,<br>or build the container from scripts</strong>. docker环境的搭建可以选择Vitis-<br>ai中的脚本搭建或者docker官方直接下载<strong>预构建的</strong> 特定架构docker(见后),即:</p><p><br> docker pull xilinx/vitis-ai-<Framework>-<Arch>:latest</p><table><thead><tr><th>Desired Docker</th><th><Framework></th><th><Arch></th></tr></thead><tbody><tr><td>PyTorch cpu-only</td><td>pytorch</td><td>cpu</td></tr><tr><td>TensorFlow 2 cpu-only</td><td>tensorflow2</td><td>cpu</td></tr><tr><td>TensorFlow 1.15 cpu-only</td><td>tensorflow</td><td>cpu</td></tr><tr><td>PyTorch ROCm</td><td>pytorch</td><td>rocm</td></tr><tr><td>TensorFlow 2 ROCm</td><td>tensorflow2</td><td>rocm</td></tr></tbody></table><p>或:</p><p><br> cd <Vitis-AI install path>/Vitis-AI<br> ./docker_run.sh xilinx/vitis-ai-<pytorch|tensorflow2|tensorflow>-<cpu|rocm>:latest</p><p>适用机器类型:</p><ol><li>CPU-only</li><li>CUDA-capable GPUs</li><li>ROCm-capable GPUs</li></ol><p>注:The <code>cpu</code> option <em>does not provide GPU acceleration support</em> which is<br><strong>strongly recommended</strong> for acceleration of the Vitis AI [:ref:<code>Quantization process <quantization-process></code>](<a href="https://github.com/Xilinx/Vitis-">https://github.com/Xilinx/Vitis-</a><br>AI/blob/master/docs/_sources/docs/install/install.rst.txt#id11<br>“:ref:<code>Quantization process <quantization-process></code> “). The pre-built <code>cpu</code><br>container should only be used when a GPU is not available on the host machine.</p><p>(原文详细介绍了在NVIDIA器件上支持CUDA GPU的vitis-ai搭建)</p><p>注:vitis-ai补丁安装:[Vitis-<br>AI/docs/_sources/docs/install/patch_instructions.rst.txt](<a href="https://github.com/Xilinx/Vitis-">https://github.com/Xilinx/Vitis-</a><br>AI/blob/master/docs/_sources/docs/install/patch_instructions.rst.txt “Vitis-<br>AI/docs/_sources/docs/install/patch_instructions.rst.txt”)</p><p><2>安装交叉编译环境</p><p>By default, the<strong>cross compiler</strong> will be installed in<br><strong><code>~/petalinux_sdk_2023.1</code></strong>. The ~/petalinux_sdk_2023.1 path is recommended<br>for the installation. Regardless of the path you choose for the installation,<br>make sure the path has read-write permissions. In this quickstart, it is<br>installed in ~/petalinux_sdk_2023.1</p><p>在bash中执行:</p><p><br> [Host] $ cd Vitis-AI/board_setup/vek280<br> [Host] $ sudo chmod u+r+x host_cross_compiler_setup.sh<br> [Host] $ ./host_cross_compiler_setup.sh</p><p>注:为下载相关资源,执行前的软件安装源为清华源,也可参考:[Vitis-<br>AI/docs/_sources/docs/install/China_Ubuntu_servers.](<a href="https://github.com/Xilinx/Vitis-">https://github.com/Xilinx/Vitis-</a><br>AI/blob/master/docs/_sources/docs/install/China_Ubuntu_servers.rst.txt “Vitis-<br>AI/docs/_sources/docs/install/China_Ubuntu_servers.”)</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/93def47e1072cf25c9fb7e564d9ac777.png"></p><p> When the installation is complete, follow the prompts and execute the<br>following command:</p><p><br> source ~/petalinux_sdk_2023.1/environment-setup-cortexa72-cortexa53-xilinx-linux</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/bc05d626369cb12f1b1b386fad291dfc.png"></p><pre><code> The **DPU** implements **an efficient tensor-level instruction set **designed to support and **accelerate** various popular **convolutional neural networks** , such as VGG, ResNet, GoogLeNet, YOLO, SSD, and MobileNet, among others. The DPU supports on AMD **Zynq™ UltraScale+™ MPSoCs, the Kria™ KV260, Versal™ and Alveo cards**. It scales to meet the requirements of many diverse applications in terms of throughput, latency, scalability, and power. </code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/acb9834ffdad75aafa209db3944d7929.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/b926c0530c9f863597c101da17b84dd2.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/7632c574e72b01f31355845825ac6439.png"></p><h5 id="Zynq-™-UltraScale-™-MPSoC-DPUCZDX8G-workflow-system"><a href="#Zynq-™-UltraScale-™-MPSoC-DPUCZDX8G-workflow-system" class="headerlink" title="Zynq ™ UltraScale+ ™ MPSoC: DPUCZDX8G([workflow-system-"></a>Zynq ™ UltraScale+ ™ MPSoC: DPUCZDX8G([workflow-system-</h5><p>integration.rst.txt at master](<a href="https://github.com/Xilinx/Vitis-">https://github.com/Xilinx/Vitis-</a><br>AI/blob/master/docs/_sources/docs/workflow-system-integration.rst.txt<br>“workflow-system-integration.rst.txt at master”)</p><p>The DPUCZDX8G IP has been optimized for Zynq UltraScale+ MPSoC. You can<br>integrate this IP as a block in the programmable logic (PL) of the selected<br>Zynq UltraScale+ MPSoCs with direct connections to the processing system (PS).<br>The DPU is user-configurable and exposes several parameters which can be<br>specified to optimize PL resources or customize enabled features.</p><p> 下载地址:</p><table><thead><tr><th>Product Guide</th><th>Platforms</th><th>Vitis AI Release</th><th>Reference Design</th><th>IP-only Download</th></tr></thead><tbody><tr><td>DPUCV2DX8G <a href="https://docs.xilinx.com/r/en-US/pg425-dpu" title="PG425">PG425</a></td><td></td><td></td><td></td><td></td></tr><tr><td>VEK280/V70/Vx2802</td><td>3.5</td><td></td><td></td><td></td></tr><tr><td>[Download](<a href="https://www.xilinx.com/bin/public/openDownload?filename=DPUCV2DX8G_VAI_v3.5.tar.gz">https://www.xilinx.com/bin/public/openDownload?filename=DPUCV2DX8G_VAI_v3.5.tar.gz</a></td><td></td><td></td><td></td><td></td></tr><tr><td>“Download”)</td><td>[Get</td><td></td><td></td><td></td></tr><tr><td>IP](<a href="https://www.xilinx.com/bin/public/openDownload?filename=DPUCV2DX8G_ip_repo_VAI_v3.5.tar.gz">https://www.xilinx.com/bin/public/openDownload?filename=DPUCV2DX8G_ip_repo_VAI_v3.5.tar.gz</a></td><td></td><td></td><td></td><td></td></tr><tr><td>“Get IP”)</td><td></td><td></td><td></td><td></td></tr><tr><td>DPUCV2DX8G <a href="https://docs.xilinx.com/r/en-US/pg425-dpu" title="PG425">PG425</a></td><td></td><td></td><td></td><td></td></tr><tr><td>VE2302(see note)</td><td>3.5</td><td>[Early Access](<a href="https://account.amd.com/en/member/vitis-">https://account.amd.com/en/member/vitis-</a></td><td></td><td></td></tr><tr><td>ai-ve2302.html “Early Access”)</td><td>[Early</td><td></td><td></td><td></td></tr><tr><td>Access](<a href="https://account.amd.com/en/member/vitis-ai-ve2302.html">https://account.amd.com/en/member/vitis-ai-ve2302.html</a> “Early Access”)</td><td></td><td></td><td></td><td></td></tr><tr><td>DPUCZDX8G <a href="https://docs.xilinx.com/r/en-US/pg338-dpu" title="PG338">PG338</a></td><td>MPSoC &</td><td></td><td></td><td></td></tr><tr><td>Kria K26</td><td>3.0</td><td></td><td></td><td></td></tr><tr><td>[Download](<a href="https://www.xilinx.com/bin/public/openDownload?filename=DPUCZDX8G_VAI_v3.0.tar.gz">https://www.xilinx.com/bin/public/openDownload?filename=DPUCZDX8G_VAI_v3.0.tar.gz</a></td><td></td><td></td><td></td><td></td></tr><tr><td>“Download”)</td><td>[Get</td><td></td><td></td><td></td></tr><tr><td>IP](<a href="https://www.xilinx.com/bin/public/openDownload?filename=DPUCZDX8G_ip_repo_VAI_v3.0.tar.gz">https://www.xilinx.com/bin/public/openDownload?filename=DPUCZDX8G_ip_repo_VAI_v3.0.tar.gz</a></td><td></td><td></td><td></td><td></td></tr><tr><td>“Get IP”)</td><td></td><td></td><td></td><td></td></tr><tr><td>DPUCVDX8G <a href="https://docs.xilinx.com/r/en-US/pg389-dpu" title="PG389">PG389</a></td><td>VCK190</td><td></td><td></td><td></td></tr><tr><td>3.0</td><td></td><td></td><td></td><td></td></tr><tr><td>[Download](<a href="https://www.xilinx.com/bin/public/openDownload?filename=DPUCVDX8G_VAI_v3.0.tar.gz">https://www.xilinx.com/bin/public/openDownload?filename=DPUCVDX8G_VAI_v3.0.tar.gz</a></td><td></td><td></td><td></td><td></td></tr><tr><td>“Download”)</td><td>[Get</td><td></td><td></td><td></td></tr><tr><td>IP](<a href="https://www.xilinx.com/bin/public/openDownload?filename=DPUCVDX8G_ip_repo_VAI_v3.0.tar.gz">https://www.xilinx.com/bin/public/openDownload?filename=DPUCVDX8G_ip_repo_VAI_v3.0.tar.gz</a></td><td></td><td></td><td></td><td></td></tr><tr><td>“Get IP”)</td><td></td><td></td><td></td><td></td></tr></tbody></table><p>For MPSoC and Versal AI Core (non AIE-ML devices) please refer to the**/dpu**<br>subdirectory in the Vitis AI 3.0 Github repository.</p><p><strong>部署过程:</strong>[Vitis-AI-Tutorials/Tutorials/Vitis-AI-Vivado-TRD at 2.0 ·<br>Xilinx/Vitis-AI-Tutorials (github.com)](<a href="https://github.com/Xilinx/Vitis-AI-">https://github.com/Xilinx/Vitis-AI-</a><br>Tutorials/tree/2.0/Tutorials/Vitis-AI-Vivado-TRD “Vitis-AI-<br>Tutorials/Tutorials/Vitis-AI-Vivado-TRD at 2.0 · Xilinx/Vitis-AI-Tutorials<br>(github.com)“)</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/959557dd80a7f6cf4d928cceb75051d3.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/0508c091f64853b67804b2e760e60cbb.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/3caf388ba1b35f2a14b2243c95dc133c.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/999d2443c9fa5ace609d9ea94ced32fa.png"></p><h3 id="2-实例"><a href="#2-实例" class="headerlink" title="2.实例"></a>2.实例</h3><p><img src="https://i-blog.csdnimg.cn/blog_migrate/7830ed03ef207f14e4a19700168625d9.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/fd38dd26c8c57234f377f0f7a4a2ef48.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/5558aa103e0c00df512de7552ebe3804.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/8bd66f3a8c93d2eb320e9af0f1109b3c.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/18e33f756df780499701f1488563de29.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/8913598ae8b0c899f6a709062fe876f9.png"></p><h3 id="3-vitis-ai的解决方案"><a href="#3-vitis-ai的解决方案" class="headerlink" title="3.vitis-ai的解决方案"></a>3.vitis-ai的解决方案</h3><p>The Vitis AI solution is packaged and delivered as follows:</p><ul><li>AMD open download: pre-built target <strong>images</strong> integrating the <strong>DPU</strong></li><li>Vitis AI <strong>docker containers</strong> : model development tools</li><li>Vitis AI <strong>github repository</strong> : model deployment libraries, setup scripts, examples and reference designs</li></ul><h3 id="4-vitis-ai工具链"><a href="#4-vitis-ai工具链" class="headerlink" title="4.vitis-ai工具链"></a>4.vitis-ai工具链</h3><p><strong>Model Development</strong><br><strong>Vitis AI Model Zoo</strong><br>The :ref:<code>Vitis AI Model Zoo <workflow-model-zoo></code> includes <strong>optimized deep<br>learning models</strong> to speed up the deployment of deep learning inference on<br>adaptable AMD platforms. These models cover different applications, including<br>ADAS/AD, video surveillance, robotics, and data center. You can get started<br>with these pre-trained models to enjoy the benefits of deep learning<br>acceleration.</p><p><strong>Vitis AI Model Inspector</strong><br>The :ref:<code>Vitis AI Model Inspector <model-inspector></code> is used to <strong>perform<br>initial sanity checks</strong> to confirm that t<strong>he operators and sequence of<br>operators</strong> in the graph is compatible with Vitis AI. Novel neural network<br>architectures, operators, and activation types are constantly being developed<br>and optimized for prediction accuracy and performance. Vitis AI provides<br>mechanisms to leverage operators that are not natively supported by your<br>specific DPU target.</p><p><strong>Vitis AI Optimizer</strong><br>The :ref:<code>Vitis AI Optimizer <model-optimization></code> exploits <strong>the notion of<br>sparsity</strong> to r<strong>educe the overall computational complexity</strong> for inference by<br>5x to 50x with minimal accuracy degradation. Many deep neural network<br>topologies employ significant levels of redundancy. This is particularly true<br>when the network backbone is optimized for prediction accuracy with training<br>datasets supporting many classes. In many cases, this redundancy can be<br>reduced by “pruning” some of the operations out of the graph.</p><p><strong>Vitis AI Quantizer</strong><br>The :ref:<code>Vitis AI Quantizer <model-quantization></code>, integrated as a component<br>of either TensorFlow or PyTorch, <strong>converts 32-bit floating-point weights</strong><br>and activations to<strong>fixed-point integers like INT8</strong> to reduce the computing<br>complexity without losing prediction accuracy. The fixed-point network model<br>requires less memory bandwidth and provides faster speed and higher power<br>efficiency than the floating-point model.</p><p><strong>Vitis AI Compiler</strong><br>The :ref:<code>Vitis AI Compiler <model-compilation></code> maps the AI quantized<br>model<strong>to a highly-efficient instruction set and dataflow model</strong>. The<br>compiler performs multiple optimizations; for example, batch normalization<br>operations are fused with convolution when the convolution operator precedes<br>the normalization operator. As the DPU supports <strong>multiple dimensions of<br>parallelism</strong> , efficient instruction scheduling is <strong>key to exploiting the<br>inherent parallelism</strong> and potential for <strong>data reuse</strong> in the graph. The<br>Vitis AI Compiler addresses such optimizations.</p><p><strong>Model Deployment<br>Vitis AI Runtime</strong><br>The :ref:<code>Vitis AI Runtime <vitis-ai-runtime></code> (VART) is<strong>a set of low-level<br>API functions</strong> that support the integration of the DPU into software<br>applications. VART is built on top of the Xilinx Runtime (XRT) amd provides a<br>unified high-level runtime for both Data Center and Embedded targets. Key<br>features of the <strong>Vitis AI Runtime API</strong> include:</p><p>Asynchronous <strong>submission</strong> of <strong>jobs</strong> to the <strong>DPU</strong>.<br>Asynchronous <strong>collection</strong> of <strong>jobs</strong> from the <strong>DPU</strong>.<br><strong>C++ and Python API</strong> implementations.<br>Support for <strong>multi-threading and multi-process</strong> execution.<br><strong>Vitis AI Library</strong><br>The :ref:<code>Vitis AI Library <vitis-ai-library></code> is a set of <strong>high-level<br>libraries and APIs built on top of the Vitis AI Runtime (VART)</strong>. The higher-<br>level APIs included in the Vitis AI Library give developers a head-start on<br>model deployment. While it is possible for developers to directly leverage the<br>Vitis AI Runtime APIs to deploy a model on AMD platforms, it is often more<br>beneficial to start with a ready-made example that incorporates the various<br>elements of a typical application, including:</p><p><strong>Simplified CPU-based pre and post-processing implementations.</strong><br>Vitis AI Runtime integration at an application level.<br><strong>Vitis AI Profiler</strong><br>The :ref:<code>Vitis AI Profiler <vitis-ai-profiler></code> profiles and visualizes AI<br>applications to find <strong>bottlenecks</strong> and allocates computing resources among<br>different devices. It is easy to use and requires no code changes. It can<br><strong>trace function calls</strong> and <strong>run time</strong> , and also <strong>collect hardware<br>information</strong> , including CPU, DPU, and memory utilization.</p><p>模型开发:示例模型、检查器(语法、适用性)、优化器(稀疏连接)、量化器(位宽)、编译器(DPU指令)</p><p>模型部署:VART(DPU API)、Library(优化预处理、后处理)、分析器(各环节运行时间)</p><h2 id="二-Docker环境搭建"><a href="#二-Docker环境搭建" class="headerlink" title="二.Docker环境搭建"></a>二.Docker环境搭建</h2><p>在第一部分“安装的准备”已经介绍了搭建的两种方法。</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/32b5b070bc91e1a49bc4d0cf742becc9.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/d0f0f5995489ccc5498b68acb9a6ac56.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/3fde56db0b1e14a450d2f3f07ce98f82.png"></p><p><br> sudo apt-get remove docker-engine docker-ce docker.io<br><br> sudo apt-get install curl</p><pre><code>curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -sudo apt-get update && sudo apt install docker-ce docker-ce-cll containerd.iosystemctl status dockersudo docker run hello-worldsudo usermod -aG docker $USERnewgrp dockerdocker run hello-worlddocker infodocker imagesdocker ps -a</code></pre><p>若安装docker-ce失败:</p><p><a href="https://mirror.tuna.tsinghua.edu.cn/help/docker-ce/" title="docker-ce | 镜像站使用帮助 | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror">docker-ce | 镜像站使用帮助 | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror</a></p><p>下载vitis-ai的docker:</p><p><a href="https://hub.docker.com/r/xilinx/vitis-ai-cpu" title="xilinx/vitis-ai-cpu - Docker Image | Docker Hub">xilinx/vitis-ai-cpu - Docker Image | Docker Hub</a></p><p><a href="https://hub.docker.com/r/xilinx/vitis-ai" title="xilinx/vitis-ai - Docker Image | Docker Hub">xilinx/vitis-ai - Docker Image | Docker Hub</a></p><pre><code>docker pull xilinx/vitis-ai</code></pre><p>使用git命令下载vitis-ai</p><p><br> git clone <a href="https://github.com/Xilinx/Vitis-AI">https://github.com/Xilinx/Vitis-AI</a></p><p>启动docker环境:vitis-ai目录下运行脚本</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/17de1dceb4e74e034696eb3b16af2272.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/53bfce013f7c4c2e53486eb49cae2149.png"></p><p>可以看到其工作目录为workspace,上机目录直接为系统根目录:</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/00f5736efd94ea115591a8121f7171b4.png"></p><p> 而且这个docker预装了conda,进入 tensorflow 的conda并打印其组件:</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/1a916ce4ff8de0d37df1060bec900bd9.png"></p><p>其他docker命令:[Docker最新超详细版教程通俗易懂(基础版) - 知乎<br>(zhihu.com)](<a href="https://zhuanlan.zhihu.com/p/442442997">https://zhuanlan.zhihu.com/p/442442997</a> “Docker最新超详细版教程通俗易懂(基础版)</p><ul><li>知乎 (zhihu.com)“)</li></ul><h2 id="三-实例"><a href="#三-实例" class="headerlink" title="三.实例"></a>三.实例</h2><h3 id="1-下载示例模型"><a href="#1-下载示例模型" class="headerlink" title="1.下载示例模型"></a>1.下载示例模型</h3><p>在model_zoo文件夹内可以浏览各种支持的模型,这里我们选择tf_yolov3_3.5,打开model_info.md文件:</p><p><br> # YOLOv3<br><br> ### Contents<br> 1. <a href="#Use-Case-and-Application">Use Case and Application</a><br> 2. <a href="#Specification">Specification</a><br> 3. <a href="#Paper-and-Architecture">Paper and Architecture</a><br> 4. <a href="#Dataset-Preparation">Dataset Preparation</a><br> 5. <a href="#Use-Guide">Use Guide</a><br> 6. <a href="#License">License</a><br> 7. <a href="#Note">Note</a></p><p><br> ### Use Case and Application<br><br> - Classic Object Detection<br> - Trained on VOC dataset</p><p><br> ### Specification<br><br> | Metric | Value |<br> | :—————– | :————————————– |<br> | Framework | TensorFlow2 |<br> | Prune Ratio | 0% |<br> | FLOPs | 65.63G |<br> | Input Dims (H W C) | 416,416,3 |<br> | FP32 Accuracy | 0.7846 mAP |<br> | INT8 Accuracy | 0.7729 mAP |<br> | Train Dataset | voc07+12_trainval |<br> | Test Dataset | voc07_test |<br> | Supported Platform | GPU, VEK280, V70 |</p><p><br> ### Paper and Architecture<br><br> 1. Network Architecture: YOLOv3</p><pre><code>2. Paper Link: https://arxiv.org/abs/1804.02767</code></pre><p><br> ### Dataset Preparation<br><br> 1. Dataset description</p><pre><code>The model is trained on VOC2007_trainval + VOC2012_trainval and tested on VOC2007_test.2. Download and prepare the datasetOur script `prepare_data.sh` downloads and prepares the dataset automatically. But if you have downloaded the VOC2007 test set before, you could place them in the `data` directory manually and choose to skip downloading the dataset when the script asking for a choice. Run the script: <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">bash code/test/dataset_tools/prepare_data.sh</span><br></pre></td></tr></table></figure>Dataset diretory structure <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">VOCdevkit is unpacked from the downloaded data</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">voc2007_test is generated by our code <span class="keyword">for</span> data preparation</span></span><br><span class="line">+ data</span><br><span class="line"> + VOCdevkit</span><br><span class="line"> + VOC2007</span><br><span class="line"> + ImageSets</span><br><span class="line"> + JPEGImages</span><br><span class="line"> + Annotations</span><br><span class="line"> + voc2007_test</span><br><span class="line"> + images</span><br><span class="line"> + 000001.jpg</span><br><span class="line"> + 000002.jpg</span><br><span class="line"> + ...</span><br><span class="line"> + test.txt</span><br><span class="line"> + gt_detection.txt</span><br></pre></td></tr></table></figure></code></pre><p><br> ### Use Guide<br><br> 1. Evaluation<br> Configure the model path and data path in <a href="code/test/run_eval.sh">code/test/run_eval.sh</a><br> <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">bash code/test/run_eval.sh</span><br></pre></td></tr></table></figure></p><p><br> ### License<br><br> Apache License 2.0</p><pre><code>For details, please refer to **[Vitis-AI License](https://github.com/Xilinx/Vitis-AI/blob/master/LICENSE)**</code></pre><p><br> ### Note<br><br> 1. Data preprocess<br> <figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">data channel order: RGB(0~255)</span><br><span class="line">input = input / 255</span><br><span class="line">resize: keep aspect ratio of the raw image and resize it to make the length of the longer side equal to 416</span><br><span class="line">padding: pad along the short side with 0.5 to generate the input image with size = 416 x 416</span><br></pre></td></tr></table></figure><br> 2. Node information</p><pre><code> <figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">input node: 'input_1:0'</span><br><span class="line">output nodes: 'conv2d_59/BiasAdd:0', 'conv2d_67/BiasAdd:0', 'conv2d_75/BiasAdd:0'</span><br></pre></td></tr></table></figure></code></pre><p><br> ### Quantize<br><br> 1. Quantize tool installation</p><pre><code> Please refer to [vai_q_tensorflow](../../../src/vai_quantizer/vai_q_tensorflow1.x) 2. Quantize workspace You could use code/quantize/ folder.</code></pre><p><strong>详细阅读该文件介绍,接下来下载所需文件:</strong></p><p>在model_zoo文件夹,运行downloader.py,下载tf_yolov3_3.5</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/c9a7d62a708af32a1de4b5d1c059a76e.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/13689caf7d2c1dcba28ba1b59e594a71.png"></p><p> 下载后对文件进行解压:</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/154c0219b2383c095a676e4a40d64715.png"></p><p>通常model-zoo提供的模型文件结构如下:</p><p>tensorflow:</p><p><br> ├── code # Contains test code that can execute the model on the target and showcase model performance.<br> │<br> │<br> ├── readme.md # Documents the environment requirements, data pre-processing requirements, and model information.<br> │ Developers should refer to this to understand how to test the model with scripts.<br> │<br> ├── data # The dataset target directory that can be used for model verification and training.<br> │ When test or training scripts run successfully, the dataset will be placed in this directory.<br> │<br> ├── quantized<br> │ └── quantize_eval_model.pb # Quantized model for evaluation.<br> │<br> └── float<br> └── frozen.pb # The floating-point frozen model is used as the input to the quantizer.<br> The naming of the protobuf file may differ from the model naming used in the model list.</p><p>pytorch:</p><p><br> ├── code # Contains test and training code.<br> │<br> │<br> ├── readme.md # Contains the environment requirements, data pre-processing requirements and model information.<br> │ Developers should refer to this to understand how to test and train the model with scripts.<br> │<br> ├── data # The dataset target directory that is used for model verification and training.<br> │ When test or training scripts run successfully, the dataset will be placed in this directory.<br> │<br> ├── qat # Contains the QAT (Quantization Aware Training) results.<br> │ For some models, the accuracy of QAT is higher than with Post Training Quantization (PTQ) methods.<br> │ Some models, but not all, provide QAT reference results, and only these models have a QAT folder.<br> │<br> ├── quantized<br> │ ├── _int.pth # Quantized model.<br> │ ├── quant_info.json # Quantization steps of tensors got. Please keep it for evaluation of quantized model.<br> │ ├── _int.py # Converted vai_q_pytorch format model.<br> │ └── _int.xmodel # Deployed model. The name of different models may be different.<br> │ For some models that support QAT you could find better quantization results in ‘qat’ folder.<br> │<br> │<br> └── float<br> └── _int.pth # Trained float-point model. The pth name of different models may be different.<br> Path and model name in test scripts could be modified according to actual situation.</p><p>打开下载好的tf_yolov3_3.5文件夹,其中按照之前的model_info文件所叙述的内容,进行“Download and prepare the<br>dataset”(不是必须运行):</p><p><br> bash code/test/dataset_tools/prepare_data.sh</p><p>下载好的文件结构也在md文件中,在docker中执行评估(不是必须运行)(docker外需配置环境cv2、numpy):</p><p><br> bash code/test/run_eval.sh</p><p>评估结果:</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/38b92c92fb4b1a06262e88117770e500.png"></p><p>安装snap和snapcraft后安装模型查看工具netron:</p><p><br> sudo apt-get install snap<br> sudo apt-get install snapcraft<br> sudo snap install netron</p><p>然后就可以查看float文件夹下的pb文件网络的结构:</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/4a57b4d4b3f8c4bcd95910f16c04e505.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/a5c9e1dc7906295e163c8989b3a3b743.png"></p><p><br> 1. Data preprocess<br> <code> data channel order: RGB(0~255) input = input / 255 resize: keep aspect ratio of the raw image and resize it to make the length of the longer side equal to 416 padding: pad along the short side with 0.5 to generate the input image with size = 416 x 416 </code><br> 2. Node information<br><br> <figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">input node: 'input_1:0'</span><br><span class="line">output nodes: 'conv2d_59/BiasAdd:0', 'conv2d_67/BiasAdd:0', 'conv2d_75/BiasAdd:0'</span><br></pre></td></tr></table></figure></p><p>可以看到在第59、67、75个conv2d节点后进行了输出:</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/030fa826ada83d08a466bb23919680bc.png"></p><h3 id="2-模型量化"><a href="#2-模型量化" class="headerlink" title="2.模型量化"></a>2.模型量化</h3><p>在上述md文件最后给出了量化指引:</p><p><br> ### Quantize<br><br> 1. Quantize tool installation</p><pre><code> Please refer to [vai_q_tensorflow](../../../src/vai_quantizer/vai_q_tensorflow1.x) 2. Quantize workspace You could use code/quantize/ folder.</code></pre><p>量化参考vitis-ai文件夹下src…和code/quantize/里的内容</p><p>在code/quantize/中的config.ini是配置文件,包括量化后模型名、存放位置为/quantized及各种参数;</p><p>打开quantize.sh脚本,关注以下内容:</p><p><br> source ./config.ini<br><br> vai_q_tensorflow quantize <br> –input_frozen_graph $FLOAT_MODEL <br> –input_nodes $Q_INPUT_NODE <br> –input_shapes ?,$INPUT_HEIGHT,$INPUT_WIDTH,3 <br> –output_nodes $Q_OUTPUT_NODE <br> –input_fn $CALIB_INPUT_FN <br> –method $METHOD <br> –gpu $GPUS <br> –calib_iter $CALIB_ITER <br> –output_dir $QUANTIZE_DIR \</p><p>可以看到在量化过程中其调用config.ini中的各种参数,然后通过src/vai_quantizer/vai_q_tensorflow1.x工具进行量化,转到对应位置,在readme文件中可以看到详细信息:</p><p>[Vitis-AI/src/vai_quantizer/vai_q_tensorflow1.x at master · Xilinx/Vitis-AI<br>(github.com)](<a href="https://github.com/Xilinx/Vitis-">https://github.com/Xilinx/Vitis-</a><br>AI/tree/master/src/vai_quantizer/vai_q_tensorflow1.x “Vitis-<br>AI/src/vai_quantizer/vai_q_tensorflow1.x at master · Xilinx/Vitis-AI<br>(github.com)“)</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/9d34d43f9036308c8f83f589b763afd2.jpeg"></p><p><br> #目的:<br> The process of inference is computation intensive and requires a high memory bandwidth to satisfy the low-latency and high-throughput requirement of edge applications.<br><br> #介绍(vitis-ai工具只包含量化工具,修建工具在optimizer中):<br> Quantization and channel pruning techniques are employed to address these issues while achieving high performance and high energy efficiency with little degradation in accuracy. Quantization makes it possible to use integer computing units and to represent weights and activations by lower bits, while pruning reduces the overall required operations. In the Vitis AI quantizer, only the quantization tool is included. The pruning tool is packaged in the Vitis AI optimizer. Contact the support team for the Vitis AI development kit if you require the pruning tool.</p><p> </p><p>将32位浮点数转化为8位整数:</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/b4e03ee0be4436f378980db2d44681b1.jpeg"></p><p>量化的步骤:</p><p><br> ## Running vai_q_tensorflow<br> ### Preparing the Float Model and Related Input Files<br> |1|frozen_graph.pb|Floating-point frozen inference graph. Ensure that the graph is the inference graph rather than the training graph.|<br> |2|calibration dataset|A subset of the training dataset containing 100 to 1000 images.|<br> |3|input_fn|An input function to convert the calibration dataset to the input data of the frozen_graph during quantize calibration. Usually performs data pre-processing and augmentation.|<br> #### <strong>Generating the Frozen Inference Graph</strong><br> Training a model with TensorFlow 1.x creates a folder containing a GraphDef file (usually ending with <em>a.pb</em> or <em>.pbtxt</em> extension) and a set of checkpoint files. What you need for mobile or embedded deployment is a single GraphDef file that has been “frozen,” or had its variables converted into inline constants, so everything is in one file. To handle the conversion, TensorFlow provides <em>freeze_graph.py</em>, which is automatically installed with the vai_q_tensorflow quantizer.<br> #### <strong>Preparing the Calibration Dataset and Input Function</strong><br> The calibration set is usually a subset of the training/validation dataset or actual application images (at least 100 images for performance). The input function is a Python importable function to load the calibration dataset and perform data preprocessing. The vai_q_tensorflow quantizer can accept an input_fn to do the preprocessing, which is not saved in the graph. If the preprocessing subgraph is saved into the frozen graph, the input_fn only needs to read the images from dataset and return a feed_dict.<br> ### Quantizing the Model Using vai_q_tensorflow<br> ### Generating the Quantized Model<br> - <em>quantize_eval_model.pb</em> is used to evaluate the CPU/GPUs, and can be used to simulate the results on hardware.<br> |1|deploy_model.pb|Quantized model for the Vitis AI compiler (extended TensorFlow format) for targeting DPUCZDX8G implementations.|<br> |2|quantize_eval_model.pb|Quantized model for evaluation (also, the Vitis AI compiler input for most DPU architectures, like DPUCAHX8H, and DPUCADF8H).|<br> ### (Optional) Fast Finetune<br> Fast finetune adjusts the weights layer by layer with calibration dataset and may get better accuracy for some models. It will take much longer time than normal PTQ (still shorter than QAT as calibration dataset is much smaller than train dataset) and is disabled by default to save time, and can be turned on to try to improve the performance if you see accuracy issues.<br> ### (Optional) Exporting the Quantized Model to ONNX<br> The quantized model is tensorflow protobuf format by default. If you want to get a ONNX format model, just add <em>output_format</em> to the <em>vai_q_tensorflow</em> command.<br> ### (Optional) Evaluating the Quantized Model<br> If you have scripts to evaluate floating point models, like the models in <a href="https://github.com/Xilinx/Vitis-AI/tree/master/model_zoo">Vitis AI Model Zoo</a>, apply the following two changes to evaluate the quantized model:…<br> ### (Optional) Dumping the Simulation Results<br><br> ## vai_q_tensorflow Quantization Aware Training<br> Quantization aware training (QAT, also called <em>quantize finetuning</em> in <a href="#quantization-overview">Quantization Overview</a>) is similar to float model training/finetuning, but in QAT, the vai_q_tensorflow APIs are used to rewrite the float graph to convert it to a quantized graph before the training starts. The typical workflow is as follows:…<br> ### Generated Files<br> ### QAT APIs for TensorFlow 1.x</p><pre><code>## Converting to Float16 or BFloat16The vai_q_tensorflow supports data type conversions for float models, including Float16, BFloat16, Float, and Double. To achieve this, you can add *convert_datatype* to the vai_q_tensorflow command. ## vai_q_tensorflow Supported Operations and APIs</code></pre><p> 在准备阶段包括:推理图的固化(freeze_graph.py已安装在vai_q_tensorflow内)、准备验证数据集和输入函数…</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/2035fe160556f3713512b51266287de1.png"></p><p>关于vai_q_tensorflow命令的详细使用见readme中的vai_q_tensorflow Usage,例:</p><p><br> #show help:<br> $vai_q_tensorflow –help<br><br> #quantize:<br> $vai_q_tensorflow quantize –input_frozen_graph frozen_graph.pb <br> –input_nodes inputs <br> –output_nodes predictions <br> –input_shapes ?,224,224,3 <br> –input_fn my_input_fn.calib_input</p><pre><code>#dump quantized model:$vai_q_tensorflow dump --input_frozen_graph quantize_results/quantize_eval_model.pb \--input_fn my_input_fn.dump_input</code></pre><p>将 /float/文件夹下的fb文件重命名为float.fb,在docker环境中转到/quantize文件夹下运行量化脚本(下载包含运行后文件,非必要):</p><p><br> bash quantize.sh</p><p>运行结果如下:</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/d38f0ab41704bb97f91f371d5b4c3cfd.png"></p><p>量化后的模型文件位于/quantize的pb文件,继续运行/quantize下的evaluate_quantize_model.sh文件(非必要)对量化后的模型进行评估,结果如下:</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/4c32c7a9a74429a18ef81f04ae3638c1.png"></p><h3 id="3-模型编译"><a href="#3-模型编译" class="headerlink" title="3.模型编译"></a>3.模型编译</h3><h2 id="四-mpsoc快速开始"><a href="#四-mpsoc快速开始" class="headerlink" title="四.mpsoc快速开始"></a>四.mpsoc快速开始</h2><p>见:[Vitis-AI/docs/_sources/docs/quickstart/mpsoc.rst.txt at v3.5 ·<br>Xilinx/Vitis-AI (github.com)](<a href="https://github.com/Xilinx/Vitis-">https://github.com/Xilinx/Vitis-</a><br>AI/blob/v3.5/docs/_sources/docs/quickstart/mpsoc.rst.txt “Vitis-<br>AI/docs/_sources/docs/quickstart/mpsoc.rst.txt at v3.5 · Xilinx/Vitis-AI<br>(github.com)“)</p><p>(适合xilinx官方开发板zcu102、zcu104、kv260)</p><h2 id="五-官方资料"><a href="#五-官方资料" class="headerlink" title="五.官方资料"></a>五.官方资料</h2><p>vivado_integration:</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/6c5bf2b5b0093972699eb12988ab59d9.png"></p><p>vitis_integration:</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/478de52c0e6c34207461eb523f74eb5a.png"></p><p>vek280_setup:</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/781bf68946aadd0ca2d81fe1be31e3f9.png"></p><p>本文转自 <a href="https://blog.csdn.net/qq_32971095/article/details/136803363">https://blog.csdn.net/qq_32971095/article/details/136803363</a>,如有侵权,请联系删除。</p>]]></content:encoded>
<category domain="https://xidianswq.github.io/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">学习笔记</category>
<category domain="https://xidianswq.github.io/tags/fpga%E5%BC%80%E5%8F%91/">fpga开发</category>
<category domain="https://xidianswq.github.io/tags/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%A1%AC%E4%BB%B6/">嵌入式硬件</category>
<category domain="https://xidianswq.github.io/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">学习笔记</category>
<category domain="https://xidianswq.github.io/tags/AI/">AI</category>
<comments>https://xidianswq.github.io/2024/03/29/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/FPGA%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0(50)%E2%80%94%E2%80%94Vitis%20AI/#disqus_thread</comments>
</item>
<item>
<title>AI学习笔记</title>
<link>https://xidianswq.github.io/2024/03/29/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/AI%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/</link>
<guid>https://xidianswq.github.io/2024/03/29/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/AI%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/</guid>
<pubDate>Fri, 29 Mar 2024 09:28:37 GMT</pubDate>
<description><p><strong>目录</strong></p></description>
<content:encoded><</p><p><a href="about:blank#3.%E5%8D%95%E5%B1%82%E6%84%9F%E7%9F%A5%E5%99%A8%E6%A8%A1%E5%9E%8B">3.单层感知器模型</a></p><p><a href="about:blank#%3C1%3E%E5%88%9B%E5%BB%BA%E6%95%B0%E6%8D%AE%E9%9B%86%EF%BC%8CX%E4%B8%BA%E7%89%B9%E5%BE%81%E5%90%91%E9%87%8F%EF%BC%8CY%E4%B8%BA%E6%A0%87%E7%AD%BE%EF%BC%9A"><1>创建数据集,X为特征向量,Y为标签:</a></p><p><a href="about:blank#%3C2%3E%C2%A0%E5%89%8D%E5%90%91%E4%BC%A0%E6%92%AD%E8%AE%A1%E7%AE%97%E8%BF%87%E7%A8%8B%EF%BC%9A%C2%A0"><2> 前向传播计算过程:</a></p><p><a href="about:blank#%3C3%3E%E4%BD%BF%E7%94%A8softmax%E5%87%BD%E6%95%B0%E8%BD%AC%E6%8D%A2%E4%B8%BA%E6%A6%82%E7%8E%87%EF%BC%9A"><3>使用softmax函数转换为概率:</a></p><p><a href="about:blank#%3C4%3E%E4%BA%A4%E5%8F%89%E7%86%B5%E6%8D%9F%E5%A4%B1%E5%87%BD%E6%95%B0"><4>交叉熵损失函数</a></p><p><a href="about:blank#%3C5%3ELoss%20Minimization%20Problem%20and%20Network%20Training%EF%BC%9A"><5>Loss Minimization Problem and Network<br>Training:</a></p><p><a href="about:blank#%3C6%3E%E5%87%BD%E6%95%B0%E5%B0%8F%E7%BB%93"><6>函数小结</a></p><p><a href="about:blank#%3C7%3ETraining%20the%20Model%C2%A0"><7>Training the Model </a></p><p><a href="about:blank#4.%E7%BD%91%E7%BB%9C%E6%A8%A1%E5%9E%8B">4.网络模型</a></p><p><a href="about:blank#%3C1%3E%E5%AE%9A%E4%B9%89%E7%BD%91%E7%BB%9C%E7%B1%BB%EF%BC%9A"><1>定义网络类:</a></p><p><a href="about:blank#%3C2%3EMulti-Layered%20Models"><2>Multi-Layered Models</a></p><p><a href="about:blank#5.%E4%BB%A3%E7%A0%81%E6%95%B4%E5%90%88">5.代码整合</a></p><p><a href="about:blank#6.3-layer%20network%20%E5%AE%9E%E7%8E%B0%20mnist%20%E6%89%8B%E5%86%99%E6%95%B0%E5%AD%97%E8%AF%86%E5%88%AB">6.3-layer network 实现 mnist<br>手写数字识别</a></p><p><a href="about:blank#%E5%85%AD.Neural%20Network%20Frameworks">六.Neural Network<br>Frameworks</a></p><p><a href="about:blank#1.Keras">1.Keras</a></p><p>[<1>Training One-Layer Network<br>(Perceptron)](about:blank#%3C1%3ETraining%20One-<br>Layer%20Network%20%28Perceptron%29)</p><p><a href="about:blank#%E2%91%A0%E6%A8%A1%E5%9E%8B%E5%AE%9A%E4%B9%89">①模型定义</a></p><p><a href="about:blank#%E2%91%A1%E6%A8%A1%E5%9E%8B%E7%BC%96%E8%AF%91%EF%BC%88%E6%8C%87%E5%AE%9A%E6%8D%9F%E5%A4%B1%E5%87%BD%E6%95%B0%E3%80%81%E4%BC%98%E5%8C%96%E6%96%B9%E6%B3%95%E3%80%90%E6%A2%AF%E5%BA%A6%E4%B8%8B%E9%99%8D%E7%AD%89%E3%80%91%E3%80%81%E7%B2%BE%E5%BA%A6%EF%BC%89">②模型编译(指定损失函数、优化方法【梯度下降等】、精度)</a></p><p><a href="about:blank#%E2%91%A2%E8%AE%AD%E7%BB%83">③训练</a></p><p>[<2>Multi-Class Classificatio(多分类问题)](about:blank#%3C2%3EMulti-<br>Class%20Classificatio%EF%BC%88%E5%A4%9A%E5%88%86%E7%B1%BB%E9%97%AE%E9%A2%98%EF%BC%89)</p><p>[<3>Multi-Label Classification(多标签分类)](about:blank#%3C3%3EMulti-<br>Label%20Classification%EF%BC%88%E5%A4%9A%E6%A0%87%E7%AD%BE%E5%88%86%E7%B1%BB%EF%BC%89)</p><p><a href="about:blank#%3C4%3E%E6%80%BB%E7%BB%93%C2%A0Summary%20of%20Classification%20Loss%20Functions"><4>总结 Summary of Classification Loss<br>Functions</a></p><hr><p>参考资料:<a href="https://github.com/microsoft/AI-For-Beginners" title="microsoft/AI-For-Beginners: 12 Weeks, 24 Lessons, AI for All! (github.com)">microsoft/AI-For-Beginners: 12 Weeks, 24 Lessons, AI for All!<br>(github.com)</a></p><h2 id="一-续opencv——级联分类器"><a href="#一-续opencv——级联分类器" class="headerlink" title="一.续opencv——级联分类器"></a>一.续opencv——级联分类器</h2><p> <a href="https://blog.csdn.net/qq_32971095/article/details/131609797" title="OpenCV学习笔记——《基于OpenCV的数字图像处理》_opencv 数字图像处理-CSDN博客">OpenCV学习笔记——《基于OpenCV的数字图像处理》_opencv 数字图像处理-<br>CSDN博客</a></p><p><br> #include “opencv.hpp”<br> #include “highgui.hpp”<br> #include “imgproc.hpp”<br> #include <iostream><br> using namespace cv;<br> using namespace std;<br> #pragma comment(lib,”opencv_world480d.lib”)<br><br> VideoCapture capture(0);<br> Mat image;<br> CascadeClassifier face_cascade;<br> // 人脸检测<br> vector<Rect> faces;<br><br> int main()<br> {<br> Mat frame_gray;<br> face_cascade.load(“OPENCV安装路径/opencv/sources/data/haarcascades/haarcascade_frontalface_alt.xml”);<br> while (capture.isOpened())<br> {<br> capture >> image;<br> if (image.empty())break;</p><pre><code> if (waitKey(1) == 27)break; // BGR2GRAY cvtColor(image, frame_gray, COLOR_BGR2GRAY); face_cascade.detectMultiScale(frame_gray, faces); for (size_t i = 0; i < faces.size(); i++) { // 人脸画框 rectangle(image, faces[i], Scalar(255, 0, 0), 1, 8); } imshow("Face detection",image); }}</code></pre><h2 id="二-c语言实现进化算法"><a href="#二-c语言实现进化算法" class="headerlink" title="二.c语言实现进化算法"></a>二.c语言实现进化算法</h2><p><a href="https://blog.csdn.net/qq_32971095/article/details/136715239" title="c语言实现进化算法——人工智能导论<1>-CSDN博客">c语言实现进化算法——人工智能导论<1>-CSDN博客</a></p><h2 id="三-LeNet-网络实现-MNIST-手写数字识别"><a href="#三-LeNet-网络实现-MNIST-手写数字识别" class="headerlink" title="三.LeNet 网络实现 MNIST 手写数字识别"></a>三.LeNet 网络实现 MNIST 手写数字识别</h2><p><a href="https://download.csdn.net/download/qq_32971095/88681364?spm=1001.2014.3001.5501" title="西电计科大三上计算机视觉作业">西电计科大三上计算机视觉作业</a></p><h2 id="四-the-simplest-neural-network-model"><a href="#四-the-simplest-neural-network-model" class="headerlink" title="四.the simplest neural network model"></a>四.the simplest neural network model</h2><p>one-layered perceptron, a linear two-class classification model.(单层线性感知机)</p><p>Perceptron Model:</p><pre><code> 假设我们的模型中有N个特征,在这种情况下,输入向量将是一个大小为N的向量。感知器是一个二元分类模型,即它可以区分两类输入数据。我们将假设对于每个输入向量x,感知器的输出将是+1或-1,这取决于类别。输出将使用以下公式计算:</code></pre><p>y(x) = f(wTx)</p><p>Training the Perceptron:</p><pre><code> 为了训练感知器,我们需要找到一个权重向量w,它能正确地分类大多数值,即产生最小的误差。该误差由感知器准则定义如下:</code></pre><p>E(w) = -∑wTxiti</p><p>对那些导致错误分类的训练数据点I求和,xi是输入数据,对于负例和正例,ti分别为-1或+1。</p><pre><code> 这个标准被认为是权重w的函数,我们需要最小化它。通常,我们使用一种称为梯度下降的方法,在这种方法中,我们从一些初始权重w(0)开始,然后在每一步中根据公式更新权重:</code></pre><p>w(t+1) = w(t) - η∇E(w)</p><p>这里η是所谓的学习率,∇E(w)表示E的梯度,计算出梯度后,我们得到</p><p>w(t+1) = w(t) + ∑ηxiti</p><p><br> //perceptron.h<br> #ifndef _PERCEPTRON_H<br> #define _PERCEPTRON_H<br> //the simplest neural network model - one-layered perceptron, a linear two-class classification model.<br> #include<stdio.h><br> #include<time.h><br><br> #define FREATURE_NUM 2//特征数(输入向量维数)<br> #define LEARNING_RATE 1 //学习率<br><br> typedef struct input_data{<br> double freature[FREATURE_NUM];<br> int label;<br> }input_data;<br> typedef struct input_dataset{<br> input_data* input;<br> int set_num;<br> }input_dataset;</p><pre><code>double weight[FREATURE_NUM]={0};void train(input_dataset dataset,int iteration);void perceptron(input_data *input);#endif</code></pre><p><br> //perceptron.c<br> #include”perceptron.h”<br><br> void train(input_dataset dataset,int iteration)<br> {<br> //生成随机数种子<br> srand((unsigned)time(NULL));<br> <br> int set_num=dataset.set_num;<br> int i,j,k;<br> for(i=0;i<iteration;i++){<br> k=rand()%set_num;<br> //梯度下降方法搜寻<br> for(j=0;j<FREATURE_NUM;j++)<br> {<br> weight[j]+=1.0<em>LEARNING_RATE</em>dataset.input[k].freature[j]*dataset.input[k].label;<br> //printf(“%lf %lf\n”,weight[j],dataset.input[k].freature[j]);<br> }<br> }<br> return;<br> }</p><pre><code>void perceptron(input_data *input){int i,temp;for(i=0,temp=0;i<FREATURE_NUM;i++)temp+=weight[i]*input->freature[i];if(temp>=0)input->label=1;else input->label=-1;printf("label:%d\n",input->label);return;}</code></pre><p><br> #include<stdio.h><br> #include”perceptron.c”<br><br> int main(){<br> <br> input_data input[2];<br> input[0].freature[0]=-3.0;<br> input[0].freature[1]=1.0;<br> input[0].label=1;<br> input[1].freature[0]=-1.0;<br> input[1].freature[1]=3.0;<br> input[1].label=1;<br> input[2].freature[0]=2.0;<br> input[2].freature[1]=4;<br> input[2].label=-1;<br> input[3].freature[0]=4.0;<br> input[3].freature[1]=-2.0;<br> input[3].label=-1;<br> <br> input_dataset dataset;<br> dataset.input=input;<br> dataset.set_num=4;<br> <br> train(dataset,10);<br> <br> int i;<br> for(i=0;i<FREATURE_NUM;i++)printf(“%lf\n”,weight[i]);<br> <br> input_data test;<br> scanf(“%lf%lf”,&test.freature[0],&test.freature[1]);<br> perceptron(&test);<br> <br> return 0;<br> }</p><p> python实现及mnist手写数字识别(两类):[NeuralNetworks/03-Perceptron at<br>main](<a href="https://github.com/microsoft/AI-For-">https://github.com/microsoft/AI-For-</a><br>Beginners/tree/main/lessons/3-NeuralNetworks/03-Perceptron<br>“NeuralNetworks/03-Perceptron at main”)</p><p> (特征:28pix*28pix)</p><p>实现N类感知器:训练N个感知器:</p><ol><li>Create 10 <strong><em>one-vs-all</em> datasets</strong> for all digits</li><li>Train <strong>10 perceptrons</strong></li><li>Define <code>classify</code> function to perform digit classification</li><li>Measure the accuracy of classification and print <em>confusion matrix</em></li><li>[Optional] Create improved <code>classify</code> function that performs the classification using one matrix multiplication.</li></ol><h2 id="五-Multi-Layered-Perceptron"><a href="#五-Multi-Layered-Perceptron" class="headerlink" title="五.Multi-Layered Perceptron"></a>五.Multi-Layered Perceptron</h2><p><strong>简介:</strong></p><p>we will extend themodel above into a more flexible framework, allowing us to:</p><ul><li>perform <strong>multi-class classification</strong> in addition to two-class</li><li>solve <strong>regression problems</strong> in addition to classification</li><li>separate classes that are not linearly separable</li></ul><p>We will also develop our own modular framework in Python that will allow us to<br>construct different neural network architectures.</p><p>Suppose we have a training dataset <strong>X</strong> with labels <strong>Y</strong> , and we need to<br>build a **model <em>f</em> **that will make most accurate predictions. The quality<br>of predictions is measured by <strong>Loss function</strong> <strong>ℒ</strong>. The following loss<br>functions are often used:</p><ul><li>For <strong>regression problem(回归问题)</strong> , when we need to predict a number, we can use <strong>absolute error</strong> **∑i|f(x(i))-y(i)| **, or <strong>squared error</strong> **∑i(f(x(i))-y(i))^2 **</li><li>For <strong>classification(分类问题)</strong> , we use <strong>0-1 loss</strong> (which is essentially the same as <strong>accuracy</strong> of the model), or <strong>logistic loss</strong>.</li></ul><p><img src="https://i-blog.csdnimg.cn/blog_migrate/621e77f5fb5595bedf41e588670f4c80.png"></p><p>从p对损失函数L的影响来看逻辑损失函数更好</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/11de84ee5edc6ce0c8007f9604f71c73.png"></p><p>For <strong>one-level perceptron</strong> , function <em>f</em> was defined as a **linear<br>function <em>f(x)=wx+b</em> **(here <em>w</em> is the weight matrix, <em>x</em> is the vector<br>of input features, and <strong><em>b</em> is bias vector</strong>). For different neural network<br>architectures, this function can take more <strong>complex form.</strong></p><blockquote><p>In the case of <strong>classification</strong> , it is often desirable to get<br><strong>probabilities</strong> of corresponding classes as <strong>network output.</strong> To<br>convert arbitrary numbers to probabilities (eg. to normalize the output), we<br>often use <strong>softmax</strong> function <strong>σ</strong> , and the function <em>f</em> becomes<br><em>f(x)=σ(wx+b)</em></p></blockquote><p><img src="https://i-blog.csdnimg.cn/blog_migrate/1760fe528375040727919cbb4587890d.png"></p><p>In the definition of <em>f</em> above, <em>w</em> and <em>b</em> are called <strong>parameters</strong> θ=〈<br><em>w,b</em> 〉. Given the dataset 〈<strong>X</strong> ,<strong>Y</strong> 〉, we can compute an overall error on<br>the whole dataset as a function of parameters θ.</p><blockquote><p>✅ <strong>The goal of neural network training is to minimize the error (Loss<br>function</strong> <strong>ℒ</strong><strong>) by varying parameters θ</strong></p></blockquote><h3 id="1-Gradient-Descent-Optimization(梯度下降算法)"><a href="#1-Gradient-Descent-Optimization(梯度下降算法)" class="headerlink" title="1.Gradient Descent Optimization(梯度下降算法)"></a>1.Gradient Descent Optimization(梯度下降算法)</h3><p>This can be formalized as follows:</p><ul><li>Initialize parameters by some random values w(0), b(0)</li><li>Repeat the following step many times: <ul><li>w(i+1) = w(i)-η∂ℒ/∂w</li><li>b(i+1) = b(i)-η∂ℒ/∂b</li></ul></li></ul><p>During training, the optimization steps are supposed to be calculated<br>considering the whole dataset (remember that loss is calculated as a sum<br>through all training samples). However, in real life we take small portions of<br>the dataset called <strong>minibatches</strong> , and calculate gradients based on a subset<br>of data. Because subset is taken randomly each time, such method is called<br><strong>stochastic gradient descent</strong> (SGD).</p><h3 id="2-Multi-Layered-Perceptrons-and-Backpropagation(多层感知器和反向传播)"><a href="#2-Multi-Layered-Perceptrons-and-Backpropagation(多层感知器和反向传播)" class="headerlink" title="2.Multi-Layered Perceptrons and Backpropagation(多层感知器和反向传播)"></a><strong>2.Multi-Layered Perceptrons and Backpropagation(多层感知器和反向传播)</strong></h3><p><strong>一个示例——两层感知器</strong> :</p><p>One-layer network, as we have seen above, is capable of classifying linearly<br>separable classes. To build a richer model, we can <strong>combine several layers of<br>the network</strong>. Mathematically it would mean that the function <em>f</em> would have<br>a more complex form, and will be computed in several steps:</p><ul><li>z1=w1x+b1</li><li>z2=w2α(z1)+b2</li><li>f = σ(z2)</li></ul><p>Here, <strong>α</strong> is a <strong>non-linear activation function</strong> , <strong>σ is a softmax<br>function</strong>, and parameters θ=<_w1,b1,w2,b2_ >.</p><p>The gradient descent algorithm would remain the same, but it would be more<br>difficult to calculate gradients. Given the chain differentiation rule, we can<br>calculate derivatives as:</p><ul><li>∂ℒ/∂w2 = (∂ℒ/∂σ)(∂σ/∂z2)(∂z2/∂w2)</li><li>∂ℒ/∂w1 = (∂ℒ/∂σ)(∂σ/∂z2)(∂z2/∂α)(∂α/∂z1)(∂z1/∂w1)</li></ul><blockquote><p>✅ The <strong>chain differentiation rule</strong> is used to calculate derivatives of the<br>loss function with respect to parameters.</p></blockquote><p><strong>链式规则、后向传播更新参数θ</strong> :</p><p>Note that the left-most part of all those expressions is the same, and thus we<br>can** effectively calculate derivatives** **starting from the loss function<br>and going “backwards” **through the computational graph. Thus the method of<br>training a multi-layered perceptron is called <strong>backpropagation</strong> , or<br>‘backprop’.</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/98446f8f75153030ff57d774b4684b02.png"></p><p>即:</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/82d7932c55daa1260a98b128ecb829ba.png"></p><h3 id="3-单层感知器模型"><a href="#3-单层感知器模型" class="headerlink" title="3.单层感知器模型"></a>3.单层感知器模型</h3><p><img src="https://i-blog.csdnimg.cn/blog_migrate/28b6864aabe5cda4e0786e846d3f43df.png"></p><pre><code> Two outputs of the network correspond to two classes, and the class with highest value among two outputs corresponds to the right solution.</code></pre><p>The model is defined as:</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/093e6e1eb8cb98c2846ce0e7fac93586.png"></p><p><strong>相关依赖:</strong></p><p><br> import matplotlib.pyplot as plt<br> from matplotlib import gridspec<br> from sklearn.datasets import make_classification<br> import numpy as np<br> # pick the seed for reproducibility - change it to explore the effects of random variations<br> np.random.seed(0)<br> import random</p><h4 id="1-创建数据集,X为特征向量,Y为标签:"><a href="#1-创建数据集,X为特征向量,Y为标签:" class="headerlink" title="< 1>创建数据集,X为特征向量,Y为标签:"></a><strong>< 1>创建数据集,X为特征向量,Y为标签:</strong></h4><p><br> n = 100<br> X, Y = make_classification(n_samples = n, n_features=2,<br> n_redundant=0, n_informative=2, flip_y=0.2)<br> X = X.astype(np.float32)<br> Y = Y.astype(np.int32)<br><br> # Split into train and test dataset<br> train_x, test_x = np.split(X, [n<em>8//10])<br> train_labels, test_labels = np.split(Y, [n</em>8//10])</p><p><br> #显示数据集<br> print(train_x[:5])<br> print(train_labels[:5])</p><p><br> [[-0.836906 -1.382417 ]<br> [ 3.0352616 -1.1195285]<br> [ 1.6688806 2.4989042]<br> [-0.5790065 2.1814067]<br> [-0.8730455 -1.4692409]]<br> [0 1 1 1 0]</p><h4 id="2-前向传播计算过程:"><a href="#2-前向传播计算过程:" class="headerlink" title="**< 2> 前向传播计算过程: **"></a>**< 2> 前向传播计算过程: **</h4><p><br> class Linear:<br> #初始化权重<br> def <strong>init</strong>(self,nin,nout):<br> self.W = np.random.normal(0, 1.0/np.sqrt(nin), (nout, nin))<br> self.b = np.zeros((1,nout))<br> #前向传播计算<br> def forward(self, x):<br> return np.dot(x, self.W.T) + self.b<br><br> net = Linear(2,2)<br> net.forward(train_x[0:5])</p><p><br> #5个输入的输出<br> 0,1.772021,-0.253845<br> 1,0.283708,-0.396106<br> 2,-0.300974,0.305132<br> 3,-0.812048,0.560794<br> 4,-1.235197,0.339497</p><h4 id="使用softmax函数转换为概率:"><a href="#使用softmax函数转换为概率:" class="headerlink" title="<3>使用softmax函数转换为概率:"></a><3>使用softmax函数转换为概率:</h4><p><br> class Softmax:<br> def forward(self,z):<br> zmax = z.max(axis=1,keepdims=True)<br> expz = np.exp(z-zmax)<br> Z = expz.sum(axis=1,keepdims=True)<br> return expz / Z<br><br> softmax = Softmax()<br> softmax.forward(net.forward(train_x[0:10]))</p><p><br> In case we have more than 2 classes, softmax will normalize probabilities across all of them.</p><h4 id="交叉熵损失函数"><a href="#交叉熵损失函数" class="headerlink" title="<4>交叉熵损失函数"></a><4>交叉熵损失函数</h4><p><br> A loss function in classification is typically a <strong>logistic function</strong> , which can <strong>be generalized as cross-entropy loss</strong>. Cross-entropy loss is a function that can calculate similarity between two arbitrary probability distributions. </p><p><br> def cross_ent(prediction, ground_truth):<br> t = 1 if ground_truth > 0.5 else 0<br> return -t * np.log(prediction) - (1 - t) * np.log(1 - prediction)<br> plot_cross_ent()</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/2f4b2ad0f83c2804efe05f9563c4c85f.png"></p><p><br> Cross-entropy loss will be defined again as <strong>a separate layer</strong> , but <code>forward</code> function will have <em><strong>two input values: output of the previous layers of the network <code>p</code>, and the expected class <code>y</code>:</strong></em></p><p><strong>应用:</strong></p><p><br> class CrossEntropyLoss:<br> def forward(self,p,y):<br> self.p = p<br> self.y = y<br> p_of_y = p[np.arange(len(y)), y]<br> log_prob = np.log(p_of_y)<br> return -log_prob.mean() # average over all input samples<br><br> cross_ent_loss = CrossEntropyLoss()<br> p = softmax.forward(net.forward(train_x[0:10]))<br> cross_ent_loss.forward(p,train_labels[0:10])</p><blockquote><p><strong>IMPORTANT</strong> : Loss function returns a number that shows how good (or bad)<br>our network performs. It should return us one number for the whole dataset,<br>or for the part of the dataset (minibatch). Thus after calculating cross-<br>entropy loss for each individual component of the input vector, we need to<br>average (or add) all components together - which is done by the call to<br><code>.mean()</code>.</p><p>(注意计算的是<strong>交叉熵均值</strong> :return -log_prob.mean() # average over all input samples )</p></blockquote><pre><code>z = net.forward(train_x[0:10]) #输出p = softmax.forward(z) #softmax归一化loss = cross_ent_loss.forward(p,train_labels[0:10])#cross_ent_loss = CrossEntropyLoss()print(loss)</code></pre><h4 id="Loss-Minimization-Problem-and-Network-Training:"><a href="#Loss-Minimization-Problem-and-Network-Training:" class="headerlink" title="<5>Loss Minimization Problem and Network Training:"></a><5>Loss Minimization Problem and Network Training:</h4><p>数学描述:</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/44ff93f6ec92975a705328447d9fcb28.png"></p><p>采用梯度下降法进行计算(见2.)</p><p><strong>网络训练</strong> 包括前向和后向传播两个过程(<strong>原理</strong> 见2和3<2>)</p><p>One pass of the <strong>network training</strong> consists of two parts:</p><ul><li><strong>Forward pass</strong> , when we calculate the value of loss function for a given input minibatch</li><li><strong>Backward pass</strong> , when we try to minimize this error by distributing it back to the model parameters through the computational graph.</li></ul><p><strong>后向传播的具体实现:</strong></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/bcc3707448e65ae4040d2b305dc71a12.png"></p><p><em>注意参数的更新在一个minibatch完全计算完后,而不是单个样本</em></p><p><br> def update(self,lr):<br> self.W -= lr<em>self.dW<br> self.b -= lr</em>self.db<br> #LR是学习率</p><h4 id="函数小结"><a href="#函数小结" class="headerlink" title="<6>函数小结"></a><6>函数小结</h4><p><br> class Linear:<br> def <strong>init</strong>(self,nin,nout):<br> self.W = np.random.normal(0, 1.0/np.sqrt(nin), (nout, nin))<br> self.b = np.zeros((1,nout))<br> self.dW = np.zeros_like(self.W)<br> self.db = np.zeros_like(self.b)<br><br> def forward(self, x):<br> self.x=x<br> return np.dot(x, self.W.T) + self.b<br><br> def backward(self, dz):<br> dx = np.dot(dz, self.W)<br> dW = np.dot(dz.T, self.x)<br> db = dz.sum(axis=0)<br> self.dW = dW<br> self.db = db<br> return dx</p><pre><code> def update(self,lr): self.W -= lr*self.dW self.b -= lr*self.db</code></pre><p><br> class Softmax:<br> def forward(self,z):<br> self.z = z<br> zmax = z.max(axis=1,keepdims=True)<br> expz = np.exp(z-zmax)<br> Z = expz.sum(axis=1,keepdims=True)<br> return expz / Z<br> def backward(self,dp):<br> p = self.forward(self.z)<br> pdp = p * dp<br> return pdp - p * pdp.sum(axis=1, keepdims=True)<br><br> class CrossEntropyLoss:<br> def forward(self,p,y):<br> self.p = p<br> self.y = y<br> p_of_y = p[np.arange(len(y)), y]<br> log_prob = np.log(p_of_y)<br> return -log_prob.mean()<br> def backward(self,loss):<br> dlog_softmax = np.zeros_like(self.p)<br> dlog_softmax[np.arange(len(self.y)), self.y] -= 1.0/len(self.y)<br> return dlog_softmax / self.p</p><h4 id="Training-the-Model"><a href="#Training-the-Model" class="headerlink" title="<7>Training the Model"></a><7>Training the Model</h4><pre><code> Now we are ready to write the **training loop** , which will go through our dataset, and perform the optimization minibatch by minibatch._One complete pass through the dataset is often called**an epoch** :_</code></pre><p><br> lin = Linear(2,2)<br> softmax = Softmax()<br> cross_ent_loss = CrossEntropyLoss()<br><br> learning_rate = 0.1<br><br> pred = np.argmax(lin.forward(train_x),axis=1)<br> acc = (pred==train_labels).mean()<br> print(“Initial accuracy: “,acc)</p><pre><code>batch_size=4for i in range(0,len(train_x),batch_size): xb = train_x[i:i+batch_size] yb = train_labels[i:i+batch_size] # forward pass z = lin.forward(xb) p = softmax.forward(z) loss = cross_ent_loss.forward(p,yb) # backward pass dp = cross_ent_loss.backward(loss) dz = softmax.backward(dp) dx = lin.backward(dz) lin.update(learning_rate) pred = np.argmax(lin.forward(train_x),axis=1)acc = (pred==train_labels).mean()print("Final accuracy: ",acc)</code></pre><p><br><br> Initial accuracy: 0.2625<br> Final accuracy: 0.7875</p><h3 id="4-网络模型"><a href="#4-网络模型" class="headerlink" title="4.网络模型"></a>4.网络模型</h3><h4 id="定义网络类-:"><a href="#定义网络类-:" class="headerlink" title="<1>定义网络类 :"></a><1>定义<strong>网络类</strong> :</h4><pre><code> Since in many cases neural network is just **a composition of layers** , we can build a class that will allow us to **stack layers together** and**make forward and backward passes** through them without explicitly programming that logic. We will **store the list of layers inside the`Net` class**, and **use`add()` function to add new layers**:</code></pre><p><br> class Net:<br> def <strong>init</strong>(self):<br> self.layers = []<br><br> def add(self,l):<br> self.layers.append(l)<br><br> def forward(self,x):<br> for l in self.layers:<br> x = l.forward(x)<br> return x</p><pre><code> def backward(self,z): for l in self.layers[::-1]: z = l.backward(z) return z def update(self,lr): for l in self.layers: if 'update' in l.__dir__(): l.update(lr)</code></pre><p>定义网络和训练:</p><p><br> net = Net()<br> net.add(Linear(2,2))<br> net.add(Softmax())<br> loss = CrossEntropyLoss()<br><br> def get_loss_acc(x,y,loss=CrossEntropyLoss()):<br> p = net.forward(x)<br> l = loss.forward(p,y)<br> pred = np.argmax(p,axis=1)<br> acc = (pred==y).mean()<br> return l,acc<br><br> print(“Initial loss={}, accuracy={}: “.format(*get_loss_acc(train_x,train_labels)))</p><pre><code>def train_epoch(net, train_x, train_labels, loss=CrossEntropyLoss(), batch_size=4, lr=0.1): for i in range(0,len(train_x),batch_size): xb = train_x[i:i+batch_size] yb = train_labels[i:i+batch_size] p = net.forward(xb) l = loss.forward(p,yb) dp = loss.backward(l) dx = net.backward(dp) net.update(lr) train_epoch(net,train_x,train_labels) print("Final loss={}, accuracy={}: ".format(*get_loss_acc(train_x,train_labels)))print("Test loss={}, accuracy={}: ".format(*get_loss_acc(test_x,test_labels)))</code></pre><p><br> Initial loss=0.8977914474068779, accuracy=0.4625:<br> Final loss=0.47908832233966514, accuracy=0.825:<br> Test loss=0.5317198099647931, accuracy=0.8:</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/9f0836ab887616dbe48bcedfff0a5ea8.png"></p><h4 id="Multi-Layered-Models"><a href="#Multi-Layered-Models" class="headerlink" title="<2>Multi-Layered Models"></a><2>Multi-Layered Models</h4><p><br> Very important thing to note, however, is that <em><strong>in between linear layers we need to have a non-linear</strong> <strong>activation function</strong></em> , such as <em><strong>tanh</strong></em>. Without such non-linearity, several linear layers would have the same expressive power as just one layers - because <em><strong>composition of linear functions is also linear!</strong></em></p><p>在线性层之间添加激活函数,线性函数的叠加仍是线性。</p><p><br> class Tanh:<br> def forward(self,x):<br> y = np.tanh(x)<br> self.y = y<br> return y<br> def backward(self,dy):<br> return (1.0-self.y**2)*dy<br><br> Adding several layers make sense, because unlike one-layer network, multi-layered model will <strong>be able to accuratley classify sets that are not linearly separable</strong>. I.e., a model with several layers will be <strong>reacher</strong>.</p><blockquote><p>It can be demonstrated that with sufficient number of neurons a <strong>two-<br>layered model</strong> is capable to classifying any <strong>convex set of data points</strong><br>, and <strong>three-layered network</strong> can classify <strong>virtually any set.</strong></p></blockquote><p>多层网络的形式见前(2.)</p><p>两层网络示例:</p><p><br> net = Net()<br> net.add(Linear(2,10))<br> net.add(Tanh())<br> net.add(Linear(10,2))<br> net.add(Softmax())<br> loss = CrossEntropyLoss()</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/aa5a7f818f593a302d689193dc8bf872.png"></p><p>关于线性模型和多层复杂模型的区别和**过拟合(**<strong>overfitting)</strong> 问题:</p><p><strong>A linear model:</strong></p><ul><li>We are likely to get high training loss - so-called <strong>underfitting</strong> , when the model does not have enough power to correctly separate all data.</li><li>Valiadation loss and training loss are more or less the same. The model is likely to generalize well to test data.</li></ul><p><strong>Complex multi-layered model</strong></p><ul><li>Low training loss - the model can approximate training data well, because it has enough expressive power.</li><li>Validation loss can be much higher than training loss and can start to increase during training - this is because the model “memorizes” training points, and loses the “overall picture”</li></ul><p><strong>小结:</strong></p><p><strong>Takeaways</strong></p><ul><li>Simple models (fewer layers, fewer neurons) with low number of parameters (“low capacity”) are less likely to overfit</li><li>More complex models (more layers, more neurons on each layer, high capacity) are likely to overfit. We need to monitor validation error to make sure it does not start to rise with further training</li><li>More complex models need more data to train on.</li><li>You can solve overfitting problem by either: <ul><li>simplifying your model</li><li>increasing the amount of training data</li></ul></li><li><strong>Bias-variance trade-off</strong> is a term that shows that you need to get the compromise <ul><li>between power of the model and amount of data,</li><li>between overfittig and underfitting</li></ul></li><li>There is not single recipe on how many layers of parameters you need - the best way is to experiment</li></ul><h3 id="5-代码整合"><a href="#5-代码整合" class="headerlink" title="5.代码整合"></a>5.代码整合</h3><p><br> ###################################################################<br> # package<br> # matplotlib nbagg<br> import matplotlib.pyplot as plt<br> from matplotlib import gridspec<br> from sklearn.datasets import make_classification<br> import numpy as np<br> # pick the seed for reproducibility - change it to explore the effects of random variations<br> np.random.seed(0)<br> import random</p><p><br> ###################################################################<br> # dataset<br> n = 100<br> X, Y = make_classification(n_samples = n, n_features=2,<br> n_redundant=0, n_informative=2, flip_y=0.2)<br> X = X.astype(np.float32)<br> Y = Y.astype(np.int32)<br><br> # Split into train and test dataset<br> train_x, test_x = np.split(X, [n<em>8//10])<br> train_labels, test_labels = np.split(Y, [n</em>8//10])</p><p><br> ###################################################################<br> # layers<br> class Linear:<br> def <strong>init</strong>(self,nin,nout):<br> self.W = np.random.normal(0, 1.0/np.sqrt(nin), (nout, nin))<br> self.b = np.zeros((1,nout))<br> self.dW = np.zeros_like(self.W)<br> self.db = np.zeros_like(self.b)<br><br> def forward(self, x):<br> self.x=x<br> return np.dot(x, self.W.T) + self.b<br><br> def backward(self, dz):<br> dx = np.dot(dz, self.W)<br> dW = np.dot(dz.T, self.x)<br> db = dz.sum(axis=0)<br> self.dW = dW<br> self.db = db<br> return dx</p><pre><code> def update(self,lr): self.W -= lr*self.dW self.b -= lr*self.dbclass Tanh: def forward(self,x): y = np.tanh(x) self.y = y return y def backward(self,dy): return (1.0-self.y**2)*dy</code></pre><p><br> class Softmax:<br> def forward(self,z):<br> self.z = z<br> zmax = z.max(axis=1,keepdims=True)<br> expz = np.exp(z-zmax)<br> Z = expz.sum(axis=1,keepdims=True)<br> return expz / Z<br> def backward(self,dp):<br> p = self.forward(self.z)<br> pdp = p * dp<br> return pdp - p * pdp.sum(axis=1, keepdims=True)</p><p><br> class CrossEntropyLoss:<br> def forward(self,p,y):<br> self.p = p<br> self.y = y<br> p_of_y = p[np.arange(len(y)), y]<br> log_prob = np.log(p_of_y)<br> return -log_prob.mean()<br> def backward(self,loss):<br> dlog_softmax = np.zeros_like(self.p)<br> dlog_softmax[np.arange(len(self.y)), self.y] -= 1.0/len(self.y)<br> return dlog_softmax / self.p</p><p><br> ###################################################################<br> # network<br> class Net:<br> def <strong>init</strong>(self):<br> self.layers = []<br><br> def add(self,l):<br> self.layers.append(l)<br><br> def forward(self,x):<br> for l in self.layers:<br> x = l.forward(x)<br> return x</p><pre><code> def backward(self,z): for l in self.layers[::-1]: z = l.backward(z) return z def update(self,lr): for l in self.layers: if 'update' in l.__dir__(): l.update(lr)def get_loss_acc(x,y,loss=CrossEntropyLoss()): p = net.forward(x) l = loss.forward(p,y) pred = np.argmax(p,axis=1) acc = (pred==y).mean() return l,accdef train_epoch(net, train_x, train_labels, loss=CrossEntropyLoss(), batch_size=4, lr=0.1): for i in range(0,len(train_x),batch_size): xb = train_x[i:i+batch_size] yb = train_labels[i:i+batch_size] p = net.forward(xb) l = loss.forward(p,yb) dp = loss.backward(l) dx = net.backward(dp) net.update(lr) print("epoch={}: ".format(i),end="") print("Final loss={}, accuracy={}: ".format(*get_loss_acc(train_x,train_labels))) print("Test loss={}, accuracy={}: ".format(*get_loss_acc(test_x,test_labels)))#################################################################### mainnet = Net()net.add(Linear(2,10))net.add(Tanh())net.add(Linear(10,2))net.add(Softmax())train_epoch(net,train_x,train_labels)</code></pre><h3 id="6-3-layer-network-实现-mnist-手写数字识别"><a href="#6-3-layer-network-实现-mnist-手写数字识别" class="headerlink" title="6.3-layer network 实现 mnist 手写数字识别"></a>6.3-layer network 实现 mnist 手写数字识别</h3><p>训练模型,保存结果:</p><p><br> ###################################################################<br> # packages<br> import matplotlib.pyplot as plt<br> from matplotlib import gridspec<br> from sklearn.datasets import make_classification<br> import numpy as np<br> # pick the seed for reproducibility - change it to explore the effects of random variations<br> np.random.seed(0)<br> import random</p><p><br> ###################################################################<br> # dataset<br> n=70000<br> # generate data<br> # X, Y = make_classification(n_samples = n, n_features=28<em>28,n_redundant=0, n_informative=8</em>8, flip_y=0.2)<br> # get data from mnist<br> from torchvision import datasets, transforms<br> mnist_train = datasets.MNIST(root=’./data’, train=True, transform=transforms.ToTensor())<br> X = mnist_train.data.numpy()<br> Y = mnist_train.targets.numpy()<br> X = X.reshape(X.shape[0],-1)<br> X = X.astype(np.float32)<br> Y = Y.astype(np.int32)<br><br> # Split into train and test dataset<br> train_x, test_x = np.split(X, [n<em>8//10]) # 80% training and 20% test<br> train_labels, test_labels = np.split(Y, [n</em>8//10]) </p><p><br> ###################################################################<br> # layers<br> class Linear:<br> def <strong>init</strong>(self,nin,nout):<br> self.W = np.random.normal(0, 1.0/np.sqrt(nin), (nout, nin))<br> self.b = np.zeros((1,nout))<br> self.dW = np.zeros_like(self.W)<br> self.db = np.zeros_like(self.b)<br><br> def forward(self, x):<br> self.x=x<br> return np.dot(x, self.W.T) + self.b<br><br> def backward(self, dz):<br> dx = np.dot(dz, self.W)<br> dW = np.dot(dz.T, self.x)<br> db = dz.sum(axis=0)<br> self.dW = dW<br> self.db = db<br> return dx</p><pre><code> def update(self,lr): self.W -= lr*self.dW self.b -= lr*self.dbclass Tanh: def forward(self,x): y = np.tanh(x) self.y = y return y def backward(self,dy): return (1.0-self.y**2)*dy</code></pre><p><br> class Softmax:<br> def forward(self,z):<br> self.z = z<br> zmax = z.max(axis=1,keepdims=True)<br> expz = np.exp(z-zmax)<br> Z = expz.sum(axis=1,keepdims=True)<br> return expz / Z<br> def backward(self,dp):<br> p = self.forward(self.z)<br> pdp = p * dp<br> return pdp - p * pdp.sum(axis=1, keepdims=True)</p><p><br> class CrossEntropyLoss:<br> def forward(self,p,y):<br> self.p = p<br> self.y = y<br> p_of_y = p[np.arange(len(y)), y]<br> log_prob = np.log(p_of_y)<br> return -log_prob.mean()<br> def backward(self,loss):<br> dlog_softmax = np.zeros_like(self.p)<br> dlog_softmax[np.arange(len(self.y)), self.y] -= 1.0/len(self.y)<br> return dlog_softmax / self.p</p><p><br> ###################################################################<br> # network<br> class Net:<br> def <strong>init</strong>(self):<br> self.layers = []<br><br> def add(self,l):<br> self.layers.append(l)<br><br> def forward(self,x):<br> for l in self.layers:<br> x = l.forward(x)<br> return x</p><pre><code> def backward(self,z): for l in self.layers[::-1]: z = l.backward(z) return z def update(self,lr): for l in self.layers: if 'update' in l.__dir__(): l.update(lr)def get_loss_acc(x,y,loss=CrossEntropyLoss()): p = net.forward(x) l = loss.forward(p,y) pred = np.argmax(p,axis=1) acc = (pred==y).mean() return l,accdef train_epoch(net, train_x, train_labels, loss=CrossEntropyLoss(), batch_size=4, lr=0.1): for i in range(0,len(train_x),batch_size): xb = train_x[i:i+batch_size] yb = train_labels[i:i+batch_size] p = net.forward(xb) l = loss.forward(p,yb) dp = loss.backward(l) dx = net.backward(dp) net.update(lr) print("epoch={}: ".format(i//batch_size)) print("Final loss={}, accuracy={}: ".format(*get_loss_acc(train_x,train_labels))) print("Test loss={}, accuracy={}: ".format(*get_loss_acc(test_x,test_labels)))#################################################################### mainif __name__ == '__main__': # model net = Net() net.add(Linear(28*28,300)) net.add(Tanh()) net.add(Linear(300,10)) net.add(Softmax()) train_epoch(net,train_x,train_labels,batch_size=1000) #save the model import pickle with open('model.pkl', 'wb') as f: pickle.dump(net, f) </code></pre><p>加载模型,进行测试:</p><p><br> import OwnFramework<br> import torchvision<br> import numpy as np<br> import pickle<br> import matplotlib.pyplot as plt<br> import matplotlib.gridspec as gridspec<br> import random<br><br> # import the model<br> with open(‘model.pkl’, ‘rb’) as f:<br> OwnFramework.net = pickle.load(f)<br><br> # test the data from minst<br> test_data = torchvision.datasets.MNIST(‘./data’, train=False, download=False)<br> test_x = test_data.data.numpy().reshape(-1,28*28)<br> test_labels = test_data.targets.numpy()</p><pre><code># test the modelprint("Test loss={}, accuracy={}: ".format(*OwnFramework.get_loss_acc(test_x,test_labels)))# show the images and the predictionsfig=plt.figure(figsize=(8, 8))gs = gridspec.GridSpec(4, 4)for i in range(16): j=random.randint(0,len(test_x)) ax = plt.subplot(gs[i]) ax.imshow(test_x[j].reshape(28,28)) ax.set_title("Predicted: {}".format(np.argmax(OwnFramework.net.forward(test_x[j:j+1])))) ax.axis('off')plt.show()# show the images that are not predicted not correctlyfig=plt.figure(figsize=(12, 8))gs = gridspec.GridSpec(4, 4)i=0for j in range(len(test_x)): if np.argmax(OwnFramework.net.forward(test_x[j:j+1])) != test_labels[j]: ax = plt.subplot(gs[i]) ax.imshow(test_x[j].reshape(28,28)) ax.set_title("Predicted: {}, True: {}".format(np.argmax(OwnFramework.net.forward(test_x[j:j+1])),test_labels[j])) ax.axis('off') i+=1 if i==16: breakplt.show()</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/0f2a5124db743b6101b0841143d3f591.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/94e98f86a86028bb9b2d14b0ed7f50d3.png"></p><h2 id="六-Neural-Network-Frameworks"><a href="#六-Neural-Network-Frameworks" class="headerlink" title="六.Neural Network Frameworks"></a>六.Neural Network Frameworks</h2><p><strong>架构API:</strong></p><p>to be able to train neural networks efficiently we need to do two things:</p><ul><li><p>To <strong>operate</strong> on <strong>tensors</strong> , eg. to multiply, add, and compute some functions such as sigmoid or softmax</p></li><li><p>To compute <strong>gradients</strong> of all expressions, in order to perform gradient descent optimization</p><pre><code>While the **`numpy` library** can **do the first part** , we need some mechanism to compute gradients. In our framework that we have developed in the previous section we had to manually program all derivative functions inside the `backward` method, which does backpropagation. Ideally, _**a framework should give us the opportunity to compute gradients of _any expression_ that we can define**_.Another important thing is to be able to **perform computations on GPU** , or any other specialized compute units, such as [TPU](https://en.wikipedia.org/wiki/Tensor_Processing_Unit "TPU"). Deep neural network training requires _a lot_ of computations, and to be able to parallelize those computations on GPUs is very important.</code></pre></li></ul><p><strong>底层和高层API:</strong> </p><pre><code> Currently, the two **most popular neural frameworks** are:** [TensorFlow](http://tensorflow.org/ "TensorFlow") and [PyTorch](https://pytorch.org/ "PyTorch").** Both provide a **low-level API** to operate with **tensors on both CPU and GPU**. On top of the low-level API, there is also **higher-level API** , called** [Keras](https://keras.io/ "Keras") and [PyTorch Lightning](https://pytorchlightning.ai/ "PyTorch Lightning") **correspondingly.</code></pre><p>Low-Level API| <a href="http://tensorflow.org/" title="TensorFlow">TensorFlow</a>|</p><p><a href="https://pytorch.org/" title="PyTorch">PyTorch</a><br>—|—|—<br>High-level API| <a href="https://keras.io/" title="Keras">Keras</a>| <a href="https://pytorchlightning.ai/" title="PyTorch Lightning">PyTorch<br>Lightning</a> </p><p><strong>Low-level APIs</strong> in both frameworks allow you to build so-called<br><strong>computational graphs</strong>. This graph defines how to compute the output<br>(usually <strong>the loss function</strong>) <strong>with given input parameters</strong> , and can be<br>pushed for computation <strong>on GPU</strong> , if it is available. There are functions to<br>differentiate this computational graph and compute gradients, which can then<br>be used for optimizing model parameters.</p><p><strong>High-level APIs</strong> pretty much consider neural networks as a <strong>sequence of<br>layers</strong> , and make constructing most of the neural networks much easier.<br>Training the model usually requires <strong>preparing the data</strong> and then calling a<br><strong><code>fit</code> function</strong> to do the job.</p><pre><code> The high-level API allows you to construct typical neural networks **very quickly without worrying about lots of details**. At the same time, low-level API offer much more control over the training process, and thus they are **used a lot in research** , when you are dealing with **new neural network architectures.** It is also important to understand that you can**use both APIs together** , eg. you can develop your own network layer architecture using low-level API, and then use it inside the larger network constructed and trained with the high-level API. Or you can define a network using the high-level API as a sequence of layers, and then use your own low-level training loop to perform optimization. Both APIs use the same basic underlying concepts, and they are designed to work well together.</code></pre><p><strong>过拟合检测:</strong></p><p><strong>How to detect overfitting</strong></p><pre><code> As you can see from the graph above, overfitting can be detected by a very low training error, and a high validation error. Normally during training we will see both training and validation errors starting to decrease, and then **at some point validation error might stop decreasing and start rising**. This will be a sign of overfitting, and the indicator that we should probably **stop training at this point** (or at least **make a snapshot of the model**).(及时备份)</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/9c3db5d1878b3ecef22e81631f39e2b0.png"></p><h3 id="1-Keras"><a href="#1-Keras" class="headerlink" title="1.Keras"></a>1.Keras</h3><pre><code> Keras is **a part of Tensorflow 2.x framework**. Let’s make sure we have version 2.x.x of Tensorflow installed:</code></pre><p><br> # packages<br> import tensorflow as tf<br> from tensorflow import keras<br> import numpy as np<br> from sklearn.datasets import make_classification<br> import matplotlib.pyplot as plt<br> print(f’Tensorflow version = {tf.<strong>version</strong>}’)</p><p><br> # data prepare<br> np.random.seed(0) # pick the seed for reproducibility - change it to explore the effects of random variations<br><br> n = 100<br> X, Y = make_classification(n_samples = n, n_features=2,<br> n_redundant=0, n_informative=2, flip_y=0.05,class_sep=1.5)<br> X = X.astype(np.float32)<br> Y = Y.astype(np.int32)<br><br> split = [ 70*n//100 ]<br> train_x, test_x = np.split(X, split)<br> train_labels, test_labels = np.split(Y, split)</p><p>**关于张量的概念:(多维向量) **</p><p><strong>Tensor</strong> is a <strong>multi-dimensional array</strong>. It is very convenient to use<br>tensors to represent different types of data:</p><ul><li>400x400 - black-and-white picture</li><li>400x400x3 - color picture</li><li>16x400x400x3 - minibatch of 16 color pictures</li><li>25x400x400x3 - one second of 25-fps video</li><li>8x25x400x400x3 - minibatch of 8 1-second videos</li></ul><p>Tensors give us a convenient way to represent input/output data, as well we<br>weights inside the neural network.</p><p><strong>归一化数据:(约束网络参数范围)Normalizing Data</strong></p><p>Before training, it is common to bring our input features<strong>to the standard<br>range of [0,1] (or [-1,1]).</strong> The exact reasons for that we will discuss later<br>in the course, but in short the reason is the following. We want to avoid<br>values that flow through our network <strong>getting too big or too small</strong> , and we<br>normally agree to keep all values in the small range close to 0. Thus we<br><strong>initialize the weights with small random numbers</strong> , and we keep signals in<br>the same range.</p><p><br> train_x_norm = (train_x-np.min(train_x,axis=0)) / (np.max(train_x,axis=0)-np.min(train_x,axis=0))<br> test_x_norm = (test_x-np.min(train_x,axis=0)) / (np.max(train_x,axis=0)-np.min(train_x,axis=0))</p><h4 id="Training-One-Layer-Network-Perceptron"><a href="#Training-One-Layer-Network-Perceptron" class="headerlink" title="<1>Training One-Layer Network (Perceptron)"></a><1>Training One-Layer Network (Perceptron)</h4><h5 id="①模型定义"><a href="#①模型定义" class="headerlink" title="①模型定义"></a>①模型定义</h5><p>In many cases, a neural network would be <strong>a sequence of layers.</strong> It can be<br>defined in Keras using **<code>Sequential</code> **model in the following manner:</p><p><br> model = keras.models.Sequential()<br> model.add(keras.Input(shape=(2,)))<br> model.add(keras.layers.Dense(1))<br> model.add(keras.layers.Activation(keras.activations.sigmoid))<br> model.summary()<br><br> # or<br> # Input size, as well as activation function, can also be specified directly in the Dense layer for brevity:<br> model = keras.models.Sequential()<br> model.add(keras.layers.Dense(1,input_shape=(2,),activation=’sigmoid’))<br> model.summary()</p><p>说明:</p><p>Here, we first create the model, and then add layers to it:</p><ul><li><p>First <code>Input</code> layer (<strong>which is not strictly speaking a layer</strong>) contains the specification of network’s <strong>input size</strong></p></li><li><p><code>Dense</code> layer is the actual perceptron that <strong>contains trainable weights</strong></p></li><li><p>Finally, there is a layer with **<em>sigmoid</em> <code>Activation</code> function **to bring the result of the network into 0-1 range (to make it a probability).</p><h1 id="Model-“sequential”-Layer-type-Output-Shape-Param"><a href="#Model-“sequential”-Layer-type-Output-Shape-Param" class="headerlink" title="Model: “sequential”_________________________________________________________________ Layer (type) Output Shape Param #"></a>Model: “sequential”<br>_________________________________________________________________<br> Layer (type) Output Shape Param #</h1><p> dense (Dense) (None, 1) 3</p><p> activation (Activation) (None, 1) 0</p><p>=================================================================<br>Total params: 3 (12.00 Byte)<br>Trainable params: 3 (12.00 Byte)<br>Non-trainable params: 0 (0.00 Byte)</p><hr></li></ul><h5 id="②模型编译(指定损失函数、优化方法【梯度下降等】、精度)"><a href="#②模型编译(指定损失函数、优化方法【梯度下降等】、精度)" class="headerlink" title="②模型编译(指定损失函数、优化方法【梯度下降等】、精度)"></a>②模型编译(指定损失函数、优化方法【梯度下降等】、精度)</h5><p>Before training the model, we need to <strong>compile it</strong> , which essentially mean<br>specifying:</p><ul><li><strong>Loss function</strong> , which defines how loss is calculated. Because we have two-class classification problem, we will use <em>binary cross-entropy loss</em>.</li><li><strong>Optimizer</strong> to use. The simplest option would be to use <code>sgd</code> for <em>stochastic gradient descent</em> , or you can use more sophisticated optimizers such as <code>adam</code>.</li><li><strong>Metrics</strong> that we want to use to measure success of our training. Since it is classification task, a good metrics would be <code>Accuracy</code> (or <code>acc</code> for short)</li></ul><p>We can specify loss, metrics and optimizer either as <strong>strings</strong> , or by<br>providing some <strong>objects from Keras framework</strong>. In our example, we need to<br>**specify<code>learning_rate</code> parameter **to fine-tune learning speed of our model,<br>and thus we provide <strong>full name of Keras SGD optimizer.</strong></p><p><strong>(可使用字符串或对象来定义)</strong></p><p><br> model.compile(optimizer=keras.optimizers.SGD(learning_rate=0.2),loss=’binary_crossentropy’,metrics=[‘acc’])</p><h5 id="③训练"><a href="#③训练" class="headerlink" title="③训练"></a>③训练</h5><p>After compiling the model, we can do the actual training by calling <strong><code>fit</code><br>method.</strong> The most important parameters are:</p><ul><li><p><code>x</code> and <code>y</code> specify <strong>training data, features and labels respectively</strong></p></li><li><p>If we want validation to be performed on each epoch, we can specify **<code>validation_data</code> **parameter, which would be a tuple of features and labels</p></li><li><p>**<code>epochs</code> **specified the number of epochs</p></li><li><p>If we want training to happen in <strong>minibatches</strong> , we can specify **<code>batch_size</code> **parameter. You can also pre-batch the data manually before passing it to <code>x</code>/<code>y</code>/<code>validation_data</code>, in which case you do not need <strong><code>batch_size</code></strong></p><p>model.fit(x=train_x_norm,y=train_labels,validation_data=(test_x_norm,test_labels),epochs=10,batch_size=1)</p></li></ul><blockquote><p>Note that you can c<strong>all<code>fit</code> function several times</strong> in a row to <strong>further<br>train the network</strong>. If you want to <strong>start training from scratch</strong> - you<br>need to <strong>re-run the cell with the model definition.</strong></p></blockquote><p>注:训练是叠加的,想从头训练需<strong>重定义网络</strong></p><h4 id="Multi-Class-Classificatio(多分类问题)"><a href="#Multi-Class-Classificatio(多分类问题)" class="headerlink" title="<2>Multi-Class Classificatio(多分类问题)"></a><2>Multi-Class Classificatio(多分类问题)</h4><pre><code> If you need to solve a problem of multi-class classification, your network would have more that one output - corresponding to the number of classes .**Each output will contain the probability of a given class.(多类多输出)**</code></pre><p>** <strong>When you expect a network to output a set of probabilities , we<br>need all of them to add up to 1. To ensure this, we use <code>softmax</code> as a final<br>activation function on the last layer. <strong>Softmax</strong> takes a vector input, and<br>makes sure that all components of that vector are transformed into<br>probabilities.</strong>(softmax 使所有概率和为1)**</p><pre><code> Also, since the output of the network is a C-dimensional vector, we need labels to have the same form. This can be achieved by using **one-hot encoding** , when the number of a class is i converted to **a vector of zeroes, with 1 at the i-th position.(独热码,一位1其他位0)** To compare the probability output of the neural network with expected one-hot-encoded label, we use **cross-entropy loss** function. It takes two probability distributions, and outputs a value of how different they are.**(概率输出和独热码标签计算交叉熵损失函数)**</code></pre><p>So, to <strong>summarize</strong> what we need to do for multi-class classification with<br>classes:</p><ul><li><p>The network should have neurons in the last layer</p></li><li><p><strong>Last activation function</strong> should be <strong>softmax</strong></p></li><li><p>Loss should be <strong>cross-entropy loss</strong></p></li><li><p>Labels should be converted to <strong>one-hot encoding</strong> (this can be done using <code>numpy</code>, or using Keras utils <code>to_categorical</code>)</p><p>model = keras.models.Sequential([<br>keras.layers.Dense(5,input_shape=(2,),activation=’relu’),<br>keras.layers.Dense(2,activation=’softmax’)<br>])<br>model.compile(keras.optimizers.Adam(0.01),’categorical_crossentropy’,[‘acc’])</p><h1 id="Two-ways-to-convert-to-one-hot-encoding"><a href="#Two-ways-to-convert-to-one-hot-encoding" class="headerlink" title="Two ways to convert to one-hot encoding"></a>Two ways to convert to one-hot encoding</h1><p>train_labels_onehot = keras.utils.to_categorical(train_labels)<br>test_labels_onehot = np.eye(2)[test_labels]</p><p>hist = model.fit(x=train_x_norm,y=train_labels_onehot,validation_data=[test_x_norm,test_labels_onehot],batch_size=1,epochs=10)</p></li></ul><p><strong>Sparse Categorical Cross-Entropy(稀疏分类交叉熵)(使用整数标签代替独热码标签)</strong></p><p>Often labels in multi-class classification are represented by class numbers.<br>Keras also supports another kind of loss function called <strong>sparse categorical<br>crossentropy</strong> , which expects class number to be <strong>integers</strong> , and not one-<br>hot vectors. Using this kind of loss function, we can simplify our training<br>code:</p><p><br> model.compile(keras.optimizers.Adam(0.01),’sparse_categorical_crossentropy’,[‘acc’])<br> model.fit(x=train_x_norm,y=train_labels,validation_data=[test_x_norm,test_labels],batch_size=1,epochs=10)</p><h4 id="Multi-Label-Classification(多标签分类)"><a href="#Multi-Label-Classification(多标签分类)" class="headerlink" title="<3>Multi-Label Classification(多标签分类)"></a><3>Multi-Label Classification(多标签分类)</h4><pre><code> With multi-label classification, instead of one-hot encoded vector, we will **have a vector that has 1 in position corresponding to all classes** relevant to the input sample. Thus, output of the network should not have normalized probabilities for all classes, but rather for each class individually - which corresponds to using **sigmoid** activation function. Cross-entropy loss can still be used as a loss function.**(不再使用独热码,而是标签中所有包含的位为1)**</code></pre><h4 id="总结-Summary-of-Classification-Loss-Functions"><a href="#总结-Summary-of-Classification-Loss-Functions" class="headerlink" title="<4>总结 Summary of Classification Loss Functions"></a><4>总结 <strong>Summary of Classification Loss Functions</strong></h4><pre><code> We have seen that binary, multi-class and multi-label classification **differ by the type of loss function and activation function on the last layer** of the network. It may all be a little bit confusing if you are just starting to learn, but here are a few rules to keep in mind:</code></pre><ul><li>If the network has one output (<strong>binary classification</strong>), we use <strong>sigmoid</strong> <strong>activation function</strong> , for <strong>multiclass classification</strong> - <strong>softmax</strong></li><li>If the output class is represented as one-hot-encoding, the <strong>loss function</strong> will be <strong>cross entropy loss</strong> (categorical cross-entropy), if the output contains class number - <strong>sparse categorical cross-entropy</strong>. For <strong>binary classification</strong> - use <strong>binary cross-entropy</strong> (same as <strong>log loss</strong>)</li><li><strong>Multi-label classification</strong> is when we can have an object belonging to several classes at the same time. In this case, we need to encode labels using one-hot encoding, and use <strong>sigmoid</strong> as activation function, so that each class probability is between 0 and 1.</li></ul><table><thead><tr><th>Classification</th><th>Label Format</th><th>Activation Function</th><th>Loss</th></tr></thead><tbody><tr><td>Binary</td><td>Probability of 1st class</td><td>sigmoid</td><td>binary crossentropy</td></tr><tr><td>Binary</td><td>One-hot encoding (2 outputs)</td><td>softmax</td><td>categorical crossentropy</td></tr><tr><td>Multiclass</td><td>One-hot encoding</td><td>softmax</td><td>categorical crossentropy</td></tr><tr><td>Multiclass</td><td>Class Number</td><td>softmax</td><td>sparse categorical crossentropy</td></tr><tr><td>Multilabel</td><td>One-hot encoding</td><td>sigmoid</td><td>categorical crossentropy</td></tr></tbody></table><h3 id="2-Tensorflow2-x-Keras"><a href="#2-Tensorflow2-x-Keras" class="headerlink" title="2.Tensorflow2.x+Keras"></a>2.Tensorflow2.x+Keras</h3><p><br> Tensorflow 2.x + Keras - new version of Tensorflow with integrated Keras functionality, which supports <strong>dynamic computation graph</strong> , allowing to perform tensor operations very similar to numpy (and PyTorch)</p><p><br> import tensorflow as tf<br> import numpy as np<br> print(tf.<strong>version</strong>)</p><h4 id="简单张量操作"><a href="#简单张量操作" class="headerlink" title="<1>简单张量操作"></a><1>简单张量操作</h4><h5 id="①创建"><a href="#①创建" class="headerlink" title="①创建"></a>①创建</h5><p>You can easily create simple tensors from lists of np-arrays, or generate<br>random ones</p><p><br> # 创建常量张量<br> a = tf.constant([[1,2],[3,4]])<br> print(a)<br> # 创建正态分布随机10*3张量<br> a = tf.random.normal(shape=(10,3))<br> print(a)</p><h5 id="②运算"><a href="#②运算" class="headerlink" title="②运算"></a>②运算</h5><p>You can use arithmetic operations on tensors, which are performed element-<br>wise, as in numpy. Tensors are automatically expanded to required dimension,<br>if needed. <strong>To extract numpy-array from tensor, use<br><code>.numpy()</code>:(将张量转化为np数组)(以下是运算示例:)</strong></p><p><br> print(a-a[0])<br> print(tf.exp(a)[0].numpy())</p><h4 id="计算梯度"><a href="#计算梯度" class="headerlink" title="<2>计算梯度"></a><2>计算梯度</h4><p>For back propagation, you need to compute gradients. This is done using<br><strong><code>tf.GradientTape()</code></strong> idiom:</p><ul><li><p>Add <code>with tf.GradientTape() as tape:</code> block around our computations</p></li><li><p>Mark those tensors with respect to which we need to compute gradients by calling <code>tape.watch</code> (all variables are <strong>watched automatically</strong>)</p></li><li><p>Compute whatever we need (build computational graph)</p></li><li><p>Obtain gradients using <code>tape.gradient</code></p><p>a = tf.random.normal(shape=(2, 2))<br>b = tf.random.normal(shape=(2, 2))</p><p>with tf.GradientTape() as tape:<br> tape.watch(a) # Start recording the history of operations applied to <code>a</code><br> c = tf.sqrt(tf.square(a) + tf.square(b)) # Do some math using <code>a</code></p><h1 id="What’s-the-gradient-of-c-with-respect-to-a"><a href="#What’s-the-gradient-of-c-with-respect-to-a" class="headerlink" title="What’s the gradient of c with respect to a?"></a>What’s the gradient of <code>c</code> with respect to <code>a</code>?</h1><p> dc_da = tape.gradient(c, a)<br> print(dc_da)</p></li></ul><p>监视变量、构建运算关系、计算梯度</p><h4 id="3-例1:线性回归问题"><a href="#3-例1:线性回归问题" class="headerlink" title="< 3>例1:线性回归问题"></a><strong>< 3>例1:线性回归问题</strong></h4><p>生成数据集</p><p><br> import matplotlib.pyplot as plt<br> from sklearn.datasets import make_classification, make_regression<br> from sklearn.model_selection import train_test_split<br> import random<br><br> np.random.seed(13) # pick the seed for reproducability - change it to explore the effects of random variations<br><br> train_x = np.linspace(0, 3, 120)<br> train_labels = 2 * train_x + 0.9 + np.random.randn(*train_x.shape) * 0.5</p><pre><code>plt.scatter(train_x,train_labels)</code></pre><p>定义损失函数:</p><p><br> input_dim = 1<br> output_dim = 1<br> learning_rate = 0.1<br><br> # This is our weight matrix<br> w = tf.Variable([[100.0]])<br> # This is our bias vector<br> b = tf.Variable(tf.zeros(shape=(output_dim,)))<br><br> def f(x):<br> return tf.matmul(x,w) + b</p><pre><code>def compute_loss(labels, predictions): return tf.reduce_mean(tf.square(labels - predictions))</code></pre><p>训练函数:</p><p><br> def train_on_batch(x, y):<br> with tf.GradientTape() as tape:<br> predictions = f(x)<br> loss = compute_loss(y, predictions)<br> # Note that <code>tape.gradient</code> works with a list as well (w, b).<br> dloss_dw, dloss_db = tape.gradient(loss, [w, b])<br> w.assign_sub(learning_rate * dloss_dw)<br> b.assign_sub(learning_rate * dloss_db)<br> return loss</p><p>训练集生成:</p><p><br> # Shuffle the data. 打乱数据<br> indices = np.random.permutation(len(train_x))<br> features = tf.constant(train_x[indices],dtype=tf.float32)<br> labels = tf.constant(train_labels[indices],dtype=tf.float32)</p><p>训练过程:(第 i 到 i+batch_size 为一组)</p><p><br> batch_size = 4<br> for epoch in range(10):<br> for i in range(0,len(features),batch_size):<br> loss = train_on_batch(tf.reshape(features[i:i+batch_size],(-1,1)),tf.reshape(labels[i:i+batch_size],(-1,1)))<br> print(‘Epoch %d: last batch loss = %.4f’ % (epoch, float(loss)))</p><p>绘制:</p><p><br> plt.scatter(train_x,train_labels)<br> x = np.array([min(train_x),max(train_x)])<br> y = w.numpy()[0,0]*x+b.numpy()[0]<br> plt.plot(x,y,color=’red’)</p><p><br> We now have obtained optimized parameters $W$ and $b$. Note that their values are <strong>similar to the original values used when generating the dataset</strong> (W=2, b=1)</p><p>本文转自 <a href="https://blog.csdn.net/qq_32971095/article/details/137124492">https://blog.csdn.net/qq_32971095/article/details/137124492</a>,如有侵权,请联系删除。</p>]]></content:encoded>
<category domain="https://xidianswq.github.io/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">学习笔记</category>
<category domain="https://xidianswq.github.io/tags/opencv/">opencv</category>
<category domain="https://xidianswq.github.io/tags/c/">c++</category>
<category domain="https://xidianswq.github.io/tags/python/">python</category>
<category domain="https://xidianswq.github.io/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">学习笔记</category>
<category domain="https://xidianswq.github.io/tags/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/">人工智能</category>
<category domain="https://xidianswq.github.io/tags/AI/">AI</category>
<comments>https://xidianswq.github.io/2024/03/29/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/AI%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/#disqus_thread</comments>
</item>
<item>
<title>人工智能导论(1)——c语言实现进化算法</title>
<link>https://xidianswq.github.io/2024/03/14/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD%E5%AF%BC%E8%AE%BA(1)%E2%80%94%E2%80%94c%E8%AF%AD%E8%A8%80%E5%AE%9E%E7%8E%B0%E8%BF%9B%E5%8C%96%E7%AE%97%E6%B3%95/</link>
<guid>https://xidianswq.github.io/2024/03/14/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD%E5%AF%BC%E8%AE%BA(1)%E2%80%94%E2%80%94c%E8%AF%AD%E8%A8%80%E5%AE%9E%E7%8E%B0%E8%BF%9B%E5%8C%96%E7%AE%97%E6%B3%95/</guid>
<pubDate>Thu, 14 Mar 2024 09:23:20 GMT</pubDate>
<description><h2 id="一-问题描述"><a href="#一-问题描述" class="headerlink" title="一.问题描述"></a>一.问题描述</h2></description>
<content:encoded><![CDATA[<h2 id="一-问题描述"><a href="#一-问题描述" class="headerlink" title="一.问题描述"></a>一.问题描述</h2><p>求该函数的最优解:</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/b72b9e9aec3b2c8f64d8b9f4e22efa21.png"></p><p>解题思路:</p><p>变量编码->生成种群->交叉->变异->选择->迭代</p><pre><code> 对x1和x2在变量范围内的值按照给定精度计算编码成二进制码的位数;随机生成一定规模的种群,其二进制编码随机; 随机对种群内个体的编码进行交叉;随机对种群内个体的编码进行按位变异;对二进制码进行解码、求解适应度函数值、保留一定数量的精英、采用轮盘赌随机选取其余个体最终组成新的种群;迭代,重复 交叉->变异->选择 至最优适应度基本不变或迭代一定次数。</code></pre><h2 id="二-代码解析"><a href="#二-代码解析" class="headerlink" title="二.代码解析"></a>二.代码解析</h2><h3 id="1-源码"><a href="#1-源码" class="headerlink" title="1.源码"></a>1.源码</h3><p><br> #include<stdio.h><br> #include<stdlib.h><br> #include<string.h><br> #include<stdbool.h><br> #include<math.h><br> #include<time.h><br><br> #define POPULATION_SIZE 100//种群规模<br> #define RESERVE_NUM 3//每代精英保留数<br> #define VARI_NUM 2//变量个数<br> #define ITERATION 1000//迭代次数<br> #define END_TIMES 100//稳定终止次数<br> #define PC 0.6//交叉概率<br> #define CROSS_LEN 8//交叉长度<br> #define PM 0.1//变异概率 </p><pre><code>//种群结构体 typedef struct v{bool encode[50];//二进制编码 double value[VARI_NUM];//解码数值 bool change;//标记是否发生交叉或变异 double fitness;//适应度double fit_rate;//适应度占比 }v;double lower[VARI_NUM],upper[VARI_NUM],accur;//x1,x2上下界和精度 int encode_num,encode_number[VARI_NUM];//二进制编码位数 double real_accur[VARI_NUM];//实际精度 v optimization_popu;//最优个体 //函数声明 v Get_Optimization(void);void Init_Population(v* group);void Cross(v* group);void Mutation(v* group);v* Select(v**group);double Fitness(double x1,double x2); void Output_Result(v* optimization);void Free_space(v** group);//************************************************************************************************************int main(){int i;v temp;//输入样例:-3.0 12.1 4.1 5.8 0.0001 printf("输入变量x1和x2的上下界和精度(x1_lower,x1_upper,x2_lower,x2_upper,accur):");scanf("%lf%lf%lf%lf%lf",&lower[0],&upper[0],&lower[1],&upper[1],&accur);//可以多次进行实验for(i=0;i<1;i++){temp=Get_Optimization();if(optimization_popu.fitness<temp.fitness)optimization_popu=temp;}Output_Result(&optimization_popu);return 0;}//************************************************************************************************************v Get_Optimization(void){srand((unsigned)time(NULL));int i,j;double temp;v** group=(v**)malloc(3*sizeof(v*));//原始、交叉、变异种群for(i=0;i<3;i++)group[i]=(v*)malloc(sizeof(v)*POPULATION_SIZE);v* optimization=group[0],opt_tmep;//最优种群 //初始化种群 Init_Population(group[0]);memcpy(group[1],group[0],sizeof(v)*POPULATION_SIZE); memcpy(group[2],group[0],sizeof(v)*POPULATION_SIZE);//迭代 for(i=j=0;i<ITERATION;i++){//交叉Cross(group[1]); //变异Mutation(group[2]);//选择 temp=optimization->fitness;optimization=Select(group); if((optimization->fitness-temp)<accur){j++;if(j>=END_TIMES)break;//结果保持稳定则退出 } }//输出结果Output_Result(optimization); opt_tmep=*optimization;Free_space(group);return opt_tmep;}//计算变量二进制编码位数 int Encode_Num(double lower,double upper,double accur){int num,i,j;num=(upper-lower)/accur+1;for(i=0,j=1;j<num;j*=2,i++);return i;}void Init_Population(v* group){int i,j;for(i=encode_num=0;i<VARI_NUM;i++)encode_num+=(encode_number[i]=Encode_Num(lower[i],upper[i],accur));//计算编码位数for(i=0;i<VARI_NUM;i++)real_accur[i]=(upper[i]-lower[i])/(pow(2,encode_number[i])-1);//计算实际精度//初始化种群 for(i=0;i<POPULATION_SIZE;i++){//随机生成二进制编码 for(j=0;j<encode_num;j++){group[i].encode[j]=rand()%2;//printf("%d %d:%d\n",i,j,group[i].encode[j]);}group[i].change=true;}}//交叉lower和upper之间的编码 void Cross(v* group){double p;int i,j,lower,upper;bool temp;//随机选取交叉片段lower=rand()%(encode_num-CROSS_LEN-1);upper=lower+CROSS_LEN; for(i=0;i<POPULATION_SIZE/2-1;i++){p=1.0*rand()/RAND_MAX;//***随机数*** if(p<PC){ //交叉 for(j=lower;j<upper;j++){temp=group[i].encode[j];group[i].encode[j]=group[POPULATION_SIZE-1-i].encode[j];group[POPULATION_SIZE-1-i].encode[j]=temp;}}//标记未交叉 else group[i].change=group[POPULATION_SIZE-1-i].change=false;}} //按位变异 void Mutation(v* group){double p;int i,j;for(i=0;i<POPULATION_SIZE/2;i++){for(j=0;j<encode_num;j++){p=1.0*rand()/RAND_MAX;//***随机数*** if(p<PM)group[i].encode[j]=!group[i].encode[j];else group[i].change=false;}}}//选择v* Select(v**group){v* fitist[RESERVE_NUM],*group_temp=(v*)malloc(sizeof(v)*POPULATION_SIZE);int i,j,k,l,m,n;int vaild_num;//有效个数 double fit_sum;//适应度总大小for(i=0;i<RESERVE_NUM;i++)fitist[i]=&group[0][0]; //解码并计算适应度函数 for(vaild_num=fit_sum=i=0;i<3;i++){for(j=0;j<POPULATION_SIZE;j++){if(!group[i][j].change)continue; for(m=n=0;m<VARI_NUM;n+=encode_number[m],m++){for(k=l=0;k<encode_number[m];k++)l+=group[i][j].encode[k+n]*pow(2,k);//解码 group[i][j].value[m]=lower[m]+l*real_accur[m];//printf("%d %d--value[%d]:%lf\n",i,j,m,group[i][j].value[m]);}//计算适应度 group[i][j].fitness=Fitness(group[i][j].value[0],group[i][j].value[1]);//保存适应度大的个体for(k=0;k<RESERVE_NUM;k++){if(group[i][j].fitness>fitist[k]->fitness){for(l=k;l<RESERVE_NUM-1;l++)fitist[l+1]=fitist[l];fitist[k]=&group[i][j];}}vaild_num++;fit_sum+=group[i][j].fitness;//适应度总和计算 //printf("%d %d--fitness:%lf\n",i,j,group[i][j].fitness);}} //***保留优秀个体***for(i=0;i<RESERVE_NUM;i++)group_temp[i]=*fitist[i];//计算比率 for(i=0;i<3;i++){for(j=0;j<POPULATION_SIZE;j++){if(!group[i][j].change)continue;group[i][j].fit_rate=group[i][j].fitness/fit_sum;//printf("%d %d--fit_rate:%lf\n",i,j,group[i][j].fit_rate);}}//轮盘赌选择for(i=RESERVE_NUM;i<POPULATION_SIZE;i++){double p=1.0*rand()/RAND_MAX;//寻找所处区间double temp;for(temp=0,j=0;j<3;j++){for(k=0;k<POPULATION_SIZE;k++){if(!group[j][k].change)continue;temp+=group[j][k].fit_rate;if(p<temp)break;}if(p<temp)break;}//复制 if(j!=3&&k!=POPULATION_SIZE)group_temp[i]=group[j][k];else group_temp[i]=group[j-1][k-1];//printf("select %3d from %3d %3d--fitness:%lf--p:%lf\n",i,j,k,group_temp[i].fitness,p);} memcpy(group[0],group_temp,sizeof(v)*POPULATION_SIZE);free(group_temp);return fitist[0]; }//适应度函数 double Fitness(double x1,double x2){return 21.5+x1*sin(4*M_PI*x1)+x2*sin(20*M_PI*x2);}void Output_Result(v* optimization){int i;printf("最优解为:x1=%9lf x2=%9lf f(x1,x2)=%9lf 二进制编码为:",optimization->value[0],optimization->value[1],optimization->fitness); for(i=0;i<encode_num;i++)printf("%d",optimization->encode[i]);printf("\n");}//释放空间 void Free_space(v** group){int i;for(i=0;i<3;i++)free(group[i]);free(group);}</code></pre><h3 id="2-算法关键参数"><a href="#2-算法关键参数" class="headerlink" title="2.算法关键参数"></a>2.算法关键参数</h3><p><br> #define POPULATION_SIZE 100//种群规模<br> #define RESERVE_NUM 3//每代精英保留数<br> #define VARI_NUM 2//变量个数<br> #define ITERATION 1000//迭代次数<br> #define END_TIMES 100//稳定终止次数<br> #define PC 0.6//交叉概率<br> #define CROSS_LEN 8//交叉长度<br> #define PM 0.1//变异概率 </p><h3 id="3-定义种群结构体、相关变量及函数"><a href="#3-定义种群结构体、相关变量及函数" class="headerlink" title="3.定义种群结构体、相关变量及函数"></a>3.定义种群结构体、相关变量及函数</h3><p><br> //种群结构体<br> typedef struct v{<br> bool encode[50];//二进制编码<br> double value[VARI_NUM];//解码数值<br> bool change;//标记是否发生交叉或变异<br> double fitness;//适应度<br> double fit_rate;//适应度占比<br> }v;<br><br> double lower[VARI_NUM],upper[VARI_NUM],accur;//x1,x2上下界和精度<br> int encode_num,encode_number[VARI_NUM];//二进制编码位数<br> double real_accur[VARI_NUM];//实际精度<br> v optimization_popu;//最优个体 </p><pre><code>//函数声明 v Get_Optimization(void);void Init_Population(v* group);void Cross(v* group);void Mutation(v* group);v* Select(v**group);double Fitness(double x1,double x2); void Output_Result(v* optimization);void Free_space(v** group);</code></pre><h3 id="4-求解流程"><a href="#4-求解流程" class="headerlink" title="4.求解流程"></a>4.求解流程</h3><p><br> v Get_Optimization(void){<br> <br> srand((unsigned)time(NULL));<br> int i,j;<br> double temp;<br> v** group=(v**)malloc(3<em>sizeof(v</em>));//原始、交叉、变异种群<br> for(i=0;i<3;i++)group[i]=(v*)malloc(sizeof(v)<em>POPULATION_SIZE);<br> v</em> optimization=group[0],opt_tmep;//最优种群<br> <br> //初始化种群<br> Init_Population(group[0]);<br> memcpy(group[1],group[0],sizeof(v)*POPULATION_SIZE);<br> memcpy(group[2],group[0],sizeof(v)*POPULATION_SIZE);<br> <br> //迭代<br> for(i=j=0;i<ITERATION;i++){<br> <br> //交叉<br> Cross(group[1]);<br> //变异<br> Mutation(group[2]);<br> //选择<br> temp=optimization->fitness;<br> optimization=Select(group);<br> if((optimization->fitness-temp)<accur){<br> j++;<br> if(j>=END_TIMES)break;//结果保持稳定则退出<br> }<br> <br> }<br> <br> //输出结果<br> Output_Result(optimization);<br> <br> opt_tmep=*optimization;<br> Free_space(group);<br> return opt_tmep;<br> <br> }</p><h2 id="三-求解结果"><a href="#三-求解结果" class="headerlink" title="三.求解结果"></a>三.求解结果</h2><pre><code> 改变算法关键参数会导致求解结果不同,不同的时间下的结果也不同。可以改变主函数中for循环的结束条件多次进行实验:</code></pre><p><br> //可以多次进行实验<br> for(i=0;i<1;i++){<br> temp=Get_Optimization();<br> if(optimization_popu.fitness<temp.fitness)optimization_popu=temp;<br> }<br><br> 笔者在一定的参数下得到了最优解:</p><p><br> 最优解为:<br> x1=11.625358<br> x2=5.725031<br> f(x1,x2)=38.850261<br> 二进制编码为:<br> 111100111111101111010110100101111<br><br> 对于问题二,修改适应度函数:</p><p><br> //适应度函数<br> double Fitness(double x1,double x2){<br> //return 21.5+x1<em>sin(4</em>M_PI<em>x1)+x2</em>sin(20<em>M_PI</em>x2);<br> return 100<em>pow((x2-x1</em>x1),2)+pow((1-x1),2);<br> }<br><br> 再输入变量范围及精度 :</p><p><br> 输入样例2:-2.048 2.048 -2.048 2.048 0.0001</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/1ede4e3460860a1737bc72b9a592cb66.png"></p><p><br> 最优解为:x1=-2.047875 x2=-2.037187 f(x1,x2)=3891.799899<br> 二进制编码为:01000000000000001011010100000000</p><h2 id="四-相关思考"><a href="#四-相关思考" class="headerlink" title="四.相关思考"></a>四.相关思考</h2><p>1.增加精度可以增加编码长度,减少交叉变异的影响,增加搜索精度,结果可能更加靠近最优解</p><p>2.增加变异概率以产生更多新的性状(<strong>变异的概率可采用自适应概率,如果最优种个体适应度值长时间未变化,可增加变异概率</strong><br>),以及采用更复杂的交叉、变异算法</p><p>3.交叉、变异过于随机会使求解趋于“遍历”,并且算法的“朝最优解的驱动力”不足</p><p>本文转自 <a href="https://blog.csdn.net/qq_32971095/article/details/136715239">https://blog.csdn.net/qq_32971095/article/details/136715239</a>,如有侵权,请联系删除。</p>]]></content:encoded>
<category domain="https://xidianswq.github.io/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">学习笔记</category>
<category domain="https://xidianswq.github.io/tags/%E7%AE%97%E6%B3%95/">算法</category>
<category domain="https://xidianswq.github.io/tags/%E4%BD%9C%E4%B8%9A%E8%A7%A3%E7%AD%94/">作业解答</category>
<category domain="https://xidianswq.github.io/tags/c%E8%AF%AD%E8%A8%80/">c语言</category>
<comments>https://xidianswq.github.io/2024/03/14/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD%E5%AF%BC%E8%AE%BA(1)%E2%80%94%E2%80%94c%E8%AF%AD%E8%A8%80%E5%AE%9E%E7%8E%B0%E8%BF%9B%E5%8C%96%E7%AE%97%E6%B3%95/#disqus_thread</comments>
</item>
<item>
<title>FPGA学习笔记(42)——Vitis开发二</title>
<link>https://xidianswq.github.io/2024/03/01/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/FPGA%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0(42)%E2%80%94%E2%80%94Vitis%E5%BC%80%E5%8F%91%E4%BA%8C/</link>
<guid>https://xidianswq.github.io/2024/03/01/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/FPGA%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0(42)%E2%80%94%E2%80%94Vitis%E5%BC%80%E5%8F%91%E4%BA%8C/</guid>
<pubDate>Fri, 01 Mar 2024 07:51:21 GMT</pubDate>
<description><p>参考:《DFZU2EG_4EV MPSoC 之嵌入式 VITIS 开发指南》——正点原子</p></description>
<content:encoded><![CDATA[<p>参考:《DFZU2EG_4EV MPSoC 之嵌入式 VITIS 开发指南》——正点原子</p><h2 id="一-自定义-IP-核-呼吸灯实验"><a href="#一-自定义-IP-核-呼吸灯实验" class="headerlink" title="一.自定义 IP 核-呼吸灯实验"></a>一.自定义 IP 核-呼吸灯实验</h2><h3 id="1-简介"><a href="#1-简介" class="headerlink" title="1.简介"></a>1.简介</h3><pre><code> 通过**创建和封装 IP 向导** 的方式来自定义 IP 核,将模块集成到 Vivado 中的 IP 库中。本 次实验选择常用的方式,即创建一个带有 AXI 接口的 IP 核,该 IP 核通过 AXI 协议实现 PS 和 PL 的数据通信。</code></pre><h4 id="硬件框图"><a href="#硬件框图" class="headerlink" title="<1>硬件框图"></a><1>硬件框图</h4><p><img src="https://i-blog.csdnimg.cn/blog_migrate/f7f69746d9c8b2612a562e216cbcb06d.png"></p><pre><code> 自定义一个 LED IP 核,来控制 PL LED 呈现呼吸灯的效果,并且 **PS 可以通过 AXI 接口来控制呼吸灯的开关和呼吸的频率** 。</code></pre><h3 id="2-硬件设计"><a href="#2-硬件设计" class="headerlink" title="2.硬件设计"></a>2.硬件设计</h3><h4 id="step1:自定义IP核"><a href="#step1:自定义IP核" class="headerlink" title="step1:自定义IP核"></a>step1:自定义IP核</h4><h5 id="创建IP核"><a href="#创建IP核" class="headerlink" title="<1>创建IP核"></a><1>创建IP核</h5><pre><code> 在vivado进入界面点击“Tasks”栏中的“Manage IP”。在弹出的选项中选择“New IP Location...”</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/75f9ff5dc9db70244cab46a870f0688d.png"></p><p>设置工程路径**“IP Location”** 和 器件**“Part”(后续可重新指定):**</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/f3b1e3885d4a1f135051044efbbe1a2b.png"></p><pre><code> 工程创建完成后,运行**创建和封装 IP 向导** 。点击**菜单栏的“Tools”** ,选择**“Create and Package New IP”** ,在弹出的界面中,点击“NEXT”</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/cb4052ba288d62dba075506fe808c59d.png"></p><p>可选择封装 IP 或者创建一个带 AXI4 接口的 IP 核 :</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/d966c8cd8965f275b224c4f87af580a0.png"></p><pre><code> 接下来分别设置 IP 核名称(Name)、版本号(Version)、显示名(Display name)、描述(Description) 和路径(IP location)。</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/eb004f9d3e754f9cc51b150f9afb459d.png"></p><p>接下来对 AXI 接口进行设置:</p><p><strong>Name(名称)</strong> :这里修改成 S0_AXI。</p><p><strong>Interface Tpye(接口类型)</strong> :共三种接口类型可选,分别是 <strong>Lite、Full 和 Stream</strong> 。AXI4-Lite<br>接口是<strong>简化版</strong> 的 AXI4 接口,用于较少数据量的存储映射通信;AXI4-Full 接口是<strong>高性能存储映射接口</strong><br>,用于较多数据量的存储映射通信;AXI4-Stream 用于<strong>高速数据流传输</strong> ,非存储映射接口。本次实验只需少量数据的通信, 因此接口类型选择默认的<br>Lite 接口。</p><p><strong>Interface Mode(接口模式)</strong> :接口模式有 <strong>Slave(从机)和 Master(主机)</strong> 两种模式可选,AXI<br>协议是<strong>主机和从机通过“握手”的方式建立连接</strong> ,这里选择默认的 <strong>Slave 接口模式</strong> 。</p><p><strong>Data Width(数据宽度)</strong> :数据位宽保持默认,即 32 位位宽。</p><p><strong>Memory Size(存储器大小)</strong> : 在 AXI4-Lite 接口模式下,该选项不可设置。</p><p><strong>Number of Registers(寄存器数量)</strong> :用于配置 PL LED 呼吸灯寄存器的数量,这里保持默认。</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/91283af0eb0913bef4fd7d225f3b9a7b.png"></p><pre><code> 最后弹出封装接口的总结描述和下一步操作选项的界面。这里保持默认,即**将 IP 添加至 IP 库中** , 点击“Finish”按钮完成 IP 核的创建和封装。</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/413f0da1496d94c764828b274017a30e.png"></p><pre><code> 在 **IP Catalog 界面** 中可以看到刚刚添加的 IP 核,位于 **User Repository** 一栏中的 AXI Peripheral 下,名称 为“breath_led_ip_v1.0”</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/5a18c63c55f085bf15281c34ab989331.png"></p><h5 id="编辑IP核"><a href="#编辑IP核" class="headerlink" title="<2>编辑IP核"></a><2>编辑IP核</h5><pre><code> 右击 breath_led_ip_v1.0 IP 核, 选择“**Edit in IP Packager** ”,在弹出的界面中点击“OK”。此时会打开一个新的工程:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/63e543b57d5d554d9b74780351c6fb78.png"></p><pre><code> 双击 breath_led_ip_v1_0.v文件即可开始编辑代码,来添加控制 PL LED 呼吸灯所需要的参数和端口信号:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/e30dec6de76b6e61b1aa50c039589999.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/e3f8c3ad3ebbdf5bdc9e7ad185618452.png"></p><pre><code> 在创建和封装 IP 核向导中,我们总共定义了 4 个寄存器,代码中的 slv_reg0 至 slv_reg3 是寄存器地址 0 至寄存器地址 3 对应的数据,通过例化呼吸灯模块,**将寄存器地址对应的数据和呼 吸灯模块(breath_led****) 的控制端口相连接**,即可实现对呼吸灯的控制。 </code></pre><p>breath_led_ip_v1_0.v文件:</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/252b8cca44230059c49602a5452d9998.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/0f62dc01cb25ae99d4f697d5b7638e66.png"></p><pre><code> breath_led_ip_v1_0_S0_AXI.v文件。 breath_led_ip_v1_0_S0_AXI 模块实现了 AXI4 协议下的读写寄存器的功能:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/425827ac7a64452aea8a0413ea593bcf.png"></p><p>时我们还需要在代码的第 401 行例化 breath_led.v 文件:</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/6ffed17009e2230f835db7440ba21eee.png"></p><p><br> // Add user logic here<br> breath_led #(<br> .START_FREQ_STEP(START_FREQ_STEP)<br> )<br> u_breath_led(<br> .sys_clk (S_AXI_ACLK),<br> .sys_rst_n (S_AXI_ARESETN),<br> .sw_ctrl (slv_reg0[0]),<br> .set_en (slv_reg1[31]),<br> .set_freq_step (slv_reg1[9:0]),<br> .led (led)<br> );<br> // User logic ends<br><br> 代码中的 <strong>slv_reg0 和 slv_reg1 是寄存器地址 0 和寄存器地址 1 对应的数据</strong> ,我们通过寄存器地址 0 对应 的数据来控制呼吸灯的使能(sw_ctrl),寄存器地址 1 对应数据的最高位控制呼吸灯频率的设置有效信号 (set_en),寄存器地址 1 对应数据的低 10 位控制呼吸灯频率的步长(set_freq_step)。</p><pre><code> 此时工程中缺失 breath_led.v 文件,breath_led.v 文件用于实现呼吸灯的功能。右击**“Design Sources”** ,选择**“Add Sources…”** ,在弹出的界面中选择“**Add or Create design source”** , 点击“NEXT”;点击“**Create File ”** 创建一个新的文件,在弹出的界面输入名称 breath_led ,路径 为../**_custom_ip/ip_repo/breath_led_ip_1.0/_ hdl**,点击“OK”按钮</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/0e3c33e0d2c764bd425828a96898b80d.png"></p><pre><code> 在弹出的**模块定义界面中点击“OK”按钮** ,接下来在弹出的确认按钮中点击“YES”。双击 u_breath_led(breath_led.v)文件并编辑代码如下:</code></pre><p><br> module breath_led(<br> input sys_clk , //时钟信号<br> input sys_rst_n , //复位信号<br> input sw_ctrl , //呼吸灯开关控制信号 1:亮 0:灭<br> input set_en , //设置呼吸灯频率设置使能信号<br> input [9:0] set_freq_step , //设置呼吸灯频率变化步长<br><br> output led //LED<br> );</p><pre><code>//*****************************************************//** main code//*****************************************************//parameter defineparameter START_FREQ_STEP = 10'd100; //设置频率步长初始值//reg definereg [15:0] period_cnt ; //周期计数器reg [9:0] freq_step ; //呼吸灯频率间隔步长reg [15:0] duty_cycle ; //设置高电平占空比的计数点reg inc_dec_flag; //用于表示高电平占空比的计数值,是递增还是递减 //为1时表示占空比递减,为0时表示占空比递增//wire definewire led_t ;//将周期信号计数值与占空比计数值进行比较,以输出驱动led的PWM信号assign led_t = ( period_cnt <= duty_cycle ) ? 1'b1 : 1'b0 ;assign led = led_t & sw_ctrl;//周期信号计数器在0-50_000之间计数always @ (posedge sys_clk) begin if (!sys_rst_n) period_cnt <= 16'd0; else if(!sw_ctrl) period_cnt <= 16'd0; else if( period_cnt == 16'd50_000 ) period_cnt <= 16'd0; else period_cnt <= period_cnt + 16'd1;end//设置频率间隔always @(posedge sys_clk) begin if(!sys_rst_n) freq_step <= START_FREQ_STEP; else if(set_en) begin if(set_freq_step == 0) freq_step <= 10'd1; else if(set_freq_step >= 10'd1_000) freq_step <= 10'd1_000; else freq_step <= set_freq_step; end end//设定高电平占空比的计数值always @(posedge sys_clk) begin if (sys_rst_n == 1'b0) begin duty_cycle <= 16'd0; inc_dec_flag <= 1'b0; end else if(!sw_ctrl) begin //呼吸灯开关关闭时,信号清零 duty_cycle <= 16'd0; inc_dec_flag <= 1'b0; end //每次计数完了一个周期,就调节占空比计数值 else if( period_cnt == 16'd50_000 ) begin if( inc_dec_flag ) begin //占空比递减 if( duty_cycle == 16'd0 ) inc_dec_flag <= 1'b0; else if(duty_cycle < freq_step) duty_cycle <= 16'd0; else duty_cycle <= duty_cycle - freq_step; end else begin //占空比递增 if( duty_cycle >= 16'd50_000 ) inc_dec_flag <= 1'b1; else duty_cycle <= duty_cycle + freq_step; end end else //未计数完一个周期时,占空比保持不变 duty_cycle <= duty_cycle ;end endmodule 模块实现了呼吸灯的功能。呼吸灯的使能由输入的端口信号 sw_ctrl 控制,呼吸灯的呼吸频率由输入的端口信号 set_en 和 set_freq_step 控制。输入的 set_freq_step 范围是 1~1000。 在左侧 Flow Navigator 导航栏中找到 SYNTHESIS,点击 该选项中的 **“Run Synthesis”** ,等待代码编译完成。</code></pre><h5 id="IP-封装"><a href="#IP-封装" class="headerlink" title="<3>IP 封装"></a><3>IP 封装</h5><pre><code> 将界面切换至 Package IP,也可以通过 **IP-XACT** 界面下的 **component.xml** 重新打开:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/a1c22b4d8b6ddec5fb30e7748ee701a2.png"></p><pre><code> Identification 这一栏的选项直接保持默认,需要注意的是,我们可以点击图 6.3.31 中 **Categories** 选项下 的“+”按钮来**修改 IP 的分类** ,这里不做修改。 </code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/e936bc92628f578319803047bbae7cc5.png"></p><pre><code> 这里勾选“zynq”和“zynquplus”两项,表示该 IP 核支持 ZYNQ 和 ZYNQ MPSOC 器件。而 Life-cycle 表明该 IP 核当前的产品生命周期,这里选择“**Pre-Production** ”</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/f16af805e5acec286ff245098ff0bdf9.png"></p><pre><code> 点击 File Groups,然后点击界面上的“Merge Changes from File Groups Wizard”,此时可以在 Verilog Synthesis 一栏中查看工程中的三个模块。 点击 **Customization Parameters** ,点击界面上的“**Merge Changes from Customization Parameters Wizard”** ,此时多了 Hidden Parameters 一栏,展开这个界面,可以看到程序中自定义的参数 START_FREQ_STEP, 右击这个参数,选择“Edit Parameter…”,弹出编辑参数的界面:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/0dc10a436eeb939c31cf5a88916780d3.png"></p><pre><code> 在弹出的页面中勾选“Visible in Customization GUI”,将此参数显示在 GUI 参数界面中; Format 格式改为“long”; 勾选“Specify Range”来设定此参数的范围。将 Type 改为“Range of integers”,Minimum 的值改为 1, Maximum 的值改为 1000,将 Default Value 的值改为 100,点击“OK”按钮:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/e7bab0fc3776af968cd45566c20131a0.png"></p><pre><code> 点击“Customization GUI”,可以在“Layout”界面拖动 Page 0 下的参数来调整参数在 GUI 显示 的位置,如下图所示:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/1c5ef7a9cd6f3c7a15449f3584ad9974.png"></p><pre><code> 点击**“Review and Package”** ,然后点击“**IP has been modified”** 更新总结界面,最后点击**“Re-Package IP”** ,如下图所示: </code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/d280db132f7fdb24445364a47d6a502d.png"></p><pre><code> IP 核封装完成后,在 IP 核所在路径(...\custom_ip\ip_repo\breath_led_ip_1.0\drivers\breath_led_ip_v1_0\src) 目录下,Vivado 软件会自动生成.c 和.h 文件,方便在 VITIS 软件中对 IP 核进行操作。最后关闭工程IP核创建结束。</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/161d049dd7e3bf4ca866b0d0354554ae.png"></p><h4 id="step2:创建vivado工程"><a href="#step2:创建vivado工程" class="headerlink" title="step2:创建vivado工程"></a>step2:创建vivado工程</h4><pre><code> 创建 Vivado 工程名为 user_led,具体过程见前。点击菜单栏的“Tools”, 选择“Setting”,把自定义的IP核添加至本工程的IP库中:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/62472d612e15937378ba85ce4929f62b.png"></p><pre><code> 点击“IP”一栏下的“Repository”,然后点击“+”来添加自定义的 IP 核。选择../custom_ip/**ip_repo/breath_led_ip_1.0** ,点击“Select”,点击“OK”按钮添加 IP 核:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/91eae14f825c3128bdcadc291c08c7ed.png"></p><h4 id="step3:使用-IP-Integrator-创建-Processing-System"><a href="#step3:使用-IP-Integrator-创建-Processing-System" class="headerlink" title="step3:使用 IP Integrator 创建 Processing System"></a>step3:使用 IP Integrator 创建 Processing System</h4><pre><code> 在左侧导航栏(Flow Navigator)中,单击 IP Integrator 下的 Create Block Design。然后在弹出的对话框中指定所创建的 Block Design 的名称,这里使用默认的“design_1”。在 Diagram 窗口中给设计添加 IP。点击图中加号“+”,会打开 IP 目录(IP Catalog)。在搜索栏中 键入“zynq”,找到并双击“ZYNQ Ultrascale+ MPSoC”,将 MPSOC 处理系统 IP 添加到设计中。和前面搭建嵌入式最小系统不同的是,我们保留了 pl_clk0、pl_resetn0、maxihpm0_lpd_aclk 和 M_AXI_HPM0_LPD 接口,只是添加了 UART 控制器(MIO42 和 MIO43),修改 Bank 电压和修改 DDR4 控制器**(见前)** 其它保持默认。</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/16e20796ae329a0e1e72eb83e2676f4a.png"></p><pre><code> 接下来添加 Breath LED IP 核,点击“+”图标,在搜索框中输入“led”,即可找到之前添加的“breath_led_ip_v1.0”IP,添加此IP核,可以双击 led IP 核来设置参数,可以看到我们自定义的参数(Start Freq Step)和其它四个参数:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/89e3ce79246c6299be15abc7c427678b.png"></p><pre><code> 接下来点击**“Run Connection Automation”** 来自动连线,在弹出的窗口中勾选 **All Automation** ,然后点击 OK。此时原理图中还没有 LED 的引脚,右击 breath_led_ip_0 的 led 引脚,选择“Make External”,将引出的 led_0 改为 led:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/42ab2d5ad83cb9c00869f8e240a49e7b.png"></p><h4 id="step4:生成顶层-HDL-模块"><a href="#step4:生成顶层-HDL-模块" class="headerlink" title="step4:生成顶层 HDL 模块"></a>step4:生成顶层 HDL 模块</h4><pre><code> 在 Sources 窗口中,选中 **Design Sources** 下的 design_1.bd,这就是我们刚刚完成的 Block Design 设 计。右键点击 design_1.bd,在弹出的菜单栏中选择**“Generate Output Products”** ,等待 Generate 完成。在 Sources 窗口中,右键点击 design_1.bd,在弹出的菜单栏中选择**“Create HDL Wrapper”** 。</code></pre><h4 id="step5:生成-Bitstream-文件并导出-Hardware。"><a href="#step5:生成-Bitstream-文件并导出-Hardware。" class="headerlink" title="step5:生成 Bitstream 文件并导出 Hardware。"></a>step5:生成 Bitstream 文件并导出 Hardware。</h4><pre><code> 在左侧 Flow Navigator 导航栏中找到 RTL ANALYSIS,点击该选项中的**“Open Elaborated Design”** 。在 ELABORATED DESIGN 界面下方找到 I/O Ports 一栏。如果没有找到则通过在菜单栏中点击 Layout, 然后在下拉列表中选择 I/O Planning。我们将在 I/O Ports 一栏对 PL 部分的接口进行管脚分配,led 分配至**BANK44** 的 **AE10** 引脚,该 BANK 的供电电压为**3.3V** ,因此 I/O Std 一列对应的电平也需要修改。 设置完成后按快捷 Ctrl+S 保存管脚约束,在弹出的对话框输入文件名“user_led”。在左侧 Flow Navigator 导航栏中找到 PROGRAM AND DEBUG,点击该选项中的**“Generate Bitstream”** 。在连续弹出的对话框中依次点击“YES”、“OK”。然后 Vivado 工具开始依次对设计进行综合、实现、并生成 Bitstream 文件。在菜单栏中选择 File > Export > **Export hardware** 。在弹出的对话框中,勾选“**Include bitstream** ”,然后点 击“OK”按钮。 新建 vitis 文件夹,将 xsa 文件拷贝到里面。选择菜单 Tools->Launch Vitis。在弹出的界面中,指定路径到..\custom_ip\user_led\vitis 下,点击 “Launch”,打开 Vitis 软件。</code></pre><h3 id="3-软件设计"><a href="#3-软件设计" class="headerlink" title="3.软件设计"></a>3.软件设计</h3><p>新建vitis工程user_led,流程同前,main.c文件内容如下:</p><p><br> #include “stdio.h”<br> #include “xparameters.h”<br> #include “xil_printf.h”<br> #include “breath_led_ip.h”<br> #include “xil_io.h”<br> #include “sleep.h”<br><br> #define LED_IP_BASEADDR XPAR_BREATH_LED_IP_0_S0_AXI_BASEADDR //LED IP基地址<br> #define LED_IP_REG0 BREATH_LED_IP_S0_AXI_SLV_REG0_OFFSET //LED IP寄存器地址0<br> #define LED_IP_REG1 BREATH_LED_IP_S0_AXI_SLV_REG1_OFFSET //LED IP寄存器地址1</p><pre><code>//main函数int main(){ int freq_flag; //定义频率状态,用于循环改变呼吸灯的呼吸频率 int led_state; //定义LED灯的状态 xil_printf("LED User IP Test!\n\r"); while(1){ //根据freq_flag的标志位,切换呼吸灯的频率 if(freq_flag == 0){ BREATH_LED_IP_mWriteReg(LED_IP_BASEADDR,LED_IP_REG1,0x800000ef); freq_flag = 1; } else{ BREATH_LED_IP_mWriteReg(LED_IP_BASEADDR,LED_IP_REG1,0x8000002f); freq_flag = 0; } //获取LED当前开关状态 1:打开 0:关闭 led_state = BREATH_LED_IP_mReadReg(LED_IP_BASEADDR,LED_IP_REG0); //如果开关关闭,打开呼吸灯 if(led_state == 0){ BREATH_LED_IP_mWriteReg (LED_IP_BASEADDR, LED_IP_REG0, 1); xil_printf("Breath LED ON\n\r"); } sleep(5); //获取LED当前开关状态 1:打开 0:关闭 led_state = BREATH_LED_IP_mReadReg(LED_IP_BASEADDR,LED_IP_REG0); //如果开关打开,关闭呼吸灯 if(led_state == 1){ BREATH_LED_IP_mWriteReg (LED_IP_BASEADDR, LED_IP_REG0, 0); xil_printf("Breath LED OFF\n\r"); } sleep(1); }} 在代码的第 8 行至第 10 行,我们对 Breath LED IP 基地址、寄存器地址 0 和寄存器地址 1 进行了宏定义。按住 Ctrl 键不放,将鼠标移动到这些参数上,单击鼠标左键,会自动跳转到定义这些参数的地方。其中 BREATH LED IP 寄存器地址 0 和寄存器地址 1 位于**breath_led_ip.h** 文件内,这个文件是系统自动为我们生成的。 程序中的 main 函数实现了每 6 秒钟(点亮 5 秒+关闭 1 秒)打开和关闭 LED 呼吸灯的开关,并切换 LED 灯呼吸频率的功能。我们通过 **BREATH_LED_IP_mReadReg()** 函数来**读取寄存器地址的数据** ,通过 **BREATH_LED_IP_mWriteReg()** 函数来**写入寄存器地址的数据** ,这两个函数同样位于 breath_led_ip.h 文件中。 在硬件设计的自定义 IP 核部分中,我们例化 breath_led 代码的时候,将寄存器 0 的数据(slv_reg0)连接至呼吸灯的开关控制信号(sw_ctrl),寄存器 1 的数据高位(slv_reg1[31])连接至呼吸灯频率设置使能信号(set_en),寄存器 1 的数据低位(slv_reg1[9:0])连接至呼吸灯频率间隔设置(set_freq_step)。因此,在 Vitis 应用程序中,可以很方便的**通过 Breath LED IP 寄存器地址 0 和寄存器地址 1 来控制 LED 呼吸灯的开关和频率** 。 值得一提的是,在 Vitis 中添加导出的硬件平台文件后,自**定义 IP 核的库函数也会导入进来** ,而这个 库函数是在自定义 IP 核时,由 Vivado 软件自动生成的:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/b90ad057bdb4f0e9b727ccacfb8609e6.png"></p><p>接着“build project”,如果编译出现error,可以参考:</p><p><a href="https://blog.csdn.net/qq_62179548/article/details/132042828" title="Vitis2021.1报错:fatal error: xparameters.h: No such file or directory-CSDN博客">Vitis2021.1报错:fatal error: xparameters.h: No such file or directory-<br>CSDN博客</a></p><p>若run时出现错误:</p><p>Error while launching program: Hardaware specification file used in the launch<br>configuration ‘Debugger_user_led_ip-Default’ doesn’t exist at the location<br>…..</p><h3 id="4-下载验证"><a href="#4-下载验证" class="headerlink" title="4.下载验证"></a>4.下载验证</h3><pre><code> 打开 Vitis Terminal 终端,设置并连接串口。在应用工程 user_led 上右击,选择**“Run As”** ,然后选择第一项**“1 Launch on Hardware (System Debugger)”** 。</code></pre><h2 id="二-程序固化实验"><a href="#二-程序固化实验" class="headerlink" title="二.程序固化实验"></a>二.程序固化实验</h2><pre><code> 之前都是通过 JTAG 接口将 FPGA 配置文件和应用程序下载到 MPSOC 器件中。接下来尝试把程序存储在非易失性存储器中,在上电或者复位时让程序自动运行,这个过程需要启动引导程序**(Boot Loader)** 的参与。**Boot Loader 会加载 FPGA 配置文件,以及运行在 ARM 中的软件应用。**</code></pre><p>** <strong>本章的实验任务是在“AXI GPIO 按键控制 LED 实验”的基础上</strong>创建 FSBL** ,实现程序上电自启动,<strong>包括从 SD<br>卡启动,QSPI Flash 和 eMMC 启动三种方式</strong> 。</p><h3 id="1-简介-1"><a href="#1-简介-1" class="headerlink" title="1.*简介"></a>1.*简介</h3><pre><code> MPSOC 的系统启动过程由**平台管理单元**(**PMU**)和**配置安全单元**(**CSU**)管理和执行。启动过程包括三个功能阶段:**预配置阶段、配置阶段和后配置阶段** 。 _ **预配置阶段** 由**平台管理单元** 控制。平台管理单元运行 **PMU ROM** 代码以设置系统。PMU 处理所有复位和唤醒过程。_ _**在配置阶段** ,**BootROM(CSU ROM 代码的一部分)** 解释引导头以配置系统,并在安全或非安全引导模式下将处理系统(PS)的**第一阶段引导加载程序(FSBL)代码** 加载到**片上 RAM(OCM)** 中。引导头定义了许多引导参数,包括安全模式和**执行 FSBL 的处理器 MPCore** 。在引导期间,CSU 还将 **PMU 用户固件(PMU FW)** 加载到**PMU RAM** 中,以与 PMU ROM 一起提供**平台管理服务** 。对于**基于 Xilinx 的 FSBL 和系统软件,PMU FW 必须存在于大多数系统中** 。_ _ FSBL 执行开始后,CSU ROM 代码进入**后配置阶段** ,该阶段负责系统干预响应。CSU 硬件提供持续的硬件支持,以验证文件,**通过 PCAP 配置 PL,存储和管理安全密钥,解密文件** 。_</code></pre><h4 id="启动流程-Boot-Flow"><a href="#启动流程-Boot-Flow" class="headerlink" title="启动流程(Boot Flow)"></a><strong>启动流程(Boot Flow)</strong></h4><p>** **PMU对内部寄存器、存储器等进行复位,检查电压,则验证 CSU ROM 完整性并释放对 CSU 的复位。PMU<br>负责处理主要的预引导任务和 PS 的管理,以确保系统资源的可靠通电断电。启动 PMU<br>的上电复位(POR)操作,直接或间接的释放了预期上电模块的复位。在这种情况下,PMU 需要 ROM 代码来保持初始化上电顺序。即使在启动过程之后,PMU<br>仍在运行,并且负责处理各种系统复位。在更改系统电源状态时也会使用它(例如上电、睡眠和唤醒)。在初始化启动期间,POR 将 PMU 从复位中释放,然后执行<br>PMU ROM。</p><p><br> 下面描述了 PMU 处理器在 POR 复位后,通过运行 PMU ROM 预启动代码完成的操作序列:<br><br> 1、 初始化 PS SYSMON 和引导单元所需的 PLL。</p><pre><code>2、 清除 PMU RAM 和 CSU RAM(仅外部 POR)。3、 验证 PLL 锁。4、 通过 PS SYSMON 单元验证 LPD、AUX 和 IO 电源范围。5、 清除低功耗和全功耗域。6、 如果前面的步骤没有错,PMU 将释放 CSU 复位并进入 PMU 服务模式。如果有错,将产生一个启动错误标志。当 CSU 复位被释放,CSU 将按照下面序列运行:1、 初始化 OCM2、 通过读取引导模式寄存器来确定启动模式。3、 CSU 继续在 OCM 中加载 FSBL,以供 RPU 或 APU 执行。然后,CSU 将 PMU 用户固件加载到 PMU RAM 中,以供 PMU 固件执行。</code></pre><h4 id="启动模式-Boot-Modes"><a href="#启动模式-Boot-Modes" class="headerlink" title="启动模式(Boot Modes)"></a><strong>启动模式(Boot Modes)</strong></h4><pre><code> BootROM 可以通过 Quad-SPI,SD,eMMC,USB2.0 控制器 0 或 NAND 等外部设备启动系统。 MPSOC 使用多个模式引脚来决定配置器件的类型,软件的存储位置以及其他的系统设置,这些引脚共享 PS 端的 MIO 引脚。总共有 7 个模式引脚,分别为 MIO[8:2]。其中,前四个引脚定义启动模式,第五个引脚定义是否使用 PLL,第六个和第七个引脚定义上电过程中 MIO bank0 和</code></pre><p>bank1 的 bank 电压。如下图所示:</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/7fd4d98a93ce3511d9f836a14f2f9eb9.png"></p><h4 id="整个系统的启动过程"><a href="#整个系统的启动过程" class="headerlink" title="整个系统的启动过程"></a><strong>整个系统的启动过程</strong></h4><p><img src="https://i-blog.csdnimg.cn/blog_migrate/6da7cbc34256053b4b7e3b7c4ee48dc5.png"></p><p>更详细的内容可参考:<a href="https://blog.csdn.net/qq_32971095/article/details/133468006?csdn_share_tail=%7B%22type%22:%22blog%22,%22rType%22:%22article%22,%22rId%22:%22133468006%22,%22source%22:%22qq_32971095%22%7D" title="嵌入式Linux_Petalinux一——三.1软件栈">嵌入式Linux_Petalinux一——三.1软件栈</a></p><h3 id="2-硬件设计-1"><a href="#2-硬件设计-1" class="headerlink" title="2.硬件设计"></a>2.硬件设计</h3><pre><code> 本次实验在“AXI GPIO 按键控制 LED 实验”的基础上进行,另存为本次实验工程,工程名为 axi_gpio_fsbl。 接下来对系统的硬件设计进行修改。在 Vivado 界面左侧选择 Open Block Design,然后在右侧的 Diagram 界面中双击 Zynq UltraScale+ MPSOC 模块修改其配置。 首先**使能 QSPI 外设** 。在左侧的导航栏中选择 I/O Configuration,在打开的右侧页面中,依次展开 Low Speed > Memory Interfaces,然后勾选 QSPI 并在后面的下拉菜单中选择 Single,QSPI Data Mode 选择 x4, QSPI IO 默认为 MIO0..5,勾选 Feedback Clk 并选择 MIO6,如下图所示:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/29757f782abd8955ade80399b026870b.png"></p><pre><code> 然后**打开 SD 卡外设** 。在上一步的页面中,展开 SD 外设,勾选 SD1,在后面的菜单栏中选择 MIO46..51, Slot Type 选择 SD2.0,Data Transfer Mode 选择 4Bit,勾选**CD 用于检测 SD 卡插入** 并选择 MIO45,如下图所示:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/446f0a292906d77dee9052eabc0e669b.png"></p><pre><code> 最后**打开 eMMC 外设** 。在同样的页面中,勾选 SD0 并选择 MIO13..22,Slot Type 设置成 eMMC,Data Transfer Mode 选择 8bit,勾选 Reset 并选择 MIO23,如下图所示:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/c686ddf6f2ebcb2be138150d60ba3ff9.png"></p><pre><code> 上面两幅图中具体每个外设所连接的 MIO 引脚可以通过查看开发板原理图得知,设置完成后点击“OK”。然后在 Diagram 窗口空白处右击,然后选择“Validate Design”验证设计。验证完成后弹出对话框提示 “Validation Successful”表明设计无误,点击“OK”确认。最后按快捷键“Ctrl + S”保存设计。 接下来在 Source 窗口中右键点击 Block Design 设计文件“design_1.bd”,执行“Generate Output Products”。 最后在左侧 Flow Navigator 导航栏中找到 PROGRAM AND DEBUG,点击该选项中的“Generate Bitstream”, 对设计进行综合、实现、并生成 Bitstream 文件。 在菜单栏中选择 File > Export > Export hardware 导出硬件,并在弹出的对话框中,勾选“Include bitstream”。 新建 vitis 文件夹,将生成的 xsa 文件放入其中。 然后在菜单栏选择 Tools > Launch Vitis,启动 Vitis 开发环境。在弹出的对话框中,将路径指定到新建 的 vitis 文件夹下,点击 Launch 启动 Vitis。</code></pre><h3 id="3-软件设计-1"><a href="#3-软件设计-1" class="headerlink" title="3.软件设计"></a>3.软件设计</h3><pre><code> 新建vitis工程如上,main.c代码:</code></pre><p><br> #include “stdio.h”<br> #include “xparameters.h”<br> #include “xgpiops.h”<br> #include “xgpio.h”<br> #include “xscugic.h”<br> #include “xil_exception.h”<br> #include “xil_printf.h”<br> #include “sleep.h”<br><br> //宏定义<br> #define SCUGIC_ID XPAR_SCUGIC_0_DEVICE_ID //中断控制器 ID<br> #define GPIOPS_ID XPAR_XGPIOPS_0_DEVICE_ID //PS端 GPIO器件 ID<br> #define AXI_GPIO_ID XPAR_AXI_GPIO_0_DEVICE_ID //PL端 AXI GPIO器件 ID<br> #define GPIO_INT_ID XPAR_FABRIC_GPIO_0_VEC_ID //PL端 AXI GPIO中断 ID</p><pre><code>#define MIO_LED 38 //PS_LED1 连接到 MIO38#define KEY_CHANNEL 1 //PL按键使用 AXI GPIO通道1#define KEY_MASK XGPIO_IR_CH1_MASK //通道1的位定义//函数声明void instance_init(); //初始化器件驱动void axi_gpio_handler(void *CallbackRef); //中断服务函数//全局变量XScuGic scugic_inst; //中断控制器 驱动实例XScuGic_Config * scugic_cfg_ptr; //中断控制器 配置信息XGpioPs gpiops_inst; //PS端 GPIO 驱动实例XGpioPs_Config * gpiops_cfg_ptr; //PS端 GPIO 配置信息XGpio axi_gpio_inst; //PL端 AXI GPIO 驱动实例int led_value = 1; //LED显示状态int main(){printf("AXI GPIO INTERRUPT TEST!\n");//初始化各器件驱动instance_init();//配置PS GPIOXGpioPs_SetDirectionPin(&gpiops_inst, MIO_LED, 1); //设置 PS GPIO 为输出XGpioPs_SetOutputEnablePin(&gpiops_inst, MIO_LED ,1); //使能 PS GPIO 输出XGpioPs_WritePin(&gpiops_inst, MIO_LED, led_value); //点亮LED//配置PL AXI GPIOXGpio_SetDataDirection(&axi_gpio_inst, KEY_CHANNEL, 1); //设置PL AXI GPIO 通道1为输入 XGpio_InterruptEnable(&axi_gpio_inst, KEY_MASK); //使能通道1中断 XGpio_InterruptGlobalEnable(&axi_gpio_inst); //使能AXI GPIO全局中断 //设置中断优先级和触发类型(高电平触发) XScuGic_SetPriorityTriggerType(&scugic_inst, GPIO_INT_ID, 0xA0, 0x1); //关联中断ID和中断处理函数 XScuGic_Connect(&scugic_inst, GPIO_INT_ID, axi_gpio_handler, &axi_gpio_inst); //使能AXI GPIO中断 XScuGic_Enable(&scugic_inst, GPIO_INT_ID); //设置并打开中断异常处理功能 Xil_ExceptionInit(); Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, &scugic_inst); Xil_ExceptionEnable(); while(1); return 0;}//初始化各器件驱动void instance_init(){//初始化中断控制器驱动scugic_cfg_ptr = XScuGic_LookupConfig(SCUGIC_ID);XScuGic_CfgInitialize(&scugic_inst, scugic_cfg_ptr, scugic_cfg_ptr->CpuBaseAddress);//初始化PS端 GPIO驱动gpiops_cfg_ptr = XGpioPs_LookupConfig(GPIOPS_ID);XGpioPs_CfgInitialize(&gpiops_inst, gpiops_cfg_ptr, gpiops_cfg_ptr->BaseAddr);//初始化PL端 AXI GPIO驱动XGpio_Initialize(&axi_gpio_inst, AXI_GPIO_ID);}//PL端 AXI GPIO 中断服务(处理)函数void axi_gpio_handler(void *CallbackRef){int key_value = 1;XGpio *GpioPtr = (XGpio *)CallbackRef;print("Interrupt Detected!\n");XGpio_InterruptDisable(GpioPtr, KEY_MASK); //关闭 AXI GPIO 中断使能 key_value = XGpio_DiscreteRead(GpioPtr, KEY_CHANNEL); //读取按键数据 if(key_value == 0){ //判断按键按下 led_value = ~led_value; XGpioPs_WritePin(&gpiops_inst, MIO_LED, led_value); //改变LED显示状态 } sleep(1); //延时1s 按键消抖 XGpio_InterruptClear(GpioPtr, KEY_MASK); //清除中断 XGpio_InterruptEnable(GpioPtr, KEY_MASK); //使能AXI GPIO中断} **保存并编译工程** 后,**创建启动镜像** 。选中应用工程,右键选择**Create Boot Image。** 接下来,在弹出的界面中添加生成 boot.bin 所需的文件,然后点击“Create Image”,如图</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/372e816b5fc79bf2ae14f19e207cdfbb.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/a22a2517141020dac5bd2d4d4f4cce68.png"></p><pre><code> 从上图中可以看到,软件已经给我们自动添加所需的文件。首先是 **Bootloader 启动文件** ,也就是序号 4 处的**fsbl.elf** 。其次是 **FPGA 的配置文件** design_1_wrapper.**bit** ,在上图中序号 5 处。最后是**应用程序** axi_gpio_fsbl.elf 文件,上图中序号 6 处。注意这三个文件的顺序不能错。 序号 2 处的 bif 文件是生成**BOOT 的配置文件** ,序号 3 处的 **BOOT.bin** 就是我们需要的**启动文件** ,可以烧录到 QSPI Flash 或 eMMC 中,也可以放到 SD 中来启动 ZYNQ MOPSOC。 创建完成后,在指定的路径下可以看到生成的两个文件,如下图所示:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/a4d08531d1eab8186a97364d2ed699b7.png"></p><h3 id="4-下载验证-1"><a href="#4-下载验证-1" class="headerlink" title="4.下载验证"></a>4.下载验证</h3><h4 id="从SD卡中启动程序"><a href="#从SD卡中启动程序" class="headerlink" title="<1>从SD卡中启动程序"></a><1>从SD卡中启动程序</h4><pre><code> 将 Micro SD 卡插入读卡器,然后在电脑上将其格式化为 FAT32 格式,如下图所示:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/93b44a4a8a61b36fb0f834c0b31a9c62.png"></p><pre><code> 将生成的 BOOT.bin 文件拷贝到 SD 卡根目录下,开发板启动模式改为从SD卡启动即可。</code></pre><h4 id="固化至QSPI-Flash中"><a href="#固化至QSPI-Flash中" class="headerlink" title="<2>固化至QSPI Flash中"></a><2>固化至QSPI Flash中</h4><pre><code> 将程序固化到 QSPI Flash 需要使用 JTAG 下载器。首先我们将下载器与开发板上的 JTAG 接口连接,下载器另外一端与电脑连接。接下来将开发板上的启动模式开关设置为 JTAG 模式。 在 Vitis 软件的菜单栏中点击“Program Flash”,如下:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/ef30f083ed0db0516b72f0c5fa19d0a1.png"></p><pre><code> 在弹出的对话框中指定前面所生成的镜像文件 BOOT.bin 以及 FSBL.elf 文件,如下图中 1 和 2 处所示。 Flash Type 选择 qspi-x4-single,并勾选 Verify after flash。点击“Program”,开始对 Flash 进行编程:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/84bec15e9c53965b8eef13f5187856f4.png"></p><pre><code> 断开开发板电源,然后将开发板上的启动模式开关设置为 32bit QSPI Flash 启动即可。</code></pre><h4 id="固化到-eMMC-中"><a href="#固化到-eMMC-中" class="headerlink" title="<3>固化到 eMMC 中"></a><3>固化到 eMMC 中</h4><pre><code> 步骤和<2>相同,在Program Flash中的 **Flash Type 选择 emmc** , 并勾选 Verify after flash,然后点击 Program,如下:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/1cd484d42fb06f898814fb196a4dab72.png"></p><pre><code> 断开开发板电源,然后将开发板上的启动模式开关设置为 emmc 启动即可。</code></pre><h2 id="三-UART-串口中断实验"><a href="#三-UART-串口中断实验" class="headerlink" title="三.UART 串口中断实验"></a>三.UART 串口中断实验</h2><pre><code> 我们在使用 PS 的时候,通常会添加 UART 控制器,用于打印信息和调试代码。除此之外,PS 在和外部设备通信时,也会经常使用串口进行通信。进一步向大家 UART 控制器以及 UART 控制器利用中断进行通信的方法。</code></pre><h3 id="1-简介-2"><a href="#1-简介-2" class="headerlink" title="1.简介"></a>1.简介</h3><h4 id="MPSOC内UART控制器"><a href="#MPSOC内UART控制器" class="headerlink" title="<1>MPSOC内UART控制器"></a><1>MPSOC内UART控制器</h4><pre><code> MPSOC内UART控制器支持可编程的波特率发生器、64 字节的接收 FIFO 和发送 FIFO、产生中断、RXD 和 TXD 信号的环回模式设置以及可配置的数据位长度、停止位和校验方式等。 UART 控制器的配置以及状态的获取由**控制(Control)和状态寄存器(Status Registers)** 完成。另外, UART 控制器不仅可以连接至 MIO,也可以**映射到 EMIO** ,从而使用 **PL 的端口来实现串口通信的功能** 。 当 UART 控制器连接到 MIO 时,只有 Tx(发送)和 Rx(接收)两个引脚;而当连接 EMIO 时,除 Tx 和 Rx 引脚外,可选的还有 CTS、RTS、DSR、DCD、RI、DTR 等引脚,这些引脚用于串口的流控制。 UART 控制器采用独立的接收和发送数据路径,每个路径包含一个 **64 字节的 FIFO** ,控制器对发送和接 收 FIFO 中的数据进行**串并转** 换操作。 **FIFO 的中断标志** 支持**轮询处理** 或**中断驱动处理** 两种方式。另外,控制器中还有一个模式开关,支持 RXD 和 TXD 信号的各种环回配置。UART 控制器内部框图如下图所示:</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/be9467098457f02d978fdaf7b35594d6.png"></p><pre><code> UART 控制器的寄存器通过 **APB 从机接口和 PS AXI 总线** 互联,控制器的寄存器用于对 UART 控制器 进行配置和获取状态。波特率发生器(**Baud Rate Generator** )为 UART 控制器的接收端和发送端提供位周期 时钟;中断控制器(**GIC** )为串口的收发提供了中断服务的功能。 APB 总线接口通过**向 TxFIFO 寄存器写值** ,将数据加载到 TxFIFO 存储器中。当数据加载至 TxFIFO 后, TxFIFO 的空标志变成无效的状态,直到最后一个数据从 TxFIFO 中移出,加载至传**输移位寄存器** ,TxFIFO 恢复空的标志位。同时 TxFIFO 使用 TFULL(满中断状态)用于表示当前 TxFIFO 已经写满,并且会阻止 数据继续写入。如果此时继续执行写操作,那么会触发溢出,数据不会加载到 TxFIFO 中。 RxFIFO 存储器接收来自接收移位寄存器的数据,当接收完数据后,RxFIFO 空标志信号同样变成无效 的状态,直到所有的数据通过 APB 总线发送出去。RxFIFO 的满标志状态用于表示 RxFIFO 已经写满,并且 会阻止更多的数据写入。 模式切换(**Mode Switch** )控制 RxD 和 TxD 的信号连接方式,总共分为四种模式,分别为: **正常模式(Normal Mode)、自动回音模式(Automatic Echo Mode)、本地环回模式(Local Loopback Mode)和远程环回模式(Remote Loopback Mode)** 。</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/a18a6641a26bc471d59113f30b2dd803.png"></p><pre><code> 如果我们只是 用串口来**打印信息** 的话,那么可以直接使用**print()或者 xil_printf()** 函数就可以了,无需在程序中对串口做配置。但是如果我们需要使用 UART 来完成某些特定功能的话,如**串口接收中断** ,那么就要了解 UART 控制器**初始化、UART 中断初始化以及 UART 常用的 API 函数** 等相关内容了。</code></pre><h4 id="UART启动和配置"><a href="#UART启动和配置" class="headerlink" title="<2>UART启动和配置"></a><2>UART启动和配置</h4><p><img src="https://i-blog.csdnimg.cn/blog_migrate/6ddbf21ee27e9c33362e57354d5eca70.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/4a310074e7bd0be3b5e5e715bd69bcec.png"></p><h4 id="收发数据"><a href="#收发数据" class="headerlink" title="<3>收发数据"></a><3>收发数据</h4><p><img src="https://i-blog.csdnimg.cn/blog_migrate/12b95a7bcc6acd13e957f41db6c99ca3.png"></p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/611810d31ceb34a9530dbcfd49af8288.png"></p><h3 id="2-硬件设计-2"><a href="#2-硬件设计-2" class="headerlink" title="2.硬件设计"></a>2.硬件设计</h3><p>DDR4 中存放和运行程序、UART 实现串口通信。</p><p><img src="https://i-blog.csdnimg.cn/blog_migrate/f9d5d8180c6ece37e8e66b243cb97514.png"></p><pre><code> 本次实验嵌入式系统的搭建和Hello World 实验完全相同,工程名为 uart_intr_loop。 _MPSOC 开发板上的 USB UART 连接的引 脚是 MIO42 和 MIO43,因此在配置界面选择的是 UART0 MIO42..MIO43_ 。图中的 Modem signals 表示是否添加**串口的流控制功能,即调制解调器** ,如果选中的话,会额外增加一些引脚,一般不勾选。需要注意的 是,串口的流控制功能只能用于**EMIO 接口** ,MIO 接口不支持此功能。</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/769bdbcd35d49412cc93d1e56acb5bd4.png"></p><pre><code> 接下来,直接导出硬件,然后新建 vitis 文件夹,将导出的 xsa 文件拷贝到里面,最后打开 Vitis 软件, 并将路径指向新建的 vitis 文件夹下。</code></pre><h3 id="3-软件设计-2"><a href="#3-软件设计-2" class="headerlink" title="3.软件设计"></a>3.软件设计</h3><pre><code> Vitis 中创建了一个名为**uart_intr_loop 的应用工程** 。展开 design_1_wrapper,找到 **platform.spr** 并双击,右面的界面中出现 **design_1_wrapper 的标签页** ,然后找到**板级支持包** 并点击,可以看到**UART 文档和导入示例:**</code></pre><p><img src="https://i-blog.csdnimg.cn/blog_migrate/4761e85c7ba0a68757090675cb7507de.png"></p><pre><code> 如果我们点击**Import Examples** ,会弹出下图所示的导入示例界面,关于**UART 有 5 个示例,** 其中 xuartps_intr_example 是串口中断的示例,可供参考。 新建main.c文件,代码如下:</code></pre><p><br> #include “xparameters.h”<br> #include “xuartps.h”<br> #include “xil_printf.h”<br> #include “xscugic.h”<br> #include “stdio.h”<br><br> #define UART_DEVICE_ID XPAR_XUARTPS_0_DEVICE_ID //串口设备ID<br> #define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID //中断ID<br> #define UART_INT_IRQ_ID XPAR_XUARTPS_0_INTR //串口中断ID</p><pre><code>XScuGic Intc; //中断控制器驱动程序实例XUartPs Uart_Ps; //串口驱动程序实例//UART初始化函数int uart_init(XUartPs* uart_ps){ int status; XUartPs_Config *uart_cfg; uart_cfg = XUartPs_LookupConfig(UART_DEVICE_ID); if (NULL == uart_cfg) return XST_FAILURE; status = XUartPs_CfgInitialize(uart_ps, uart_cfg, uart_cfg->BaseAddress); if (status != XST_SUCCESS) return XST_FAILURE; //UART设备自检 status = XUartPs_SelfTest(uart_ps); if (status != XST_SUCCESS) return XST_FAILURE; //设置工作模式:正常模式 XUartPs_SetOperMode(uart_ps, XUARTPS_OPER_MODE_NORMAL); //设置波特率:115200 XUartPs_SetBaudRate(uart_ps,115200); //设置RxFIFO的中断触发等级 XUartPs_SetFifoThreshold(uart_ps, 1); return XST_SUCCESS;}//UART中断处理函数void uart_intr_handler(void *call_back_ref){ XUartPs *uart_instance_ptr = (XUartPs *) call_back_ref; u32 rec_data = 0 ; u32 isr_status ; //中断状态标志 //读取中断ID寄存器,判断触发的是哪种中断 isr_status = XUartPs_ReadReg(uart_instance_ptr->Config.BaseAddress, XUARTPS_IMR_OFFSET); isr_status &= XUartPs_ReadReg(uart_instance_ptr->Config.BaseAddress, XUARTPS_ISR_OFFSET); //判断中断标志位RxFIFO是否触发 if (isr_status & (u32)XUARTPS_IXR_RXOVR){ rec_data = XUartPs_RecvByte(XPAR_PSU_UART_0_BASEADDR); //清除中断标志 XUartPs_WriteReg(uart_instance_ptr->Config.BaseAddress, XUARTPS_ISR_OFFSET, XUARTPS_IXR_RXOVR) ; } XUartPs_SendByte(XPAR_PSU_UART_0_BASEADDR,rec_data);}//串口中断初始化int uart_intr_init(XScuGic *intc, XUartPs *uart_ps){ int status; //初始化中断控制器 XScuGic_Config *intc_cfg; intc_cfg = XScuGic_LookupConfig(INTC_DEVICE_ID); if (NULL == intc_cfg) return XST_FAILURE; status = XScuGic_CfgInitialize(intc, intc_cfg, intc_cfg->CpuBaseAddress); if (status != XST_SUCCESS) return XST_FAILURE; //设置并打开中断异常处理功能 Xil_ExceptionInit(); Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, (void *)intc); Xil_ExceptionEnable(); //为中断设置中断处理函数 XScuGic_Connect(intc, UART_INT_IRQ_ID, (Xil_ExceptionHandler) uart_intr_handler,(void *) uart_ps); //设置UART的中断触发方式 XUartPs_SetInterruptMask(uart_ps, XUARTPS_IXR_RXOVR); //使能GIC中的串口中断 XScuGic_Enable(intc, UART_INT_IRQ_ID); return XST_SUCCESS;}//main函数int main(void){ int status; status = uart_init(&Uart_Ps); //串口初始化 if (status == XST_FAILURE) { xil_printf("Uart Initial Failed\r\n"); return XST_FAILURE; } uart_intr_init(&Intc, &Uart_Ps); //串口中断初始化 while (1); return status;}</code></pre><h5 id="分析:"><a href="#分析:" class="headerlink" title="*分析:"></a>*分析:</h5><pre><code> XScuGic 和 XUartPs 为程序中定义的两个结构体。如果在 Vitis 软件中, 按住 Ctrl 键不放,将鼠标移动到 XScuGic 或者 XUartPs 上,当鼠标变成手指状时,单击鼠标左键,会自动 跳转到定义这两个结构体的地方。其中 **XScuGic 包含了中断控制器相关的参数和数据** ,而 **XUartPs 则包含 了串口相关的参数和数据** 。 在代码的第 15 行至第 40 行完成了对 UART 的初始化。其中代码的第 28 行 **XUartPs_SelfTest** 函数实现 了 UART 设备自检的功能,即使用 UART**本地环回** 的模式,并验证数据是否可以正确发送和接收。 **XUartPs_SetOperMode** 函数设置**串口的工作模式** ,这里输入的参数 XUARTPS_OPER_MODE_NORMAL 为 正常的工作模式。**XUartPs_SetBaudRate** 函数用于设置串口的通信**波特率** ,这里设置的波特率为 115200,如 果需要修改成其它波特率,可直接在此修改输入的参数即可。**XUartPs_SetFifoThreshold** 函数用于设置 RxFIFO 的中断触发等级,即**触发** **RxFIFO 中断的数据个数** ,**这里设置的值为 1(字节)** ,即每收到一个值就触发中断。注意,中断触发等级最大值不超过 63。 在代码的第 65 行至第 94 行完成了串口中断的初始化。程序首先对**中断控制器进行初始化** ,随后设置 并打开**中断异常处理** 的功能。接下来为串口中断设置**中断处理函数** ,通过 **XScuGic_Connect** 函数进行设置,这里设置的串口中断处理函数为 **uart_intr_handler** 。**XUartPs_SetInterruptMask** 函数用于设置 UART 的**中断触发方式** ,函数输入的参数为 **XUARTPS_IXR_RXOVR** ,**表示达到 RxFIFO 的触发等级** 时,开始触发中断,当然也可以设置成 RxFIFO 为满时触发中断或者为空时触发中断等。最后,通过 **XScuGic_Enable** 函数来**使能 GIC** 中的串口中断。 在代码的第 42 行至第 63 行为 **UART 中断处理函数** ,由于 RxFIFO 的触发等级设置为 1,因此每次接收到数据都会进入此中断函数。程序中首先**读取中断 ID 寄存器** ,判断触发的是**哪种中断** ,再读取**中断的状态** 。 当判断中断标志位为 **RxFIFO 触发中断** 时,通过 **XUartPs_RecvByte** 函数来**读取接收到的数据** ,并**清除对应的中断标志位** 。最后通过 **XUartPs_SendByte** 函数**发送接收到的数据** ,实现串口环回的功能。</code></pre><p>注:首先程序会对 UART 串口进行初始化,我们知道,当使用一些打印函数的时候(如:xil_printf()),实际上调用的还是 UART 相关的 API<br>函数,如果在<strong>初始化的过程中, 使用打印函数,或者在打印的过程中对串口进行初始化,都会导致串口助手打印信息出错。</strong></p><h2 id="四-定时器中断实验"><a href="#四-定时器中断实验" class="headerlink" title="四.定时器中断实验"></a>四.定时器中断实验</h2><pre><code> MPSOC 中 PS 部分包含许多不同类型的定时器,包括**全局定时器、TTC 定时器、系统看门狗定时器** 等。 定时器可以不受 CPU 的干预,自己独立运行,来完成计时、定时、中断以及计算来自 MIO 或 EMIO 引脚 的信号脉冲宽度等。本章我们将向大家介绍 **TTC**(**三路定时器**)以 TTC(三路定时器)**中断** 的使用方法。</code></pre><h3 id="1-简介-3"><a href="#1-简介-3" class="headerlink" title="1.简介"></a>1.简介</h3><p>本文转自 <a href="https://blog.csdn.net/qq_32971095/article/details/136352300">https://blog.csdn.net/qq_32971095/article/details/136352300</a>,如有侵权,请联系删除。</p>]]></content:encoded>
<category domain="https://xidianswq.github.io/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">学习笔记</category>
<category domain="https://xidianswq.github.io/tags/fpga%E5%BC%80%E5%8F%91/">fpga开发</category>
<category domain="https://xidianswq.github.io/tags/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%A1%AC%E4%BB%B6/">嵌入式硬件</category>
<category domain="https://xidianswq.github.io/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">学习笔记</category>
<comments>https://xidianswq.github.io/2024/03/01/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/FPGA%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0(42)%E2%80%94%E2%80%94Vitis%E5%BC%80%E5%8F%91%E4%BA%8C/#disqus_thread</comments>
</item>
</channel>
</rss>