Compare commits

..
145 Commits
Author SHA1 Message Date
josh 9785f013c7 new post 2025-07-02 10:12:16 +08:00
josh e722750086 Merge branch 'master' of https://github.com/joshgao22/josh-blog-source 2025-06-26 14:38:29 +08:00
josh 3e39baaee4 update dependencies, config and post 2025-06-26 14:38:07 +08:00
Josh Gao 4009348802 Merge pull request #44 from joshgao22/dependabot/npm_and_yarn/hexo-word-counter-0.2.1
Bump hexo-word-counter from 0.2.0 to 0.2.1
2025-06-17 19:13:59 +08:00
dependabot[bot] 929cb50354 Bump hexo-word-counter from 0.2.0 to 0.2.1
Bumps [hexo-word-counter](https://github.com/next-theme/hexo-word-counter) from 0.2.0 to 0.2.1.
- [Release notes](https://github.com/next-theme/hexo-word-counter/releases)
- [Commits](https://github.com/next-theme/hexo-word-counter/compare/v0.2.0...v0.2.1)

---
updated-dependencies:
- dependency-name: hexo-word-counter
  dependency-version: 0.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-06-05 03:41:13 +00:00
Josh Gao a190552c0c Merge pull request #43 from joshgao22/dependabot/npm_and_yarn/next-theme/plugins-8.23.1
Bump @next-theme/plugins from 8.23.0 to 8.23.1
2025-06-05 11:40:06 +08:00
Josh Gao 3a0103be03 Merge pull request #42 from joshgao22/dependabot/npm_and_yarn/hexo-theme-next-8.23.1
Bump hexo-theme-next from 8.23.0 to 8.23.1
2025-06-05 11:39:56 +08:00
dependabot[bot] a406b98bac Bump @next-theme/plugins from 8.23.0 to 8.23.1
Bumps [@next-theme/plugins](https://github.com/next-theme/plugins) from 8.23.0 to 8.23.1.
- [Release notes](https://github.com/next-theme/plugins/releases)
- [Commits](https://github.com/next-theme/plugins/compare/v8.23.0...v8.23.1)

---
updated-dependencies:
- dependency-name: "@next-theme/plugins"
  dependency-version: 8.23.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-06-04 23:27:41 +00:00
dependabot[bot] be8b9ba539 Bump hexo-theme-next from 8.23.0 to 8.23.1
Bumps [hexo-theme-next](https://github.com/next-theme/hexo-theme-next) from 8.23.0 to 8.23.1.
- [Release notes](https://github.com/next-theme/hexo-theme-next/releases)
- [Commits](https://github.com/next-theme/hexo-theme-next/compare/v8.23.0...v8.23.1)

---
updated-dependencies:
- dependency-name: hexo-theme-next
  dependency-version: 8.23.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-06-04 23:27:32 +00:00
Josh Gao 2c43000367 Merge pull request #40 from joshgao22/dependabot/npm_and_yarn/hexo-markmap-2.0.8
Bump hexo-markmap from 1.2.5 to 2.0.8
2025-04-15 08:58:28 +08:00
dependabot[bot] 6b4afd1e42 Bump hexo-markmap from 1.2.5 to 2.0.8
Bumps [hexo-markmap](https://github.com/MaxChang3/hexo-markmap) from 1.2.5 to 2.0.8.
- [Release notes](https://github.com/MaxChang3/hexo-markmap/releases)
- [Commits](https://github.com/MaxChang3/hexo-markmap/compare/v1.2.5...v2.0.8)

---
updated-dependencies:
- dependency-name: hexo-markmap
  dependency-version: 2.0.8
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-04-14 23:40:20 +00:00
josh 08b722f278 feat: add new server 2025-04-12 10:56:13 +08:00
josh 5cd88bb922 Revert "Merge pull request #37 from joshgao22/dependabot/npm_and_yarn/hexo-renderer-pandoc-0.5.0"
This reverts commit 7717b21612, reversing
changes made to 43aebe64fe.

hexo-renderer-pandoc 0.5.0 renders file header latex definition wrongly,
and should be checked later
2025-04-11 12:59:46 +08:00
Josh Gao 4c4201dd8c Merge pull request #39 from joshgao22/dependabot/npm_and_yarn/hexo-markmap-2.0.8
Bump hexo-markmap from 1.2.5 to 2.0.8
2025-04-11 10:58:54 +08:00
Josh Gao 7717b21612 Merge pull request #37 from joshgao22/dependabot/npm_and_yarn/hexo-renderer-pandoc-0.5.0
Bump hexo-renderer-pandoc from 0.4.0 to 0.5.0
2025-04-11 10:58:35 +08:00
Josh Gao 43aebe64fe Merge pull request #36 from joshgao22/dependabot/npm_and_yarn/hexo-generator-searchdb-1.5.0
Bump hexo-generator-searchdb from 1.4.1 to 1.5.0
2025-04-11 10:58:17 +08:00
Josh Gao 43b3a85289 Merge pull request #35 from joshgao22/dependabot/npm_and_yarn/hexo-theme-next-8.23.0
Bump hexo-theme-next from 8.22.0 to 8.23.0
2025-04-11 10:58:05 +08:00
dependabot[bot] 91cdcfa52f Bump hexo-theme-next from 8.22.0 to 8.23.0
Bumps [hexo-theme-next](https://github.com/next-theme/hexo-theme-next) from 8.22.0 to 8.23.0.
- [Release notes](https://github.com/next-theme/hexo-theme-next/releases)
- [Commits](https://github.com/next-theme/hexo-theme-next/compare/v8.22.0...v8.23.0)

---
updated-dependencies:
- dependency-name: hexo-theme-next
  dependency-version: 8.23.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-04-11 02:57:34 +00:00
Josh Gao 337f429ea7 Merge pull request #34 from joshgao22/dependabot/npm_and_yarn/next-theme/plugins-8.23.0
Bump @next-theme/plugins from 8.22.0 to 8.23.0
2025-04-11 10:57:04 +08:00
Josh Gao f1c3d5f6bd Merge pull request #30 from joshgao22/dependabot/npm_and_yarn/hexo-theme-landscape-1.1.0
Bump hexo-theme-landscape from 1.0.0 to 1.1.0
2025-04-11 10:56:21 +08:00
dependabot[bot] b688a474a8 Bump hexo-markmap from 1.2.5 to 2.0.8
Bumps [hexo-markmap](https://github.com/MaxChang3/hexo-markmap) from 1.2.5 to 2.0.8.
- [Release notes](https://github.com/MaxChang3/hexo-markmap/releases)
- [Commits](https://github.com/MaxChang3/hexo-markmap/compare/v1.2.5...v2.0.8)

---
updated-dependencies:
- dependency-name: hexo-markmap
  dependency-version: 2.0.8
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-04-08 00:41:18 +00:00
dependabot[bot] 91b8d6c318 Bump hexo-renderer-pandoc from 0.4.0 to 0.5.0
Bumps [hexo-renderer-pandoc](https://github.com/hexojs/hexo-renderer-pandoc) from 0.4.0 to 0.5.0.
- [Commits](https://github.com/hexojs/hexo-renderer-pandoc/commits)

---
updated-dependencies:
- dependency-name: hexo-renderer-pandoc
  dependency-version: 0.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-04-03 23:12:13 +00:00
dependabot[bot] 285389294d Bump hexo-generator-searchdb from 1.4.1 to 1.5.0
Bumps [hexo-generator-searchdb](https://github.com/next-theme/hexo-generator-searchdb) from 1.4.1 to 1.5.0.
- [Release notes](https://github.com/next-theme/hexo-generator-searchdb/releases)
- [Commits](https://github.com/next-theme/hexo-generator-searchdb/compare/v1.4.1...v1.5.0)

---
updated-dependencies:
- dependency-name: hexo-generator-searchdb
  dependency-version: 1.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-04-01 00:02:29 +00:00
dependabot[bot] fa6b3f6ae2 Bump @next-theme/plugins from 8.22.0 to 8.23.0
Bumps [@next-theme/plugins](https://github.com/next-theme/plugins) from 8.22.0 to 8.23.0.
- [Release notes](https://github.com/next-theme/plugins/releases)
- [Commits](https://github.com/next-theme/plugins/compare/v8.22.0...v8.23.0)

---
updated-dependencies:
- dependency-name: "@next-theme/plugins"
  dependency-version: 8.23.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-03-31 23:55:14 +00:00
dependabot[bot] c967373488 Bump hexo-theme-landscape from 1.0.0 to 1.1.0
Bumps [hexo-theme-landscape](https://github.com/hexojs/hexo-theme-landscape) from 1.0.0 to 1.1.0.
- [Release notes](https://github.com/hexojs/hexo-theme-landscape/releases)
- [Commits](https://github.com/hexojs/hexo-theme-landscape/compare/v1.0.0...v1.1.0)

---
updated-dependencies:
- dependency-name: hexo-theme-landscape
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-02-14 23:29:39 +00:00
josh 5e51314dfe update packages and deploy server 2025-02-06 08:56:10 +08:00
Josh Gao fb06efb960 Merge pull request #26 from joshgao22/dependabot/npm_and_yarn/hexo-theme-next-8.22.0
Bump hexo-theme-next from 8.21.0 to 8.22.0
2025-02-05 22:20:32 +08:00
Josh Gao 99538a0e9e Merge pull request #28 from joshgao22/dependabot/npm_and_yarn/hexo-related-posts-1.6.2
Bump hexo-related-posts from 1.5.2 to 1.6.2
2025-02-05 22:20:21 +08:00
dependabot[bot] c4b5eecc85 Bump hexo-related-posts from 1.5.2 to 1.6.2
Bumps [hexo-related-posts](https://github.com/sergeyzwezdin/hexo-related-posts) from 1.5.2 to 1.6.2.
- [Release notes](https://github.com/sergeyzwezdin/hexo-related-posts/releases)
- [Commits](https://github.com/sergeyzwezdin/hexo-related-posts/commits/v1.6.2)

---
updated-dependencies:
- dependency-name: hexo-related-posts
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-01-15 23:56:18 +00:00
dependabot[bot] 9d9303e03f Bump hexo-theme-next from 8.21.0 to 8.22.0
Bumps [hexo-theme-next](https://github.com/next-theme/hexo-theme-next) from 8.21.0 to 8.22.0.
- [Release notes](https://github.com/next-theme/hexo-theme-next/releases)
- [Commits](https://github.com/next-theme/hexo-theme-next/compare/v8.21.0...v8.22.0)

---
updated-dependencies:
- dependency-name: hexo-theme-next
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-01-01 23:04:34 +00:00
josh 25e0a81a87 update posts 2024-10-11 20:58:04 +08:00
Josh Gao 4bcbbf54b0 Merge pull request #23 from joshgao22/dependabot/npm_and_yarn/hexo-theme-next-8.21.0
Bump hexo-theme-next from 8.20.0 to 8.21.0
2024-10-11 20:56:29 +08:00
Josh Gao c191a5af65 Merge pull request #22 from joshgao22/dependabot/npm_and_yarn/next-theme/plugins-8.21.0
Bump @next-theme/plugins from 8.20.0 to 8.21.0
2024-10-11 20:56:21 +08:00
dependabot[bot] 88ce267098 Bump hexo-theme-next from 8.20.0 to 8.21.0
Bumps [hexo-theme-next](https://github.com/next-theme/hexo-theme-next) from 8.20.0 to 8.21.0.
- [Release notes](https://github.com/next-theme/hexo-theme-next/releases)
- [Commits](https://github.com/next-theme/hexo-theme-next/compare/v8.20.0...v8.21.0)

---
updated-dependencies:
- dependency-name: hexo-theme-next
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-09-20 23:20:38 +00:00
dependabot[bot] 15aa117543 Bump @next-theme/plugins from 8.20.0 to 8.21.0
Bumps [@next-theme/plugins](https://github.com/next-theme/plugins) from 8.20.0 to 8.21.0.
- [Release notes](https://github.com/next-theme/plugins/releases)
- [Commits](https://github.com/next-theme/plugins/compare/v8.20.0...v8.21.0)

---
updated-dependencies:
- dependency-name: "@next-theme/plugins"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-09-20 23:20:26 +00:00
Josh Gao f0adb4a625 Merge pull request #21 from joshgao22/dependabot/npm_and_yarn/hexo-generator-index-4.0.0
Bump hexo-generator-index from 3.0.0 to 4.0.0
2024-08-19 10:19:17 +08:00
dependabot[bot] ae1862be8a Bump hexo-generator-index from 3.0.0 to 4.0.0
Bumps [hexo-generator-index](https://github.com/hexojs/hexo-generator-index) from 3.0.0 to 4.0.0.
- [Release notes](https://github.com/hexojs/hexo-generator-index/releases)
- [Commits](https://github.com/hexojs/hexo-generator-index/compare/v3.0.0...v4.0.0)

---
updated-dependencies:
- dependency-name: hexo-generator-index
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-07-09 23:31:02 +00:00
josh c666cf18aa update posts 2024-07-07 17:12:20 +08:00
josh c8252851cb Merge branch 'master' of https://github.com/joshgao22/josh-blog-source 2024-07-07 17:04:27 +08:00
Josh Gao 56398591e7 Merge pull request #20 from joshgao22/dependabot/npm_and_yarn/hexo-7.3.0
Bump hexo from 7.2.0 to 7.3.0
2024-07-07 17:04:18 +08:00
josh a9ceb54cc6 new post josh-cvx-2.2, update josh-cvx-2.1, new draft zynq-debug-fsbl 2024-07-04 00:29:38 +08:00
dependabot[bot] 4dd6f0ffd3 Bump hexo from 7.2.0 to 7.3.0
Bumps [hexo](https://github.com/hexojs/hexo) from 7.2.0 to 7.3.0.
- [Release notes](https://github.com/hexojs/hexo/releases)
- [Commits](https://github.com/hexojs/hexo/compare/v7.2.0...v7.3.0)

---
updated-dependencies:
- dependency-name: hexo
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-07-01 23:52:29 +00:00
josh 5d0a940aea finish post, zynq dynamic ddr configuration 2024-06-28 10:39:55 +08:00
josh 83586f61d9 new post, zynq dynamic ddr configuration 2024-06-28 00:30:08 +08:00
josh ea44545b90 update post sv-1 2024-06-26 00:27:08 +08:00
josh 6218adecc8 update toc of post cvx-2.1 2024-06-24 10:37:04 +08:00
josh 3e4f48e36f finish post cvx-2.1 2024-06-16 13:32:18 +08:00
josh f1d95ce8b4 new post cvx-2.1, new hexo plugin to support mindmap 2024-06-15 16:36:21 +08:00
josh 565bdaaefd new post cvx-1.6, update cvx series 2024-06-13 22:39:02 +08:00
josh ade0322aa9 new post cvx-1.5 2024-06-13 10:31:45 +08:00
josh b9e587f5d5 new post cvx-1.4 2024-06-12 17:45:24 +08:00
josh a93552d9b9 finish post cvx-1.3 2024-06-12 11:31:27 +08:00
josh 3f40a887c9 update package 2024-06-11 20:12:56 +08:00
josh abbc0da71b update cvx post 2024-06-11 20:10:20 +08:00
josh 9e9b00b0dd fix some typo 2024-06-11 08:15:22 +08:00
josh 32b118f0e5 update post cvx-1.1, enlarge font size 2024-06-10 16:51:09 +08:00
josh 5ec621c28e new post cvx-1.3 2024-06-09 23:19:23 +08:00
josh af188d3046 new post cvx-1.2 2024-06-08 17:29:33 +08:00
josh da0fbe84dc finish post - convex optimization 1.1 2024-06-08 12:14:53 +08:00
josh 7c14960b5f release post on convex optimization, update opa references 2024-06-08 00:32:57 +08:00
josh 85e6bd77a3 update sv blogs
change a few translations, change how markdown images are  linked
2024-06-07 09:43:46 +08:00
josh 7b8d5d80cb update blog titles
split tiles of note & review serie into two lines, making it neat. but in archive view, the lines are still splited, which is a little annoying
2024-06-06 19:54:21 +08:00
josh c051aec7aa update post
update rcosdesign based on MATLAB R2024a, improve some translation
2024-06-06 19:28:01 +08:00
Josh Gao 99df295a36 Merge pull request #19 from joshgao22/dependabot/npm_and_yarn/hexo-theme-next-8.20.0
Bump hexo-theme-next from 8.19.2 to 8.20.0
2024-05-07 17:24:25 +08:00
Josh Gao e483a1169c Merge pull request #18 from joshgao22/dependabot/npm_and_yarn/next-theme/plugins-8.20.0
Bump @next-theme/plugins from 8.19.2 to 8.20.0
2024-05-07 17:24:11 +08:00
dependabot[bot] 6d95a37581 Bump @next-theme/plugins from 8.19.2 to 8.20.0
Bumps [@next-theme/plugins](https://github.com/next-theme/plugins) from 8.19.2 to 8.20.0.
- [Release notes](https://github.com/next-theme/plugins/releases)
- [Commits](https://github.com/next-theme/plugins/compare/v8.19.2...v8.20.0)

---
updated-dependencies:
- dependency-name: "@next-theme/plugins"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-05-07 09:23:54 +00:00
Josh Gao 5904a9487e Merge pull request #17 from joshgao22/dependabot/npm_and_yarn/hexo-7.2.0
Bump hexo from 7.1.1 to 7.2.0
2024-05-07 17:22:53 +08:00
dependabot[bot] 6cc06a9a39 Bump hexo-theme-next from 8.19.2 to 8.20.0
Bumps [hexo-theme-next](https://github.com/next-theme/hexo-theme-next) from 8.19.2 to 8.20.0.
- [Release notes](https://github.com/next-theme/hexo-theme-next/releases)
- [Commits](https://github.com/next-theme/hexo-theme-next/compare/v8.19.2...v8.20.0)

---
updated-dependencies:
- dependency-name: hexo-theme-next
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-05-01 23:43:27 +00:00
dependabot[bot] 2f00b115e2 Bump hexo from 7.1.1 to 7.2.0
Bumps [hexo](https://github.com/hexojs/hexo) from 7.1.1 to 7.2.0.
- [Release notes](https://github.com/hexojs/hexo/releases)
- [Commits](https://github.com/hexojs/hexo/compare/v7.1.1...v7.2.0)

---
updated-dependencies:
- dependency-name: hexo
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-04-17 23:52:56 +00:00
Josh Gao 9f94881fa0 Merge pull request #16 from joshgao22/dependabot/npm_and_yarn/hexo-word-counter-0.2.0
Bump hexo-word-counter from 0.1.0 to 0.2.0
2024-04-17 15:34:56 +08:00
dependabot[bot] c1e112445b Bump hexo-word-counter from 0.1.0 to 0.2.0
Bumps [hexo-word-counter](https://github.com/next-theme/hexo-word-counter) from 0.1.0 to 0.2.0.
- [Release notes](https://github.com/next-theme/hexo-word-counter/releases)
- [Commits](https://github.com/next-theme/hexo-word-counter/compare/v0.1.0...v0.2.0)

---
updated-dependencies:
- dependency-name: hexo-word-counter
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-04-16 23:18:13 +00:00
josh e52cd7d85f update readme 2024-03-05 08:58:48 +08:00
Josh Gao ec35c8cdea Merge pull request #14 from joshgao22/dependabot/npm_and_yarn/next-theme/plugins-8.19.2
Bump @next-theme/plugins from 8.19.1 to 8.19.2
2024-03-05 08:53:48 +08:00
Josh Gao b2b75aad55 Merge pull request #15 from joshgao22/dependabot/npm_and_yarn/hexo-theme-next-8.19.2
Bump hexo-theme-next from 8.19.1 to 8.19.2
2024-03-05 08:53:42 +08:00
dependabot[bot] 7314bd1056 Bump hexo-theme-next from 8.19.1 to 8.19.2
Bumps [hexo-theme-next](https://github.com/next-theme/hexo-theme-next) from 8.19.1 to 8.19.2.
- [Release notes](https://github.com/next-theme/hexo-theme-next/releases)
- [Commits](https://github.com/next-theme/hexo-theme-next/compare/v8.19.1...v8.19.2)

---
updated-dependencies:
- dependency-name: hexo-theme-next
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-03-04 23:41:30 +00:00
dependabot[bot] c980afba5f Bump @next-theme/plugins from 8.19.1 to 8.19.2
Bumps [@next-theme/plugins](https://github.com/next-theme/plugins) from 8.19.1 to 8.19.2.
- [Release notes](https://github.com/next-theme/plugins/releases)
- [Commits](https://github.com/next-theme/plugins/compare/v8.19.1...v8.19.2)

---
updated-dependencies:
- dependency-name: "@next-theme/plugins"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-03-04 23:41:15 +00:00
Josh Gao 3310fa3f0f Merge pull request #13 from joshgao22/dependabot/npm_and_yarn/hexo-related-posts-1.5.2
Bump hexo-related-posts from 1.5.1 to 1.5.2
2024-02-28 12:03:45 +08:00
dependabot[bot] 3d80770890 Bump hexo-related-posts from 1.5.1 to 1.5.2
Bumps [hexo-related-posts](https://github.com/sergeyzwezdin/hexo-related-posts) from 1.5.1 to 1.5.2.
- [Release notes](https://github.com/sergeyzwezdin/hexo-related-posts/releases)
- [Commits](https://github.com/sergeyzwezdin/hexo-related-posts/commits)

---
updated-dependencies:
- dependency-name: hexo-related-posts
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-02-24 00:02:17 +00:00
josh 3311cbd1db fix typo 2024-02-06 20:54:06 +08:00
josh f5c9f10e0d update MVDR simulation 2024-02-05 16:47:55 +08:00
josh dc2bb9435d new post, mvdr simulation 2024-02-01 17:14:17 +08:00
josh 675c6b3da8 update github url 2024-01-30 20:21:06 +08:00
josh 1cb2e781df change boldsymbol to mathbf 2024-01-30 20:10:15 +08:00
josh bcc43f83e7 new post IAA-APES, update github rep linko 2024-01-30 18:11:19 +08:00
josh 1be8af2a9c upgrade hexo 2024-01-23 09:58:49 +08:00
Josh Gao d2d4cf2ebd Merge pull request #12 from joshgao22/dependabot/npm_and_yarn/hexo-7.1.1
Bump hexo from 7.1.0 to 7.1.1
2024-01-23 09:53:07 +08:00
dependabot[bot] a440b21a7b Bump hexo from 7.1.0 to 7.1.1
Bumps [hexo](https://github.com/hexojs/hexo) from 7.1.0 to 7.1.1.
- [Release notes](https://github.com/hexojs/hexo/releases)
- [Commits](https://github.com/hexojs/hexo/compare/v7.1.0...v7.1.1)

---
updated-dependencies:
- dependency-name: hexo
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-01-22 23:35:52 +00:00
josh 306b2eeeac update dependency, move pics from tencent cloud to local repo 2024-01-21 21:08:30 +08:00
josh 47e4e57cb3 update packge dependency, upgrade hexo to 7.0.0 2024-01-14 10:30:44 +08:00
josh 5861d96192 remove annimation to boost page loading, change imgae dir structure 2023-10-20 16:26:53 +08:00
josh f3713c248b update packge dependency 2023-09-05 16:35:56 +08:00
josh 3edd328b6d remove plugin hexo-related-popular-post 2023-07-09 11:12:47 +08:00
josh 8c57cf87b9 minor update to post josh-verilog 2023-07-09 10:52:38 +08:00
josh 5a9e7370ef minor update to post josh-oap-1-5 2023-07-09 10:03:36 +08:00
josh 75fc6de429 minor update to post josh-oap-1-5 2023-07-03 09:27:39 +08:00
josh 059aedd89f finish post, josh-oap-1-5 2023-06-30 18:44:57 +08:00
josh ee8dd1ad54 update post, josh-oap-1-5 2023-06-30 18:12:48 +08:00
josh 9ba83e61c9 finish post josh-oap-2-1 2023-06-21 14:51:28 +08:00
josh 85e2b1bb85 update several posts, add matlab code to figs 2023-06-20 19:17:57 +08:00
josh 67b99a2560 new post, josh-oap-2-1 2023-06-19 19:39:16 +08:00
josh 5b1a81fb10 update hexo-theme-next; change tex \vec to \boldsymbol 2023-06-11 10:35:01 +08:00
josh 947817dac9 new post, oxford-5000-bound 2023-06-01 14:45:05 +08:00
josh ad73e85dec new post, oxford-5000-resort; update several posts 2023-05-25 23:59:25 +08:00
josh 9a4575d148 update several posts; finish strike 2023-05-24 23:53:53 +08:00
josh 0fa7790491 new post, oxford-5000-strike; revise 'pitch' 2023-05-21 22:55:33 +08:00
josh 2e4c85ade0 update hexo next theme 2023-05-19 19:34:48 +08:00
josh 324822c003 new post git-delete-large-file 2023-05-14 15:10:59 +08:00
josh f4e9d64f2f update post, josh-oap-1-5 2023-05-04 21:24:24 +08:00
josh 51f864ef87 update post, josh-oap-1-5 2023-05-04 18:15:26 +08:00
josh 6a978b74a0 update post, josh-oap-1-5 2023-04-26 19:51:15 +08:00
josh 1fa4e5a6a8 add new post, josh-oap-1-5 2023-04-24 19:44:32 +08:00
josh e5ea0ff79b review post, josh-oap-1-4 2023-04-24 11:48:33 +08:00
josh 66b9eb698b first post, josh-oap-1-4 2023-04-23 13:18:00 +08:00
josh 7e949c1980 update post, josh-oap-1-4 2023-04-23 12:05:24 +08:00
josh 4b752f4b2d update post, josh-oap-1-4 2023-04-23 11:33:40 +08:00
josh 80fbb36c17 new post, josh-oap-1-4 2023-04-22 19:19:15 +08:00
josh 938b80d30e review post, josh-oap-1-3 2023-04-22 17:08:42 +08:00
josh 5d38bef83b update post, josh-oap-1-3 2023-04-22 12:47:01 +08:00
josh 211be1a75f finish post, josh-oap-1-3 2023-04-22 11:37:07 +08:00
josh 8d354828dc update post josh-oap-1-3 2023-04-21 19:30:46 +08:00
josh 54058d3d9c update post, josh-oap-1-3 2023-04-21 00:00:23 +08:00
josh 80f7730639 new post, josh-oap-1-3 2023-04-20 20:09:52 +08:00
josh ad701025f1 finish post, josh-oap-1-2 2023-04-20 15:46:33 +08:00
josh 34ee0358bb update post, josh-oap-1-2 2023-04-20 10:12:07 +08:00
josh 4ebf80ee3a new post, josh-oap-1-2 2023-04-20 00:50:40 +08:00
josh e4f8ff9918 finish post, josh-opa-1-1 2023-04-20 00:12:31 +08:00
josh 18e512b477 update post josh-oap-1-1 2023-04-19 21:29:43 +08:00
josh 0a9ae20ece update post josh-oap-1-1 2023-04-19 13:31:41 +08:00
josh 37dc8469b7 update post josh-oap-1-1 2023-04-19 09:56:54 +08:00
josh 7d89c68c6f new post, josh-oap-1-1 2023-04-19 01:06:58 +08:00
josh ed034469eb update some post name 2023-04-18 23:54:26 +08:00
josh cc3a554bd5 change some next dependencies to local 2023-04-18 19:03:14 +08:00
josh a85b8b525c review josh-verilog-6 2023-04-18 00:22:42 +08:00
josh 3726774315 review josh-verilog-5 2023-04-17 21:37:49 +08:00
josh 657f34e74f update hyperref links in josh-verilog-4 2023-04-17 19:49:59 +08:00
josh e50c0bcfcc review josh-verilog-4, change hyperref styles 2023-04-17 19:46:59 +08:00
josh 5f2488bfa9 update caption in josh-verilog-1~3 2023-04-17 09:52:22 +08:00
josh cd92265be1 review josh-verilog 1-3, correct some mistakes, update some layout 2023-04-17 00:56:17 +08:00
josh ca83c80da0 optimize main style, looking for ways to invert background image in dark mode 2023-04-16 19:24:02 +08:00
josh eedb4f0957 update caption of josh-verilog-6 & 7 2023-04-16 17:29:32 +08:00
josh 2ae9ba3003 add post josh-verilog-7 2023-04-16 14:39:19 +08:00
josh 0de9bc010f add post josh-verilog-6 2023-04-16 12:37:03 +08:00
josh 4a4f39fcd3 add post josh-dsp-7 2023-04-16 00:14:14 +08:00
josh abeab5d047 add post josh-dsp-6 2023-04-15 23:33:00 +08:00
josh 8587ef4deb add post josh-dsp-5 2023-04-15 23:00:00 +08:00
388 changed files with 25847 additions and 3594 deletions
+3
View File
@@ -0,0 +1,3 @@
{
"recommendations": []
}
+1 -1
View File
@@ -1 +1 @@
# JoshGao-bit.github.io
# joshgao22.github.io
+26 -25
View File
@@ -50,10 +50,10 @@ darkmode: true
# ---------------------------------------------------------------
favicon:
small: /images/favicon-16x16-j.png
medium: /images/favicon-32x32-j.png
apple_touch_icon: /images/apple-touch-icon-j.png
safari_pinned_tab: /images/favicon-j.svg
small: /images/meta/favicon-16x16-j.png
medium: /images/meta/favicon-32x32-j.png
apple_touch_icon: /images/meta/apple-touch-icon-j.png
safari_pinned_tab: /images/meta/favicon-j.svg
#android_manifest: /manifest.json
# Custom Logo (Warning: Do not support scheme Mist)
@@ -140,7 +140,7 @@ sidebar:
# Sidebar Avatar
avatar:
# Replace the default image and set the url here.
url: /images/favicon-j.svg
url: /images/meta/favicon-j.svg
# If true, the avatar will be displayed in circle.
rounded: true
# If true, the avatar will be rotated with the cursor.
@@ -154,7 +154,7 @@ site_state: true
# Key is the link label showing to end users.
# Value before `||` delimiter is the target permalink, value after `||` delimiter is the name of Font Awesome icon.
social:
GitHub: https://github.com/JoshGao-bit || fab fa-github
GitHub: https://github.com/joshgao22 || fab fa-github
E-Mail: mailto:[email protected] || fa fa-envelope
#Weibo: https://weibo.com/yourname || fab fa-weibo
#Google: https://plus.google.com/yourname || fab fa-google
@@ -180,6 +180,7 @@ links_settings:
links:
#Title: https://example.com
"gatsby.icu": https://gatsby.icu/zh-cn/
# Table of Contents in the Sidebar
# Front-matter variable (nonsupport wrap expand_all).
@@ -231,7 +232,7 @@ footer:
# The full num of gongan beian.
gongan_num: 京公网安备11010802039063号
# The icon for gongan beian. See: http://www.beian.gov.cn/portal/download
gongan_icon_url: https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/MIsc/%E5%A4%87%E6%A1%88%E5%9B%BE%E6%A0%87.png
gongan_icon_url: /images/misc/备案图标.png
# ---------------------------------------------------------------
@@ -291,13 +292,13 @@ follow_me:
related_posts:
enable: true
title: # Custom header, leave empty to use the default one
display_in_home: false
display_in_home: true
# Post edit
# Easily browse and edit blog source code online.
post_edit:
enable: false
url: https://github.com/JoshGao-bit/JoshGao-bit.github.io/tree/src/source/ # Link for view source
url: https://github.com/joshgao22/joshgao22.github.io/tree/src/source/ # Link for view source
#url: https://github.com/user-name/repo-name/edit/branch-name/subdirectory-name/ # Link for fork & edit
# Show previous post and next post in post footer if exists
@@ -366,8 +367,8 @@ codeblock:
# Code Highlight theme
# All available themes: https://theme-next.js.org/highlight/
theme:
light: default
dark: github-dark
light: vs
dark: github-dark-dimmed
prism:
light: prism
dark: prism-dark
@@ -397,17 +398,17 @@ reading_progress:
# Bookmark Support
bookmark:
enable: false
enable: true
# Customize the color of the bookmark.
color: "#222"
# If auto, save the reading progress when closing the page or clicking the bookmark-icon.
# If manual, only save it by clicking the bookmark-icon.
save: manual
save: auto
# `Follow me on GitHub` banner in the top-right corner.
github_banner:
enable: true
permalink: https://github.com/JoshGao-bit
enable: false
permalink: https://github.com/joshgao22
# ---------------------------------------------------------------
@@ -447,18 +448,18 @@ font:
# Font settings for headlines (<h1> to <h6>).
headings:
external: true
external: false
family:
size:
# Font settings for posts (.post-body).
posts:
external: true
external: false
family:
# Font settings for <code> and code blocks.
codes:
external: true
external: false
family:
@@ -530,7 +531,7 @@ pdf:
# Mermaid tag
mermaid:
enable: false
enable: true
# Available themes: default | dark | forest | neutral
theme:
light: forest
@@ -620,8 +621,8 @@ quicklink:
# Use Animate.css to animate everything.
# For more information: https://animate.style
motion:
enable: true
async: false
enable: false
async: true
transition:
# All available transition variants: https://theme-next.js.org/animate/
menu_item: fadeInDown
@@ -668,7 +669,7 @@ comments:
# Setting `true` means remembering the comment system selected by the visitor.
storage: true
# Lazyload all comment systems.
lazyload: false
lazyload: true
# Modify texts or order for any naves, here are some examples.
nav:
#disqus:
@@ -713,11 +714,11 @@ livere_uid: # <your_uid>
# For more information: https://gitalk.github.io
gitalk:
enable: true
github_id: JoshGao-bit # GitHub repo owner
github_id: joshgao22 # GitHub repo owner
repo: Josh-Blog-Comment # Repository name to store issues
client_id: eb4dc2ea750519598663 # GitHub Application Client ID
client_secret: 4fe0fb49aeb8fac49c609796b214a99a6df044cf # GitHub Application Client Secret
admin_user: JoshGao-bit # GitHub repo owner and collaborators, only these guys can initialize gitHub issues
admin_user: joshgao22 # GitHub repo owner and collaborators, only these guys can initialize gitHub issues
distraction_free_mode: true # Facebook-like distraction free mode
# When the official proxy is not available, you can change it to your own proxy address
proxy: https://cors-anywhere.azm.workers.dev/https://github.com/login/oauth/access_token # This is official proxy address
@@ -909,7 +910,7 @@ vendors:
# The default CDN provider of third-party plugins.
# Available values: local | jsdelivr | unpkg | cdnjs | custom
# Dependencies for `plugins: local`: https://github.com/next-theme/plugins
plugins: cdnjs
plugins: jsdelivr
# Custom CDN URL
# For example:
# custom_cdn_url: https://cdn.jsdelivr.net/npm/${npm_name}@${version}/${minified}
+19 -23
View File
@@ -6,14 +6,14 @@
title: Josh's Blog
subtitle: 一个电子工程师的修养
description: 我,搞通信的
keywords: 硬件,Verilog
keywords: 硬件,Verilog,阵列
author: Josh Gao
language: zh-CN
timezone: Asia/Shanghai
# URL
## Set your site url here. For example, if you use GitHub Page, set url as 'https://username.github.io/project'
url: http://josh-gao.top
url: https://josh-gao.top
# permalink: :year/:month/:day/:title.html
permalink: posts/:abbrlink.html
# abbrlink config: https://github.com/rozbo/hexo-abbrlink
@@ -55,6 +55,8 @@ highlight:
tab_replace: ' '
wrap: true
hljs: false
exclude_languages:
- mermaid
prismjs:
enable: false
preprocess: true
@@ -88,7 +90,7 @@ time_format: HH:mm:ss
## updated_option supports 'mtime', 'date', 'empty'
updated_option: 'mtime'
# Pagination
# Archive Pagination
## Set per_page to 0 to disable pagination
per_page: 15
pagination_dir: page
@@ -108,23 +110,11 @@ theme: next
## Docs: https://hexo.io/docs/one-command-deployment
deploy:
- type: git
repo: josh@101.43.227.73:/home/josh/documents/josh-blog-deploy.git
repo: josh@129.153.124.210:/home/josh/documents/josh-blog-deploy.git
branch: master
- type: git
repo: [email protected]:/home/josh/documents/josh-blog.git
repo: https://github.com/joshgao22/joshgao22.github.io.git
branch: master
- type: git
repo: [email protected]:josh-gao/josh-blog/josh-blog.git
branch: master
- type: git
repo: [email protected]:JoshGao-bit/JoshGao-bit.github.io.git
branch: master
# MathJax [Redundant]
# math:
# engine: 'mathjax'
# mathjax:
# src: https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-mml-chtml.min.js
# Local Search
search:
@@ -199,12 +189,18 @@ neat_js:
related_posts:
enabled: true
enable_env_name: prod
filter_threshold: 0.13
related_count: 3
related_count: 5
weight:
title: 0.1
description: 0
keywords: 0
tags: 0.01
categories: 0.05
text: 0
description: 0.01
keywords: 0.01
tags: 0.005
categories: 0.005
text: 0.2
# config of hexo-renderer-pandoc
pandoc:
args:
- --mathjax
+5401 -1774
View File
File diff suppressed because it is too large Load Diff
+12 -11
View File
@@ -9,30 +9,31 @@
"server": "hexo server"
},
"hexo": {
"version": "6.3.0"
"version": "7.3.0"
},
"dependencies": {
"hexo": "^6.3.0",
"@next-theme/plugins": "^8.23.1",
"hexo": "^7.3.0",
"hexo-abbrlink": "^2.2.1",
"hexo-deployer-git": "^4.0.0",
"hexo-filter-github-emojis": "^3.0.5",
"hexo-generator-archive": "^2.0.0",
"hexo-generator-category": "^2.0.0",
"hexo-generator-index": "^3.0.0",
"hexo-generator-searchdb": "^1.4.1",
"hexo-generator-index": "^4.0.0",
"hexo-generator-searchdb": "^1.5.0",
"hexo-generator-sitemap": "^3.0.1",
"hexo-generator-tag": "^2.0.0",
"hexo-helper-live2d": "^3.1.1",
"hexo-markmap": "^2.0.8",
"hexo-neat": "^1.0.9",
"hexo-related-popular-posts": "^5.0.1",
"hexo-related-posts": "^1.5.1",
"hexo-related-posts": "^1.6.2",
"hexo-renderer-ejs": "^2.0.0",
"hexo-renderer-pandoc": "^0.3.1",
"hexo-renderer-stylus": "^2.1.0",
"hexo-renderer-pandoc": "^0.5.0",
"hexo-renderer-stylus": "^3.0.1",
"hexo-server": "^3.0.0",
"hexo-tag-cloud": "2.1.*",
"hexo-theme-landscape": "^0.0.3",
"hexo-theme-next": "^8.15.1",
"hexo-word-counter": "^0.1.0"
"hexo-theme-landscape": "^1.1.0",
"hexo-theme-next": "^8.23.1",
"hexo-word-counter": "^0.2.1"
}
}
+1 -1
View File
@@ -8,7 +8,7 @@ comments: true
copyright: true
toc:
enable: true
number: ture
number: true
wrap: true
expand_all: true
max_depth: 4
+2 -2
View File
@@ -1,4 +1,4 @@
{% if site.tags.length > 1 %}
{# {% if site.tags.length > 1 %}
<script type="text/javascript" charset="utf-8" src="{{ url_for('/js/tagcloud.js') }}"></script>
<script type="text/javascript" charset="utf-8" src="{{ url_for('/js/tagcanvas.js') }}"></script>
<div class="widget-wrap">
@@ -8,4 +8,4 @@
</canvas>
</div>
</div>
{% endif %}
{% endif %} #}
+8 -13
View File
@@ -1,22 +1,14 @@
// Custom styles.
// 设置背景图片
body{
// background:url('https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/backgroud.jpg');
background:url(../images/bg.svg);
background-repeat:repeat;
// background-attachment:fixed;
// background-position:center;
// background-size:100% 100%;
}
// 博客内容透明化
// :root {
// --content-bg-color:rgba(255, 255, 255, 0.96);
// }
// 设置背景图片
background:url(../images/misc/bg.svg);
background-repeat:repeat;
}
@media (prefers-color-scheme: light) {
:root {
// 博客内容透明化
--content-bg-color:rgba(255, 255, 255, 0.96);
}
}
@@ -25,6 +17,9 @@ body{
:root {
--content-bg-color:rgba(0, 0, 0, 0.88);
}
// img{
// filter: invert(1);
// }
}
// 修复不蒜子显示属性被 hexo-helper-live2d 覆盖
+3
View File
@@ -3,3 +3,6 @@ $border-radius-inner = 10px;
$border-radius = 10px;
// $font-family-chinese = "PingFang SC", "Microsoft YaHei";
// Font size of articles.
// $font-size-base = 18px
+1 -1
View File
@@ -50,7 +50,7 @@ date: 2021-11-27 19:20:36
应用概率论、随机过程、数理统计等方法来研究信息的传输、提取和处理系统中的一般规律。
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2021-11-27-josh-toi-part-1/2021-11-27-josh-toi-part-1-010-SystemModel.png" width=600px alt="图1-1 信息传输系统的模型"/>
<img src="../images/post/2021-11-27-josh-toi-part-1/2021-11-27-josh-toi-part-1-010-SystemModel.png" width=600px alt="图1-1 信息传输系统的模型"/>
</div>
## 研究目的
@@ -1,32 +0,0 @@
---
title: Josh 的学习笔记之凸优化 (Part 1 —— 凸集)
mathjax: true
comments: true
copyright: true
sticky: false
toc:
enable: true
number: false
wrap: true
expand_all: true
max_depth: 4
categories:
- - Josh 的学习笔记
- 凸优化
tags:
- 凸优化
abbrlink: 43146ee9
date: 2022-03-29 11:07:04
---
# 仿射集合和凸集
&emsp;&emsp;设 $x_1 \ne x_2$ 是 $\mathbf{R}^n$ 空间中的两个点,则具有下列形式的点
$$
y = \theta x_1 + (1-\theta)x_2,\theta \in \mathbf{R}
$$
组成一条穿过 $x_1$ 和 $x_2$ 的**直线**(*line*). 参数 $\theta = 0$ 对应 $y=x_2$,$\theta = 1$ 表明 $y = x_2$. 参数 $\theta$ 的值在
<!-- more -->
@@ -0,0 +1,36 @@
---
title: Zynq 系列 SoC / MPSoC 创建可调试的 FSBL
mathjax: true
comments: true
copyright: true
toc:
enable: true
number: true
wrap: true
expand_all: true
max_depth: 4
tags:
- 调试记录
- MPSoC
- RFSoC
- Zynq
- FSBL
categories:
- 调试记录
date: 2024-06-29 16:46:38
---
FSBL 可以初始化 SoC 设备,将所需的应用程序或数据加载到内存,并在目标 CPU 核心上启动应用程序。
在 Vitis 中创建 Platform 时,可以选择同时创建 FSBL,这样 FSBL 就会位于 Platform 下。也可以创建单独的 FSBL 程序,作为普通程序使用,以便进一步修改或调试。
本文以 Zynq UltraScale+ RFSoC 为例,对 FSBL 进行调试。
# 名词释义
- [FSBL](https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18842019/Zynq+UltraScale+FSBL#ZynqUltraScale+FSBL-WhatisFSBL?):First Stage Bootloader,第一阶段引导加载程序
- [SoC](https://en.wikipedia.org/wiki/System_on_a_chip):System-on-Chip,片上系统
# 参考文档
[Creating a Debuggable First Stage Boot Loader](https://xilinx.github.io/Embedded-Design-Tutorials/docs/2021.1/build/html/docs/Feature_Tutorials/debuggable-fsbl/debuggable-fsbl.html)
@@ -0,0 +1,35 @@
---
title: Josh's Summary — 工科数学分析<br>Part 1.2 常微分方程
mathjax: true
comments: true
copyright: true
toc:
enable: true
number: true
wrap: true
expand_all: true
max_depth: 4
tags:
- 高等数学
- 数学分析
- 微积分
categories:
- - Josh 的学习笔记
- 高等数学
- - 数学
- 数学分析
abbrlink: 5a263f58
date: 2025-06-26 10:21:02
---
# 常见等价无穷小
1. $\sin x \sim x$
2. $\tan x \sim x$
3. $\arcsin x \sim x$
4. $\arctan x \sim x$
5. $1 - \cos x \sim \frac{x^2}{2}$
6. $\ln(1+x) \sim x$
7. $e^x - 1 \sim x$
8. $a^x - 1 \sim x \ln a$
9. $(1+x)^\alpha - 1 \sim \alpha x$
+33 -38
View File
@@ -19,40 +19,41 @@ date: 2020-11-25 22:32:42
# 语法
`b = rcosdesign(beta,span,sps)`
`b = rcosdesign(beta,span,sps,shape)`
<!-- more -->
# 说明
`b = rcosdesign(beta,span,sps)` 返回系数 `b`,该系数对应于具有由 `beta` 指定的衰减因子的平方根升余弦 FIR 滤波器。滤波器有 `span` 个符号,每个符号包含 `sps` 个样本。 滤波器的阶次,也即 `sps * span` 必须是偶数。滤波器的能量为 1。[举例](#Examples-01)
`b = rcosdesign(beta,span,sps)` 返回根升余弦(square-root raised cosine)FIR 滤波器的系数 `b`。根升余弦 FIR 滤波器的滚降系数(rolloff factor)为 `beta`。滤波器被截断(truncated)为 `span` 个符号,并且每个符号周期包含 `sps` 个采样点。滤波器的阶数 `sps * span` 必须是偶数。滤波器的能量为 1。[示例](#Examples-01)
`b = rcosdesign(beta,span,sps,shape)` 根据 `shape` 返回不同的滤波器。当 `shape` 为 `sqrt` 时,将返回根升余弦滤波器;当 `shape` 为 `normal` 时,将返回升余弦 FIR 滤波器。[举例](#Examples-02)
`b = rcosdesign(beta,span,sps,shape)` 根据 `shape` 返回不同的滤波器。当 `shape` 为 `sqrt` 时,返回根升余弦滤波器;当 `shape` 为 `normal` 时,返回升余弦(raised cosine) FIR 滤波器。[示例](#Examples-02)
# 示例
## 设计根升余弦滤波器<a name="Examples-01"></a>
将滚降系数设为 `0.25`,波器的符号数设为 `6`,每个符号 `4` 个采样点。验证 `sqrt` 是 `shape` 参数的默认值。
令滚降系数为 `0.25`,滤波器符号数为 `6` 个,每个符号 `4` 个采样点。验证 `sqrt` 是参数 `shape` 的默认值。
``` matlab
h = rcosdesign(0.25,6,4);
mx = max(abs(h-rcosdesign(0.25,6,4,'sqrt')))
```
> <font face="Consolas">mx = 0</font><br>
> `mx = 0`
``` matlab
fvtool(h,'Analysis','impulse')
```
![ ](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-25-matlab-rcosdesign/2020-11-25-matlab-rcosdesign-010-DesignASquareRootRaisedCosineFilterExample-01.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/14/dissolve/20/gravity/southeast/dx/5/dy/5)
![ ](../images/post/2020-11-25-matlab-rcosdesign/2020-11-25-matlab-rcosdesign-010-DesignASquareRootRaisedCosineFilterExample.svg)
## 升余弦和根升余弦滤波器的脉冲响应<a name="Examples-02"></a>
将升余弦滤波器与根升余弦滤波器进行比较。一个理想的(无限长)升余弦脉冲成形滤波器等效于两个级联的理想的根升余弦滤波器。因此,FIR 升余弦滤波器的脉冲响应应类似于与其自身卷积的根升余弦滤波器的脉冲响应。
设计一个衰减为 `0.25` 的升余弦滤波器。指定滤波器有 `4` 个符号,每个符号 `3` 个采样点。
设计一个滚降系数为 `0.25`、符号数为 `4` 个、每个符号 `3` 个采样点的升余弦滤波器。
``` matlab
rf = 0.25;
@@ -60,38 +61,34 @@ span = 4;
sps = 3;
h1 = rcosdesign(rf,span,sps,'normal');
fvtool(h1,'impulse')
impz(h1)
```
![ ](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-25-matlab-rcosdesign/2020-11-25-matlab-rcosdesign-020-ImpulseResponsesOfNormalAndSquareRootRaisedCosineFiltersExample-01.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/14/dissolve/20/gravity/southeast/dx/5/dy/5)
![ ](../images/post/2020-11-25-matlab-rcosdesign/2020-11-25-matlab-rcosdesign-020-ImpulseResponsesOfNormalAndSquareRootRaisedCosineFiltersExample-01.svg)
**升余弦滤波器在 `sps` 的整数倍处具有零值点**。因此,它满足无码间串扰(ISI)的 Nyquist 准则。但是,根升余弦滤波器没有这样的特性:
``` matlab
h2 = rcosdesign(rf,span,sps,'sqrt');
fvtool(h2,'impulse')
h2 = rcosdesign(rf,span,sps,"sqrt");
impz(h2)
```
![ ](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-25-matlab-rcosdesign/2020-11-25-matlab-rcosdesign-030-ImpulseResponsesOfNormalAndSquareRootRaisedCosineFiltersExample-02.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/14/dissolve/20/gravity/southeast/dx/5/dy/5)
![ ](../images/post/2020-11-25-matlab-rcosdesign/2020-11-25-matlab-rcosdesign-030-ImpulseResponsesOfNormalAndSquareRootRaisedCosineFiltersExample-02.svg)
将根升余弦滤波器与自身进行卷积。在最大值处截断脉冲响应,使其长度与 `h1` 相同。使用最大值将响应归一化。然后,将卷积后的根升余弦滤波器与升余弦滤波器进行比较。
``` matlab
h3 = conv(h2,h2);
p2 = ceil(length(h3)/2);
m2 = ceil(p2-length(h1)/2);
M2 = floor(p2+length(h1)/2);
ct = h3(m2:M2);
h3 = conv(h2,h2,"same");
stem([h1/max(abs(h1));ct/max(abs(ct))]','filled')
xlabel('Samples')
ylabel('Normalized amplitude')
legend('h1','h2 * h2')
stem(0:span*sps,[h1/max(abs(h1));h3/max(abs(h3))]',"filled")
xlabel("Samples")
ylabel("Normalized Amplitude")
legend("h1","h2 * h2")
```
![ ](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-25-matlab-rcosdesign/2020-11-25-matlab-rcosdesign-040-ImpulseResponsesOfNormalAndSquareRootRaisedCosineFiltersExample-03.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/14/dissolve/20/gravity/southeast/dx/5/dy/5)
![ ](../images/post/2020-11-25-matlab-rcosdesign/2020-11-25-matlab-rcosdesign-040-ImpulseResponsesOfNormalAndSquareRootRaisedCosineFiltersExample-03.svg)
卷积响应的长度是有限的,因此根升余弦滤波器与自身进行卷积得到的结果会与升余弦滤波器不一致。增加 `span` 可以在响应之间获得更紧密的一致性,并更好地符合 Nyquist 准则。
由于卷积响应的长度是有限的,因此根升余弦滤波器与自身进行卷积得到的结果会与升余弦滤波器不一致。增加 `span` 可以在响应之间获得更紧密的一致性,并更好地符合 Nyquist 准则。
## 将信号通过升余弦滤波器<a name="Examples-03"></a>
@@ -100,9 +97,9 @@ legend('h1','h2 * h2')
指定滤波器参数。
``` matlab
rolloff = 0.25; % 滚降因子
rolloff = 0.25; % 滚降系数
span = 6; % 滤波器宽度(符号数)
sps = 4; % 每个符号的样本数
sps = 4; % 每个符号的采样点数
```
生成根升余弦滤波器的系数。
@@ -135,31 +132,33 @@ r = x + randn(size(x))*0.01;
y = upfirdn(r, b, 1, sps);
```
有关如何使用根升余弦滤波器对信号进行插值和抽取的信息,请参见使[用 RRC 滤波器进行插值和抽取](https://ww2.mathworks.cn/help/comm/ug/interpolate-and-decimate-using-rrc-filter.html)(Communications Toolbox)。
有关如何使用根升余弦滤波器对信号进行插值和抽取的信息,请参见使[用 RRC 滤波器进行插值和抽取](https://ww2.mathworks.cn/help/releases/R2024a/comm/ug/filtering.html#mw_fa589f54-fcad-495e-b4f8-4a4ad52c1f1a)(Communications Toolbox)。
# 输入参数
## `beta` - 滚降系数
滚降系数,指定为不大于 `1` 的**实非负标量**。滚降系数决定滤波器的多余带宽。滚降系数为 `0` 时为矩形滤波器(brick-wall filter),滚降因子为 `1` 时为纯升余弦滤波器。
滚降系数,应为不大于 `1` 的**实非负标量**。滚降系数决定滤波器的多余带宽。滚降系数为 `0` 时为矩形滤波器(brick-wall filter),滚降系数为 `1` 时为纯升余弦滤波器。
**数据类型**:`double` | `single`
## `span` - 符号数
符号数,指定为**正整数标量**。
符号数,应为**正整数标量**。
**数据类型**:`double` | `single`
## `sps` - 每个符号的样本数
## `sps` - 每个符号的采样点数
每个符号的样本数(上采样因子),指定为**正整数标量**。
> 正整数标量
每个符号的采样点数(上采样因子),应为**正整数标量**。
**数据类型**:`double` | `single`
## `shape` - 升余弦滤波器的形状
升余弦滤波器的形状,指定为 `normal` 或 `sqrt`。
升余弦滤波器的形状,应为 `"normal"` 或 `"sqrt"`。
# 输出参数
@@ -171,7 +170,7 @@ y = upfirdn(r, b, 1, sps);
# 提示
- 如果您拥有 Communications Toolbox™ 软件的许可证,则可以执行具有流传输行为的多速率升余弦滤波。为此,请使用 System object™ 滤波器——`comm.RaisedCosineTransmitFilter` 和 `comm.RaisedCosineReceiveFilter`。
- 如果您有 Communications Toolbox™ 软件的许可证,则可以执行具有流式传输行为的多速率升余弦滤波。为此,请使用 System object™ 滤波器——`comm.RaisedCosineTransmitFilter` 和 `comm.RaisedCosineReceiveFilter`。
# 参考
@@ -182,10 +181,6 @@ y = upfirdn(r, b, 1, sps);
## C/C++ 代码生成
> 使用 MATLAB® Coder™ 生成 C 代码和 C++ 代码。
>
>> 用法说明和限制:
>>
>> 所有输入必须为常数。 如果表达式或变量的值不变,则也允许使用。
# 版本历史
@@ -193,10 +188,10 @@ y = upfirdn(r, b, 1, sps);
# 另请参阅
[`gaussdesign`](https://ww2.mathworks.cn/help/signal/ref/gaussdesign.html)
[`gaussdesign`](https://ww2.mathworks.cn/help/releases/R2024a/signal/ref/gaussdesign.html)
## 主题
[用 RRC 滤波器进行插值和抽取](https://ww2.mathworks.cn/help/comm/ug/interpolate-and-decimate-using-rrc-filter.html)(Communications Toolbox)
[用 RRC 滤波器进行插值和抽取](https://ww2.mathworks.cn/help/releases/R2024a/comm/ug/filtering.html#mw_fa589f54-fcad-495e-b4f8-4a4ad52c1f1a)(Communications Toolbox)
> 原文参考:[https://ww2.mathworks.cn/help/signal/ref/rcosdesign.html](https://ww2.mathworks.cn/help/signal/ref/rcosdesign.html)
> 原文参考:[https://ww2.mathworks.cn/help/releases/R2024a/signal/ref/rcosdesign.html](https://ww2.mathworks.cn/help/releases/R2024a/signal/ref/rcosdesign.html)
@@ -40,7 +40,7 @@ h = gaussdesign(bt,span,sps);
fvtool(h,'impulse')
```
![ ](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-26-matlab-gaussdesign/2020-11-26-matlab-gaussdesign-010-GaussianFilterForAGSMGMSKDigitalCellularCommunicationSysExample-01.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/14/dissolve/20/gravity/southeast/dx/5/dy/5)
![ ](../images/post/2020-11-26-matlab-gaussdesign/2020-11-26-matlab-gaussdesign-010-GaussianFilterForAGSMGMSKDigitalCellularCommunicationSysExample-01.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/14/dissolve/20/gravity/southeast/dx/5/dy/5)
# 输入参数
@@ -18,6 +18,7 @@ date: 2020-11-26 22:23:39
# 语法
`y = upsample(x,n)`
`y = upsample(x,n,phase)`
<!-- more -->
+45 -30
View File
@@ -1,5 +1,5 @@
---
title: Josh 的学习笔记之 Verilog(Part 1 —— 初识 HDL 设计方法)
title: "Josh's Note — Verilog<br>Part 1 初识 HDL 设计方法"
date: 2020-11-27 22:58:07
tags:
- Verilog
@@ -20,44 +20,49 @@ toc:
expand_all: true
max_depth: 4
abbrlink: 460433dd
description: 本文阐述了 HDL 语言/设计方法的基本概念。主要介绍了数字系统建模方法的演变,引入了 HDL 语言的基本概念,对 Verilog HDL 和 VHDL、Verilog HDL 和 C 的联系与区别进行了说明,最后引入了 HDL 的设计和验证流程,并对各个流程进行了简单介绍。
---
本文阐述了 HDL 语言/设计方法的基本概念。主要介绍了数字系统建模方法的演变,引入了 HDL 语言的基本概念,对 Verilog HDL 和 VHDL、Verilog HDL 和 C 的联系与区别进行了说明,在最后引入了 HDL 的设计和验证流程,并对各个流程进行了简单介绍。
# 1. 设计方法的变迁<a name="01"></a>
# 1. 设计方法的变迁<a id="toc.1"></a>
随着微电子设计技术与工艺的发展,数字集成电路从电子管、晶体管、中小规模集成电路、超大规模集成电路(Very Large Scale Integrated Circuit, VLSIC)逐步发展到今天的专用集成电路(Application Specific Integrated Circuit, ASIC),愈发数字化的产品如计算机、手机、数字电视等都运用了复杂的专用数字集成电路。数字逻辑器件从简单的逻辑门到复杂的 SoC,种类繁多,提供了对复杂系统的灵活支撑。
<!-- more -->
随着数字电路系统的不断发展,系统的逻辑复杂度与规模日益增加,数字系统的设计方法也随之不断演进。早期简单的门逻辑设计阶段,EDA 工具应用范围十分有限,工程师们习惯于使用**{% label @卡诺图 %}**简化设计,然后通过面包板等实验系统验证设计;系统相对复杂后,工程师们借助 EDA 工具通过原理图描述数字系统。
随着数字电路系统的不断发展,系统的逻辑复杂度与规模日益增加,数字系统的设计方法也随之不断演进。在早期简单的门逻辑设计阶段,EDA(Electronic Design Automation,电子设计自动化)工具应用范围十分有限,工程师们习惯于使用**{% label prime@卡诺图 %}**简化设计,然后通过面包板等实验系统验证设计;系统相对复杂后,工程师们借助 EDA 工具通过原理图描述数字系统。
{% note default %}
原理图由元件库中的元件构成,使用 EDA(Electronic Design Automation,电子设计自动化)工具可以对原理图进行仿真并分析其性能。
原理图由元件库中的元件构成,使用 EDA 工具可以对原理图进行仿真并分析其性能。
{% endnote %}
当数字系统发展到 ASIC 与 PLD(Programmable Logic Device,可编程逻辑器件) 设计阶段后,原理图不利于移植、维护费时费力等缺点逐步显现,这时需要抽象度更高、更灵活的设计方式 —— HDL(Hardware Description Language,硬件描述语言)。
当数字系统发展到 ASIC 与 PLD(Programmable Logic Device,可编程逻辑器件)设计阶段后,原理图不利于移植、维护费时费力等缺点逐步显现,这时需要抽象度更高、更灵活的设计方式 —— HDL(Hardware Description Language,硬件描述语言)。
使用 HDL 语言,可以从算法、系统级(System Level)、功能模块级(Functional Model Level)、行为级(Behavioral Level)、寄存器传输级(RTL, Register Transfer Level)、门级(Gate Level)到开关级(Switch Level)等不同层次描述数字电路系统,然后通过 EDA 工具综合、仿真并实现该系统。可以说 HDL 语言的出现是数字系统设计方法的一个重大飞跃。
数字电路系统设计方法的另一个重大飞跃是随着 EDA 工具的不断推陈出新发生的。早期 ASIC 和 PLD 设计时,人们需要直接描述 CMOS 的开关电路或门级电路,其设计量庞大,仿真速度也非常慢,像当今系统门数量为千万门级的 FPGA 用开关级或门级方法描述在当时是不可想象的。这时人们就希望能够使用 HDL 直接从更高的层次描述电路,然后使用 EDA 工具自动将高层次的 HDL 电路描述解析到门级,这些将大大节约设计与仿真时间,这个**{% label @从高层次的电路描述通过 EDA 工具解析到门级等低层次的电路描述的过程就叫“综合”(Synthesize),或者逻辑综合 %}**。
数字电路系统设计方法的另一个重大飞跃是随着 EDA 工具的不断推陈出新发生的。早期 ASIC 和 PLD 设计时,需要直接描述 CMOS 的开关电路或门级电路,其设计量庞大,仿真速度也非常慢,用开关级或门级方法描述如当今门数量为千万门级的 FPGA 在当时是不可想象的。这时人们就希望能够使用 HDL 直接从更高的层次描述电路,然后使用 EDA 工具自动将高层次的 HDL 电路描述解析到门级,这些将大大节约设计与仿真时间,这个**{% label prime@从高层次的电路描述通过 EDA 工具解析到门级等低层次的电路描述的过程就叫“综合”(Synthesize),或者逻辑综合 %}**。
{% note default %}
综合工具能将高层次的 HDL 语言、原理图等设计描述翻译成由与、或、非门等基本逻辑单元组成的门级连接(**网表**)并根据设计目标与要求(约束条件)优化所生成的逻辑连接,输出门级网表文件。
{% endnote %}
目前最成熟的综合工具是 RTL 级综合工具,它能将 RTL 级描述翻译并优化为门级网表。综合工具的产生支撑了直接从 RTL 级描述硬件电路,这种从门级描述抽象到 RTL 级描述数字电路是设计方法的又一次伟大飞跃。
从上面描述可以看到 HDL 语言是分层次的,关于上述 HDL 语言设计层次的含义在 [3. HDL 的设计与验证流程](#03)小节和 [《Part 3——描述方式和设计层次》的 5. 设计层次](https://josh-gao.blog.csdn.net/article/details/105262549#5__1023)小节有详细论述。)
从上面描述可以看到 HDL 语言是分层次的,关于上述 HDL 语言设计层次的含义在本文的 [3. HDL 的设计与验证流程](#toc.3)小节和 [Part 3——描述方式和设计层次的 5. 设计层次][]小节有详细论述。
# 2. Verilog 语言的特点<a name="02"></a>
# 2. Verilog 语言的特点<a id="toc.2"></a>
## 2.1. Verilog 的由来
Verilog 是 Verilog HDL 的简称。
{% note info %}
Verilog 语言最初于1983年由 Gateway Design Automation 公司开发,于1995年接受为 IEEE 标准。
{% endnote %}
Verilog 语言不仅定义了语法,而且对每个语法结构都清晰定义了仿真语义,从而便于仿真调试。而且 Verilog 从 C 语言继承了很多操作符和语法结构,对初学者而言易学易用。另外 Verilog 语言具有很强的扩展能力,最新的 Verilog 2001 标准[^1]大大扩展了 Verilog 的应用灵活性。
@@ -80,61 +85,65 @@ Verilog 语言是根据 C 语言发明而来的,因此 Verilog 具备了 C 语
1. C 语言与 Verilog 的最大区别
C 语言与 Verilog 的最大区别在于 C 缺乏硬件描述的 3 个基本概念:
C 语言与 Verilog 的最大区别在于 C 缺乏硬件描述的 3 个基本概念:
- **{% label primary @互连(connectivity) %}**:硬件系统中,互连是非常重要的组成部分,而在 C 语言中并没有直接可以用来表示模块间互连的变量;而 Verilog 的 `wire` 型变量配合一些驱动结构能有效地描述网线的互连。
- **{% label primary @互连(connectivity) %}**:硬件系统中,互连是非常重要的组成部分,而在 C 语言中并没有直接可以用来表示模块间互连的变量;而 Verilog 的 `wire` 型变量配合一些驱动结构能有效地描述网线的互连。
- **{% label primary @并发(concurrency) %}**:C 语言天生是**串行**的,不能描述硬件之间并发的特性,C 语言编译后,其机器指令在 CPU 的高速缓冲队列中基本是顺序执行;而 Verilog 可以有效地描述并行的硬件系统,硬件系统比软件系统速度快、实时性高的一个重要原因就是硬件系统中**各个单元的运算是独立的,信号流是并行的**。
- **{% label primary @并发(concurrency) %}**:C 语言天生是**串行**的,不能描述硬件之间并发的特性,C 语言编译后,其机器指令在 CPU 的高速缓冲队列中基本是顺序执行;而 Verilog 可以有效地描述并行的硬件系统,硬件系统比软件系统速度快、实时性高的一个重要原因就是硬件系统中**各个单元的运算是独立的,信号流是并行的**。
- **{% label primary @时间(time) %}**:C 程序运行的时候,没有一个严格的时间概念,程序运行的时间长短取决于处理器本身的性能;而 Verilog 语言本身定义了绝对和相对的时间度量,在仿真时可以通过时间度量与周期关系描述信号直接的时间关系。
- **{% label primary @时间(time) %}**:C 程序运行的时候,没有一个严格的时间概念,程序运行的时间长短取决于处理器本身的性能;而 Verilog 语言本身定义了绝对和相对的时间度量,在仿真时可以通过时间度量与周期关系描述信号直接的时间关系。
2. HDL 语言的本质
硬件描述语言(HDL)同软件语言(如 C、C++ 等)是有本质区别的。Verilog 作为硬件描述语言,**它的本质作用在于描述硬件**。Verilog 虽然采用了 C 语言形式,但是它的最终描述结果是芯片内部的实际电路。所以评判一段 HDL 代码优劣的最终标准是其描述并实现的硬件电路的性能(包括面积和速度两个方面)。评价一个设计的代码水平较高,仅仅是说这个设计由硬件向 HDL 代码这种表现形式转换得更流畅、合理。而一个设计的最终性能更大程度上取决于设计工程师所构想的硬件实现方案的效率以及合理性。
硬件描述语言(HDL)同软件语言(如 C、C++ 等)是有本质区别的。Verilog 作为硬件描述语言,**它的本质作用在于描述硬件**。Verilog 虽然采用了 C 语言形式,但是它的最终描述结果是芯片内部的实际电路。所以评判一段 HDL 代码优劣的最终标准是其描述并实现的硬件电路的性能(包括**面积**和**速度**两个方面)。评价一个设计的代码水平较高,仅仅是说这个设计由硬件向 HDL 代码这种表现形式转换得更流畅、合理。而一个设计的最终性能更大程度上取决于设计工程师所构想的硬件实现方案的效率以及合理性。
{% note warning %}
初学者,特别是由软件转行的初学者,片面追求代码的整洁、简短,这是错误的,是与评价 HDL 的标准背道而驰的。正确的编写代码的方法是,首先要做到对所需实现的硬件电路“胸有成竹”,对该部分硬件的结构与连接十分清晰,然后再用适当的 HDL 语句表达出来即可。
{% endnote %}
{% note warning %}
初学者,特别是由软件转行的初学者,片面追求代码的整洁、简短,这是错误的,是与评价 HDL 的标准背道而驰的。正确的编写代码的方法是,首先要做到对所需实现的硬件电路“胸有成竹”,对该部分硬件的结构与连接十分清晰,然后再用适当的 HDL 语句表达出来即可。
{% endnote %}
3. Verilog 与 C 的结合
Verilog 毕竟是硬件描述语言,在抽象层次上比 C 语言要差一些,语法不如 C 灵活,例如文件输入和输出方面,Verilog 的功能显然不如 C。为了克服 Verilog 高级抽象的缺陷,Verilog 的设计者们发明了 PLI。PLI 可以在仿真器中将 C 语言的程序和 Verilog 的程序互相通信,或者在 Verilog 中调用 C 语言的函数库,这样就大大扩展了 Verilog 语言的灵活性和高层次抽象的能力。开发时,一方面,硬件设计者使用 Verilog 进行硬件建模;另一方面,验证工程师却常常使用 C 来编写测试向量,然后通过 Verilog 的 PLI 将 Verilog 和 C 联系起来。这样,C 语言就很好地弥补了 Verilog 高层次建模的缺陷。
Verilog 毕竟是硬件描述语言,在抽象层次上比 C 语言要差一些,语法不如 C 灵活,例如文件输入和输出方面,Verilog 的功能显然不如 C。为了克服 Verilog 高级抽象的缺陷,Verilog 的设计者们发明了 PLI(Programming Language Interface)。PLI 可以在仿真器中将 C 语言的程序和 Verilog 的程序互相通信,或者在 Verilog 中调用 C 语言的函数库,这样就大大扩展了 Verilog 语言的灵活性和高层次抽象的能力。开发时,一方面,硬件设计者使用 Verilog 进行硬件建模;另一方面,验证工程师却常常使用 C 来编写测试向量,然后通过 Verilog 的 PLI 将 Verilog 和 C 联系起来。这样,C 语言就很好地弥补了 Verilog 高层次建模的缺陷。
# 3. HDL 的设计与验证流程<a name="03"></a>
# 3. HDL 的设计与验证流程<a id="toc.3"></a>
HDL 的基本功能就是有效地描述并仿真硬件系统。在此部分,抛开具体的 PLD 或 ASIC 设计流程,从 HDL 语言层次入手,分析典型的 HDL 设计与验证流程。基于 HDL 的设计、仿真流程如下图所示。图中,虚线框表示的步骤可以根据项目的复杂度省略,而实线框表示的步骤为必须执行的步骤。
HDL 的基本功能就是有效地描述并仿真硬件系统。在此部分,抛开具体的 PLD 或 ASIC 设计流程,从 HDL 语言层次入手,分析典型的 HDL 设计与验证流程。基于 HDL 的设计、仿真流程如[图 1-1](#fig.1-1) 所示。图中,虚线框表示的步骤可以根据项目的复杂度省略,而实线框表示的步骤为必须执行的步骤。
![基于 HDL 的设计、仿真流程](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-27-josh-verilog-part-1/2020-11-27-josh-verilog-part-1-010-DesignSimulationFlowChartBasedonHDL.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/14/dissolve/20/gravity/southeast/dx/5/dy/5){width=800px}
<a id="fig.1-1"></a>
![图 1-1 基于 HDL 的设计、仿真流程](../images/post/2020-11-27-josh-verilog-part-1/2020-11-27-josh-verilog-part-1-010-DesignSimulationFlowChartBasedonHDL.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/14/dissolve/20/gravity/southeast/dx/5/dy/5){width=800px}
下面对一些关键设计步骤与概念进行展开。
## 3.1. 系统与功能模块定义(系统与功能模块级)
在大型系统的设计与实现中,首先要进行详细的系统规划和描述,此时 HDL 描述 **{% label @侧重于整体系统的划分和实现 %}**。对系统级的仿真侧重于对整个系统的功能和性能指标的考量。功能模块级设计时将系统整体功能划分为可实现的具体功能模块,大致确定模块间的接口,如时钟、读写信号、数据流、控制信号等。在有些情况下,还要根据系统要求,描述每个模块或进程的时序约束。另外在此层次,必须权衡整个系统多种的实现方式的优劣,选出系统性能指标优并且可以高效实现的设计方案。功能模块级仿真主要是考察每个功能的功能和基本时序情况。系统与功能模块级设计与仿真常常要借助于 C 语言和抽象程度较高的 HDL 语言描述,如 SystemC、Coware C、SystemVerilog、Superlog 等。
在大型系统的设计与实现中,首先要进行详细的系统规划和描述,此时 HDL 描述 **{% label prime@侧重于整体系统的划分和实现 %}**。对系统级的仿真侧重于对整个系统的功能和性能指标的考量。功能模块级设计时将系统整体功能划分为可实现的具体功能模块,大致确定模块间的接口,如时钟、读写信号、数据流、控制信号等。在有些情况下,还要根据系统要求,描述每个模块或进程的时序约束。另外在此层次,必须权衡整个系统多种的实现方式的优劣,选出系统性能指标优并且可以高效实现的设计方案。功能模块级仿真主要是考察每个功能的功能和基本时序情况。系统与功能模块级设计与仿真常常要借助于 C 语言和抽象程度较高的 HDL 语言描述,如 SystemC、Coware C、SystemVerilog、Superlog 等。
## 3.2. 行为级描述测试激励(Behavioral Level)
行为级模块描述的最大特点是 **{% label @必须明确每个模块间的所有接口和边界 %}**。此时模块内部的功能已经明确,模块间的所有接口,顶层的输入、输出信号等在行为级已经被清晰地描述出来。在 PLD 和 ASIC 设计流程中,常用行为级描述方式编写测试激励。延时描述、监视描述等命令都是在编写测试激励过程中常用的行为级语法。行为级描述常用 HDL 语言如 Verilog 和 VHDL 等。
行为级模块描述的最大特点是 **{% label prime@必须明确每个模块间的所有接口和边界 %}**。此时模块内部的功能已经明确,模块间的所有接口,顶层的输入、输出信号等在行为级已经被清晰地描述出来。在 PLD 和 ASIC 设计流程中,常用行为级描述方式编写测试激励。延时描述、监视描述等命令都是在编写测试激励过程中常用的行为级语法。行为级描述常用 HDL 语言如 Verilog 和 VHDL 等。
## 3.3. 寄存器传输级(RTL)
寄存器传输级指不关注寄存器和组合逻辑的细节(如使用了多少逻辑门,逻辑门之间的连接拓扑结构等),**{% label @通过描述寄存器到寄存器之间的逻辑功能描述电路 %}**的 HDL 层次。RTL 级是比门级更高的抽象层次,一般使用 RTL 级语言描述硬件电路比门级描述电路简单、高效得多。寄存器传输级描述的最大特点是可以直接用综合工具综合门级网表。RTL 设计直接决定着设计的功能和效率。好的 RTL 设计能在满足逻辑功能的前提下,使设计的速度和面积达到一种平衡的优化。RTL 级描述最常用的 HDL 语言是 Verilog 和 VHDL 语言。
寄存器传输级指不关注寄存器和组合逻辑的细节(如使用了多少逻辑门,逻辑门之间的连接拓扑结构等),**{% label prime@通过描述寄存器到寄存器之间的逻辑功能描述电路 %}**的 HDL 层次。RTL 级是比门级更高的抽象层次,一般使用 RTL 级语言描述硬件电路比门级描述电路简单、高效得多。寄存器传输级描述的最大特点是可以直接用综合工具综合门级网表。RTL 设计直接决定着设计的功能和效率。好的 RTL 设计能在满足逻辑功能的前提下,使设计的速度和面积达到一种平衡的优化。RTL 级描述最常用的 HDL 语言是 Verilog 和 VHDL 语言。
## 3.4 对 RTL 级描述进行功能仿真
一般来说需要对 RTL 级设计进行功能仿真,仿真的目的为 **{% label @验证 RTL 级描述是否与设计意图一致 %}**。为了提高效率,一般功能仿真的测试激励使用行为级的 HDL 语言描述。
一般来说需要对 RTL 级设计进行功能仿真,仿真的目的为 **{% label prime@验证 RTL 级描述是否与设计意图一致 %}**。为了提高效率,一般功能仿真的测试激励使用行为级的 HDL 语言描述。
## 3.5. 逻辑综合(使用 RTL 级 EDA 工具)
RTL 级综合指 **{% label @将 RTL 级 HDL 语言翻译成由与、或、非门等基本逻辑单元组成的门级连接(网表),并根据设计目标与要求(约束条件)优化所生成的逻辑连接,输出门级网表文件 %}**。随着综合工具的不断智能化,使用 RTL 级语言描述硬件电路越来越方便,特别是在 PLD(主要指 FPGA 和 CPLD)设计领域,最重要的代码设计层次就是 RTL 级。
RTL 级综合指 **{% label prime@将 RTL 级 HDL 语言翻译成由与、或、非门等基本逻辑单元组成的门级连接(网表),并根据设计目标与要求(约束条件)优化所生成的逻辑连接,输出门级网表文件 %}**。随着综合工具的不断智能化,使用 RTL 级语言描述硬件电路越来越方便,特别是在 PLD(主要指 FPGA 和 CPLD)设计领域,最重要的代码设计层次就是 RTL 级。
## 3.6. 门级(Gate Level)
由于目前 FPGA 设计大多数依靠专业综合工具完成从 RTL 级代码向门级代码的转换,所有设计者直接用 HDL 语言描述门级模型的情况越来越少,高效的综合工具将设计者从复杂繁琐的门级描述中彻底解脱出来。目前直接使用门级描述的场合一般是 ASIC 和 FPGA 设计中 **{% label @某些面积或时序要求较高的模块 %}**。门级描述的特点是整个设计用逻辑门实现,通过逻辑门的组合显化描述了设计的引脚、功能、时钟周期等所有信息。
由于目前 FPGA 设计大多数依靠专业综合工具完成从 RTL 级代码向门级代码的转换,所有设计者直接用 HDL 语言描述门级模型的情况越来越少,高效的综合工具将设计者从复杂繁琐的门级描述中彻底解脱出来。目前直接使用门级描述的场合一般是 ASIC 和 FPGA 设计中 **{% label prime@某些面积或时序要求较高的模块 %}**。门级描述的特点是整个设计用逻辑门实现,通过逻辑门的组合显化描述了设计的引脚、功能、时钟周期等所有信息。
## 3.7. 综合后门级仿真
综合完成后,如果需要检查综合结果是否与原设计一致,就需要做综合后仿真。在仿真时,把综合生成的标准延时文件反标注到综合仿真模型中去,可估计门延时带来的影响。综合后仿真虽然比功能仿真精确一些,但是**只能估计门延时,不能估计线延时**,仿真结果**与布线后的实际情况还有一定的差距**,并不十分准确。这种仿真的主要目的在于 **{% label @检查综合器的综合结果是否与设计输入一致 %}**。目前主流综合工具日益成熟,对于一般性设计,如果设计者确信自己表述明确,没有综合歧义发生,则可以省略综合后仿真步骤。**一般情况下,综合后仿真与功能仿真的仿真激励相同**。
综合完成后,如果需要检查综合结果是否与原设计一致,就需要做综合后仿真。在仿真时,把综合生成的标准延时文件反标注到综合仿真模型中去,可估计门延时带来的影响。综合后仿真虽然比功能仿真精确一些,但是**只能估计门延时,不能估计线延时**,仿真结果**与布线后的实际情况还有一定的差距**,并不十分准确。这种仿真的主要目的在于 **{% label prime@检查综合器的综合结果是否与设计输入一致 %}**。目前主流综合工具日益成熟,对于一般性设计,如果设计者确信自己表述明确,没有综合歧义发生,则可以省略综合后仿真步骤。**一般情况下,综合后仿真与功能仿真的仿真激励相同**。
## 3.8. 布局规划与布局布线
@@ -144,4 +153,10 @@ RTL 级综合指 **{% label @将 RTL 级 HDL 语言翻译成由与、或、非
将最终布局规划或布局布线的时延信息反标注到设计网表中,所进行的仿真就叫时序仿真或布局规划与布局布线后仿真,简称后仿真。布局规划与布局布线之后生成的仿真时延文件包含的时延信息最全,不仅包含门延时,还包含实际布线延时,所以时序仿真最准确,能较好地反映芯片的实际工作情况。一般来说,建议进行时序仿真步骤,通过时序仿真能检查设计时序与芯片实际运行情况是否一致,确保设计的可靠性和稳定性。时序仿真的主要目的在于发现时序违规(Timing Violation),即不满足时序约束条件或者器件固有时序规则(建立时间、保持时间等)的情况。
[^1]: 最新的 Verilog HDL标准为 1364-2005。
# 参考文献
EDA 先锋工作室. _轻松成为设计高手——Verilog HDL 实用精解._ 北京航空航天大学出版社, 2012.
[Part 3——描述方式和设计层次的 5. 设计层次]: https://josh-gao.top/posts/fd117896.html#toc.5
[^1]: 最新的 Verilog HDL标准为 [IEEE 1364-2005](https://ieeexplore.ieee.org/document/1620780)。
+9 -2
View File
@@ -19,10 +19,17 @@ date: 2020-11-27 01:15:12
# 语法
`out = awgn(in,snr)`
`out = awgn(in,snr,signalpower)`
---
`out = awgn(in,snr,signalpower,randobject)`
`out = awgn(in,snr,signalpower,seed)`
---
`out = awgn(___,powertype)`
<!-- more -->
@@ -60,7 +67,7 @@ plot(t,[x y])
legend('Original Signal','Signal with AWGN')
```
![ ](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-27-matlab-awgn/2020-11-27-matlab-awgn-010-AddAWGNToSawtoothSignalExample-01.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/14/dissolve/20/gravity/southeast/dx/5/dy/5)
![ ](../images/post/2020-11-27-matlab-awgn/2020-11-27-matlab-awgn-010-AddAWGNToSawtoothSignalExample-01.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/14/dissolve/20/gravity/southeast/dx/5/dy/5)
## AWGN 信道中的常规 QAM 调制<span id="Examples-02"></span>
@@ -101,7 +108,7 @@ grid
hold off
```
![ ](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-27-matlab-awgn/2020-11-27-matlab-awgn-020-GeneralQAMModulationInAnAWGNChannelExample-01.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/fontsize/15/dissolve/60/gravity/southeast/dx/5/dy/5)
![ ](../images/post/2020-11-27-matlab-awgn/2020-11-27-matlab-awgn-020-GeneralQAMModulationInAnAWGNChannelExample-01.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/fontsize/15/dissolve/60/gravity/southeast/dx/5/dy/5)
使用 `genqamdemod` 函数解调接收到的信号。计算误符号数和误符号率。
@@ -245,15 +245,15 @@ busuanzi_count:
添加 Live2D 前的不蒜子显示情况如下。
![添加 Live2D 前单篇博客的不蒜子显示情况](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-27-hexo-next-busuanzi-issues/2020-11-27-hexo-next-busuanzi-issues-010-Live2D-01.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/14/dissolve/20/gravity/southeast/dx/5/dy/5)
![添加 Live2D 前单篇博客的不蒜子显示情况](../images/post/2020-11-27-hexo-next-busuanzi-issues/2020-11-27-hexo-next-busuanzi-issues-010-Live2D-01.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/14/dissolve/20/gravity/southeast/dx/5/dy/5)
![添加 Live2D 前网站的不蒜子显示情况](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-27-hexo-next-busuanzi-issues/2020-11-27-hexo-next-busuanzi-issues-020-Live2D-02.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/14/dissolve/20/gravity/southeast/dx/5/dy/5)
![添加 Live2D 前网站的不蒜子显示情况](../images/post/2020-11-27-hexo-next-busuanzi-issues/2020-11-27-hexo-next-busuanzi-issues-020-Live2D-02.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/14/dissolve/20/gravity/southeast/dx/5/dy/5)
添加 Live2D 后,不蒜子在页面中不显示。
![添加 Live2D 后单篇博客的不蒜子显示情况](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-27-hexo-next-busuanzi-issues/2020-11-27-hexo-next-busuanzi-issues-030-Live2D-03.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/14/dissolve/20/gravity/southeast/dx/5/dy/5)
![添加 Live2D 后单篇博客的不蒜子显示情况](../images/post/2020-11-27-hexo-next-busuanzi-issues/2020-11-27-hexo-next-busuanzi-issues-030-Live2D-03.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/14/dissolve/20/gravity/southeast/dx/5/dy/5)
![添加 Live2D 后网站的不蒜子显示情况](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-27-hexo-next-busuanzi-issues/2020-11-27-hexo-next-busuanzi-issues-040-Live2D-04.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/14/dissolve/20/gravity/southeast/dx/5/dy/5)
![添加 Live2D 后网站的不蒜子显示情况](../images/post/2020-11-27-hexo-next-busuanzi-issues/2020-11-27-hexo-next-busuanzi-issues-040-Live2D-04.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/14/dissolve/20/gravity/southeast/dx/5/dy/5)
### 问题原因
@@ -283,7 +283,7 @@ busuanzi_count:
在网页生成引擎中修改代码,去掉不蒜子部分的 `id` 和 `style` 属性,重新生成网页即可解决该问题。若将 `class` 属性一并删除,会导不蒜子部分和前面的其他显示部分缺少分隔符,如下图。
![ ](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-27-hexo-next-busuanzi-issues/2020-11-27-hexo-next-busuanzi-issues-050-Delimeter-01.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/14/dissolve/20/gravity/southeast/dx/5/dy/5)
![ ](../images/post/2020-11-27-hexo-next-busuanzi-issues/2020-11-27-hexo-next-busuanzi-issues-050-Delimeter-01.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/14/dissolve/20/gravity/southeast/dx/5/dy/5)
具体需要修改两个文件,`next/layout/_third-party/statistics/busuanzi-counter.swig` 中修改的是网页页脚部分的不蒜子显示,`next/layout/_macro/post.swig` 中修改的博客文章阅览数的不蒜子显示。
+234 -184
View File
@@ -1,5 +1,5 @@
---
title: Josh 的学习笔记之 Verilog(Part 2 —— Verilog 语言基础)
title: "Josh's Note — Verilog<br>Part 2 Verilog 语言基础"
date: 2020-11-28 11:42:50
tags:
- Verilog
@@ -20,25 +20,24 @@ toc:
expand_all: true
max_depth: 4
abbrlink: fd2ca242
description: 本文从一个 Verilog 用例出发,对 Verilog 语言的语法进行了阐释。包括的内容主要有 Verilog 语言的基本词法,常用的编译指令,逻辑值、常量、变量的含义,操作符的概念和分类等,还对 Verilog 中的参数、并发以及系统任务和系统函数进行了简要说明。
---
本文从一个 Verilog 用例出发,对 Verilog 语言的语法进行了阐释。包括的内容主要有 Verilog 语言的基本词法,常用的编译指令,逻辑值、常量、变量的含义,操作符的概念和分类等,还对 Verilog 中的参数、并发以及系统任务和系统函数进行了简要说明。
# 1. 两种设计方法(Top-Down 和 Bottom-Up)
在传统意义上,设计硬件电路主要是使用自底向上(Bottom-Up)的设计方法。工程师们总是从最底层的逻辑门开始,逐渐搭建成较大的模块,然后再将这些模块组成更大的模块,最后形成整个设计。
在 [Part 1——初识 HDL 设计方法](https://josh-gao.top/posts/460433dd.html)中已经提到,随着 HDL 和逻辑综合技术的进步,工程师们逐渐可以使用自顶向下(Top-Down)的方法来设计硬件。这样,工程师们**首先关注于设计的规格(Specification),然后将规格分解为一个个模块,再分解为更小的模块**。然后采用 HDL 的可综合子集直接描述硬件的行为,由逻辑综合工具自动完成由 HDL 到门级电路的转换。
在 [Part 1——初识 HDL 设计方法][]中已经提到,随着 HDL 和逻辑综合技术的进步,工程师们逐渐可以使用自顶向下(Top-Down)的方法来设计硬件。这样,工程师们**首先关注于设计的规格(Specification),然后将规格分解为一个个模块,再分解为更小的模块**。然后采用 HDL 的可综合子集直接描述硬件的行为,由逻辑综合工具自动完成由 HDL 到门级电路的转换。
<!-- more -->
最近几年,随着 IP核 市场的逐渐兴起,许多设计者逐渐意识到**利用现有的 IP核 可以帮助节约设计成本、减少设计周期**,有许多设计工程师,甚至希望所有的设计模块都使用现成的模块,自己仅仅开发一些简单的粘合逻辑。这就有点像电路板设计的过程,工程师将各种芯片集成到一块电路板上,自己完成这些芯片间的互连和一些简单的 CPLD 逻辑设计,以及对微处理器的编程。使用现有的 IP 来搭建系统实际上也是一种自底向上(Bottom-Up)的设计方法。
最近几年,随着 IP 核市场的逐渐兴起,许多设计者逐渐意识到**利用现有的 IP 核可以帮助节约设计成本、减少设计周期**,有许多设计工程师,甚至希望所有的设计模块都使用现成的模块,自己仅仅开发一些简单的粘合逻辑。这就有点像电路板设计的过程,工程师将各种芯片集成到一块电路板上,自己完成这些芯片间的互连和一些简单的 CPLD 逻辑设计,以及对微处理器的编程。使用现有的 IP 来搭建系统实际上也是一种**自底向上**(Bottom-Up)的设计方法。
从以上描述可以看出,设计硬件电路时,这两种设计方法都有可能采用。Verilog HDL 可以完全支持这两种设计方法。
- 在门级的设计中,用户可以直接实例化 Verilog 语言中的门级原语构建系统;
- 如果需要描述硬件的行为,可以使用 Verilog 的行为级描述功能;
- 如果要使用 IP核 ,只要在设计中直接实例化 IP核 即可。
- 如果要使用 IP 核,只要在设计中直接实例化 IP 核即可。
EDA 行业的先行者们发明了 Verilog 硬件描述语言,其最根本的目的就是用 Verilog 来描述硬件的行为,但是有的描述是不需要实现为硬件电路的。
@@ -50,26 +49,30 @@ EDA 行业的先行者们发明了 Verilog 硬件描述语言,其最根本的
## 2.1. Verilog 实例
<a name="JoshVerilog模块"></a>首先看一个简单的如下图所示的电路(模块):JoshVerilog。它可以是一个独立的设计,也可以是更大的系统的一个组成部分。
<a id="HelloVlog"></a>
![ ](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-28-josh-verilog-part-2/2020-11-28-josh-verilog-part-2-010-JoshVerilog.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/18/dissolve/20/gravity/southeast/dx/5/dy/5){width=800px}
首先看一个简单的如[图 2-1](#fig.2-1) 所示的电路(模块):`HelloVlog`。它可以是一个独立的设计,也可以是更大的系统的一个组成部分。
<a id="fig.2-1"></a>
![图 2-1 HelloVlog 模块](../images/post/2020-11-28-josh-verilog-part-2/2020-11-28-josh-verilog-part-2-010-JoshVerilog.png){width=800px}
该电路首先在两个 2 位的输入数据 `A_in[1:0]` 的和 `B_in[1:0]` 之间,由 `sel` 信号做二选一。后面是一个 2-4 译码电路,将输入的信号 `result[1:0]`解析成 `eq0`、`eql`、`eq2` 和 `eq3` 这4个信号,它们同时只有一个为 1。
将 `eq0` 和 `eql` 相异或(xor),`eq2` 和 `eq3` 相异或。然后,将两个异或的结果 `A_xor_wire` 和 `XOR_B` 分别寄存输出给 `A_xor_out` 和 `B_xor_out` 两个输出寄存器带有低有效(active low)的异步复位端。
将 `eq0` 和 `eql` 相异或(xor),`eq2` 和 `eq3` 相异或。然后,将两个异或的结果 `A_xor_wire` 和 `XOR_B` 分别寄存输出给 `A_xor_out` 和 `B_xor_out`。两个输出寄存器带有低有效(active low)的异步复位端。
**这些电路单元都是同时并行工作的,相互之间并没有先后顺序关系,这一点与软件设计程序很不一样。**
下面具体分析 [JoshVerilog 模块](#JoshVerilog模块) 的电路功能。源代码如下。
下面具体分析 [HelloVlog 模块](#HelloVlog) 的电路功能,代码如下。
<a name="JoshVerilog代码"></a>
<a id="HelloVlogCode"></a>
```verilog Josh.v
``` verilog HelloVlog.v
// 编译指令, 定义时间单位和时间精度
`timescale 1ns/100p // 每个时间单位是1ns, 仿真精度是100ps
`timescale 1ns / 100ps // 每个时间单位是1ns, 仿真精度是100ps
// module名 + 端口列表
module Josh( clk, rst_n, A_in, B_in, sel, A_xor_out, B_xor_out );
module HelloVlog( clk, rst_n, A_in, B_in, sel, A_xor_out, B_xor_out );
// IO端口声明
input clk;
@@ -141,119 +144,135 @@ endmodule
1. 二选一多路选择器
对于 `MUX21` 这样二选一的电路,将采用如下的数据流描述(assign语句):
对于 `MUX21` 这样二选一的电路,将采用如下的数据流描述(assign语句):
```verilog Josh.v
assign #3 result = sel ? B_in : A_in;
```
``` verilog HelloVlog.v
assign #3 result = sel ? B_in : A_in;
```
`assign` 是 Verilog 中的关键词,用它赋值的语言称为**连续赋值语句**。
`assign` 是 Verilog 中的关键词,用它赋值的语言称为**连续赋值语句**。
如果 `sel`为真(1),则选择 `B_in`,否则将选择 `A_in`,而 `#3` 表示经过 3 个延时单位,再将选择结果赋值给 `result`,这也模拟了组合逻辑的延时。由于在[代码](#JoshVerilog代码)最开头已经使用 Verilog 的编译指令将延时单位定义为 1ns(`timescale 1ns/100ps`),因此这里的 `#3` 代表 3ns 的延时。
如果 `sel`为真(1),则选择 `B_in`,否则将选择 `A_in`,而 `#3` 表示经过 3 个延时单位,再将选择结果赋值给 `result`,这也模拟了组合逻辑的延时。由于在[代码](#HelloVlogCode)最开头已经使用 Verilog 的编译指令将延时单位定义为 1ns(`timescale 1ns/100ps`),因此这里的 `#3` 代表 3ns 的延时。
2. 2 - 4 译码器
关于实现 2 - 4 译码器,则采用了如下的描述:
关于实现 2 - 4 译码器,则采用了如下的描述:
```verilog Josh.v
always @(result) begin
case(result)
2'b00: begin
{eq3, eq2, eq1, eq0} = #2 4'b0001;
$display ("At time %t-", $time, "eq0 = 1");
end
// ...
default: ;
endcase
end
```
``` verilog HelloVlog.v
always @(result) begin
case(result)
2'b00: begin
{eq3, eq2, eq1, eq0} = #2 4'b0001;
$display ("At time %t-", $time, "eq0 = 1");
end
// ...
default: ;
endcase
end
```
这里采用了另一种描述方式:用 `always` 语句来描述电路的行为。通过 `case` 判断 `result` 的值来决定 `eq0`、`eq3` 的值。同样,也采用 `#2` 来模拟组合逻辑的延时。`always` 和 `case` 也是 Verilog 中的关键词。这样的描述方法称之为**行为描述**,它侧重于描述电路的行为。
这里采用了另一种描述方式:用 `always` 语句来描述电路的行为。通过 `case` 判断 `result` 的值来决定 `eq0` ~ `eq3` 的值。同样,也采用 `#2` 来模拟组合逻辑的延时。`always` 和 `case` 也是 Verilog 中的关键词。这样的描述方法称之为**行为描述**,它侧重于描述电路的行为。
```verilog Josh.v
{eq3, eq2, eq1, eq0} = #2 4'b0001;
```
``` verilog HelloVlog.v
{eq3, eq2, eq1, eq0} = #2 4'b0001;
```
该语句表示将 `4'b0001` 赋值给 `eq3~eq0` 合并成的 4 位变量。`{}` 是 Verilog 的合并符号。
该语句表示将 `4'b0001` 赋值给 `eq3` ~ `eq0` 合并成的 4 位变量。`{}` 是 Verilog 的合并符号。
3. 异或门
对于 `A_xor_wire` 和 `XOR_B` 的两个完全一样的异或门,也采用了两种不同的描述方式:
对于 `A_xor_wire` 和 `XOR_B` 的两个完全一样的异或门,也采用了两种不同的描述方式:
```verilog Josh.v
assign #1 A_xor_wire = eq0 ^ eq1;
```
``` verilog HelloVlog.v
assign #1 A_xor_wire = eq0 ^ eq1;
```
和
和
```verilog Josh.v
xor #1 XOR_B(B_xor_wire, eq2, eq3);
```
``` verilog HelloVlog.v
xor #1 XOR_B(B_xor_wire, eq2, eq3);
```
`xor` 是 Verilog 中自带的基本逻辑门原语。这里相当于调用了该 `xor` 门。而 `B_xor_wire`、`eq2` 和 `eq3` 是代入到 `xor` 门中的参数。`eq2` 和 `eq3` 是输入,`B_xor_wire` 是输出。这里 `B_xor_wire` 是 `eq2` 和 `eq3` 相异或的结果。
`xor` 是 Verilog 中自带的基本逻辑门原语。这里相当于调用了该 `xor` 门。而 `B_xor_wire`、`eq2` 和 `eq3` 是代入到 `xor` 门中的参数。`eq2` 和 `eq3` 是输入,`B_xor_wire` 是输出。这里 `B_xor_wire` 是 `eq2` 和 `eq3` 相异或的结果。
在 Verilog 中,**将调用其他功能模块(包括 Verilog 的内嵌基本逻辑门)称为“实例化(lnstantiate)”**。实例化**类似**于软件设计中的调用,但不能简单理解为软件中的调用。软件调用过程是顺序执行的,而实例化的硬件电路在设计中是独立于其他功能块,并行运行的。
在 Verilog 中,**将调用其他功能模块(包括 Verilog 的内嵌基本逻辑门)称为“实例化(Instantiate)”**。实例化**类似**于软件设计中的调用,但不能简单理解为软件中的调用。软件调用过程是顺序执行的,而实例化的硬件电路在设计中是独立于其他功能块,并行运行的。
这种**在模块中实例化其他功能模块**的描述方式被称之为**结构化描述**。
这种**在模块中实例化其他功能模块**的描述方式被称之为**结构化描述**。
## 2.2. 3 种描述方法
## 2.2. 3 种描述方法<a id="toc.2.2"></a>
从以上的描述可以看出 Verilog 语言的 3 种基本的描述方法(基本上所有的 Verilog 功能模块都是由这 3 种方式来描述):
- **数据流描述**:采用 `assign` 语句,该语句被称为连续赋值语句;
- **行为描述**:使用 `always` 或 `initial` 语句块,其中出现的语句被称为过程赋值语句;
- **结构化描述**:实例化已有的功能模块。结构化描述主要有以下3种:
- Module实例化:实例化已有的 module;
- **行为描述**:使用 `always` 或 `initial` 语句块,其中出现的语句被称为过程赋值语句;
- **结构化描述**:实例化已有的功能模块。结构化描述主要有以下 3 种:
- Module 实例化:实例化已有的 module;
- 门实例化:实例化基本的门电路原语;
- 用户定义原语(UDP)实例化:实例化用户定义的原语。
在[《Part 3——描述方式和设计层次》](https://josh-gao.blog.csdn.net/article/details/105262549)中会将详细介绍 Verilog 语言中的这 3 种描述方式。
在 [Part 3——描述方式和设计层次][]中会详细介绍 Verilog 语言中的这 3 种描述方式。
# 3. Verilog 的基本词法
Verilog HDL 是一种**大小写敏感**的语言,这一点与 VHDL 不同,因此在书写的时候要格外注意。在 Verilog 语言中,**所有的关键字(又叫保留字)都为小写**。Verilog 的内部信号名(或称为标识符)使用大写和小写都可以。标识符可以是字母、数字、`$`(美元符号)和 `_`(下划线)任意组合,只要**第一个字符是字母或者下划线**即可。
1. Verilog HDL 是一种**大小写敏感**的语言,这一点与 VHDL 不同,因此在书写的时候要格外注意。在 Verilog 语言中,**所有的关键字(又叫保留字)都为小写**。Verilog 的内部信号名(或称为标识符)使用大写和小写都可以。标识符可以是字母、数字、`$`(美元符号)和 `_`(下划线)任意组合,只要**第一个字符是字母或者下划线**即可。
> 因为 Verilog HDL 对大小写敏感,因此养成良好的信号定义习惯非常重要,否则容易因为大小写不同造成信号的歧义。推荐的信号定义习惯为:**所有信号和网线名均小写,用下划线分割单词,而宏变量全部用大写字母。**
{% note warning %}
在上述[代码](#JoshVerilog代码)中,用双反斜线 `//` 表示注释。另外,还有一种注释方式,用 `/* ...... */` 来表示。所不同的是前者为单行注释,而后者将 `/*` 和 `*/` 之间的内容全部看作注释内容。
因为 Verilog HDL 对大小写敏感,因此养成良好的信号定义习惯非常重要,否则容易因为大小写不同造成信号的歧义。推荐的信号定义习惯为:**所有信号和网线名均小写,用下划线分割单词,而宏变量全部用大写字母。**
> 通常,注释的内容只是作者为了增强代码的可读性而增加的内容,对整个代码的功能没有任何影响。不过,在一些工具中,尤其是逻辑综合工具,定义了一些特殊的指令,用于控制工具编译过程。这些指令也是以注释的方式出现的。例如:
>
> ```verilog
> moduleblbox(out, data, clk) /* synthesis syn_black_box */;
> ```
>
> 在 `modulebl_box` 的声明处有一行注释,用 `/* ...... */` 表示。它看起来是一个注释,实际上,是综合工具Synplify中的一个指令,指示 Synplify 将该模块看作一个黑盒(black_box),不处理模块内部的描述。
{% endnote %}
在 Verilog 中,通常使用空格符、跳格符和换行符作为间隔。在书写代码的时候,适当运用间隔符可以提高代码的可读性。比如在声明 4 个 `reg` 型数据 `eq0~eq3` 时,可以采用上述[例子](#JoshVerilog代码)中的方法:
2. 在上述[代码](#HelloVlogCode)中,用双反斜线 `//` 表示注释。另外,还有一种注释方式,用 `/* ...... */` 来表示。所不同的是前者为单行注释,而后者将 `/*` 和 `*/` 之间的内容全部看作注释内容。
```verilog Josh.v
reg eq0, eq1, eq2, eq3;
```
{% note info %}
也可以用换行符将其分开:
通常,注释的内容只是作者为了增强代码的可读性而增加的内容,对整个代码的功能没有任何影响。不过,在一些工具中,尤其是逻辑综合工具,定义了一些特殊的指令,用于控制工具编译过程。这些指令也是以注释的方式出现的。例如:
```verilog
reg eq0;
reg eq1;
reg eq2;
reg eq3;
```
``` verilog
module bl_box(out, data, clk) /* synthesis syn_black_box */;
```
在verilog中,还有一些转义字符。比如 `\n` 表示换行符;`\t` 表示 Tab 键;防止引起歧义,就用 `\` 表示 `\` 符号本身等等。这里不再对 Verilog 的词法做过多的描述,更多可以参考 Verilog IEEE 国际标准([IEEE Std. 1364-2005](https://standards.ieee.org/standard/1364-2005.html))。
在 `module bl_box` 的声明处有一行注释,用 `/* ...... */` 表示。它看起来是一个注释,实际上,是综合工具 Synplify 中的一个指令,指示 Synplify 将该模块看作一个黑盒(black_box),不处理模块内部的描述。
{% endnote %}
3. 在 Verilog 中,通常使用空格符、跳格符和换行符作为间隔。在书写代码的时候,适当运用间隔符可以提高代码的可读性。比如在声明 4 个 `reg` 型数据 `eq0~eq3` 时,可以采用上述[例子](#HelloVlogCode)中的方法:
``` verilog HelloVlog.v
reg eq0, eq1, eq2, eq3;
```
也可以用换行符将其分开:
``` verilog
reg eq0;
reg eq1;
reg eq2;
reg eq3;
```
4. 在verilog中,还有一些转义字符。比如 `\n` 表示换行符;`\t` 表示 Tab 键;防止引起歧义,就用 `\` 表示 `\` 符号本身等等。这里不再对 Verilog 的词法做过多的描述,更多可以参考 Verilog IEEE 国际标准([IEEE Std. 1364-2005][])。
# 4. 模块和端口
大型设计往往是由一个个模块构成的。实际上,模块可大可小,大到一个复杂的微处理器系统,小到一个基本的晶体管,都可以作为一个模块来设计。例如,在上述代码中描述的 [JoshVerilog](#JoshVerilog代码) 就是一个模块。
大型设计往往是由一个个模块构成的。实际上,模块可大可小,大到一个复杂的微处理器系统,小到一个基本的晶体管,都可以作为一个模块来设计。例如,在上述代码中描述的 [HelloVlog](#HelloVlogCode) 就是一个模块。
在 Verilog 中,模块(module)是基本的组成单位。
> 通常,建议在一个 Verilog 文件中,只放一个 `module` 定义,而且使文件名称和 `module` 名称一致。这是一个良好的设计习惯。
{% note info %}
通常,建议在一个 Verilog 文件中,只放一个 `module` 定义,而且使文件名称和 `module` 名称一致。这是一个良好的设计习惯。
{% endnote %}
以下是 Verilog 中 `module` 的基本语法:
```verilog
``` verilog
module 模块名称( 端口列表 );
// 声明:
reg, parameter,
@@ -265,7 +284,7 @@ module 模块名称( 端口列表 );
module 实例化
门实例化
用户定义原语 (UDP) 实例化
连续赋值 (Continous assignment)
连续赋值 (Continuous assignment)
endmodule
```
@@ -275,9 +294,9 @@ endmodule
有些 `module` 也不包含端口。例如,在仿真平台的顶层模块中,其内部已经实例化了所有的设计模块和激励模块,是一个封闭的系统,没有输入和输出。一般这种没有端口的模块都是用于仿真的,不用作实际电路。
在 `module` 内部的声明部分,需要声明端口的方向,(`input`, `output` 和 `inout`)和位宽。按照 Verilog 的习惯,**高位写在左边,低位写在右边**。比如
在 `module` 内部的声明部分,需要声明端口的方向(`input`, `output` 和 `inout`)和位宽。按照 Verilog 的习惯,**高位写在左边,低位写在右边**。比如
```verilog
``` verilog
input [1:0] A_in;
```
@@ -297,12 +316,16 @@ input [1:0] A_in;
- `always` 语句;
- 其他子 `module` 实例化;
- 门实例化;
- 用户定义原语(UDP)实例化;
- 连续赋值(Continous assignment)。
- 用户定义原语(User-Defined Primitive, UDP)实例化;
- 连续赋值(Continuous assignment)。
Verilog 中所有的功能描述都是通过以上几种描述方式进行的。
> 需要格外注意的是,以上几种语句如果出现在同一个 `module` 内,其**相互之间是没有任何顺序关系的**,它们在 `module` 中出现顺序的改变不会改变 `module` 的功能,这正是硬件的一大特点。有硬件电路原理图设计经验的读者们可以想象一下画原理图的过程,先画哪个,后画哪个器件根本没有任何关系。在 Verilog 中也是类似的道理。
{% note warning %}
需要格外注意的是,以上几种语句如果出现在同一个 `module` 内,其**相互之间是没有任何顺序关系的**,它们在 `module` 中出现顺序的改变不会改变 `module` 的功能,这正是硬件的一大特点。有硬件电路原理图设计经验的读者们可以想象一下画原理图的过程,先画哪个,后画哪个器件根本没有任何关系。在 Verilog 中也是类似的道理。
{% endnote %}
# 5. 编译指令
@@ -316,27 +339,27 @@ Verilog 中的编译指令是从 C 语言中的“预处理指令”演变得来
- `` `include``;
- `` `resetall``。
与 C 语言中使用的 `#` 不同,Verilog 中使用反引号一来标识编译指令。编译器一旦遇到某个编译指令,则其在整个编译过程中有效,可以包含多个文件,直到编译器遇到另一个相同的编译指令。
与 C 语言中使用的 `#` 不同,Verilog 中使用反引号“`` ` ``”来标识编译指令。编译器一旦遇到某个编译指令,则其在整个编译过程中有效,可以包含多个文件,直到编译器遇到另一个相同的编译指令。
## 5.1. `` `timescale``
在每一个 `module` 文件前面加上`` ` ``的编译指令,就可以保证该文件中的延时信息受其自身文件中的 `` `timescale`` 编译指令指导。**否则在编译过程中,该模块将沿用上一个** `` `timescale`` **的值,或者使用缺省值**。
在每一个 `module` 文件前面加上 `` ` `` 的编译指令,就可以保证该文件中的延时信息受其自身文件中的 `` `timescale`` 编译指令指导。**否则在编译过程中,该模块将沿用上一个** `` `timescale`` **的值,或者使用缺省值**。
在上述实例代码中描述的 [JoshVerilog](#JoshVerilog代码) 模块中使用了一个`` `timescale 1ns/100ps`` 编译指令。其中 `1ns` 表示延时单位,`100ps` 表示时间精度,也就是编译器所能接收的最小仿真时间粒度。`` `timescale`` 编译指令在模块外部出现,并且影响后面模块中所有的时延值,直到遇到下一个 `` `timescale`` 或 `` `resetall``指令。
在上述实例代码描述的 [HelloVlog](#HelloVlogCode) 模块中使用了一个`` `timescale 1ns/100ps`` 编译指令。其中 `1ns` 表示延时单位,`100ps` 表示时间精度,也就是编译器所能接收的最小仿真时间粒度。`` `timescale`` 编译指令在模块外部出现,并且影响后面模块中所有的时延值,直到遇到下一个 `` `timescale`` 或 `` `resetall`` 指令。
比如语句:
```verilog
assign #1.16 A_xor_wire = eq0 ^ eq1;
``` verilog
assign #(1.16) A_xor_wire = eq0 ^ eq1;
```
如果采用 `` `timescale 1ns/100ps`` 编译指令由于延时单位是 `1ns`,同时最小时间粒度是 `100ps`,即 `0.1ns` ,那么根据四舍五入的规则,`1.16ns` 则实际上对应 `1.2ns` 延时。如果采用 `` `timescale 1ns/10ps`` 编译指令,由于延时单位是 `1ns`,同时最小时间粒度是 `10ps`,即 `0.01ns`,那么 `1.16ns` 则实际上对应 `1.16ns` 延时。
## 5.2. `` `define`` 和 `` `undef``
`` `define`` 用于定义宏。例如,首先定义一个总线宽度的宏为 16,然后利用这个宏定义一个宽度为 16 的 `reg`类型数据 `Data`,方法如下:
`` `define`` 用于定义宏。例如,首先定义一个总线宽度的宏为 16,然后利用这个宏定义一个宽度为 16 的 `reg` 类型数据 `Data`,方法如下:
```verilog
``` verilog
`define BUS_WIDTH 16
// ...
reg [`BUS_WIDTH - 1 : 0] Data
@@ -346,7 +369,7 @@ reg [`BUS_WIDTH - 1 : 0] Data
`` `define`` 指令被编译以后,则在整个编译过程中都有效,直到遇到 `` `undef`` 指令,该宏就不再有效。如下:
```verilog
``` verilog
`undef BUS_WIDTH
```
@@ -356,11 +379,11 @@ reg [`BUS_WIDTH - 1 : 0] Data
再来看看如下的条件编译指令:
```verilog
``` verilog
`ifdef NARROW
parameter BUS_WIDTH = 16;
`else
paramete rBUS_WIDTH = 32;
parameter BUS_WIDTH = 32;
`endif
```
@@ -370,7 +393,7 @@ reg [`BUS_WIDTH - 1 : 0] Data
在 Verilog 中,可以使用 `` `include`` 指令来嵌入某个文件的内容。例如:
```verilog
``` verilog
`include "HEADFILE.h"
```
@@ -380,26 +403,35 @@ reg [`BUS_WIDTH - 1 : 0] Data
`` `resetall`` 编译指令会将所有其他编译指令重新设置为缺省值,要谨慎使用。
> Verilog 语言中的编译指令不止这几条,其他不常用的指令这里不一一介绍,有兴趣可以参考其他文献。
{% note info %}
Verilog 语言中的编译指令不止这几条,其他不常用的指令这里不一一介绍,有兴趣可以参考其他文献。
{% endnote %}
# 6. 逻辑值与常量
## 6.1. 逻辑值
在二进制计数中,单位逻辑值只有 `1` 和 `0` 两种状态。而在 Verilog 语言中,为了对电路进行精确建模,于是增加了两种逻辑状态 `X` 和 `Z`。
在二进制计数中,单位逻辑值只有 `1` 和 `0` 两种状态。而在 Verilog 语言中,为了对电路进行精确建模,增加了两种逻辑状态 `X` 和 `Z`。
- `X` 表示未知值(unknown),或者不关心(don't care),`X` 用作信号状态时表示未知,用在条件判断时(在 `casex` 或 `casez`中)表示不关心;
- `Z` 表示高阻状态,也就是**没有任何驱动**,通常用来对**三态总线**进行建模。
在后面将提到 Verilog 语言中的变量类型。通常 `net` 型变量如果没有初始化,其值为 `Z`,`register` 型变量如果没有初始化,其值为 `X` 。这一点在仿真时显得比较有意义。
在[第 7 节](#toc.7)将提到 Verilog 语言中的变量类型。通常 `net` 型变量如果没有初始化,其值为 `Z`,`register` 型变量如果没有初始化,其值为 `X` 。这一点在仿真时显得比较有意义。
> 但是,对综合工具而言(或者说在实际电路中),并没有什么 `X` 值,只存在 `0`、`1` 和 `Z` 这 3 种状态。在实际电路中还可能出现亚稳态,它既不是 `0`,也不是 `1`,是一种暂时的不稳定状态。
{% note warning %}
但是,对综合工具而言(或者说在实际电路中),并没有什么 `X` 值,只存在 `0`、`1` 和 `Z` 这 3 种状态。在实际电路中还可能出现亚稳态,它既不是 `0`,也不是 `1`,是一种暂时的不稳定状态。
{% endnote %}
Verilog 语言中所有数据都是由以上描述的 4 种基本的逻辑值 `0`、`1`、`X` 和 `Z` 构成。同时,`X` 和 `Z` 是不区分大小写的。例如:`0z1x` 和 `0Z1X` 表示同一个数据。
## 6.2. 常量
常量是 Verilog 中不变的数值。在上述[实例代码](#JoshVerilog代码)中,`4'b0001` 就表示一个 4 位的二进制整型常量:0001。
常量是 Verilog 中不变的数值。在上述[实例代码](#HelloVlogCode)中,`4'b0001` 就表示一个 4 位的二进制整型常量:0001。
Verilog中的常量有3种:
@@ -416,18 +448,18 @@ Verilog中的常量有3种:
整数型常量也可以采用基数表示法,例如:
- `8'haa`:表示 8 位的**十六进制数**,换算成二进制是 1010_1010。
- `6'o33`:表示 6 位的**八进制数**,换算成二进制是 011_011。
- `4'b1011`:表示 4 位的**二进制数** 1011。
- `3'd7`:表示 3 位**十进制**的 7。
- `8'haa`:表示 8 位的**十六进制数**,换算成二进制是 `1010_1010`。
- `6'o33`:表示 6 位的**八进制数**,换算成二进制是 `011_011`。
- `4'b1011`:表示 4 位的**二进制数** `1011`。
- `3'd7`:表示 3 位**十进制**的 `7`。
在基数表示法中,都是以如下格式写的:
```verilog
``` verilog
[长度]'数值符号 数字
```
其中长度可有可无,数值符号中,`h` 表示十六进制,`o` 表示八进制,`b` 表示二进制,`d` 表示十进制数据。如果长度比后面数字的实际位数多,则**自动在数字的左边补足 0**;如果位数少,则**自动截断数字左边超出的位数**。
其中**长度可有可无**,数值符号中,`h` 表示十六进制,`o` 表示八进制,`b` 表示二进制,`d` 表示十进制数据。如果长度比后面数字的实际位数多,则**{% label primary @自动在数字的左边补足 0 %}**;如果位数少,则**{% label primary @自动截断数字左边超出的位数 %}**。
如果将数字写成 `'haa`,那么这个十六进制数的长度就决定于数字本身的长度。
@@ -439,23 +471,23 @@ Verilog中的常量有3种:
Verilog 语言中的实数型变量可以采用十进制,也可以采用科学计数法,例如:
```verilog
``` verilog
5.512
13_2.18e2 // 表示13218
```
### 6.2.3. 字符串型常量
字符串是双引号中的字符序列,例如:`"HeIIo World"`。字符串是 8 位 ASCII 码值的序列,`"HeIIo World"` 就需要 11 字节存储,方法如下:
字符串是双引号中的字符序列,例如:`"Hello World"`。字符串是 8 位 ASCII 码值的序列,`"Hello World"` 就需要 11 字节存储,方法如下:
```verilog
reg[1:8 * 11] Message;
Message = "HeIIo World";
``` verilog
reg [1:8 * 11] Message;
Message = "Hello World";
```
这样就将字符串常量存入到 Message 变量中。
这样就将字符串常量存入到 `Message` 变量中。
# 7. 变量类型
# 7. 变量类型<a id="toc.7"></a>
在 Verilog 语言中,有两大变量类型:
@@ -464,9 +496,13 @@ Message = "HeIIo World";
对于初学者而言,则需要首先遵守如下的简单规则:
{% note primary %}
- **凡是在** `always` **或** `initial` **语句中赋值的变量,一定是寄存器变量**;
- **在** `assign` **中赋值的一定是线网变量**。
{% endnote %}
## 7.1. 线网类型
在线网类型下,分为几种子类,它们具有线网的共性:
@@ -475,14 +511,14 @@ Message = "HeIIo World";
- `wor`、`trior`:表示该连线具有“线或”功能;
- `wand`、`triand`:表示该连线具有“线与”功能;
- `trireg`:表示该连线具有总线保持功能;
- `tri1`、`tri0`:表示当无驱动时,连线状态为1(`tri1`)和0(`tri0`);
- `tri1`、`tri0`:表示当无驱动时,连线状态为 1(`tri1`)或 0(`tri0`);
- `supply1`、`supply0`:分别表示电源和地信号。
在以上描述的线网类型中,除了 `trireg` 未初始化时为 `X` 以外,其余的未初始化时的值为 `Z`。
线网类型主要用在连续赋值语句中,以及作为模块之间的互连信号。
在后面的内容中会详细阐述常用线网类型的使用方法。
在 [Part 3——描述方式和设计层次][]中会详细阐述常用线网类型的使用方法。
## 7.2. 寄存器类型
@@ -499,14 +535,14 @@ Message = "HeIIo World";
`reg` 类型可以定位为一个寄存器,可以定义一位或者多位,例如:
```verilog
``` verilog
reg AB; // 定义一个名为 AB 的 1 位寄存器
reg [3:0] ABC; // 定义一个名为 ABC 的 4 位寄存器
```
在多位寄存器中,可以作“位选择”或“部分选择”,例如:
```verilog
``` verilog
ABC [3] = 1; // 将 ABC 的第 3 位赋值为 1
ABC [0] = 0; // 将 ABC 的第 0 位赋为 0
ABC [2:1] = 2'b01; // 将 ABC 的第 1、2 位赋值为 1 和 0
@@ -518,25 +554,25 @@ Message = "HeIIo World";
`reg` 类型可以作为二维数组,也就是存储器,例如:
```verilog
``` verilog
reg [3:0] MEMABC [0:7]; // 定义一个存储器,地址为 0~7,每个存储单元是 4 位
```
与一维的 `reg` 变量不同的是,存储器中的存储单元不能再做位选择或部分选择,而每个单元可以单独赋值。比如:
```verilog
``` verilog
MEMABC[1] = 4'b0101; // 为 MEMABC 中的第 1 个存储单元赋值 4'b0101
```
同时,在 Verilog 中,不存可以对整个存储器赋值的语句,必须对每个单元独立赋值。除非使用 `$readmemb` 或 `$readmemh` 系统任务从文件中读入整个或者部分存储器的数据。
同时,在 Verilog 中,**不存可以对整个存储器赋值的语句**,必须对每个单元独立赋值。除非使用 `$readmemb` 或 `$readmemh` 系统任务从文件中读入整个或者部分存储器的数据。
[comment]: <> (在第7章将讨论如何从文件中读入数据给存储器赋值。)
> 在 [Part 7—— 逻辑验证与 testbench 编写][]中将讨论如何从文件中读入数据给存储器赋值。
### 7.2.2. `integer` 类型
`integer` 变量通常用于高层次建模,也常用在 `for` 语句的索引中,例如:
```verilog
``` verilog
initial
begin: ACCESS
integer i;
@@ -553,59 +589,63 @@ end
这里需要引起重视,**“线网"变量可以理解为电路模块中的连线,但“寄存器"并不严格对应于电路上的存储单元**,包括触发器(flip-flop)或锁存器(latch)。从纯粹语言表达的语义角度来说,寄存器类型变量的值,从一个赋值到下一个赋值被保存下来,并且在仿真过程中会保持而不会丢失。
实际上,从语义上来讲,在 Verilog 仿真工具对语言进行仿真的时候,**寄存器类型的变量是占用仿真环境的物理内存的**,这与 C 语言中的变量类似。寄存器在被赋值后,便一直保存在内存中,保持该值不变,直到再次对该寄存器变量进行赋值。而**线网类型是不占用仿内存的**,它的值是由当前所有驱动该线网的其他变量(可以是寄存器或线网)决定的。这是寄存器和线网最大的区别,也是当初 Verilog 的发明者定义“线网”和“寄存器”变量的根本动机。
实际上,从语义上来讲,在 Verilog 仿真工具对语言进行仿真的时候,**寄存器类型的变量是占用仿真环境的物理内存的**,这与 C 语言中的变量类似。寄存器在被赋值后,便一直保存在内存中,保持该值不变,直到再次对该寄存器变量进行赋值。而**线网类型是不占用仿真内存的**,它的值是由当前所有驱动该线网的其他变量(可以是寄存器或线网)决定的。这是寄存器和线网最大的区别,也是当初 Verilog 的发明者定义“线网”和“寄存器”变量的根本动机。
在下一小节中,将引入“驱动”和“赋值”两个概念,深入探讨两种变量的含义。
## 7.4. 驱动和赋值
## 7.4. 驱动和赋值<a id="toc.7.4"></a>
为了更清楚地描述寄存器和线网变量的概念,将以上述[实例代码](#JoshVerilog代码)中的语句来说明。首先,引入Verilog 语言中两个重要的概念:驱动(Driving)和赋值(Assigning)。
为了更清楚地描述寄存器和线网变量的概念,将以上述[实例代码](#HelloVlogCode)中的语句来说明。首先,引入 Verilog 语言中两个重要的概念:驱动(Driving)和赋值(Assigning)。
{% note primary %}
- **线网是被驱动的,该值不被保持,在任意一个仿真步进上都需要重新计算**;
- **寄存器是被赋值的,且该值在仿真过程中被保持,直到下一个赋值的出现**。
在上述[实例代码](#JoshVerilog代码)中,定义了一个 `A_xor_wire` 的 `wire`,它是 `eq0` 和 `eq1` 相异或的结果。采用如下描述方式:
{% endnote %}
```verilog
在上述[实例代码](#HelloVlogCode)中,定义了一个 `A_xor_wire` 的 `wire`,它是 `eq0` 和 `eq1` 相异或的结果。采用如下描述方式:
``` verilog
assign #1 A_xor_wire = eq0 ^ eq1;
```
实际上,也可以采用如下的另一种描述方式:
```verilog
``` verilog
always @(eq0 or eq1)
A_xor_wire = #1 eq0 ^ eq1;
```
当然需要在 `module` 的声明处,将 `A_xor_wire` 首先定义成 `reg` 变量,而不是 `wire` 变量,即需要做如下定义:
```verilog
``` verilog
reg A_xor_wire
```
这两者描述的目的一样,都是一个异或门,如下图所示。
这两者描述的目的一样,都是一个异或门,如[图 2-2](#fig.2-2) 所示。
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-28-josh-verilog-part-2/2020-11-28-josh-verilog-part-2-020-XORGate.png!700px"/>
</div>
<a id="fig.2-2"></a>
![图 2-2 异或门](../images/post/2020-11-28-josh-verilog-part-2/2020-11-28-josh-verilog-part-2-020-XORGate.png){width=700px}
下面从语义上的角度探讨两种描述方式的不同。
第一种描述方式使用 `assign` 语句,Verilog 中将其称为连续赋值语句(Continously Assignment)实际上是**连续驱动**的过程。也就是说,在任意一个仿真时刻,当前时刻 `eq0` 和 `eq1` 相异或的结果决定了 `1ns` 以后(语句 `#1` 的延时控制)的线网变量 `A_xor_wire` 的值,**不管 `eq0` 和 `eq1` 变化与否,这个驱动过程一直存在**,因此称为连续驱动。(在仿真器中,线网变量是不占用仿真内存空间的。)如上[异或门图](#异或门)中的时序所示,这个驱动过程在任意时刻都存在。
第一种描述方式使用 `assign` 语句,Verilog 中将其称为连续赋值语句(Continuously Assignment),实际上是**连续驱动**的过程。也就是说,在任意一个仿真时刻,当前时刻 `eq0` 和 `eq1` 相异或的结果决定了 `1ns` 以后(语句 `#1` 的延时控制)的线网变量 `A_xor_wire` 的值,**不管 `eq0` 和 `eq1` 变化与否,这个驱动过程一直存在**,因此称为连续驱动。(在仿真器中,线网变量是不占用仿真内存空间的。)如上[图 2-2](#fig.2-2) 中的时序所示,这个驱动过程在任意时刻都存在。
在第二种描述方式中使用了 `always` 语句,后面紧跟着一个敏感列表:`@(eq0 or eq1)` 因此,这个语句只有在 `eq0` 或 `eq1` 发生变化时才会执行。如上[异或门图](#异或门)中,在时刻 2、3 和 6,该语句都将执行,将 `eq0` 和 `eq1` 赋值的结果延时 1ns 以后赋值给 `A_xor_wire` 变量。**在其他时刻,`A_xor_wire` 变量必须保持**。因此,**从仿真语义上讲,需要一个存储单元,也可以说是寄存器,来保存 `A_xor_wire` 变量的中间值**。这就是Verilog 语言的“寄存器类型”变量的来历,而这个 `A_xor_wire` 变量首先需要定义为 `reg` 类型。
在第二种描述方式中使用了 `always` 语句,后面紧跟着一个敏感列表:`@(eq0 or eq1)` 因此,这个语句只有在 `eq0` 或 `eq1` 发生变化时才会执行。如[图 2-2](#fig.2-2) 中,在时刻 2、3 和 6,该语句都将执行,将 `eq0` 和 `eq1` 赋值的结果延时 1ns 以后赋值给 `A_xor_wire` 变量。**在其他时刻,`A_xor_wire` 变量必须保持**。因此,**从仿真语义上讲,需要一个存储单元,也可以说是寄存器,来保存 `A_xor_wire` 变量的中间值**。这就是 Verilog 语言的“寄存器类型”变量的来历,而这个 `A_xor_wire` 变量首先需要定义为 `reg` 类型。
不管采用哪种方式,所描述的是一样的组合逻辑电路。尤其是第二种描述,虽然其在语言中被定义为 reg 型,但并不是对应硬件上的触发器(flip-flop),而是 Verilog 语言仿真语义上的寄存器概念。
不管采用哪种方式,所描述的是一样的组合逻辑电路。尤其是第二种描述,虽然其在语言中被定义为 `reg` 型,但并不是对应硬件上的触发器(flip-flop),而是 Verilog 语言仿真语义上的寄存器概念。
但是,在对实际电路中D触发器建模的时候,必须采用 `reg` 型的变量。下图是 D 触发器的模型。
但是,在对实际电路中 D 触发器建模的时候,必须采用 `reg` 型的变量。[图 2-3](#fig.2-3) 是 D 触发器的模型。
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-11-28-josh-verilog-part-2/2020-11-28-josh-verilog-part-2-030-DFlipFlop.png!300px"/>
</div>
<a id="fig.2-3"></a>
在上述[实例代码](#JoshVerilog代码)中相应的描述如下:
![图 2-3 D 触发器模型](../images/post/2020-11-28-josh-verilog-part-2/2020-11-28-josh-verilog-part-2-030-DFlipFlop.png){width=300px}
```verilog Josh.v
在上述[实例代码](#HelloVlogCode)中相应的描述如下:
``` verilog HelloVlog.v
always @(posedge clk or negedge rst_n)
if (~rst_n)
A_xor_out <= 0;
@@ -613,7 +653,7 @@ always @(posedge clk or negedge rst_n)
A_xor_out <= A_xor_wire;
```
D 触发器只对时钟和复位(置位)敏感,因此在敏感列表中,列出了 `clk` 的上升沿和 `rst_n` 的下降沿。如果 `rst_n` 为 0,就对触发器的输出复位,否则在 `clk` 的时钟上升沿发生的时候,将输入的 `A_xor_wire` 寄存到触发器的输出端 `A_xor_out`。
D 触发器**只对时钟和复位(置位)敏感**,因此在敏感列表中,列出了 `clk` 的上升沿和 `rst_n` 的下降沿。如果 `rst_n` 为 0,就对触发器的输出复位,否则在 `clk` 的时钟上升沿发生的时候,将输入的 `A_xor_wire` 寄存到触发器的输出端 `A_xor_out`。
这样的代码精确地描述了一个 D 触发器的行为。这里的 `reg` 变量就对应了硬件中的 D 触发器。
@@ -623,7 +663,7 @@ D 触发器只对时钟和复位(置位)敏感,因此在敏感列表中,
参数是一种常量,通常出现在 `module` 内部。它常常被用作定义状态机的状态、数据位宽和延时大小等等。例如:
```verilog
``` verilog
parameter and_delay = 2;
parameter xor_delay = 4;
```
@@ -632,7 +672,7 @@ parameter xor_delay = 4;
前面介绍的 `` `define`` 是一种全局的定义,而 `parameter` 是出现在模块内部的**局部定义**,而且可以被**灵活改变**,这是 `parameter` 的一个重要特征。
在[《Part 3——描述方式和设计层次》的 4.2 小节](https://josh-gao.blog.csdn.net/article/details/105262549#42__865)中会详细探讨改变模块参数的方法。
在 [Part 3——描述方式和设计层次的 4.2 参数][]小节会详细探讨改变模块参数的方法。
# 9. Verilog 中的并发与顺序
@@ -640,14 +680,14 @@ parameter xor_delay = 4;
与在处理器上运行的软件不同的是,**硬件电路之间的工作是并行的**。
为了描述硬件的并行性,Verilog 语言本身就具有并发的特性。在 Verilog 语言的 `module` 中,所有的描述语句(包括连续赋值语句,行为语句块:`always` 和 `initial`,模块实例化等)之间都是并行发生的。任何功能描述语句,在 Verilog 的 module 中的顺序都不重要。
为了描述硬件的并行性,Verilog 语言本身就具有并发的特性。在 Verilog 语言的 `module` 中,所有的描述语句(包括连续赋值语句,行为语句块:`always` 和 `initial`,模块实例化等)之间都是并行发生的。任何功能描述语句,在 Verilog 的 `module` 中的顺序都不重要。
但是,在语句块(`always` 和 `initial`)内部,则可以存在两种语句组:
- `begin ... end`:顺序语句组;
- `fork ... join`:并行语句组。
在 `begin ... end` 中存在的语句,按照 Veilog 的语义,应该是顺序执行的。而在 `fork ... join` 中的语句,则是并行执行的。
在 `begin ... end` 中存在的语句,按照 Verilog 的语义,应该是顺序执行的。而在 `fork ... join` 中的语句,则是并行执行的。
相比较顺序运行的事物,并行的事物比较难以理解和建模。同时,用于仿真的计算机是串行执行的,而 Verilog 语言本身的语义是用计算机进行模拟的语义,是用一种串行的语义来模拟并行的硬件。
@@ -655,14 +695,14 @@ Verilog 仿真器用来模拟硬件的并行行为的方式类似于软件中的
后续将会重点介绍 Verilog 语言中的这一并行特性,同时阐述 Verilog 的高级仿真原理,希望能帮助大家领会 Verilog 的语义精髓。
# 10. 操作数、操作符和表达式
# 10. 操作数、操作符和表达式<a id="toc.10"></a>
## 10.1. 操作符
操作符是操作数之间的运算符号。在介绍操作数之前,先来看看 Verilog 中的各种操作符。
| 操作符 | 含义 | 操作符 | 含义 |
| :-- | :-- | :-- | :-- |
| :--: | :----: | :--: | :----: |
| `+` | 一元加 | `>>` | 右移 |
| `-` | 一元减 | `<` | 小于 |
| `!` | 一元逻辑非 | `<=` | 小于等于 |
@@ -671,13 +711,13 @@ Verilog 仿真器用来模拟硬件的并行行为的方式类似于软件中的
| `~&` | 归约与非 | `==` | 逻辑相等 |
| `^` | 归约异或 | `!=` | 逻辑不等 |
| `^~` 或 `~^`| 归约异或非 | `===` | 全等 |
| <code>&#124;</code> | 归约或 | `!==` | 非全等 |
| <code>~&#124;</code> | 归约或非 | `&` | 按位与 |
| `\|` | 归约或 | `!==` | 非全等 |
| `~\|` | 归约或非 | `&` | 按位与 |
| `*` | 乘 | `^` | 按位异或 |
| `/` | 除以 | `^~` 或 `~^` | 按位异或非 |
| `%` | 取模 | <code>&#124;</code> | 按位或 |
| `%` | 取模 | `\|` | 按位或 |
| `+` | 二元加 | `&&` | 逻辑与 |
| `-` | 二元减 | <code>&#124;>&#124;</code> | 逻辑或 |
| `-` | 二元减 | `\|\|` | 逻辑或 |
| `<<` | 左移 | `? :` | 条件操作符 |
其中,一元操作表示仅有一个操作数,二元操作表示有两个操作数。归约操作也是只有一个操作数,它是该操作数中的所有位之间的计算。
@@ -685,7 +725,7 @@ Verilog 仿真器用来模拟硬件的并行行为的方式类似于软件中的
### 10.1.1. 算术操作符
| 操作符 | 表达式 | 说明
| :--: | :--: | :--: |
| :--: | :--: | :------: |
| `+` | `m + n` | 将 `n` 与 `m` 相加 |
| `-` | `m - n` | 将 `m` 减去 `n` |
| `-` | `-m` | 将 `m` 取反(二进制补码)|
@@ -696,7 +736,7 @@ Verilog 仿真器用来模拟硬件的并行行为的方式类似于软件中的
### 10.1.2. 按位操作符
| 操作符 | 表达式 | 说明
| :--: | :--: | :--: |
| :--: | :--: | :------: |
| `~` | `~m` | 将 `m` 的每个位取反 |
| `&` | `m & n` | 将 `m` 的每个位与 `n` 的相应位相与
| <code>&#124;</code> | <code>m &#124; n</code> | 将 `m` 的每个位与 `n` 的相应位相或
@@ -706,7 +746,7 @@ Verilog 仿真器用来模拟硬件的并行行为的方式类似于软件中的
### 10.1.3. 归约操作符
| 操作符 | 表达式 | 说明
| :--: | :--: | :--: |
| :--: | :--: | :------: |
| `&` | `&m` | 将 `m` 中的所有位相与(1位结果) |
| `~&` | `~&m` | 将 `m` 中的所有位相与非(1位结果) |
| <code>&#124;</code> | <code>&#124;m</code> | 将 `m` 中的所有位相或(1位结果) |
@@ -717,7 +757,7 @@ Verilog 仿真器用来模拟硬件的并行行为的方式类似于软件中的
### 10.1.4. 逻辑操作符
| 操作符 | 表达式 | 说明
| :--: | :--: | :--: |
| :--: | :--: | :------: |
| `!` | `!m` | `m` 是否不为真?(1 位 真/假结果) |
| `&&` | `m && n` | `m` 和 `n` 是否都为真?(1位 真/假结果) |
| <code>&#124;&#124;</code> | <code>m &#124;&#124; n</code> | `m` 或 `n` 是否为真?(1位 真/假结果) |
@@ -725,7 +765,7 @@ Verilog 仿真器用来模拟硬件的并行行为的方式类似于软件中的
### 10.1.5. 相等操作符
| 操作符 | 表达式 | 说明
| :--: | :--: | :--: |
| :--: | :--: | :------: |
| `==` | `m == n` | `m` 和 `n` 相等吗?(1 位 正确/错误结果) |
| `!=` | `m != n` | `m` 和 `n` 不等吗?(1 位 正确/错误结果) |
> 相等操作符仅比较逻辑 1 和 0。
@@ -733,14 +773,14 @@ Verilog 仿真器用来模拟硬件的并行行为的方式类似于软件中的
### 10.1.6. 全等操作符
| 操作符 | 表达式 | 说明
| :--: | :--: | :--: |
| :--: | :--: | :------: |
| `===` | `m === n` | `m` 和 `n` 全等吗?(1 位 正确/错误结果) |
| `!==` | `m !== n` | `m` 和 `n` 不全等吗?(1 位 正确/错误结果) |
### 10.1.7. 关系操作符
| 操作符 | 表达式 | 说明
| :--: | :--: | :--: |
| :--: | :--: | :------: |
| `<` | `m < n` | `m` 小于 `n` ?(1 位 正确/错误结果) |
| `>` | `m > n` | `m` 大于 `n` ?(1 位 正确/错误结果) |
| `<=` | `m <= n` | `m` 小于等于 `n` ?(1 位 正确/错误结果) |
@@ -749,20 +789,20 @@ Verilog 仿真器用来模拟硬件的并行行为的方式类似于软件中的
### 10.1.8. 逻辑移位操作符
| 操作符 | 表达式 | 说明
| :--: | :--: | :--: |
| :--: | :--: | :------: |
| `<<` | `m << n` | 将 `m` 左移 `n` 位 |
| `>>` | `m >> n` | 将 `m` 右移 `n` 位 |
### 10.1.9. 条件操作符
| 操作符 | 表达式 | 说明
| :--: | :--: | :--: |
| :--: | :--: | :------: |
| `? :` | `sel ? m : n` | 如果 `sel` 为真,选择 `m`,否则选择 `n` |
### 10.1.10. 连接复制操作符
| 操作符 | 表达式 | 说明
| :--: | :--: | :--: |
| :--: | :--: | :------: |
| `{ }` | `{m,n}` | 将 `m` 和 `n` 连接起来,产生更大的向量 |
| `{{ }}` | `{n{m}}` | 将 `m` 重复 `n` 次 |
@@ -778,9 +818,9 @@ Verilog 仿真器用来模拟硬件的并行行为的方式类似于软件中的
| `==`、`!=`、`===`、`!==` | $\vdots$
| `&`、`~&` | $\vdots$
| `^`、`~^`| $\vdots$
| <code>&#124;</code>、<code>~&#124;</code>| $\vdots$
| `\|`、`~\|` | $\vdots$
| `&&` | $\vdots$
| <code>&#124;&#124;</code>| $\vdots$
| `\|\|` | $\vdots$
| `? :` | 最低优先级
> 例如:`A + B & C + D` 就表示 `(A + B) & (C + D)`,而不是 `A + (B & C) + D`。
@@ -809,7 +849,7 @@ Verilog 仿真器用来模拟硬件的并行行为的方式类似于软件中的
- 存储器单元;
- 系统函数或用户自定义函数调用的返回值。
在选择操作数时,需要用户尤其注意的是操作数的极性。通常在 Verilog 中,无符号数用以下3种形式存在:
在选择操作数时,需要用户尤其注意的是**操作数的极性**。通常在 Verilog 中,无符号数用以下 3 种形式存在:
- 线网变量;
- 一般寄存器变量;
@@ -826,21 +866,25 @@ Verilog 仿真器用来模拟硬件的并行行为的方式类似于软件中的
这里定义两个变量,一个是无符号的 `reg` 型,另一个是有符号的整型:
```verilog
``` verilog
reg [4:0] Opreg; // 一个 5 位的 reg 型,存储无符号数
integer Opint; // 一个 32 位的 integer 型,存储有符号数
```
做如下运算:
```verilog
Opreg = -4d'12/4; // Opreg 被赋值 29,(-4d'12/4)的最低5位
``` verilog
Opreg = -4d'12/4; // Opreg 被赋值 29,(-4d'12/4) 的最低5位
Opint = -4d'12/4; // Opint 被赋值为 1073741821,共 32 位
Opreg = -12/4; // Opreg 被赋值29,(-12/4)的最低5位
Opreg = -12/4; // Opreg 被赋值29,(-12/4) 的最低5位
Opint = -12/4; // Opint 被赋值为 -3,采用 32 位的二进制补码表示方式
```
通过以上的计算结果可以看出,无符号数和有符号数的算术运算非常不同,用户在设计常量和变量并用它们计算的时候,一定要搞清楚它们中哪些表示有符号数,哪些表示无符号数,这很重要。
{% note warning %}
通过以上的计算结果可以看出,**无符号数和有符号数的算术运算非常不同**,用户在设计常量和变量并用它们计算的时候,一定要搞清楚它们中哪些表示有符号数,哪些表示无符号数,这很重要。
{% endnote %}
# 11. 系统任务和系统函数
@@ -852,7 +896,7 @@ Opint = -12/4; // Opint 被赋值为 -3,采用 32 位的二进制
- 拟控制任务(simulation control task);
- 时序验证任务(timing check task);
- PLA建模任务(PLA modeling task);
- 机建模任务(stochastic modeling task);
- 随机建模任务(stochastic modeling task);
- 实数变换函数(conversion functions for real);
- 概率分布数(probabilistic distribution function)。
@@ -862,17 +906,17 @@ Opint = -12/4; // Opint 被赋值为 -3,采用 32 位的二进制
`$display` 是显示任务,通常用来显示变量值、字符串,以及仿真时间等信息。
在 [JoshVerilog 模块](#JoshVerilog代码)中使用了这样的系统任务。
在 [HelloVlog 模块](#HelloVlogCode)中使用了这样的系统任务。
```verilog Josh.v
``` verilog HelloVlog.v
$display ("At time %t-", $time, "eq0 = 1"); // 显示时间
```
其中,双引号中的是字符串,`%t` 是时间格式。`$time` 是产生模拟时间的系统函数,它的返回值显示在字符串中的 `%t` 位置。
其中,双引号中的是字符串,`%t` 是时间格式。`$time` 是产生模拟时间的系统函数,它的返回值显示在字符串中的 `%t` 位置。
再如:
```verilog
``` verilog
$display("The value of ABC is %d", ABC); // 显示当前 ABC 变量的值
```
@@ -882,8 +926,8 @@ $display("The value of ABC is %d", ABC); // 显示当前 ABC 变量的值
系统函数 `$fopen` 用于打开一个文件,并返回一个整数的文件指针。然后,`$fdisplay` 就可以使用这个文件指针向文件中写入信息。写完后,则可以使用 `$fclose` 这个系统关闭这个文件。例如:
```verilog
integer Write_Out_File; // 定义一个文件指针
``` verilog
integer Write_Out_File; // 定义一个文件指针
Write_Out_File = $fopen("Write_Out_File.txt");
$fdisplay(Write_Out_File, "@ %h\n%h", Mpi_addr, Data_in);
$fclose(Write_Out_File);
@@ -893,16 +937,16 @@ $fclose(Write_Out_File);
用户可以通过 `$readmemb` 或者 `$readmemh` 来从文件中读入数据,但是这个文件中的数据格式是一定的。例如:
```verilog
``` verilog
reg [7:0] DataSource [0:47];
$readmemh ("Read_In_File.txt, DataSource);
$readmemh ("Read_In_File.txt", DataSource);
```
就是将 `Read_In_FiIe` 文件中数据读入到 `DataSource` 数组中,然后就可以直接使用。
`Read_In_File` 数据文件的格式,可以参考如下写法:
```verilog
``` verilog
@2f
24
@2e
@@ -935,6 +979,12 @@ $readmemh ("Read_In_File.txt, DataSource);
除了系统任务和系统函数之外,VeriIog还允许用户自己定义任务和函数。关于自定义的任务和函数的特点及使用方法,请参考后续的相关内容。
---
# 参考文献
在本篇笔记中,以一个实例为出发点,系统介绍了 Verilog 的基本语法,相信能为大家深入学习 Verilog 语言打下坚实的基础。
EDA 先锋工作室. *轻松成为设计高手——Verilog HDL 实用精解.* 北京航空航天大学出版社, 2012.
[Part 1——初识 HDL 设计方法]: https://josh-gao.top/posts/460433dd.html
[Part 3——描述方式和设计层次]: https://josh-gao.top/posts/fd117896.html
[IEEE Std. 1364-2005]: https://standards.ieee.org/standard/1364-2005.html
[Part 7—— 逻辑验证与 testbench 编写]: https://josh-gao.top/posts/e060f513.html
[Part 3——描述方式和设计层次的 4.2 参数]: https://josh-gao.top/posts/fd117896.html#toc.4.2
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+259 -249
View File
@@ -1,5 +1,5 @@
---
title: Josh 的学习笔记之 Verilog(Part 5 —— RTL 设计与编码指导)
title: "Josh's Note — Verilog<br>Part 5 RTL 设计与编码指导"
mathjax: true
comments: true
copyright: true
@@ -22,10 +22,9 @@ categories:
- [Josh 的学习笔记, Verilog]
abbrlink: 53b8b42e
date: 2020-12-05 00:46:00
description: 在<a href="https://josh-gao.top/posts/ecb88422.html">《Part 4 —— RTL 概念与常用 RTL 建模》</a>中,通过具体的 RTL 建模建立了一些对 RTL 级描述的一些感性认识,本文将较深入地探讨一些 RTL 设计的基本规律。RTL 设计规律与方法是一个非常大的论题,在此不可能面面俱到,希望通过本文的介绍,引起大家的注意。如果大家能在日后的工作实践中,不断积累,有意识地积累基本设计原则、设计思想,将取得事半功倍的效果!
---
在[《Part 4 —— RTL 概念与常用 RTL 建模》](https://josh-gao.top/posts/ecb88422.html)中,通过具体的 RTL 建模建立了一些对 RTL 级描述的一些感性认识,本文将较深入地探讨一些 RTL 设计的基本规律。RTL 设计规律与方法是一个非常大的论题,在此不可能面面俱到,希望通过本文的介绍,引起大家的注意。如果大家能在日后的工作实践中,不断积累,有意识地积累基本设计原则、设计思想,将取得事半功倍的效果!
# 1. 一般性指导原则
RTL 级设计的评判标准有很多,如时序性能、所占面积、可测试性、可重要性、功耗、时钟域的分配、复位信号设计、是否与所用 EDA 工具匹配等。如果设计目标是在 FPGA 或 CPLD 等可编程逻辑器件上实现,则还需考虑是否能发挥这些 PLD 的结构特点等。根据以上所述这些目标的组合和优先级可以派生出很多不同的设计原则。这里仅仅讨论一般意义的指导原则。
@@ -38,11 +37,11 @@ RTL 级设计的评判标准有很多,如时序性能、所占面积、可测
2. **硬件原则**
硬件原则重点在于提醒读者转化软件设计的思路,理解 HDL 语言设计的本质。
硬件原则重点在于转化软件设计的思路,理解 HDL 语言设计的本质。
3. **系统原则**
系统原则希望读者能够通过全局、整体上把握设计,从而提高设计质址,优化设计效果。
系统原则希望能够通过全局、整体上把握设计,从而提高设计质址,优化设计效果。
4. **同步设计原则**
@@ -50,49 +49,58 @@ RTL 级设计的评判标准有很多,如时序性能、所占面积、可测
<!-- more -->
## 1.1 面积和速度的平衡与互换原则
## 1.1. 面积和速度的平衡与互换原则
这里“面积”是指一个设计所消耗的目标器件(如 FPGA/CPLD/ASIC 等)的硬件资源数量:
- 对于 FPGA,可以用所消耗的触发器(FF)和查找表(LUT)来衡扯;
- 对于 FPGA,可以用所消耗的触发器(FF)和查找表(LUT)来衡量;
- 对于 CPLD,常用宏单元(MC)衡量;
- 对于 ASIC 可以用设计的系统门衡量。
“速度”指设计在芯片上稳定运行时所能够达到的最高频率,这个频率由设计的时序状况决定,与设计满足的时钟周期、PAD to PAD Time、Clock Setup Time、Clock Hold Time 和 Clock-to-Output Delay 等众多时序特征量密切相关。
{% note %}
{% note info %}
面积(Area)和速度(Speed)这两个指标贯穿着 RTL 设计的始终,是设计质量评价的终极标准。
{% endnote %}
这里就讨论一下设计中关于面积和速度的基本原则:{% label primary @面积和速度的平衡与互换 %}。
面积和速度是一对对立统一的矛盾体。要求一个设计同时具备设计面积最小,运行频率最高,这是不现实的。科学的设计目标应该是在满足设计时序要求(包含对设计最高频率的要求)的前提下,占用最小的芯片面积,或者在所规定的面积下,使设计的时序余量更大、频率更高。这两种目标充分体现了面积和速度的平衡思想。关于面积和速度的要求,不应该简单地理解为工程师水平的提高和设计完美性的追求,而应该认识到它们是和产品的质量、成本直接相关的。**如果设计的时序余量比较大,运行的频率比较高,则意味着设计的健壮性更强,整个系统的质量更有保证;另一方面,设计所消耗的面积更小,则意味着在单位芯片上实现的功能模块更多,需要的芯片数量更少,整个系统的成本也随之大幅度削减。**
面积和速度是一对对立统一的矛盾体。要求一个设计同时具备设计面积最小,运行频率最高,这是不现实的。科学的设计目标应该是:
- 在满足设计时序要求(包含对设计最高频率的要求)的前提下,占用最小的芯片面积;
- 或者在所规定的面积下,使设计的时序余量更大、频率更高。
这两种目标充分体现了面积和速度的平衡思想。关于面积和速度的要求,不应该简单地理解为工程师水平的提高和设计完美性的追求,而应该认识到它们是和产品的质量、成本直接相关的。
- **如果设计的时序余量比较大,运行的频率比较高,则意味着设计的健壮性更强,整个系统的质量更有保证;**
- **另一方面,设计所消耗的面积更小,则意味着在单位芯片上实现的功能模块更多,需要的芯片数量更少,整个系统的成本也随之大幅度削减。**
作为矛盾的两个组成部分,面积和速度的地位是不一样的。相比之下,满足时序、工作频率的要求更重要一些,当两者冲突时,采用**速度优先**的准则。
面积和速度的互换是 RTL 设计的一个重要思想。从理论上讲,一个设计如果时序余量较大,所能跑的频率远远高于设计要求,那么就能通过功能模块复用减少整个设计消耗的芯片面积,这就是**用速度的优势换面积的节约**;反之,如果一个设计的时序要求很高,普通方法达不到设计频率,那么一般可以通过将数据流串/并转换,并行复制多个操作模块,对整个设计采取“乒乓操作”和“串/并转换”的思想进行处理,在芯片输出模块处再对数据进行“并/串转换”。从宏观上看,整个芯片满足了处理速度的要求,这相当于**用面积复制换取速度的提高**。面积和速度互换的具体操技巧很多,比如模块复用、“乒乓操作”、“串/并转换”等,需要在工作中不断积累。下面举例说明如何使用“速度换面积”和“面积换速度”。
### 1.1.1 “用速度的优势换面积的节约”举例
### 1.1.1. “用速度的优势换面积的节约”举例
WCDMA(宽带码分多址)系统中使用到了快速哈达码(Fast Hadamard Transform, FHT)运算, FHT 由 4 步相同的算法完成,如[图 5-1](#图5-1) 所示。
WCDMA(宽带码分多址)系统中使用到了快速哈达码(Fast Hadamard Transform, FHT)运算, FHT 由 4 步相同的算法完成,如[图 5-1](#fig.5-1) 所示。
<a name="图5-1"></a>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-010-FastHadamardTransform.png!sign" alt="FHT 原理图"/>
</div>
<a id="fig.5-1"></a>
![图 5-1 FHT 原理图](../images/post/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-010-FastHadamardTransform.png){width=1000px}
FHT 单步算法如下:
$$
\begin{aligned}
\begin{align}
&\mathrm{Out}[2i]=\mathrm{In}[2i] + \mathrm{In}[2i+8],&i=0\sim7\\
&\mathrm{Out}[2i+1]=\mathrm{In}[2i+1] - \mathrm{In}[2i+1+8],&i=0\sim7
\end{aligned}
\end{align}
$$
考虑流水线式数据处理的要求,最自然的设计方法就是设计不同端口宽度的 4 个单步 FHT,并用将这 4 个单步模块串联起来,从而完成数据流的流水线处理。该 FHT 实现方式的代码如下:
```verilog fhtpart.v
``` verilog fhtpart.v
/******************************
该模块是 FHT 的顶层,调用 4 个不同端口宽度的单步 FHT 模块,完成整个 FHT 算法
******************************/
@@ -175,7 +183,7 @@ endmodule
单步 FHT 运算举例如下(仅举例第 1 步的模块):
```verilog fht_unit1.v
``` verilog fht_unit1.v
/******************************
第 1 次 FHT 单步运算
******************************/
@@ -246,16 +254,15 @@ end
endmodule
```
评估一下系统的流水线时间余量后,发现整个流水线有 16 个时钟周期,而 FHT 模块的频率很高,加法本身仅消耗 1 个时钟周期,加上数据的选择和分配所消耗时间,也完全能满足系统频率要求,所以**将单步 FHT 运算复用 4 次**,就能大幅度节约所消耗的资源。这种复用单步算法的FHT 实现框图如[图 5-2](#图5-2) 所示,由输入选择寄存、单步FHT 模块、输出选择寄存和计数器构成。
评估一下系统的流水线时间余量后,发现整个流水线有 16 个时钟周期,而 FHT 模块的频率很高,加法本身仅消耗 1 个时钟周期,加上数据的选择和分配所消耗时间,也完全能满足系统频率要求,所以**将单步 FHT 运算复用 4 次**,就能大幅度节约所消耗的资源。这种复用单步算法的FHT 实现框图如[图 5-2](#fig.5-2) 所示,由输入选择寄存、单步FHT 模块、输出选择寄存和计数器构成。
<a name="图5-2"></a>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-020-FHTOperationReuseStructureDiagram.png!sign" width="500px" alt="FHT 运算复用结构图"/>
</div>
<a id="fig.5-2"></a>
![图 5-2 FHT 运算复用结构图](../images/post/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-020-FHTOperationReuseStructureDiagram.png){width=600px}
代码如下:
```verilog wch_fht.v
``` verilog wch_fht.v
/******************************
优化后的 FHT 运算
******************************/
@@ -362,36 +369,33 @@ end
endmodule
```
为了便于对比两种实现方式的资源消耗,在 Synplify Pro 中对两种实现方法分别做了综合。两次综合选用的参数都完全一致,所以仅考察设计所消耗的寄存器和逻辑资源,选 中Disable I/O In sertion 选项,不插入 I/O,取消 Synplify Pro 中诸如 FSM Compiler、FSM Explorer、Resource Sharing、Retiming、Pipelining等综合优化选项。两次综合的结果如[图 5-3](#图5-3) 和[图 5-4](#图5-4) 所示。
为了便于对比两种实现方式的资源消耗,在 Synplify Pro 中对两种实现方法分别做了综合。两次综合选用的参数都完全一致,所以仅考察设计所消耗的寄存器和逻辑资源,选中 Disable I/O Insertion 选项,不插入 I/O,取消 Synplify Pro 中诸如 FSM Compiler、FSM Explorer、Resource Sharing、Retiming、Pipelining等综合优化选项。两次综合的结果如[图 5-3](#fig.5-3) 和[图 5-4](#fig.5-4) 所示。
<a name="图5-3"></a>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-030-FHTPARTResource.bmp!sign" alt="未采用复用方案的“fhtpart”模块综合所消耗的资源"/>
</div>
<a id="fig.5-3"></a>
<a name="图5-4"></a>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-040-WCHFHTResource.bmp!sign" alt="采用复用方案的“wch_fht”模块综合所消耗的资源"/>
</div>
![图 5-3 未采用复用方案的 `fhtpart` 模块综合所消耗的资源](../images/post/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-030-FHTPARTResource.bmp)
通过对比可以清晰地观察到,采用复用实现方案所占面积约为原方案的 1/4,而得到这个好处的代价是,完成整个 FHT 运算的周期为原来的 4 倍。这个例子通过运算周期的加长,换取了消耗芯片面积的减少,是前面所述的用频率换面积的一种体现。本例所述“频率换面积”的前提是,FHT 模块频率较高,运算周期的余量较大,采用4 步复用后.仍然能够满足系统流水线设计的要求。其实,如果流水线时序允许,FHT 运算甚至可以采用 1 bit 串行方案实现,该方案所消耗的芯片面积资源更少!
<a id="fig.5-4"></a>
### 1.1.2 “用面积复制换取速度的提高”举例
![图 5-4 采用复用方案的 `wch_fht` 模块综合所消耗的资源](../images/post/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-040-WCHFHTResource.bmp)
通过对比可以清晰地观察到,采用复用实现方案所占面积约为原方案的 1/4,而得到这个好处的代价是,完成整个 FHT 运算的周期为原来的 4 倍。这个例子通过运算周期的加长,换取了消耗芯片面积的减少,是前面所述的用频率换面积的一种体现。本例所述“频率换面积”的前提是,FHT 模块频率较高,运算周期的余量较大,采用 4 步复用后,仍然能够满足系统流水线设计的要求。其实,如果流水线时序允许,FHT 运算甚至可以采用 1 bit 串行方案实现,该方案所消耗的芯片面积资源更少!
### 1.1.2. “用面积复制换取速度的提高”举例
举一个通过复制模块,并行处理达到高处理带宽的例子(可实际应用于无线系统、有线接入、路由器、视频系统等)。假设输入数据流的速率是 800 Mbit/s,而 FPGA 上设计的数据处理模块的处理速度最大为 200 Mbit/s,由于处理模块的数据吞吐量满足不了要求,直接在 FPGA 上实现这个设计是一个“impossible mission”!
这种情况下。就应该利用“面积换速度”的思想,至少复制 4 个处理模块,**首先将输入数据进行串/并转换**,然后利用这 4 个模块并行处理分配的数据,**最后将处理结果并/串变换**,完成数据速率的要求。在整个处理模块的两端看,数据速率仍然是 800 Mbit/s,而在 FPGA 的内部看,每个子模块处理的数据速率仅为 200 Mbit/s,其实整个数据的吞吐扯的保障是依赖于 4 个子模块并行处理完成的,也就是说利用了占用更多的芯片面积,实现了高速处理,通过使用“面积的复制换取处理速度的提高”的思想实现了设计。设计的示意框图如[图 5-5](#图5-5) 所示。
这种情况下。就应该利用“面积换速度”的思想,至少复制 4 个处理模块,**首先将输入数据进行串/并转换**,然后利用这 4 个模块并行处理分配的数据,**最后将处理结果并/串变换**,完成数据速率的要求。在整个处理模块的两端看,数据速率仍然是 800 Mbit/s,而在 FPGA 的内部看,每个子模块处理的数据速率仅为 200 Mbit/s,其实整个数据的吞吐量的保障是依赖于 4 个子模块并行处理完成的,也就是说利用了占用更多的芯片面积,实现了高速处理,通过使用“面积的复制换取处理速度的提高”的思想实现了设计。设计的示意框图如[图 5-5](#fig.5-5) 所示。
<a name="图5-5"></a>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-050-MoreAreaforSpeed.png!sign" width="700px" alt="“面积换速度”示意图"/>
</div>
<a id="fig.5-5"></a>
“面积复制换取速度提高”或者说“面积复制换取数据吞吐量的提高”是目前 FPGA 设计的常用技巧之一。现代高速FPGA 基本都有 DDR/DDR2/DDR3 的 I/O 硬件电路,通过这种 I/O 硬件电路,可以实现输入数据流的 1:2 和 1:4 的串/并变换和并/串变换,很多中高端 FPGA 在 I/O BANK 附近还专门设计了硬件的 DLL 或PLL,配合 DDR/DDR2/DDR3 的 I/O 硬件电路完成对应的采样时钟的降速和倍速。调用这些 I/O 的硬件模块,可以方便、可靠地实现数据流的并行化(输入端)和串行化(输出端),从而更利于实现“面积复制换取速度提高”,或“面积复制换取数据吞吐量的提高”的设计思想。
![图 5-3 “面积换速度”示意图](../images/post/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-050-MoreAreaforSpeed.png){width=700px}
上面仅仅是对“面积换速度“思想的一个简单的举例,其实具体操作过程中还涉及很多的方法和技巧,例如,对高速数据流进行串/并转换,采用“乒乓操作”方法提高数据处理速率等。希望读者通过平时的应用进一步积累经验。
“面积复制换取速度提高”或者说“面积复制换取数据吞吐量的提高”是目前 FPGA 设计的常用技巧之一。现代高速FPGA 基本都有 DDR/DDR2/DDR3 的 I/O 硬件电路,通过这种 I/O 硬件电路,可以实现输入数据流的 1:2 和 1:4 的串/并变换和并/串变换,很多中高端 FPGA 在 I/O BANK 附近还专门设计了硬件的 DLL 或 PLL,配合 DDR/DDR2/DDR3 的 I/O 硬件电路完成对应的采样时钟的降速和倍速。调用这些 I/O 的硬件模块,可以方便、可靠地实现数据流的并行化(输入端)和串行化(输出端),从而更利于实现“面积复制换取速度提高”,或“面积复制换取数据吞吐量的提高”的设计思想。
## 1.2 硬件原则
上面仅仅是对“面积换速度“思想的一个简单的举例,其实具体操作过程中还涉及很多的方法和技巧,例如,对高速数据流进行串/并转换,采用“乒乓操作”方法提高数据处理速率等。希望大家通过平时的应用进一步积累经验。
## 1.2. 硬件原则
硬件原则主要针对 HDL 代码编写而言。首先应该明确 FPGA/CPLD、ASIC 的逻辑设计所采用的硬件描述语言(HDL) 同软件语言(如 C、C++ 等)是有本质区别的!以 Verilog 语言为例,虽然 Verilog 很多语法规则和 C 语言相似,但是 Verilog 作为硬件描述语言,它的本质作用在于描述硬件,应该认识到 Verilog 是采用了 C 语言形式的硬件的抽象,它的**最终实现结果是芯片内部的实际电路**。
@@ -401,11 +405,11 @@ endmodule
前面已经讨论过 HDL 语言与 C 语言等软件语言相比的最显著区别在于:HDL 语言便于描述“互联”、”并发”、”时间”这 3 个硬件设计的基本概念。
- **互连(connectivity)**: 互连是硬件电路的一个基本要素,在 C 语言中,并没有直接可以用来表示模块间互连的变扯;而 HDL 的网线型变最则专为模块互连而设计,描述电路连接清晰明确。如 Verilog 的 `wire` 型变量配合一些驱动结构就能有效地描述各个模块直接的端口与网线连接关系。
- **互连(connectivity)**: 互连是硬件电路的一个基本要素,在 C 语言中,并没有直接可以用来表示模块间互连的变量;而 HDL 的网线型变最则专为模块互连而设计,描述电路连接清晰明确。如 Verilog 的 `wire` 型变量配合一些驱动结构就能有效地描述各个模块直接的端口与网线连接关系。
- **并发(concurrency)** : C 语言天生是**串行**的,不能描述硬件之间并发的特性, C 语言编译后.其机器指令在 CPU 的高速缓冲队列中基本是顺序执行;而 Verilog 可以有效地描述并行的硬件系统,硬件系统比软件系统速度快、实时性高的一个重要原因就是硬件系统中**各个单元的运算是独立的,信号流是并行的**。所以在使用 HDL 建模时,应该充分理解硬件系统的并行处理特点,合理安排数据流的时序,提高整个设计的效率。
- **并发(concurrency)** : C 语言天生是**串行**的,不能描述硬件之间并发的特性, C 语言编译后,其机器指令在 CPU 的高速缓冲队列中基本是顺序执行;而 Verilog 可以有效地描述并行的硬件系统,硬件系统比软件系统速度快、实时性高的一个重要原因就是硬件系统中**各个单元的运算是独立的,信号流是并行的**。所以在使用 HDL 建模时,应该充分理解硬件系统的并行处理特点,合理安排数据流的时序,提高整个设计的效率。
- **时间(time)**:C 程序运行的时候,没有一个严格的时间概念,程序运行的时间长短,取决于处理器本身的性能;而 HDL 语言定义了绝对和相对的时间度量,在仿真时可以通过时间度扯与周期关系描述信号直接的时间关系。
- **时间(time)**:C 程序运行的时候,没有一个严格的时间概念,程序运行的时间长短,取决于处理器本身的性能;而 HDL 语言定义了绝对和相对的时间度量,在仿真时可以通过时间度量与周期关系描述信号直接的时间关系。
Verilog 作为一种 HDL 语言,对系统行为的建模方式是分层次的。比较重要的层次有系统级(System)、算法级(Algorithm)、寄存器传输级(RTL)、逻辑级(Logic)、门级(Gate)和电路开关级(Switch)等。系统级和算法级与 C 语言更相似,可用的语法和表现形式也更丰富。自 RTL 级以后,HDL 语言的功能就越来越侧重于硬件电路的描述,可用的语法和表现形式的局限性也越大。相比之下, C 语言与系统级和算法级 Verilog 描述更相近一些,而与 RTL 级、Gate 级、Switch 级描述从描述目标和表现形式上都有较大的差异。
@@ -413,15 +417,14 @@ Verilog 作为一种 HDL 语言,对系统行为的建模方式是分层次的
在C 语言的描述中,为了使代码执行效率高,表述简洁,经常用到下面的 `for` 循环语句:
```c
for (i = O; i < l6; i++)
``` c
for (i = O; i < 16; i++)
DoSomething();
```
但是在实际工作中,除了描述仿真测试激励(testbench)时使用 `for` 循环语句外,RTL 级编码中**必须要慎用 `for` 循环**。其原因是 **`for` 循环会被综合器展开为所有变量情况的执行语句,每个变量独立占用寄存器资源,有些情况下不能有效地复用硬件逻辑资源,造成资源浪费**。在 RTL 硬件描述中,遇到类似算法,常用的方式是先搞清楚设计的时序要求,做一个 `reg` 型计数器,在每个时钟沿累加,并在每个时钟沿判断
计数器情况,做相应的处理,能复用的处理模块尽量复用,即使所有操作不易复用,也可以采用 `case` 语句展开描述。代码如下:
但是在实际工作中,除了描述仿真测试激励(testbench)时使用 `for` 循环语句外,RTL 级编码中**必须要慎用 `for` 循环**。其原因是 **`for` 循环会被综合器展开为所有变量情况的执行语句,每个变量独立占用寄存器资源,有些情况下不能有效地复用硬件逻辑资源,造成资源浪费**。在 RTL 硬件描述中,遇到类似算法,常用的方式是先搞清楚设计的时序要求,做一个 `reg` 型计数器,在每个时钟沿累加,并在每个时钟沿判断计数器情况,做相应的处理,能复用的处理模块尽量复用,即使所有操作不易复用,也可以采用 `case` 语句展开描述。代码如下:
```verilog
``` verilog
reg [3:0] counter;
always @(posedge clk)
@@ -442,14 +445,14 @@ end
另外,在 C 描述中有 `if ... else` 和 `switch` 条件判断语句,其语法如下:
```c
``` c
if (flag) // 表示flag为真
...
else
...
```
```c
``` c
switch (variable) {
case value1: ...; break;
case value2: ...; break;
@@ -462,7 +465,7 @@ switch (variable) {
对应 Verilog 也有 `if ... else` 语句和 `case` 语句,`if` 语句的语法相似,`case` 语句的语法如下:
```verilog
``` verilog
case (var)
var_value1: ...;
var_value2: ...;
@@ -470,56 +473,54 @@ case (var)
default: ...;
```
通过 [《Part 4 —— RTL 概念与常用 RTL 建模》的 3.10 小节](https://josh-gao.top/posts/ecb88422.html#3-10-%E7%94%A8-case-%E5%92%8C-if-else-%E5%BB%BA%E6%A8%A1)的学习,我们会发现 `case` 语句和 `if ... else if ... else if ...` 语句以及 `if ... if ... if ...` 语句建模时可以建立无优先级和带有优先级的判断结构,使用 HDL 语言建模时,关键在于其综合实现结果的硬件结构。
通过 [Part 4——RTL 概念与常用 RTL 建模的 3.10 用 `case` 和 `if ... else` 建模][]的学习,我们会发现 `case` 语句和 `if ... else if ... else if ...` 语句以及 `if ... if ... if ...` 语句建模时可以建立无优先级和带有优先级的判断结构,使用 HDL 语言建模时,关键在于其综合实现结果的硬件结构。
这里进一步引申讨论一下 Verilog 的 `for` 循环。前面讲过 Verilog 语言是分层次的,即使同一个语法关键字在不同的应用层次也有不同的理解,for 循环就是一个非常好的例子。
- `for` 循环在行为级描述测试激励时的应用:前面介绍过,推荐使用 Behavior 级方式描述测试激励,在描述测试激励时,推荐使用 `for` 循环。好处主要有两个,一是描述简单,代码清晰;二是仿真器会对 `for` 循环开放一片内存,提供代码执行效率,加快仿真进程。
- `for` 循环在行为级描述测试激励时的应用:前面介绍过,推荐使用 Behavior 级方式描述测试激励,在描述测试激励时,推荐使用 `for` 循环。好处主要有两个,一是描述简单,代码清晰;二是仿真器会对 `for` 循环开放一片内存,提高代码执行效率,加快仿真进程。
[comment]:<> (如7. 2. 1 小节就论述了如何使用for 语句实现遍历测试。)
<!-- [comment]:<> (如7. 2. 1 小节就论述了如何使用for 语句实现遍历测试。) -->
- `for` 循环在 RTL 级描述硬件电路时的应用:在 RTL 级描述硬件时,一定要慎用 `for` 循环。前面已经介绍过,`for` 循环在硬件实现时会被综合器展开,不利于硬件资源复用,如果应用不当,还会造成资源浪费。但是任何问题不是绝对的,如果用户非常清晰 `for` 循环会被综合器展开这一基本原则,则可以逆向思维,对某些硬件上无法复用的展开结构抽象为 `for` 循环描述,大大提高代码的可读性。
[comment]:<> (例如8. 6. 2" 案例分析“小节就分别列举了使用展开结构和使用for 循环语句对某"冒泡排序“寻找最小值电路的建模方法,请读者仔细琢磨。)
<!-- [comment]:<> (例如8. 6. 2" 案例分析“小节就分别列举了使用展开结构和使用for 循环语句对某"冒泡排序“寻找最小值电路的建模方法,请读者仔细琢磨。) -->
## 1.3 系统原则
## 1.3. 系统原则
系统原则包含两个层次的含义:一是实现的目标器件本身可以看作一个系统,需要充分有效地发挥该系统的每个单元的功效。如果设计的实现目标为 FPGA,因为当代 FPGA 内嵌了很多固有的硬件资源(如:可编程输入/输出单元、基本可编程逻辑单元、嵌入式块 RAM 、丰富的布线资源、底层嵌入功能单元和内嵌专用硬核等),如何合理地使用这些硬件资源,对设计的全局有个宏观上的合理安排,比如合理安排时钟域、模块复用、约束、面积和速度等问题就显得至关重要。如果实现目标是 SoC,则需要分析什么样的算法和功能适合放在硬件系统里面实现,什么样的算法和功能适合放在微处理器系统(如 DSP、CPU 等)里面实现,并进一步合理划分软硬件之间的数据交换。
从更高层面上看,对于任何一个硬件系统,如何进行模块划分与任务分配,什么样的算法和功能适合放在可编程逻辑器件或 ASIC 里面实现,什么样的算法和功能适合放在 DSP、CPU 等微处理器实现,如何划分软硬件功能,安排模块接口设计等问题都非常重要。要知道**在系统上复用模块节省的面积远比在代码上小打小闹来得实惠多。**
[图 5-6](#图5-6) 描述了FPGA 设计的系统规划流程。我们可以发现**对设计从整体上进行模块复用应该在系统功能定义后就充分考虑**,并指导模块的具体划分。模块划分非常重要,除了关系到是否最大程度上发挥项目成员的协同设计能力,而且直接决定着设计的综合、实现效果和相关的操作时间,模块划分的具体方法请参考 4.2 小节中关于模块划分技巧的论述。
[图 5-6](#fig.5-6) 描述了FPGA 设计的系统规划流程。我们可以发现**对设计从整体上进行模块复用应该在系统功能定义后就充分考虑**,并指导模块的具体划分。模块划分非常重要,除了关系到是否最大程度上发挥项目成员的协同设计能力,而且直接决定着设计的综合、实现效果和相关的操作时间,模块划分的具体方法请参考 4.2 小节中关于模块划分技巧的论述。
<a name="图5-6"></a>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-060-SystemPlanningProc.png!sign" width="700px" alt="系统规划的简化流程"/>
</div>
<a id="fig.5-6"></a>
![图 5-6 系统规划的简化流程](../images/post/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-060-SystemPlanningProc.png){width=700px}
对系统原则做一点引申,简单谈谈模块化设计方法。模块化设计是系统原则的一个很好的体现,它不仅是一种设计工具,它更是一种设计思路、设计方法,它是由顶向下、模块划分、分工协作设计思路的集中体现,是当代大型复杂系统的推荐设计方法。目前很多的 EDA 厂商都提高了模块化设计工具,通过这类工具划分每个模块的设计区域,然后单独设计和优化每个模块,最后将每个模块融合到顶层设计中,从而实现了团队协作、并行设计的模块化设计方法。合理使用模块化设计方法,能在最大程度上继承以往设计成果,并行分工协作,有效利用开发资源,缩短开发周期。
下举例说明如何在系统层次复用模块
下举例说明如何在系统层次复用模块。
利用“可编程匹配滤波器“实现 WCDMA 基站的方案,其核心是在合理规划系统的基础上,合理划分模块并安排操作时序,提高单元模块的复用率令从而大大降低硬件消耗,其设计思想是系统原则的集中体现。可编程匹配滤波器原理框图如[图 5-7](#图5-7) 所示。
利用“可编程匹配滤波器“实现 WCDMA 基站的方案,其核心是在合理规划系统的基础上,合理划分模块并安排操作时序,提高单元模块的复用率令从而大大降低硬件消耗,其设计思想是系统原则的集中体现。可编程匹配滤波器原理框图如[图 5-7](#fig.5-7) 所示。
<a name="图5-7"></a>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-070-ProgrammableMatchFilter.png!sign" width="500px" alt="系统规划的简化流程"/>
</div>
<a id="fig.5-7"></a>
其设计思想是:利用信道固有特点(如信道 pilot 导频、信道结构等),应用现代可编程数字信号处理的技术(如 DSP、FPGA 等),采取反馈与控制匹配滤波方式,实现对某信道的已扩信息的自动解扩解扰。该可编程 MF 的主要组成部分为本地码发生器、可编程信号 MF(S MF)、帧匹配滤波器(FRAME MF)和控制器。本地码发生器可生成各种所需的扩频、加扰序列,可接收控制器的指示脉冲,产生规定的本地解扩、解扰序列,作为 S MF 的参考序列;S MF 是完成匹配滤波的主体,可接收控制器的指示脉冲,将自己的匹配状态切换到下一匹配状态;F MF 完成对导频信号等特殊信号(信息位待选集有限)的检测,生成指示相关峰,通知控制器将 S MF 切换到下一匹配状态;控制器统一协调各部分工作。这种可编程滤波器可以在如越区切换、同步方面、CPCH 收发信机等多方面应用,如果适当安排时序流程,可以在较大程度上节约硬件资源。
![图 5-7 可编程匹配滤波器原理框图](../images/post/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-070-ProgrammableMatchFilter.png){width=600px}
其设计思想是:利用信道固有特点(如信道 pilot 导频、信道结构等),应用现代可编程数字信号处理的技术(如 DSP、FPGA 等),采取反馈与控制匹配滤波方式,实现对某信道的已扩信息的自动解扩解扰。该可编程 MF 的主要组成部分为本地码发生器、可编程信号 MF(S MF)、帧匹配滤波器(FRAME MF)和控制器。本地码发生器可生成各种所需的扩频、加扰序列,可接收控制器的指示脉冲,产生规定的本地解扩、解扰序列,作为 S MF 的参考序列;S MF 是完成匹配滤波的主体,可接收控制器的指示脉冲,将自己的匹配状态切换到下一匹配状态;FMF 完成对导频信号等特殊信号(信息位待选集有限)的检测,生成指示相关峰,通知控制器将 SMF 切换到下一匹配状态;控制器统一协调各部分工作。这种可编程滤波器可以在如越区切换、同步方面、CPCH 收发信机等多方面应用,如果适当安排时序流程,可以在较大程度上节约硬件资源。
# 2. 同步设计原则和多时钟处理
## 2.1 同步设计原则<a name="0201"></a>
## 2.1. 同步设计原则<a id="toc.2.1"></a>
同步设计是 PLD 和 ASIC 设计的最重要原则。本小节首先阐释为什么在 PLD 设计中要采用同步时序设计,然后重点论述同步时序设计的要点。
### 2.1.1 异步时序设计与同步时序设计
### 2.1.1. 异步时序设计与同步时序设计
简单比较一下异步电路和同步电路的异同。
| 电路类型 | <center>特点</center> |
|:--:|:--|
| 电路类型 | 特点 |
|:--:|:------------|
| 异步电路 | · 电路的核心逻辑用组合电路实现,比如异步的 FIFO/RAM 读/写信号、地址译码等电路。<br>· 电路的主要信号、输出信号等并不依赖于任何一个时钟性信号,不是由时钟信号驱动触发器(FF)产生的。<br>· 异步时序电路的最大缺点是容易产生毛刺。在布局布线后仿真和用高分辨率逻辑分析仪观测实际信号时,这种毛刺尤其明显。<br>· 不利于器件移植,这包括 FPGA 器件族之间的移植和从 FPGA 向结构化 ASIC 的移植。<br>· 不利于静态时序分析(STA)、验证设计时序性能。|
| 同步电路 | · 电路的核心逻辑用各种各样的触发器实现。<br>· 电路的主要信号、输出信号等都是由某个时钟沿驱动触发器产生的。<br>· 同步时序电路可以很好地避免毛刺。布局布线后仿真和用高速逻辑分析仪采样实际工作信号皆无毛刺。<br>· 利于器件移植,这包括 FPGA 器件族之间的移植和从 FPGA 向结构化 ASIC 的移植。<br>· 有利于静态时序分析(STA)、验证设计时序性能。
@@ -529,9 +530,13 @@ case (var)
随着EDA 工具的发展,大规模设计的综合、实现的优化效果越来越强。但是目前大多数综合、实现等EDA 工具都是基于时序驱动(Timing Driven)优化策略的。异步时序电路增加了时序分析的难度,需要确定最佳时序路径所需的计算量超出想象,所需时序约束相当繁琐,而且**对于异步电路很多综合、实现工具的编译会带来歧义**。而对于同步时序设计则恰恰相反,其**时序路径清晰,相关时序约束简单明了,综合、实现优化容易,布局布线计算量小**。所以目前可编程逻辑的 EDA 工具都推荐使用同步时序设计。
{% note info %}
综上所述,**现代数字芯片设计推荐采用同步时序设计方式!**
### 2.1.2 同步时序设计
{% endnote %}
### 2.1.2. 同步时序设计
同步时序设计的基本原则是**使用时钟沿触发所有的操作**。如果所有寄存器的时序要求(Setup、Hold 时间等指标)都能够满足,则同步时序设计与异步时序设计相比,在不同的 PVT(工艺、电压、温度)条件下能获得更佳的系统稳定性与可靠性。
@@ -543,58 +548,63 @@ case (var)
同步时序设计有以下几个注意事项:
- 异步时钟域的数据转换。详见 [2.3 小节“异步时钟域数据同步”](#0203)。
- 异步时钟域的数据转换。详见 [2.3 小节“异步时钟域数据同步”](#toc.2.3)。
- 组合逻辑电路的设计方法。详见[第 5 节“组合逻辑的注意事项”](#05)。
- 组合逻辑电路的设计方法。详见[第 5 节“组合逻辑的注意事项”](#toc.5)。
- 同步时序电路的时钟设计。 详见[第 6 节“时钟设计的注意事项”](#06)。
- 同步时序电路的时钟设计。 详见[第 6 节“时钟设计的注意事项”](#toc.6)。
- 同步时序电路的延迟。同步时序设计中电路延迟最常用的设计方法是用分频或倍频的时钟或者同步计数器完成所需延迟。换句话说,同步时序电路的延时被当作一个电路逻辑来设计。对于**比较大的和特殊定时要求的延时,一般用高速时钟产生一个计数器,根据计数器的计数,控制延时**;对于**比较小的延时,可以用 D 触发器打一下**,这种做法**不仅使信号延时了一个时钟周期,而且完成了信号与时钟的初次同步**,在输入信号采样或增加时序约束余量时使用。另外许多初学者用行为级(Behavioral Level)方法描述延时,如 `#5 a<= 4'b0101;` 这种行为级描述方法常用于仿真测试激励,但是**在电路综合时会被忽略、并不能起到延时作用**。
- 同步时序电路的延迟。
## 2.2 亚稳态
同步时序设计中电路延迟最常用的设计方法是用分频或倍频的时钟或者同步计数器完成所需延迟。换句话说,同步时序电路的延时被当作一个电路逻辑来设计。对于**比较大的和特殊定时要求的延时,一般用高速时钟产生一个计数器,根据计数器的计数,控制延时**;对于**比较小的延时,可以用 D 触发器打一下**,这种做法**不仅使信号延时了一个时钟周期,而且完成了信号与时钟的初次同步**,在输入信号采样或增加时序约束余量时使用。另外许多初学者用行为级(Behavioral Level)方法描述延时,如 `#5 a<= 4'b0101;` 这种行为级描述方法常用于仿真测试激励,但是**在电路综合时会被忽略、并不能起到延时作用**。
在后续笔记中会介绍异步时钟域转换的问题,在谈这个话题之前,先分析一下什么是亚稳态,以及如何避免。
## 2.2. 亚稳态<a id="toc.2.2"></a>
异步时钟域的转换的核心就是要保证下级时钟对上级数据采样的 Setup 时间和 Hold 时间。如果触发器的Setup 时间或者 Hold 时间不满足,就可能产生亚稳态,**此时触发器输出端 Q 在有效时钟沿之后比较长的一段时间内处于不确定的状态,在这段时间内 Q 端产生毛刺并不断振荡,最终固定在某一电压值,此电压值并不一定等于原来数据输入端 D 的数值**,这段时间称为决断时间(Resolution time)。经过 Resolution time 之后 Q 端将稳定到 0 或1, 但是究竟是 0 还是1,这是随机的,与输入没有必然的关系,其产生示意图如[图 5-8](#图5-8) 所示。
在后续文章中会介绍异步时钟域转换的问题,在谈这个话题之前,先分析一下什么是亚稳态,以及如何避免。
<a name="图5-8"></a>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-080-MetastableGenerate.png!sign" width="700px" alt="亚稳态产生示意图"/>
</div>
异步时钟域的转换的核心就是要保证下级时钟对上级数据采样的 Setup 时间和 Hold 时间。如果触发器的Setup 时间或者 Hold 时间不满足,就可能产生亚稳态,**此时触发器输出端 Q 在有效时钟沿之后比较长的一段时间内处于不确定的状态,在这段时间内 Q 端产生毛刺并不断振荡,最终固定在某一电压值,此电压值并不一定等于原来数据输入端 D 的数值**,这段时间称为决断时间(Resolution time)。经过 Resolution time 之后 Q 端将稳定到 0 或1, 但是究竟是 0 还是1,这是随机的,与输入没有必然的关系,其产生示意图如[图 5-8](#fig.5-8) 所示。
**亚稳态的危害主要体现在破坏系统的稳定性**。由于输出在稳定下来之前可能是毛刺、振荡、固定的某一电压值,因此亚稳态将**导致逻辑误判**,严重情况下输出 0~1 之间的中间电压值还会**使下一级产生亚稳态,即导致亚稳态的传播**。逻辑误判导致功能性错误,而亚稳态的传播则扩大了故障面。另外,在亚稳态状态下,任何诸如环境噪声、电源于扰等细微扰动都将导致更恶劣的状态不稳定。这时这个系统的传输延迟增大,状态输出错误,在某些情况下甚至会使寄存器在两个有效判定门限(V~oL~ 、V~oH~)之间长时间的振荡。
<a id="fig.5-8"></a>
![图 5-8 亚稳态产生示意图](../images/post/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-080-MetastableGenerate.png){width=800px}
**亚稳态的危害主要体现在破坏系统的稳定性**。由于输出在稳定下来之前可能是毛刺、振荡、固定的某一电压值,因此亚稳态将**导致逻辑误判**,严重情况下输出 0~1 之间的中间电压值还会**使下一级产生亚稳态,即导致亚稳态的传播**。逻辑误判导致功能性错误,而亚稳态的传播则扩大了故障面。另外,在亚稳态状态下,任何诸如环境噪声、电源于扰等细微扰动都将导致更恶劣的状态不稳定。这时这个系统的传输延迟增大,状态输出错误,在某些情况下甚至会使寄存器在两个有效判定门限($\mathrm{V_{oL}}$ 、$\mathrm{V_{oH}}$)之间长时间的振荡。
**只要系统中有异步元件,亚稳态就无法避免**,因此设计的电路**首先要减少亚稳态导致的错误**,**其次要使系统对产生的错误不敏感**。前者要靠同步设计来实现,而后者则根据不同的设计应用不同的处理办法。
**使用两级以上寄存器采样可以有效地减少亚稳态继续传播的概率**。在[图 5-9](#图5-9) 中,左边为异步输入端,经过两级触发器采样,在右边的输出与 `bclk` 同步,而且该输出基本不存在亚稳态。其原理是使第一个触发器的输出端存在亚稳态,经过一个 clk 周期后,第二个触发器 D 端的电平仍未稳定的概率非常小,因此第二个触发器 Q 端基本不会产生亚稳态。理论上如果再添加一级寄存器,使同步采样达到 3 级,则末级输出为亚稳态的概率几乎为 0。
**使用两级以上寄存器采样可以有效地减少亚稳态继续传播的概率**。在[图 5-9](#fig.5-9) 中,左边为异步输入端,经过两级触发器采样,在右边的输出与 `bclk` 同步,而且该输出基本不存在亚稳态。其原理是使第一个触发器的输出端存在亚稳态,经过一个 clk 周期后,第二个触发器 D 端的电平仍未稳定的概率非常小,因此第二个触发器 Q 端基本不会产生亚稳态。理论上如果再添加一级寄存器,使同步采样达到 3 级,则末级输出为亚稳态的概率几乎为 0。
<a name="图5-9"></a>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-090-TwoStageRegisterSampling.png!sign" width="700px" alt="两级寄存器采样降低亚稳态概率"/>
</div>
<a id="fig.5-9"></a>
使用[图 5-9](#图5-9) 两级寄存器采样仅能降低亚稳态的概率,但是并不能保证第二级输出的稳态电平就是正确电平。前面说过经过 Resolution time 之后寄存器输出的电平是一个不确定的稳态值,也就是说**这种处理方法并不能排除采样错误的产生**,这时就**要求所设计的系统对采样错误有一定的容忍度**。有些应用本身就对采样错误不敏感,如一帧图像编码,一段话音编码等。而有些系统对错误采样比较敏感。这类由于亚稳态造成的采样是一些突发的错误,所以可以采用一些纠错编码手段完成错误的纠正。
![图 5-9 两级寄存器采样降低亚稳态概率](../images/post/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-090-TwoStageRegisterSampling.png){width=800px}
## 2.3 异步时钟域数据同步<a name="0203"></a>
使用[图 5-9](#fig.5-9) 两级寄存器采样仅能降低亚稳态的概率,但是并不能保证第二级输出的稳态电平就是正确电平。前面说过经过 Resolution time 之后寄存器输出的电平是一个不确定的稳态值,也就是说**这种处理方法并不能排除采样错误的产生**,这时就**要求所设计的系统对采样错误有一定的容忍度**。有些应用本身就对采样错误不敏感,如一帧图像编码,一段话音编码等。而有些系统对错误采样比较敏感。这类由于亚稳态造成的采样是一些突发的错误,所以可以采用一些纠错编码手段完成错误的纠正。
异步时钟域数据同步是芯片设计的一个常见问题,既是一个重点也是一个难点问题。很多设计工作时的不稳定都是源于异步时钟域数据同步不稳定。
## 2.3. 异步时钟域数据同步<a id="toc.2.3"></a>
### 2.3.1 两类异步时钟域同步的表现形式
异步时钟域数据同步是芯片设计的一个常见问题,**既是一个重点也是一个难点问题**。很多设计工作时的不稳定都是源于异步时钟域数据同步不稳定。
### 2.3.1. 两类异步时钟域同步的表现形式
异步时钟域数据同步,也被称为数据接口同步,顾名思义,是指**如何在两个时钟不同步的数据域之间可靠地进行数据交换**。数据的时钟域不同步主要有两种情况:
- 两个域的时钟频率相同,但是相位差不固定,或者相差固定但是不可测,简称为同频异相问题;
- 两个时钟域频率根本不同,简称为异频问题。
### 2.3.2 两种不推荐的异步时钟域操作方法
### 2.3.2. 两种不推荐的异步时钟域操作方法
首先讨论两种在设计中不推荐的异步时钟域转换方法:一种是通过增加 Buffer 或者其他门延时调整采样;另一种是盲目使用时钟正负沿调整数据采样。
1. 通过 Buffer 等组合逻辑延迟线调整采样时间
在早期逻辑电路图设计阶段,有一些设计者养成了手工加入 Buffer 或者非门调整数据延迟的习惯,从而保证本级模块的时钟对上级模块数据的建立、保持时间的要求。这些做法目前主要应用的场合有两种:一是使用分立逻辑元件(如 74 系列)搭建数字逻辑电路;另一种是在 ASIC 设计领域。**目前使用分立逻辑元件搭建数字逻辑电路的场合一般为系统复杂度相对较低,系统灵活性要求不高的场合。**在上述场合使用分立逻辑器件设计数字逻辑电路,由于可以使用的调整延时的手段相对有限,而且采用插入 Buffer 、数字延迟逻辑甚至两个非门等手段调整采样的 Setup 和 Hold 时间是可以接受的。而 ASIC 设计领域采用这种方法是以严格的仿真和约束条件作为强力支持的。
在早期逻辑电路图设计阶段,有一些设计者养成了手工加入 Buffer 或者非门调整数据延迟的习惯,从而保证本级模块的时钟对上级模块数据的建立、保持时间的要求。这些做法目前主要应用的场合有两种:
正如 [2.1 同步设计原则](#0201)所述,**使用组合逻辑方法产生延迟,容易产生毛刺**,而且这种设计方法的**时序余量较差**,一旦外界条件变换(环境试验,特别是高低温试验),采样时序就有可能完全紊乱,造成电路瘫痪。另外,一旦芯片更新换代,或者移植到其他器件族的芯片上,采样时延必须重新调整,电路的可维护性和继承性都很差。
- 一是使用分立逻辑元件(如 74 系列)搭建数字逻辑电路;
- 另一种是在 ASIC 设计领域。**目前使用分立逻辑元件搭建数字逻辑电路的场合一般为系统复杂度相对较低,系统灵活性要求不高的场合**。
在上述场合使用分立逻辑器件设计数字逻辑电路,由于可以使用的调整延时的手段相对有限,而且采用插入 Buffer 、数字延迟逻辑甚至两个非门等手段调整采样的 Setup 和 Hold 时间是可以接受的。而 ASIC 设计领域采用这种方法是以严格的仿真和约束条件作为强力支持的。
正如 [2.1 同步设计原则](#toc.2.1)所述,**使用组合逻辑方法产生延迟,容易产生毛刺**,而且这种设计方法的**时序余量较差**,一旦外界条件变换(环境试验,特别是高低温试验),采样时序就有可能完全紊乱,造成电路瘫痪。另外,一旦芯片更新换代,或者移植到其他器件族的芯片上,采样时延必须重新调整,电路的可维护性和继承性都很差。
2. 盲目使用时钟正负沿调整数据采样
@@ -609,57 +619,56 @@ case (var)
针对使用两个时钟沿,在这里还想补充以下两点:
- 使用者虽然使用了同一个时钟的两个沿,但是**保证不在同一个周期内同时使用双沿,则不会增加时钟频率**。
- DDR 、QDR 本身就是利用了上下沿采样的原理,随着存储器件高速发展,时钟速度已经成为存取器件的瓶颈,所以可用时钟上下沿操作缓解对单沿 RAM 时钟振荡器的要求。但是必须清楚,硬件的 DDR、QDR 电路(包括 ASIC 的 DDR、QDR 与 FPGA 内嵌的 DDR、QDR 电路)是专用高速设计电路,对时钟的正沿、负沿的 Jitter 、Skew 和占空比等指标都有详细和明确的要求,这一点是和普通逻辑设计,特别是实现在 FPGA 中设计的情况截然不同,希望读者加以区分。
### 2.3.3 异步时钟域数据同步常用方法
- DDR 、QDR 本身就是利用了上下沿采样的原理,随着存储器件高速发展,时钟速度已经成为存取器件的瓶颈,所以可用时钟上下沿操作缓解对单沿 RAM 时钟振荡器的要求。但是必须清楚,硬件的 DDR、QDR 电路(包括 ASIC 的 DDR、QDR 与 FPGA 内嵌的 DDR、QDR 电路)是专用高速设计电路,对时钟的正沿、负沿的 Jitter 、Skew 和占空比等指标都有详细和明确的要求,这一点是和普通逻辑设计,特别是实现在 FPGA 中设计的情况截然不同,希望大家加以区分。
下面分别介绍 [2.3 小节](#0203)提出的两大类异步时钟域数据同步问题的解决方法。
### 2.3.3. 异步时钟域数据同步常用方法
下面分别介绍 [2.3 小节](#toc.2.3)提出的两大类异步时钟域数据同步问题的解决方法。
1. 同频异相问题
同频异相问题的简单解决方法是**用后级时钟对前级数据采样两次**,即通常所述的**用寄存器打两次**。数据同步如[图 5-10](#图5-10) 所示,这样的做法是有效地减少了亚稳态的传播,使后级电路数据都是有效电平值。但是这种做法并不能保证两级寄存器采样后的数据是正确的电平值,因为一旦 Setup 或 Hold 时间不满足,采样发生亚稳态,则经判决时间(Resolution Time)后,还是可能判决到错误电平值。所以这种方法仅仅适用于对少量错误不敏感的功能单元。
同频异相问题的简单解决方法是**用后级时钟对前级数据采样两次**,即通常所述的**用寄存器打两次**。数据同步如[图 5-10](#fig.5-10) 所示,这样的做法是有效地减少了亚稳态的传播,使后级电路数据都是有效电平值。但是这种做法并不能保证两级寄存器采样后的数据是正确的电平值,因为一旦 Setup 或 Hold 时间不满足,采样发生亚稳态,则经判决时间(Resolution Time)后,还是可能判决到错误电平值。所以**这种方法仅仅适用于对少量错误不敏感的功能单元**。
<a name="图5-10"></a>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-100-DataSynchronization.png!sign" width="700px" alt="数据同步"/>
</div>
<a id="fig.5-10"></a>
可靠的做法是用 DPRAM 、FIFO 或者一段寄存器 Buffer 完成异步时钟域的数据转换。把数据存放在 DPRAM 或FIFO 的方法如下:将上级芯片提供的数据随路时钟作为写信号,将数据写入 DPRAM 或者FIFO, 然后使用本级的采样时钟( 一般是数据处理的主时钟),将数据读出即可。由于时钟频率相同,所以 DPRAM 或 FIFO 两端的数据吞吐率一致,实现起来相对简单。
![图 5-10 数据同步](../images/post/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-100-DataSynchronization.png){width=800px}
可靠的做法是用 DPRAM 、FIFO 或者一段寄存器 Buffer 完成异步时钟域的数据转换。把数据存放在 DPRAM 或FIFO 的方法如下:将上级芯片提供的数据随路时钟作为写信号,将数据写入 DPRAM 或者FIFO, 然后使用本级的采样时钟( 一般是数据处理的主时钟),将数据读出即可。由于时钟频率相同,所以 DPRAM 或 FIFO 两端的数据吞吐率一致,实现起来相对简单。
2. 异频问题
可靠完成异频问题的解决方法就是使用 DPRAM 或 FIFO 。其实现思路与前面所述一致,用上级随路时钟写上级数据,然后用本级时钟读出数据。但是由于时钟频率不同,所以两个端口的数据吞吐率不一致,设计时一定要开好缓冲区,并通过监控(Full、Half、Empty 等指示)确保数据流不会溢出。
可靠完成异频问题的解决方法就是使用 DPRAM 或 FIFO 。其实现思路与前面所述一致,用上级随路时钟写上级数据,然后用本级时钟读出数据。但是由于时钟频率不同,所以两个端口的数据吞吐率不一致,设计时一定要开好缓冲区,并通过监控(Full、Half、Empty 等指示)确保数据流不会溢出。
# 3. 代码风格
代码风格,即 Coding Style,其分为一般性 Coding Style 和针对综合工具、实现工具、器件类型的 Coding Style。
## 3.1 Coding Style 的分类
## 3.1. Coding Style 的分类
所谓一般性的 Coding Style,是指不依赖于综合、实现工具和器件类型的代码风格。不同的综合实现工具对一些语法细节的阐释略有不同,特别是那些关于优先级实现的先后顺序等,所以不同的综合工具在个别细节上对 Coding Style 的解释有一定的差异。本篇笔记所述的 Coding Style,如果没有特别声明,都是不依赖于具体 EDA 工具, 一般意义上的 Coding Style,适用于不同厂商的综合实现工具和不同目标器件。
所谓一般性的 Coding Style,是指不依赖于综合、实现工具和器件类型的代码风格。不同的综合实现工具对一些语法细节的阐释略有不同,特别是那些关于优先级实现的先后顺序等,所以不同的综合工具在个别细节上对 Coding Style 的解释有一定的差异。本文所述的 Coding Style,如果没有特别声明,都是不依赖于具体 EDA 工具, 一般意义上的 Coding Style,适用于不同厂商的综合实现工具和不同目标器件。
还有一类 Coding Style 是针对某种综合工具或者特定器件结构的,根据器件硬件结构,正确地实例化底层单元模块,合理地使用其内嵌的硬件电路,以达到最优化的设计效果。另外需要特别声明一点,一般 ASIC 设计的 Coding Style 和 PLD(主要指 FPGA 和 CPLD)设计的 Coding Style 有明显差异。这主要是因为PLD 设计是基于固有的硬件结构(如:逻辑单元、块 RAM、PLL/DLL、时钟资源等)。而 ASIC 设计结构灵活,目标多样,特别是在功耗、速度、时序等要求上,与 PLD 设计有明显差异。例如, ASIC 设计中根据要求会有意识地采样某些组合逻辑、门控时钟等降低功耗或提高速度。这里讲述的 Coding Style 和基本原则如不特殊声明,均基于 PLD 设计要求。
还有一类 Coding Style 是针对某种综合工具或者特定器件结构的,根据器件硬件结构,正确地实例化底层单元模块,合理地使用其内嵌的硬件电路,以达到最优化的设计效果。另外需要特别声明一点,一般 ASIC 设计的 Coding Style 和 PLD(主要指 FPGA 和 CPLD)设计的 Coding Style 有明显差异。这主要是因为 PLD 设计是基于固有的硬件结构(如:逻辑单元、块 RAM、PLL/DLL、时钟资源等)。而 ASIC 设计结构灵活,目标多样,特别是在功耗、速度、时序等要求上,与 PLD 设计有明显差异。例如, ASIC 设计中根据要求会有意识地采样某些组合逻辑、门控时钟等降低功耗或提高速度。这里讲述的 Coding Style 和基本原则如不特殊声明,均基于 PLD 设计要求。
另外本篇笔记所述 Coding Style 主要是基于 RTL(寄存器传输级)而言,并非其他描述层次。所以诸如业界非常热门的结构化设计方法(Architectural-based Design)的代码风格的原则和方法与本章无关,甚至有很多原则和方法是与本章所述背道而驰的。
另外本文所述 Coding Style 主要是基于 RTL(寄存器传输级)而言,并非其他描述层次。所以诸如业界非常热门的结构化设计方法(Architectural-based Design)的代码风格的原则和方法与本章无关,甚至有很多原则和方法是与本章所述背道而驰的。
## 3.2 Coding Style 的重要性
## 3.2. Coding Style 的重要性
当代的可编程逻辑设计日趋复杂,其系统复杂度和设计频率要求与 5 年前不可同日而语。良好的 Coding Style 对设计的工作频率,所消耗的芯片面积,甚至整个系统的稳定性都非常重要,良好规范的Coding Style 便于设计移植。
随着 EDA 技术的不断发展,综合、实现工具的优化能力越来越强大,可以自动完成许多复杂设计的面积和时序方面的优化,并且其优化效果日趋先进。但是如果盲目依赖综合、实现等 EDA 工具的优化,而忽略自己设计的代码风格,就大错特错了。因为 Coding Style 对综合、实现等 EDA 工具的优化结果的影响可以用这样一句话来概括:**好的Coding Style 会使综合、实现等优化事半功倍,达到最优化的结果;不良的Coding Style 会使综合、实现优化南辕北辙,甚至产生错误的结果**。所以必须明确:综合、实现等 EDA 工具的优化能力和正确性最终取决于设计的 Coding Style 的优劣。
随着 EDA 技术的不断发展,综合、实现工具的优化能力越来越强大,可以自动完成许多复杂设计的面积和时序方面的优化,并且其优化效果日趋先进。但是如果盲目依赖综合、实现等 EDA 工具的优化,而忽略自己设计的代码风格,就大错特错了。因为 Coding Style 对综合、实现等 EDA 工具的优化结果的影响可以用这样一句话来概括:**好的 Coding Style 会使综合、实现等优化事半功倍,达到最优化的结果;不良的 Coding Style 会使综合、实现优化南辕北辙,甚至产生错误的结果**。所以必须明确:综合、实现等 EDA 工具的优化能力和正确性最终取决于设计的 Coding Style 的优劣。
在后面的几节中,将详细谈谈设计和代码风格。
# 4. 结构层次和模块划分
# 4. 结构层次和模块划分<a id="toc.4"></a>
## 4.1 结构层次化编码
## 4.1. 结构层次化编码
结构层次化编码(Hierarchical Coding)是模块化设计思想的一种体现。目前大型设计中必须采用结构层次化编码风格,以提高代码的可读性,易于模块划分,易于分工协作,易于设计仿真测试激励。最基本的结构化层次是由一个顶层模块和若干个子模块构成,每个子模块根据需要还可以包含自己的子模块。结构层次化编码结构如[图 5-11](#图5-11) 所示。
结构层次化编码(Hierarchical Coding)是模块化设计思想的一种体现。目前大型设计中必须采用结构层次化编码风格,以提高代码的可读性,易于模块划分,易于分工协作,易于设计仿真测试激励。最基本的结构化层次是由一个顶层模块和若干个子模块构成,每个子模块根据需要还可以包含自己的子模块。结构层次化编码结构如[图 5-11](#fig.5-11) 所示。
<a name="图5-11"></a>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-110-StructuredCoding.png!sign" width="500px" alt="结构层次化编码示意图"/>
</div>
<a id="fig.5-11"></a>
![结构层次化编码示意图](../images/post/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-110-StructuredCoding.png){width=600px}
结构层次化编码有如下注意事项:
@@ -677,39 +686,43 @@ case (var)
虽然理论上任何设计都可以在同一个模块中完成,但是如果将不同功能、不同层次、不同类型的电路混淆在同一个模块中,这不是一种好的系统设计方法,对于比较复杂的设计,将会导致整个设计杂乱无章,不利于设计的阅读与维护,也会给综合和实现过程带来许多麻烦。
## 4.2 模块划分的技巧
## 4.2. 模块划分的技巧
结构层次化设计方法的第一个要点就是模块划分,模块划分非常重要,关系到能否最大程度上发挥项目成员协同设计的能力,更重要的是它直接决定着设计的综合、实现的耗时与效率。模块划分的基本原则介绍如下:
1. **对每个同步时序设计的子模块的输出使用寄存器**
这也被称为用寄存器分割同步时序模块的原则。使用寄存器分割同步时序单元的好处是:便于综合工具权衡所分割的子模块中的组合电路部分和同步时序电路部分,从而达到更好的时序优化效果,这种模块划分符合时序约束的习惯,便于利用约束属性进行时序约束。
这也被称为用寄存器分割同步时序模块的原则。使用寄存器分割同步时序单元的好处是:便于综合工具权衡所分割的子模块中的组合电路部分和同步时序电路部分,从而达到更好的时序优化效果,这种模块划分符合时序约束的习惯,便于利用约束属性进行时序约束。
2. **将相关的逻辑或者可以复用的逻辑划分在同一模块内**
这个做法有时被称为**呼应系统原则**。这样做的好处有:一方面将相关的逻辑和可以复用的逻辑划分在同一模块,可在最大程度上复用资源,减少设计所消耗的面积;另一方面更利于综合工具优化某个具体功能的时序关键路径。其原因是,传统的综合工具只能同时优化某一部分的逻辑,而所能同时优化的逻辑的从本单元就是模块,所以将相关功能划分在同一模块将在时序和面积上获得更好的综合优化效果。
这个做法有时被称为**呼应系统原则**。这样做的好处有:一方面将相关的逻辑和可以复用的逻辑划分在同一模块,可在最大程度上复用资源,减少设计所消耗的面积;另一方面更利于综合工具优化某个具体功能的时序关键路径。其原因是,传统的综合工具只能同时优化某一部分的逻辑,而所能同时优化的逻辑的从本单元就是模块,所以将相关功能划分在同一模块将在时序和面积上获得更好的综合优化效果。
3. **将不同优化目标的逻辑分开**
在介绍速度、面积平衡与互换原则时,合理的设计目标应该综合考虑面积最小和频率最高两个指标。好的设计,在规划阶段设计者就应该初步规划了设计的规模和时序关键路径,并对设计的优化目标有一个整体上的把握。对于时序紧张的部分.应该独立划分为一个模块.其优化目标为“Speed”,这种划分方法便于设计者进行时序约束,也便于综合和实现工具进行优化。目前很多综合与实现工具都支持物理区域位置约束,以模块为单元进行物理区域约束,从而优化关键路径时序,以达到更高的系统工作频率就更为方便有效。另一类情况是,设计的矛盾主要集中在芯片的资源消耗上。这时应该将资源消耗过大的部分划分为独立的模块,这类模块的优化目标应该定为“Area” 。同理,将它们规划到一起,更有利于区域布局与约束。这种根据优化目标进行优化的方法最大好处是,对于某个模块综合器仅需要考虑一种优化目标和策略,从而比较容易达到较好的优化效果。相反,如果同时考虑两种优化目标,会使综合器陷入互相制约的困境,耗费巨大的综合优化时间也得不到令人满意的综合优化结果。
在介绍速度、面积平衡与互换原则时,合理的设计目标应该综合考虑面积最小和频率最高两个指标。好的设计,在规划阶段设计者就应该初步规划了设计的规模和时序关键路径,并对设计的优化目标有一个整体上的把握。
对于时序紧张的部分,应该独立划分为一个模块,其优化目标为“Speed”,这种划分方法便于设计者进行时序约束,也便于综合和实现工具进行优化。目前很多综合与实现工具都支持物理区域位置约束,以模块为单元进行物理区域约束,从而优化关键路径时序,以达到更高的系统工作频率就更为方便有效。
另一类情况是,设计的矛盾主要集中在芯片的资源消耗上。这时应该将资源消耗过大的部分划分为独立的模块,这类模块的优化目标应该定为“Area” 。同理,将它们规划到一起,更有利于区域布局与约束。这种根据优化目标进行优化的方法最大好处是,对于某个模块综合器仅需要考虑一种优化目标和策略,从而比较容易达到较好的优化效果。相反,如果同时考虑两种优化目标,会使综合器陷入互相制约的困境,耗费巨大的综合优化时间也得不到令人满意的综合优化结果。
4. **将时序约束较松的逻辑归到同一模块**
有些逻辑的时序非常宽松,不需要较高的时序约束,可以将这类逻辑归入同一模块,如多周期路径(Multi-cycle Path)等。将这些模块归类,并指定宽松约束,则可以让综合器尽量节省面积资源。
有些逻辑的时序非常宽松,不需要较高的时序约束,可以将这类逻辑归入同一模块,如多周期路径(Multi-cycle Path)等。将这些模块归类,并指定宽松约束,则可以让综合器尽量节省面积资源。
5. **将存储逻辑独立划分成模块**
RAM、ROM、CAM 和 FIFO 等存储单元应该独立划分模块。这样做的好处是便于利用综合约束属性显化指定这些存储单元的结构和所使用的资源类型,也便于综合器将这些存储单元自动类推为指定器件的硬件原语。另一个好处是在仿真时消耗的内存也会减少,便于提高仿真速度。这是因为大多数仿真器对大面积的RAM都有独特的内存管理方式,以提高仿真效率。
RAM、ROM、CAM 和 FIFO 等存储单元应该独立划分模块。这样做的好处是便于利用综合约束属性显化指定这些存储单元的结构和所使用的资源类型,也便于综合器将这些存储单元自动类推为指定器件的硬件原语。另一个好处是在仿真时消耗的内存也会减少,便于提高仿真速度。这是因为大多数仿真器对大面积的 RAM 都有独特的内存管理方式,以提高仿真效率。
6. **合适的模块规模**
从理论上讲,模块的规模越大,越利于模块资源共享(Resource Sharing)。但是庞大的模块,将要求对综合器同时处理更多的逻辑结构.这将对综合器的处理能力和计算机的配置提出了较高的要求。另外,庞大的模块划分,不利于发挥目前非常流行的增拭综合与实现技术的优势。
从理论上讲,模块的规模越大,越利于模块资源共享(Resource Sharing)。但是庞大的模块,将要求对综合器同时处理更多的逻辑结构,这将对综合器的处理能力和计算机的配置提出了较高的要求。另外,庞大的模块划分,不利于发挥目前非常流行的增拭综合与实现技术的优势。
# 5. 组合逻辑的注意事项<a name="05"></a>
# 5. 组合逻辑的注意事项<a id="toc.5"></a>
相对复杂一些的设计都是由两部分组成的,分别为时序逻辑(Sequential Logic)和组合逻辑(Combination Logic)。同步时序设计系统中并不是不包含组合逻辑,而是要更加合理地设计、划分组合逻辑。在以下几小节中将介绍组合逻辑设计的一些问题。
## 5.1 `always` 组合逻辑信号敏感表
## 5.1. `always` 组合逻辑信号敏感表
几乎所有的编码指导手册都有关于信号敏感表的论述。时序逻辑的信号敏感表比较好写,在信号敏感表中写明时钟信号的正负触发沿即可,关于信号敏感表的主要问题集中在组合逻辑的信号敏感表的写法。在此,仅强调组合逻辑的信号敏感表的相关要点:
@@ -723,16 +736,15 @@ case (var)
有些初学者发现在信号敏感表中增减一些信号,会得到不同的仿真结果,于是企图依靠修改信号敏感表,而方便地完成某些逻辑的设计,这种做法是不可能的。其实一般综合工具的默认操作都是将 `always` 模块中使用到的所有输入信号和条件判断信号都当作触发信号,综合到信号敏感表中,所以增减信号敏感表,其实得到的综合结果完全一致。而增减信号敏感表,得到的仿真结果不同是因为仿真器的工作机制决定的,大多数仿真器是数据流和时钟周期驱动的,如果信号敏感表中没有某个信号,则无法触发和该信号相关的仿真进程,从而得到的仿真结果不同。
## 5.2 组合逻辑环路
## 5.2. 组合逻辑环路
**组合逻辑反馈环路是数字同步逻辑设计的大忌**,它最容易因振荡、毛刺、时序违规等引起整个系统的不稳定和不可靠。
典型的组合逻辑反馈环路如[图 5-12](#图5-12) 所示,寄存器的 Q 端输出直接通过组合逻辑反馈到寄存器的异步复位端,如果 Q 输出为 0 时,经组合逻辑运算后为异步复位端有效,则电路进入不断清零的死循环。
典型的组合逻辑反馈环路如[图 5-12](#fig.5-12) 所示,寄存器的 Q 端输出直接通过组合逻辑反馈到寄存器的异步复位端,如果 Q 输出为 0 时,经组合逻辑运算后为异步复位端有效,则电路进入不断清零的死循环。
<a name="图5-12"></a>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-120-CombinatorialLogicFeedbackLoop.png!sign" width="400px" alt="组合逻辑反馈环路示意图"/>
</div>
<a id="fig.5-12"></a>
![组合逻辑反馈环路示意图](../images/post/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-120-CombinatorialLogicFeedbackLoop.png){width="400px"}
组合逻辑反馈环路是一种**高风险**设计方式,主要原因如下:
@@ -746,31 +758,29 @@ case (var)
- 检查综合、实现报告的 Warning 信息,发现 Combinational Loops 后进行相应修改。
## 5.3 脉冲产生器
## 5.3. 脉冲产生器
在异步时序设计中,常用延时链(Delay Chains)产生脉冲,常用的异步脉冲产生方法如[图 5-13](#图5-13) 所示。
在异步时序设计中,常用延时链(Delay Chains)产生脉冲,常用的异步脉冲产生方法如[图 5-13](#fig.5-13) 所示。
<a name="图5-13"></a>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-130-AsynchronousPulseGeneration.png!sign" width="500px" alt="常用的异步脉冲产生方法示意图"/>
</div>
<a id="fig.5-13"></a>
![图 5-13 常用的异步脉冲产生方法示意图](../images/post/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-130-AsynchronousPulseGeneration.png){width=600px}
这类异步方法设计的脉冲产生电路的脉冲宽度取决于 Delay Chains 的门延迟和线延迟,而在 FPGA/CPLD 中,大多数 Timing Driven 的综合、布线工具无法保证其布线延迟恒定。另外,PLD 器件本身在不同的 PVT(工艺、电压、温度)环境下其延时参数也有微小波动,所以脉冲宽度无法准确确定。而且 STA 工具也无法准确分析脉冲的特性,为时序仿真和验证带来了很多的不确定性。
异步脉冲序列产生电路(Multi-Vibrators)也被称为毛刺生成器(Glitch Generator),**利用组合反馈环路振荡而不断产生毛刺**。正如前面所述,组合反馈环是同步时序必须避免的.这类基于组合反馈环的 Multi-Vibrator 也会给设计带来稳定性、可靠性等方面的问题,必须避免使用。
异步脉冲序列产生电路(Multi-Vibrators)也被称为毛刺生成器(Glitch Generator),**利用组合反馈环路振荡而不断产生毛刺**。正如前面所述,组合反馈环是同步时序必须避免的,这类基于组合反馈环的 Multi-Vibrator 也会给设计带来稳定性、可靠性等方面的问题,必须避免使用。
同步时序设计脉冲电路的常用方法如[图 5-14](#图5-14) 所示。该设计的脉冲宽度不因器件或设计移植而改变,恒等于时钟周期,而且避免了异步设计的诸多不确定因素,其时序路径便于计算、STA 分析和仿真验证。
同步时序设计脉冲电路的常用方法如[图 5-14](#fig.5-14) 所示。该设计的脉冲宽度不因器件或设计移植而改变,恒等于时钟周期,而且避免了异步设计的诸多不确定因素,其时序路径便于计算、STA 分析和仿真验证。
<a name="图5-14"></a>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-140-SynchronousPulseGeneration.png!sign" width="500px" alt="常用的同步脉冲产生方法示意图"/>
</div>
<a id="fig.5-14"></a>
## 5.4 慎用锁存器
![图 5-14 常用的同步脉冲产生方法示意图](../images/post/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-140-SynchronousPulseGeneration.png){width=600px}
## 5.4. 慎用锁存器
同步时序设计要尽量慎用锁存器(Latch), 特别要注意综合出与设计意图不一致的 Latch 导致仿真和设计的错误。对于某些特定设计一定要使用 Latch 时,设计者必须明确该 Latch 是否为有意设计的。综合出与设计意图不吻合的Latch 结构的主要原因在于:在设计组合逻辑时,使用不完全的条件判断语句。如:有 `if` 而没有 `else`,或不完整的 `case` 语句等(这仅是一种可能,并不一定生成 Latch);另外一种情况是设计中有组合逻辑的反馈环路(Combinatorial Feedback Loops)等异步逻辑。
```verilog latch.v
``` verilog latch.v
/******************************
因if语句不完整而产生Latch的典型情况
******************************/
@@ -781,24 +791,23 @@ input cond_1;
input data_in;
output data_out;
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
reg data_out;
always @(cond_1 or data_in) begin
if (cond_1)
data_out <= data_in;
end
// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
endmodule
```
上述描述,由于未指定在条件 `cond_1` 等于 `0` 时的动作,一般情况下会生成 Latch 结构如[图 5-15](#图5-15) 所示。
上述描述,由于未指定在条件 `cond_1` 等于 `0` 时的动作,一般情况下会生成 Latch 结构如[图 5-15](#fig.5-15) 所示。
<a name="图5-15"></a>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-150-LatchRTL.png!sign" width="400px" alt="Latch 的 RTL 示意图"/>
</div>
<a id="fig.5-15"></a>
![图 5-15 Latch 的 RTL 示意图](../images/post/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-150-LatchRTL.png){width=500px}
防止产生非目的性的Latch 的措施如下:
@@ -807,28 +816,31 @@ endmodule
- 为每个输入条件设计输出操作,对 `case` 语句设置 `default` 操作。特别是在状态机设计中,最好有一个 `default` 的状态转移,而且每个状态最好也有一个 `default` 的操作。
- 如果使用 `case` 语句时,特别是在设计状态机时,尽量附加综合约束属性,综合为完全条件 `case` 语句(full case)。目前,大多数综合工具支持 full case 的综合约束属性,具体的语法请参考综合工具的约束属性指南。
> 仔细检查综合器的综合报告,目前大多数的综合器对所综合出的 Latch 都会报“warning”, 通过综合报告可以较为方便地找出无意中生成的 Latch。
{% note info %}
# 6. 时钟设计的注意事项<a name="06"></a>
仔细检查综合器的综合报告,目前大多数的综合器对所综合出的 Latch 都会报“warning”, 通过综合报告可以较为方便地找出无意中生成的 Latch。
{% endnote %}
# 6. 时钟设计的注意事项<a id="toc.6"></a>
时钟是同步设计的基础,在同步设计中,所有操作都是基于时钟沿触发的,所以时钟的设计对同步时序电路而言非常重要。对于 PLD 设计,通常推荐使用 FPGA 内嵌的 PLL 或 DLL 完成时钟的频率与相位变化,并用全局时钟和专用时钟选择器进行时钟布线。对于 ASIC 设计,常会用到各种各样的组合逻辑产生的时钟,但是这些设计如果直接移植到同步时序电路中会带来各种各样的问题,本节旨在辨析一些常用的时钟电路的优劣。
## 6.1 内部逻辑产生的时钟
## 6.1. 内部逻辑产生的时钟
**如果需要使用内部逻辑产生时钟,必须要在组合逻辑产生的时钟后插入寄存器**,如[图 5-16](#图5-16) 所示。如果直接使用组合逻辑产生的信号作为时钟信号或者异步置位/复位信号,会使设计不稳定。这是因为组合逻辑难免产生毛刺,这些毛刺到达一般数据路径,在经过寄存器采用后一般影响不大,但是如果作为时钟信号或者异步置位/复位信号时,如果毛刺的宽度足以驱动寄存器的时钟端或者异步置位/复位端,则必将产生错误的逻辑操作;即使毛刺的宽度不足以驱动时钟端或异步置位/复位端,也会带来寄存器的不稳定,甚至激发寄存器产生亚稳态。所以对于时钟路径,必须插入寄存器以过滤毛刺。
**如果需要使用内部逻辑产生时钟,必须要在组合逻辑产生的时钟后插入寄存器**,如[图 5-16](#fig.5-16) 所示。如果直接使用组合逻辑产生的信号作为时钟信号或者异步置位/复位信号,会使设计不稳定。这是因为组合逻辑难免产生毛刺,这些毛刺到达一般数据路径,在经过寄存器采用后一般影响不大,但是如果作为时钟信号或者异步置位/复位信号时,如果毛刺的宽度足以驱动寄存器的时钟端或者异步置位/复位端,则必将产生错误的逻辑操作;即使毛刺的宽度不足以驱动时钟端或异步置位/复位端,也会带来寄存器的不稳定,甚至激发寄存器产生亚稳态。所以对于时钟路径,必须插入寄存器以过滤毛刺。
<a name="图5-16"></a>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-160-InternalClockDesignwithRegister.png!sign" width="800px" alt="内部时钟设计必须插入寄存器"/>
</div>
<a id="fig.5-16"></a>
![图 5-16 内部时钟设计必须插入寄存器](../images/post/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-160-InternalClockDesignwithRegister.png){width=800px}
另一方面,组合逻辑产生的时钟还会带来另外一个问题,组合逻辑电路的 Jitter 和 Skew 都比较大,如果时钟产生逻辑的延迟比数据路径的延迟更大,会带来负的 Skew,负的 Skew 同步逻辑设计是灾难性的。所以**使用组合逻辑产生内部时钟仅适用于时钟频率较低、时钟精度要求不高的情况**。另外,**这类时钟应该使用快速布线资源布线,而且需要对组合逻辑电路附加一定的约束条件,以确保时钟质质量**。
## 6.2 Ripple Counter
## 6.2. Ripple Counter
所谓 Ripple Counter,即行波计数器,其结构为:一组寄存器级连,每个寄存器的输出端接到下一级寄存器的时钟管脚,这种计数器常常用于异步分频电路。早期的 PLD 设计经常使用 Ripple Counter 以节约芯片资源。但是由于 Ripple Counter 是一种典型的异步时序逻辑,正如前面“[同步设计原则](#0201)”所述,异步时序逻辑会带来各种各样的时序问题,**在同步时序电路设计中必须严格避免使用 Ripple Counter**。
所谓 Ripple Counter,即行波计数器,其结构为:一组寄存器级连,每个寄存器的输出端接到下一级寄存器的时钟管脚,这种计数器常常用于异步分频电路。早期的 PLD 设计经常使用 Ripple Counter 以节约芯片资源。但是由于 Ripple Counter 是一种典型的异步时序逻辑,正如前面“[同步设计原则](#toc.2.1)”所述,异步时序逻辑会带来各种各样的时序问题,**在同步时序电路设计中必须严格避免使用 Ripple Counter**。
## 6.3 时钟选择
## 6.3. 时钟选择
在通信系统中,为了适应不同的数据速率要求,经常要进行时钟切换。有时为了节约功耗,也会把高速时钟切换到低速时钟,或者进行时钟休眠操作。时钟切换的最佳途径是使用芯片内部的专用 Clock MUX 。这些 MUX 的反应速度快,锁定时间短,切换瞬间带来的冲击和抖动小。
@@ -838,46 +850,43 @@ endmodule
- 时钟切换后,对所有相关电路复位,以保证所有寄存器、状态机和 RAM 等电路的状态不会锁死或进入死循环。
- 所设计系统对时钟切换过程发生的短暂错误不敏感。
## 6.4 门控时钟
## 6.4. 门控时钟
门控时钟即 Gated Clock,如[图 5-17](#图5-17) 所示,是 IC 设计的一种常用减少功耗的手段。通过 Gating Logic 的控制,可以控制门后端的所有寄存器不再翻转,从而非常有效地节约功耗。
门控时钟即 Gated Clock,如[图 5-17](#fig.5-17) 所示,是 IC 设计的一种常用减少功耗的手段。通过 Gating Logic 的控制,可以控制门后端的所有寄存器不再翻转,从而非常有效地节约功耗。
<a name="图5-17"></a>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-170-GatedClock.png!sign" width="800px" alt="门控时钟"/>
</div>
<a id="fig.5-17"></a>
但是 Gated Clock 不是同步时序电路,其 Gating Logic(门控逻辑)会污染 Clock 的质量,通过控制门后会产生毛刺并使时钟的 Skew(偏斜)、Jitter(延时)等指标恶化。正如“[同步设计原则](#0201)” 一节所述,在同步时序电路中,应该尽量不使用 Gated Clock 。
![图 5-17 门控时钟](../images/post/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-170-GatedClock.png){width=800px}
虽然有些材料指出当功耗成为主要矛盾时,可以使用门控时钟改进电路如[图 5-18](#图5-18) 所示的电路完成类似门控时钟的功能,但是笔者仍强烈建议在 PLD 设计中不要使用该图所示的门控时钟改进电路。虽然这个改进电路已经在较大程度上解决了门控电路产生的毛刺,但是请读者注意,这个电路工作的前提是时钟源Clock 的占空比(Duty Cycle)是非常理想的 50%,如果时钟的占空比不能保证 50%,则会产生许多有规律的毛刺信号。另外这个电路还有一个前提,那就是 Clock 与 Enable 信号的不布线 Skew 为 0,否则也会造成宽度为 Skew 的毛刺。
但是 Gated Clock 不是同步时序电路,其 Gating Logic(门控逻辑)会污染 Clock 的质量,通过控制门后会产生毛刺并使时钟的 Skew(偏斜)、Jitter(延时)等指标恶化。正如“[同步设计原则](#toc.2.1)” 一节所述,在同步时序电路中,应该尽量不使用 Gated Clock 。
<a name="图5-18"></a>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-180-ImprovedGatedClock.png!sign" width="800px" alt="门控时钟改进电路"/>
</div>
虽然有些材料指出当功耗成为主要矛盾时,可以使用门控时钟改进电路如[图 5-18](#fig.5-18) 所示的电路完成类似门控时钟的功能,但是笔者仍强烈建议在 PLD 设计中不要使用该图所示的门控时钟改进电路。虽然这个改进电路已经在较大程度上解决了门控电路产生的毛刺,但是请注意,这个电路工作的前提是时钟源Clock 的占空比(Duty Cycle)是非常理想的 50%,如果时钟的占空比不能保证 50%,则会产生许多有规律的毛刺信号。另外这个电路还有一个前提,那就是 Clock 与 Enable 信号的不布线 Skew 为 0,否则也会造成宽度为 Skew 的毛刺。
<a id="fig.5-18"></a>
![图 5-18 门控时钟](../images/post/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-180-ImprovedGatedClock.png){width=800px}
如果功耗真的成为了 PLD 设计的首要问题,建议采用其他方法减少功耗。如果最近发展起来的低核电压芯片(Core 电压为 1.0V),芯片休眠功能,Clock MUX 等新技术器件能有效地节约芯片功耗。
## 6.5 时钟同步使能端
## 6.5. 时钟同步使能端
大多数像寄存器这样的同步单元,都支持时钟的同步使能(Synchronous Clock Enable)。需要注意的是,虽然使能无效时这些单元无输出,但是这种方法并不能如 Gated Clock 一样减少功耗。但 Synchronous Clock Enable 却能够非常方便地完成一些逻辑功能,通过使用同步时钟使能端完成某些逻辑功能,有时可以节约芯片面积并提高设计频率。
同步使能端如[图 5-19](#图5-19) 所示,上半部分是同步使能功能,在目前大多数的器件上可以直接将使能信号连接到芯片的同步使能端实现,如[图 5-19](#图5-19) 的下半部分所示。
同步使能端如[图 5-19](#fig.5-19) 所示,上半部分是同步使能功能,在目前大多数的器件上可以直接将使能信号连接到芯片的同步使能端实现,如[图 5-19](#fig.5-19) 的下半部分所示。
<a name="图5-19"></a>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-190-EnableSynchronization.png!sign" width="500px" alt="同步使能端"/>
</div>
<a id="fig.5-19"></a>
# 7. RTL 代码优化技巧
![图 5-19 同步使能端](../images/post/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-190-EnableSynchronization.png){width=500px}
## 7.1 使用 Pipelining 技术优化时序
# 7. RTL 代码优化技巧<a id="toc.7"></a>
Pipelining,即流水线时序优化方法,其本质是调整一个较长的组合逻辑路径中的寄存器位置,用寄存器合理分割该组合逻辑路径,从而降低了对路径的 Output 和 Setup 等时间参数的要求,达到提高设计频率的目的。但是必须要注意的是,使用 Pipelining 优化技术**只能合理地调整寄存器位置,而不应该凭空增加寄存器级数**,所以 Pipelining 有时也被称为 Register Balance。
## 7.1. 使用 Pipelining 技术优化时序
目前一些先进的综合工具能根据用户参数配置,自动运用 Pipelining 技术,通过用寄存器平衡设计中的较长组合路径(Register Balance),在一定程度上提高设计的工作频率。这种时序优化手段对乘法器、ROM等单元效果显著。
Pipelining,即流水线时序优化方法,其**本质是调整一个较长的组合逻辑路径中的寄存器位置**,用寄存器合理分割该组合逻辑路径,从而降低了对路径的 Output 和 Setup 等时间参数的要求,达到提高设计频率的目的。但是必须要注意的是,使用 Pipelining 优化技术**只能合理地调整寄存器位置,而不应该凭空增加寄存器级数**,所以 Pipelining 有时也被称为 Register Balance。
## 7.2 模块复用与 Resource Sharing
目前一些先进的综合工具能根据用户参数配置,自动运用 Pipelining 技术,通过用寄存器平衡设计中的较长组合路径(Register Balance),在一定程度上提高设计的工作频率。这种时序优化手段对乘法器、ROM 等单元效果显著。
## 7.2. 模块复用与 Resource Sharing
本小节的模块复用和Resource Sharing 主要站在微观的角度观察节约面积的问题。为了便与理解,首先看两个例子。
@@ -885,7 +894,7 @@ Pipelining,即流水线时序优化方法,其本质是调整一个较长的
第一种实现方式:
```verilog resource_share1.v
``` verilog resource_share1.v
module resource_share1 (data_in,square);
input [ 7:0] data_in; // 输入是补码
output [15:0] square;
@@ -898,7 +907,7 @@ endmodule
第二种实现方式:
```verilog resource_share2
``` verilog resource_share2
module resource_share2 (data_in,square);
input [ 7:0] data_in; // 输入是补码
output [15:0] square;
@@ -911,17 +920,15 @@ endmodule
仔细观察一下可以发现:第一种实现方式需要两个 16 位乘法器,同时平方,然后根据输入补码的符号选择输出结果,其关键在于使用了两个乘法器,选择器在乘法器之后;第二种实现方法,首先根据输入补码的符号,换算为正数,然后平方,其关键在于选择器在乘法器之前,仅使用了一个乘法器,节约了资源。第二种实现方式与第一种实现方式相比节约的资源有两部分:第一部分,节约了一个 16 bit 乘法器;第二部分,后者的选择器是 1 bit 判断 8 bit 输出,而前者是 1 bit 判断 16 bit 输出。
两种代码的硬件结构示意图如[图 5-20](#图5-20) 和图5 - 21 所示。
两种代码的硬件结构示意图如[图 5-20](#fig.5-20) 和图5 - 21 所示。
<a name="图5-20"></a>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-200-TwoMultipliedwithoutResourceSharing.png!sign" width="" alt="未Resource Sharing,2个乘法器的实现方案"/>
</div>
<a id="fig.5-20"></a>
<a name="图5-21"></a>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-210-OneMultipliedwithResourceSharing.png!sign" width="" alt="Resource Sharing,1个乘法器的实现方案"/>
</div>
![图 5-20 未 Resource Sharing,2 个乘法器的实现方案](../images/post/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-200-TwoMultipliedwithoutResourceSharing.png){width=800px}
<a id="fig.5-21"></a>
![图 5-21 Resource Sharing,1 个乘法器的实现方案](../images/post/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-210-OneMultipliedwithResourceSharing.png){width=800px}
对于综合后的 RTL 视图,这里需要强调以下几点:
@@ -933,16 +940,15 @@ endmodule
4. 最后需要强调的是,**不能因为综合工具的优化能力增强,而片面依靠综合工具放松对自己 Coding Style 的要求**。这是因为:第一,综合工具的优化力度毕竟有限,很多情况下不能智能地发现需要 Resource Sharing 的逻辑;第二,前面已经说过,“不同的综合工具、同一综合工具的不同版本、不同的优化参数、不同厂商的目标器件、同一厂商的不同器件族等因素"都会直接影响综合工具的优化能力和效果,所以依靠综合工具的优化能力十分不可靠;第三,在 ASIC 设计中,综合工具非常忠于用户意图,这时 Coding Style 更加重要。所以逻辑工程师必须注意自己 Coding Style 方面的修养并不断提高。
## 7.3 逻辑复制
## 7.3. 逻辑复制
逻辑复制是一种通过增加面积而改善时序条件的优化手段。逻辑复制最常使用的场合是调整信号的扇出。如果某个信号需要驱动后级的很多单元,换句话说,也就是其扇出非常大,那么为了增加这个信号的驱动能力,必须插入很多级 Buffer,这样就在一定程度上增加了这个信号路径的延时。这时可以复制生成这个信号的逻辑,使多路同频同相的信号驱动后续电路,平均到每路的扇出变低,不需要加 Buffer 也能满足驱动能力的要求,这样就节约了该信号的路径时延。用逻辑复制改善扇头电路如[图 5-22](#图5-22) 所示。
逻辑复制是一种通过增加面积而改善时序条件的优化手段。逻辑复制最常使用的场合是调整信号的扇出。如果某个信号需要驱动后级的很多单元,换句话说,也就是其扇出非常大,那么为了增加这个信号的驱动能力,必须插入很多级 Buffer,这样就在一定程度上增加了这个信号路径的延时。这时可以复制生成这个信号的逻辑,使多路同频同相的信号驱动后续电路,平均到每路的扇出变低,不需要加 Buffer 也能满足驱动能力的要求,这样就节约了该信号的路径时延。用逻辑复制改善扇头电路如[图 5-22](#fig.5-22) 所示。
<a name="图5-22"></a>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-220-DuplicationtoImproveFanOut.png!sign" width="" alt="用逻辑复制改善扇出"/>
</div>
<a id="fig.5-22"></a>
需要说明的是,现在很多综合工具都可以自动设置最大扇出值(Max Fanout),如果某个信号的扇出值大于最大扇出,则该信号自动被综合工具复制。最大扇出值和器件的工艺密切相关,其合理值应该根据器件手册的声明和工程经验设置。这里举例用逻辑复制手段调整扇出,达到优化路径时延仅仅是为了讲述逻辑复制的概念,其实逻辑复制还有其他很多形式。例如,香农扩展(Shannon Expansion) 等时序优化技术,香农扩展在后面将会有详细的介绍。
![图 5-22 用逻辑复制改善扇出](../images/post/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-220-DuplicationtoImproveFanOut.png){width=800px}
需要说明的是,现在很多综合工具都可以自动设置最大扇出值(Max Fanout),如果某个信号的扇出值大于最大扇出,则该信号自动被综合工具复制。最大扇出值和器件的工艺密切相关,其合理值应该根据器件手册的声明和工程经验设置。这里举例用逻辑复制手段调整扇出,达到优化路径时延仅仅是为了讲述逻辑复制的概念,其实逻辑复制还有其他很多形式。例如,香农扩展(Shannon Expansion)等时序优化技术,香农扩展在后面将会有详细的介绍。
有的读者会有疑问,逻辑复制和资源共享是两个矛盾的概念,既然使用了资源共享优化技术,为什么还要做逻辑复制呢?
@@ -950,62 +956,63 @@ endmodule
首先看下面的一个加法器资源共享的例子。
这个例子和前面乘法器的例子非常相似,只是将平方器换成了加法器。实现这个加法器也有两种代码写法,对应两种不同的硬件结构,资源共享如[图 5-23](#图5-23) 所示。
这个例子和前面乘法器的例子非常相似,只是将平方器换成了加法器。实现这个加法器也有两种代码写法,对应两种不同的硬件结构,资源共享如[图 5-23](#fig.5-23) 所示。
<a name="图5-23"></a>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-230-ResourceSharingExample.png!sign" width="700px" alt="资源共享示例"/>
</div>
<a id="fig.5-23"></a>
![图 5-23 资源共享示例](../images/post/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-230-ResourceSharingExample.png){width=700px}
第一种写法,对应左边的 RTL 结构示意图:
```verilog mod_copy1.v
``` verilog mod_copy1.v
module mod_copy1 (sel, a, b, c, d, data_out);
input sel, a, b, c, d;
output data_out;
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
assign data_out= (sel)? (a+b) : (c+d) ;
// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
endmodule
```
第二种写法,对应右边的 RTL 结构示意图:
```verilog mod_copy2.v
``` verilog mod_copy2.v
module mod_copy2 (sel, a, b, c, d, data_out);
input sel, a, b, c, d;
output data_out;
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
wire temp1, temp2;
assign temp1 = (sel) ? (a) : (c) ;
assign temp2 = (sel) ? (b) : (d) ;
assign data_out = temp1 + temp2;
// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
endmodule
```
第一种写法比第二种省了一个加法器。而且第一种写法比第二种写法耗时略少一些,这在本例还不算十分明显,当运算模块不是加法器而是一些较复杂的逻辑时,会比较明显。当**设计的时序满足要求,或者设计的面积紧张时,一般会采用资源共享的优化方法**,将第一种设计转换为第二种设计,绝大多数情况如是;但是**在某些特殊情况下,时序非常紧张,就会反其道而行之,将第二种设计转换为第一种设计**,从而便于调整组合逻辑信号的到达时间,提高这个加法选择器的工作频率。
## 7.4 香农扩展
## 7.4. 香农扩展
前面已经讲到,香农扩展(Shannon Expansion)也是一种逻辑复制、增加面积、提高频率的时序优化手段。
其定义如下,布尔逻辑可以做如下扩展:
$$
$$\begin{equation}
F\left(a,b,c\right) = aF\left(a,b,c\right) +\bar{a}F\left(a,b,c\right)
$$
\end{equation}$$
从上面的定义可以看到,香农扩展即布尔逻辑扩展,是卡诺逻辑化简反向运算,香农扩展相当于逻辑复制,提高频率;而卡诺逻辑化简相当于资源共享,节约面积。
香农扩展通过增加 MUX,从而缩短了某个优先级,但是组合路径长的信号路径时延,从而提高了该关键路径的工作频率。通过下面的例子,会对香农扩展有更全面的理解。
设所需的运算逻辑表达式为:
```verilog
``` verilog
F= ((({8{late}} | in0) + in1) == in2) & en;
```
@@ -1013,7 +1020,7 @@ F= ((({8{late}} | in0) + in1) == in2) & en;
使用香农扩展。
```verilog
``` verilog
F = late.F(late = 1) + ~late.F(late = 0)
= late.[((({8{1'b1}} | i0)+in1) == in2) & en] + ~late.[((({8{11b0}} | in0) + in1) == in2) & en]
= late.[(8'b1 + inl) == in2) & en] + ~late[((in0 + in1) == in2) & en]
@@ -1023,7 +1030,7 @@ F = late.F(late = 1) + ~late.F(late = 0)
未使用香农扩展的 Verilog 代码描述如下:
```verilog un_shannon.v
``` verilog un_shannon.v
module un_shannon (in0, in1, in2, late, en, out);
input [7:0] in0, in1, in2;
input late, en;
@@ -1034,16 +1041,15 @@ assign out = ((({8{late}} | in0) + in1) == in2) & en;
endmodule
```
<a name="图5-24"></a>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-240-BeforeShannonExtension.png!sign" width="" alt="未使用香农扩展前的逻辑表达式对应的RTL视图"/>
</div>
<a id="fig.5-24"></a>
![图 5-24 未使用香农扩展前的逻辑表达式对应的RTL视图](../images/post/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-240-BeforeShannonExtension.png){width=1000px}
从图中可以清晰地看到,未使用香农扩展时,从输入 PAD late 到输出 PAD out 之间共有4 个逻辑单元, 5 段路径。其综合结果使用了 8 个 2 输入或门,1 个 8 bit 输入加法器, 1 个 8 bit 比较器, 1 个 2 输入与门。
使用香农扩展的 Verilog 代码如下:
```verilog shannon_fast.v
``` verilog shannon_fast.v
module shannon_fast (in0, in1, in2, late, en, out);
input [7:0] in0, in1, in2;
input late, en;
@@ -1060,10 +1066,9 @@ assign out = (late) ? late_eq_1 : late_eq_0;
endmodule
```
<a name="图5-25"></a>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-250-AfterShannonExtension.png!sign" width="" alt="香农扩展后的逻辑表达式对应的RTL视图"/>
</div>
<a id="fig.5-25"></a>
![图 5-25 香农扩展后的逻辑表达式对应的RTL视图](../images/post/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-250-AfterShannonExtension.png){width=1000px}
在图中可以清晰地看到,使用香农扩展后,从输入 PAD late 到输出 PAD out 之间共有 1 个逻辑单元,2 段路径。其综合结果使用了 2 个 8 bit 输入加法器, 2 个 8 bit 比较器,2 个输入与门和一个 2 输入选择器。
@@ -1073,20 +1078,25 @@ endmodule
# 8. 小结
[图 5-26](#图5-26) 罗列了 RTL 编码的全面设计目标,它们是:
[图 5-26](#fig.5-26) 罗列了 RTL 编码的全面设计目标,它们是:
- 时序(Timing):要求设计满足预期的时序约束条件,满足预期频率要求。
- 面积(Areag):要求设计所消耗的资源满足所规划的面积要求。
- 时钟(Clocksg):要求设计中的时钟质量满足规划要求。
- 验证(Verificationg):要求设计通过仿真验证的测试。
- 可测试性(DFT, Design For Testg):要求设计时充分考量设计的可测试性。
- 可重用性(Reuseg):希望设计便于被重用,便千继承设计成果。
- 功耗(Powerg):要求设计的最大功耗在规定范围之内。
- 面积(Area):要求设计所消耗的资源满足所规划的面积要求。
- 时钟(Clocks):要求设计中的时钟质量满足规划要求。
- 验证(Verification):要求设计通过仿真验证的测试。
- 可测试性(DFT, Design For Test):要求设计时充分考量设计的可测试性。
- 可重用性(Reuse):希望设计便于被重用,便千继承设计成果。
- 功耗(Power):要求设计的最大功耗在规定范围之内。
- Vendor Policies(原厂的要求):这里主要指 EDA 工具的优化测量和 PLD 或 ASIC 厂方的设计规格与软硬件需求。
<a name="图5-26"></a>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-260-GoalsofRTLCode.png!sign" width="600px" alt="RTL代码的设计目标"/>
</div>
<a id="fig.5-26"></a>
![图 5-26 RTL代码的设计目标](../images/post/2020-12-05-josh-verilog-part-5/2020-12-05-josh-verilog-part-5-260-GoalsofRTLCode.png){width=1000px}
对一个 RTL 设计求全责备地要求它同时满足上述所有目标是非常困难的,应该根据这个RTL 设计的实现载体和具体应用,分析上述要求对本设计的重要性,然后综合考虑以上因素。
# 参考文献
EDA 先锋工作室. *轻松成为设计高手——Verilog HDL 实用精解.* 北京航空航天大学出版社, 2012.
[Part 4——RTL 概念与常用 RTL 建模的 3.10 用 `case` 和 `if ... else` 建模]: https://josh-gao.top/posts/ecb88422.html#toc.3.10
@@ -25,7 +25,7 @@ date: 2020-12-15 11:35:17
| | "Lost" |
|:--:|:------------:|
| Cover | <img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/Album%20Cover/Cher%20Lloyd/Cher%20Lloyd-Lost-Cover.jpg" width=300px/> |
| Cover | <img src="../images/post/Album%20Cover/Cher%20Lloyd/Cher%20Lloyd-Lost-Cover.jpg" width=300px/> |
| Singer | Cher Lloyd |
| Album Type | Single
| Released | 24 April 2020 |
@@ -41,7 +41,7 @@ date: 2021-02-27 15:58:53
```
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2021-02-27-latex-multicolum/2021-02-27-latex-multicolum-010-AllOneColumn.png" width=600px alt="全文单栏效果图"/>
<img src="../images/post/2021-02-27-latex-multicolum/2021-02-27-latex-multicolum-010-AllOneColumn.png" width=600px alt="全文单栏效果图"/>
</div>
### 全文双栏
@@ -53,7 +53,7 @@ date: 2021-02-27 15:58:53
```
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2021-02-27-latex-multicolum/2021-02-27-latex-multicolum-020-AllTwoColumn.png" width=600px alt="全文双栏效果图"/>
<img src="../images/post/2021-02-27-latex-multicolum/2021-02-27-latex-multicolum-020-AllTwoColumn.png" width=600px alt="全文双栏效果图"/>
</div>
### 部分双栏
@@ -79,7 +79,7 @@ date: 2021-02-27 15:58:53
```
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2021-02-27-latex-multicolum/2021-02-27-latex-multicolum-030-PartTwoColumn.png" width=600px alt="部分双栏效果图"/>
<img src="../images/post/2021-02-27-latex-multicolum/2021-02-27-latex-multicolum-030-PartTwoColumn.png" width=600px alt="部分双栏效果图"/>
</div>
### 参考
+3 -3
View File
@@ -1,5 +1,5 @@
---
title: Josh 的学习笔记之多抽样率信号处理 (Part 1 —— 抽样率转换)
title: "Josh's Note — 多抽样率信号处理<br>Part 1 抽样率转换"
mathjax: true
comments: true
copyright: true
@@ -76,7 +76,7 @@ X_s\left( j\Omega \right) =\frac{1}{2\pi}X_c\left( j\Omega \right) \ast \frac{2\
<a id="图1.1"></a>
![图1.1 采样信号与模拟信号的关系](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2021-12-08-josh-msp-part-1/2021-12-08-josh-msp-part-1-010-RelationshipBetweenSampledSignalandAnalogSignal.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/14/dissolve/20/gravity/southeast/dx/5/dy/5){width=500px}
![图1.1 采样信号与模拟信号的关系](../images/post/2021-12-08-josh-msp-part-1/2021-12-08-josh-msp-part-1-010-RelationshipBetweenSampledSignalandAnalogSignal.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/14/dissolve/20/gravity/southeast/dx/5/dy/5){width=500px}
**定理 1.1 (Nyquist-Shannon 采样定理)** 设 $x\left(t\right)$ 是带限信号,频带范围为 $\left(-\Omega_M,\Omega_M\right)$。如果采样率满足
@@ -134,7 +134,7 @@ y_D\left( nT_2 \right) =x\left( nDT_1 \right)
<a id="图1.2"></a>
![图1.2 抽取](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2021-12-08-josh-msp-part-1/2021-12-08-josh-msp-part-1-020-DecimationDemostration.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/14/dissolve/20/gravity/southeast/dx/5/dy/5){width=500px}
![图1.2 抽取](../images/post/2021-12-08-josh-msp-part-1/2021-12-08-josh-msp-part-1-020-DecimationDemostration.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/14/dissolve/20/gravity/southeast/dx/5/dy/5){width=500px}
&emsp;&emsp;上述关系也可以简记为
+237
View File
@@ -0,0 +1,237 @@
---
title: "Josh's Note — 凸优化<br>Part 1.1 凸集—仿射集合和凸集"
mathjax: true
comments: true
copyright: true
sticky: false
toc:
enable: true
number: false
wrap: true
expand_all: true
max_depth: 4
categories:
- - Josh 的学习笔记
- 凸优化
- 凸集
- - 数学
- 凸优化
tags:
- 凸优化
- 凸集
- 仿射
- 锥
abbrlink: 43146ee9
date: 2022-03-29 11:07:04
---
# 1. 直线与线段
$
\newcommand{\bfR}{\mathbf{R}}
\def\aff{\mathop{\bf aff}}
\def\relint{\mathop{\bf relint}}
\def\cl{\mathop{\bf cl}}
\def\conv{\mathop{\bf conv}}
\newcommand{\dd}{\mathrm{d}}
\newcommand{\prob}{\mathbf{prob}}
$&emsp;&emsp;设 $x_1 \ne x_2$ 是 $\bfR^n$ 空间中的两个点,则具有下列形式的点
$$
y = \theta x_1 + (1-\theta)x_2,\theta \in \bfR
$$
组成一条穿过 $x_1$ 和 $x_2$ 的**直线**(*line*)。参数 $\theta = 0$ 和 $\theta = 1$ 分别对应 $y=x_2$ 和 $y = x_1$。参数 $\theta$ 的值在 0 和 1 之间变动,构成了 $x_1$ 和 $x_2$ 之间的(闭)**线段**((closed) *line segment*)。
&emsp;&emsp;另一种 $y$ 的表示形式
$$
y = x_2 + \theta (x_1 - x_2)
$$
可以解释为:$y$ 是**基点**(*base point*)$x_2$(对应 $\theta = 0$)和**方向**(*direction*)$x_1 - x_2$(由 $x_2$ 指向 $x_1$)乘以参数 $\theta$ 的和。因此,$\theta$ 给出了 $y$ 在由 $x_2$ 通向 $x_1$ 的路上的位置。当 $\theta$ 由 $0$ 增加到 $1$,点 $y$ 相应地由 $x_2$ 移动到 $x_1$。如果 $\theta > 1$,点 $y$ 在超越了 $x_1$ 的直线上。[图 1](#图1) 给出了直观的解释。
<a id="图1"></a>
![图 1. 通过 $x_1$ 和 $x_2$ 的直线可以参数化描述为 $\theta x_1 + (1-\theta)x_2$,其中 $\theta$ 在 $\bfR$ 上变化。$x_1$ 和 $x_2$ 之间的线段由深色所示,对应处于 $0$ 和 $1$ 之间的 $\theta$。](../images/post/2022-03-29-josh-cvx-1-1/2022-03-29-josh-cvx-1-1-010-TheLinePassingThroughX1AndX2.png){width=600px}
<!-- more -->
# 2. 仿射集合和凸集
&emsp;&emsp;如果通过集合 $C \subseteq \bfR^n$ 中任意两个不同点的直线仍然在集合 $C$ 中,那么称集合 $C$ 是**仿射**(*affine*)的。也就是说,$C \subseteq \bfR^n$ 是仿射的等价于:对于任意 $x_1, x_2 \in C$ 及 $\theta \in \bfR$ 有 $\theta x_1 + (1-\theta)x_2 \in C$。换言之,$C$ 包含了 $C$ 中任意两点的系数之和为 $1$ 的线性组合。
&emsp;&emsp;这个概念可以扩展到多个点的情况。若 $\theta_1 + \cdots + \theta_k = 1$,则称具有 $\theta_1 x_1 + \cdots + \theta_k x_k$ 形式的点为 $x_1, \cdots, x_k$ 的**仿射组合**(*affine combination*)。利用仿射集合的定义(即仿射集合包含其中任意两点的仿射组合),可以归纳出以下结论:一个仿射集合包含其中任意点的仿射组合,即如果 $C$ 是一个仿射集合,$x_1, \cdots, x_k \in C$,并且 $\theta_1 + \cdots + \theta_k = 1$,那么 $\theta_1 x_1 + \cdots + \theta_k x_k$ 仍然在 $C$ 中。
&emsp;&emsp;如果 $C$ 是一个仿射集合并且 $x_0 \in C$,则集合
$$
V = C - x_0 = \left\{ x - x_0\mid x \in C \right\}
$$
是一个子空间,即关于加法和数乘是封闭的。
> **简单说明**&emsp;设 $v_1, v_2 \in V$,$\alpha, \beta \in \bfR$,则有 $v_1 + x_0 \in C$,$v_2 + x_0 \in C$。因为 $C$ 是仿射的,且 $\alpha + \beta + (1 - \alpha - \beta) = 1$,所以
>
> $$
> \alpha v_1 + \beta v_2 + x_0 = \alpha (v_1 + x_0) + \beta(v_2 + x_0) + (1 - \alpha - \beta)x_0 \in C
> $$
>
> 由 $\alpha v_1 + \beta v_2 + x_0 \in C$,可知 $\alpha v_1 + \beta v_2 \in V$。
&emsp;&emsp;因此,仿射集合 $C$ 可以表示为
$$
C = V + x_0 = \left\{ v + x_0\mid v \in V \right\}
$$
即一个子空间加上一个偏移。与仿射集合 $C$ 相关联的子空间 $V$ 与 $x_0$ 的选取无关,所以 $x_0$ 可以是 $C$ 中的任意一点。定义仿射集合 $C$ 的维数为子空间 $V = C - x_0$ 的维数,其中 $x_0$ 是 $C$ 中的任意元素。
> **举例**&emsp;**线性方程组的解集**。线性方程组的解集 $C = \{x\mid Ax= b\}$ 是一个仿射集合,其中 $A\in\bfR^{m\times n}$,$b \in \bfR^{m}$ 。为说明这点,设 $x_1,x_2\in C$,即 $Ax_1 = b, Ax_2 = b$。则对于任意 $\theta$,有
>
> $$\begin{aligned}
> A(\theta x_1 + (1-\theta)x_2) &= \theta Ax_1 + (1-\theta)Ax_2 \\
> &= \theta b + (1-\theta)b \\
> &= b
> \end{aligned}$$
>
> 这表明任意的仿射组合 $\theta x_1 + (1-\theta)x_2$ 也在 $C$ 中,并且与仿射集合 $C$ 相关联的子空间就是 $A$ 的零空间。
>
> 反之,任意仿射集合可以表示为一个线性方程组的解集。
&emsp;&emsp;由集合 $C \subseteq \bfR^n$ 中的点的所有仿射组合组成的集合称为 $C$ 的**仿射包**(*affine hull*),记为 $\aff{C}$:
$$
\aff{C} = \left\{ \theta_1 x_1 + \cdots + \theta_k x_k\mid x_1, \cdots, x_k \in C, \theta_1 + \cdots + \theta_k = 1 \right\}
$$
仿射包是包含 $C$ 的最小的仿射集合,也就是说:如果 $S$ 是满足 $C \subseteq S$ 的仿射集合,那么 $\aff{C} \subseteq S$。
# 3. 仿射维数与相对内部
&emsp;&emsp;集合 $C$ 的仿射维数定义为其仿射包的维数。仿射维数在凸分析及凸优化中十分有用,但它与其他维数的定义常常不相容。
> **举例**&emsp;考虑 $\bfR^2$ 上的单位圆环 $\left\{x\in\bfR^2\mid x_1^2 + x_2^2 = 1 \right\}$。它的仿射包是全空间 $\bfR^2$,所以其仿射维数为 $2$。但是,在其他大多数维数的定义下,$\bfR^2$ 上的单位圆环的维数为 $1$。
&emsp;&emsp;如果集合 $C \subseteq \bfR^n$ 的仿射维数小于 $n$,那么这个集合在仿射集合 $\aff C \ne \bfR^n$ 中。定义集合 $C$ 的**相对内部**(*relative interior*)为 $\aff C$ 的内部,记为 $\relint C$,即
$$
\relint C = \left\{ x \in C\mid B(x,r) \cap \aff C \subseteq C\ 对于某些\ r > 0 \right\}
$$
其中 $B(x,r) = \left\{ y\mid \left\| y-x \right\| \leqslant r \right\}$,即半径为 $r$,中心为 $x$ 并由范数 $\| \cdot \|$ 定义的球(这里的 $\| \cdot \|$ 可以是任意范数,并且所有范数定义了相同的相对内部)。于是可以定义集合 $C$ 的**相对边界**(*relative boundary*)为 $\cl C\ \setminus \relint C$,此处 $\cl C$ 表示 $C$ 的闭包。
{% note info %}
这里的 “$\setminus$” 表示“集合减”,也即集合 $C$ 的相对边界为其闭包 $\mathbf{cl}\ C$ 减去其相对内部 $\mathbf{relint}\ C$。
{% endnote %}
> **举例**&emsp;考虑 $\bfR^3$ 中处于 $(x_1,x_2)$ 平面的一个正方形,定义
>
> $$
> C = \{x \in \bfR \mid -1\leqslant 1, -1\leqslant x_2\leqslant 1, x_3 = 0\}
> $$
>
> 其仿射包为 $(x_1,x_2)$-平面,即 $\aff C = \{x\in\bfR^3\mid x_3 = 0 \}$。$C$ 的内部为空,但其相对内部为
>
> $$
> \relint C = \{x\in\bfR^3\mid -1<x_1<1,-1<x_2<1,x_3 = 0\}
> $$
>
> $C$(在 $\bfR^3$ 中)的边界是其自身,而相对边界是其边框,
>
> $$
> \{x \in \bfR^3\mid \max\{|x_1|,|x_2|\} = 1,x_3 = 0\}
> $$
# 4. 凸集
&emsp;&emsp;集合 $C$ 被称为**凸集**(*convex set*),如果 $C$ 中任意两点间的线段仍然在 $C$ 中,即对于任意 $x_1, x_2 \in C$ 和满足 $0 \leqslant \theta \leqslant 1$ 的 $\theta$ 都有
$$
\theta x_1 + (1-\theta)x_2 \in C
$$
粗略地看,如果集合中的每一点都可以被其他点沿着它们之间一条无阻碍的路径看见,那么这个集合就是凸集。所谓无阻碍,是指整条路径都在集合中。由于仿射集包含穿过集合中任意不同两点的整条直线,任意不同两点间的线段自然也在集合中。因而仿射集是凸集。[图 2](#图2) 显示了 $\bfR^2$ 空间中一些简单的凸和非凸集合。
<a id="图2"></a>
![图 2. 一些简单的凸和非凸集合。**左**:包含其边界的六边形是凸的。**中**:肾形集合不是凸的,因为图中所示集合中两点间的线段不为集合所包含。**右**:仅包含部分边界的正方形不是凸的。](../images/post/2022-03-29-josh-cvx-1-1/2022-03-29-josh-cvx-1-1-020-SomeSimpleConvexAndNonconvexSets.png){width=1000px}
&emsp;&emsp;集合 $C$ 中所有点的凸组合的集合称为集合 $C$ 的**凸包**(*convex hull*),记为 $\conv C$:
$$
\conv C = \left\{ \theta_1 x_1 + \cdots + \theta_k x_k\mid x_i \in C, \theta_i \geqslant 0, i = 1,\cdots, k, \theta_1 + \cdots + \theta_k = 1 \right\}
$$
顾名思义,凸包 $\conv C$ 总是凸的。它是包含 $C$ 的最小的凸集。也就是说,如果 $B$ 是包含 $C$ 的凸集,那么 $\conv C \subseteq B$。[图 3](#图3) 展示了凸包的定义。
<a id="图3"></a>
![图 3. $\bfR^2$ 上两个集合的凸包。**左**:(如图所示的)十五个点的集合的凸包是一个五边形示)。**右**:[图 2](#图2) 中的肾形集合的凸包是阴影所示的集合。](../images/post/2022-03-29-josh-cvx-1-1/2022-03-29-josh-cvx-1-1-030-TheConvexHullsOfTwoSets.png){width=800px}
{% note info %}
集合 $C$ 的仿射包 $\mathbf{aff}\ C$ 和凸包 $\mathbf{Conv}\ C$ 的区别是参数 $\theta$ 的定义域。可以看出,仿射包 $\mathbf{aff}\ C$ 包含凸包 $\mathbf{Conv}\ C$,因此集合 $C$ 的仿射包是凸集。
{% endnote %}
&emsp;&emsp;凸组合的概念可以扩展到无穷级数、积分以及大多数形式的概率分布。假设 $\theta_1,\theta_2,\cdots$ 满足
$$
\theta_i \geqslant 0, \quad i = 1,2,\cdots,\quad \sum_{i=1}^\infty \theta_i = 1
$$
并且 $x_1, x_2, \cdots \in C$,其中 $C \subseteq \bfR^n$ 为凸集。那么,如果下面的级数收敛,则有
$$
\sum_{i=1}^\infty \theta_i x_i \in C
$$
更一般地,假设 $p:\bfR^n\to\bfR$ 对所有 $x \in C$ 满足 $p(x) \geqslant 0$,并且 $\displaystyle \int_C p(x) \dd x = 1$,其中 $C \subseteq \bfR^n$ 是凸集。那么,如果下面的积分存在,则有
$$
\int_C p(x)x \dd x \in C
$$
&emsp;&emsp;最一般的情况,设 $C \subseteq \bfR^n$ 是凸集,$x$ 是随机变量,并且 $x \in C$ 的概率为 $1$,那么 $\mathbb{E}\{x\} \in C$。事实上,这一形式包含了前述的特殊情况。例如,假设随机变量 $x$ 只在 $x_1$ 和 $x_2$ 中取值,其概率分别为 $\prob(x=x_1) = \theta$ 和 $\prob(x=x_2) = 1-\theta$,其中 $0 \leqslant \theta \leqslant 1$。于是,$\mathbb{E}\{x\} = \theta x_1 + (1-\theta)x_2$,即回到了两个点的简单的凸组合。
# 5. 锥
&emsp;&emsp;如果对于任意 $x \in C$ 和 $\theta \geqslant 0$ 都有 $\theta x \in C$,我们称集合 $C$ 是**锥**(*cone*)或者**非负齐次**(*nonnegative homogeneous*)。如果集合 $C$ 是锥,并且是凸的,则称 $C$ 为**凸锥**(*convex cone*),即对于任意 $x_1, x_2 \in C$ 和 $\theta_1, \theta_2 \geqslant 0$,都有
$$
\theta_1 x_1 + \theta_2 x_2 \in C
$$
在几何上,具有此类形式的点构成了二维的扇形,这个扇形以 $0$ 为顶点,边通过 $x_1$ 和 $x_2$(如[图 4](#图4)所示)。
<a id="图4"></a>
![图 4. 扇形展示了所有具有形式 $\theta_1 x_1 + \theta_2 x_2$ 的点,其中 $\theta_1, \theta_2 \geqslant 0$。扇形的顶点 ($\theta_1 = \theta_2 = 0$) 在 $0$;其边界(对应于 $$\theta_1 = 0$ 或 $\theta_2 = 0$) 穿过点 $x_1$ 和 $x_2$。](../images/post/2022-03-29-josh-cvx-1-1/2022-03-29-josh-cvx-1-1-040-ThePieSlice.png){width=400px}
&emsp;&emsp;具有 $\theta_1 x_1 + \cdots + \theta_k x_k, \theta_1,\cdots,\theta_k \geqslant 0$ 形式的点称为 $x_1,\cdots,x_k$ 的**锥组合**(*conic combination*)(或**非负线性组合**(*nonnegative linear combination*))。如果 $x_i$ 均属于凸锥 $C$,那么,$x_i$ 的每一个锥组合也在 $C$ 中。反言之,集合 $C$ 是凸锥的充要条件是它包含其元素的所有锥组合。如同凸(或仿射)组合一样,锥组合的概念可以扩展到无穷级数和积分中。
&emsp;&emsp;集合 $C$ 的**锥包**(*conic hull*)是 $C$ 中元素的所有锥组合的集合,即
$$
\left\{ \theta_1 x_1 + \cdots + \theta_k x_k\mid x_i \in C, \theta_i \geqslant 0, i = 1,\cdots,k \right\}
$$
它是包含 $C$ 的最小的凸锥(如[图 5](#图5) 所示)。
<a id="图5"></a>
![图 5. [图 3](#图3) 中两个集合的锥包(阴影所示)。](../images/post/2022-03-29-josh-cvx-1-1/2022-03-29-josh-cvx-1-1-050-TheConicHulls.png){width=600px}
{% note info %}
类似仿射包,集合 $C$ 的凸包 $\mathbf{Conv}\ C$ 和锥包的区别是参数 $\theta$ 的定义域。可以看出,锥包包含凸包 $\mathbf{Conv}\ C$,因此集合 $C$ 的锥包是凸集。
{% endnote %}
# 参考文献
1. Stephen P. Boyd and Lieven Vandenberghe, *Convex optimization*. Cambridge, UK: Cambridge University Press, 2004.
2. Stephen P. Boyd and Lieven Vandenberghe, *凸优化*. 北京: 清华大学出版社, 2013.
+230 -207
View File
@@ -1,5 +1,5 @@
---
title: 'Josh''s Notes: SystemVerilog 验证 (Part 1 — 验证导论)'
title: "Josh's Note — SystemVerilog 验证<br>Part 1 验证导论"
mathjax: true
comments: true
copyright: true
@@ -15,243 +15,264 @@ date: 2022-05-30 11:40:49
tags:
- SystemVerilog
- Testbench
- 测试平台
- 验证
categories:
- [Josh 的学习笔记, SystemVerilog]
---
在开始学习有关 System Verilog 语言的细节之前,需要理解如何制订计划来验证手中的设计,以及整个验证计划对 testbench 结构的影响。就像所有房子都有厨房、卧室和浴室一样,所有 testbench 也都需要共享一些用于产生激励、检验响应的结构。本文对 testbench 的构建和设计给出一些引导性的建议和编码风格方面的参考,以满足不同的需要。
&emsp;&emsp;在开始学习有关 SystemVerilog 语言的细节之前,我们需要了解如何制订计划来验证手中的设计,以及这个验证计划对测试平台(testbench)结构的影响。所有测试平台都有用于产生激励、检验响应的结构。本文对测试平台的构建和设计给出一些引导性的建议和编码风格方面的参考,以满足不同的需要。
验证工程师能学到的最重要的原则是“Bugs are good”,不要因为害怕 bug 而不敢 debug,每次找到 bug 都应该及时告警并记录下来。任何一个项目中都不可能没有 bug,所以在流片之前每发现一个 bug 都意味着用户手中的产品少一个 bug。我们应该尽可能细致深入地去检验设计,找出所有可能存在的 bug,尽管有时候这些 bug 可能很容易修复。
&emsp;&emsp;对于验证工程师而言,最重要的原则是“有漏洞是好事(Bugs are good)”,要勇于寻找程序中的漏洞,每次找到漏洞都应该及时告警并记录下来。任何一个项目中都不可能没有漏洞,所以在流片之前每发现一个漏洞都意味着用户手中的产品少一个漏洞。我们应该尽可能细致深入地去检验设计,找出所有可能存在的漏洞,尽管有时候这些漏洞可能很容易修复。
本文需要 Verilog 语言基础,面向对 SystemVerilog HVL (Hard­ware Verification Language, 硬件验证语言) 感兴趣的读者。与 HDL (Hardware Desription Language, 硬件描述语言) 相比,HVL 具有一些特别的性质:
&emsp;&emsp;本文需要 Verilog 语言基础,面向对 SystemVerilog HVL(Hard­ware Verification Language,硬件验证语言)感兴趣的读者。与 HDL(Hardware Description Language,硬件描述语言)相比,HVL 具有一些特别的性质:
1. **约束下的随机激励生成** (*Constrained-random stimulus generation*)。
2. **功能覆盖率** (*Functional coverage*)。
3. **更高层次的结构**,尤其是面向对象的编程 (*Higher-level structures*, especially object-oriented programming)。
4. **多线程**及线程间的通信 (*Multithreading* and interprocess communication)。
5. **支持 HDL 数据类型** (*Support for HDL types* such as Verilog’s 4-state values)。
6. **集成了事件仿真器**,便于对设计施加控制 (*Tight integration with event-simulator* for control of the design)。
1. **受约束的随机激励生成**(*Constrained-random stimulus generation*)。
上述特性使得 HVL 可以创建高度抽象的 testbench,其抽象层次比使用 HDL 或计算机编程语言如 C 所能达到的还要高。
2. **功能覆盖率**(*Functional coverage*)。
3. **更高层次的结构**,尤其是面向对象的编程(*Higher-level structures*, especially object-oriented programming)。
4. **多线程**及线程间的通信(*Multithreading* and interprocess communication)。
5. **支持 HDL 数据类型**(*Support for HDL types*)。
6. **集成了事件仿真器**,便于对设计施加控制(*Tight integration with event-simulator* for control of the design)。
&emsp;&emsp;此外还有其他很多有用的特性,但上述特性使得 HVL 可以创建高度抽象的测试平台,其抽象层次比使用 HDL 或计算机编程语言(如 C 语言)所能达到的还要高。
<!-- more -->
# 1. 验证流程
验证的目的是什么?如果说是为了“寻找 bug”,那也只答对了一部分。硬件设计的目的是设计一个**基于设计规范并能完成特定任务的设计**,例如 DVD 播放器、路由器或者雷达信号处理器。验证工程师需要**确保这些设计能够成功地完成预定的任务**——也就是说,确保**设计能够准别表达这些规范**;而设计在超出预定目标之外的行为可以不用关心。
&emsp;&emsp;验证的目的是什么?如果说是为了“寻找漏洞”,那只答对了一部分。硬件设计的目的是设计一个**基于设计规范并能完成特定任务的设备**,例如 DVD 播放器、路由器或者雷达信号处理器。验证工程师需要**确保这些设备能够成功地完成预定的任务**——也就是说,该设计是**对规范的一种准确表达**;而设计在超出预定目标之外的行为可以不用关心。
验证和设计是并行的流程。对于每个设计模块,设计者需要首先了解硬件设计规范/设计输入,理解其中设计需求,然后使用 RTL 代码之类的机器语言创建相应的逻辑。为了完成这个过程,设计者需要知道输入格式、传输函数以及输出格式。在理解设计需求的过程中总是会有模糊的地方,可能因为是设计输入文档本身的表述不清楚,遗漏了细节或者前后不一致。验证工程师必须阅读硬件规范并拟定验证计划,然后按照计划,创建测试来检查 RTL 代码是否准确地实现了满足了所有的规范。
&emsp;&emsp;验证和设计是**并行**的流程。对于每个设计模块,设计工程师需要首先了解硬件设计规范/设计输入,理解其中的设计需求,然后使用 RTL 等的机器语言创建相应的逻辑。为了完成这个过程,设计工程师需要知道输入格式、传输函数以及输出格式。在理解设计需求的过程中总会有一定模糊(ambiguity),可能因为是设计输入文档本身的表述不清楚,遗漏了细节或者前后不一致。验证工程师必须阅读硬件规范并拟定验证计划,然后按照计划,创建测试来检查 RTL 代码是否准确地实现了所有的特性。
如果有多人按照同一规范进行解读,那么设计流程可能会出现冗余。验证工程师的工作是阅读同样的硬件设计规范并对其含义做出独立的判断,然后利用测试来检查对应的 RTL 代码是否与理解相一致。
&emsp;&emsp;如果有多人按照同一规范进行解读,那么设计流程可能会出现冗余。验证工程师的工作是阅读同样的硬件设计规范并对其含义做出独立的判断,然后利用测试来检查对应的 RTL 代码是否与理解相一致。
## 1.1. 不同层次上的测试
## 1.1. 不同层次的测试
设计中会潜藏着哪些类型的 bug 呢?最容易检测的是在**代码块 (*block*) 层次**上,代码块由每个设计者在模块 (module) 内创建。ALU (Arithmetic-Logic Unit, 运算逻辑单元) 是否正确地执行了两个数的加法?是否每个总线传输都能够成功完成?是否所有的数据包都经过了网络交换机?为了找出这些 bug 而去编写定向测试是一件十分繁琐的事情,原因是这些 bug 都被包含在设计的代码块里。
&emsp;&emsp;设计中会潜藏着哪些类型的漏洞呢?最容易检测的是在**代码块(*block*)层次**上,代码块由每个设计工程师在模块(module)内创建。ALU(Arithmetic-Logic Unit,运算逻辑单元)是否正确地执行了两个数的加法?是否每次总线传输都能够成功完成?是否所有的数据包都经过了网络交换机?为了找出这些漏洞而去编写定向测试是一件十分繁琐的事情,因为这些漏洞都被包含在设计的代码块里。
除了代码块以外,代码块的**输入输出接口**也是 bug 丛生的地方,通常是因为多个设计者对同一规范产生了不同理解。对于一个给定的协议,什么信号发生了变化?在什么时候变化?第一个设计者按照自己对规范的理解建立了一个总线驱动器,第二个设计者也按照自己的理解建立了一个总线接收器,但两者对规范的理解略有不同。我们的工作就是找到两者在硬件逻辑上有冲突的地方,然后将两者进行统一。
&emsp;&emsp;除了代码块以外,代码块的**输入输出接口**也是容易出现漏洞的地方,通常是因为多个设计工程师对同一规范产生了不同理解。对于一个给定的协议,什么信号发生了变化?在什么时候变化?第一个设计工程师按照自己对规范的理解建立了一个总线驱动器,第二个设计工程师也按照自己的理解建立了一个总线接收器,但两者对规范的理解略有不同。**验证工程师的工作就是找到两者在硬件逻辑上有冲突的地方,然后将两者进行统一。**
为了对一个代码块进行仿真,我们需要创建测试集来模拟周围代码块产生激励,这是一件困难而繁琐的事情。好消息是低层次的仿真运行起来会很快。但是,随着代码块数量的增加,可能会在设计和 testbench 中同时找到 bug,因为 testbench 为了提供足够的激励,代码也会很长。当开始对所有的代码块进行合并测试时,它们也会相互激励,测试负担就会相对减少。多个代码块同时仿真可能会发现更多的 bug,但是运行起来也会慢一些。
&emsp;&emsp;为了对一个代码块进行仿真,我们需要创建测试集来模拟周围代码块产生激励,这是一件困难而繁琐的事情。虽然低层次的仿真运行起来会很快,但是随着代码块数量的增加,可能会在设计和测试平台中同时找到漏洞,因为测试平台为了提供足够的激励,代码量也会很长。当开始对所有的代码块进行合并测试时,它们也会相互激励,测试负担就会相对减少。多个代码块同时仿真可能会发现更多的漏洞,但是运行起来也会慢一些。
在 DUT (Design under Test, DUT) 的最高层次中,整个系统都会被测试,但是仿真过程会简单很多。我们的测试应该尽可能让所有的代码块并发活动。所有的输入输出端口都被激活,处理器正在处理数据,而高速缓存也正在载入数据。有了这些行为以后,数据分配和时序上的 bug 肯定会出现。
&emsp;&emsp;在 DUT(Design under Test,待测设计)的最高层次中,整个系统都会被测试,但是仿真过程会简单很多。我们的测试应该尽可能让所有的代码块并发活动。所有的输入输出端口都被激活,处理器正在处理数据,而高速缓存也正在载入数据。有了这些行为以后,数据分配和时序上的漏洞肯定会出现。
在这个层次上,能够运行更加精细的测试,可以**让 DUT 并发执行多种操作以激活尽可能多的代码块**。如果一个 MP3 播放器正在播放音乐时,用户希望从计算机上下载新的音乐会发生什么?在下载的过程中,用户在播放器上按键又会发生什么?显然,一个实际的设备在被使用时,有些用户会去做这些事情,那为什么不在设备制造之初去做同样的测试呢?这种测试可以把易于使用的产品和经常发生故障的产品区分开来。
&emsp;&emsp;在这个层次能够运行更加精细的测试,可以**让 DUT 并发执行多种操作以激活尽可能多的代码块**。如果一个 MP3 播放器正在播放音乐时,用户希望从计算机上下载新的音乐会发生什么?在下载的过程中,用户在播放器上按键又会发生什么?显然,一个实际的设备在被使用时,有些用户会去做这些事情,那为什么不在设备制造之初去做同样的测试呢?这种测试可以把易于使用的产品和经常发生故障的产品区分开来。
一旦验证了 DUT 能够执行所有预期的功能以后,还需要看一下当出现错误时 DUT 会怎样操作。设计是否能应对只进行了一半的事件,已经受损的数据或控制字段?想要列举出所有可能的问题就很困难,更不用说去判断设计会如何从这些错误中恢复了。所以**错误注入和处理 (Error Injection and Handling) 是验证中最具挑战性的部分**。
&emsp;&emsp;一旦验证了 DUT 能够执行所有预期的功能以后,还需要看一下当出现错误时 DUT 会怎样操作。设计是否能应对只进行了一半的事件,已经受损的数据或控制字段?想要列举出所有可能的问题就很困难,更不用说去判断设计会如何从这些错误中恢复了。所以**错误注入和处理(Error Injection and Handling)是验证中最具挑战性的部分**。
随着设计抽象层次的提高,验证的挑战性也会加大。我们可以确定单个信元是否正确通过 ATM (Asynchronous Transfer Mode, 异步传输模式) 路由器,但如果是一系列有着不同优先权的数据流呢?在最高的抽象层次中,下一个操作应该选择哪个信元并不是显而易见的,可能不得不统计成千上万的信元,以便确定这种集总的操作是否正确。
&emsp;&emsp;随着设计抽象层次的提高,验证的挑战性也会加大。我们可以确定单个信元是否正确通过 ATM(Asynchronous Transfer Mode,异步传输模式)路由器,但如果是一系列有着不同优先权的数据流呢?在最高的抽象层次中,下一个操作应该选择哪个信元并不是显而易见的,可能不得不统计成千上万的信元,以便确定这种集总的操作是否正确。
最后,**我们永远也无法证明没有任何遗留的 bug**,所以需要不停地尝试新的验证策略。
&emsp;&emsp;最后,**我们永远也无法证明没有任何遗留的漏洞**,所以需要不停地尝试新的验证策略。
## 1.2. 验证计划
验证计划和硬件规范是紧密联系在一起的,它描述了需要验证什么样的特性,以及采用哪些技术。这些步骤可能包含有定向测试 (directed test) 或随机测试 (random test) 、断言 (assertion)、软硬件协同验证 (HW/SW co-verification)、硬件仿真 (emulation)、形式验证 (formal proof),以及对验证 IP 的使用等等。有关验证更全面的讨论,可参见 Bergeron 的 *Verification Methodology Manual for
SystemVerilog* (2006)。
&emsp;&emsp;验证计划和硬件规范是紧密联系在一起的,它描述了需要验证什么样的特性,以及采用哪些技术。这些步骤可能包含有定向测试(directed testing)或随机测试(random testing)、断言(assertion)、软硬件协同验证(HW/SW co-verification)、硬件仿真(emulation)、形式验证(formal proof),以及对验证 IP 的使用等等。有关验证更全面的讨论,可参见 Bergeron 的 *Verification Methodology Manual for
SystemVerilog*(2006)。
# 2. Testbench 的基本功能
# 2. 测试平台的基本功能
Testbench 的用途在于**确定 DUT 的正确性**。包含下列步骤:
&emsp;&emsp;测试平台的用途在于**确定 DUT 的正确性**。包含下列步骤:
1. 产生激励。
2. 把激励施加到 DUT 上。
3. 捕捉响应。
4. 检验正确性。
5. 对照整个验证目标测算进展情况。
1. 产生激励。
有些步骤是 testbench 自动完成的,有些则需要手动操作,所选择的验证方法学决定了上述步骤如何展开。
2. 把激励施加到 DUT 上。
3. 捕捉响应。
4. 检验正确性。
5. 对照整个验证目标测算进展情况。
&emsp;&emsp;有些步骤是测试平台自动完成的,有些则需要手动操作,所选择的验证方法学(methodology)决定了上述步骤如何展开。
# 3. 定向测试
当需要验证一个设计的正确性时,传统的做法可能是使用定向测试。使用这种方式,首先需要阅读硬件规范,然后写下验证计划,计划上列有各种测试,每个测试针对一系列相关的特性。按照这个计划,接着**编写针对 DUT 具体特性的激励向量,然后使用这些向量对 DUT 进行仿真**。仿真结束后,手动查看一下结果文件和波形,确保设计的行为与预期的一致。一旦测试结果正确,就可以开始下一个测试。
&emsp;&emsp;当需要验证一个设计的正确性时,传统的做法可能是使用**定向测试**(*directed testing*)。使用这种方式,首先需要阅读硬件规范,然后写下验证计划,计划上列有各种测试,每个测试针对一系列相关的特性。按照这个计划,接着**编写针对 DUT 具体特性的激励向量,然后使用这些向量对 DUT 进行仿真**。仿真结束后,手动查看一下结果文件和波形,确保设计的行为与预期的一致。一旦测试结果正确,就可以开始下一个测试。
这种渐进的方法比较容易取得稳步的进展,因而很受那些喜欢看到项目持续向前推进管理者的欢迎。由于创建每个激励向量时并不需要什么基础,所以定向测试的结果也会很快得到。只要给予足够的时间和人力,定向测试对于大部分设计验证来讲都是可以胜任的。
&emsp;&emsp;这种渐进的方法比较容易取得稳步的进展,因而很受那些喜欢看到项目持续向前推进的管理者的欢迎。由于创建每个激励向量时并不需要什么基础,所以定向测试的结果也会很快得到。只要给予足够的时间和人力,定向测试对于大部分设计验证来讲都是可以胜任的。
[图 1.1](#图1.1) 显示了定向测试如何逐步覆盖验证计划中的每个特性。每个测试都针对一个特别的设计元素集合。**如果有足够的时间**,可以写出 100% 覆盖整个验证计划所需要的全部测试。
&emsp;&emsp;[图 1](#图1) 显示了定向测试如何逐步覆盖验证计划中的每个特性。每个测试都针对一个特别的设计元素集合。**如果有足够的时间**,可以写出 100% 覆盖整个验证计划所需要的全部测试。
<span id="图1.1"></span>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2022-05-30-josh-systemverilog-1/2022-05-30-josh-systemverilog-1-010-DirectedTestProgressOverTime.png" width=500px alt="图 1.1 定向测试随时间的进展"/>
</div>
<a id="图1"></a>
如果没有足够的时间和资源来完成定向测试该怎么办?如[图 1.1](#图1.1),当在时间往前推进时,覆盖率 (coverage) 可能维持不变。如果设计复杂度翻倍,那么测试就需要增加一倍的时间或者人力,而这种情况是我们所不愿意看到的。因此为了达到 100% 覆盖率的目标,需要一种可以更快找出 bug 的方法。
![图 1. 定向测试随时间的进展](../images/post/2022-05-30-josh-systemverilog-1/2022-05-30-josh-systemverilog-1-010-DirectedTestProgressOverTime.png){width=500px}
[图 1.2](#图1.2) 所示为整个设计空间和各种特性被定向测试案例覆盖的情形。在设计空间里有很多特性 (feature),其中有些存在 bug,需要编写各种测试 (test) 去覆盖所有的特性并找出 bug。
&emsp;&emsp;如果没有足够的时间和资源来完成定向测试该怎么办?如[图 1](#图1),当在时间往前推进时,覆盖率(coverage)可能维持不变。如果设计复杂度翻倍,那么测试就需要增加一倍的时间或者人力,而这种情况是我们所不愿意看到的。因此为了达到 100% 覆盖率的目标,需要一种可以更快找出漏洞的方法。
<span id="图1.2"></span>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2022-05-30-josh-systemverilog-1/2022-05-30-josh-systemverilog-1-020-DirectedTestCoverage.png" width=800px alt="图 1.2 定向测试的覆盖率"/>
</div>
&emsp;&emsp;[图 2](#图2) 所示为整个设计空间和各种特性被定向测试案例覆盖的情形。在设计空间里有很多特性(feature),其中有些存在漏洞,需要编写各种测试(test)去覆盖所有的特性并找出漏洞。
<a id="图2"></a>
![图 2. 定向测试的覆盖率](../images/post/2022-05-30-josh-systemverilog-1/2022-05-30-josh-systemverilog-1-020-DirectedTestCoverage.png){width=800px}
# 4. 方法学基础
本文使用如下原则:
&emsp;&emsp;本文使用如下原则:
1. 约束下的随机激励。
2. 功能覆盖率。
3. 使用事件处理器的分层 testbench。
4. 对所有测试通用的 testbench。
5. 独立于 testbench 之外的个性化测试代码。
1. 受约束的随机激励。
这些原则是相关联的。随机激励对于测试复杂设计十分关键。**定向测试可以找出设计中预期的 bug,而随机测试则能够找出预料不到的 bug**。当使用随机激励时,需要用功能覆盖率来评估验证的进展情况。一旦开始使用自动生成的激励,就需要一种能够**自动预测结果**的方式——通常是记分板或者参考模型。建立包括自预测在内的 testbench 基础设施,是一件工作量很大的事情。分层 testbench (layered testbench) 能够把问题分解为容易处理的小块,这样有助于控制复杂度。事件处理器 (transactors) 能够为构建这些小块提供有用的模式。在适当的规划下,可以建立一个 testbench 所需的基础设施,它们能在所有测试中通用并且不需要经常修改,只需要在某些地方放置“hook”,以便测试能够在这些地方执行调整激励或注入错误等特定操作。相反,针对单一测试的个性化代码必须与 testbench 分开,这样可以避免增加基础设施的复杂度。
2. 功能覆盖率。
建立这种风格的 testbench 所需的时间要比传统的定向 testbench 多得多——尤其是自检的部分。其结果是,可能需要很长的准备时间才能进行第一次可运行的测试。这会给项目管理带来阵痛,所以需要在测试时间表上把这部分考虑进去。从[图 1.3](#图1.3) 中可以看到,第一个随机测试运行前有比较长的初始延迟。
3. 使用事件处理器的分层测试平台。
<span id="图1.3"></span>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2022-05-30-josh-systemverilog-1/2022-05-30-josh-systemverilog-1-030-ConstraineRandomTestProgressOverTimeVSDirectedTesting.png" width=500px alt="图 1.3 约束下的随机测试与定向测试随时间的进度比较"/>
</div>
4. 对所有测试通用的测试平台。
随机测试的前期准备工作看起来似乎令人不满意,但是其回报却很高。每个随机测试都可以共享这个通用的 testbench,不像每个定向测试都要从零开始编写。每个随机测试都会包含一部分代码,将激励约束到特定的方向上并触发期望的异常,比如创建一个协议违例。其结果是,约束下的随机 testbench 找起 bug 来会比很多定向测试快很多。随着 bug 出现率的下降,应该创建新的随机约束去探索新的区域。最后的几个 bug 可能只能通过定向测试来发现,但是绝大部分的 bug 都应该会在随机测试中出现。
5. 独立于测试平台之外的个性化测试代码。
# 5. 约束下的随机激励<a name="05"></a>
&emsp;&emsp;些原则是相关联的。随机激励对于测试复杂设计十分关键。**定向测试可以找出设计中预期的漏洞,而随机测试则能够找出预料不到的漏洞**。当使用随机激励时,需要用功能覆盖率来评估验证的进展情况。一旦开始使用自动生成的激励,就需要一种能够**自动预测结果**的方式——通常是记分板(scoreboard)或者参考模型(reference model)。建立包括自预测在内的测试平台是一件工作量很大的事情。**分层测试平台**(*layered testbench*)能够把问题分解为容易处理的小块,这样有助于控制复杂度。**事件处理器**(*transactors*)能够为构建这些小块提供有用的模式(pattern)。在适当的规划下,可以建立一个测试平台所需的基础设施,它们能在所有测试中通用并且不需要经常修改,只需要在某些地方放置“钩子(hook)”,以便测试能够在这些地方执行调整激励或注入错误等特定操作。相反,针对单一测试的个性化代码必须与测试平台分开,这样可以避免增加基础设施的复杂度。
虽然我们希望仿真器能产生随机激励,但同时又**不希望这些激励数值完全随机**。使用 SystemVerilog 语言可以描述激励的格式 (例如,地址是 32 位;操作码是 ADD 、 SUB 或 STORE;长度 < 32 字节),然后让仿真器产生满足约束的数值。这些数值会被发送到设计中去,同时也会被发送到一个负责预测仿真结果的高层模块中去。设计的实际输出最终需要和预测输出做对比。
&emsp;&emsp;建立这种风格的测试平台所需的时间要比传统的定向测试平台多得多,尤其是自检的部分,因此可能需要很长的准备时间才能进行第一次可运行的测试。这会给项目管理带来阵痛,所以需要在测试时间表上把这部分考虑进去。从[图 3](#图3) 中可以看到,第一个随机测试运行前有比较长的初始延迟。
[图 1.4](#图1.4) 所示为约束下的随机测试在整个设计空间中的覆盖率。
<a id="图3"></a>
- 值得注意的是,**一个随机测试的覆盖范围往往比一个定向测试大**。多出来的覆盖部分可能会与其他测试发生交叠,或者探测到事先没有预料到的新区域 (new area)。
- 在这些新区域中发现 bug 是一件幸运的事情。如果这些对新区域的测试不合法,则需要编写更多的约束去阻止随机测试产生非法的功能。
- 对于那些约束下的随机测试覆盖不到的地方,可能还需要编写一些定向测试。
![图 3. 受约束的随机测试与定向测试随时间的进度比较](../images/post/2022-05-30-josh-systemverilog-1/2022-05-30-josh-systemverilog-1-030-ConstraineRandomTestProgressOverTimeVSDirectedTesting.png){width=500px}
<span id="图1.4"></span>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2022-05-30-josh-systemverilog-1/2022-05-30-josh-systemverilog-1-040-ConstrainedRandomTestCoverage.png" width=800px alt="图 1.4 约束下的随机测试覆盖率"/>
</div>
&emsp;&emsp;随机测试的前期准备工作看起来似乎令人不满意,但是其回报却很高。每个随机测试都可以共享这个通用的测试平台,不像每个定向测试都要从零开始编写。每个随机测试都会包含一部分代码,将激励约束到特定的方向上并触发期望的异常,比如创建一个协议违例(protocol violation),受约束的随机测试平台找起漏洞来会比很多定向测试快很多。
[图 1.5](#图1.5) 所示为达到完全覆盖的技术路线:
&emsp;&emsp;随着漏洞出现率的下降,应该创建新的随机约束去探索新的区域。最后的几个漏洞可能只能通过定向测试来发现,但是绝大部分的漏洞都应该会在随机测试中出现。
1. 从左上角的基本的约束下的随机测试 (constrained random test) 开始,使用不同的种子 (seed) 运行。
2. 当我们查看功能覆盖率 (functional covrage) 报告时,注意找出覆盖率中的间隙 (hole),即覆盖盲区。
3. 针对这些盲区进行最小程度代码修改 (mininal code midification),可能是使用新的约束 (constraint),也可能是把错误或延迟加入到 DUT 中。这个外部循环会花掉我们大部分的时间,只有对少数使用随机测试达不到的特性才编写定向测试。
# 5. 受约束的随机激励<a name="05"></a>
<span id="图1.5"></span>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2022-05-30-josh-systemverilog-1/2022-05-30-josh-systemverilog-1-050-CoverageConvergence.png" width=500px alt="图 1.5 覆盖率收敛"/>
</div>
&emsp;&emsp;虽然我们希望仿真器能产生随机激励,但同时又**不希望这些激励数值完全随机**。使用 SystemVerilog 语言可以描述激励的格式(例如,地址是 32 位;操作码是 ADD、 SUB 或 STORE;长度 < 32 字节),然后让仿真器产生满足约束的数值。这些数值会被发送到设计中去,同时也会被发送到一个负责预测仿真结果的高层模块中去。设计的实际输出最终需要和预测输出做对比。
&emsp;&emsp;[图 4](#图4) 所示为受约束的随机测试在整个设计空间中的覆盖率。
- 值得注意的是,**一个随机测试的覆盖范围往往比一个定向测试大**。多出来的覆盖部分可能会与其他测试发生交叠,或者探测到事先没有预料到的新区域(new area)。
- 在这些新区域中发现漏洞是一件幸运的事情。如果这些对新区域的测试不合法,则需要编写更多的约束去阻止随机测试产生非法的功能。
- 对于那些受约束的随机测试覆盖不到的地方,可能还需要编写一些定向测试。
<a id="图4"></a>
![图 4. 受约束的随机测试覆盖率](../images/post/2022-05-30-josh-systemverilog-1/2022-05-30-josh-systemverilog-1-040-ConstrainedRandomTestCoverage.png){width=800px}
&emsp;&emsp;[图 5](#图5) 所示为达到完全覆盖的技术路线:
1. 从左上角的基本的受约束的随机测试(constrained random test)开始,使用不同的种子(seed)运行。
2. 当我们查看功能覆盖率(functional coverage)报告时,注意找出覆盖率中的间隙(hole),即覆盖盲区。
3. 针对这些盲区进行最小程度代码修改(minimal code modification),可能是使用新的约束(constraint),也可能是把错误或延迟加入到 DUT 中。这个外部循环会花掉我们大部分的时间,只有对少数使用随机测试达不到的特性才编写定向测试。
<a id="图5"></a>
![图 5. 覆盖率收敛](../images/post/2022-05-30-josh-systemverilog-1/2022-05-30-josh-systemverilog-1-050-CoverageConvergence.png){width=500px}
# 6. 我们的随机化对象是什么<a name="06"></a>
当考虑对一个设计的激励进行随机化时,首先想到的可能是数据字段。这种激励最容易创建——只需调用 `$random()` 即可。问题是这种随机数据在找 bug 方面的回报很小。能够使用随机数据找到的 bug 类型基本上都是在数据路径上的,很可能还都是比特级的错误,还需要找出**控制逻辑上的 bug**。
&emsp;&emsp;当考虑对一个设计的激励进行随机化时,首先想到的可能是数据字段。这种激励最容易创建——只需调用 `$random()` 即可。问题是这种随机数据在找漏洞方面的回报很小。能够使用随机数据找到的漏洞类型基本上都是在数据路径上的,很可能还都是比特级的错误,还需要找出**控制逻辑上的漏洞**。
此外,需要广泛地考虑所有的设计输入,如下所列:
&emsp;&emsp;此外,需要广泛地考虑所有的设计输入,如下所列:
1. 设备配置。
2. 环境配置。
3. 输入数据。
4. 协议异常。
5. 错误和违例。
6. 时延。
1. 设备配置。
2. 环境配置。
3. 输入数据。
4. 协议异常。
5. 错误和违例。
6. 时延。
## 6.1. 设备和环境配置
在对 RTL 设计进行测试的过程中,察觉不到 bug 的最常见的原因是什么?是因为**没有尝试足够多的不同配置**。很多测试只使用了仅仅经过复位的设计,或者施加固定的初始化向量集把设计引向一个已知的状态。这就好比是在个人电脑上刚刚安装完操作系统,还没有安装任何应用程序的时候,就对操作系统进行测试。测试结果当然会很好,但是并没有挖掘出实际的问题。
&emsp;&emsp;在对 RTL 设计进行测试的过程中,察觉不到漏洞的最常见的原因是什么?是因为**没有尝试足够多的不同配置(*configuration*)**。很多测试只使用了仅仅经过复位的设计,或者施加固定的初始化向量集把设计引向一个已知的状态。这就好比是在个人电脑上刚刚安装完操作系统,还没有安装任何应用程序的时候,就对操作系统进行测试。测试结果当然会很好,但是并没有挖掘出实际的问题。
在一个实际的应用环境中,随着 DUT 使用时间的增加,其配置会变得越来越随机。例如,验证一个分时复用的多路开关,它有 2000 个输入通道和 12 个输出通道。这些通道在另外一边可以映射成各种不同的配置。每个输入可能作为单个通道使用,也可能会被进一步分割成多个通道。棘手的是,虽然大部分时间里使用的是几种标准的通道分割方式,但由于其他分割方式的组合也是合法的,所以存在着大量可能的用户配置。
> &emsp;&emsp;在一个实际的应用环境中,随着 DUT 使用时间的增加,其配置会变得越来越随机。例如,验证一个分时复用的多路开关,它有 2000 个输入通道和 12 个输出通道。这些通道在另外一边可以映射成各种不同的配置。每个输入可能作为单个通道使用,也可能会被进一步分割成多个通道。棘手的是,虽然大部分时间里使用的是几种标准的通道分割方式,但由于其他分割方式的组合也是合法的,所以存在着大量可能的用户配置。
>
> &emsp;&emsp;为了测试这个设备,对于每个通道的配置,工程师都必须写出好几十行的定向测试代码。显然,验证工程师无力应对如此多的通道配置。后来编写了一个测试平台,对每个通道的参数都采用随机化策略,然后把这部分代码放到一个循环里去完成所有开关通道的配置。现在,找出与配置相关的漏洞变得更加容易,而这些漏洞在以前常常不被察觉。
为了测试这个设备,对于每个通道的配置,工程师都必须写出好几十行的定向测试代码。显然,验证工程师无力应对如此多的通道配置。后来编写了一个 testbench,对每个通道的参数都采用随机化策略,然后把这部分代码放到一个循环里去完成所有开关通道的配置。现在,找出与配置相关的 bug 变得更加容易,而这些 bug 在以前常常不被察觉。
&emsp;&emsp;在实际的应用中,我们的设计所在的环境里会包含其他的部件。当对 DUT 进行验证时,实际上就是把测试平台连接起来模仿这个环境,应该对整个环境的配置进行随机化,包括仿真的时长、设备的数量,以及它们的配置方式。当然,需要创建约束以确保配置的合法性。
在实际的应用中,我们的设计所在的环境里会包含其他的部件。当对 DUT 进行验证时,实际上就是把 testbench 连接起来模仿这个环境,应该对整个环境的配置进行随机化,包括仿真的时长、设备的数量,以及它们的配置方式。当然,需要创建约束以确保配置的合法性。
> &emsp;&emsp;在另外一个 Synopsys 公司的客户案例中,一家公司设计了一个 I/O 交换芯片,用于把多套 PCI 总线连接到一套内部总线上。在仿真一开始,他们就随机地选择了 PCI 总线的数目(1\~4)以及总线上设备的数目(1\~8),而且对每个设备上的参数也进行了随机化(如主从模式、 CSR 地址等等)。他们使用功能覆盖率对测试过的组合进行跟踪,以确保所有可能的组合都被覆盖。
在另外一个 Synopsys 公司的客户案例中,一家公司设计了一个 I/O 交换芯片,用于把多套 PCI 总线连接到一套内部总线上。在仿真一开始,他们就随机地选择了 PCI 总线的数目 (1~4) 以及总线上设备的数目 (1~8),而且对每个设备上的参数也进行了随机化(如主从模式、 CSR 地址等等)。他们使用功能覆盖率对测试过的组合进行跟踪,以确保所有可能的组合都被覆盖。
其他环境参数还包括测试长度、错误注入比率,以及时延模式等。Bergeron (2006) 在这方面有更多的例子。
&emsp;&emsp;其他环境参数还包括测试长度、错误注入比率,以及时延模式等。Bergeron(2006)在这方面有更多的例子。
## 6.2. 输入数据
当看到随机激励时,我们可能会想到**选取一个总线写入的事件或 ATM 信元,然后把随机数值填充到其中的数据字段里**。实际上,这种方式相当直接,需要事先估计好所有的分层协议和错误注入,以及记分板的内容和功能覆盖率。
&emsp;&emsp;当看到随机激励时,我们可能会想到**选取一个总线写入的事件或 ATM 信元,然后把随机数值填充到其中的数据字段里**。实际上,这种方式相当直接,需要事先估计好所有的分层协议和错误注入,以及记分板的内容和功能覆盖率。
## 6.3. 协议异常、错误和违例
最令人沮丧的事情莫过于个人电脑或移动电话之类的设备死机。大多数情况下,唯一的办法就是关机然后重新启动。死机最有可能的原因是,产品内部的一部分逻辑遇到了错误以后无法恢复过来,因此使得设备不能正常工作。
&emsp;&emsp;最令人沮丧的事情莫过于个人电脑或移动电话之类的设备死机。大多数情况下,唯一的办法就是关机然后重新启动。死机最有可能的原因是,产品内部的一部分逻辑遇到了错误以后无法恢复过来,因此使得设备不能正常工作。
如何才能阻止这些问题出现在我们创建的硬件上呢?应该尽量尝试去仿真在实际的硬件中可能出现的错误,而且应该针对所有可能出现的错误。如果一个总线事件没有完成会怎么样?如果遇到一个非法的操作呢?设计规范中有没有指出哪两个信号互斥?要对这些情况一一尝试,然后确保设备还能继续正常运作。
&emsp;&emsp;如何才能阻止这些问题出现在我们创建的硬件上呢?应该尽量尝试去仿真在实际的硬件中可能出现的错误,而且应该针对所有可能出现的错误。如果一个总线事件没有完成会怎么样?如果遇到一个非法的操作呢?设计规范中有没有指出哪两个信号互斥?要对这些情况一一尝试,然后确保设备还能继续正常运作。
**在尝试使用不当的命令去激励硬件的同时,也应该注意捕捉出现的问题**。例如,重新调用那些互斥的信号。可以增加用于检验的代码来帮忙找出问题所在。这些代码应该至少能够在出错的地方打印一个警告信息,如果能够报告出错误并且使测试停下来则更好。花费大最时间在代码中追溯故障的根源,是一件令人非常不愉快的事情,尤其是在本来如果使用一个简单的断言就可以定位这个错误的情况下。(关于如何在 testbench 和设计代码中编写断言,可以参考 Vijayaraghavan 和 Ramanathan 在 2005 出版的著作。) 只要确保能够使代码在出错的地方停止仿真,那么就很容易应对测试中的错误。
&emsp;&emsp;**在尝试使用不当的命令去激励硬件的同时,也应该注意捕捉出现的问题**。例如,重新调用那些互斥的信号。可以增加用于检验的代码来帮忙找出问题所在。这些代码应该至少能够在出错的地方打印一个警告信息,如果能够报告出错误并且使测试停下来则更好。花费大最时间在代码中追溯故障的根源,是一件令人非常不愉快的事情,尤其是在本来如果使用一个简单的断言就可以定位这个错误的情况下。(关于如何在测试平台和设计代码中编写断言,可以参考 Vijayaraghavan 和 Ramanathan 在 2005 出版的著作。)只要确保能够使代码在出错的地方停止仿真,那么就很容易应对测试中的错误。
## 6.4. 时延和同步
Testbench 应该以多快的速度发送激励呢?使用**约束下的随机时延**有助于捕捉协议上的 bug。时延最短的测试运行速度最快,但它产生不了所有可能的激励。可以创建一个 testbench 以最快的速度与另一个代码块通信,但那些隐蔽的 bug 往往是在引入间歇性时延之后才被发现的。
&emsp;&emsp;测试平台应该以多快的速度发送激励呢?使用**受约束的随机时延**有助于捕捉协议上的漏洞。时延最短的测试运行速度最快,但它产生不了所有可能的激励。可以创建一个测试平台以最快的速度与另一个代码块通信,但那些隐蔽的漏洞往往是在引入间歇性时延之后才被发现的。
一个代码块对于来自同一接口的所有可能激励也许都能正常工作,但如果同时面对多个输入,隐蔽的 bug 可能就会出现。尝试协调各个驱动器使它们能够在不同的速率下进行通信。如果输入以可能的最快速率到达,而输出却被卡在一个较低的速率上,该怎么办?如何处理来自多个输人的激励同时到达的情况?如果这此激励带有不同的时延又该怎么办?使用功能覆盖率,可以测量随机生成的各种组合。
&emsp;&emsp;一个代码块对于来自同一接口的所有可能激励也许都能正常工作,但如果同时面对多个输入,隐蔽的漏洞可能就会出现。尝试协调各个驱动器使它们能够在不同的速率下进行通信。如果输入以可能的最快速率到达,而输出却被卡在一个较低的速率上,该怎么办?如何处理来自多个输人的激励同时到达的情况?如果这此激励带有不同的时延又该怎么办?使用功能覆盖率,可以测量随机生成的各种组合。
## 6.5. 并行的随机测试
如何运行测试?每个定向测试都带有一个 testbench,能够产生一组特定的激励和响应向量。如果想改变激励,就需要改变测试。随机测试则包含了 testbench 代码和随机种子。如果对同一个测试运行 50 次,每次都采用不同的种子,那么将会得到 50 个不同的激励集合。使用多个种子运行同一个测试可以加大覆盖率,同时也能减少工作量。
&emsp;&emsp;如何运行测试?每个定向测试都带有一个测试平台,能够产生一组特定的激励和响应向量。如果想改变激励,就需要改变测试。随机测试则包含了测试平台代码和随机种子。如果对同一个测试运行 50 次,每次都采用不同的种子,那么将会得到 50 个不同的激励集合。使用多个种子运行同一个测试可以加大覆盖率,同时也能减少工作量。
我们需要**为每次仿真选定一个独特的种子**。有些人使用自然时间作为种子,但这依然会引起重复。如果半夜里在一个计算机集群系统上开始 10 项任务会怎么样?多项任务可能会于同一时间在不同的计算机上启动,这样还是会得到相同的随机种子并运行相同的激励。因此,应该把处理器的名称加入到种子里去。如果集群系统里面有多核计算机,那还是可能会出现两个相同的种子,所以在这种情况下应该把处理器核的编号也加到种子里去,这样就能得到独一无二的种子了。
&emsp;&emsp;我们需要**为每次仿真选定一个独特的种子**。有些人使用自然时间作为种子,但这依然会引起重复。如果半夜里在一个计算机集群系统上开始 10 项任务会怎么样?多项任务可能会于同一时间在不同的计算机上启动,这样还是会得到相同的随机种子并运行相同的激励。因此,应该把处理器的名称加入到种子里去。如果集群系统里面有多核计算机,那还是可能会出现两个相同的种子,所以在这种情况下应该把处理器核的编号也加到种子里去,这样就能得到独一无二的种子了。
> 我们还需要对并行仿真的文件组织进行规划。每次仿真都会有一系列的输出文件,例如日志文件和功能覆盖率文件,可以让每个仿真在不同的目录里运行,或者也可以尝试给每个文件取不同的名字。最简单的办法是在目录名后面加上随机种子的值。
{% note info %}
&emsp;&emsp;我们还需要对并行仿真的文件组织进行规划。每次仿真都会有一系列的输出文件,例如日志文件和功能覆盖率文件,可以让每个仿真在不同的目录里运行,或者也可以尝试给每个文件取不同的名字。最简单的办法是在目录名后面加上随机种子的值。
{% endnote %}
# 7. 功能覆盖率
本文[第 5 节](#05)和[第 6 节](#06)讲述了如何创建激励并使这些激励遍历整个可能的输入空间。使用这种方法,Testbench 会频繁访问部分区域,但需要花费很长的时间来达到所有可能的状态。即使对仿真时间不加限制,无法达到的状态还是永远也不会被访问到,因此需要知道哪些部分已经被验证过,这样才能对验证计划中的项目进行核对。
&emsp;&emsp;本文[第 5 节](#05)和[第 6 节](#06)讲述了如何创建激励并使这些激励遍历整个可能的输入空间。使用这种方法,测试平台会频繁访问部分区域,但需要花费很长的时间来达到所有可能的状态。即使对仿真时间不加限制,无法达到的状态还是永远也不会被访问到,因此需要知道哪些部分已经被验证过,这样才能对验证计划中的项目进行核对。
对功能覆盖率的测量和使用包含了几个步骤。首先,需要在 testbench 中加入代码,用于监控进入设备中的激励,以及设备对激励的反应,并据此确定哪些功能已经被验证过。运行几次仿真,每次使用不同的种子。接下来,把这些仿真的结果合并到一个报告中。然后需要对结果进行分析,最后决定如何采用新的激励来达到那些尚未被测试到的条件和逻辑。
&emsp;&emsp;对功能覆盖率的测量和使用包含了几个步骤。首先,需要在测试平台中加入代码,用于监控进入设备中的激励,以及设备对激励的反应,并据此确定哪些功能已经被验证过。运行几次仿真,每次使用不同的种子。接下来,把这些仿真的结果合并到一个报告中。然后需要对结果进行分析,最后决定如何采用新的激励来达到那些尚未被测试到的条件和逻辑。
## 7.1. 从功能覆盖率到激励的反馈
随机测试需要使用反馈 (feedback)。最初的测试会被运行很多次,使用不同的种子,创建很多互异的输入序列。但是到了最后,即使使用新的种子,所产生的激励也很可能无法在设计空间中探测到新区域。**随着功能覆盖率逐渐接近极限,需要改变测试,以期能找出新的方法去达到那些尚未被覆盖的区域**。这被称为“覆盖率驱动的验证”,如[图 1.6](#图1.6) 所示。
&emsp;&emsp;随机测试需要使用反馈(feedback)。最初的测试会被运行很多次,使用不同的种子,创建很多互异的输入序列。但是到了最后,即使使用新的种子,所产生的激励也很可能无法在设计空间中探测到新区域。**随着功能覆盖率逐渐接近极限,需要改变测试,以期能找出新的方法去达到那些尚未被覆盖的区域**。这被称为“覆盖率驱动的验证”,如[图 6](#图6) 所示。
<span id="图1.6"></span>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2022-05-30-josh-systemverilog-1/2022-05-30-josh-systemverilog-1-060-TestProgressWithAndWithoutFeedback.png" width=500px alt="图 1.6 带反馈和不带反馈的测试进展"/>
</div>
<a id="图6"></a>
Testbench 有没有可能为我们做到这一点呢?假设现在需要使用 testbench 在每个周期为处理器产生一个总线事件,并为总线事件做出终止判断(成功、校验错误、重试)。在没有使用 HVL 的时候,通常会编写一个很长的定向测试集,然后花费了很多天的工夫编排终止判断代码,并让它们在合适的周期里给出判断。经过了大量的手动分析以后才得出成功的结论达到 100 %的覆盖率。但之后可能由于处理器的时序有了一点微小的改变,不得不重新分析测试并改变激励。
![图 6. 带反馈和不带反馈的测试进展](../images/post/2022-05-30-josh-systemverilog-1/2022-05-30-josh-systemverilog-1-060-TestProgressWithAndWithoutFeedback.png){width=500px}
更加有效的测试策略是**使用随机总线事件和终止判断**。运行的时间越长,覆盖率就会越高。另外的一个好处是,这种测试在创建激励时灵活性很高,足以应对设计时序有改变的情形。为了做到这一点,可以在测试代码中加入一个反馈循环,用于监测己生成的激励 (是否已经产生所有写周期?) 并根据情况调整约束的权重 (把写的权重降到零)。这种改进能大大缩减达到完全覆盖的时间,而且只需要很少量的人工干预。
&emsp;&emsp;测试平台有没有可能为我们做到这一点呢?假设现在需要使用测试平台在每个周期为处理器产生一个总线事件,并为总线事件做出终止判断(成功、校验错误、重试)。在没有使用 HVL 的时候,通常会编写一个很长的定向测试集,然后花费了很多天的工夫编排终止判断代码,并让它们在合适的周期里给出判断。经过了大量的手动分析以后才得出成功的结论达到 100 %的覆盖率。但之后可能由于处理器的时序有了一点微小的改变,不得不重新分析测试并改变激励。
其实,这并不是一种典型的情况,因为从功能覆盖率到激励的反馈往往是微不足道的。在实际的设计中,应该如何改变激励以使它达到一个期望的设计状态呢?这不仅要求对设计有深入的了解,而且还需要高超的形式验证技术。总之答案并不简单,所以**在约束下的随机激励中很少采用动态反馈**。相反地,**需要手动分析覆盖率报告,然后调整随机约束**。
&emsp;&emsp;更加有效的测试策略是**使用随机总线事件和终止判断**。运行的时间越长,覆盖率就会越高。另外的一个好处是,这种测试在创建激励时灵活性很高,足以应对设计时序有改变的情形。为了做到这一点,可以在测试代码中加入一个反馈循环,用于监测己生成的激励(是否已经产生所有写周期?)并根据情况调整约束的权重(把写的权重降到零)。这种改进能大大缩减达到完全覆盖的时间,而且只需要很少量的人工干预。
有些形式分析工具如 Magellan (Synopsys, 2003) 用到了反馈。它首先对设计进行分析并找出所有可以达到的互异状态。然后运行一小段仿真看有多少状态被访问到。最后,在状态机和设计输入之间进行搜索并计算出达到所有遗留状态所需要的激励,然后 Ma­gellan 再把这些激励施加到 DUT 上。
&emsp;&emsp;其实,这并不是一种典型的情况,因为从功能覆盖率到激励的反馈往往是微不足道的。在实际的设计中,应该如何改变激励以使它达到一个期望的设计状态呢?这不仅要求对设计有深入的了解,而且还需要高超的形式验证技术。总之答案并不简单,所以**在受约束的随机激励中很少采用动态反馈**。相反地,**需要手动分析覆盖率报告,然后调整随机约束**。
# 8. Testbench 的构建
&emsp;&emsp;有些形式分析工具如 Magellan(Synopsys, 2003)用到了反馈。它首先对设计进行分析并找出所有可以达到的互异状态。然后运行一小段仿真看有多少状态被访问到。最后,在状态机和设计输入之间进行搜索并计算出达到所有遗留状态所需要的激励,然后 Ma­gellan 再把这些激励施加到 DUT 上。
在仿真时,**testbench 会把整个 DUT 包围起来**,就像一个硬件测试器连接到一个物理芯片上一样,如[图 1.7](#图1.7) 所示。testbench 和测试仪器都会产生激励并捕捉响应。不同的是,testbench 需要工作在一个很宽的抽象层次范围内,同时创建事件和激励序列并最终转换成比特向量。而测试仪器则只工作在比特级上。
# 8. 测试平台的构建
<span id="图1.7"></span>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2022-05-30-josh-systemverilog-1/2022-05-30-josh-systemverilog-1-070-TheTestbenchDesignEnvironment.png" width=450px alt="图 1.7 Testbench 与设计环境"/>
</div>
&emsp;&emsp;在仿真时,**测试平台会把整个 DUT 包围起来**,就像一个硬件测试器连接到一个物理芯片上一样,如[图 7](#图7) 所示。测试平台和测试仪器都会产生激励并捕捉响应。不同的是,测试平台需要工作在一个很宽的抽象层次范围内,同时创建事件和激励序列并最终转换成比特向量。而测试仪器则只工作在比特级上。
Testbench 模块里都包含了什么呢?有很多的 BFM (Bus Functional Models, 总线功能模型),可以把它们看成是 testbench 构件 (components) ——从 DUT 的角度看,它们和真实的构件没什么两样,但它们其实只是 testbench 的组成部分,并非 RTL 设计。如果实际应用中设备被连接到 AMBA、USB、PCI 和 SPI 总线上,那么就必须**在 testbench 中建立能够产生激励并校验响应的等效构件**,如[图 1.8](#图1.8) 所示。这些构件并不是带有细节的可综合模型,而是遵循协议并且执行速度更快的高层次事件处理器。如果把设计原型在 FPGA 上实现或者是进行硬件仿真,那么这些 BFM 就需要是可综合的。
<a id="图7"></a>
<span id="图1.8"></span>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2022-05-30-josh-systemverilog-1/2022-05-30-josh-systemverilog-1-080-TestbenchComponents.png" width=450px alt="图 1.8 Testbench 构件"/>
</div>
![图 7. 测试平台与设计环境](../images/post/2022-05-30-josh-systemverilog-1/2022-05-30-josh-systemverilog-1-070-TheTestbenchDesignEnvironment.png){width=450px}
# 9. 分层 testbench
&emsp;&emsp;测试平台模块里都包含了什么呢?有很多的 BFM(Bus Functional Models, 总线功能模型),可以把它们看成是测试平台构件(components)——从 DUT 的角度看,它们和真实的构件没什么两样,但它们其实只是测试平台的组成部分,并非 RTL 设计。如果实际应用中设备被连接到 AMBA、USB、PCI 和 SPI 总线上,那么就必须**在测试平台中建立能够产生激励并校验响应的等效构件**,如[图 8](#图8) 所示。这些构件并不是带有细节的可综合模型,而是遵循协议并且执行速度更快的高层次事件处理器。如果把设计原型在 FPGA 上实现或者是进行硬件仿真,那么这些 BFM 就需要是可综合的。
对于任何一种新型的验证方法学来讲,分层的 testbench 是一个关键的概念。虽然分层似乎会使 testbench 变得更复杂,但它能够把代码分而治之,**有助于减轻工作负担**。不要试图去编写一个包含所有功能 (随机产生所有合法和非法的激励,并使用多层协议进行错误注入) 的子程序,因为这样的子程序很快就会变得很复杂,并且难以维护。
<a id="图8"></a>
## 9.1. 不分层的 testbench
![图 8. 测试平台构件](../images/post/2022-05-30-josh-systemverilog-1/2022-05-30-josh-systemverilog-1-080-TestbenchComponents.png){width=450px}
在刚开始学习 Verilog 并尝试写测试程序的时候,这些程序看起来可能会和[例 1.1](#例1.1) 所示的用于执行一个简单 APB (AMBA Peripheral Bus, AMBA 外设总线)写入的低层次代码很相似。
# 9. 分层测试平台
<span id="例1.1"></span>
&emsp;&emsp;对于任何一种新型的验证方法学来讲,分层的测试平台是一个关键的概念。虽然分层似乎会使测试平台变得更复杂,但它能够把代码分而治之,**有助于减轻工作负担**。不要试图去编写一个包含所有功能(随机产生所有合法和非法的激励,并使用多层协议进行错误注入)的子程序,因为这样的子程序很快就会变得很复杂,并且难以维护。
``` verilog 例 1.1 驱动 APB 引脚
## 9.1. 不分层的测试平台
&emsp;&emsp;在刚开始学习 Verilog 并尝试写测试程序的时候,这些程序看起来可能会和[例 1.1](#例1.1) 所示的用于执行一个简单 APB(AMBA Peripheral Bus, AMBA 外围总线)写入的低层次代码很相似。
<a id="例1.1"></a>
``` verilog 例 1.1. 驱动 APB 引脚
module test(PAddr,PWrite,PSel,PWData,PEnable,Rst,clk);
// 此处省略端口声明
@@ -283,11 +304,11 @@ module test(PAddr,PWrite,PSel,PWData,PEnable,Rst,clk);
endmodule
```
经过几天连续编写这种代码以后,我们可能会意识到这是一种重复性的劳动,所以会尝试创建可用于总线写入这种普通操作的任务,如[例 1.2](#例1.2) 所示。
&emsp;&emsp;经过几天连续编写这种代码以后,我们可能会意识到这是一种重复性的劳动,所以会尝试创建可用于总线写入这种普通操作的任务,如[例 1.2](#例1.2) 所示。
<span id="例1.2"></span>
<a id="例1.2"></a>
``` verilog 例 1.2 一个用于驱动 APB 引脚的任务
``` verilog 例 1.2. 一个用于驱动 APB 引脚的任务
task write(reg [15:0] addr, reg [31:0] data);
// 驱动控制总线
@(posedge clk)
@@ -304,11 +325,11 @@ task write(reg [15:0] addr, reg [31:0] data);
endtask
```
这样,testbench 就会变得简单一些,如[例 1.3](#例1.3)。
&emsp;&emsp;这样,测试平台就会变得简单一些,如[例 1.3](#例1.3)。
<span id="例1.3"></span>
<a id="例1.3"></a>
``` verilog 例 1.3 低层次的 Verilog 测试
``` verilog 例 1.3. 低层次的 Verilog 测试
module test(PAddr,PWrite,PSel,PWData,PEnable,Rst,clk);
// 此处省略端口声明
// 此处省略如例 1.2 给出的任务函数
@@ -318,7 +339,7 @@ module test(PAddr,PWrite,PSel,PWData,PEnable,Rst,clk);
write(16'h50, 32'h50); // 把数据写入到存储器中
// 校验结果
if (top.mem.memory[16'h50] == 32'h50)
if(top.mem.memory[16'h50] == 32'h50)
$display("Success");
else
$display("Error, wrong value in memory");
@@ -327,140 +348,142 @@ module test(PAddr,PWrite,PSel,PWData,PEnable,Rst,clk);
endmodule
```
通过把一些通用的操作 (如复位、总线读出和总线写入) 放到一个子程序中,可以提高工作效率并减少错误。这里,物理和命令层的建立只是通往分层 testbench 的第一步。
&emsp;&emsp;通过把一些通用的操作(如复位、总线读出和总线写入)放到一个子程序中,可以提高工作效率并减少错误。这里,物理和命令层的建立只是通往分层测试平台的第一步。
## 9.2. 信号和命令层
[图 1.9](#图1.9) 所示为一个 testbench 中最低的几个层次。
&emsp;&emsp;[图 9](#图9) 所示为一个测试平台中最低的几个层次。
<span id="图1.9"></span>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2022-05-30-josh-systemverilog-1/2022-05-30-josh-systemverilog-1-090-SignalAndCommandLlayers.png" width=500px alt="图 1.9 信号和命令层"/>
</div>
<a id="图9"></a>
在底部的**信号层** (*signal*),包含 DUT 和把 DUT 连接到 testbench 的信号。
![图 9. 信号和命令层](../images/post/2022-05-30-josh-systemverilog-1/2022-05-30-josh-systemverilog-1-090-SignalAndCommandLlayers.png){width=500px}
再往上一层是**命令层** (*command*)。执行总线读写命令的驱动器驱动 DUT 的输入。DUT 的输出与监视器 (monitor) 相连,监视器负责检测信号的变化,并把这些变化按照命令分组。断言 (assertion) 也穿过命令层和信号层,它们负责监视独立的信号以寻找穿越整个命令的信号变化。
&emsp;&emsp;在底部的**信号层**(*signal*),包含 DUT 和把 DUT 连接到测试平台的信号。
&emsp;&emsp;再往上一层是**命令层**(*command*)。执行总线读写命令的驱动器驱动 DUT 的输入。DUT 的输出与监视器(monitor)相连,监视器负责检测信号的变化,并把这些变化按照命令分组。断言(assertion)也穿过命令层和信号层,它们负责监视独立的信号以寻找穿越整个命令的信号变化。
## 9.3. 功能层
[图 1.10](#图1.10) 给出了为加上**功能层** (*functional*) 的 testbench,功能层向下面对的是命令层。代理 (agent, 在 VMM 中称为事件处理器) 接收到来自上层的事件,例如,DMA 读或写,把它们分解成独立的命令。这些命令也被送往用于预测事件结果的记分板 (scoreboard)。检验器 (checker) 则负责比较来自监视器和记分板的命令。
&emsp;&emsp;[图 10](#图10) 给出了为加上**功能层**(*functional*)的测试平台,功能层向下面对的是命令层。代理(agent, 在 VMM 中称为事件处理器)接收到来自上层的事件,例如,DMA 读或写,把它们分解成独立的命令。这些命令也被送往用于预测事件结果的记分板(scoreboard)。检验器(checker)则负责比较来自监视器和记分板的命令。
<span id="图1.10"></span>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2022-05-30-josh-systemverilog-1/2022-05-30-josh-systemverilog-1-100-TestbenchWithFunctionalLlayerAdded.png" width=500px alt="图 1.10 加上功能层的 testbench"/>
</div>
<a id="图10"></a>
![图 10. 加上功能层的测试平台](../images/post/2022-05-30-josh-systemverilog-1/2022-05-30-josh-systemverilog-1-100-TestbenchWithFunctionalLlayerAdded.png){width=500px}
## 9.4. 场景层
[图 1.11](#图1.11) 所示,功能层被位于**场景层** (*scenario*) 中的发生器 (generator) 所驱动。什么是场景呢?记住一点,验证工程师的工作是确保 DUT 能够完成预期的任务。比如 MP3 播放器,它能一边播放事先存储好的音乐,一边从一台主机上下载新的音乐,并且同时对用户输入如音量调整或音轨控制等操作保持响应。这中间的每一个操作都能称为一个场景。下载一个音乐文件需要若于步骤,例如前期准备时的控制寄存器的读写操作,歌曲传送过程中多次 DMA 写操作,以及之后的很多读写操作。场景层就是负责组织协调这些步骤的,操作的参数如音轨大小和寄存器位置等都采用约束下的随机值。
&emsp;&emsp;[图 11](#图11) 所示,功能层被位于**场景层**(*scenario*)中的发生器(generator)所驱动。什么是场景呢?记住一点,验证工程师的工作是确保 DUT 能够完成预期的任务。比如 MP3 播放器,它能一边播放事先存储好的音乐,一边从一台主机上下载新的音乐,并且同时对用户输入如音量调整或音轨控制等操作保持响应。这中间的每一个操作都能称为一个场景。下载一个音乐文件需要若于步骤,例如前期准备时的控制寄存器的读写操作,歌曲传送过程中多次 DMA 写操作,以及之后的很多读写操作。场景层就是负责组织协调这些步骤的,操作的参数如音轨大小和寄存器位置等都采用受约束的随机值。
<span id="图1.11"></span>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2022-05-30-josh-systemverilog-1/2022-05-30-josh-systemverilog-1-110-TestbenchWithScenarioLayerAdded.png" width=500px alt="图 1.11 加上场景层的 testbench"/>
</div>
<a id="图11"></a>
在 testbench **环境** (*environment*) 中的这些块 ([图 1.11](#图1.11) 虚线框内) 是在刚开始开发的时候画出来的。随着项目的进展,它们可能会有一些变化,也可能会加入一些功能,但是这些块对于每个独立的测试都是不应改变的。可以通过在代码中留下“hook”来做到这一点,这样即使这些块的行为需要在测试时改变,也不必重新编写代码。“hook”可以使用工厂模式 (factory patterns) 和回调函数 (callbacks) 来创建。
![图 11. 加上场景层的测试平台](../images/post/2022-05-30-josh-systemverilog-1/2022-05-30-josh-systemverilog-1-110-TestbenchWithScenarioLayerAdded.png){width=500px}
&emsp;&emsp;在测试平台**环境**(*environment*)中的这些块([图 11](#图11)虚线框内)是在刚开始开发的时候画出来的。随着项目的进展,它们可能会有一些变化,也可能会加入一些功能,但是这些块对于每个独立的测试都是不应改变的。可以通过在代码中留下“钩子”来做到这一点,这样即使这些块的行为需要在测试时改变,也不必重新编写代码。“钩子”可以使用工厂模式(factory patterns)和回调函数(callbacks)来创建。
## 9.5. 测试的层次和功能覆盖率
现在到了 testbench 的最顶层——测试层,如[图 1.12](#图1.12)。DUT 模块间的 bug 是比较难以发现的,因为这些模块可能是不同的人按照不同的规范设计出来的。
&emsp;&emsp;现在到了测试平台的最顶层——测试层,如[图 12](#图12)。DUT 模块间的漏洞是比较难以发现的,因为这些模块可能是不同的人按照不同的规范设计出来的。
<span id="图1.12"></span>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2022-05-30-josh-systemverilog-1/2022-05-30-josh-systemverilog-1-120-FullTestbenchWithAllLayers.png" width=500px alt="图 1.12 带着所有层次的完整 testbench"/>
</div>
<a id="图12"></a>
这个顶层的测试 (test) 就像一个指挥官:他不演奏任何乐器,但引领着其他人的表演。测试包含了用于创建激励的约束。
![图 12. 带着所有层次的完整测试平台](../images/post/2022-05-30-josh-systemverilog-1/2022-05-30-josh-systemverilog-1-120-FullTestbenchWithAllLayers.png){width=500px}
功能覆盖率 (fonctional coverage) 可以衡量所有测试在满足验证计划要求方面的进展。随着各项测量标准的完成,功能覆盖率代码在整个项目过程中会经常变化。由于代码经常被修改,所以它不作为测试环境的组成部分。
&emsp;&emsp;这个顶层的测试(test)就像一个指挥官:他不演奏任何乐器,但引领着其他人的表演。测试包含了用于创建激励的约束。
我们可以在约束下的随机环境中创建“定向测试”。只需在随机序列中间插入定向测试的代码,或者把两部分代码并列。定向代码执行期望的任务,而随机的“背景噪声”可能会使 bug 暴露出来,而且 bug 还有可能来自从未被关注过的模块。
&emsp;&emsp;功能覆盖率(functional coverage)可以衡量所有测试在满足验证计划要求方面的进展。随着各项测量标准的完成,功能覆盖率代码在整个项目过程中会经常变化。由于代码经常被修改,所以它不作为测试环境的组成部分。
Testbench 中是否需要所有的层次呢?答案要视 DUT 而定。设计越复杂,所需的 testbench 就要越完备。测试层则是必须的。对于一个简单的设计来说,场景层可能过于简单以至于可以把它合并到代理中。
&emsp;&emsp;我们可以在受约束的随机环境中创建“定向测试”。只需在随机序列中间插入定向测试的代码,或者把两部分代码并列。定向代码执行期望的任务,而随机的“背景噪声”可能会使漏洞暴露出来,而且漏洞还有可能来自从未被关注过的模块。
当然,可能还需要更多的层次。如果 DUT 有多个协议层,那么每个层都应该在 testbench 环境中有对应的层。例如使用 IP 封装了 TCP 流量,然后通过以太网数据包的形式发送,对这种情况的测试应该考虑使用三个独立的层来产生和校验数据,如
&emsp;&emsp;测试平台中是否需要所有的层次呢?答案要视 DUT 而定。设计越复杂,所需的测试平台就要越完备。测试层则是必须的。对于一个简单的设计来说,场景层可能过于简单以至于可以把它合并到代理中。
&emsp;&emsp;当然,可能还需要更多的层次。如果 DUT 有多个协议层,那么每个层都应该在测试平台环境中有对应的层。例如使用 IP 封装了 TCP 流量,然后通过以太网数据包的形式发送,对这种情况的测试应该考虑使用三个独立的层来产生和校验数据,如
果能够使用已有的验证构件则更好。
[图 1.12](#图1.12) 中需要注意的最后一点是,它只给出了各块之间一些可能的连接方式,testbench 模块间的连接可能会与之不同。比如测试层可能需要连接到驱动器层以迫使物理 bug 出现。这里给出的只是一些引导——实际当中应该是,需要什么就创建什么。
&emsp;&emsp;[图 12](#图12) 中需要注意的最后一点是,它只给出了各块之间一些可能的连接方式,测试平台模块间的连接可能会与之不同。比如测试层可能需要连接到驱动器层以迫使物理漏洞出现。这里给出的只是一些引导——实际当中应该是,需要什么就创建什么。
# 10. 建立一个分层的 testbench
# 10. 建立一个分层的测试平台
现在是学习如何把前面图示的那些构件映射成 SystemVerilog 结构时候了。
&emsp;&emsp;现在是学习如何把前面图示的那些构件映射成 SystemVerilog 结构时候了。
## 10.1. 创建一个简单的驱动器
首先,来仔细看看其中的一个模块——驱动器。[图 1.13](#图1.13) 所示的驱动器接收来自代理的命令。驱动器可能会注入错误或者增加时延,然后再把命令分解成一些信号的变化,例如总线请求或握手。这样一个 testbench 模块通常被称为“事件处理器 (transactor)”,它的核心部分是一个循环:有关事件处理器的示范代码如[例 1.4](#例1.4) 所示。
&emsp;&emsp;首先,来仔细看看其中的一个模块——驱动器。[图 13](#图13) 所示的驱动器接收来自代理的命令。驱动器可能会注入错误或者增加时延,然后再把命令分解成一些信号的变化,例如总线请求或握手。这样一个测试平台模块通常被称为“事件处理器(transactor)”,它的核心部分是一个循环:有关事件处理器的示范代码如[例 1.4](#例1.4)所示。
<span id="图1.13"></span>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2022-05-30-josh-systemverilog-1/2022-05-30-josh-systemverilog-1-130-ConnectionsForTheDriver.png" width=120px alt="图 1.13 带着所有层次的完整 testbench"/>
</div>
<a id="图13"></a>
<span id="例1.4"></span>
![图 13. 带着所有层次的完整测试平台](../images/post/2022-05-30-josh-systemverilog-1/2022-05-30-josh-systemverilog-1-130-ConnectionsForTheDriver.png){width=120px}
``` verilog 例 1.4 基本的事件处理器代码
<a id="例1.4"></a>
``` verilog 例 1.4. 基本的事件处理器代码
task run();
done = 0;
while (!done) begin
// 获取下一个事件
// 进行变换
// 发送事件
end
done = 0;
while (!done) begin
// 获取下一个事件
// 进行变换
// 发送事件
end
endtask
```
后序的文章给出了:
&emsp;&emsp;后序的文章给出了:
- 基本的 OOP 以及如何创建一个对象并使对象里面包含事件处理器所需要的子程序和数据,事件处理器的另一个例子是代理,它可能会把一个复杂的事件如 DMA 读分解成多个总线命令;
- 如何创建一个对象并使对象里面包含构成一个命令所需要的数据和子程序。使用 SystemVerilog 信箱可以实现这些对象在不同的事件处理器之间传递;
- 还将介绍很多方法,用于在不同层之间交换数据并使事件处理器实现同步。
# 11. 仿真环境的阶段
到目前为止,已经学习了环境的构成部分。这些部分在什么时候执行呢?我们希望把各个阶段清楚地定义好,以便协调 testbench,使项目中的所有代码能在一起工作。三个基本的阶段是建立 (build)、运行 (run) 和收尾 (wrap-up)。每个阶段都可以再细分为更小的步骤。
&emsp;&emsp;到目前为止,已经学习了环境的构成部分。这些部分在什么时候执行呢?我们希望把各个阶段清楚地定义好,以便协调测试平台,使项目中的所有代码能在一起工作。三个基本的阶段是建立(build)、运行(run)和收尾(wrap-up)。每个阶段都可以再细分为更小的步骤。
**建立阶段**可以分为如下步骤。
&emsp;&emsp;**建立阶段**可以分为如下步骤。
1. **生成配置** (*Generate configuration*):把 DUT 的配置和周围的环境随机化。
2. **建立环境** (*Build environment*):基于配置来分配和连接 testbench 构件。Testbench 构件指的是存在于 testbench 中的部分,注意与设计中的物理构件区分开,后者是采用 RTL 代码描述的。例如,如果配置选择了三个总线驱动器,那么 testbench 应该在这个阶段对它们进行分配和初始化。
3. **对 DUT 进行复位** (*Reset the DUT.*)。
4. **配置 DUT** (*Configure the DUT*):基于第一步中生成的配置,载入 DUT 的命令寄存器。
1. **生成配置**(*Generate configuration*):把 DUT 的配置和周围的环境随机化。
**运行阶段**是指测试实际运行的阶段,可分为以下步骤。
2. **建立环境**(*Build environment*):基于配置来分配和连接测试平台构件。测试平台构件指的是存在于测试平台中的部分,注意与设计中的物理构件区分开,后者是采用 RTL 代码描述的。例如,如果配置选择了三个总线驱动器,那么测试平台应该在这个阶段对它们进行分配和初始化。
1. **启动环境** (*Start environment*):运行 testbench 构件,例如各种 BFM 和激励发生器。
2. **运行测试** (*Run the test*):启动测试然后等待测试完成。定向测试的完成很容易判断,但随机测试却比较困难。可以使用 testbench 的层作为引导。从顶层启动,等待一个层接收完来自上一层 (如果有的话) 的所有输入,接着等待当前层空闲下来,然后再等待下一层。应该同时使用超时检测以确保 DUT 或 testbench 不出现死锁 (lock up)。
3. **对 DUT 进行复位**(*Reset the DUT.*)。
收尾阶段包含如下两个步骤。
4. **配置 DUT**(*Configure the DUT*):基于第一步中生成的配置,载入 DUT 的命令寄存器。
1. **清空** (*Sweep*):在最下层完成以后,需要等待 DUT 清空最后的事务。
2. **报告** (*Report*):一旦 DUT 空闲下来,就可以清空遗留在 testbench 中的数据了。有时候保存在记分板里面的数据从来就没有送出来过,这些数据可能是被 DUT 丢弃掉的。可以根据这些信息创建最终报告,说明测试通过或者失败。如果测试失败,务必把相应的功能覆盖率结果删除,因为它们可能是不正确的。
&emsp;&emsp;**运行阶段**是指测试实际运行的阶段,可分为以下步骤。
如[图 1.12](#图1.12) 所示,测试启动环境以后,环境就会按上述步骤运行。
1. **启动环境**(*Start environment*):运行测试平台构件,例如各种 BFM 和激励发生器。
2. **运行测试**(*Run the test*):启动测试然后等待测试完成。定向测试的完成很容易判断,但随机测试却比较困难。可以使用测试平台的层作为引导。从顶层启动,等待一个层接收完来自上一层(如果有的话)的所有输入,接着等待当前层空闲下来,然后再等待下一层。应该同时使用超时检测以确保 DUT 或测试平台不出现死锁(lock up)。
&emsp;&emsp;收尾阶段包含如下两个步骤。
1. **清空**(*Sweep*):在最下层完成以后,需要等待 DUT 清空最后的事务。
2. **报告**(*Report*):一旦 DUT 空闲下来,就可以清空遗留在测试平台中的数据了。有时候保存在记分板里面的数据从来就没有送出来过,这些数据可能是被 DUT 丢弃掉的。可以根据这些信息创建最终报告,说明测试通过或者失败。如果测试失败,务必把相应的功能覆盖率结果删除,因为它们可能是不正确的。
&emsp;&emsp;如[图 12](#图12) 所示,测试启动环境以后,环境就会按上述步骤运行。
# 12. 最大限度的代码重用
为了验证一个带有数百个特性的复杂设备,必须编写数百个定向测试。如果使用约束下的随机激励,需要编写的测试就会少很多。与定向测试相比,随机测试的主要工作是构建 testbench,使它包含所有较低的层:场景、功能、命令以及信号。这个 testbench 代码要能够被所有的测试使用,所以它需要有很好的**通用性**。
&emsp;&emsp;为了验证一个带有数百个特性的复杂设备,必须编写数百个定向测试。如果使用受约束的随机激励,需要编写的测试就会少很多。与定向测试相比,随机测试的主要工作是构建测试平台,使它包含所有较低的层:场景、功能、命令以及信号。这个测试平台代码要能够被所有的测试使用,所以它需要有很好的**通用性**。
这些建议似乎是在推荐一个极度复杂的 testbench,但需要记住的是,在 testbench 中每输入一行,就等于给每个单独的测试都减少了一行,相当于在同时创建很多个测试,而这也正是建立一个复杂 testbench 所能获得的巨额回报。
&emsp;&emsp;这些建议似乎是在推荐一个极度复杂的测试平台,但需要记住的是,在测试平台中每输入一行,就等于给每个单独的测试都减少了一行,相当于在同时创建很多个测试,而这也正是建立一个复杂测试平台所能获得的巨额回报。
# 13. Testbench 的性能
# 13. 测试平台的性能
如果你是第一次接触这种方法学的话,可能还是会怀疑它工作起来是否会优于定向测试?一个普遍的质疑便是 testbench 的性能。一个定向测试通常可以在一秒之内运行完,但**约束下的随机测试却要花费数分钟甚至数小时去搜索整个状态空间**。这种论点的问题在于,它忽略了一个在验证上真实存在的瓶颈:创建一个测试所需要的时间。你可以在一天之内手动编写完一个定向测试,然后再花一两天的时间调试并手动验证结果。测试的实际运行时间比起你在其他方面花费的时间其实要少得多。
&emsp;&emsp;如果你是第一次接触这种方法学的话,可能还是会怀疑它工作起来是否会优于定向测试?一个普遍的质疑便是测试平台 的性能。一个定向测试通常可以在一秒之内运行完,但**受约束的随机测试却要花费数分钟甚至数小时去搜索整个状态空间**。这种论点的问题在于,它忽略了一个在验证上真实存在的瓶颈:创建一个测试所需要的时间。你可以在一天之内手动编写完一个定向测试,然后再花一两天的时间调试并手动验证结果。测试的实际运行时间比起你在其他方面花费的时间其实要少得多。
创建约束下的随机测试需要几个步骤。
&emsp;&emsp;创建受约束的随机测试需要几个步骤。
1. 最重要的一步是建立分层的 testbench,包括自检的部分。这项工作能给所有的测试带来好处,所以是非常值得的。
2. 按照验证计划中列举的目标创建激励。可以使用随机约束,也可以采用注入错误或协议违例等迂回的方式。以这其中的任何一种方式创建激励所花费的时间可能可以用于创建好儿个定向测试,但是它的回报也要高很多。一个约束下的随机测试能够尝试成千上万种不同的协议违例,而在同样的时间里创建的几个定向测试却只能尝试几种情形,显然前者要比后者好得多。
3. 功能覆盖率 (约束下的随机测试)。这项任务的开始是创建一个强有力的验证计划,这个计划必须带有清晰而且便于测植的目标。接下来你需要创建 System­Verilog 代码,在环境中添加工具用于收集数据。最后很重要的一点,你需要
4. 对结果进行分析,并据此判断是否满足目标要求,如果不满足,应如何修改测试。
1. 最重要的一步是建立分层的测试平台,包括自检的部分。这项工作能给所有的测试带来好处,所以是非常值得的。
2. 按照验证计划中列举的目标创建激励。可以使用随机约束,也可以采用注入错误或协议违例等迂回的方式。以这其中的任何一种方式创建激励所花费的时间可能可以用于创建好儿个定向测试,但是它的回报也要高很多。一个受约束的随机测试能够尝试成千上万种不同的协议违例,而在同样的时间里创建的几个定向测试却只能尝试几种情形,显然前者要比后者好得多。
3. 功能覆盖率(受约束的随机测试)。这项任务的开始是创建一个强有力的验证计划,这个计划必须带有清晰而且便于测植的目标。接下来你需要创建 System­Verilog 代码,在环境中添加工具用于收集数据。最后很重要的一点,你需要对结果进行分析,并据此判断是否满足目标要求,如果不满足,应如何修改测试。
# 14. 结束语
电子设计复杂度的持续增长要求以一种新颖的、系统的且自动化的方法来创建 testbench。从硬件规范到 RTL 编码、门级综合、芯片制造,以及最后到用户手里,项目每向前推进一步,修复单个 bug 所需要的代价就会增加数倍甚至数十倍。定向测试每次只能测试一个特性,而无法模拟设备在实际应用环境中所面对的复杂的激励和配置。为了得到稳健的设计,**必须使用约束下的随机激励加上功能覆盖率**,才能在可能的限度内创建出最广泛的激励。
&emsp;&emsp;电子设计复杂度的持续增长要求以一种新颖的、系统的且自动化的方法来创建测试平台。从硬件规范到 RTL 编码、门级综合、芯片制造,以及最后到用户手里,项目每向前推进一步,修复单个漏洞所需要的代价就会增加数倍甚至数十倍。定向测试每次只能测试一个特性,而无法模拟设备在实际应用环境中所面对的复杂的激励和配置。为了得到稳健的设计,**必须使用受约束的随机激励加上功能覆盖率**,才能在可能的限度内创建出最广泛的激励。
# 参考文献
1. 克里斯·斯皮尔, 斯皮尔, 张春,等. SystemVerilog验证:测试平台编写指南[M]. 科学出版社, 2009.
2. Spear C. SystemVerilog for verification: a guide to learning the testbench language features[M]. Springer Science & Business Media, 2008.
1. C. Spear. *SystemVerilog 验证: 测试平台编写指南 原书第二版*. 北京: 科学出版社, 2009.
2. C. Spear. *SystemVerilog for verification: a guide to learning the testbench language features*, 2nd ed. New York: Springer, 2008.
+197 -201
View File
@@ -1,5 +1,5 @@
---
title: 'Josh''s Notes: SystemVerilog 验证 (Part 2 — 数据类型)'
title: "Josh's Note — SystemVerilog 验证<br>Part 2 数据类型"
mathjax: true
comments: true
copyright: true
@@ -25,12 +25,12 @@ categories:
date: 2022-05-31 10:18:34
---
和 Verilog 相比,SystemVerilog 提供了很多改进的数据结构。虽然其中的部分结构最初是为设计者创建的,但对测试者也同样有用。本文将介绍这些对验证很有用的数据结构。
和 Verilog 相比,SystemVerilog 提供了很多改进了的数据结构。虽然其中的部分结构最初是为设计人员创建的,但对测试人员也同样有用。本文将介绍这些对验证很有用的数据结构。
SystemVerilog 引进了一些新的数据类型,它们具有如下优点。
SystemVerilog 引进了一些新的数据类型,它们具有如下优点:
1. **双状态数据类型** (*Two-state*):更好的性能,更低的内存消耗。
2. **队列、动态数组和关联数组** (*Queues, dynamic and associative arrays*):减少内存消耗,自带搜索和分类功能。
1. **双状态数据类型** (*Two-state*):性能更好,内存消耗更低。
2. **队列、动态数组和关联数组** (*Queues, dynamic and associative arrays*):内存消耗减少,自带搜索和分类功能。
3. **类和结构** (*Classes and structures:*):支持抽象数据结构。
4. **联合和合并结构** (*Unions and packed structures*):允许对同一数据有多种视图 (view)。
5. **字符串** (*Strings*):支持内建的字符序列。
@@ -44,7 +44,7 @@ Verilog-1995 有两种基本的数据类型:变量 (variable) 和线网 (net)
- 单比特或多比特的无符号数 (unsigned single or multi-bit, `reg [7:0] m`);
- 32 比特的有符号数 (signed 32-bit variable, `integer`);
- 64 比特的无符号数 (unsigned 64-bit variable, `time`)
- 64 比特的无符号数 (unsigned 64-bit variable, `time`);
- 浮点数 (floating point number, `real`)。
若干变量可以被一起存放到定宽数组 (fixed-size array) 里。所有的存储都是静态 (static) 的,意味着所有的变量在整个仿真过程当中都是存活 (alive) 的,子程序 (routine) 不能通过堆栈来保存参数和局部变量。线网可以用来连接设计当中的不同部分,例如门原语和模块实例。尽管线网有很多种用法,但是大多数设计者还是使用标量或矢量 `wire` 来连接各个设计模块的端口。
@@ -55,22 +55,22 @@ SystemVerilog 增加了很多新的数据类型,对设计和验证工程师都
在 Verilog 中,初学者经常分不清 `reg` 和 `wire` 两者的区别。应该使用哪一个来驱动端口?连接不同模块时又该怎么做?SystemVerilog 对经典的 `reg` 数据类型进行了改进,使得它除了作为一个变量以外,还**可以被连续赋值、门单元和模块所驱动**。为了与寄存器类型相区别,这种改进的数据类型称为 `logic`。任何使用线网的地方均可使用 `logic`,但**要求 `logic` 不能有多个结构性的驱动**,例如在对双向总线建模的时候。此时,需要使用线网类型,例如 `wire`,SystemVerilog 会对多个数据来源进行解析以后确定最终值。
[例 2.1](#例2.1) 示范了在 SystemVerilog 中使用 `logic` 类型。
[例 1](#例1) 给出在 SystemVerilog 中使用 `logic` 类型的例子。
<span id="例2.1"></span>
<a id="例1"></a>
``` verilog 例 2.1 <code>logic</code> 类型的使用
``` verilog 例 1 <code>logic</code> 类型的使用
module logic_data_type(input logic rst_h);
parameter CYCLE = 20;
logic q, q_l, d, clk, rst_l;
initial begin
clk = 0; // 过程赋值
forever #(CYCLE/2) clk = ~clk;
end
parameter CYCLE = 20;
logic q, q_l, d, clk, rst_l;
initial begin
clk = 0; // 过程赋值
forever #(CYCLE/2) clk = ~clk;
end
assign rst_l = ~rst_h; // 连续赋值
not n1(q_l, q); // q_l 被门驱动
my_dff d1(q, d, clk, rst_l); // q 被模块驱动
assign rst_l = ~rst_h; // 连续赋值
not n1(q_l, q); // q_l 被门驱动
my_dff d1(q, d, clk, rst_l); // q 被模块驱动
endmodule
```
@@ -82,11 +82,11 @@ endmodule
## 1.2. 双状态数据类型
相比四状态数据类型,SystemVerilog 引入的双状态数据类型有利于提高仿真器的性能并减少内存的使用量。最简单的双状态数据类型是 `bit`,它是无符号的。另四种带符号的双状态数据类型是 `byte`,`shortint`,`int` 和 `longint`,如[例 2.2](#例2.2) 所示。
相比四状态数据类型,SystemVerilog 引入的双状态数据类型有利于提高仿真器的性能并减少内存的使用量。最简单的双状态数据类型是 `bit`,它是无符号的。另四种带符号的双状态数据类型是 `byte`,`shortint`,`int` 和 `longint`,如[例 2](#例2) 所示。
<span id="例2.2"></span>
<a id="例2"></a>
``` verilog 例 2.2 带符号的数据类型
``` verilog 例 2 带符号的数据类型
bit b; // 双状态,单比特
bit [31:0] b32; // 双状态,32 比特无符号整数
int unsigned ui; // 双状态,32 比特无符号整数
@@ -102,11 +102,11 @@ real r; // 双状态,双精度浮点数
> 虽然使用 `byte` 等数据类型来替代类似 `logic[7:0]` 进行声明可以让程序更简洁,但需要注意,这些新的数据类型都是**带符号**的,所以 `byte` 变量的最大值只有 127,而不是 255 (它的范围是 -128~127)。可以使用 `byte unsigned`,但这其实比使用 `byte [7:0]` 还要麻烦。在进行随机化时,带符号变量可能会造成意想不到的结果,这一点在后面会讨论到。
> 在把双状态变量连接到 DUT 务必要小心,尤其是连接到 DUT 的输出时,因为 DUT 产生的 `X` 或 `Z` 会被转换成双状态值,而测试代码可能永远也察觉不了。这些值被转换成了 `0` 还是 `1` 并不重要,重要的是要**随时检查未知值的传播**。使用 `$isunknown()` 操作符,可以在表达式的任意位出现 `X` 或 `Z` 时返回 `1`,如[例 2.3](#例2.3)。
> 在把双状态变量连接到 DUT 务必要小心,尤其是连接到 DUT 的输出时,因为 DUT 产生的 `X` 或 `Z` 会被转换成双状态值,而测试代码可能永远也察觉不了。这些值被转换成了 `0` 还是 `1` 并不重要,重要的是要**随时检查未知值的传播**。使用 `$isunknown()` 操作符,可以在表达式的任意位出现 `X` 或 `Z` 时返回 `1`,如[例 3](#例3)。
<span id="例2.3"></span>
<a id="例3"></a>
``` verilog 例 2.3 对四状态值的检查
``` verilog 例 3 对四状态值的检查
if ($isunknown(iport) == 1)
$display("@%0t: 4-state value detected on iport %b",
$time, iport);
@@ -122,18 +122,18 @@ if ($isunknown(iport) == 1)
Verilog 要求在声明中必须给出数组的上下界。因为几乎所有数组都使用 `0` 作为索引下界,所以 SystemVerilog **允许只给出数组宽度的便捷声明方式**,跟 C 语言类似。
<span id="例2.4"></span>
<a id="例4"></a>
``` verilog 例 2.4 定宽数组的声明
``` verilog 例 4 定宽数组的声明
int lo_hi[0:15]; // 16 个整数 [0]..[15]
int c_style[16]; // 16 个整数 [0]..[15]
```
可以通过在变量名后面指定维度的方式来创建**多维定宽数组** (*multidimensional fixed-size array*)。[例 2.5](#例2.5) 创建了几个二维的整数数组,大小都是 8 行 4 列,最后一个元素的值被设置为 1。多维数组在 Verilog-2001 中已经引入,但这种紧凑型声明方式却是新的。
可以通过在变量名后面指定维度的方式来创建**多维定宽数组** (*multidimensional fixed-size array*)。[例 5](#例5) 创建了几个二维的整数数组,大小都是 8 行 4 列,最后一个元素的值被设置为 1。多维数组在 Verilog-2001 中已经引入,但这种紧凑型声明方式却是新的。
<span id="例2.5"></span>
<a id="例5"></a>
``` verilog 例 2.5 声明并使用多维数组
``` verilog 例 5 声明并使用多维数组
int array2 [0:7][0:3]; // 完整的声明
int array3 [8][4]; // 紧凑的声明
@@ -147,28 +147,27 @@ array2[7][3] = 1; // 设置最后一个元素
这适用于所有数组类型,包括定宽数组、动态数组、关联数组和队列,也同时适用于地址中含有 `X` 或 `Z` 的情况。线网在没有驱动的时候输出是 `Z`。
很多 SystemVerilog 仿真器**在存放数组元素时使用 32 比特的字 (word) 边界**,所以 `byte`,`shortint` 和 `int` 都是存放在一个字中,`longint` 存放到两个字中。如[例 2.6](#例2.6) 所示,**在非合并数组中,字的低位用来存放数据,高位不使用**。[图 2.1](#图2.1) 所示的字节数组 `b_unpack` 被存放到三个字的空间里。
很多 SystemVerilog 仿真器**在存放数组元素时使用 32 比特的字 (word) 边界**,所以 `byte`,`shortint` 和 `int` 都是存放在一个字中,`longint` 存放到两个字中。如[例 6](#例6) 所示,**在非合并数组中,字的低位用来存放数据,高位不使用**。[图 1](#图1) 所示的字节数组 `b_unpack` 被存放到三个字的空间里。
<span id="例2.6"></span>
<a id="例6"></a>
``` verilog 例 2.6 非合并数组的声明
``` verilog 例 6 非合并数组的声明
bit [7:0] b_unpack[3]; // 非合并数组
```
<span id="图2.1"></span>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2022-05-31-josh-systemverilog-2/2022-05-31-josh-systemverilog-2-010-UnpackedArrayStorage.png" width=600px alt="图 2.1 非合并数组的存放"/>
</div>
<a id="图1"></a>
![图 1 非合并数组的存放](../images/post/2022-05-31-josh-systemverilog-2/2022-05-31-josh-systemverilog-2-010-UnpackedArrayStorage.png){width=600px}
仿真器通常使用两个或两个以上连续的字来存放 `logic` 和 `integer` 等四状态类型,这**比存放双状态变量多占用一倍的空间**。
## 2.2. 常量数组
[例 2.7](#例2.7) 示范了如何使用常量数组,即**用一个单引号加大括号来初始化数组** (注意这里的单引号并不同于编译器指引或宏定义中的单引号),可以一次性地为数组的部分或所有元素赋值。在大括号前标上重复次数可以对多个元素重复赋值,还可以为没有显式赋值的元素指定一个默认值。
[例 7](#例7) 示范了如何使用常量数组,即**用一个单引号加大括号来初始化数组** (注意这里的单引号并不同于编译器指引或宏定义中的单引号),可以一次性地为数组的部分或所有元素赋值。在大括号前标上重复次数可以对多个元素重复赋值,还可以为没有显式赋值的元素指定一个默认值。
<span id="例2.7"></span>
<a id="例7"></a>
``` verilog 例 2.7 初始化一个数组
``` verilog 例 7 初始化一个数组
int ascend[4] = '{0,1,2,3}; // 对 4 个元素进行初始化
int descend[5];
@@ -180,11 +179,11 @@ descend = '{9, 8, default:1}; // {9,8,1,1,1}
## 2.3. 基本的数组操作—— `for` 和 `foreach`
操作数组的最常见的方式是使用 `for` 或 `foreach` 循环。在[例 2.8](#例2.8) 中,`i` 被声明为 `for` 循环内的局部变量。SystemVerilog 的 `$size` 函数返回数组的宽度。在 `foreach` 循环中,只需要给出数组名并在后面的方括号中给出索引变量,SystemVerilog 便会自动遍历数组中的元素。索引变量将自动声明,并只在循环内有效。
操作数组的最常见的方式是使用 `for` 或 `foreach` 循环。在[例 8](#例8) 中,`i` 被声明为 `for` 循环内的局部变量。SystemVerilog 的 `$size` 函数返回数组的宽度。在 `foreach` 循环中,只需要给出数组名并在后面的方括号中给出索引变量,SystemVerilog 便会自动遍历数组中的元素。索引变量将自动声明,并只在循环内有效。
<span id="例2.8"></span>
<a id="例8"></a>
``` verilog 例 2.8 在数组操作中使用 <code>for</code> 和 <code>foreach</code> 循环
``` verilog 例 8 在数组操作中使用 <code>for</code> 和 <code>foreach</code> 循环
initial begin
bit [31:0] src[5], dst[5];
for (int i=0; i<$size(src); i++)
@@ -194,11 +193,11 @@ initial begin
end
```
注意在[例 2.9](#例2.9) 中,对多维数组使用 `foreach` 的语法可能会与设想的有所不同。使用时并不是像 `[i][j]` 这样把每个下标分别列在不同的方括号里,而是用逗号隔开后放在同一个方括号里,像 `[i,j]`。
注意在[例 9](#例9) 中,对多维数组使用 `foreach` 的语法可能会与设想的有所不同。使用时并不是像 `[i][j]` 这样把每个下标分别列在不同的方括号里,而是用逗号隔开后放在同一个方括号里,像 `[i,j]`。
<span id="例2.9"></span>
<a id="例9"></a>
``` verilog 例 2.9 初始化并遍历多维数组
``` verilog 例 9 初始化并遍历多维数组
int md[2][3] = '{'{0,1,2}, '{3,4,5}};
initial begin
@@ -214,11 +213,11 @@ initial begin
end
```
[例 2.9](#例2.9) 的输出结果如[例 2.10](#例2.10) 所示。
[例 9](#例9) 的输出结果如[例 10](#例10) 所示。
<span id="例2.10"></span>
<a id="例10"></a>
``` plaintext 例 2.10 多维数组元素值的打印输出结果
``` plaintext 例 10 多维数组元素值的打印输出结果
Initial value:
md[0][0] = 0
md[0][1] = 1
@@ -235,11 +234,11 @@ md[1][1] = 5
md[1][2] = 5
```
**如果不需要遍历数组中的所有维度,可以在 `foreach` 循环里忽略不需要的维度**。[例 2.11](#例2.11) 把一个二维数组打印成一个方形的阵列。它在外层循环中遍历第一个维度,然后在内层循环中遍历第二个维度。
**如果不需要遍历数组中的所有维度,可以在 `foreach` 循环里忽略不需要的维度**。[例 11](#例11) 把一个二维数组打印成一个方形的阵列。它在外层循环中遍历第一个维度,然后在内层循环中遍历第二个维度。
<span id="例2.11"></span>
<a id="例11"></a>
``` verilog 例 2.11 打印一个多维数组
``` verilog 例 11 打印一个多维数组
initial begin
byte twoD[4][6];
foreach(twoD[i,j])
@@ -254,11 +253,11 @@ initial begin
end
```
[例 2.11](#例2.11) 的输出结果如[例 2.12](#例2.12) 所示。
[例 11](#例11) 的输出结果如[例 12](#例12) 所示。
<span id="例2.12"></span>
<a id="例12"></a>
``` plaintext 例 2.12 打印多维数组的输出结果
``` plaintext 例 12 打印多维数组的输出结果
Initial value:
0: 0 1 2 3 4 5
1: 10 11 12 13 14 15
@@ -273,11 +272,11 @@ Initial value:
## 2.4. 基本的数组操作——复制和比较
可以在不使用循环的情况下对数组进行聚合比较和复制 (aggregate compare and copy, 聚合操作适用于整个数组而不是单个元素),其中比较**只限于等于比较或不等于比较**。[例 2.13](#例2.13) 列出了几个比较的例子。操作符 `? :` 是一个迷你型的 `if` 语句,在[例 2.13](#例2.13) 中用来对两个字符串进行选择。例子最后的比较语句使用了数组的一部分,`src[1:4]`,它实际上产生了一个有四个元素的临时数组。
可以在不使用循环的情况下对数组进行聚合比较和复制 (aggregate compare and copy, 聚合操作适用于整个数组而不是单个元素),其中比较**只限于等于比较或不等于比较**。[例 13](#例13) 列出了几个比较的例子。操作符 `? :` 是一个迷你型的 `if` 语句,在[例 13](#例13) 中用来对两个字符串进行选择。例子最后的比较语句使用了数组的一部分,`src[1:4]`,它实际上产生了一个有四个元素的临时数组。
<span id="例2.13"></span>
<a id="例13"></a>
``` verilog 例 2.13 数组的复制和比较操作
``` verilog 例 13 数组的复制和比较操作
initial begin
bit [31:0] src[5] = '{0,1,2,3,4},
dst[5] = '{5,4,3,2,1};
@@ -307,11 +306,11 @@ end
## 2.5. 同时使用位下标和数组下标
在 Verilog-1995 中一个很不方便的地方就是数组下标 (array subscript) 和位下标 (bit subscript) 不能同时使用。Verilog-2001 对定宽数组取消了这个限制。[例 2.14](#例2.14) 打印出数组的第一个元素 (二进制 101 )、它的最低位 (1) 以及紧接的高两位 (二进制 10)。
在 Verilog-1995 中一个很不方便的地方就是数组下标 (array subscript) 和位下标 (bit subscript) 不能同时使用。Verilog-2001 对定宽数组取消了这个限制。[例 14](#例14) 打印出数组的第一个元素 (二进制 101 )、它的最低位 (1) 以及紧接的高两位 (二进制 10)。
<span id="例2.14"></span>
<a id="例14"></a>
``` verilog 例 2.14 同时使用数组下标和位下标
``` verilog 例 14 同时使用数组下标和位下标
initial begin
bit [31:0] src[5] = '{5{5}};
$displayb(src[0],, // 'b101 或 'd5
@@ -328,11 +327,11 @@ end
## 2.7. 合并数组的例子
声明合并数组时,**合并的位和数组大小是数据类型的一部分,必须在变量名前面指定**。数组大小定义的格式必须是 `[msb:lsb]`,而不是 `[size]`。[例 2.15](#例2.15) 中的变量 `bytes` 是一个有 4 个字节的合并数组,使用单独的 32 比特的字来存放,如图 2.2 所示。
声明合并数组时,**合并的位和数组大小是数据类型的一部分,必须在变量名前面指定**。数组大小定义的格式必须是 `[msb:lsb]`,而不是 `[size]`。[例 15](#例15) 中的变量 `bytes` 是一个有 4 个字节的合并数组,使用单独的 32 比特的字来存放,如图 2 所示。
<span id="例2.15"></span>
<a id="例15"></a>
``` verilog 例 2.15 合并数组的声明和用法
``` verilog 例 15 合并数组的声明和用法
bit [3:0] [7:0] bytes; // 4 个 字节 组装成 32 比特
bytes = 32'hCafe_Dada;
$displayh(bytes,, // 显示所有的 32 比特
@@ -340,16 +339,15 @@ $displayh(bytes,, // 显示所有的 32 比特
bytes[3][7]); // 显示 MSB “1”
```
<span id="图2.2"></span>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2022-05-31-josh-systemverilog-2/2022-05-31-josh-systemverilog-2-020-PackedArrayLayout.png" width=600px alt="图 2.2 合井数组存放示意图"/>
</div>
<a id="图2"></a>
合并和非合并数组可以混合使用。可以使用数组来表示存储单元,这些单元可以按比特、字节或长字的方式进行存取。在[例 2.16](#例2.16) 中,`barray` 是一个具有 3 个合并元素的非合并数组。
![图 2 合井数组存放示意图](../images/post/2022-05-31-josh-systemverilog-2/2022-05-31-josh-systemverilog-2-020-PackedArrayLayout.png){width=600px}
<span id="例2.16"></span>
合并和非合并数组可以混合使用。可以使用数组来表示存储单元,这些单元可以按比特、字节或长字的方式进行存取。在[例 16](#例16) 中,`barray` 是一个具有 3 个合并元素的非合并数组。
``` verilog 例 2.16 合并数组的声明和用法
<a id="例16"></a>
``` verilog 例 16 合并数组的声明和用法
bit [3:0] [7:0] barray [3]; // 合并,3×32 比特
bit [31:0] lw = 32'h0123_4567; // 字
bit [7:0] [3:0] nibbles; // 合并数组
@@ -359,12 +357,11 @@ barray[0][1][6] = 1'b1;
nibbles = barray[0]; // 复制合并数组的元素值
```
[例 2.15](#例2.15) 中的变量 `bytes` 是一个具有 4 个字节的合并数组,以单字形式存放。`barray` 则是一个具有 3 个类似 `bytes` 元素的数组,其存放形式如图 2.3。
[例 15](#例15) 中的变量 `bytes` 是一个具有 4 个字节的合并数组,以单字形式存放。`barray` 则是一个具有 3 个类似 `bytes` 元素的数组,其存放形式如图 3。
<span id="图2.3"></span>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2022-05-31-josh-systemverilog-2/2022-05-31-josh-systemverilog-2-030-PackedArrayBitLayout.png" width=600px alt="图 2.3 合并数组存放示意图"/>
</div>
<a id="图3"></a>
![图 3 合并数组存放示意图](../images/post/2022-05-31-josh-systemverilog-2/2022-05-31-josh-systemverilog-2-030-PackedArrayBitLayout.png){width=600px}
- 使用一个下标,可以得到一个字的数据,如 `barray[2]`;
- 使用两个下标,可以得到一个字节的数据,如 `barray[0][3]`;
@@ -372,13 +369,13 @@ nibbles = barray[0]; // 复制合并数组的元素值
注意数组声明中在变量名后面指定了数组的大小,`barray[3]`,这个维度是非合并的,所以在使用该数组时至少要有一个下标。
[例 2.16](#例2.16) 中的最后一行在两个合并数组间实现复制。由于操作是以比特为单位进行的,所以即使数组维度不同也可以进行复制。
[例 16](#例16) 中的最后一行在两个合并数组间实现复制。由于操作是以比特为单位进行的,所以即使数组维度不同也可以进行复制。
## 2.8. 合井数组和非合并数组的选择
应该选择合并数组还是非合并数组呢?当需要和标量进行相互转换时,使用合并数组会非常方便。例如,以字节或字为单位对存储单元进行操作。[图 2.3](#图2.3) 中所示的 `barray` 可以满足这一要求。任何数组类型都可以合并,包括动态数组、队列和关联数组。
应该选择合并数组还是非合并数组呢?当需要和标量进行相互转换时,使用合并数组会非常方便。例如,以字节或字为单位对存储单元进行操作。[图 3](#图3) 中所示的 `barray` 可以满足这一要求。任何数组类型都可以合并,包括动态数组、队列和关联数组。
**如果需要等待数组中的变化,则必须使用合并数组**。当 testbench 需要通过存储器数据的变化来唤醒时,需要使用 `@` 操作符,但 **`@` 操作符只能用于标量或者合并数组**。在[例 2.16](#例2.16) 中,可以把 `lw` 和 `barray[0]` 用作敏感信号,但却不能用整个的 `barray` 数组,除非把它扩展成:`@(barray[0] or barray[1] or barray[2])`。
**如果需要等待数组中的变化,则必须使用合并数组**。当 testbench 需要通过存储器数据的变化来唤醒时,需要使用 `@` 操作符,但 **`@` 操作符只能用于标量或者合并数组**。在[例 16](#例16) 中,可以把 `lw` 和 `barray[0]` 用作敏感信号,但却不能用整个的 `barray` 数组,除非把它扩展成:`@(barray[0] or barray[1] or barray[2])`。
# 3. 动态数组
@@ -386,11 +383,11 @@ nibbles = barray[0]; // 复制合并数组的元素值
SystemVerilog 提供了动态数组类型,可以**在仿真时分配空间或调整宽度**,这样在仿真中就可以使用最小的存储星。
动态数组在声明时使用空的下标 `[]`,表示数组的宽度不在编译时给出,在程序运行时再指定。数组在最开始时是空的,所以必须调用 `new[]` 操作符来分配空间,同时在方括号中传递数组宽度。可以把数组名传给 `new[]` 构造符,并把已有数组的值复制到新数组里,如[例 2.17](#例2.17) 所示。
动态数组在声明时使用空的下标 `[]`,表示数组的宽度不在编译时给出,在程序运行时再指定。数组在最开始时是空的,所以必须调用 `new[]` 操作符来分配空间,同时在方括号中传递数组宽度。可以把数组名传给 `new[]` 构造符,并把已有数组的值复制到新数组里,如[例 17](#例17) 所示。
<span id="例2.17"></span>
<a id="例17"></a>
``` verilog 例 2.17 使用动态数组
``` verilog 例 17 使用动态数组
int dyn[], d2[]; // 声明动态数组
initial begin
@@ -406,7 +403,7 @@ initial begin
end
```
在[例 2.17](#例2.17) 中:
在[例 17](#例17) 中:
- A:调用 `new[5]` 为动态数组 `dyn` 分配了 5 个整型元素。
- B:把数组的索引值赋给相应的元素。
@@ -418,11 +415,11 @@ end
调用系统函数 `$size` 可以返回数组的宽度。动态数组有一些内建的子程序 (rou­tines),例如 `delete` 和 `size`。
如果想声明一个常数数组但又不想统计元素的个数,可以使用动态数组并使用常量数组进行赋值。在[例 2.18](#例2.18) 中声明的 `mask` 数组具有 9 个 8 比特元素,SystemVerilog 会自动统计元素的个数,这比声明一个定宽数组然后不小心把宽度错指为 8 要好。
如果想声明一个常数数组但又不想统计元素的个数,可以使用动态数组并使用常量数组进行赋值。在[例 18](#例18) 中声明的 `mask` 数组具有 9 个 8 比特元素,SystemVerilog 会自动统计元素的个数,这比声明一个定宽数组然后不小心把宽度错指为 8 要好。
<span id="例2.18"></span>
<a id="例18"></a>
``` verilog 例 2.18 使用动态数组来保存元素数量不定的列表
``` verilog 例 18 使用动态数组来保存元素数量不定的列表
bit [7:0] mask[] = '{8'b0000_0000, 8'b0000_0001,
8'b0000_0011, 8'b0000_0111,
8'b0000_1111, 8'b0001_1111,
@@ -438,13 +435,13 @@ bit [7:0] mask[] = '{8'b0000_0000, 8'b0000_0001,
SystemVerilog 引进了一种新的数据类型——队列 (queue),它结合了链表和数组的优点。队列与链表相似,**可以在一个队列中的任何地方增加或删除元素**,这类操作在性能上的损失比动态数组小得多,因为动态数组需要分配新的数组并复制所有元素的值。队列与数组相似,可以通过索引实现对任一元素的访问,而不需要像链表那样去遍历目标元素之前的所有元素。
队列的声明是使用带有美元符号的下标:`[$]`。队列元素的编号从 `0` 到 `$`。[例 2.19](#例2.19) 示范了如何使用方法 (method) 在队列中增加和删除元素。注意队列的常量 (literal) 只有大括号而没有数组常量中开头的单引号。
队列的声明是使用带有美元符号的下标:`[$]`。队列元素的编号从 `0` 到 `$`。[例 19](#例19) 示范了如何使用方法 (method) 在队列中增加和删除元素。注意队列的常量 (literal) 只有大括号而没有数组常量中开头的单引号。
SystemVerilog 的队列类似于标准模板库 (standard template library) 中的双端队列。通过增加元素来创建队列,SystemVerilog 会分配额外的空间以便新元素能够被快速插入。当元素增加到超过原有空间的容量时,SystemVerilog 会自动分配更多的空间。因此队列可以扩大或缩小,但不用像动态数组那样在性能上付出很大代价,System­Verilog 会随时记录闲置的空间。注意不要对队列使用构造函数 `new[]`。
<span id="例2.19"></span>
<a id="例19"></a>
``` verilog 例 2.19 队列的操作
``` verilog 例 19 队列的操作
int j = 1,
q2[$] = {3,4}, // 队列的常量不需要使用 “'”
q[$] = {0,2,5}; // {0,2,5}
@@ -465,11 +462,11 @@ initial begin
end
```
还可以使用字下标串联来替代方法。如果把 `$` 放在一个范围表达式的左边,那么 `$` 将代表最小值,例如 `[$:2]` 就代表 `[0:2]`。如果 `$` 放在表达式的右边,则代表最大值,如[例 2.20](#例2.20) 中初始化块的第一行里的 `[1:$]` 就表示 `[1:2]`。
还可以使用字下标串联来替代方法。如果把 `$` 放在一个范围表达式的左边,那么 `$` 将代表最小值,例如 `[$:2]` 就代表 `[0:2]`。如果 `$` 放在表达式的右边,则代表最大值,如[例 20](#例20) 中初始化块的第一行里的 `[1:$]` 就表示 `[1:2]`。
<span id="例2.20"></span>
<a id="例20"></a>
``` verilog 例 2.20 队列的操作
``` verilog 例 20 队列的操作
int j = 1,
q2[$] = {3,4}, // 队列的常量不需要使用 “'”
q[$] = {0,2,5}; // {0,2,5}
@@ -499,22 +496,21 @@ end
如果只是偶尔需要创建一个大容量的数组,那么动态数组已经足够好用了,但是如果需要超大容量的呢?假设正在对一个有着几个 G 字节寻址范围的处理器进行建模。在典型的测试中,这个处理器可能只访问了用来存放可执行代码和数据的几百或几千个字节,这种情况下对几 G 字节的存储空间进行分配和初始化显然是浪费的。
SystemVerilog 提供了关联数组 (associative array) 类型,用来保存稀疏矩阵 (sparse matrix) 的元素。这意味着当对一个非常大的地址空间进行寻址时,SystemVerilog 只为实际写入的元素分配空间。在[图 2.4](#图2.4) 中,关联数组只保留 0…3、42、1000、4521 和 200,000 等位置上的值。这样,用来存放这些值的空间比有 200,000 个条目的定宽或动态数组所占用的空间要小得多。
SystemVerilog 提供了关联数组 (associative array) 类型,用来保存稀疏矩阵 (sparse matrix) 的元素。这意味着当对一个非常大的地址空间进行寻址时,SystemVerilog 只为实际写入的元素分配空间。在[图 4](#图4) 中,关联数组只保留 0…3、42、1000、4521 和 200,000 等位置上的值。这样,用来存放这些值的空间比有 200,000 个条目的定宽或动态数组所占用的空间要小得多。
<span id="图2.4"></span>
<div align="center">
<img src="https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2022-05-31-josh-systemverilog-2/2022-05-31-josh-systemverilog-2-040-AssociativeArray.png" width=600px alt="图 2.4 关联数组"/>
</div>
<a id="图4"></a>
![图 4 关联数组](../images/post/2022-05-31-josh-systemverilog-2/2022-05-31-josh-systemverilog-2-040-AssociativeArray.png){width=600px}
仿真器可以采用树或哈希表的形式来存放关联数组,但有一定的额外开销。当保存索引值比较分散的数组时,例如使用 32 位地址或 64 位数据作为索引的数据包,这种额外开销显然是可以接受的。
关联数组采用**在方括号中放置数据类型[^DataTypeNote]**的形式来进行声明,例如 `[int]` 或 `[Packet]`。[例 2.21](#例2.21) 示范了关联数组的声明、初始化和遍历过程。
关联数组采用**在方括号中放置数据类型[^DataTypeNote]**的形式来进行声明,例如 `[int]` 或 `[Packet]`。[例 21](#例21) 示范了关联数组的声明、初始化和遍历过程。
[^DataTypeNote]: 也可以采用通配符作为下标进行关联数组的声明,例如 `wild[*]`。但是不推荐使用这种风格,因为不明确指明数据类型会导致很多问题。一个典型的问题是在 `foreach` 循环中——在 `foreach(wild[j])` 中的变量 `j` 究竟是什么类型?
<span id="例2.21"></span>
<a id="例21"></a>
``` verilog 例 2.21 关联数组的声明、初始化和使用
``` verilog 例 21 关联数组的声明、初始化和使用
initial begin
bit [63:0] assoc[int], idx = 1;
@@ -543,13 +539,13 @@ initial begin
end
```
[例 2.21](#例2.21) 中的关联数组 `assoc` 具有稀疏分布的元素:1、2、4、8、16 等等。简单的 `for` 循环并不能遍历该数组,需要使用 `foreach` 循环来完成。如果想控制得更好,可以在 `do ... while` 循环中使用 `first` 和 `next` 函数。这些函数可以修改索引参数的值,然后根据数组是否为空返回 0 或 1。
[例 21](#例21) 中的关联数组 `assoc` 具有稀疏分布的元素:1、2、4、8、16 等等。简单的 `for` 循环并不能遍历该数组,需要使用 `foreach` 循环来完成。如果想控制得更好,可以在 `do ... while` 循环中使用 `first` 和 `next` 函数。这些函数可以修改索引参数的值,然后根据数组是否为空返回 0 或 1。
和 Perl 语言中的哈希数组类似,关联数组也可以使用字符串索引进行寻址。[例 2.22](#例2.22) 使用字符串索引读取文件,并建立关联数组 `switch`,以实现从字符串到数字的映射。如[例 2.22](#例2.22) 所示,可以使用函数 `exists()` 来检查元素是否存在。如果试图读取尚未被写入的元素,SystemVerilog 会返回数组类型的默认值,例如对于双状态类型是 `0`,对于四状态类型是 `X`。
和 Perl 语言中的哈希数组类似,关联数组也可以使用字符串索引进行寻址。[例 22](#例22) 使用字符串索引读取文件,并建立关联数组 `switch`,以实现从字符串到数字的映射。如[例 22](#例22) 所示,可以使用函数 `exists()` 来检查元素是否存在。如果试图读取尚未被写入的元素,SystemVerilog 会返回数组类型的默认值,例如对于双状态类型是 `0`,对于四状态类型是 `X`。
<span id="例2.22"></span>
<a id="例22"></a>
``` verilog 例 2.22 使用带字符串索引的关联数组
``` verilog 例 22 使用带字符串索引的关联数组
/*
输入文件的内容如下:
42 min_address
@@ -594,11 +590,11 @@ SystemVerilog 提供了很多数组的方法,可用于任何一种非合并的
## 7.1. 数组缩减方法
基本的数组缩减方法是把一个数组缩减成一个值,如[例 2.23](例2.23) 所示。最常用的缩减方法是 `sum`,它对数组中的所有元素求和。这里必须对 SystemVerilog 处理操作**位宽**的规则十分小心。默认情况下,如果把一个单比特数组的所有元素相加,其和也是单比特的。但如果使用 32 比特的表达式,把结果保存在 32 比特的变量里,与一个 32 比特的变量进行比较,或者使用适当的 `with` 表达式,SystemVerilog 都会在数组求和的过程中使用 32 比特位宽。
基本的数组缩减方法是把一个数组缩减成一个值,如[例 23](例23) 所示。最常用的缩减方法是 `sum`,它对数组中的所有元素求和。这里必须对 SystemVerilog 处理操作**位宽**的规则十分小心。默认情况下,如果把一个单比特数组的所有元素相加,其和也是单比特的。但如果使用 32 比特的表达式,把结果保存在 32 比特的变量里,与一个 32 比特的变量进行比较,或者使用适当的 `with` 表达式,SystemVerilog 都会在数组求和的过程中使用 32 比特位宽。
<span id="例2.23"></span>
<a id="例23"></a>
``` verilog 例 2.23 数组求和
``` verilog 例 23 数组求和
bit on[10]; // 单比特数组
int total;
@@ -627,11 +623,11 @@ end
其他的数组缩减方法还有 `product` (积),`and` (与),`or` (或) 和 `xor` (异或)。SystemVerilog 没有提供专门从数组里随机选取一个元素的方法。所以对于定宽数组队列、动态数组和关联数组可以使用 `$urandom_range($size (array)-1)`,而对于队列和动态数组还可以使用 `$urandom_ range(array.size()-1)`。
如果想从一个关联数组中随机选取一个元素,则需要逐个访问它之前的元素,因为无法直接访问到第 $N$ 个元素。[例 2.24](#例2.24) 示范了如何从一个以整数值作为索引的关联数组中随机选取一个元素。如果数组是以字符串作为索引,只需要将 `idx` 的类型改为 `string` 即可。
如果想从一个关联数组中随机选取一个元素,则需要逐个访问它之前的元素,因为无法直接访问到第 $N$ 个元素。[例 24](#例24) 示范了如何从一个以整数值作为索引的关联数组中随机选取一个元素。如果数组是以字符串作为索引,只需要将 `idx` 的类型改为 `string` 即可。
<span id="例2.24"></span>
<a id="例24"></a>
``` verilog 例 2.24 从一个关联数组中随机选取一个元素
``` verilog 例 24 从一个关联数组中随机选取一个元素
int aa[int], rand_idx, element, count;
element = $urandom_range(aa.size()-1);
@@ -649,11 +645,11 @@ $display("%0d element aa[%0d] = %0d",
数组中的最大值是什么?数组中有没有包含某个特定值?要想在非合并数组中查找数据,可以使用数组定位方法。**这些方法的返回值通常是一个队列**。
[例 2.25](#例2.25) 使用一个定宽数组 `f[6]`,一个动态数组 `d[]` 和一个队列 `q[$]`。`min` 和 `max` 函数能够找出数组中的最小值和最大值。注意,它们返回的是一个队列而非标量。这些方法也适用于关联数组。方法 `unique` 返回的是在数组中具有唯一值的队列,即排除掉重复的数值。
[例 25](#例25) 使用一个定宽数组 `f[6]`,一个动态数组 `d[]` 和一个队列 `q[$]`。`min` 和 `max` 函数能够找出数组中的最小值和最大值。注意,它们返回的是一个队列而非标量。这些方法也适用于关联数组。方法 `unique` 返回的是在数组中具有唯一值的队列,即排除掉重复的数值。
<span id="例2.25"></span>
<a id="例25"></a>
``` verilog 例 2.25 数组定位方法:<code>min</code>、<code>max</code>、<code>unique</code>
``` verilog 例 25 数组定位方法:<code>min</code>、<code>max</code>、<code>unique</code>
int aa[int], rand_idx, element, count;
element = $urandom_range(aa.size()-1);
@@ -667,11 +663,11 @@ $display("%0d element aa[%0d] = %0d",
element, rand_idx, aa[rand_idx]);
```
使用 `foreach` 循环固然可以实现数组的完全搜索,但是如果使用 SystemVerilog 的定位方法,则只需一个操作便可完成。表达式 `with` 可以指示 SystemVerilog 如何进行搜索,如[例 2.26](#例2.26) 所示。
使用 `foreach` 循环固然可以实现数组的完全搜索,但是如果使用 SystemVerilog 的定位方法,则只需一个操作便可完成。表达式 `with` 可以指示 SystemVerilog 如何进行搜索,如[例 26](#例26) 所示。
<span id="例2.26"></span>
<a id="例26"></a>
``` verilog 例 2.26 数组定位方法:<code>find</code>
``` verilog 例 26 数组定位方法:<code>find</code>
int d[] = '{9,1,8,3,4,4}, tq[$];
// 找出所有大于 3 的元素
@@ -689,22 +685,22 @@ tq = d.find_last with (item==4); // {4}
tq = d.find_last_index with (item==4); // {5} d[5]=4
```
在条件语句 `with` 中,`item` 被称为重复参数,它代表了数组中一个单独的元素。`item` 是默认的名字,也可以指定别的名字,只要在数组方法的参数列表中列出来就可以了,如[例 2.27](#例2.27) 所示。
在条件语句 `with` 中,`item` 被称为重复参数,它代表了数组中一个单独的元素。`item` 是默认的名字,也可以指定别的名字,只要在数组方法的参数列表中列出来就可以了,如[例 27](#例27) 所示。
<span id="例2.27"></span>
<a id="例27"></a>
``` verilog 例 2.27 重复参数的声明
``` verilog 例 27 重复参数的声明
tq = d.find_first with (item==4); // 本例的四个语句都是等价的
tq = d.find_first() with (item==4);
tq = d.find_first(item) with (item==4);
tq = d.find_first(x) with (x==4);
```
[例 2.28](#例2.28) 示范了几种对数组子集进行求和的方式。第一次求和 (`total`) 是先把元素值与 7 进行比较,比较表达式返回 1 (为真) 或 0 (为假),然后再把返回结果与对应元素相乘,所以 `{9, 0, 8, 0, 0, 0}` 的元素和是 17。第二次求和 (`total`) 则使用条件操作符 `? :` 进行计算。
[例 28](#例28) 示范了几种对数组子集进行求和的方式。第一次求和 (`total`) 是先把元素值与 7 进行比较,比较表达式返回 1 (为真) 或 0 (为假),然后再把返回结果与对应元素相乘,所以 `{9, 0, 8, 0, 0, 0}` 的元素和是 17。第二次求和 (`total`) 则使用条件操作符 `? :` 进行计算。
<span id="例2.28"></span>
<a id="例28"></a>
``` verilog 例 2.28 数组定位方法
``` verilog 例 28 数组定位方法
int count, total, d[] = '{9,1,8,3,4,4};
count = d.sum with (item > 7); // 2: {9, 8}
@@ -714,17 +710,17 @@ total = d.sum with (item < 8 ? item : 0); // 12=1+3+4+4
count = d.sum with (item == 4); // 2: {4, 4}
```
当把数组缩减方法与条件语句 `with` 结合使用时,会产生令人惊讶的结果,例如 `sum` 方法。在[例 2.28](#例2.28) 中,`sum` 操作符的结果是条件表达式为真的次数。对于[例 2.28](#例2.28) 的第一个运算语句来说,总共有两个数组元素大于 7 (9 和 8),所以 `count` 最后得 2。
当把数组缩减方法与条件语句 `with` 结合使用时,会产生令人惊讶的结果,例如 `sum` 方法。在[例 28](#例28) 中,`sum` 操作符的结果是条件表达式为真的次数。对于[例 28](#例28) 的第一个运算语句来说,总共有两个数组元素大于 7 (9 和 8),所以 `count` 最后得 2。
> 返回值为索引的数组定位方法,其返回的队列类型是 `int` 而非 `integer`,例如 `find_index` 方法。如果在这些语句中不小心用错了数据类型,那么代码有可能通不过编译。
## 7.3. 数组的排序
SystemVerilog 有几个可以改变数组中元素顺序的方法。可以对元素进行正排序、逆排序,或是打乱它们的顺序,如[例 2.29](#例2.29) 所示。注意,与前述数组定位方法不同的是,**排序方法改变了原始数组**,而**数组定位方法新建了一个队列来保存结果**。
SystemVerilog 有几个可以改变数组中元素顺序的方法。可以对元素进行正排序、逆排序,或是打乱它们的顺序,如[例 29](#例29) 所示。注意,与前述数组定位方法不同的是,**排序方法改变了原始数组**,而**数组定位方法新建了一个队列来保存结果**。
<span id="例2.29"></span>
<a id="例29"></a>
``` verilog 例 2.29 对数组排序
``` verilog 例 29 对数组排序
int d[] = '{9,1,8,3,4,4};
d.reverse(); // '{4,4,3,8,1,9}
d.sort(); // '{1,3,4,4,8,9}
@@ -732,11 +728,11 @@ d.rsort(); // '{9,8,4,4,3,1}
d.shuffle(); // '{9,4,3,8,1,4}
```
`reverse` 和 `shuffle` 方法不能带 `with` 条件语句,**它们的作用范围是整个数组**。[例 2.30](#例2.30) 示范了如何使用子域对一个结构进行排序。结构和合并结构后面会有解释。
`reverse` 和 `shuffle` 方法不能带 `with` 条件语句,**它们的作用范围是整个数组**。[例 30](#例30) 示范了如何使用子域对一个结构进行排序。结构和合并结构后面会有解释。
<span id="例2.30"></span>
<a id="例30"></a>
``` verilog 例 2.30 对结构数组进行排序
``` verilog 例 30 对结构数组进行排序
struct packed { byte red, green, blue; } c[];
initial begin
c = new[100]; // 分配 100 个像素
@@ -752,11 +748,11 @@ end
## 7.4. 使用数组定位方法建立记分板
数组定位方法可以用来建立记分板。[例 2.31](#例2.31) 定义了包结构 (`Packet`),然后建立了一个由包结构队列组成的记分板。后面会解释如何使用 `typedef` 创建结构。
数组定位方法可以用来建立记分板。[例 31](#例31) 定义了包结构 (`Packet`),然后建立了一个由包结构队列组成的记分板。后面会解释如何使用 `typedef` 创建结构。
<span id="例2.31"></span>
<a id="例31"></a>
``` verilog 例 2.31 带数组方法的记分板
``` verilog 例 31 带数组方法的记分板
typedef struct packed
{bit [7:0] addr;
bit [7:0] pr;
@@ -777,7 +773,7 @@ function void check_addr(bit [7:0] addr);
endfunction : check_addr
```
[例 2.31](#例2.31) 中的 `check_addr()` 函数在记分板里寻找和参数匹配的地址。`find_index()` 方法返回一个 `int` 队列。如果该队列为空 (`size==0`),则说明没有匹配值。如果该队列有一个成员 (`size==1`),则说明有一个匹配,该匹配元素随后被 `check_addr()` 函数删除掉。如果该队列有多个成员 (`size>1`),则说明记分板里有多个包地址和目标值匹配。
[例 31](#例31) 中的 `check_addr()` 函数在记分板里寻找和参数匹配的地址。`find_index()` 方法返回一个 `int` 队列。如果该队列为空 (`size==0`),则说明没有匹配值。如果该队列有一个成员 (`size==1`),则说明有一个匹配,该匹配元素随后被 `check_addr()` 函数删除掉。如果该队列有多个成员 (`size>1`),则说明记分板里有多个包地址和目标值匹配。
对于包信息的存储,更好的方式是采用类 (class),后续会有相关介绍。
@@ -843,11 +839,11 @@ endfunction : check_addr
# 9. 使用 `typedef` 创建新的类型
typedef 语句可以用来创建新的类型。例如,要求一个算术逻辑单元 (ALU) 在编译时可配置,以适应 8 比特、 16 比特、 24 比特或 32 比特等不同位宽的操作数。在 Verilog 中,可以为操作数的位宽和类型分别定义一个宏 (macro),如[例 2.32](#例2.32) 所示。
typedef 语句可以用来创建新的类型。例如,要求一个算术逻辑单元 (ALU) 在编译时可配置,以适应 8 比特、 16 比特、 24 比特或 32 比特等不同位宽的操作数。在 Verilog 中,可以为操作数的位宽和类型分别定义一个宏 (macro),如[例 32](#例32) 所示。
<span id="例2.32"></span>
<a id="例32"></a>
``` verilog 例 2.32 Verilog 中用户自定义的类型宏
``` verilog 例 32 Verilog 中用户自定义的类型宏
// 旧的 Verilog 风格
`define OPSIZE 8
`define OPREG reg [`OPSIZE-1:0]
@@ -857,9 +853,9 @@ typedef 语句可以用来创建新的类型。例如,要求一个算术逻辑
这种情况并没有创建新的类型,而只是在进行文本替换。在 SystemVerilog 中,采用下面的代码可以创建新的类型。本文约定,所有用户自定义类型都带后缀 “`_t`”。
<span id="例2.33"></span>
<a id="例33"></a>
``` verilog 例 2.33 SystemVerilog 中用户自定义类型
``` verilog 例 33 SystemVerilog 中用户自定义类型
// 新的 SystemVerilog 风格
parameter OPSIZE = 8;
typedef reg [OPSIZE-1:0] opreg_t;
@@ -873,18 +869,18 @@ opreg_t op_a, op_b;
> 用户自定义的最有用的类型是双状态的 32 比特的无符号整数。在 testbench 中,很多数值都是正整数,例如字段长度或事件次数,这种情况下如果定义有符号整数就会出问题。把对 `uint` 的定义放到通用定义程序包中,这样就可以在仿真程序的任何地方使用它。
<span id="例2.34"></span>
<a id="例34"></a>
``` verilog 例 2.34 <code>uint</code> 的定义
``` verilog 例 34 <code>uint</code> 的定义
typedef bit [31:0] uint; // 32 比特双状态无符号数
typedef int unsigned uint; // 等效定义
```
对新的数组类型的定义并不是很明显,需要把数组的下标放在新的数组名称中。[例 2.35](#例2.35) 创建了一种新的类型,`fixed_array5`,它是一个有着 5 个元素的定宽数组。[例 2.35](#例2.35) 接着声明了一个这种类型的数组并进行了初始化。
对新的数组类型的定义并不是很明显,需要把数组的下标放在新的数组名称中。[例 35](#例35) 创建了一种新的类型,`fixed_array5`,它是一个有着 5 个元素的定宽数组。[例 35](#例35) 接着声明了一个这种类型的数组并进行了初始化。
<span id="例2.35"></span>
<a id="例35"></a>
``` verilog 例 2.35 用户自定义数组类型
``` verilog 例 35 用户自定义数组类型
typedef int fixed_array5[5];
fixed_array5 f5;
@@ -902,19 +898,19 @@ Verilog 的最大缺陷之一是没有数据结构。在 SystemVerilog 中可以
## 10.1. 使用 `struct` 创建新类型
可以把若干变量组合到一个结构中。[例 2.36](#例2.36) 创建了一个名为 `pixel` 的结构,它有三个无符号的字节变量,分别代表红、绿和蓝。
可以把若干变量组合到一个结构中。[例 36](#例36) 创建了一个名为 `pixel` 的结构,它有三个无符号的字节变量,分别代表红、绿和蓝。
<span id="例2.36"></span>
<a id="例36"></a>
``` verilog 例 2.36 创建一个 <code>pixel</code> 类型
``` verilog 例 36 创建一个 <code>pixel</code> 类型
struct {bit [7:0] r, g, b;} pixel;
```
[例 2.36](#例2.36) 中的声明只是创建了一个 `pixel` 变量。要想在端口和程序中共享它,则必须创建一个新的类型,如[例 2.37](#例2.37) 所示。
[例 36](#例36) 中的声明只是创建了一个 `pixel` 变量。要想在端口和程序中共享它,则必须创建一个新的类型,如[例 37](#例37) 所示。
<span id="例2.37"></span>
<a id="例37"></a>
``` verilog 例 2.37 <code>pixel</code> 结构
``` verilog 例 37 <code>pixel</code> 结构
typedef struct {bit [7:0] r, g, b;} pixel_s;
pixel_s my_pixel;
```
@@ -923,11 +919,11 @@ pixel_s my_pixel;
## 10.2. 对结构进行初始化
可以在声明或者过程赋值语句中把多个值赋给一个结构体,就像数组那样。如[例 2.38](#例2.38) 所示,赋值时要把数值放到带单引号的大括号中。
可以在声明或者过程赋值语句中把多个值赋给一个结构体,就像数组那样。如[例 38](#例38) 所示,赋值时要把数值放到带单引号的大括号中。
<span id="例2.38"></span>
<a id="例38"></a>
``` verilog 例 2.38 对 <code>struct</code> 类型进行初始化
``` verilog 例 38 对 <code>struct</code> 类型进行初始化
initial begin
typedef struct {int a;
byte b;
@@ -944,11 +940,11 @@ end
## 10.3. 创建可容纳不同类型的联合
在硬件中,寄存器里的某些位的含义可能与其他位的值有关。例如,不同的操作码对应的处理器指令格式也不同。带立即操作数的指令,它在操作数位置上存放的是一个常量。整数指令对这个立即数的译码结果会与浮点指令大不相同。[例 2.39](#例2.39) 把整数 `i` 和实数 `f` 存放在同一位置上。
在硬件中,寄存器里的某些位的含义可能与其他位的值有关。例如,不同的操作码对应的处理器指令格式也不同。带立即操作数的指令,它在操作数位置上存放的是一个常量。整数指令对这个立即数的译码结果会与浮点指令大不相同。[例 39](#例39) 把整数 `i` 和实数 `f` 存放在同一位置上。
<span id="例2.39"></span>
<a id="例39"></a>
``` verilog 例 2.39 使用一个下标 <code>typedef</code> 创建联合
``` verilog 例 39 使用一个下标 <code>typedef</code> 创建联合
typedef union { int i; real f; } num_u;
num_u un;
un.f = 0.0; // 把数值设为浮点形式
@@ -960,11 +956,11 @@ un.f = 0.0; // 把数值设为浮点形式
## 10.4. 合并结构
SystemVerilog 提供的合并结构允许对数据在存储器中的排布方式有更多的控制。合并结构是以连续比特集的方式存放的,中间没有闲置的空间。[例 2.37](#例2.37) 中的 `pixel` 结构使用了三个数值,所以它占用了三个长字的存储空间,即使它实际只需要三个字节。可以指定把它合并到尽可能小的空间里。
SystemVerilog 提供的合并结构允许对数据在存储器中的排布方式有更多的控制。合并结构是以连续比特集的方式存放的,中间没有闲置的空间。[例 37](#例37) 中的 `pixel` 结构使用了三个数值,所以它占用了三个长字的存储空间,即使它实际只需要三个字节。可以指定把它合并到尽可能小的空间里。
<span id="例2.40"></span>
<a id="例40"></a>
``` verilog 例 2.40 合并结构
``` verilog 例 40 合并结构
typedef struct packed {bit [7:0] r, g, b;} pixel_p_s;
pixel_p_s my_pixel;
```
@@ -981,11 +977,11 @@ SystemVerilog 数据类型的多样性意味着可能需要在它们之间进行
## 11.1. 静态转换
静态转换操作不对转换值进行检查。如[例 2.41](#例2.41) 所示,转换时指定目标类型,并在需要转换的表达式前加上单引号即可。注意,Verilog 对整数和实数类型,或者不同位宽的向量之间进行隐式转换。
静态转换操作不对转换值进行检查。如[例 41](#例41) 所示,转换时指定目标类型,并在需要转换的表达式前加上单引号即可。注意,Verilog 对整数和实数类型,或者不同位宽的向量之间进行隐式转换。
<span id="例2.41"></span>
<a id="例41"></a>
``` verilog 例 2.41 在整型和实划之间进行静态转换
``` verilog 例 41 在整型和实划之间进行静态转换
int i;
real r;
@@ -999,11 +995,11 @@ r = real'(42); // 转换是非强制的
## 11.3. 流操作符
流操作符 `<<` 和 `>>` 用在赋值表达式的右边,后面带表达式、结构或数组。流操作符用于把其后的数据打包成一个比特流。操作符 `>>` 把数据从左至右变成流,而 `<<` 则把数据从右至左变成流,如[例 2.42](#例2.42) 所示。也可以指定一个片段宽度,把源数据按照这个宽度分段以后再转变成流。不能将比特流结果直接赋给非合并数组,而应该在赋值表达式的左边使用流操作符把比特流拆分到非合并数组中。
流操作符 `<<` 和 `>>` 用在赋值表达式的右边,后面带表达式、结构或数组。流操作符用于把其后的数据打包成一个比特流。操作符 `>>` 把数据从左至右变成流,而 `<<` 则把数据从右至左变成流,如[例 42](#例42) 所示。也可以指定一个片段宽度,把源数据按照这个宽度分段以后再转变成流。不能将比特流结果直接赋给非合并数组,而应该在赋值表达式的左边使用流操作符把比特流拆分到非合并数组中。
<span id="例2.42"></span>
<a id="例42"></a>
``` verilog 例 2.42 基本的流操作
``` verilog 例 42 基本的流操作
initial begin
int h;
bit [7:0] b, g[4], j[4] = '{8'ha, 8'hb, 8'hc, 8'hd};
@@ -1022,11 +1018,11 @@ end
也可以使用很多连接符 `{}` 来完成同样的操作,但是流操作符用起来会更简洁并且易于阅读。
如果需要打包或拆分数组,可以使用流操作符来完成具有不同尺寸元素的数组间的转换。例如,可以将字节数组转换成字数组。对于定宽数组、动态数组和队列都可以这样。[例 2.43](#例2.43) 示范了队列之间的转换,这种转换同时也适用于动态数组。数组元素会根据需要自动分配。
如果需要打包或拆分数组,可以使用流操作符来完成具有不同尺寸元素的数组间的转换。例如,可以将字节数组转换成字数组。对于定宽数组、动态数组和队列都可以这样。[例 43](#例43) 示范了队列之间的转换,这种转换同时也适用于动态数组。数组元素会根据需要自动分配。
<span id="例2.43"></span>
<a id="例43"></a>
``` verilog 例 2.43 使用流操作符进行队列间的转换
``` verilog 例 43 使用流操作符进行队列间的转换
initial begin
bit [15:0] wq[$] = {16'h1234, 16'h5678};
bit [7:0] bq[$];
@@ -1042,11 +1038,11 @@ end
> 数组下标失配是在数组间进行流操作时常见的错误。数组声明中的下标 `[256]` 等同于 `[0:255]` 而非 `[255:0]`。由于很多数组使用 `[high:low]` (由高到低) 的下标形式进行声明,使用流操作把它们的值赋给带 `[size]` 下标形式的数组,会造成元素倒序。同样,如果把声明形式为 `bit [7:0] src [255:0]` 的非合并数组使用流操作赋值给声明形式为 `bit [7:0] [255:0] dst` 的合并数组,则数值的顺序会被打乱。对于合并的字节数组,正确的声明形式应该是 `bit [255:0] [7:0] dst`。
流操作符也可用来将结构 (例如,ATM 信元) 打包或拆分到字节数组中。在[例 2.44](#例2.44) 中使用流操作把结构转换成动态的字节数组,然后字节数组又被反过来转换成结构。
流操作符也可用来将结构 (例如,ATM 信元) 打包或拆分到字节数组中。在[例 44](#例44) 中使用流操作把结构转换成动态的字节数组,然后字节数组又被反过来转换成结构。
<span id="例2.44"></span>
<a id="例44"></a>
``` verilog 例 2.44 使用流操作符在结构和数组间进行转换
``` verilog 例 44 使用流操作符在结构和数组间进行转换
initial begin
typedef struct {int a;
byte b;
@@ -1072,19 +1068,19 @@ end
在学会使用枚举类型之前,只能使用文本宏。宏的作用范围太大,而且大多数情况下对于调试者是可见的。枚举创建了一种强大的变量类型,它仅限于一些特定名称的集合,例如指令中的操作码或者状态机中的状态名。例如,使用 ADD、MOVE 或 ROTW 这些名称有利于编写和维护代码,它比直接使用 `8'h01` 这样的常量或者宏要好得多。定义常量的另一种方法是使用参数。但参数需要对每个数值进行单独的定义,而枚举类型却能够自动为列表中的每个名称分配不同的数值。
最简单的枚举类型声明包含了一个常量名称列表以及一个或多个变量,如[例 2.45](#例2.45) 所示。通过这种方式创建的是一个匿名的枚举类型,它只能用于这个例子中声明的变量。
最简单的枚举类型声明包含了一个常量名称列表以及一个或多个变量,如[例 45](#例45) 所示。通过这种方式创建的是一个匿名的枚举类型,它只能用于这个例子中声明的变量。
<span id="例2.45"></span>
<a id="例45"></a>
``` verilog 例 2.45 一个简单的枚举类型
``` verilog 例 45 一个简单的枚举类型
enum {RED, BLUE, GREEN} color;
```
创建一个署名的枚举类型有利于声明更多新变量,尤其是当这些变量被用作子程序参数或模块端口时。首先需要创建枚举类型,然后再创建相应的变量。使用内建的 `name()` 函数,可以得到枚举变量值对应的字符串,如[例 2.46](#例2.46) 所示。
创建一个署名的枚举类型有利于声明更多新变量,尤其是当这些变量被用作子程序参数或模块端口时。首先需要创建枚举类型,然后再创建相应的变量。使用内建的 `name()` 函数,可以得到枚举变量值对应的字符串,如[例 46](#例46) 所示。
<span id="例2.46"></span>
<a id="例46"></a>
``` verilog 例 2.46 枚举类型
``` verilog 例 46 枚举类型
// 创建代表 0,1,2 的数据类型
typedef enum {INIT, DECODE, IDLE} fsmstate_e;
fsmstate_e pstate, nstate; // 声明自定义类型变量
@@ -1104,28 +1100,28 @@ end
## 12.1. 定义枚举值
枚举值默认为从 0 开始递增的整数。可以定义自己的枚举值。[例 2.47](#例2.47) 中使用 `INIT` 代表默认值 0,`DECODE` 代表 2,`IDLE` 代表 3。
枚举值默认为从 0 开始递增的整数。可以定义自己的枚举值。[例 47](#例47) 中使用 `INIT` 代表默认值 0,`DECODE` 代表 2,`IDLE` 代表 3。
<span id="例2.47"></span>
<a id="例47"></a>
``` verilog 例 2.47 指定枚举值
``` verilog 例 47 指定枚举值
typedef enum {INIT, DECODE=2, IDLE} fsmtype_e;
```
枚举常量,如[例 2.47](#例2.47) 中的 `INIT`,它们的作用范围规则和变量是一样的。因此,如果在不同的枚举类型中用到了同一个枚举常量名,例如把 `INIT` 用于不同的状态机中,那么必须在不同的作用域里声明它们,例如模块、程序块、函数和类。
枚举常量,如[例 47](#例47) 中的 `INIT`,它们的作用范围规则和变量是一样的。因此,如果在不同的枚举类型中用到了同一个枚举常量名,例如把 `INIT` 用于不同的状态机中,那么必须在不同的作用域里声明它们,例如模块、程序块、函数和类。
> 如果没有特别指出,枚举类型会被当成 `int` 类型存储。由于 `int` 类型的默认值是 0,所以在给枚举常量赋值时务必小心。在[例 2.48](#例2.48) 中 `position` 会被初始化为 0,这并不是一个合法的 `ordinal_e` 变量。这种情况是语言本身所规定的,而非工具上的缺陷。因此把 0 指定给一个枚举常量可以避免这个错误,如[例 2.49](#例2.49) 所示。
> 如果没有特别指出,枚举类型会被当成 `int` 类型存储。由于 `int` 类型的默认值是 0,所以在给枚举常量赋值时务必小心。在[例 48](#例48) 中 `position` 会被初始化为 0,这并不是一个合法的 `ordinal_e` 变量。这种情况是语言本身所规定的,而非工具上的缺陷。因此把 0 指定给一个枚举常量可以避免这个错误,如[例 49](#例49) 所示。
<span id="例2.48"></span>
<a id="例48"></a>
``` verilog 例 2.48 指定枚举值:不正确
``` verilog 例 48 指定枚举值:不正确
typedef enum {FIRST=1, SECOND, THIRD} ordinal_e;
ordinal_e position;
```
<span id="例2.49"></span>
<a id="例49"></a>
``` verilog 例 2.49 指定枚举值:正确
``` verilog 例 49 指定枚举值:正确
typedef enum {BAD_O=0, FIRST=1, SECOND, THIRD} ordinal_e;
ordinal_e position;
```
@@ -1147,11 +1143,11 @@ SystemVerilog 提供了一些可以遍历枚举类型的函数:
件。如果使用 `current! =current.last`,则循环会在到达最后一个成员之前终止。如果
使用 `current<=current.last`,则会造成死循环,因为 `next` 给出的值永远也不会大于最后一个值。这类似于 `for` 循环的步长为 0.3,而循环变量定义为 `bit [1:0]`,所以循环永远不会退出。
实际上,可以使用 `do ... while` 循环来遍历所有值,如[例 2.50](#例2.50) 所示。
实际上,可以使用 `do ... while` 循环来遍历所有值,如[例 50](#例50) 所示。
<span id="例2.50"></span>
<a id="例50"></a>
``` verilog 例 2.50 遍历所有枚举成员
``` verilog 例 50 遍历所有枚举成员
typedef enum {RED, BLUE, GREEN} color_e;
color_e color;
color = color.first;
@@ -1167,9 +1163,9 @@ while (color != color.first); // 环形绕回时即完成
枚举类型的默认类型为双状态 `int`。可以使用简单的赋值表达式把枚举变量的值直接赋给非枚举变量如 `int`。但 SystemVerilog 不允许在没有进行显式类型转换的情况下把整型变量赋给枚举变量。SystemVerilog 要求显式类型转换的原因是**可能存在的数值越界情况**。
<span id="例2.51"></span>
<a id="例51"></a>
``` verilog 例 2.51 整型和枚举类型之间的相互赋值
``` verilog 例 51 整型和枚举类型之间的相互赋值
typedef enum {RED, BLUE, GREEN} COLOR_E;
COLOR_E color, c2;
int c;
@@ -1187,9 +1183,9 @@ initial begin
end
```
在[例 2.51](#例2.51) 中,`$cast` 被当成函数进行调用,目的在于把右边的值赋给左边的量。如果赋值成功,`$cast()` 返回 1。如果因为数值越界而导致赋值失败,则不进行任何赋值,函数返回 0。如果把 `cast` 当成任务使用并且操作失败,则 SystemVerilog 会打印错误信息。
在[例 51](#例51) 中,`$cast` 被当成函数进行调用,目的在于把右边的值赋给左边的量。如果赋值成功,`$cast()` 返回 1。如果因为数值越界而导致赋值失败,则不进行任何赋值,函数返回 0。如果把 `cast` 当成任务使用并且操作失败,则 SystemVerilog 会打印错误信息。
也可以像[例 2.51](#例2.51) 所示的那样使用 `type'(val)` 进行类型转换,但这种方式并不进行任何类型检查,所以转换结果可能会越界。例如,在[例 2.51](#例2.51) 中进行静态类型转换以后,赋给 `c2` 的值实际上已经越界,所以应该尽量避免使用这种方式。
也可以像[例 51](#例51) 所示的那样使用 `type'(val)` 进行类型转换,但这种方式并不进行任何类型检查,所以转换结果可能会越界。例如,在[例 51](#例51) 中进行静态类型转换以后,赋给 `c2` 的值实际上已经越界,所以应该尽量避免使用这种方式。
# 13. 常量
@@ -1199,26 +1195,26 @@ SystemVerilog 中有好几种类型的常量。Verilog 中创建常量的最典
SystemVerilog 也支持 `const` 修饰符,允许在变量声明时对其进行初始化,但不能在过程代码中改变其值。
<span id="例2.52"></span>
<a id="例52"></a>
``` verilog 例 2.52 <code>const</code> 变量的声明
``` verilog 例 52 <code>const</code> 变量的声明
initial begin
const byte colon = ":";
...
end
```
在[例 2.52](#例2.52) 中,`colon` 的值在 `initial` 块开头就被初始化。`const` 还可以作为子程序参数。
在[例 52](#例52) 中,`colon` 的值在 `initial` 块开头就被初始化。`const` 还可以作为子程序参数。
# 14. 字符串
Verilog 中使用 `reg` 变量来保存字符串,这一表达很不方便。SystemVerilog 中的 `string` 类型可以用来保存长度可变的字符串。单个字符是 `byte` 类型。长度为 $N$ 的字符串中,元素编号从 0 到 $N — 1$。注意,跟 C 语言 不一样的是,字符串的结尾并不带标识符 null,所有尝试使用字符 “\0” 的操作都会被忽略。字符串使用动态的存储方式,所以不用担心存储空间会全部用完。
[例 2.53](#例2.53) 示范了与字符串相关的几种操作。函数 `getc(N)` 返回位置 `N` 上的字节,`toup­per` 返回一个所有字符大写的字符串,`tolower` 返回一个小写的字符串。大括号 `{}` 用于串接字符串。任务 `putc(M,C)` 把字节 `c` 写到字符串的 `M` 位上。`M` 必须介于 0 和 `len` 所给出的长度之间。函数 `substr(start,end)` 提取出从位置 `start` 到 `end` 之间的所有字符。
[例 53](#例53) 示范了与字符串相关的几种操作。函数 `getc(N)` 返回位置 `N` 上的字节,`toup­per` 返回一个所有字符大写的字符串,`tolower` 返回一个小写的字符串。大括号 `{}` 用于串接字符串。任务 `putc(M,C)` 把字节 `c` 写到字符串的 `M` 位上。`M` 必须介于 0 和 `len` 所给出的长度之间。函数 `substr(start,end)` 提取出从位置 `start` 到 `end` 之间的所有字符。
<span id="例2.53"></span>
<a id="例53"></a>
``` verilog 例 2.53 字符串方法
``` verilog 例 53 字符串方法
string s;
initial begin
@@ -1241,20 +1237,20 @@ task my_log(string message);
endtask
```
稍加留意便可发现动态字符串的用处有多大。在别的语言如 C 里,必须不停地创建临时字符串来接收函数返回的结果。在[例 2.53](#例2.53) 中,函数 `psprintf()` 替代了 Verilog-2001 中的函数 `sformat()`。这个新函数返回一个格式化的临时字符串,并且可以直接传递给其他子程序。这样就可以不用定义新的临时字符串并在格式化语句与函数调用过程中传递这个字符串。
稍加留意便可发现动态字符串的用处有多大。在别的语言如 C 里,必须不停地创建临时字符串来接收函数返回的结果。在[例 53](#例53) 中,函数 `psprintf()` 替代了 Verilog-2001 中的函数 `sformat()`。这个新函数返回一个格式化的临时字符串,并且可以直接传递给其他子程序。这样就可以不用定义新的临时字符串并在格式化语句与函数调用过程中传递这个字符串。
# 15. 表达式的位宽
在 Verilog 中,表达式的位宽是造成行为不可预知的主要原因之一。[例 2.54](#例2.54) 使用四种不同方式实现 `1+1`:
在 Verilog 中,表达式的位宽是造成行为不可预知的主要原因之一。[例 54](#例54) 使用四种不同方式实现 `1+1`:
- 方式 A 使用两个单比特变量,在这种精度下得到 `1+1=0`。
- 方式 B 由于赋值表达式的左边有一个 8 比特的变量,所以其精度是 8 比特,得到的结果是 `1+1=2`。
- 方式 C 采用一个哑元常数强迫 SystemVerilog 使用 2 比特精度。
- 方式 D 中,第一个值在转换符的作用下被指定为 2 比特的值,所以结果是 `1+1=2`。
<span id="例2.54"></span>
<a id="例54"></a>
``` verilog 例 2.54 表达式位宽依赖于上下文
``` verilog 例 54 表达式位宽依赖于上下文
bit [7:0] b8;
bit one = 1'b1; // 单比特
$displayb(one + one); // A: 1+1 = 0
@@ -1,5 +1,5 @@
---
title: 'Josh''s Notes: SystemVerilog 验证 (Part 3 — 过程语句和子程序)'
title: "Josh's Note — SystemVerilog 验证<br>Part 3 过程语句和子程序"
mathjax: true
comments: true
copyright: true
+7 -3
View File
@@ -29,7 +29,7 @@ The Oxford 3000 is the list of the 3000 most important words to learn in English
| | | |
| :----------------------------------- | :------------------------------------ | :-------------------------------- |
| a, an *indefinite article* A1 | agreement *n.* B1 | appointment *n.* B1 |
| [a, an][] *indefinite article* A1 | agreement *n.* B1 | appointment *n.* B1 |
| abandon *v.* B2 | ah *exclam.* A2 | appreciate *v.* B1 |
| ability *n.* A2 | ahead *adv.* B1 | approach *n.*, *v.* B2 |
| able *adj.* A2 | aid *n.*, *v.* B2 | appropriate *adj.* B2 |
@@ -736,7 +736,7 @@ The Oxford 3000 is the list of the 3000 most important words to learn in English
| painful *adj.* B1 | pin *n.*, *v.* B1 | presentation *n.* B1 |
| paint *v.*, *n.* A1 | pink *adj.*, *n.* A1 | preserve *v.* B2 |
| painter *n.* A2 | pipe *n.* B1 | president *n.* A2 |
| painting *n.* A1 | pitch *n.* B2 | press *v.*, *n.* B1 |
| painting *n.* A1 | [pitch][] *n.* B2 | press *v.*, *n.* B1 |
| pair *n.* A1 | place *n.* A1, *v.* B1 | pressure *n.* B1 |
| palace *n.* A2 | plain *adj.* B2 | pretend *v.* B1 |
| pale *adj.* B1 | plan *n.*, *v.* A1 | pretty *adj.*, *adv.* A1 |
@@ -938,7 +938,7 @@ The Oxford 3000 is the list of the 3000 most important words to learn in English
| sector *n.* B2 | slight *adj.* B2 | stress *n.*, *v.* A2 |
| secure *v.*, *adj.* B2 | slightly *adv.* B1 | stretch *v.*, *n.* B2 |
| security *n.* B1 | slip *v.* B2 | strict *adj.* B2 |
| see *v.* A1 | slope *n.*, *v.* B2 | strike *v.*, *n.* B2 |
| see *v.* A1 | slope *n.*, *v.* B2 | [strike][] *v.*, *n.* B2 |
| seed *n.* B1 | slow *adj.* A1, *v.* B1 | string *n.* B1 |
| seek *v.* B2 | slowly *adv.* A2 | strong *adj.* A1 |
| seem *v.* A2 | small *adj.* A1 | strongly *adv.* B1 |
@@ -1158,3 +1158,7 @@ The Oxford 3000 is the list of the 3000 most important words to learn in English
| | | |
| :--------------- | :----------- | :--- |
| zero *number* A2 | zone *n.* B2 | |
[a, an]: https://josh-gao.top/posts/6635e93f.html
[pitch]: https://josh-gao.top/posts/279fbed9.html
[strike]: https://josh-gao.top/posts/dc727c0.html
+8 -11
View File
@@ -7,7 +7,7 @@ comments: true
copyright: true
toc:
enable: true
number: true
number: false
wrap: true
expand_all: true
max_depth: 3
@@ -201,9 +201,7 @@ date: 2023-04-08 00:04:11
{% note primary Synonyms **throw**%}
**throw**
toss | hurlf | ling | chuck | lob | bowl | pitch
toss | hurl | fling | chuck | lob | bowl | pitch
These words all mean to send something from your hand through the air.
@@ -282,7 +280,7 @@ date: 2023-04-08 00:04:11
{% endnote %}
### {% label primary@of roof屋顶 %}
### {% label primary@of roof 屋顶 %}
10. \[singular, uncountable\] (*specialist*) the degree to which a roof slopes倾斜度
@@ -314,22 +312,18 @@ date: 2023-04-08 00:04:11
### Verb Forms
- present simple I / you / we / they **pitch**
- BrE: /pɪtʃ/
- NAmE: /pɪtʃ/
- he / she / it **pitches**
- BrE: /ˈpɪtʃɪz/
- NAmE: /ˈpɪtʃɪz/
- past simple **pitched**
- BrE: /pɪtʃt/
- NAmE: /pɪtʃt/
- past participle **pitched**
- BrE: /pɪtʃt/
- NAmE: /pɪtʃt/
@@ -434,6 +428,9 @@ date: 2023-04-08 00:04:11
{% note primary **compare** roll %}
- BrE: /rəʊl/
- NAmE: /rəʊl/
{% label primary@of ship/plane/walk 船只;飞机;行走 %}
\[intransitive, transitive\] **roll (something) (+ adv./prep.)** to move or make something move from side to side(使)摇摆,摇晃
@@ -566,14 +563,14 @@ date: 2023-04-08 00:04:11
#### pitch in
- pitch in (with somebody/something)
- **pitch in (with somebody/something)**
(*informal*) to join in and help with an activity, by doing some of the work or by giving money, advice, etc. 投入;参与;支援
- *Everyone pitched in with the work.* 每个人都投入了这项工作。
- *Local companies pitched in with building materials and labour.* 当地的公司支援了建筑材料和劳动力。
- pitch something ↔ in
- **pitch something ↔ in**
to give a particular amount of money in order to help with something 参与;出力;出份子
+1 -1
View File
@@ -7,7 +7,7 @@ comments: true
copyright: true
toc:
enable: true
number: true
number: false
wrap: true
expand_all: true
max_depth: 3
@@ -1,194 +0,0 @@
---
title: 高等数学常用公式
mathjax: true
comments: true
copyright: true
toc:
enable: true
number: false
wrap: true
expand_all: true
max_depth: 4
abbrlink: 1823c9d1
date: 2023-04-14 16:25:59
tags:
- 等价无穷小
- 导数公式
- Maclaurin 公式
- 曲率
- 积分公式
- 三角函数
categories:
- [数学, 微积分]
---
# 1. 常见等价无穷小
||||
| :--: | :--: | :--: |
| $\sin x \sim x$ | $\tan x \sim x$ | $\arcsin x \sim x$ |
| $\arctan x \sim x$ | $\displaystyle\left( 1 - \cos x \right) \sim \frac{x^2}{2}$ | $\ln (1+x) \sim x$ |
| $\left( e^x -1 \right) \sim x$ | $\left( a^x - 1 \right) \sim x \ln a$ | $\left( \left( 1+x \right) ^\alpha -1 \right) \sim \alpha x$ |
<!-- more -->
# 2. 导数基本公式
| 一般函数 | 三角函数 | 反三角函数 | 双曲函数<br>(圆函数) |
| :--: | :--: | :--: | :----: |
| $\left( C \right)' = 0$ | $\left( \sin x \right)' = \cos x$ | $\displaystyle\left( \arcsin x \right)' = \frac{1}{\sqrt{1-x^2}}$ | $\displaystyle\left( \sinh x \right)' = \left(\frac{e^x-e^{-x}}{2}\right)' = \cosh x$ |
| $\left( x^\alpha \right)'=\alpha x^{\alpha-1} \left( \alpha \in \mathbf{Z} \right)$ | $\left( \cos x \right)' = -\sin x$ | $\displaystyle\left( \arccos x \right)' = -\frac{1}{\sqrt{1-x^2}}$ | $\displaystyle\left( \cosh x \right)' = \left( \frac{e^x+e^{-x}}{2} \right)'=\sinh x$ |
| $\displaystyle\left( \log_ax\right)'=\frac{1}{x\ln a}$ | $\displaystyle\left( \tan x \right)' = \frac{1}{\cos^2 x}=\sec^2 x$ | $\displaystyle\left( \arctan x \right)' = \frac{1}{1+x^2}$ | $\displaystyle\left( \mathrm{arsinh} \, x \right)' = \left(\ln \left( x+\sqrt{x^2 + 1} \right) \right)' = \frac{1}{x^2+1}$ |
| $( \ln$\| $x$ \|$)'=\displaystyle\frac{1}{x}$ | $\displaystyle\left( \cot x \right)' = -\frac{1}{\sin^2 x} = -\csc^2 x$ | $\displaystyle\left( \mathrm{arccot} \, x \right)' = -\frac{1}{1+x^2}$ | $\displaystyle\left( \mathrm{arcosh} \, x \right)' = \left( \ln \left( x + \sqrt{x^2 - 1} \right) \right)' = \frac{1}{\sqrt{x^2-1}}$
| | $\left( \sec x \right)' = \sec x \cdot \tan x$ |
| | $\left( \csc x \right)' = \csc x \cdot \cot x$ |
- Newton-Leibniz 公式:
$$
\begin{aligned}
\left( u \cdot v \right)^{\left( n \right)} &= u^{\left( n \right)}v + nu^{\left( n-1 \right)}v' + \frac{n \left( n-1 \right)}{2!}u^{\left( n-2 \right)}v'' + \cdots + \frac{n\left( n-1 \right)\cdots\left(n-k+1\right)}{k!}u^{\left( n-k \right)}v^{(k)} + \cdots + uv^{\left( n \right)} \\
&= \sum_{k=0}^{n}C_n^k u^{\left( u-k \right)}v^k
\end{aligned}
$$
可以注意到 Newton-Leibniz 公式具有类似二项式定理展开的形式。
# 3. 几个初等函数的 Maclaurin 公式
## 3.1 Taylor 公式的一般形式
$$
f(x)=f(x_0) + f'(x_0)(x-x_0) + \frac{f''(x_0)}{2!}(x-x_0)^2 + \cdots + \frac{f^{(n)}(x_0)}{n!}(x-x_0)^n + R_n
$$
其中
$$
R_n = \frac{f^{(n+1)}(\xi)}{(n+1)!}(x-x_0)^{n+1} \, (\xi\,在\,x\,和\,x_0\,之间) = o\left( \left( x - x_0 \right)^n \right)(x\to x_0)
$$
## 3.2 Maclaurin 公式的一般形式
$$
f(x)=f(0)+f'(0)\,x + \frac{f''(0)}{2!}x^2 + \cdots + \frac{f^{(n)}(0)}{n!}x^n + R_n
$$
其中
$$
R_n = \frac{f^{(n+1)}(\xi)}{(n+1)!}x^{n+1} \, (\xi\,在\,0\,和\,x\,之间) = \frac{f^{(n+1)}(\theta x)}{(n+1)!} x^{n+1}(0<\theta<1) = o\left( \left( x - x_0 \right)^n \right)(x\to x_0)
$$
## 3.3 指数函数的 Maclaurin 展开式
$$
e^x=1+x+\frac{x^2}{2} + \frac{x^3}{3} + \cdots +\frac{x^n}{n!} + \frac{e^{\theta x}}{(n+1)!}(0<\theta<1)
$$
## 3.4 正弦函数的 Maclaurin 展开式
$$
\sin x = x - \frac{x^3}{3!} + \frac{x^5}{5!} + \cdots + (-1)^{m-1}\frac{x^{2m-1}}{(2m-1)!} + R_{2m}
$$
其中
$$
R_{2m}=\frac{\sin\left( \theta x + \frac{(2m-1)\pi}{2}\right)}{(2m+1)!}x^{2m+1} = o(x^{2m})(0<\theta <1)
$$
## 3.5 余弦函数的 Maclaurin 展开式
$$
\cos x = 1 - \frac{x^2}{2!} + \frac{x^4}{4!} + \cdots + (-1)^m\frac{x^{2m}}{2m!} + R_{2m+1}
$$
其中
$$
R_{2m+1}=\frac{\cos(\theta x + (m+1)\pi)}{(2m+2)!} x^{2m+2}=o(x^{2m+2}) (0<\theta <1)
$$
## 3.6 $\ln (1+x)$ 的 Maclaurin 展开式
$$
\ln(1+x) = x - \frac{x^2}{2} + \frac{x^3}{3} -\frac{x^4}{4} + \cdots + \frac{(-1)^{n-1}x^n}{n} + R_n(x)
$$
其中
$$
R_n(x) = \frac{(-1)^n}{(n+1)(1+\theta x)^{n+1}}x^{n+1} = o(x^n)(0<\theta <1)
$$
## 3.7 $(1+x)^\alpha$ 的 Maclaurin 展开式
$$
(1+x)^\alpha = 1 + \alpha x + \frac{\alpha(\alpha-1)}{2!}x^2 + \cdots + \frac{\alpha(\alpha - 1)\cdots (\alpha-n+1)}{n!}x^n + R_n(x)
$$
其中
$$
R_n(x) = \frac{\alpha(\alpha -1)\cdots(\alpha-n)}{(n+1)!}(1+\theta x)^{\alpha-n-1}x^{n+1} = o(x)(0<\theta <1)
$$
## 3.8 $\frac{1}{1-x}$ 的 Maclaurin 展开式
$$
\frac{1}{1-x} = 1+x+x^2+\cdots+x^n +o(x^n)
$$
# 4. 曲率及曲率半径
| 曲率 | 曲率半径 |
| :--: | :--: |
| $K=\left\| \dfrac{\mathrm{d}\alpha}{\mathrm{d}s}\right\| \xlongequal{\tan \alpha = y' \Rightarrow \alpha = \arctan y'} \dfrac{\left\| \frac{y''}{1+y'^2}\mathrm{d}x \right\|}{\sqrt{1+y'^2}}\mathrm{d}x = \dfrac{\left\| y'' \right\|}{\left( 1 + y' \right)^\frac{3}{2}}$ | $R = \frac{1}{K}$ |
# 5. 积分常用公式
| 序 | 描述 | 公式 |
| :--: | :----: | :----------------------------------------------:|
| 1 | 定积分的定义 | $\displaystyle\int^1_0f(x)\mathrm{d}x=I=\lim_{\lambda \to 0}\sum_{i=1}^{n}f(\xi_i)\Delta x_i$,其中 $\lambda = \max \left\{ \Delta x_1,\Delta x_2, \cdots, \Delta x_n \right\}$ |
| 2 | 变上限积分 | $考察定积分\displaystyle\int^x_af(x)\mathrm{d}x=\int^x_af(t)\mathrm{d}t$,对 $\displaystyle\Phi(x)=\int_a^xf(t)\mathrm{d}t$,有 $\displaystyle\Phi'(x)=\frac{\mathrm{d}}{\mathrm{d}x}\int_a^xf(t)\mathrm{d}t = f(x)$ |
| 3. | — | $\displaystyle\frac{\mathrm{d}}{\mathrm{d}x}\int^{\beta(x)}_{\alpha(x)}f'(t)\mathrm{d}t = f\left[ \beta\left(x\right)\right]\beta'(x)-f[\alpha(x)]\alpha'(x)$ |
| 4 | 上下限对称的积分 | 若 $f(x)$ 为偶函数,则 $\displaystyle\int_{-a}^af(x)\mathrm{d}x=2\int_0^af(x)\mathrm{d}x$;若 $f(x)$ 为奇函数,则 $\displaystyle\int_{-a}^af(x)\mathrm{d}x=0$ |
| 5 | 周期函数的积分 | $\displaystyle f(x+T)=f(x)\Rightarrow\int_0^{nT}f(x)\mathrm{d}x=n\int^T_0f(x)\mathrm{d}x$ |
| 6 | 分部积分法 | $\displaystyle\int uv'\mathrm{d}x=uv - \int u'v\mathrm{d}x \Leftrightarrow \int u\mathrm{d}v = uv - \int v\mathrm{d}u$ |
# 6. 基本积分表
| 序 | 积分式 |
| :--: | :-------------------------: |
| 1 | $\displaystyle\int k\mathrm{d}x=kx+C$,特别地 $\displaystyle\int\mathrm{d}x=x+C$ |
| 2 | $\displaystyle\int x^\mu\mathrm{d}x=\frac{x^{\mu+1}}{\mu+1}+C(\mu\ne-1)$,特别地 $\displaystyle\int \frac{\mathrm{d}x}{x^2}=-\frac{1}{x}+C,\int\frac{\mathrm{d}x}{\sqrt{x}}=2\sqrt{x}+C$ |
| 3 | $\displaystyle\int\frac{\mathrm{d}x}{x}=\ln \|x\|+C$ |
| 4 | $\displaystyle\int\frac{\mathrm{d}x}{1+x^2} = \arctan x +C$ |
| 5 | $\displaystyle\int\frac{\mathrm{d}x}{\sqrt{1-x^2}}=\arcsin x+C$ |
| 6 | $\displaystyle\int\sin x\mathrm{d}x = -\cos x+C, \int\cos x\mathrm{d}x = \sin x +C$ |
| 7 | $\displaystyle\int\frac{\mathrm{d}x}{\cos^2x} = \int\sec^2x\mathrm{d}x = \tan x +C, \int\frac{\mathrm{d}x}{\sin^2x}=\int\csc^2x\mathrm{d}x = -\cot x +C$ |
| 8 | $\displaystyle\int a^x\mathrm{d}x = \frac{a^x}{\ln a} + C$,特别地 $\displaystyle\int e^x\mathrm{d}x = e^x +C$
| 9 | $\displaystyle\int \sinh x\mathrm{d}x = \cosh x + C,\int \cosh x \mathrm{d}x=\sinh x +C$ |
# 7. 三角函数相关公式
| 序 | 公式 |
| :--: | :-------------------------: |
| 1 | $\sin^2x+\cos^2x=1, \tan^2x+1=\sec^2x,\cot^2x+1=\csc^2x$ |
| 2 | $\begin{aligned}&\cosh^2x-\sinh^2x=1,\\ &\sinh(x\pm y)=\sinh x\cdot\cosh y \pm \sinh y\cdot\cosh x, \cosh(x\pm y) = \cosh x\cdot\cosh y,\\ &\sinh2x = 2\sinh x\cdot \cosh x, \cosh 2x = \cosh^2x+\sinh^2x = 2\cosh^2x - 1\end{aligned}$ |
| 3<br>积化和差公式 | $\sin\alpha\cos\beta=\frac12[\sin(\alpha+\beta)+\sin(\alpha-\beta)],\cos\alpha\sin\beta = \frac12[\sin(\alpha+\beta) - \sin(\alpha-\beta)]$ <br> $\cos\alpha\cos\beta = \frac12[cos(\alpha+\beta) + cos(\alpha - \beta)], \sin\alpha\sin\beta=-\frac12[\cos(\alpha+\beta) - \cos(\alpha-\beta)]$ |
| 4<br>和差化积公式 | $\displaystyle\sin\alpha + \sin\beta = 2\sin\left(\frac{\alpha+\beta}{2}\right) \cos\left(\frac{\alpha-\beta}{2}\right), \sin\alpha - \sin\beta = 2\sin\left(\frac{\alpha-\beta}{2}\right) \cos\left(\frac{\alpha+\beta}{2}\right)$ <br> $\displaystyle\cos\alpha + \cos\beta = 2\cos\left(\frac{\alpha+\beta}{2}\right) \cos\left(\frac{\alpha-\beta}{2}\right), \cos\alpha - \cos\beta = -2\sin\left(\frac{\alpha+\beta}{2}\right) \sin\left(\frac{\alpha-\beta}{2}\right)$ |
| 5<br>三角代换 | $\displaystyle\sqrt{a^2-x^2}\xrightarrow{x=a\sin t}a\cos t, \sqrt{a^2+x^2} \xrightarrow{x=a\tan t}a\sec t, \sqrt{x^2-a^2}\xrightarrow{x=a\sec t}a\tan t \left( a>0,t\in\left( -\frac{\pi}{2} , \frac{\pi}{2} \right) \right)$ |
| 6 | $\displaystyle\int\sqrt{a^2-x^2}\mathrm{d}x = \frac{a^2}{2}\arcsin\frac xa + \frac12x\sqrt{a^2-x^2} + C(a>0)$ |
| 7 | $\displaystyle\int\sqrt{x^2+a^2}\mathrm{d}x = \frac x2\sqrt{x^2+a^2} + \frac{a^2}2\ln \left\| x+\sqrt{x^2+a^2} \right\|+C(a>0)$ |
| 8 | $\displaystyle\int\frac{1}{\sqrt{x^2+a^2}}\mathrm{d}x = \ln\left\| x+ \sqrt{x^2+a^2} \right\| +C$, $\displaystyle\int\frac{1}{\sqrt{x^2-a^2}}\mathrm{d}x = \ln\left\| x + \sqrt{x^2+a^2}\right\|(a>0)$,特别地,$\displaystyle\int\frac{1}{\sqrt{x^2+1}}\mathrm{d}x=\left(x+\sqrt{x^2+1}\right) = \mathrm{arsinh}\, x$, $\displaystyle\int\frac{1}{\sqrt{x^2-1}}\mathrm{d}x = \ln\left( x+\sqrt{x^2-1}\right) = \mathrm{arcosh}\, x$ |
| 9 | $\displaystyle\int\sec x\mathrm{d}x = \int\frac{1}{\cos x}\mathrm{d}x = \int\frac{\sec^2x+\sec x \tan x}{\sec x + \tan x}\mathrm{d}x = \int\frac{1}{\sec x + \tan x}\mathrm{d}(\sec x + \tan x) = \ln \left\| \sec x + \tan x \right\| + C$ |
| 10 | $\displaystyle\int\csc x\mathrm{d}x = \int\frac{1}{\sin x}\mathrm{d}x = \ln\left\| \tan\frac x2 \right\| + C = \frac 12 \ln \left\| \frac{1-\cos x}{1 + \cos x}\right\| + C$ |
| 11 | $\displaystyle\int\tan x\mathrm{d}x = \int\frac{\sin x}{\cos x}\mathrm{d}x = -\int\frac{1}{\cos x}\mathrm{d}(\cos x) = -\ln \left\| \cos x\right\| +C$ |
| 12 | $\displaystyle\int\frac{1}{\tan x}\mathrm{d}x = \int\frac{\cos x}{\sin x}\mathrm{d}x = \int\frac{1}{\sin x}\mathrm{d}(\sin x) = \ln\left\| \sin x \right\| + C$ |
| 13 | $\displaystyle\int\arctan x\mathrm{d}x = x\arctan x - \ln \left\| 1+x^2 \right\| +C$ |
| 14<br>Wallis 公式 | $\displaystyle\int^{\frac{\pi}{2}}_{0}\sin^nx\mathrm{d}x = \int^{\frac{\pi}{2}}_{0}\cos^nx\mathrm{d}x = \begin{cases} \displaystyle\frac{n-1}{n}\cdot\frac{n-3}{n-2}\cdot\cdots\cdot\frac12\cdot\frac\pi2,&n为偶数 \\ \displaystyle\frac{n-1}{n}\cdot\frac{n-3}{n-2}\cdot\cdots\cdot\frac23\cdot1,&n为奇数 \end{cases} \\ = \begin{cases} \displaystyle\frac{(n-1)!!}{n!!}\cdot\frac\pi2,&n为偶数 \\ \displaystyle\frac{(n-1)!!}{n!!},&n为奇数 \end{cases}$ |
| 15 | $\displaystyle\int_0^\pi\sin^nx\mathrm{d}x = 2\int^\frac\pi2_0\sin^nx\mathrm{d}x,\int_0^\pi\cos^nx\mathrm{d}x = \begin{cases} 2\displaystyle\int^\frac\pi2_0\cos^nx\mathrm{d}x,&n为偶数 \\ 0,&n为奇数 \end{cases}$ <br> $\displaystyle\int_0^{2\pi}\sin^nx = \int_0^{2\pi}\cos^nx\mathrm{d}x = \begin{cases} 4\displaystyle\int^\frac\pi2_0\sin^nx\mathrm{d}x,&n为偶数 \\ 0,&n为奇数 \end{cases}$ <br> $\displaystyle\int_0^\frac\pi2f(\sin x)\mathrm{d}x = \int_0^\frac\pi2f(\cos x)\mathrm{d}x$, $\displaystyle\int_0^\pi f(\sin x)\mathrm{d}x \ne \int_0^\pi f(\cos x)\mathrm{d}x$ <br> $\displaystyle\int_0^\pi\pi f(\sin x)\mathrm{d}x = \frac\pi2\int_0^\pi f(\sin x)\mathrm{d}x = \pi\int_0^\frac\pi2 f(\sin x)\mathrm{d}x$ |
| 16<br>万能公式 | 令 $u=\displaystyle\tan\frac x2,x=2\arctan u$,则 $\displaystyle\sin x = \frac{2u}{1+u^2},\cos x=\frac{1-u^2}{1+u^2}, \mathrm{d}x = \frac{2}{1+u^2}\mathrm{d}u$ |
| 17 | $\displaystyle\int \frac{a\cos x+ b\sin x}{c\cos x + d \sin x} = A\int\mathrm{d}x+B\int\frac{\mathrm{d}(c\cos x+d \sin x)}{c \cos x + d \sin x}$ <br> (设 $a\cos x + b\sin x = A(c \cos x + d \sin x) + B(c \cos x + d \sin x)'$,由待定系数法求出A、B)$ |
@@ -0,0 +1,285 @@
---
title: Josh's Summary — 工科数学分析<br>Part 1.1 基本微分与积分
mathjax: true
comments: true
copyright: true
toc:
enable: true
number: false
wrap: true
expand_all: true
max_depth: 4
abbrlink: 1823c9d1
date: 2023-04-14 16:25:59
tags:
- 等价无穷小
- 导数公式
- Maclaurin 公式
- 曲率
- 积分公式
- 三角函数
categories:
- - Josh 的学习笔记
- 微积分
- - 数学
- 微积分
---
$\newcommand\diff{\mathop{}\!\mathrm{d}}$
# 1. 常见等价无穷小
||||
| :--: | :--: | :--: |
| $\sin x \sim x$ | $\tan x \sim x$ | $\arcsin x \sim x$ |
| $\arctan x \sim x$ | $\displaystyle\left( 1 - \cos x \right) \sim \dfrac{x^2}{2}$ | $\ln (1+x) \sim x$ |
| $\left( e^x -1 \right) \sim x$ | $\left( a^x - 1 \right) \sim x \ln a$ | $\left( \left( 1+x \right) ^\alpha -1 \right) \sim \alpha x$ |
<!-- more -->
# 2. 导数基本公式
| 一般函数 | 三角函数 | 反三角函数 | 双曲函数<br>(圆函数) |
| :--: | :--: | :--: | :----: |
| $\left( C \right)' = 0$ | $\left( \sin x \right)' = \cos x$ | $\displaystyle\left( \arcsin x \right)' = \dfrac{1}{\sqrt{1-x^2}}$ | $\displaystyle\left( \sinh x \right)' = \left(\dfrac{e^x-e^{-x}}{2}\right)' = \cosh x$ |
| $\left( x^\alpha \right)'=\alpha x^{\alpha-1} \left( \alpha \in \mathbb{Z} \right)$ | $\left( \cos x \right)' = -\sin x$ | $\displaystyle\left( \arccos x \right)' = -\dfrac{1}{\sqrt{1-x^2}}$ | $\displaystyle\left( \cosh x \right)' = \left( \dfrac{e^x+e^{-x}}{2} \right)'=\sinh x$ |
| $\displaystyle\left( \log_ax\right)'=\dfrac{1}{x\ln a}$ | $\displaystyle\left( \tan x \right)' = \dfrac{1}{\cos^2 x}=\sec^2 x$ | $\displaystyle\left( \arctan x \right)' = \dfrac{1}{1+x^2}$ | $\displaystyle\left( \mathrm{arsinh} \, x \right)' = \left(\ln \left( x+\sqrt{x^2 + 1} \right) \right)' = \dfrac{1}{x^2+1}$ |
| $( \ln$\| $x$ \|$)'=\displaystyle\dfrac{1}{x}$ | $\displaystyle\left( \cot x \right)' = -\dfrac{1}{\sin^2 x} = -\csc^2 x$ | $\displaystyle\left( \mathrm{arccot} \, x \right)' = -\dfrac{1}{1+x^2}$ | $\displaystyle\left( \mathrm{arcosh} \, x \right)' = \left( \ln \left( x + \sqrt{x^2 - 1} \right) \right)' = \dfrac{1}{\sqrt{x^2-1}}$
| | $\left( \sec x \right)' = \sec x \cdot \tan x$ |
| | $\left( \csc x \right)' = \csc x \cdot \cot x$ |
- Newton-Leibniz 公式:
$$
\begin{aligned}
\left( u \cdot v \right)^{\left( n \right)} &= u^{\left( n \right)}v + nu^{\left( n-1 \right)}v' + \dfrac{n \left( n-1 \right)}{2!}u^{\left( n-2 \right)}v'' + \cdots + \dfrac{n\left( n-1 \right)\cdots\left(n-k+1\right)}{k!}u^{\left( n-k \right)}v^{(k)} + \cdots + uv^{\left( n \right)} \\
&= \sum_{k=0}^{n}C_n^k u^{\left( u-k \right)}v^k
\end{aligned}
$$
可以注意到 Newton-Leibniz 公式具有类似二项式定理展开的形式。
# 3. 几个初等函数的 Maclaurin 公式
## 3.1 Taylor 公式的一般形式
$$\begin{aligned}
f(x)&=f(x_0) + f'(x_0)(x-x_0) + \dfrac{f''(x_0)}{2!}(x-x_0)^2 + \cdots + \dfrac{f^{(n)}(x_0)}{n!}(x-x_0)^n + R_n
\\
&= \sum_{k=0}^n \dfrac{f^{(n)}(x_0)}{n!}(x - x_0)^n + R_n
\end{aligned}$$
其中
$$
R_n = \dfrac{f^{(n+1)}(\xi)}{(n+1)!}(x-x_0)^{n+1} \xlongequal{x\to x_0} o\left( \left( x - x_0 \right)^n \right), \quad \xi\,在\,x\,和\,x_0\,之间
$$
## 3.2 Maclaurin 公式的一般形式
$$\begin{aligned}
f(x) &= f(0)+f'(0)\,x + \dfrac{f''(0)}{2!}x^2 + \cdots + \dfrac{f^{(n)}(0)}{n!}x^n + R_n
\\
&= \sum_{k=0}^n \dfrac{f^{(n)}(0)}{n!}x^n + R_n
\end{aligned}$$
其中
$$
R_n = \dfrac{f^{(n+1)}(\xi)}{(n+1)!}x^{n+1} = \dfrac{f^{(n+1)}(\theta x)}{(n+1)!} x^{n+1} \xlongequal{x\to x_0} o\left( \left( x - x_0 \right)^n \right), \quad \xi\,在\,0\,和\,x\,之间, 0<\theta<1
$$
## 3.3 指数函数的 Maclaurin 展开式
$$
e^x=1+x+\dfrac{x^2}{2} + \dfrac{x^3}{3} + \cdots +\dfrac{x^n}{n!} + \dfrac{e^{\theta x}}{(n+1)!}, \quad 0<\theta<1
$$
## 3.4 正弦函数的 Maclaurin 展开式
$$
\sin x = x - \dfrac{x^3}{3!} + \dfrac{x^5}{5!} + \cdots + (-1)^{m-1}\dfrac{x^{2m-1}}{(2m-1)!} + R_{2m}
$$
其中
$$
R_{2m}=\dfrac{\sin\left( \theta x + \dfrac{(2m-1)\pi}{2}\right)}{(2m+1)!}x^{2m+1} = o(x^{2m}), \quad 0<\theta<1
$$
## 3.5 余弦函数的 Maclaurin 展开式
$$
\cos x = 1 - \dfrac{x^2}{2!} + \dfrac{x^4}{4!} + \cdots + (-1)^m\dfrac{x^{2m}}{2m!} + R_{2m+1}
$$
其中
$$
R_{2m+1}=\dfrac{\cos(\theta x + (m+1)\pi)}{(2m+2)!} x^{2m+2}=o(x^{2m+2}), \quad 0<\theta<1
$$
## 3.6 $\ln (1+x)$ 的 Maclaurin 展开式
$$
\ln(1+x) = x - \dfrac{x^2}{2} + \dfrac{x^3}{3} -\dfrac{x^4}{4} + \cdots + \dfrac{(-1)^{n-1}x^n}{n} + R_n(x)
$$
其中
$$
R_n(x) = \dfrac{(-1)^n}{(n+1)(1+\theta x)^{n+1}}x^{n+1} = o(x^n), \quad 0<\theta<1
$$
## 3.7 $(1+x)^\alpha$ 的 Maclaurin 展开式
$$
(1+x)^\alpha = 1 + \alpha x + \dfrac{\alpha(\alpha-1)}{2!}x^2 + \cdots + \dfrac{\alpha(\alpha - 1)\cdots (\alpha-n+1)}{n!}x^n + R_n(x)
$$
其中
$$
R_n(x) = \dfrac{\alpha(\alpha -1)\cdots(\alpha-n)}{(n+1)!}(1+\theta x)^{\alpha-n-1}x^{n+1} = o(x), \quad 0<\theta<1
$$
## 3.8 $\dfrac{1}{1-x}$ 的 Maclaurin 展开式
$$
\dfrac{1}{1-x} = 1+x+x^2+\cdots+x^n +o(x^n)
$$
# 4. 曲率及曲率半径
| 曲率 | 曲率半径 |
| :--: | :--: |
| $K=\left\| \dfrac{\diff \alpha}{\diff s}\right\| \xlongequal{令\ \tan \alpha = y', 则\ \alpha = \arctan y'} \dfrac{\left\| \dfrac{y''}{1+y'^2}\diff x \right\|}{\sqrt{1+y'^2}}\diff x = \dfrac{\left\| y'' \right\|}{\left( 1 + y' \right)^{3/2}}$ | $R = \dfrac{1}{K}$ |
# 5. 积分常用公式
| 序 | 描述 | 公式 |
| :--: | :----: | :----------------------------------------------:|
| 1 | 定积分的定义 | $\displaystyle\int^1_0f(x)\diff x=I=\lim_{\lambda \to 0}\sum_{i=1}^{n}f(\xi_i)\Delta x_i$,其中 $\lambda = \max \left\{ \Delta x_1,\Delta x_2, \cdots, \Delta x_n \right\}$ |
| 2 | 变上限积分 | $考察定积分\displaystyle\int^x_af(x)\diff x=\int^x_af(t)\diff t$,对 $\displaystyle\Phi(x)=\int_a^xf(t)\diff t$,有 $\displaystyle\Phi'(x)=\dfrac{\diff }{\diff x}\int_a^xf(t)\diff t = f(x)$ |
| 3 | 变上限积分的扩展 | $\displaystyle\dfrac{\diff }{\diff x}\int^{\beta(x)}_{\alpha(x)}f'(t)\diff t = f\left[ \beta\left(x\right)\right]\beta'(x)-f[\alpha(x)]\alpha'(x)$ |
| 4 | 上下限对称的积分 | 若 $f(x)$ 为偶函数,则 $\displaystyle\int_{-a}^af(x)\diff x=2\int_0^af(x)\diff x$;若 $f(x)$ 为奇函数,则 $\displaystyle\int_{-a}^af(x)\diff x=0$ |
| 5 | 周期函数的积分 | $\displaystyle f(x+T)=f(x)\Rightarrow\int_0^{nT}f(x)\diff x=n\int^T_0f(x)\diff x$ |
| 6 | 分部积分法 | $\displaystyle\int uv'\diff x=uv - \int u'v\diff x \Leftrightarrow \int u\diff v = uv - \int v\diff u$ |
# 6. 基本积分表
| 序 | 积分式 |
| :--: | :-------------------------: |
| 1 | $\displaystyle\int k\diff x=kx+C$,特别地 $\displaystyle\int\diff x=x+C$ |
| 2 | $\displaystyle\int x^\mu\diff x=\dfrac{x^{\mu+1}}{\mu+1}+C(\mu\ne-1)$,特别地 $\displaystyle\int \dfrac{1}{x^2}\diff x=-\dfrac{1}{x}+C,\int\dfrac{1}{\sqrt{x}}\diff x=2\sqrt{x}+C$ |
| 3 | $\displaystyle\int\dfrac{1}{x}\diff x=\ln \|x\|+C$ |
| 4 | $\displaystyle\int\dfrac{1}{1+x^2}\diff x = \arctan x +C$ |
| 5 | $\displaystyle\int\dfrac{1}{\sqrt{1-x^2}}\diff x=\arcsin x+C$ |
| 6 | $\displaystyle\int\sin x\diff x = -\cos x+C, \int\cos x\diff x = \sin x +C$ |
| 7 | $\displaystyle\int\dfrac{\diff x}{\cos^2x} = \int\sec^2x\diff x = \tan x +C, \int\dfrac{\diff x}{\sin^2x}=\int\csc^2x\diff x = -\cot x +C$ |
| 8 | $\displaystyle\int a^x\diff x = \dfrac{a^x}{\ln a} + C$,特别地 $\displaystyle\int e^x\diff x = e^x +C$
| 9 | $\displaystyle\int \sinh x\diff x = \cosh x + C,\int \cosh x \diff x=\sinh x +C$ |
# 7. 三角函数相关公式
| 序 | 公式 |
| :--: | :-------------------------: |
| 1 | $\sin^2x+\cos^2x=1, \tan^2x+1=\sec^2x,\cot^2x+1=\csc^2x$ |
| 2 | $\begin{aligned}&\cosh^2x-\sinh^2x=1,\\ &\sinh(x\pm y)=\sinh x\cdot\cosh y \pm \sinh y\cdot\cosh x, \cosh(x\pm y) = \cosh x\cdot\cosh y,\\ &\sinh2x = 2\sinh x\cdot \cosh x, \cosh 2x = \cosh^2x+\sinh^2x = 2\cosh^2x - 1\end{aligned}$ |
| 3<br>积化和差公式 | $\sin\alpha\cos\beta=\dfrac12[\sin(\alpha+\beta)+\sin(\alpha-\beta)],\cos\alpha\sin\beta = \dfrac12[\sin(\alpha+\beta) - \sin(\alpha-\beta)]$ <br> $\cos\alpha\cos\beta = \dfrac12[cos(\alpha+\beta) + cos(\alpha - \beta)], \sin\alpha\sin\beta=-\dfrac12[\cos(\alpha+\beta) - \cos(\alpha-\beta)]$ |
| 4<br>和差化积公式 | $\displaystyle\sin\alpha + \sin\beta = 2\sin\left(\dfrac{\alpha+\beta}{2}\right) \cos\left(\dfrac{\alpha-\beta}{2}\right), \sin\alpha - \sin\beta = 2\sin\left(\dfrac{\alpha-\beta}{2}\right) \cos\left(\dfrac{\alpha+\beta}{2}\right)$ <br> $\displaystyle\cos\alpha + \cos\beta = 2\cos\left(\dfrac{\alpha+\beta}{2}\right) \cos\left(\dfrac{\alpha-\beta}{2}\right), \cos\alpha - \cos\beta = -2\sin\left(\dfrac{\alpha+\beta}{2}\right) \sin\left(\dfrac{\alpha-\beta}{2}\right)$ |
| 5<br>三角代换 | $\displaystyle\sqrt{a^2-x^2}\xrightarrow{x=a\sin t}a\cos t, \sqrt{a^2+x^2} \xrightarrow{x=a\tan t}a\sec t, \sqrt{x^2-a^2}\xrightarrow{x=a\sec t}a\tan t \left( a>0,t\in\left( -\dfrac{\pi}{2} , \dfrac{\pi}{2} \right) \right)$ |
| 6 | $\displaystyle\int\sqrt{a^2-x^2}\diff x = \dfrac{a^2}{2}\arcsin\dfrac xa + \dfrac12x\sqrt{a^2-x^2} + C(a>0)$ |
| 7 | $\displaystyle\int\sqrt{x^2+a^2}\diff x = \dfrac x2\sqrt{x^2+a^2} + \dfrac{a^2}2\ln \left\| x+\sqrt{x^2+a^2} \right\|+C(a>0)$ |
| 8 | $\displaystyle\int\dfrac{1}{\sqrt{x^2+a^2}}\diff x = \ln\left\| x+ \sqrt{x^2+a^2} \right\| +C$, $\displaystyle\int\dfrac{1}{\sqrt{x^2-a^2}}\diff x = \ln\left\| x + \sqrt{x^2-a^2}\right\|(a>0)$<br>特别地,$\displaystyle\int\dfrac{1}{\sqrt{x^2+1}}\diff x=\ln\left(x+\sqrt{x^2+1}\right) = \mathrm{arsinh}\, x$, $\displaystyle\int\dfrac{1}{\sqrt{x^2-1}}\diff x = \ln\left( x+\sqrt{x^2-1}\right) = \mathrm{arcosh}\, x$ |
| 9 | $\displaystyle\int\sec x\diff x = \int\dfrac{1}{\cos x}\diff x = \int\dfrac{\sec^2x+\sec x \tan x}{\sec x + \tan x}\diff x = \int\dfrac{1}{\sec x + \tan x}\diff (\sec x + \tan x) = \ln \left\| \sec x + \tan x \right\| + C$ |
| 10 | $\displaystyle\int\csc x\diff x = \int\dfrac{1}{\sin x}\diff x = \ln\left\| \tan\dfrac x2 \right\| + C = \dfrac 12 \ln \left\| \dfrac{1-\cos x}{1 + \cos x}\right\| + C$ |
| 11 | $\displaystyle\int\tan x\diff x = \int\dfrac{\sin x}{\cos x}\diff x = -\int\dfrac{1}{\cos x}\diff (\cos x) = -\ln \left\| \cos x\right\| +C$ |
| 12 | $\displaystyle\int\dfrac{1}{\tan x}\diff x = \int\dfrac{\cos x}{\sin x}\diff x = \int\dfrac{1}{\sin x}\diff (\sin x) = \ln\left\| \sin x \right\| + C$ |
| 13 | $\displaystyle\int\arctan x\diff x = x\arctan x - \ln \left\| 1+x^2 \right\| +C$ |
| 14<br>Wallis 公式 | $\displaystyle\int^{\pi/2}_{0}\sin^nx\diff x = \int^{\pi/2}_{0}\cos^nx\diff x = \begin{cases} \displaystyle\dfrac{n-1}{n}\cdot\dfrac{n-3}{n-2}\cdot\cdots\cdot\dfrac12\cdot\dfrac\pi2,&n为偶数 \\ \displaystyle\dfrac{n-1}{n}\cdot\dfrac{n-3}{n-2}\cdot\cdots\cdot\dfrac23\cdot1,&n为奇数 \end{cases} \\ = \begin{cases} \displaystyle\dfrac{(n-1)!!}{n!!}\cdot\dfrac\pi2,&n为偶数 \\ \displaystyle\dfrac{(n-1)!!}{n!!},&n为奇数 \end{cases}$ |
| 15 | $\displaystyle\int_0^\pi\sin^nx\diff x = 2\int^{\pi/2}_0\sin^nx\diff x,\int_0^\pi\cos^nx\diff x = \begin{cases} 2\displaystyle\int^{\pi/2}_0\cos^nx\diff x,&n为偶数 \\ 0,&n为奇数 \end{cases}$ <br> $\displaystyle\int_0^{2\pi}\sin^nx = \int_0^{2\pi}\cos^nx\diff x = \begin{cases} 4\displaystyle\int^{\pi/2}_0\sin^nx\diff x,&n为偶数 \\ 0,&n为奇数 \end{cases}$ <br> $\displaystyle\int_0^{\pi/2}f(\sin x)\diff x = \int_0^{\pi/2}f(\cos x)\diff x$, $\displaystyle\int_0^\pi f(\sin x)\diff x \ne \int_0^\pi f(\cos x)\diff x$ <br> $\displaystyle\int_0^\pi\pi f(\sin x)\diff x = \dfrac\pi2\int_0^\pi f(\sin x)\diff x = \pi\int_0^{\pi/2} f(\sin x)\diff x$ |
| 16<br>万能公式 | 令\ $u=\displaystyle\tan\dfrac x2,x=2\arctan u$,则\ $\displaystyle\sin x = \dfrac{2u}{1+u^2},\cos x=\dfrac{1-u^2}{1+u^2}, \diff x = \dfrac{2}{1+u^2}\diff u$ |
| 17 | $\displaystyle\int \dfrac{a\cos x+ b\sin x}{c\cos x + d \sin x} = A\int\diff x+B\int\dfrac{\diff (c\cos x+d \sin x)}{c \cos x + d \sin x}$ <br> (设 $a\cos x + b\sin x = A(c \cos x + d \sin x) + B(c \cos x + d \sin x)'$,由待定系数法求出 $A, B$) |
# 8. 定积分的几何应用
## 8.1 平面
### 8.1.1 直角坐标
1. 直角梯形的面积
$$\begin{equation*}
A = \int_a^b [f(x_1) - f(x_2)] \diff x
\end{equation*}$$
2. 曲边梯形的面积:对于参数方程 $\begin{cases}
x = \varphi(x) \\ y = {\psi(x)}
\end{cases}$,曲边梯形的面积(变换上下限)
$$\begin{equation*}
A = \int_a^b y\diff x = \int_{t_1}^{t_2} \psi(t) \diff \varphi(t) = \int_{t_1}^{t_2} \psi(t)\varphi'(t) \diff t
\end{equation*}$$
3. 椭圆的面积:椭圆 $\begin{cases}
x = a \cos t \\ y = b \sin t
\end{cases}$,即 $\dfrac{x^2}{a^2} + \dfrac{y^2}{b^2} = 1$ 的面积
$$\begin{equation*}
A = 4 \int_0^a y \diff x = 4ab \int_0^{\pi/2} (1-\cos t)^2 \diff t = 3\pi a^2
\end{equation*}$$
4. 摆线的面积:摆线 $\begin{cases}
x = a (t - \sin t) \\ y = a (1 - \cos t)
\end{cases}$ 的一拱与 $x$ 轴所围图形的面积
$$\begin{equation*}
A = \int_0^2\pi a y \diff x = a^2 \int_0^{2\pi} (1 - \cos t)^2 \diff t = 3\pi a^2
\end{equation*}$$
### 8.1.2 极坐标
1. 扇形的面积:由 $\rho = \rho(\theta)$ 及射线 $\theta = \alpha$ 和 $\theta = \beta$ 所围曲边扇形的面积
$$\begin{equation*}
A = \int_\alpha^\beta \frac{1}{2} \rho^2(\theta) \diff \theta = \frac{1}{2} \int_\alpha^\beta \rho^2 \diff \theta
\end{equation*}$$
2. 阿基米德螺线:阿基米德螺线 $\rho = a \theta (a > 0)$ 对应 $\theta$ 从 $0$ 变换到 $2\pi$ 所围图形的面积
$$\begin{equation*}
A = \int_0^{2\pi} \frac{1}{2} (a\theta)^2\diff \theta = \frac{4}{3} \pi^3 a^2
\end{equation*}$$
3. 双纽线:双纽线 $\rho^2 = a^2 \cos 2\theta$ 所围平面图形的面积
$$\begin{equation*}
A = 4 \int_0^{\pi/4} a^2 \cos 2\theta \diff \theta = a^2
\end{equation*}$$
4. 心形线:心形线 $\rho = a(a+\cos\theta), a>0$ 所围平面图形的面积
$$\begin{equation*}
A = 2 \cdot \frac{1}{2} \int_0^\pi a^2 (1+ \cos \theta)^2 \diff \theta = \frac{3}{2}\pi a^2
\end{equation*}$$
5. 曲线的弧长
| 弧微分 | 直角坐标 | 参数方程 | 极坐标 |
| :--: | :--: | :--: | :--: |
| $\diff s = \sqrt{(\diff x)^2 + (\diff y)^2}$ | $s = \displaystyle\int_a^b \sqrt{1 + y'^2}\diff x$ | $s = \displaystyle\int_a^b \sqrt{\varphi'^2(t) + \psi'^2(t)}\diff t$ | $s = \displaystyle\int_\alpha^\beta \sqrt{\rho^2{\theta} + \rho'^2(\theta)} \diff\theta$
## 8.2 空间
1. 已知平行截面面积求立体体积:令 $A(x)$ 为截面面积,则立体体积
$$\begin{equation*}
V = \int_a^b A(x) \diff x
\end{equation*}$$
2. 旋转体体积
| 薄片法 | 柱壳法 |
| :--: | :--: |
| $V = \displaystyle\int_a^b \pi f^2(x) \diff x$ | $V = \displaystyle\int_a^b 2\pi x \left| f(x) \right|\diff x$ |
+11 -11
View File
@@ -1,5 +1,5 @@
---
title: Josh 的学习笔记之数字信号处理(Part 1——离散时间信号和系统分析基础)
title: "Josh's Review — 数字信号处理<br>Part 1 离散时间信号和系统分析基础"
mathjax: true
comments: true
copyright: true
@@ -8,7 +8,7 @@ toc:
number: false
wrap: true
expand_all: false
max_depth: 3
max_depth: 4
abbrlink: 1391fb05
date: 2023-04-14 17:24:45
tags:
@@ -179,7 +179,7 @@ y^T=\left[\begin{matrix}h_1&h_2&h_3&\cdots&h_{m-1}&h_m\\\end{matrix}\right]_{1\t
# 7. 单位取样响应 $h\left(n\right)$ 和系统频率响应 $H\left(e^{j\omega}\right)$ 的关系
## 7.1 通过单位取样响应 $h\left(n\right)$ 从时域表征系统
## 7.1. 通过单位取样响应 $h\left(n\right)$ 从时域表征系统
&emsp;&emsp;当系统的输入为单位取样序列 $\delta\left(n\right)$ 时的输出序列称为系统的单位取样响应 $h\left(n\right)$,记
@@ -208,11 +208,11 @@ $$\begin{align}
故任何离散时间线性时不变系统,可以通过其单位取样响应 $h\left(n\right)$ 来**完全表征**。
## 7.2 通过系统频率响应 $H\left(e^{j\omega}\right)$ 从频域表征系统
## 7.2. 通过系统频率响应 $H\left(e^{j\omega}\right)$ 从频域表征系统
&emsp;&emsp;离散时间系统的频率响应是由系统的结构参数决定的。当输入频率为 $\omega$ 的复指数序列时,其输出必仍为同一频率的、乘上因子 $H\left(e^{j\omega}\right)$ 的复指数序列。随着输入频率 $\omega$ 的不同,$H\left(e^{j\omega}\right)$ 的值也不同。因此系统的频率响应 $H\left(e^{j\omega}\right)$ **描述了系统对不同频率的复指数序列的不同传输能力**。
## 7.3 单位取样响应 $h\left(n\right)$ 和系统频率响应 $H\left(e^{j\omega}\right)$ 的关系
## 7.3. 单位取样响应 $h\left(n\right)$ 和系统频率响应 $H\left(e^{j\omega}\right)$ 的关系
&emsp;&emsp;令单位取样响应为 $h\left(n\right)$ 的线性时不变系统的输入 $x\left(n\right)=Ae^{j\left(\omega n+\varphi_x\right)}=Ae^{j\omega n}e^{j\varphi_x}$,则输出
@@ -230,15 +230,15 @@ H\left(e^{j\omega}\right)=\sum_{k=-\infty}^{\infty}{h\left(k\right)e^{-j\omega k
# 8. 共轭对称与共轭反对称
## 8.1 共轭对称
## 8.1. 共轭对称
&emsp;&emsp;若序列 $x_e\left(n\right)=x_e^\ast(-n)$,则称 $x_e\left(n\right)$ 是共轭对称的序列,对实序列,又称为偶序列。
## 8.2 共轭反对称
## 8.2. 共轭反对称
&emsp;&emsp;若序列 $x_o\left(n\right)=-x_o^\ast(-n)$,则称 $x_o\left(n\right)$ 是共轭反对称的序列,对实序列,又称为奇序列。
## 8.3 序列的对称性
## 8.3. 序列的对称性
&emsp;&emsp;若
@@ -252,7 +252,7 @@ $$\begin{equation}
x\left(n\right)=x_e\left(n\right)+x_o\left(n\right)
\end{equation}$$
## 8.4 傅里叶变换的共轭对称性
## 8.4. 傅里叶变换的共轭对称性
$$\begin{equation}
X\left(e^{j\omega}\right)=X_e\left(e^{j\omega}\right)+X_o\left(e^{j\omega}\right)
@@ -264,9 +264,9 @@ X_e\left(e^{j\omega}\right)=\frac{1}{2}\left[X\left(e^{j\omega}\right)+X^\ast\le
# 9. 傅里叶变换、拉氏变换和 $z$ 变换的关系
![傅里叶变换、拉氏变换和 $z$ 变换的关系](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2023-04-14-josh-dsp-part-1/2023-04-14-josh-dsp-part-1-010-RelationshipBetweenTransform.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/80/dissolve/20/gravity/southeast/dx/5/dy/5){width=600px}
![傅里叶变换、拉氏变换和 $z$ 变换的关系](../images/post/2023-04-14-josh-dsp-part-1/2023-04-14-josh-dsp-part-1-010-RelationshipBetweenTransform.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/80/dissolve/20/gravity/southeast/dx/5/dy/5){width=600px}
# 参考文献
# 10. 参考文献
王世一. *数字信号处理, 修订版.* 北京理工大学出版社, 1997.
+2 -2
View File
@@ -1,5 +1,5 @@
---
title: Josh 的学习笔记之数字信号处理(Part 2——离散傅里叶级数 DFS)
title: "Josh's Review — 数字信号处理<br>Part 2 离散傅里叶级数 DFS"
mathjax: true
comments: true
copyright: true
@@ -8,7 +8,7 @@ toc:
number: false
wrap: true
expand_all: false
max_depth: 3
max_depth: 4
tags:
- 数字信号和处理
- DSP
+1 -1
View File
@@ -1,5 +1,5 @@
---
title: Josh 的学习笔记之数字信号处理(Part 3——离散傅里叶变换 DFT)
title: "Josh's Review — 数字信号处理<br>Part 3 离散傅里叶变换 DFT"
mathjax: true
comments: true
copyright: true
+13 -13
View File
@@ -1,5 +1,5 @@
---
title: Josh 的学习笔记之数字信号处理(Part 4——快速傅里叶变换 FFT)
title: "Josh's Review — 数字信号处理<br>Part 4 快速傅里叶变换 FFT"
mathjax: true
comments: true
copyright: true
@@ -8,7 +8,7 @@ toc:
number: false
wrap: true
expand_all: false
max_depth: 3
max_depth: 4
abbrlink: 7c6d68a2
date: 2023-04-14 23:11:52
tags:
@@ -114,11 +114,11 @@ X\left(k+\frac{N}{2}\right)&=X_1\left(k+\frac{N}{2}\right)+W_N^{\left(k+\frac{N}
## 3.2 蝶形运算流图符号
![基-2 按时间抽取的 FFT 算法的鲽形图](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2023-04-14-josh-dsp-part-4/2023-04-14-josh-dsp-part-4-010-Radix2DITFFTButterfly.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/80/dissolve/20/gravity/southeast/dx/5/dy/5){width=1000px}
![基-2 按时间抽取的 FFT 算法的鲽形图](../images/post/2023-04-14-josh-dsp-part-4/2023-04-14-josh-dsp-part-4-010-Radix2DITFFTButterfly.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/80/dissolve/20/gravity/southeast/dx/5/dy/5){width=1000px}
## 3.3 8 点基-2 DIT-FFT 推导
![8 点 radix-2 DIT-FFT 推导](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2023-04-14-josh-dsp-part-4/2023-04-14-josh-dsp-part-4-020-Radix2DITFFTDerivation.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/40/dissolve/20/gravity/southeast/dx/5/dy/5){width=1000px}
![8 点 radix-2 DIT-FFT 推导](../images/post/2023-04-14-josh-dsp-part-4/2023-04-14-josh-dsp-part-4-020-Radix2DITFFTDerivation.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/40/dissolve/20/gravity/southeast/dx/5/dy/5){width=1000px}
&emsp;&emsp;对于 8 点的序列,进行两次分解后每部分序列只含有两个点,可以直接计算 DFT。为了得到自然顺序输出的 DFT 序列,将第二级分解以后的结果作为输入。下面推导每级分解后序列的结果表示。
@@ -156,7 +156,7 @@ $$\begin{align}
将上述各式的旋转因子统一为 $W_{\frac{N}{2}}^k=W_N^{2k}$,则一个 8 点的 DFT 可以分解为四个 $\dfrac{N}{4}$ 点的 DFT ,先做 $\dfrac{N}{4}$ 点的 DFT,再用相应的两个 $\dfrac{N}{4}$ 点 DFT 的结果合成 $\dfrac{N}{2}$ 点的 DFT,从而得到 $X_1\left(k\right)、X_2\left(k\right)$,最后组合成为 $N$ 点的 DFT。上述过程的运算流图如下左图,实际绘制按照如下右图即可。
![8 点 radix-2 DIT-FFT 的蝶形图](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2023-04-14-josh-dsp-part-4/2023-04-14-josh-dsp-part-4-030-8PointRadix2DITFFTButterfly.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/80/dissolve/20/gravity/southeast/dx/5/dy/5){width=1000px}
![8 点 radix-2 DIT-FFT 的蝶形图](../images/post/2023-04-14-josh-dsp-part-4/2023-04-14-josh-dsp-part-4-030-8PointRadix2DITFFTButterfly.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/80/dissolve/20/gravity/southeast/dx/5/dy/5){width=1000px}
## 3.4 算法特点
@@ -255,15 +255,15 @@ X\left(2r\right)=\sum_{n=0}^{\frac{N}{2}-1}{x_1\left(n\right)W_{\frac{N}{2}}^{rn
## 4.2 蝶形运算流图符号
![基-2 按频率抽取的 FFT 算法的蝶形图](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2023-04-14-josh-dsp-part-4/2023-04-14-josh-dsp-part-4-040-Radix2DIFFFTButterfly.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/80/dissolve/20/gravity/southeast/dx/5/dy/5){width=1000px}
![基-2 按频率抽取的 FFT 算法的蝶形图](../images/post/2023-04-14-josh-dsp-part-4/2023-04-14-josh-dsp-part-4-040-Radix2DIFFFTButterfly.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/80/dissolve/20/gravity/southeast/dx/5/dy/5){width=1000px}
## 4.3 8 点基-2 DIF-FFT 推导简述
![8 点 radix-2 DIF-FFT 推导](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2023-04-14-josh-dsp-part-4/2023-04-14-josh-dsp-part-4-050-Radix2DIFFFTDerivation.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/40/dissolve/20/gravity/southeast/dx/5/dy/5){width=1000px}
![8 点 radix-2 DIF-FFT 推导](../images/post/2023-04-14-josh-dsp-part-4/2023-04-14-josh-dsp-part-4-050-Radix2DIFFFTDerivation.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/40/dissolve/20/gravity/southeast/dx/5/dy/5){width=1000px}
运算流图如下左图,实际绘制按照如下右图即可。
![8 点 radix-2 DIF-FFT 的蝶形图](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2023-04-14-josh-dsp-part-4/2023-04-14-josh-dsp-part-4-060-8PointRadix2DIFFFTButterfly.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/80/dissolve/20/gravity/southeast/dx/5/dy/5){width=1000px}
![8 点 radix-2 DIF-FFT 的蝶形图](../images/post/2023-04-14-josh-dsp-part-4/2023-04-14-josh-dsp-part-4-060-8PointRadix2DIFFFTButterfly.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/80/dissolve/20/gravity/southeast/dx/5/dy/5){width=1000px}
**对于任何流图,只要保持各节点所连的支路及其传输系数不变,则不论节点位置怎么排列,所得流图总是等效的,最后所得 DFT 结果也是正确的**,只是数据的提取和存放次序不同而已。
@@ -288,7 +288,7 @@ $$\begin{align}
# 5. 基-2 DIT-FFT 和 基-2 DIF-FFT 的比较
![radix-2 DIT-FFT 和 radix-2 DIF-FFT 的比较](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2023-04-14-josh-dsp-part-4/2023-04-14-josh-dsp-part-4-070-Radix2DIFFFTRadix2DIFFFTComparison.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/40/dissolve/20/gravity/southeast/dx/5/dy/5){width=1000px}
![radix-2 DIT-FFT 和 radix-2 DIF-FFT 的比较](../images/post/2023-04-14-josh-dsp-part-4/2023-04-14-josh-dsp-part-4-070-Radix2DIFFFTRadix2DIFFFTComparison.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/40/dissolve/20/gravity/southeast/dx/5/dy/5){width=1000px}
# 6. 分裂基 FFT 算法(split-radix FFT Method)
@@ -379,11 +379,11 @@ X\left(4r+3\right)=\displaystyle\sum_{n=0}^{\frac{N}{4}-1}{x_4^2\left(n\right)W_
## 6.2 L 蝶形运算流图符号
![L 蝶形运算流图符号](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2023-04-14-josh-dsp-part-4/2023-04-14-josh-dsp-part-4-080-Radix24LButterfly.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/80/dissolve/20/gravity/southeast/dx/5/dy/5){width=1000px}
![L 蝶形运算流图符号](../images/post/2023-04-14-josh-dsp-part-4/2023-04-14-josh-dsp-part-4-080-Radix24LButterfly.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/80/dissolve/20/gravity/southeast/dx/5/dy/5){width=1000px}
## 6.3 8 点 radix-2/4 FFT举例
![8 点 radix-2/4 FFT举例](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2023-04-14-josh-dsp-part-4/2023-04-14-josh-dsp-part-4-090-8PointRadix24LButterfly.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/80/dissolve/20/gravity/southeast/dx/5/dy/5){width=600px}
![8 点 radix-2/4 FFT举例](../images/post/2023-04-14-josh-dsp-part-4/2023-04-14-josh-dsp-part-4-090-8PointRadix24LButterfly.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/80/dissolve/20/gravity/southeast/dx/5/dy/5){width=600px}
## 6.4 运算量分析
@@ -441,7 +441,7 @@ X_2\left(k\right)=-{jX}_{op}\left(k\right)=-\frac{j}{2}\left[X\left(k\right)-X^\
\end{equation}$$
蝶形图如下:
![用一个 N点 DFT 同时计算两个 N 点实序列的 DFT的蝶形图](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2023-04-14-josh-dsp-part-4/2023-04-14-josh-dsp-part-4-100-ComputeNPointComplxDFT.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/40/dissolve/20/gravity/southeast/dx/5/dy/5){width=500px}
![用一个 N点 DFT 同时计算两个 N 点实序列的 DFT的蝶形图](../images/post/2023-04-14-josh-dsp-part-4/2023-04-14-josh-dsp-part-4-100-ComputeNPointComplxDFT.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/40/dissolve/20/gravity/southeast/dx/5/dy/5){width=500px}
## 7.2 用一个 $N$ 点 DFT 计算一个 $2N$ 点实序列的 DFT
@@ -495,7 +495,7 @@ X\left(k+N\right)=X_1\left(k\right)-W_{2N}^kX_2\left(k\right),\ \ k=0,1,\cdots,N
蝶形图如下:
![用一个 N 点 DFT 计算一个 2N 点实序列的 DFT的蝶形图](https://josh-blog-1257563604.cos.ap-beijing.myqcloud.com/img/2023-04-14-josh-dsp-part-4/2023-04-14-josh-dsp-part-4-110-Compute2NPointRealDFT.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/40/dissolve/20/gravity/southeast/dx/5/dy/5){width=500px}
![用一个 N 点 DFT 计算一个 2N 点实序列的 DFT的蝶形图](../images/post/2023-04-14-josh-dsp-part-4/2023-04-14-josh-dsp-part-4-110-Compute2NPointRealDFT.png?imageMogr2/thumbnail/!100p|watermark/2/text/QEpvc2ggR2Fv/font/YWhyb25iZC50dGY=/fontsize/40/dissolve/20/gravity/southeast/dx/5/dy/5){width=500px}
# 参考文献
+125
View File
@@ -0,0 +1,125 @@
---
title: "Josh's Review — 数字信号处理<br>Part 5 部分 FFT 蝶形图"
mathjax: true
comments: true
copyright: true
toc:
enable: true
number: false
wrap: true
expand_all: false
max_depth: 4
abbrlink: 14fc3f1c
date: 2023-04-15 22:20:54
tags:
- 数字信号和处理
- DSP
- 蝶形图
- FFT
- 基2按时间抽取
- 基2按频率抽取
- 基4
- 分裂基FFT
categories:
- [Josh 的学习笔记, 数字信号处理]
---
# 1. 4 点 FFT
## 1.1. 基-2 按时间抽取 FFT(4-point radix-2 DIT-FFT)
### 1.1.1. 比特位反序输入、自然顺序输出
![4-point radix-2 DIT-FFT 比特位反序输入、自然顺序输出](../images/post/2023-04-15-josh-dsp-part-5/2023-04-15-josh-dsp-part-5-010-4PointRadix2DITFFTIRON.png){width=400px}
<!-- more -->
### 1.1.2. 自然顺序输入、比特位反序输出
![4-point radix-2 DIT-FFT 自然顺序输入、比特位反序输出](../images/post/2023-04-15-josh-dsp-part-5/2023-04-15-josh-dsp-part-5-020-4PointRadix2DITFFTINOR.png){width=400px}
## 1.2. 基-2 按频率抽取 FFT(4-point radix-2 DIF-FFT)
### 1.2.1. 比特位反序输入、自然顺序输出
![4-point radix-2 DIF-FFT 比特位反序输入、自然顺序输出](../images/post/2023-04-15-josh-dsp-part-5/2023-04-15-josh-dsp-part-5-030-4PointRadix2DIFFFTIRON.png){width=400px}
### 1.2.2. 自然顺序输入、比特位反序输出
![4-point radix-2 DIF-FFT 自然顺序输入、比特位反序输出](../images/post/2023-04-15-josh-dsp-part-5/2023-04-15-josh-dsp-part-5-040-4PointRadix2DIFFFTINOR.png){width=400px}
## 1.3. 分裂基按频率抽取 FFT(4-point split radix-2/4 DIF-FFT)
![4-point split radix-2/4 DIF-FFT](../images/post/2023-04-15-josh-dsp-part-5/2023-04-15-josh-dsp-part-5-050-4PointSplitRadix24DIFFFT.png){width=400px}
## 1.4. 基-4 按频率抽取 FFT(4-point radix-4 DIF-FFT)
![4-point radix-4 DIF-FFT](../images/post/2023-04-15-josh-dsp-part-5/2023-04-15-josh-dsp-part-5-060-4PointRadix4DIFFFT.png){width=400px}
# 2. 8 点 FFT
## 2.1. 基-2 按时间抽取 FFT(8-point radix-2 DIT-FFT)
### 2.1.1. 比特位反序输入、自然顺序输出
![8-point radix-2 DIT-FFT 比特位反序输入、自然顺序输出](../images/post/2023-04-15-josh-dsp-part-5/2023-04-15-josh-dsp-part-5-070-8PointRadix2DITFFTIRON.png){width=600px}
### 2.1.2. 自然顺序输入、比特位反序输出
![8-point radix-2 DIT-FFT 自然顺序输入、比特位反序输出](../images/post/2023-04-15-josh-dsp-part-5/2023-04-15-josh-dsp-part-5-080-8PointRadix2DITFFTINOR.png){width=600px}
## 2.2. 基-2 按频率抽取 FFT(8-point radix-2 DIF-FFT)
### 2.2.1. 比特位反序输入、自然顺序输出
![8-point radix-2 DIF-FFT 自然顺序输入、比特位反序输出](../images/post/2023-04-15-josh-dsp-part-5/2023-04-15-josh-dsp-part-5-090-8PointRadix2DIFFFTIRON.png){width=600px}
### 2.2.2. 2自然顺序输入、比特位反序输出
![8-point radix-2 DIF-FFT 自然顺序输入、比特位反序输出](../images/post/2023-04-15-josh-dsp-part-5/2023-04-15-josh-dsp-part-5-100-8PointRadix2DIFFFTINOR.png){width=600px}
## 2.3. 分裂基按频率抽取 FFT(8-point split radix-2/4 DIF-FFT)
![8-point split radix-2/4 DIF-FFT](../images/post/2023-04-15-josh-dsp-part-5/2023-04-15-josh-dsp-part-5-110-8PointSplitRadix24DIFFFT.png){width=600px}
# 3. 16 点 FFT
## 3.1. 基-2 按时间抽取 FFT(16-point radix-2 DIT-FFT)
### 3.1.1. 比特位反序输入、自然顺序输出
![16-point radix-2 DIT-FFT 比特位反序输入、自然顺序输出](../images/post/2023-04-15-josh-dsp-part-5/2023-04-15-josh-dsp-part-5-120-16PointRadix2DITFFTIRON.png){width=1000px}
### 3.1.2. 自然顺序输入、比特位反序输出
![16-point radix-2 DIT-FFT 自然顺序输入、比特位反序输出](../images/post/2023-04-15-josh-dsp-part-5/2023-04-15-josh-dsp-part-5-130-16PointRadix2DITFFTINOR.png){width=1000px}
## 3.2. 基-2 按频率抽取 FFT(16-point radix-2 DIF-FFT)
### 3.2.1. 比特位反序输入、自然顺序输出
![16-point radix-2 DIF-FFT 比特位反序输入、自然顺序输出](../images/post/2023-04-15-josh-dsp-part-5/2023-04-15-josh-dsp-part-5-140-16PointRadix2DIFFFTIRON.png){width=1000px}
### 3.2.2. 自然顺序输入、比特位反序输出
![16-point radix-2 DIF-FFT 自然顺序输入、比特位反序输出](../images/post/2023-04-15-josh-dsp-part-5/2023-04-15-josh-dsp-part-5-150-16PointRadix2DIFFFTINOR.png){width=1000px}
## 3.3. 分裂基按时间抽取 FFT(16-point split radix-2/4 DIT-FFT)
![16-point split radix-2 DIT-FFT](../images/post/2023-04-15-josh-dsp-part-5/2023-04-15-josh-dsp-part-5-160-16PointSplitRadix24DITFFT.png){width=1000px}
## 3.4. 分裂基按频率抽取 FFT(16-point split radix-2/4 DIF-FFT)
![16-point split radix-2 DIF-FFT](../images/post/2023-04-15-josh-dsp-part-5/2023-04-15-josh-dsp-part-5-170-16PointSplitRadix24DIFFFT.png){width=1000px}
## 3.5. 基-4 按频率抽取 FFT(16-point radix-4 DIF-FFT)
![16-point radix-4 DIF-FFT](../images/post/2023-04-15-josh-dsp-part-5/2023-04-15-josh-dsp-part-5-180-16PointRadix4DITFFT.png){width=1000px}
可以定义如下基-4 DIF-FFT 简化蝶形来简化流图表示的复杂程度
![基-4 DIF-FFT 简化蝶形](../images/post/2023-04-15-josh-dsp-part-5/2023-04-15-josh-dsp-part-5-190-SimplifiedRadix4Butterfly.png){width=800px}
# 参考文献
王世一. *数字信号处理, 修订版.* 北京理工大学出版社, 1997.
+398
View File
@@ -0,0 +1,398 @@
---
title: "Josh's Review — 数字信号处理<br>Part 6 数字滤波器的基本结构"
mathjax: true
comments: true
copyright: true
toc:
enable: true
number: false
wrap: true
expand_all: false
max_depth: 4
abbrlink: 8df56ea6
date: 2023-04-15 23:00:09
tags:
- 数字信号和处理
- DSP
- IIR
- FIR
- 直接型
- 级联型
- 并联型
- 梳状滤波器
- 谐振柜
- 频率取样
- 线性相位
categories:
- [Josh 的学习笔记, 数字信号处理]
---
# 1. 基本运算单元的结构图表示
| 基本运算单元 | 方框图 | 流图 |
| :--: | :----: | :----: |
单位延时 | ![单位延时方框图](../images/post/2023-04-15-josh-dsp-part-6/2023-04-15-josh-dsp-part-6-010-UnitDelayBlock.png){width=150px} | ![单位延时流图](../images/post/2023-04-15-josh-dsp-part-6/2023-04-15-josh-dsp-part-6-020-UnitDelayFlow.png){width=150px}
常数乘法器 | ![常数乘法器方框图](../images/post/2023-04-15-josh-dsp-part-6/2023-04-15-josh-dsp-part-6-030-MultiplierBlock.png){width=150px} | ![常数乘法器流图](../images/post/2023-04-15-josh-dsp-part-6/2023-04-15-josh-dsp-part-6-040-MultiplierFlow.png){width=150px}
加法器 | ![加法器方框图](../images/post/2023-04-15-josh-dsp-part-6/2023-04-15-josh-dsp-part-6-050-AdderBlock.png){width=150px} | ![加法器流图](../images/post/2023-04-15-josh-dsp-part-6/2023-04-15-josh-dsp-part-6-060-AdderFlow.png){width=150px}
<!-- more -->
# 2. IIR(Infinite Impulse Response)数字滤波器的基本结构
&emsp;&emsp;IIR 数字滤波器的结构特点
$$\begin{align}
&系统函数:H\left(z\right)=\frac{Y\left(z\right)}{X\left(z\right)}=\frac{\displaystyle\sum_{k=0}^{M}{b_kz^{-k}}}{1-\displaystyle\sum_{k=1}^{N}{a_kz^{-k}}}\\
&差分方程:y\left(n\right)=\sum_{k=1}^{N}{a_ky\left(n-k\right)}+\sum_{k=0}^{M}{b_kx\left(n-k\right)}
\end{align}$$
- 系统的单位脉冲响应 $h\left(n\right)$ 无限长;
- 系统函数 $H\left(z\right)$ 在有限 $z$ 平面($0<\left|z\right|<\infty$)上有极点存在;
- 存在输出到输入的反馈,递归型结构:直接Ⅰ、Ⅱ型,级、并联型。
## 2.1. 直接Ⅰ型
&emsp;&emsp;将系统函数写为
$$\begin{equation}
H\left( z \right) =\frac{Y\left( z \right)}{X\left( z \right)}=\frac{\displaystyle\sum_{k=0}^M{b_kz^{-k}}}{1-\displaystyle\sum_{k=1}^N{a_kz^{-k}}}=\underset{H_1\left( z \right)}{\underbrace{\sum_{k=0}^M{b_kz^{-k}}}}\times \underset{H_2\left( z \right)}{\underbrace{\left( 1-\displaystyle\sum_{k=1}^N{a_kz^{-k}} \right) ^{-1}}}
\end{equation}$$
则系统框图可表示为
![直接Ⅰ型系统框图](../images/post/2023-04-15-josh-dsp-part-6/2023-04-15-josh-dsp-part-6-070-Direct1SystemBlock.png){width=500px}
由此可得系统的两级输入输出的微分方程
$$\begin{equation}
H_1\left(z\right)=\sum_{k=0}^{M}{b_kz^{-k}}=\frac{U\left(z\right)}{X\left(z\right)}\Longrightarrow u\left(n\right)=\sum_{k=0}^{M}{b_kx\left(n-k\right)}
\end{equation}$$
$$\begin{equation}
H_2\left(z\right)=\left(1-\sum_{k=1}^{N}{a_kz^{-k}}\right)^{-1}=\frac{Y\left(z\right)}{U\left(z\right)}\Longrightarrow y\left(n\right)=u\left(n\right)+\sum_{k=1}^{M}{a_ky\left(n-k\right)}
\end{equation}$$
由微分方程可得直接Ⅰ型 IIR 滤波器的流图
![直接Ⅰ型 IIR 滤波器的流图](../images/post/2023-04-15-josh-dsp-part-6/2023-04-15-josh-dsp-part-6-080-Direct1IIRFlow.png){width=500px}
## 2.2. 直接Ⅱ型(典范型)
&emsp;&emsp;系统函数仍为
$$\begin{equation}
H\left( z \right) =\frac{Y\left( z \right)}{X\left( z \right)}=\frac{\displaystyle\sum_{k=0}^M{b_kz^{-k}}}{1-\displaystyle\sum_{k=1}^N{a_kz^{-k}}}=\underset{H_1\left( z \right)}{\underbrace{\sum_{k=0}^M{b_kz^{-k}}}}\times \underset{H_2\left( z \right)}{\underbrace{\left( 1-\displaystyle\sum_{k=1}^N{a_kz^{-k}} \right) ^{-1}}}
\end{equation}$$
将系统框图变为
![直接Ⅱ型系统框图](../images/post/2023-04-15-josh-dsp-part-6/2023-04-15-josh-dsp-part-6-090-Direct2SystemBlock.png){width=500px}
由此可得系统的两级输入输出的微分方程
$$\begin{equation}
H_2\left(z\right)=\left(1-\sum_{k=1}^{N}{a_kz^{-k}}\right)^{-1}=\frac{W\left(z\right)}{X\left(z\right)}\Longrightarrow w\left(n\right)=x\left(n\right)+\sum_{k=1}^{M}{a_kx\left(n-k\right)}
\end{equation}$$
$$\begin{equation}
H_1\left(z\right)=\sum_{k=0}^{M}{b_kz^{-k}}=\frac{Y\left(z\right)}{W\left(z\right)}\Longrightarrow y\left(n\right)=\sum_{k=0}^{M}{b_kw\left(n-k\right)}
\end{equation}$$
由微分方程可得直接Ⅱ型 IIR 滤波器的流图
![直接Ⅱ型 IIR 滤波器的流图](../images/post/2023-04-15-josh-dsp-part-6/2023-04-15-josh-dsp-part-6-100-Direct2IIRFlow.png){width=400px}
- 直接型 IIR 滤波器的结构特点
<table>
<tr>
<td></td>
<th>直接Ⅰ型</th>
<th>直接Ⅱ型</th>
</tr>
<tr>
<th rowspan="2">不同点</th>
<td>两个网络级联:第一个横向结构 <i>M</i> 节延时网络实现零点,第二个有反馈的 <i>N</i> 节延时网络实现极点。</td>
<td>两个网络级联:第一个有反馈的 <i>N</i> 节延时网络实现极点,第二个横向结构 <i>M</i> 节延时网络实现零点。</td>
</tr>
<tr>
<td>延时单元数:<i>N</i> + <i>M</i><br>乘法器数:<i>N</i> + <i>M</i> + 1<br>加法器数:1
</td>
<td>延时单元数:max{<i>N</i> , <i>M</i>}<br>乘法器数:<i>N</i> + <i>M</i> + 1<br>加法器数:2
</td>
</tr>
<tr>
<th rowspan="3">相同点</th>
<td colspan="2">系数 <i>a<sub>k</sub> , b<sub>k</sub></i> 不能直接决定单个零极点,因而不能很好地进行滤波器性能控制。</td>
</tr>
<tr>
<td colspan="2">极点对系数(零极点的位置)变化过于灵敏,从而使系统频率响应对系数变化过于灵敏,也就是对有限精度(有限字长)运算过于灵敏,容易出现不稳定或产生较大误差。</td>
</tr>
<tr>
<td colspan="2">计算的累积误差较大</td>
</tr>
</table>
## 2.3. 级联型
&emsp;&emsp;将系统函数按零极点因式分解,可表示为
$$\begin{equation}
H\left(z\right)=\frac{\displaystyle\sum_{k=0}^{M}{b_kz^{-k}}}{1-\displaystyle\sum_{k=1}^{N}{a_kz^{-k}}}=A\frac{\displaystyle\prod_{k=1}^{M_1}\left(1-p_kz^{-1}\right)\displaystyle\prod_{k=1}^{M_2}\left(1-q_kz^{-1}\right)\left(1-q_k^\ast z^{-1}\right)}{\displaystyle\prod_{k=1}^{N_1}\left(1-c_kz^{-1}\right)\displaystyle\prod_{k=1}^{N_2}\left(1-d_kz^{-1}\right)\left(1-d_k^\ast z^{-1}\right)}
\end{equation}$$
其中 $A$ 为常数,$M=M_1+2M_2$,$N=N_1+2N_2$,$p_k,c_k$分别为实数零、极点,$q_k,q_k^\ast$ 和 $d_k,d_k^\ast$ 分别为复共轭零、极点。将共轭成对的复数零、极点合并为为实系数二阶多项式,得
$$\begin{equation}
H\left(z\right)=A\prod_{k=1}^{L}\left[\frac{1+\beta_{1k}z^{-1}+\beta_{2k}z^{-2}}{1-\alpha_{1k}z^{-1}-\alpha_{2k}z^{-2}}\right]=A\prod_{k=1}^{L}{H_k\left(z\right)},\ \ L=\left\lfloor\frac{N+1}{2}\right\rfloor
\end{equation}$$
则系统框图可表示为
![级联型 IIR 滤波器的系统框图](../images/post/2023-04-15-josh-dsp-part-6/2023-04-15-josh-dsp-part-6-110-CascadingIIRBlock.png){width=700px}
进一步可得级联型 IIR 滤波器的流图
![级联型 IIR 滤波器的流图](../images/post/2023-04-15-josh-dsp-part-6/2023-04-15-josh-dsp-part-6-120-CascadingIIRFlow.png){width=700px}
- 级联型 IIR 滤波器的结构特点
- 分别调整系数 $\beta_{1k},\beta_{2k}$、$\alpha_{1k},\alpha_{2k}$,能单独调整滤波器的第k对零、极点,而不影响其它零、极点,由此,可以方便的调整滤波器的频响性能。
- 运算的累积误差较小、所需存储单元少,可实现时分复用、组合方式多等。
## 2.4. 并联型
&emsp;&emsp;将系统函数展开成部分分式的形式,可表示为
$$\begin{equation}
H\left(z\right)=\sum_{k=0}^{M-N}{G_kz^{-k}}+\sum_{k=1}^{N_1}\frac{A_k}{1-g_kz^{-1}}+\sum_{k=1}^{N_2}\frac{\beta_{0k}+\beta_{1k}z^{-1}}{1-\alpha_{1k}z^{-1}-\alpha_{2k}z^{-2}}
\end{equation}$$
其中 $G_k,A_k,g_k,\beta_{0k},\beta_{1k},\alpha_{1k},\alpha_{2k}$ 均为实数。且当 $M<N$ 时,上式不包含 $\displaystyle\sum_{k=0}^{M-N}{G_kz^{-k}}$ 项;当 $M=N$ 时,上式变为
$$\begin{equation}
H\left(z\right)=G_0+\sum_{k=1}^{N_1}\frac{A_k}{1-g_kz^{-1}}+\sum_{k=1}^{N_2}\frac{\beta_{0k}+\beta_{1k}z^{-1}}{1-\alpha_{1k}z^{-1}-\alpha_{2k}z^{-2}}\ (M=N)
\end{equation}$$
可得 $M=N$ 时并联型 IIR 滤波器的系统框图和流图
![并联型 IIR 滤波器的系统框图和流图](../images/post/2023-04-15-josh-dsp-part-6/2023-04-15-josh-dsp-part-6-130-ParallelIIRBlockFlow.png){width=1000px}
- 并联型IIR滤波器的结构特点
- 通过调整系数 $\alpha_{1k},\alpha_{2k}$,可单独调整一对极点位置,但不能单独调整零点位置。
- 各并联基本节的误差互相不影响,故运算累积误差小。
- 可进行并行运算,运算速度高。
## 2.5. 转置定理
&emsp;&emsp;对于单输入单输出系统,将原网络中所有支路方向倒转,并将输入 $x\left(n\right)$ 和输出 $y\left(n\right)$ 相互交换,则倒转后的结构与原结构的系统函数 $H(z)$ 向相同。
# 3. FIR(Finite Impulse Response)数字滤波器的基本结构
&emsp;&emsp;FIR 数字滤波器的结构特点
$$\begin{align}
&系统函数:H\left(z\right)=\frac{Y\left(z\right)}{X\left(z\right)}=\sum_{n=0}^{N-1}{h\left(n\right)z^{-n}}\\
&差分方程:y\left(n\right)=\sum_{k=0}^{N-1}h\left(k\right)x\left(n-k\right)=h\left(n\right)\ast x\left(n\right)
\end{align}$$
- 系统的单位脉冲响应 $h(n)$ 有限长($N$ 点);
- 系统函数 $H\left(z\right)$ 在 $\left|z\right|>0$ 处收敛,有限 $z$ 平面只有零点,全部极点在 $z=0$ 处(因果系统);
- 没有输出到输入的反馈,一般为非递归型结构。
## 3.1. 直接型(卷积型、横截型)
&emsp;&emsp;由 FIR 数字滤波器的差分方程
$$\begin{equation}
y\left(n\right)=\sum_{k=0}^{N=1}h\left(k\right)x\left(n-k\right)=h\left(n\right)\ast x\left(n\right)
\end{equation}$$
可得直接型 FIR 滤波器的流图
![直接型 FIR 滤波器的流图](../images/post/2023-04-15-josh-dsp-part-6/2023-04-15-josh-dsp-part-6-140-Direct1FIRFlow.png){width=600px}
## 3.2. 级联型
&emsp;&emsp;当需要灵活方便地控制滤波器的传输零点时,可将 $H\left(z\right)$ 分解成实系数二阶因式的乘积形式,表示为
$$\begin{equation}
H\left(z\right)=\sum_{n=0}^{N-1}{h\left(n\right)z^{-n}}=\sum_{k=1}^{\left\lfloor\frac{N}{2}\right\rfloor}\left(\beta_{0k}+\beta_{1k}z^{-1}+\beta_{2k}z^{-2}\right)
\end{equation}$$
可得级联型 FIR 滤波器的流图
![级联型 FIR 滤波器的流图](../images/post/2023-04-15-josh-dsp-part-6/2023-04-15-josh-dsp-part-6-150-CascadingFIRFlow.png){width=600px}
- 级联型FIR滤波器的结构特点:
- 由于这种结构所需的系数比直接型多,所需乘法运算也比直接型多,很少用。
- 由于这种结构的每一节控制一对零点,因而通常仅在需要控制传输零点时用。
## 3.3. 频率取样型
&emsp;&emsp;系统函数 $H\left(z\right)$ 在单位圆上作 $N$ 等分取样的取样值就是 $h\left(n\right)$ 的 DFT $H\left(k\right)$。由[内插公式](https://josh-gao.blog.csdn.net/article/details/106087154#5__319),用 $H\left(k\right)$ 恢复 $H\left(z\right)$ 的内插公式为
$$\begin{equation}
H\left( z \right) =\underset{H_c\left( z \right)}{\underbrace{\left( 1-z^{-N} \right) }}\frac{1}{N}\sum_{k=0}^{N-1}{\underset{H_k\left( z \right)}{\underbrace{\frac{H\left( k \right)}{1-W_{N}^{-k}z^{-1}}}}}
\end{equation}$$
可见频率取样型 FIR 系统可用子 FIR 系统 $H_c\left(z\right)=1-z^{-N}$ 和子 IIR 系统 $\displaystyle\sum_{k=0}^{N-1}{H_k\left(z\right)}$ 表示。
### 3.3.1. 梳状滤波器 $H_c\left(z\right)$
![梳状滤波器](../images/post/2023-04-15-josh-dsp-part-6/2023-04-15-josh-dsp-part-6-160-CombFilter.png){width=800px}
&emsp;&emsp;子 FIR 系统 $H_c\left(z\right)=1-z^{-N}$ 是一个由 $N$ 节延迟单元组成的梳状滤波器,在单位圆上有 $N$ 个等分零点。可将梳状滤波器的频率响应写为
$$\begin{equation}
\begin{aligned}
H_c\left(e^{j\omega}\right)&=\left.H_c\left(z\right)\right|_{z=e^{j\omega}}=1-e^{-j\omega N}\\
&=e^{-j\frac{\omega N}{2}}\left(e^{j\frac{\omega N}{2}}-e^{-j\frac{\omega N}{2}}\right)=2je^{-j\frac{\omega N}{2}}\sin{\frac{\omega N}{2}}
\end{aligned}
\end{equation}$$
其幅频特性
$$\begin{equation}
\left|H_c\left(e^{j\omega}\right)\right|=2\left|\sin{\frac{\omega N}{2}}\right|
\end{equation}$$
### 3.3.2. 谐振柜 $\displaystyle\sum_{k=0}^{N-1}{H_k\left(z\right)}$
&emsp;&emsp;子 IIR 系统 $\displaystyle\sum_{k=0}^{N-1}{H_k\left(z\right)}$ 是由 $N$ 个谐振器组成的谐振“柜”。每一个谐振器 $H_k\left(z\right)=\dfrac{H\left(k\right)}{1-W_N^{-k}z^{-1}}$ 都是一个一阶网络,在单位圆上有一极点 $z_k=W_N^{-k}=e^{j\frac{2\pi}{N}k}$,因此谐振器对频率为 $\omega=\dfrac{2\pi}{N}k$ 的响应是 $\infty$,是一个谐振频率为 $\dfrac{2\pi}{N}k$ 的无耗谐振器。并联谐振柜的极点正好各自抵消一个梳状滤波器的零点,从而使系统在频率点 $\omega=\dfrac{2\pi}{N}k$ 的响应就是 $H\left(k\right)$。
&emsp;&emsp;将梳状滤波器和谐振柜级联可得到频率取样型 FIR 滤波器的结构
![频率取样型 FIR 滤波器的结构](../images/post/2023-04-15-josh-dsp-part-6/2023-04-15-josh-dsp-part-6-170-FrequencySampling.png){width=600px}
- 频率取样型 FIR 滤波器的结构特点:
- (优点)调整 $H\left(k\right)$ 就可以有效地调整频响特性(在频率 $\omega_k=\dfrac{2\pi}{N}k$ 处的响应即为 $H\left(k\right)$)。
- (优点)若 $h\left(n\right)$ 长度相同,则除了各支路增益 $H\left(k\right)$ 外网络结构完全相同,便于标准化、模块化。
- (缺点)有限字长效应可能导致零极点不能完全对消(梳状滤波器的零点由延时器形成,并不受量化误差影响),导致系统不稳定。
- (缺点)系数多为复数,增加了复数乘法和存储量。
### 3.3.3. 修正频率取样型
&emsp;&emsp;由于谐振器的所有极点均在单位圆上,当系数量化时,这些极点会移动,因此系统的稳定裕度为零,实际上是不能使用的。因此将所有谐振器的极点设置在半径 $r$ 小于 $1$ 又接近于 $1$ 的圆周上,为了使得子 FIR 系统的零点需要和这些极点重合以相互抵消,故梳状滤波器的零点也移到半径r的圆周上。修正后的系统函数为
$$\begin{equation}
H\left(z\right)=\frac{1-r^Nz^{-N}}{N}\sum_{k=0}^{N-1}\frac{H_r\left(k\right)}{1-rW_N^{-k}z^{-1}}
\end{equation}$$
此时谐振柜的第 $k$ 个谐振器的极点变为 $rW_N^{-k}$,其中 $H_r\left(k\right)$ 是修正点的取样值,因为 $r\approx1$,则
$$\begin{equation}
H_r\left(k\right)=\left.H\left(z\right)\right|_{z=rW_N^{-k}}=H\left(rW_N^{-k}\right)\approx H\left(W_N^{-k}\right)=H\left(k\right)
\end{equation}$$
则修正后的系统函数可近似为
$$\begin{equation}
H\left(z\right)=\frac{1-r^Nz^{-N}}{N}\sum_{k=0}^{N-1}\frac{H\left(k\right)}{1-rW_N^{-k}z^{-1}}
\end{equation}$$
为了使系数是实数,将共轭根合并,这些共轭根在半径为r的圆周上以实轴对称分布。由对称性 $z_{N-k}=z_k^\ast,W_N^{-\left(N-k\right)}=W_N^k=\left(W_N^{-k}\right)^\ast$,将第 $k$ 个和第 $N-k$ 个谐振器合并成一个实系数的二阶网络
$$\begin{equation}
\begin{aligned}
H_k\left(z\right)&\approx\frac{H\left(k\right)}{1-rW_N^{-k}z^{-1}}+\frac{H\left(N-k\right)}{1-rW_N^{-\left(N-k\right)}z^{-1}}=\frac{H\left(k\right)}{1-rW_N^{-k}z^{-1}}+\frac{H^\ast\left(k\right)}{1-r\left(W_N^{-k}\right)^\ast z^{-1}}\\
&=\frac{H\left(k\right)+H^\ast\left(k\right)-H\left(k\right)rW_N^kz^{-1}-H^\ast\left(k\right)rW_N^{-k}z^{-1}}{1-z^{-1}\left(W_N^{-k}+W_N^k\right)+r^2z^{-2}}\\
&=\frac{\beta_{0k}+\beta_{1k}z^{-1}}{1-z^{-1}2r\cos{\left(\frac{2\pi}{N}k\right)+r^2z^{-2}}}
\end{aligned}
\end{equation}$$
其中
$$\begin{equation}
\begin{cases}
\beta_{0k}=2\Re{\left[H\left(k\right)\right]}\\
\beta_{1k}=-2r\Re{\left[H\left(k\right)W_N^k\right]}
\end{cases},\ \
\begin{cases}
\begin{aligned}
k&=1,2,\cdots,\frac{N-1}{2},\ \ &k为奇数\\
k&=1,2,\cdots,\frac{N}{2},&k为偶数
\end{aligned}
\end{cases}
\end{equation}$$
![修正频率取样型](../images/post/2023-04-15-josh-dsp-part-6/2023-04-15-josh-dsp-part-6-180-ModifiedFrequencySampling.png){width=800px}
&emsp;&emsp;当 $N$ 为偶数时,除了共轭根,还有一对实数根,分别位于 $k=0,\dfrac{N}{2}$ 两点,则此时系统函数为
$$\begin{equation}
H\left(z\right)=\left(1-r^Nz^{-N}\right)\cdot\frac{1}{N}\cdot\left[H_0\left(z\right)+H_\frac{N}{2}\left(z\right)+\sum_{k=1}^{\frac{N}{2}-1}{H_k\left(z\right)}\right]
\end{equation}$$
&emsp;&emsp;当 $N$ 为奇数时,除了共轭根,只有一个实数根,位于 $k=0$ 处,则此时系统函数为
$$\begin{equation}
H\left(z\right)=\left(1-r^Nz^{-N}\right)\cdot\frac{1}{N}\cdot\left[H_0\left(z\right)+\sum_{k=1}^{\frac{N-1}{2}}{H_k\left(z\right)}\right]
\end{equation}$$
在上两式中
$$\begin{equation}
H_0\left(z\right)=\frac{H\left(0\right)}{1-rz^{-1}},\ \ H_\frac{N}{2}\left(z\right)=\frac{H\left(\dfrac{N}{2}\right)}{1+rz^{-1}}
\end{equation}$$
则修正频率取样型 FIR 滤波器的结构为
![修正频率取样型 FIR 滤波器的结构](../images/post/2023-04-15-josh-dsp-part-6/2023-04-15-josh-dsp-part-6-190-ModifiedFrequencySamplingFIRStructure.png){width=600px}
- 修正频率取样型 FIR 滤波器的结构特点:
- 结构有递归部分——谐振柜;又有非递归部分——梳状滤波器。
- 它的零、极点数目只取决于单位脉冲响应的长度,因而单位脉冲响应长度相同。利用同一梳状滤波器、同一结构而只有加权系数 $\beta_{0k},\beta_{1k},H\left(0\right),H\left(\dfrac{N}{2}\right)$ 不同的谐振器,就能得到不同的滤波器。
- 其结构可以高度模块化,可时分复用。
## 3.4. 线性相位型
&emsp;&emsp;线性相位的因果FIR系统的单位取样响应满足
$$\begin{equation}
h\left(n\right)=\pm h\left(N-1-n\right)
\end{equation}$$
即序列要么是奇对称的,要么是偶对称的。
&emsp;&emsp;当 $N$ 为奇数时,系统函数可表示为
$$\begin{equation}
\begin{aligned}
H\left(z\right)&=\sum_{n=0}^{N-1}{h\left(n\right)z^{-n}}=\sum_{n=0}^{\frac{N-1}{2}-1}{h\left(n\right)z^{-n}}+h\left(\frac{N-1}{2}\right)z^\frac{N-1}{2}+\sum_{n=\frac{N-1}{2}+1}^{N-1}{h\left(n\right)z^{-n}}\\
&=\sum_{n=0}^{\frac{N-1}{2}-1}h\left(n\right)\left[z^{-n}\pm z^{-\left(N-1-n\right)}\right]+h\left(\frac{N-1}{2}\right)z^\frac{N-1}{2}
\end{aligned}
\end{equation}$$
&emsp;&emsp;当 $N$ 为偶数时,系统函数可表示为
$$\begin{equation}
H\left(z\right)=\sum_{n=0}^{N-1}{h\left(n\right)z^{-n}}=\sum_{n=0}^{\frac{N}{2}-1}{h\left(n\right)z^{-n}}+\sum_{n=\frac{N}{2}}^{N-1}{h\left(n\right)z^{-n}}=\sum_{n=0}^{\frac{N}{2}-1}h\left(n\right)\left[z^{-n}\pm z^{-\left(N-1-n\right)}\right]
\end{equation}$$
**当序列 $h\left(n\right)$ 偶对称时,取“$+$”号;当序列奇对称时,取“$-$”号**。则线性相位型 FIR 滤波器的结构为
![线性相位型 FIR 滤波器的结构](../images/post/2023-04-15-josh-dsp-part-6/2023-04-15-josh-dsp-part-6-200-LinearPhaseFIRStructure.png){width=900px}
## 3.5. 快速卷积型(略)
# 参考文献
王世一. *数字信号处理, 修订版.* 北京理工大学出版社, 1997.
+542
View File
@@ -0,0 +1,542 @@
---
title: "Josh's Review — 数字信号处理<br>Part 7 数字滤波器设计"
mathjax: true
comments: true
copyright: true
toc:
enable: true
number: false
wrap: true
expand_all: false
max_depth: 4
tags:
- 数字信号和处理
- DSP
- 巴特沃斯
- 数字滤波器
- IIR
- FIR
- 频率取样
- 窗函数
- 通带波动
- 阻带衰减
- 截止频率
- 系统函数
- 脉冲响应不变
- 双线性变换
- 线性相位
categories:
- - Josh 的学习笔记
- 数字信号处理
abbrlink: 60664a7e
date: 2023-04-15 23:33:09
---
# 1. 幅度平方响应与数字滤波器的技术指标
## 1.1. 幅度平方响应
&emsp;&emsp;常采用滤波器的幅度平方响应 $\left|H\left(e^{j\omega}\right)\right|^2$ 来描述滤波器的选频特性。
## 1.2. 数字滤波器的技术指标
![数字滤波器的技术指标](../images/post/2023-04-15-josh-dsp-part-7/2023-04-15-josh-dsp-part-7-010-DigtalFilterBenchmark.png){width=600px}
1. 通带截止频率(passband edge frequency):$\omega_p$。
2. 阻带截止频率(stopband edge frequency):$\omega_s$。
3. 通带波动(passband ripple in dB):$R_p=-10\lg{\dfrac{1}{1+\varepsilon^2}}$,其中 $\varepsilon$ 为通带波动系数。
4. 阻带衰减(stopband attenuation in dB):$A_s=20\lg{\delta}$。
<!-- more -->
# 2. 低通 IIR 数字滤波器设计
## 2.1. 巴特沃斯(Butterworth)模拟原型滤波器
![巴特沃斯(Butterworth)模拟原型滤波器](../images/post/2023-04-15-josh-dsp-part-7/2023-04-15-josh-dsp-part-7-020-ButterworthAnalogFilter.png){width=500px}
### 2.1.1. 幅度平方频率响应
&emsp;&emsp;$N$ 阶 Butterworth 模拟滤波器的幅度平方频率响应为
$$\begin{equation}
A^2\left(\Omega\right)=\left|H_a\left(j\Omega\right)\right|^2=\frac{1}{1+\left(\dfrac{\Omega}{\Omega_c}\right)^{2N}}
\end{equation}$$
其中 $A^2\left(\Omega\right)$ 为幅度平方函数,整数 $N$ 为滤波器阶数,$\Omega_c$ 为 3 dB 截止频率,$\Omega_p$ 为通带截止频率,$\left(1+\varepsilon^2\right)^{-1}$ 为通带截止频率处的幅度平方频响值,$\Omega_s$ 为阻带截止频率,$\delta^2$ 为阻带截止频率处的幅度平方频响值。
&emsp;&emsp;Butterworth 滤波器在通带中拥有最大平坦的振幅特性,即 $N$ 阶低通 Butterworth 滤波器在 $\Omega=0$ 处的幅度平方函数的前 $(2N-1)$ 阶导数等于零,在止带内接近于单调变化。
### 2.1.2. 极点分布及系统函数的确定
&emsp;&emsp;$N$ 阶 Butterworth 模拟滤波器的幅度平方频率响应可表示为
$$\begin{equation}
\begin{aligned}
A^2\left(\Omega\right)&=\left|H_a\left(j\Omega\right)\right|^2=H_a\left(j\Omega\right)H_a^\ast\left(j\Omega\right)=H_a\left(j\Omega\right)H_a\left(-j\Omega\right)\\
&=\left.H_a\left(s\right)H_a\left(-s\right)\right|_{s=j\Omega}=\frac{1}{1+\left(\dfrac{s}{j\Omega_c}\right)^{2N}}
\end{aligned}
\end{equation}$$
令 $A^2\left(\Omega\right)=0$,可解得极点
$$\begin{equation}
s_k=\left(-1\right)^\frac{1}{2N}\left(j\Omega_c\right)=\Omega_ce^{j\left(\frac{1}{2}+\frac{2k+1}{2N}\right)\pi},\ \ k=0,1,\cdots,2N-1
\end{equation}$$
由此可得常用低阶次Butterworth滤波器的系统函数
| 阶次 | 系统函数 $H_a\left(s\right)=\dfrac{\left(-1\right)^Ns_0s_1\cdots s_{N-1}}{\left(s-s_0\right)\left(s-s_1\right)\cdots(s-s_{N-1})}$ |
| :--: | :--------------: |
| 1 | $\displaystyle\frac{\Omega_c}{\left(s+\Omega_c\right)}$ |
| 2 | $\displaystyle\frac{\Omega_c^2}{\left(s^2+\sqrt2\Omega_cs+\Omega_c^2\right)}$ |
| 3 | $\displaystyle\frac{\Omega_c^3}{(s^3+2\Omega_cs^2+2\Omega_c^2s+\Omega_c^3)}$ |
### 2.1.3. 参数 $N$ 和 $\Omega_c$ 的确定
#### 2.1.3.1. 参数选取原则
1. 在通带范围内允许的最大衰减为 $\left(1+\varepsilon^2\right)^{-1}$ 或 $\alpha_p\text{dB}$,截止频率为$\Omega_p$。
$$\begin{equation}
10\lg{\frac{1}{1+\varepsilon^2}}=-\alpha_p\Longrightarrow\lg{\left(1+\varepsilon^2\right)}=\frac{\alpha_p}{10}\Longrightarrow\varepsilon=\sqrt{10^{\frac{\alpha_p}{10}-1}}
\end{equation}$$
2. 在阻带范围内允许的最小衰减为 $\delta^2$ 或 $\alpha_s\text{dB}$,临界频率为 $\Omega_s$。
$$\begin{equation}
10\lg{\delta^2}=-\alpha_s\Longrightarrow\delta^{-2}={10}^\frac{\alpha_s}{10}
\end{equation}$$
#### 2.1.3.2. 参数确定
&emsp;&emsp;由参数选取原则,有
$$\begin{equation}
\begin{aligned}
&\left|H_a\left(j\Omega_p\right)\right|^2=\frac{1}{1+\left(\frac{\Omega_p}{\Omega_c}\right)^{2N}}\geqslant\frac{1}{1+\varepsilon^2}\Longrightarrow\left(\frac{\Omega_p}{\Omega_c}\right)^{2N}\leqslant\varepsilon^2\\
\Longrightarrow&\left(\frac{\Omega_c}{\Omega_p}\right)^N\geqslant\varepsilon^{-1}\\
&\left|H_a\left(j\Omega_s\right)\right|^2=\frac{1}{1+\left(\dfrac{\Omega_s}{\Omega_c}\right)^{2N}}\leqslant\delta^2\Longrightarrow\left(\frac{\Omega_s}{\Omega_c}\right)^{2N}\geqslant\delta^{-2}-1\\
\Longrightarrow&\left(\frac{\Omega_s}{\Omega_c}\right)^N\geqslant\sqrt{\delta^{-2}-1}
\end{aligned}
\end{equation}$$
由上两式,有
$$\begin{equation}
N\geqslant\left\lceil\frac{\lg{\left(\dfrac{\sqrt{\delta^{-2}-1}}{\varepsilon}\right)}}{\lg{\left(\dfrac{\Omega_s}{\Omega_p}\right)}}\right\rceil=\left\lceil\frac{\lg{\dfrac{10^\frac{\alpha_s}{10}-1}{10^\frac{\alpha_p}{10}-1}}}{2\lg{\left(\dfrac{\Omega_s}{\Omega_p}\right)}}\right\rceil
\end{equation}$$
$$\begin{equation}
\Omega_c\in\left[\Omega_p\varepsilon^{-\frac{1}{N}},\Omega_s\left(\delta^2-1\right)^{-\frac{1}{2N}}\right]=\left[\Omega_p\left({10}^\frac{\alpha_p}{10}-1\right)^{-\frac{1}{2N}},\Omega_s\left({10}^\frac{\alpha_s}{10}-1\right)^{-\frac{1}{2N}}\right]
\end{equation}$$
对于 $\Omega_c$,通常取其下边带即可,即
$$\begin{equation}
\Omega_c=\Omega_p\varepsilon^{-\frac{1}{N}}=\Omega_p\left({10}^\frac{\alpha_p}{10}-1\right)^{-\frac{1}{2N}}
\end{equation}$$
## 2.2. 模拟原型低通滤波器数字化的时域方法——脉冲响应不变法(Impulse Invariance Method)
### 2.2.1. 变换原理
&emsp;&emsp;对模拟原型滤波器的系统函数 $H_a\left(s\right)$ 进行反拉氏变换,得到相应模拟滤波器的单位脉冲响应 $h_a\left(t\right)$,即
$$\begin{equation}
h_a\left(t\right)=\mathrm{ILT}\left[H_a\left(s\right)\right]=\mathrm{ILT}\left[\sum_{k=0}^{N-1}\frac{c_k}{s-s_k}\right]=\sum_{k=0}^{N-1}{c_ke^{s_kt}u\left(t\right)}
\end{equation}$$
对模拟滤波器的单位脉冲响应进行采样后进行 $z$ 变换即可得到数字滤波器的系统函数 $H\left(z\right)$,即
$$\begin{equation}
H\left(z\right)=\mathrm{ZT}\left[h\left(n\right)\right]=\mathrm{ZT}\left[\left.h_a\left(t\right)\right|_{t=nT}\right]
\end{equation}$$
在实际设计时,为了避免数字滤波器在取样间隔T很小(采样频率很高)的情况下出现过高的增益,对取样进行如下修正
$$\begin{equation}
h\left(n\right)=Th_a\left(nT\right)
\end{equation}$$
由此可将导出 Butterworth 数字低通滤波器的系统函数
$$\begin{equation}
\begin{aligned}
H\left(z\right)&=\mathrm{ZT}\left[h\left(n\right)\right]=\mathrm{ZT}\left[Th_a\left(nT\right)\right]=\mathrm{ZT}\left[\sum_{k=0}^{N-1}{Tc_ke^{s_knT}u\left(t\right)}\right]\\
&=\sum_{n=-\infty}^{\infty}{\left[\sum_{k=0}^{N-1}{Tc_k\left(e^{s_kT}\right)^nu\left(t\right)}\right]z^{-n}}=\sum_{k=0}^{N-1}{Tc_k\left[\sum_{n=0}^{\infty}\left(e^{s_kT}z^{-1}\right)^n\right]}\\
&=\sum_{k=0}^{N-1}{Tc_k\left[ \lim_{N\rightarrow \infty} \!\:\frac{1-\left( e^{s_kT}z^{-1} \right) ^N}{1-e^{s_kT}z^{-1}} \right]}\\
&\xlongequal{\left|z\right|>\left|e^{s_kT}\right|}\sum_{k=1}^{N-1}\frac{Tc_k}{1-e^{s_kT}z^{-1}}
\end{aligned}
\end{equation}$$
对比模拟滤波器的单位脉冲响应 $h_a\left(t\right)$,可得脉冲响应不变法的系统函数转换关系
$$\begin{equation}
H_a\left(s\right)=\sum_{k=0}^{N-1}\frac{c_k}{s-s_k}\Longleftrightarrow H\left(z\right)=\sum_{k=1}^{N-1}\frac{Tc_k}{1-e^{s_kT}z^{-1}}
\end{equation}$$
### 2.2.2. 变换后数字滤波器的稳定性
&emsp;&emsp;模拟 Butterworth 滤波器的所有极点均在 $s$ 平面的左半平面内,其实部 $\sigma_k<0$,则在极点变化的过程中 $s_k\Rightarrow e^{s_kT}<1$,即变换后得到的数字滤波器的极点位于 $z$ 平面的单位圆内,因而脉冲响应不变法所设计的数字滤波器也是稳定的。
### 2.2.3. 优缺点
1. (优点)脉冲响应变换法的频率坐标变换是线性的,即 $\omega=\Omega T$。因此如果模拟滤波器的频响是带限的且在折叠频率以内的话,变换后的得到的数字滤波器的频响可以不失真地反映原响应与频率的关系
$$\begin{equation}
H\left(e^{j\Omega T}\right)=H\left(j\Omega\right),\ \ \left|\Omega\right|<\frac{\pi}{T}
\end{equation}$$
2. (主要缺点)由于时域的取样,$h_a\left(t\right)$ 拉氏变换 $H_a\left(s\right)$ 在 $s$ 平面上沿虚轴周期延拓,然后再经过 $z=e^{sT}$ 的映射关系,将 $H_a\left(s\right)$ 映射到 $z$ 平面上,得到 $H\left(z\right)$。对于上述修正后的变换
$$\begin{equation}
H\left(e^{j\omega}\right)=\left.H\left(z\right)\right|_{z=e^{j\omega}}=\sum_{k=0}^{N-1}\frac{Tc_k}{1-s^{s_kTe^{-j\omega}}}=\sum_{m=-\infty}^{\infty}{H_a\left(j\frac{\omega-2\pi m}{T}\right)}\approx{\widetilde{H}}_a\left(j\frac{\omega}{T}\right)
\end{equation}$$
由于 $H_a\left(s\right)$ 的周期延拓,可能造成频谱混叠,导致滤波器的阻带性能降低。因此只能用于具有带限的频响特性的信号,**一般用于设计低通、带通滤波器,而不用于设计高通、带阻滤波器**。
### 2.2.4. 脉冲响应不变法的主要步骤
1. 确定滤波器的技术指标(通常在数字域给出)
1. 通带、阻带的波动;
2. 通带、过渡带、阻带的截止频率;
3. 频率选择特性(低通)。
2. 对数字域的频率指标进行如下变换
$$\begin{equation}
\Omega=\frac{\omega}{T}
\end{equation}$$
3. 选择模拟逼近方法(Butterworth),并确定其传递函数 $H_a\left(s\right)$。
4. 按照脉冲响应不变法的系统函数转换关系,将 $H_a\left(s\right)$ 转变为 $H\left(z\right)$,完成数字化。
$$\begin{equation}
H_a\left(s\right)=\sum_{k=0}^{N-1}\frac{c_k}{s-s_k}\Longleftrightarrow H\left(z\right)=\sum_{k=1}^{N-1}\frac{Tc_k}{1-e^{s_kT}z^{-1}}
\end{equation}$$
## 2.3. 模拟原型低通滤波器数字化的频域方法——双线性变换法(Bilinear Transform Method)
### 2.3.1. 变换原理
&emsp;&emsp;由 $s$ 平面与 $z$ 平面的双线性变换关系(变化式中 $s$ 与 $z$ 的关系无论分子还是分母部分都是线性的)
$$\begin{equation}
s=\frac{2}{T}\cdot\frac{1-z^{-1}}{1+z^{-1}},\ \ z=\frac{2/T+s}{2/T-s}
\end{equation}$$
将 $s=\sigma+j\omega$ 代入可得
$$\begin{equation}
z=\frac{2/T+\sigma+j\Omega}{2/T-\sigma-j\Omega}\Longrightarrow\left|z\right|=\sqrt{\frac{\left( 2/T+\sigma\right)^2+\Omega^2}{\left(2/T-\sigma\right)^2+\Omega^2}}
\end{equation}$$
由上式,当 $\sigma<0$ 时,$\left|z\right|<1$;当 $\sigma=0$ 时,$\left|z\right|=1$;当 $\sigma>0$ 时,$\left|z\right|>1$。也即把 $s$ 左半开平面映射在单位圆 $\left|z\right|=1$ 的内部;把 $s$ 平面的整个 $j\Omega$ 轴映射成单位圆 $\left|z\right|=1$,把 $s$ 右半开平面映射到单位圆 $\left|z\right|=1$ 的外部。
由 $s$ 平面与 $z$ 平面的双线性变换关系(变化式中 $s$ 与 $z$ 的关系无论分子还是分母部考虑映射到单位圆上的情况,则由 $s$ 平面与 $z$ 平面的双线性变换关系可得模拟滤波器和数字滤波器的频率关系
$$\begin{equation}
\begin{aligned}
&z=e^{j\omega}=\frac{2/T+j\Omega}{2/T-j\Omega}\\
\Longrightarrow&\Omega=j\frac{2}{T}\cdot\frac{1-e^{j\omega}}{1+e^{j\omega}}=j\frac{2}{T}\cdot\frac{e^{j\frac{\omega}{2}}\left(e^{-j\frac{\omega}{2}}-e^{j\frac{\omega}{2}}\right)}{e^{j\frac{\omega}{2}}\left(e^{-j\frac{\omega}{2}}+e^{j\frac{\omega}{2}}\right)}=j\frac{2}{T}\cdot\frac{-2j\sin{\dfrac{\omega}{2}}}{2\cos{\dfrac{\omega}{2}}}=\dfrac{2}{T}\tan{\frac{\omega}{2}}
\end{aligned}
\end{equation}$$
### 2.3.2. 优缺点
1. (优点)消除了混频误差。
2. (优点)在零频附近,模拟频率 $\Omega$ 与数字频率 $\omega$ 的关系接近与线性。
3. (缺点)模拟滤波器的全部频响特性被压缩在等效的数字频率 $0<\omega<\pi$ 之间,可见**双线性变换消除混叠的特性是依托严重的非线性得到的**。
### 2.3.3. 双线性变换法的主要步骤
1. 确定滤波器的技术指标(通常在数字域给出)
1. 通带、阻带的波动;
2. 通带、过渡带、阻带的截止频率;
3. 频率选择特性(低通)。
2. 对数字域的指标进行如下式的**预畸**处理
$$\begin{equation}
\Omega=\frac{2}{T}\tan{\frac{\omega}{2}}
\end{equation}$$
3. 选择模拟逼近方法(Butterworth),并确定其传递函数 $H_a\left(s\right)$。
4. 按照双线性变换关系将 $H_a\left(s\right)$ 转变为 $H\left(z\right)$,完成数字化。
$$\begin{equation}
s=\frac{2}{T}\cdot\frac{1-z^{-1}}{1+z^{-1}}
\end{equation}$$
5. 检查结果是否满足指标,如不满足,返回第 3 步,改变 $N$。
# 3. 线性相位 FIR 数字滤波器的特点
## 3.1. 线性相位条件
$$\begin{align}
&偶对称\qquad h\left(n\right)=h\left(N-1-n\right)\\
&奇对称\qquad h\left(n\right)=-h\left(N-1-n\right)
\end{align}$$
![线性相位条件](../images/post/2023-04-15-josh-dsp-part-7/2023-04-15-josh-dsp-part-7-030-LinearPhaseCondition.png){width=700px}
## 3.2. 线性相位 FIR 系统的频域特点($h\left(n\right)$ 中心偶对称,$N$ 为奇数时)
### 3.2.1. $h\left(n\right)$ 中心偶对称,$N$ 为奇数情况的推导<a name="3.2.1"></a>
$$\begin{equation}
\begin{aligned}
H\left(e^{j\omega}\right)&=\sum_{n=0}^{N-1}{h\left(n\right)e^{-j\omega n}}=\sum_{n=0}^{\frac{N-1}{2}-1}{h\left(n\right)e^{-j\omega n}}+h\left(\frac{N-1}{2}\right)e^{-j\omega\left(\frac{N-1}{2}\right)}+\sum_{n=\frac{N+1}{2}}^{N-1}{h\left(n\right)e^{-j\omega n}}\\
&=\sum_{n=0}^{\frac{N-1}{2}-1}{h\left(n\right)e^{-j\omega n}}+h\left(\frac{N-1}{2}\right)e^{-j\omega\left(\frac{N-1}{2}\right)}+\sum_{n=0}^{\frac{N-1}{2}-1}{h\left(N-1-n\right)e^{-j\omega\left(N-1-n\right)}}\\
&=\sum_{n=0}^{\frac{N-1}{2}-1}h\left(n\right)\left[e^{-j\omega n}+e^{-j\omega\left(N-1-n\right)}\right]+h\left(\frac{N-1}{2}\right)e^{-j\omega\left(\frac{N-1}{2}\right)}\\
&=e^{-j\omega\left(\frac{N-1}{2}\right)}\left\{h\left(\frac{N-1}{2}\right)+\sum_{n=0}^{\frac{N-1}{2}-1}h\left(n\right)\left[e^{j\omega\left(\frac{N-1}{2}-n\right)}+e^{-j\omega\left(\frac{N-1}{2}-n\right)}\right]\right\}\\
&=e^{-j\omega\left(\frac{N-1}{2}\right)}\left\{h\left(\frac{N-1}{2}\right)+\sum_{n=0}^{\frac{N-1}{2}-1}{2h\left(n\right)\cos{\left[\omega\left(\frac{N-1}{2}-n\right)\right]}}\right\}
\end{aligned}
\end{equation}$$
定义一个 $\dfrac{N+1}{2}$ 点序列 $a\left(n\right)$
$$\begin{equation}
\begin{cases}
a\left(0\right)=h\left(\dfrac{N-1}{2}\right)\\
a\left(n\right)=2h\left(\dfrac{N-1}{2}-n\right),\qquad n=1,2,\cdots,\dfrac{N-1}{2}
\end{cases}
\end{equation}$$
即**取序列 $h\left(n\right)$ 的后半部,中间值不变,其余翻倍**。则 $H\left(e^{j\omega}\right)$ 可以进一步化为
$$\begin{equation}
H\left(e^{j\omega}\right)=e^{-j\omega\left(\frac{N-1}{2}\right)}\sum_{n=0}^{\frac{N-1}{2}}{a\left(n\right)\cos{\left(\omega n\right)}}=A\left(\omega\right)e^{j\varphi\left(\omega\right)}
\end{equation}$$
其中 $A\left(\omega\right)=\displaystyle\sum_{n=0}^{\frac{N-1}{2}}{a\left(n\right)\cos{\left(\omega n\right)}}$ 称为符幅频率响应,其值可正可负,其与幅度频率响应的关系为 $\left|A\left(\omega\right)\right|=\left|H\left(e^{j\omega}\right)\right|$。
### 3.2.2. 四种线性相位FIR滤波器的特性
| | $h\left(n\right)$ | $N$ | 单位脉冲响应 |符幅频率响应 | 相位特性 | 特点 |
| :--: | :--: | :--: | :--: | :--: | :--: | :--: |
| 情况 1 | 中<br>心<br>偶<br>对<br>称 | 奇数 | ![情况1-h](../images/post/2023-04-15-josh-dsp-part-7/2023-04-15-josh-dsp-part-7-040-Case1h.png){width=150px} ![情况1-a](../images/post/2023-04-15-josh-dsp-part-7/2023-04-15-josh-dsp-part-7-050-Case1a.png){width=150px} | $\displaystyle A\left(\omega\right)=\sum_{n=0}^{\frac{N-1}{2}}{a\left(n\right)\cos{\left(\omega n\right)}}$ ![情况1-A](../images/post/2023-04-15-josh-dsp-part-7/2023-04-15-josh-dsp-part-7-060-Case1A.png){width=200px} | $\displaystyle\varphi\left(\omega\right)=-\frac{N-1}{2}\omega$ ![情况1-相位](../images/post/2023-04-15-josh-dsp-part-7/2023-04-15-josh-dsp-part-7-070-Case1phi.png){width=1200px} | 可实现<br>低通<br>高通<br>带通<br>带阻 |
| 情况 2 | 中<br>心<br>偶<br>对<br>称 | 偶数 | ![情况2-h](../images/post/2023-04-15-josh-dsp-part-7/2023-04-15-josh-dsp-part-7-080-Case2h.png){width=200px} ![情况2-b](../images/post/2023-04-15-josh-dsp-part-7/2023-04-15-josh-dsp-part-7-090-Case2b.png){width=150px} | $\displaystyle B\left(\omega\right)=\sum_{n=0}^{\frac{N}{2}}{b\left(n\right)\cos{\left[\omega\left(n-\frac{1}{2}\right)\right]}}$ ![情况2-B](../images/post/2023-04-15-josh-dsp-part-7/2023-04-15-josh-dsp-part-7-100-Case2B.png){width=200px} | 同上 | 可实现<br>低通<br>带通 |
| 情况 3 | 中心奇对称 | 奇数 | ![情况3-h](../images/post/2023-04-15-josh-dsp-part-7/2023-04-15-josh-dsp-part-7-110-Case3h.png){width=200px} ![情况3-c](../images/post/2023-04-15-josh-dsp-part-7/2023-04-15-josh-dsp-part-7-120-Case3c.png){width=150px} | $\displaystyle C\left(\omega\right)=\sum_{n=0}^{\frac{N-1}{2}}{c\left(n\right)\sin{\left(\omega n\right)}}$ ![情况3-C](../images/post/2023-04-15-josh-dsp-part-7/2023-04-15-josh-dsp-part-7-130-Case3C.png){width=200px} | $\displaystyle\varphi\left(\omega\right)=\frac{\pi}{2}-\frac{N-1}{2}\omega$ ![情况3-相位](../images/post/2023-04-15-josh-dsp-part-7/2023-04-15-josh-dsp-part-7-140-Case3phi.png){width=120px} | 可实现<br>带通 |
| 情况 4 | 中心奇对称 | 偶数 | ![情况4-h](../images/post/2023-04-15-josh-dsp-part-7/2023-04-15-josh-dsp-part-7-150-Case4h.png){width=200px} ![情况4-h](../images/post/2023-04-15-josh-dsp-part-7/2023-04-15-josh-dsp-part-7-160-Case4d.png){width=150px} | $\displaystyle D\left(\omega\right)=\sum_{n=0}^{\frac{N}{2}}{d\left(n\right)\sin{\left[\omega\left(n-\frac{1}{2}\right)\right]}}$ ![情况4-h](../images/post/2023-04-15-josh-dsp-part-7/2023-04-15-josh-dsp-part-7-170-Case4D.png){width=200px} | 同上 | 可实现<br>高通<br>带阻 |
## 3.3. 线性相位 FIR 滤波器的零点位置
&emsp;&emsp;由 $h\left(n\right)$ 的中心对称性,有
$$\begin{equation}
\begin{aligned}
H\left(z\right)&=\sum_{n=0}^{N-1}{h\left(n\right)z^{-n}}=\sum_{n=0}^{N-1}{\pm h\left(N-1-n\right)z^{-n}}=\sum_{m=0}^{N-1}{\pm h\left(m\right)z^{-\left(N-1-m\right)}}\\
&=\pm z^{-\left(N-1\right)}\sum_{m=0}^{N-1}{h\left(m\right)\left(z^{-1}\right)^{-m}}=\pm z^{-\left(N-1\right)}H\left(z^{-1}\right)
\end{aligned}
\end{equation}$$
由 $h\left(n\right)$ 的实值性,有
$$\begin{equation}
H^\ast\left(z\right)=\left[\sum_{n=0}^{N-1}{h\left(n\right)z^{-n}}\right]^\ast=\sum_{n=0}^{N-1}{h\left(n\right)\left(z^\ast\right)^{-n}}=H\left(z^\ast\right)
\end{equation}$$
由上两式可知,若 $z=z_i$ 是 $H\left(z\right)$ 的零点,则 $z_i$ 的倒数 $z=z_i^{-1}、z_i$ 的共轭 $z=z_i^\ast$、$z_i$ 共轭的倒数 $z=\left(z_i^\ast\right)^{-1}$ 也一定是 $H\left(z\right)$ 的零点。因此线性相位FIR滤波器的零点位置有四种可能,如下表。
| $z_i$ 的位置 | 对应所有零点的位置 | 在下图中的对应点 |
| :--: | :--: | :--: |
即不在实轴上又不在单位圆上 | 互为倒数的两组共轭对 |$z_1$
即在实轴上又在单位圆上 | $z=+1$ 或 $z=-1$ | $z_2,z_3$
不在实轴上但在单位圆上 | 一组共轭对 | $z_4$
在实轴上但不在单位圆上 | 一组互为倒数的实数对 | $z_5$
![线性相位 FIR 滤波器的零点位置](../images/post/2023-04-15-josh-dsp-part-7/2023-04-15-josh-dsp-part-7-180-ZeroPointOfLinearPhaseFIR.png){width=300px} | |
# 4. FIR 数字滤波器的设计
- 需要掌握低通、带通、带阻、高通四种选频特性 FIR 滤波器的设计。
- 若要求 FIR 数字滤波器具有线性相位响应,只考虑第一种情形,即 $h\left(n\right)$ 为奇点数中心偶对称。
- 需要掌握窗函数法和频率取样法。
## 4.1. FIR 数字滤波器设计的时域方法——窗函数法(Windowing Method)
### 4.1.1. 窗函数法设计 FIR 数字低通滤波器的步骤
&emsp;&emsp;窗函数设计法的基本思想为,首先选择一个适当的理想的滤波器 $H_d\left(e^{j\omega}\right)$,然后用窗函数截取它的单位脉冲响应 $h_d\left(n\right)$,平移后得到线性相位和因果的FIR滤波器。这种方法的重点是选择一个合适的窗函数和理想滤波器,使设计的滤波器的单位脉冲响应逼近理想滤波器的单位脉冲响应。
1. 根据给定指标确定理想低通数字滤波器的截止频率,以及相应的理想频率响应 $H_d\left(e^{j\omega}\right)$,其相位响应为零(或将相位响应设为 $-\dfrac{\left(N-1\right)\omega}{2}$,而非零相位响应,这样即无需步骤 3 中的平移操作,直接加窗即可)。
2. 利用 IDTFT 计算理想低通系统的单位脉冲响应序列 $h_d\left(n\right)$
$$\begin{equation}
h_d\left(n\right)=\frac{1}{2\pi}\int_{2\pi}{H_d\left(e^{j\omega}\right)e^{j\omega n}\mathrm{d}\omega}
\end{equation}$$
3. 确定滤波器阶数 $N$,将 $h_d\left(n\right)$ 向右平移 $\tau=\dfrac{\left(N-1\right)}{2}$,加窗得到 $h\left(n\right)$
$$\begin{equation}
h\left(n\right)=w\left(n\right)h_d\left[n-\tau\right]
\end{equation}$$
由此,实际频率响应为平移后的脉冲响应序列与窗函数频域卷积,即
$$\begin{equation}
H\left(e^{j\omega}\right)=H_d^\prime\left(e^{j\omega}\right)\ast W\left(e^{j\omega}\right)=\frac{1}{2\pi}\int_{2\pi}{H_d\left(e^{j\omega}\right)e^{-j\frac{\left(N-1\right)\theta}{2}}W\left[e^{j\left(\omega-\theta\right)}\right]\mathrm{d}\theta}
\end{equation}$$
4. 检验结果,如果不满足指标要求,则返回步骤 3,重新选择窗长或窗形进行设计,直到满足要求。
### 4.1.2. 窗函数法设计高通、带通、带阻滤波器
![窗函数法设计高通、带通、带阻滤波器](../images/post/2023-04-15-josh-dsp-part-7/2023-04-15-josh-dsp-part-7-190-WindowingMethod.png){width=900px}
| 滤波器类型 | 理想滤波器的<br>频率响应 | 理想滤波器的<br>单位抽样响应 |
| :--: | :--------: | :--------------: |
| 高通 | $H_d\left(e^{j\omega}\right)=\begin{aligned}\begin{cases}e^{-j\omega\tau},&\omega_c\leqslant\begin{vmatrix}\omega\end{vmatrix}\leqslant\pi\\0,&\text{otherwise}\end{cases}\end{aligned}$ | $\begin{aligned}h_d\left(n\right)&=\frac{1}{2\pi}\left[\int_{-\pi}^{-\omega_c}e^{j\omega\left(n-\tau\right)d\omega}+\int_{\omega_c}^{\pi}e^{j\omega\left(n-\tau\right)d\omega}\right]\\&=\begin{aligned}\begin{cases}\dfrac{1}{\pi\left(n-\tau\right)}\left\{\sin{\pi\left(n-\tau\right)}-\sin{\left[\omega_c\left(n-\tau\right)\right]}\right\},&n\neq\tau\\ \dfrac{\pi-\omega_c}{\pi},&n=\tau\end{cases}\end{aligned}\end{aligned}$ |
| 带通 | $H_d\left(e^{j\omega}\right)=\begin{aligned}\begin{cases}e^{-j\omega\tau},&0<\omega_1\leqslant\begin{vmatrix}\omega\end{vmatrix}\leqslant\omega_2<\pi\ \\ 0,&\text{otherwise} \end{cases}\end{aligned}$$ | $\begin{aligned}h_d\left(n\right)&=\frac{1}{2\pi}\left[\int_{-\omega_2}^{-\omega_1}e^{j\omega\left(n-\tau\right)d\omega}+\int_{\omega_1}^{\omega_2}e^{j\omega\left(n-\tau\right)d\omega}\right] \\ &=\begin{aligned}\begin{cases}\dfrac{1}{\pi\left(n-\tau\right)}\left\{\sin{\omega_2\left(n-\tau\right)}-\sin{\left[\omega_1\left(n-\tau\right)\right]}\right\},&n\neq\tau \\ \dfrac{\omega_2-\omega_1}{\pi},&n=\tau\end{cases}\end{aligned}\end{aligned}$ |
| 带阻 | $H_d\left(e^{j\omega}\right)=\begin{aligned}\begin{cases}e^{-j\omega\tau},&0\leqslant\begin{vmatrix}\omega\end{vmatrix}\leqslant\omega_1,\omega_2\leqslant\begin{vmatrix}\omega\end{vmatrix}\leqslant\pi\ \\ 0,&\text{otherwise}\end{cases}\end{aligned}$ | $\begin{aligned}h_d\left(n\right)&=\frac{1}{2\pi}\left[\int_{-\pi}^{-\omega_2}e^{j\omega\left(n-\tau\right)d\omega}+\int_{-\omega_1}^{\omega_1}e^{j\omega\left(n-\tau\right)d\omega}+\int_{\omega_2}^{\pi}e^{j\omega\left(n-\tau\right)d\omega}\right]\\ &= \begin{aligned}\begin{cases}\dfrac{1}{\pi\left(n-\tau\right)}\left\{\sin{\pi\left(n-\tau\right)}+\sin{\left[\omega_1\left(n-\tau\right)\right]}-\sin{\left[\omega_2\left(n-\tau\right)\right]}\right\},&n\neq\tau \\ \dfrac{\pi+\omega_1-\omega_2}{\pi},&n=\tau\end{cases}\end{aligned}\end{aligned}$ |
> 说明:
>
> 1. 表中理想频率 $H_d\left(e^{j\omega}\right)$ 具有线性相位,理想低通系统的单位抽样响应 $h_d\left(n\right)$ 无需平移即可加窗。
>
> 2. 数字滤波器的单位抽样响应 $h\left(n\right)=w\left(n\right)\cdot h_d\left(n\right)$。
>
> 3. $\tau=\dfrac{\left(N-1\right)}{2}$。
## 4.2. FIR 数字滤波器设计的频域方法——频率取样法(Frequency Sampling Method)
### 4.2.1. 取样原则
1. 预期频率特性的取样点数应等于滤波器阶数 $N$,并在单位圆上等间隔分布;
2. 为保证滤波器系数为实数,单位抽样序列应为实序列,取样频率特性应具有圆周共轭对称性;
3. 为使预期频率特性具有线性相位,其幅度特性和傅氏反变换得到的序列应为中心对称或中心反对称结构。
### 4.2.2. 取样值的确定($h\left(n\right)$ 为中心偶对称,阶数 $N$ 为奇数时)
&emsp;&emsp;由 [3.2.1](#3.2.1) $h\left(n\right)$ 中心偶对称,$N$ 为奇数情况的推导,有
$$\begin{equation}
H_d\left(e^{j\omega}\right)=e^{-j\omega\left(\frac{N-1}{2}\right)}H\left(\omega\right)
\end{equation}$$
其中符幅频率响应函数 $H\left(\omega\right)$ 是偶对称的,即
$$\begin{equation}
H\left(\omega\right)=H\left(2\pi-\omega\right)
\end{equation}$$
对 $H\left(e^{j\omega}\right)$ 在 $0\sim2\pi$ 之间等间隔取样 $N$ 点,得到 $H\left(k\right)$,即
$$\begin{equation}
H\left(k\right)=\left.H_d\left(e^{j\omega}\right)\right|_{\omega=\frac{2\pi}{N}k}=H_ke^{j\theta_k},\ \ k=0,1,\cdots,N-1
\end{equation}$$
其中频率采样符幅满足
$$\begin{equation}
H_k=H_{\frac{2\pi}{N}k}=H_{\frac{2\pi}{N}\left(N-k\right)}=H_{N-k};\left|H_k\right|=\left|H\left(k\right)\right|
\end{equation}$$
频率采样相位
$$\begin{equation}
\theta_k=-\frac{N-1}{2}\cdot\frac{2\pi}{N}k=-k\pi\left(1-\frac{1}{N}\right);e^{j\theta_{\left(N-k\right)}}=-e^{j\theta_k}
\end{equation}$$
### 4.2.3. 系统单位脉冲响应、传递函数和频率响应($h\left(n\right)$ 为中心偶对称,阶数 $N$ 为奇数时)<a name="4.2.3"></a>
&emsp;&emsp;由于 $H\left(k\right)$ 是 $h\left(n\right)$ 的 DFT
$$\begin{equation}
\begin{aligned}
h\left(n\right)&=\mathrm{IDFT}\left[H\left(k\right)\right]=\frac{1}{N}\sum_{k=0}^{N-1}{H\left(k\right)e^{j\frac{2\pi}{N}kn}}=\frac{1}{N}\sum_{k=0}^{N-1}{H_ke^{j\theta_k}e^{j\frac{2\pi}{N}nk}}\\
&=\frac{H_0e^{j\theta_0}}{N}+\frac{1}{N}\sum_{k=1}^{\frac{N-1}{2}}{H_k\left[e^{j\theta_k}e^{j\frac{2\pi}{N}nk}+e^{j\theta_{\left(N-k\right)}}e^{j\frac{2\pi}{N}n\left(N-k\right)}\right]}\\
&=\frac{H_0}{N}+\frac{1}{N}\sum_{k=1}^{\frac{N-1}{2}}{H_k\left[e^{j\theta_k}e^{j\frac{2\pi}{N}nk}+e^{-j\theta_k}e^{-j\frac{2\pi}{N}nk}\right]}\\
&=\frac{H_0}{N}+\frac{2}{N}\sum_{k=1}^{\frac{N-1}{2}}{H_k\cos{\left(\theta_k+\frac{2\pi}{N}nk\right)}}
\\
&=\frac{H_0}{N}+\frac{2}{N}\sum_{k=1}^{\frac{N-1}{2}}{H_k\cos{\left[-\left(1-\frac{1}{N}\right)k\pi+\frac{2\pi}{N}nk\right]}}
\end{aligned}
\end{equation}$$
&emsp;&emsp;由内插公式从 $H\left(k\right)$ 计算 $H\left(z\right)$
$$\begin{equation}
\begin{aligned}
H\left(z\right)&=\frac{1-z^{-N}}{N}\sum_{k=0}^{N-1}\frac{H\left(k\right)}{1-W_N^{-k}z^{-1}}\\
&=\frac{1-z^{-N}}{N}\left\{\frac{H_0}{1-z^{-1}}+\sum_{k=1}^{\frac{N-1}{2}}{H_k\left[\frac{e^{j\theta_k}}{1-W_N^{-k}z^{-1}}+\frac{e^{j\theta_{\left(N-k\right)}}}{1-W_N^{-\left(N-k\right)}z^{-1}}\right]}\right\}\\
&=\frac{1-z^{-N}}{N}\left[\frac{H_0}{1-z^{-1}}+\sum_{k=1}^{\frac{N-1}{2}}{H_k\left(\frac{e^{j\theta_k}}{1-W_N^{-k}z^{-1}}+\frac{e^{-j\theta_k}}{1-W_N^kz^{-1}}\right)}\right]\\
&=\frac{1-z^{-N}}{N}\left\{\frac{H_0}{1-z^{-1}}+\sum_{k=1}^{\frac{N-1}{2}}{H_k\frac{e^{j\theta_k}+\left(e^{j\theta_k}\right)^\ast-\left[e^{j\theta_k}W_N^k+\left(e^{j\theta_k}W_N^k\right)^\ast\right]z^{-1}}{1-z^{-1}\left(W_N^{-k}+W_N^k\right)+z^{-2}}}\right\}\\
&=\frac{1-z^{-N}}{N}\left[\frac{H_0}{1-z^{-1}}+\sum_{k=1}^{\frac{N-1}{2}}{H_k\frac{2\cos{\theta_k}-2z^{-1}\Re{\left[e^{j\theta_k}W_N^k\right]}}{1-z^{-1}\left(W_N^{-k}+W_N^k\right)+z^{-2}}}\right]\\
&\xlongequal{\theta_k=-k\pi\left(1-\frac{1}{N}\right)}\frac{1-z^{-N}}{N}\left[\frac{H_0}{1-z^{-1}}+\sum_{k=1}^{\frac{N-1}{2}}{H_k\frac{2\left(-1\right)^k\cos{\left(\dfrac{\pi}{N}k\right)}\left(1-z^{-1}\right)}{1-2\cos{\left(\dfrac{2\pi}{N}k\right)}z^{-1}+z^{-2}}}\right]
\end{aligned}
\end{equation}$$
由 $H\left(z\right)$ 和 $H\left(e^{j\omega}\right)$ 的关系
$$\begin{equation}
\begin{aligned}
H\left(e^{j\omega}\right)&=\left.H\left(z\right)\right|_{z=e^{j\omega}}=\frac{1-e^{-j\omega N}}{N}\sum_{k=0}^{N-1}\frac{H\left(k\right)}{1-W_N^{-k}e^{-j\omega}}=\frac{1-e^{-j\omega N}}{N}\sum_{k=0}^{N-1}\frac{H\left(k\right)}{1-e^{-j\left(\omega-\frac{2\pi}{N}k\right)}}\\
&=e^{-j\frac{\left(N-1\right)}{2}\omega}\frac{\left(e^{j\frac{N\omega}{2}}-e^{-j\frac{N\omega}{2}}\right)e^{-j\frac{\omega}{2}}}{N}\sum_{k=0}^{N-1}\frac{H\left(k\right)}{e^{-j\left(\frac{\omega}{2}-\frac{\pi}{N}k\right)}\left[e^{j\left(\frac{\omega}{2}-\frac{\pi}{N}k\right)}-e^{-j\left(\frac{\omega}{2}-\frac{\pi}{N}k\right)}\right]}\\
&=e^{-j\frac{\left(N-1\right)}{2}\omega}\frac{2j\sin{\left(\dfrac{N\omega}{2}\right)}e^{-j\frac{\omega}{2}}}{N}\sum_{k=0}^{N-1}\frac{H\left(k\right)}{e^{-j\left(\frac{\omega}{2}-\frac{\pi}{N}k\right)}2j\sin{\left(\frac{\omega}{2}-\frac{\pi}{N}k\right)}}\\
&\xlongequal{约分}e^{-j\frac{\left(N-1\right)}{2}\omega}\frac{\sin{\left(\dfrac{N\omega}{2}\right)}}{N}\sum_{k=0}^{N-1}\frac{H\left(k\right)e^{-j\frac{\pi}{N}k}}{\sin{\left(\dfrac{\omega}{2}-\dfrac{\pi}{N}k\right)}}\\
&\xlongequal[将第1项分开]{H\left(k\right)=H_ke^{j\theta_k}}e^{-j\frac{\left(N-1\right)}{2}\omega}\left\{\frac{H_0}{N}\cdot\frac{\sin{\left(\dfrac{N\omega}{2}\right)}}{\sin{\left(\dfrac{\omega}{2}\right)}}+\sum_{k=1}^{N-1}{\frac{H_ke^{j\theta_k}}{N}\cdot\frac{e^{-j\frac{\pi}{N}k}\sin{\left(\dfrac{N\omega}{2}\right)}}{\sin{\left(\dfrac{\omega}{2}-\dfrac{\pi}{N}k\right)}}}\right\}\\
&\xlongequal{合并}e^{-j\frac{\left(N-1\right)}{2}\omega}\left\{\frac{H_0}{N}\cdot\frac{\sin{\left(\dfrac{N\omega}{2}\right)}}{\sin{\left(\dfrac{\omega}{2}\right)}}+\sum_{k=1}^{\frac{N-1}{2}}{\frac{H_k}{N}\cdot\left[\frac{e^{j\theta_k}e^{-j\frac{\pi}{N}k}\sin{\left(\dfrac{N\omega}{2}\right)}}{\sin{\left(\dfrac{\omega}{2}-\dfrac{\pi}{N}k\right)}}+\frac{e^{j\theta_{\left(N-k\right)}}e^{-j\frac{\pi}{N}\left(N-k\right)}\sin{\left(\dfrac{N\omega}{2}\right)}}{\sin{\left[\dfrac{\omega}{2}-\dfrac{\pi}{N}\left(N-k\right)\right]}}\right]}\right\}\\
&\xlongequal{\theta_k=-k\pi\left(1-\frac{1}{N}\right)}e^{-j\frac{\left(N-1\right)}{2}\omega}\left\{\frac{H_0}{N}\cdot\frac{\sin{\left(\dfrac{N\omega}{2}\right)}}{\sin{\left(\dfrac{\omega}{2}\right)}}+\sum_{k=1}^{\frac{N-1}{2}}{\frac{H_k}{N}\cdot\left[\frac{e^{-jk\pi}\sin{\left(\dfrac{N\omega}{2}\right)}}{\sin{\left(\dfrac{\omega}{2}-\dfrac{\pi}{N}k\right)}}+\frac{e^{jk\pi}\sin{\left(\dfrac{N\omega}{2}\right)}}{\sin{\left(\dfrac{\omega}{2}+\dfrac{\pi}{N}k\right)}}\right]}\right\}\\
&=e^{-j\frac{\left(N-1\right)}{2}\omega}\left\{\frac{H_0}{N}\cdot\frac{\sin{\left(\dfrac{N\omega}{2}\right)}}{\sin{\left(\dfrac{\omega}{2}\right)}}+\sum_{k=1}^{\frac{N-1}{2}}{\frac{H_k}{N}\cdot\left[\frac{\sin{\left[N\left(\dfrac{\omega}{2}-\dfrac{\pi}{N}k\right)\right]}}{\sin{\left(\dfrac{\omega}{2}-\dfrac{\pi}{N}k\right)}}+\frac{\left[\sin{N\left(\dfrac{\omega}{2}+\dfrac{\pi}{N}k\right)}\right]}{\sin{\left(\dfrac{\omega}{2}+\dfrac{\pi}{N}k\right)}}\right]}\right\}
\end{aligned}
\end{equation}$$
其中最后一步化简
$$\begin{equation}
\begin{aligned}
\sin{\left[N\left(\frac{\omega}{2}+\frac{\pi}{N}k\right)\right]}&=\frac{1}{2j}\left[e^{jN\left(\frac{\omega}{2}+\frac{\pi}{N}k\right)}-e^{-jN\left(\frac{\omega}{2}+\frac{\pi}{N}k\right)}\right]=\frac{e^{-jk\pi}}{2j}\left[e^{j\left(N\frac{\omega}{2}+2\pi k\right)}-e^{-j\left(\frac{N\omega}{2}+\pi k\right)}\right]\\
&\xlongequal{e^{j2\pi k}=1}\frac{e^{-jk\pi}}{2j}\left[e^{j\left(N\frac{\omega}{2}\right)}-e^{-j\left(\frac{N\omega}{2}\right)}\right]=e^{-jk\pi}\sin{\left(\frac{N\omega}{2}\right)}
\end{aligned}
\end{equation}$$
### 4.2.4. 频率取样法设计滤波器的步骤
1. 确定滤波器的技术指标,及预期频率响应(简单起见,可从理想选频特性开始)。
2. 选择频率采样类型(Ⅰ型),确定采样频点
$$\begin{equation}
\omega_k=k\frac{f_s}{N}
\end{equation}$$
3. 计算所需频率采样点数 $N$ 及对应的频域采样值 $H\left(k\right)$,确定过渡带中频率采样点数 $M$ 以及对应的幅度。
4. 利用 [4.2.3](#4.2.3) 中推导的公式计算滤波器的参数
$$\begin{equation}
h\left(n\right)=\frac{H_0}{N}+\frac{2}{N}\sum_{k=1}^{\frac{N-1}{2}}{H_k\cos{\left[-\left(1-\frac{1}{N}\right)k\pi+\frac{2\pi}{N}nk\right]}}
\end{equation}$$
$$\begin{equation}
H\left(z\right)=\frac{1-z^{-N}}{N}\left[\frac{H_0}{1-z^{-1}}+\sum_{k=1}^{\frac{N-1}{2}}{H_k\frac{2\left(-1\right)^k\cos{\left(\frac{\pi}{N}k\right)}\left(1-z^{-1}\right)}{1-2\cos{\left(\frac{2\pi}{N}k\right)}z^{-1}+z^{-2}}}\right]
\end{equation}$$
$$\begin{equation}
H\left(e^{j\omega}\right)=e^{-j\frac{\left(N-1\right)}{2}\omega}\left\{\frac{H_0}{N}\cdot\frac{\sin{\left(\dfrac{N\omega}{2}\right)}}{\sin{\left(\dfrac{\omega}{2}\right)}}+\sum_{k=1}^{\frac{N-1}{2}}{\frac{H_k}{N}\cdot\left[\frac{\sin{\left[N\left(\dfrac{\omega}{2}-\dfrac{\pi}{N}k\right)\right]}}{\sin{\left(\dfrac{\omega}{2}-\dfrac{\pi}{N}k\right)}}+\frac{\left[\sin{N\left(\dfrac{\omega}{2}+\dfrac{\pi}{N}k\right)}\right]}{\sin{\left(\dfrac{\omega}{2}+\dfrac{\pi}{N}k\right)}}\right]}\right\}
\end{equation}$$
5. 检验结果,如果不满足指标要求,则返回步骤 3 重新设计。
# 参考文献
王世一. *数字信号处理, 修订版.* 北京理工大学出版社, 1997.
@@ -0,0 +1,824 @@
---
title: "Josh's Note — Verilog<br>Part 6 如何写好状态机"
mathjax: false
comments: true
copyright: true
toc:
enable: true
number: false
wrap: true
expand_all: false
max_depth: 4
abbrlink: d860a67e
date: 2023-04-16 11:36:44
tags:
- Verilog
- HDL
- RTL
- 状态机
- 摩尔型
- 米里型
- 两段式
- 三段式
categories:
- [Josh 的学习笔记, Verilog]
description: 状态机是逻辑设计的重要内容,其设计水平直接反映工程师的逻辑功底,所以许多公司的硬件和逻辑工程师面试中,状态机设计几乎是必选题目。本文在引入状态机设计思想的基础上,重点讨论如何写好状态机。
---
# 1. 状态机的基本概念
本节的重点在于理解状态机的基本概念和应用场合。
## 1.1. 状态机是一种思想方法<a id="toc.1.1"></a>
大多数工科生在学习数字电路时都学习过状态机的基本概念,了解一些使用状态机描述时序电路的基本方法。但是**状态机不仅仅是一种时序电路设计工具,它更是一种思想方法**。
<!-- more -->
先看一个简单的例子。在大学生活中,某同学的在校生活可以简单地概括为宿舍、教室、食堂之间的周而复始,可以用[图 6-1](#fig.6-1) 形象地表现出来。这张图并不是要讨论这个学生是否是一个“乖乖”类型学生。
{% note info %}
请注意,如果将图中的“地点”认为是“状态”,将“功能“认为是状态的“输出”,这张图就是一张标准的状态转移图,也就是说,用状态机的方式清晰地描述了这个学生的在校生活方式。
{% endnote %}
<a id="fig.6-1"></a>
![图 6-1 某学生在校生活状态转移图](../images/post/2023-04-16-josh-verilog-part-6/2023-04-16-josh-verilog-part-6-010-SchoolLifeStateTransitionDiagramOfStudentA.png){width=600}
如果你认为这张图描述的学生生活过于单调而怀疑状态机描述方法的能力,就再看另一位生活丰富多彩的同学的在校生活,他/她的在校生活方式可以用[图 6-2](#fig.6-2) 表示。
<a id="fig.6-2"></a>
![图 6-2 另一位学生在校生活状态转移图](../images/post/2023-04-16-josh-verilog-part-6/2023-04-16-josh-verilog-part-6-020-SchoolLifeStateTransitionDiagramOfStudentB.png){width=600}
{% note info %}
同样如果将图中的“地点”认为是“状态”,将“功能”认为是状态的“输出”,将“条件”认为是状态转移的“输入条件”,[图 6-2](#fig.6-2) 也是一张标准的状态转移图,通过状态机的方式再次清晰地描述了另一个学生的在校生活方式。
{% endnote %}
事实上使用状态机可以细致入微地描述任何一位同学的在校生活方式。通过前面两个简单举例可以发现,**状态机特别适合描述有发生有先后顺序,或者有逻辑规律的事情**——这就是状态机的本质——对具有逻辑顺序或时序规律事件的一种描述方法。这个论断最重要的两个词就是“**逻辑顺序**”和“**时序规律**”,这两点就是状态机所要描述的核心和强项,换言之,**所有具有逻辑顺序和时序规律的事情都适合用状态机描述**。
很多初学者不知道何时应用状态机。这里介绍两种应用思路:第一种思路,**从状态变量入手**。如果一个电路具有时序规律或者逻辑顺序,就可以自然而然地规划出状态,从这些状态入手,分析每个状态的输入,状态转移和输出,从而完成电路功能。第二种思路,首先明确电路的输出关系,这些输出相当于状态的输出,**回溯规划**每个状态和状态转移条件与状态输入。无论哪种思路,使用状态机的目的都是要控制某部分电路,完成某种具有逻辑顺序或时序规律的电路设计。
其实对于逻辑电路而言,小到一个简单的时序逻辑,大到复杂的微处理器,都适合用状态机方法进行描述。请打开思路,不要仅仅局限于时序逻辑,发现电路的内在规律,确认电路的“状态变量”,大胆使用状态机描述电路模型。由于**状态机不仅是一种电路描述工具,它更是一种思想方法**,而且状态机的 HDL 语言表达方式比较规范,有章可循,所以很多有经验的设计者习惯用状态机思想进行逻辑设计,对各种复杂设计都套用状态机的设计理念,从而提高设计的效率和稳定性。
## 1.2. 状态机的基本要素与分类
状态机的基本要素有 3 个,其实在[第一小节](#toc.1.1)的举例中都有涉及,只是没有点明,它们是:**状态**、**输出**和**输入**。
- **状态**:也叫状态变量。在逻辑设计中,使用状态划分逻辑顺序和时序规律。比如,设计伪随机码发生器时,可以用移位寄存器序列作为状态;在设计电机控制电路时,可以以电机的不同转速作为状态;在设计通信系统时,可以用信号的状态作为状态变量等。
- **输出**:输出指**在某一个状态时特定发生的事件**。如设计电机控制电路中,如果电机转速过高,则输出为转速过高报警,也可以伴随减速指令或降温措施等。
- **输入**:指状态机中**进入每个状态的条件**,有的状态机没有输入条件,其中的状态转移较为简单,有的状态机有输入条件,当某个输入条件存在时才能转移到相应的状态。
根据状态机的输出是否与输入条件相关,可将状态机分为两大类:摩尔(Moore)型状态机和米里 (Mealy) 型状态机。
- **摩尔型状态机**:摩尔型状态机的**输出仅仅依赖于当前状态,而与输入条件无关**。例如[图 6-1](#fig.6-1) 所示的例子,将图中的“地点”认为是“状态”,将“功能”认为是状态的“输出”,则每个输出仅仅与状态相关,所以它是一个摩尔型状态机。
- **米里型状态机**:米里型状态机的**输出不仅依赖于当前状态,而且取决于该状态的输入条件**。例如[图 6-2](#fig.6-2) 所示的例子,将图中的“地点”认为是“状态”,将“功能”认为是状态的“输出”,将“条件”认为是状态转移的“输入条件”,可以发现,该学生到达什么地方,做什么事情都是由当前状态和输入条件共同决定,所以它是一个米里型状态机。
根据状态机的数掀是否为有限个,可将状态机分为有限状态机 (Finite State Machine, FSM) 和无限状态机 (Infinite State Machine, ISM)。**逻辑设计中一般所涉及的状态都是有限的,所以以后所说的状态机都指有限状态机**,用 FSM 表示。
## 1.3. 状态机的基本描述方式
逻辑设计中,状态机的基本描述方式有 3 种,分别是状态转移图、状态转移列表及 HDL 语言描述。
### 1.3.1. 状态转移图
状态转移图是状态机描述的最自然的方式。如[图 6-1](#fig.6-1)、[图 6-2](#fig.6-2) 都使用了状态转移图这一描述方式。状态转移图经常在设计规划阶段定义逻辑功能时使用,也可以在分析代码中状态机时使用,通过图形化的方式非常有助于理解设计意图。
另外值得一提的是目前有一些 EDA 工具支持状态转移图作为逻辑设计的输入,如 StateCAD。在该工具中设计者只要画出状态转移图就可以了, StateCAD 能自动将状态转移图翻译成 HDL 语言代码,而且翻译出来的代码规范、可读性较好、可综合、易维护。 StateCAD 还能自动检测状态机的完备性和正确性,对状态转移图中的冗余状态、自锁状态、歧义转移条件和不完备状态机等隐含错误都会报警,并协助设计者更正错误。最后 StateCAD 会自动生成设计的测试激励,并调用仿真程序,验证状态机的正确性,这个测试激励甚至可在后仿真中使用。总之, StateCAD 提供了状态机的输入、翻译、检测、优化和测试等一条龙的服务,使状态机的设计变得安全、可靠、快速、便捷。这类自动转换状态转移图为 HDL 源代码的工具对设计、分析一些规模较小的状态机非常有效,但是由于自动反应的代码过于程式化,效率不是很高,所以对于较大规模的逻辑设计,一般还是推荐使用 HDL 语言描述。
{% note info %}
使用 Synplify Pro 的 RTL 视图配合 FSM Viewer 可以将源代码中描述的 FSM 用状态转移图显示出来,使用图形化的界面帮助用户分析、理解状态机。
{% endnote %}
### 1.3.2. 状态转移列表
状态转移列表是用列表的方式描述状态机,是数字逻辑电路常用的设计方法之一,经常被用于对状态化简,对可编程逻辑设计,由于可用逻辑资源比较丰富,而且状态编码要考虑设计的稳定性、安全性等因素,所以并不经常使用状态转移列表优化状态。
### 1.3.3. HDL 语言描述状态机
使用 HDL 语言描述状态机是本文讨论的重点,使用 HDL 语言描述状态机有一定的灵活性,但不是天马行空,而是有章可循的。通过一些规范的描述方法,可以使 HDL 语言描述的状态机更安全、稳定、高效、易于维护。
# 2. 如伺写好状态机
本节重点讨论可综合的状态机描述的一些基本规范,即如何在 RTL 级描述安全、高效的 FSM。
## 2.1. 什么是好的 RTL 级 FSM 描述
首先介绍好的 RTL 级 FSM 的评判标准。其实评判 FSM 的标准很多,这里挑选最重要的几个方面讨论一 下。好的 RTL 级 FSM 的评判标准如下:
1. **FSM 要安全,稳定性高**
FSM 安全是指 FSM **不会进入死循环,特别是不会进入非预知的状态,而且由于某些扰动进入非设计状态,也能很快地恢复到正常的状态循环中来**。这里面有两层含义,第一 ,要求该 FSM 的综合实现结果**无毛刺**等异常扰动;第二,要求状态机要**完备**,即使收到异常扰动进入非设计状态,也能很快恢复到正常状态。
2. FSM 速度快,满足设计的频率要求
任何 RTL 设计都应该满足设计的频率要求。
3. FSM 面积小,满足设计的面积要求
同理任何 RTL 设计都应该满足设计的面积要求。
4. FSM 设计要清晰易懂、易维护
不规范的 FSM 写法很难让其他人解读,甚至过一段时间后设计者也发现很难维护。
需要说明的是以上所列的各项标准,特别是前 3 项标准绝不是割裂的,它们直接有紧密的内在联系。前面花了相当长的篇幅论述 FPGA/CPLD 设计评判的两个基本标准:面积和速度。这里“面积”是指一个设计所消耗 FPGA/CPLD 的逻辑资源数量;“速度”指设计在芯片上稳定运行所能够达到的最高频率。两者是对立统一的矛盾体,要求一个设计同时具备设计面积最小,运行频率最高,这是不现实的。科学的设计目标应该是:**在满足设计时序要求(包含对设计最高频率的要求)的前提下,占用最小的芯片面积,或者在所规定的面积下,使设计的时序余量更大,频率更高**。
另外,如果要求 FSM 安全,则很多时候需要使用“full case”的编码方式,即将状态转移变量的所有向量组合情况都在 FSM 中有相应的处理,这势必意味若要多花更多的设计资源,有时也会影响 FSM 的频率。
所以,各条标准要综合考虑,根据设计的要求进行权衡。但是如果各条评判标准发生冲突时,请按照标准的罗列顺序考虑,前文标准的罗列顺序是根据这些标准在设计中的重要性排列的,也就是说第 1 条“FSM 要安全,稳定性高”的优先级最高,最重要;第 4 条“FSM 设计要清晰易懂易维护”的优先级最低,是相对次要的标准。
## 2.2. RTL 级状态机描述常用语法<a id=2.2></a>
在 [Part 2——Verilog 语言基础][]和 [Part 3——描述方式和设计层次][]中论述了 Verilog 的基本语法和常用关键字,其中 RTL 级设计可综合的FSM 相关的常用关键字如下:
1. `wire`、`reg` 等
对 `wire`、`reg` 等变量、向量定义不加累述,需要补充的是**状态编码时(也就是用某种编码描述各个状态)一般都要使用 `reg` 寄存器型向量**。
2. `parameter`
用于描述状态名称,增强源代码可读性,简化描述。
例:某状态机使用初始值为 `0` 的**独热码**(one-hot)编码方式定义的 4 bit 宽度的状态变量 `NS`(代表 Next State,下一状态)和 `CS`(代表 Current State,当前状态),且状态机包含 5 个具体状态 `IDLE`(空闲状态)、`S1`(工作状态 1)、 `S2`(工作状态 2)、 `S3`(工作状态 3)、`ERROR`(告警状态),则代码如下:
``` verilog
reg [3:0] NS,CS;
parameter [3:0] // one hot with zero initial
IDLE = 4'b0000,
S1 = 4'b0001,
S2 = 4'b0010,
S3 = 4'b0100,
ERROR = 4'b1000;
```
3. `always`
在 FSM 设计中有 3 种 `always` 的使用方法,第 1 种用法是根据**主时钟沿**,完成同步时序的状态迁移。
例:某状态机从当前状态 `CS` 迁移到下一个状态 `NS` 可以如下表述:
``` verilog
// sequential state transition
always @(posedge elk or negedge nrst)
if (!nrst)
CS <= IDLE;
else
CS <= NS;
```
`always` 的第 2 种用法是根据**信号敏感表**,完成组合逻辑的输出。
`always` 的第 3 种用法是根据**时钟沿**,完成同步时序逻辑的输出。
4. `case/endcase`
`case/endcase` 是 FSM 描述中最重要的语法关键字 ,要详细讨论一下。 `case/endcase` 的基本语法结构如下:
``` verilog
case (case_expression)
case_item1 : case_item_statement1;
case_item2 : case_item_statement2;
case_item3 : case_item_statement3;
case_item4 : case_item_statement4;
default : case_item_statement5;
endcase
```
其中:
- `case_expression` 就是 `case` 的判断条件表达式,在 FSM 描述中,它一般为当前状态寄存器;每个 `case_item` 是 `case` 语句的分支列表,在 FSM 描述中,它一般为 FSM 中的所有状态的罗列,从中还可以分析出状态的编码方式;
- `case_item_statement` 为进入每个 `case_item` 的对应操作,在 FSM 中,即为每个状态对应的状态转移或者输出,如果 `case_item_statement` 包含的操作不只一条,可以用 `begin/end` 嵌套多条操作;
- `default` 是可选的关键字,用以指明当所列的所有 `case_item` 与 `case_ex­pression` 都不匹配时的操作,在 FSM 设计中,为了提高设计的安全性,排除所设计的FSM 进入死循环,一般要求加上 `default` 关键字来描述 FSM 所需状态的补集状态下的操作。
另外 Verilog 还支持 `casex` 和 `casez` 等不同关键字,但是由于综合器对这两个关键字的支持情况略有差异,所以建议初学者使用完整的 `case` 结构而不使用 `casex` 或 `casez`。
例:某 FSM 的状态转移用 `case/endcase` 结构描述如下:
``` verilog
case (CS)
IDLE: begin
IDLE_out;
if (~i1) NS = IDLE;
if (i1 && i2) NS = S1;
if (i1 && (~i2)) NS = ERROR;
end
S1: begin
S1_out;
if (~i2) NS = S1;
if (i2 && i1) NS = S2;
if (i2 && (~i)) NS = ERROR;
end
S2: begin
S2_out;
if (i2) NS = S2;
if ((~i2) && i1) NS = IDLE;
if ((~i2) && (~i1)) NS = ERROR;
end
ERROR: begin
ERROR_out;
if (i1) NS = ERROR;
if (~i1) NS = IDLE;
end
default: begin
Default_out;
NS = ERROE;
end
endcase
```
{% note warning %}
Verilog 的 `case` 结构虽然与 C 等高级语言的 `case` 结构形式相似,但是本质不同。Verilog 的 `case` 结构对应并行判断的硬件结构,而且当 `case_expression` 与任意一个 `case_item` 匹配后,将忽略对其他 `case_item` 的判断,执行完匹配的 `case_item_statement` 后直接跳出 `case` 结构。
{% endnote %}
5. `task/endtask`
`task/endtask` 在描述状态机时主要用途是将不同状态对应的输出用 `task/endtask` 封装,增强了代码的可维护性和可读性。
例:某状态机 IDLE 状态的输出可以用 `task/endtask` 封装为 `IDLE_out` 任务:
``` verilog
task IDLE_out;
begin
{w_ol, w_o2, w_err} = 3'b000;
end
endtask
```
`endtask` 描述状态机时也会使用到其他一些常用的 RTL 级语法,如 `if/else`、`as­sign` 等,它们的功能和一般 RTL 描述方法一致,这里不在叙述。
## 2.3. 推荐的状态机描述方法<a id=2.3></a>
状态机描述时关键是要描述清楚前面提到的几个状态机的要素,即如何进行状态转移;每个状态的输出是什么;状态转移是否和输入条件相关等。具体描述时方法各不相同。
- 有的设计者习惯将整个状态机写到 1 个 always 模块里面,在该模块中既描述状态转移,又描述状态的输入和输出,这种写法一般被称为**一段式 FSM 描述方法**;
- 还有一种写法是将 2 个 `always` 模块中的一个 `always` 模块采用同步时序描述状态转移,另一个模块采用组合逻辑判断状态转移条件,描述状态转移规律,这种写法被称为**两段式 FSM 描述方法**;
- 还有一种写法是在两段式描述方法基础上发展出来的,这种写法使用 3 个 `always` 模块,第 1 个 `always` 模块采用同步时序描述状态转移;第 2 个采用组合逻辑判断状态转移条件,描述状态转移规律;第 3 个 `always` 模块使用同步时序电路描述每个状态的输出,这种写法在这里称为**三段式写法**。
一般而言,推荐的 FSM 描述方法是后两种,即两段式和三段式 FSM 描述方法。其原因为:FSM 和其他设计一样,最好使用同步时序方式设计,以提高设计的稳定性,消除毛刺。状态机实现后,一般来说,**状态转移部分是同步时序电路**,而**状态的转移条件的判断是组合逻辑**。两段式之所以比一段式编码合理,就在于**两段式编码将同步时序和组合逻辑分别放到不同的 `always` 程序块中实现**。这样做的好处不仅是便于阅读、理解、维护,更重要的是利于综合器优化代码、利于用户添加合适的时序约束条件、利于布局布线器实现设计。而一段式 FSM 描述不利于时序约束、功能更改、调试等,而且不能很好的表示米里 FSM 的输出,容易写出 Latches,导致逻辑功能错误。
在一般两段式描述中,为了便于描述当前状态的输出,很多设计者习惯将当前状态的输出用组合逻辑实现。但是这种组合逻辑**仍然有产生毛刺的可能性**,而且不利于约束、不利于综合器和布局布线器实现高性能的设计。因此如果设计运行额外的一个时钟节拍的插入(latency),则要求尽量对状态机的输出用寄存器寄存一拍。但是很多**实际情况不允许插入一个寄存节拍,此时则可以通过三段式描述方法进行解决**。三段式与两段式相比,关键在于根据状态转移规律,在上一状态根据输入条件判断出当前状态的输出,从而在不插入额外时钟节拍的前提下,实现了寄存器输出。
为了便于理解,将通过一个使用不同的 FSM 描述风格描述状态机的实例讨论这 3 种不同的写法。
在这个范例中将用一段式、两段式、三段式分别描述例子的状态转移,如[图 6-3](#fig.6-3) 所示。这里选用了一个非常典型的米里型状态机,共有 4 个状态: `IDEL`、`S1`、`S2`、`ERROR`;输入信号为时钟 `clk`,低电平异步复位信号 `nrst`, 输入信号 `i1`、`i2`,输出信号为 `o1`、`o2` 和 `err`,状态关系如[图 6-3](#fig.6-3) 所示。状态的输出如下:
``` verilog
IDLE 状态的输出为: {o1, o2, err} = 3'b000;
S1 状态的输出为: {o1, o2, err} = 3'b100;
S2 状态的输出为: {o1, o2, err} = 3'b010;
ERROR 状态的输出为: {o1, o2, err} = 3'b111。
```
<a id="fig.6-3"></a>
![图 6-3 例子的状态转移图](../images/post/2023-04-16-josh-verilog-part-6/2023-04-16-josh-verilog-part-6-030-StateTransitionDiagramOfExample.png){width=600}
### 2.3.1. 一段式状态机描述方法(应该避免的写法)
该例的一段式描述代码如下:
``` verilog state1.v
// state1.v
// 1-paragraph method to describe FSM
// Describe state transition, state output, state input condition in only 1
// always block
// Westor, Dec. 2006
// Verilog Usage Book
module state1 (
nrst,clk,
i1,i2,
o1,o2,
err
);
input nrst,clk;
input i1,i2;
output o1,o2,err;
reg o1,o2,err;
reg [2:0] NS; // NextState
parameter [2:0] // one hot with zero idle
IDLE = 3'b000,
S1 = 3'b001,
S2 = 3'b010,
ERROR = 3'b100;
// 1 always block to describe state transition, state output, state input
// condition
always @(posedge clk or negedge nrst)
if (!nrst) begin
NS <= IDLE;
{o1,o2,err} <= 3'b000;
end
else begin
NS <= 3'bx;
{o1,o2,err} <= 3'b000;
case (NS)
IDLE: begin
if (~i1) begin{o1,o2,err}<=3'b000;NS <= IDLE; end
if (i1 && i2) begin{o1,o2,err}<=3'b100;NS <= S1; end
if (i1 && ~i2) begin{o1,o2,err}<=3'b111;NS <= ERROR;end
end
S1: begin
if (~i2) begin{o1,o2,err}<=3'b100;NS <= S1; end
if (i2 && i1) begin{o1,o2,err}<=3'b010;NS <= S2; end
if (i2 && (~i1)) begin{o1,o2,err}<=3'b111;NS <= ERROR;end
end
S2: begin
if (i2) begin{o1,o2,err}<=3'b010;NS <= S2; end
if (~i2 && i1) begin{o1,o2,err}<=3'b000;NS <= IDLE; end
if (~i2 && (~i1))begin{o1,o2,err}<=3'b111;NS <= ERROR;end
end
ERROR: begin
if (i1) begin{o1,o2,err}<=3'b111;NS <= ERROR;end
if (~i1) begin{o1,o2,err}<=3'b000;NS <= IDLE; end
end
endcase
end
endmodule
```
如前面介绍,一段式写法就是将状态的同步转移、状态输出和状态的输入条件都写在一个 `always` 模块中,一段式写法可以概括为[图 6-4](#fig.6-4) 描述的结构。
<a id="fig.6-4"></a>
![图 6-4 一段式 FSM 描述结构](../images/post/2023-04-16-josh-verilog-part-6/2023-04-16-josh-verilog-part-6-040-OneStageFSM.png){width=900}
一段式描述方法将状态转移判断的组合逻辑和状态寄存器转移的时序逻辑混写在同一个 always 模块中,**不符合将时序和组合逻辑分开描述的 Coding Style(代码风格)**,而且在描述当前状态时要考虑下个状态的输出,整个代码不清晰,不利于维护修改,并且不利于附加约束,不利于综合器和布局布线器对设计的优化。
另外,这种描述相对于两段式描述比较**冗长**。本例为了便于初学者掌握,选择了一个非常简单的米里型状态机,不能很好的反应一段式比较冗长的缺点,但是如果状态机相对复杂些,一般来说,一段式代码长度会比两段式冗长大约 80%~150%。
所以一段式 FSM 描述是不推荐的 FSM 描述方式,请一定要避免。
### 2.3.2. 两段式状态机描述方法(推荐写法)
为了使 FSM 描述清晰简洁,易于维护,易于附加时序约束,使综合器和布局布线器更好的优化设计,推荐使用两段式 FSM 描述方法。
本例的两段式描述代码如下:
``` verilog state2.v
// state2.v
// 2-paragraph method to describe FSM
// Describe sequential state transition in 1 sequential always block
// State transition conditions in the other combinational always block
// Package state output by task. Then register the output
// Westor, Dec. 2006
// Verilog Usage Book
module state2 (
nrst,clk,
i1,i2,
o1,o2,
err
);
input nrst,clk;
input i1,i2;
output o1,o2,err;
reg o1,o2,err;
reg [2:0] NS,CS;
parameter [2:0] // one hot with zero idle
IDLE = 3'b000,
S1 = 3'b001,
S2 = 3'b010,
ERROR = 3'b100;
// sequential state transition
always @(posedge clk or negedge nrst)
if (!nrst)
CS <= IDLE;
else
CS <= NS;
// combinational condition judgment
always @(nrst or CS or i1 or i2) begin
NS = 3'bx;
ERROR_out;
case (CS)
IDLE: begin
IDLE_out;
if (~i1) NS = IDLE;
if (i1 && i2) NS = S1;
if (i1 && ~i2) NS = ERROR;
end
S1: begin
S1_out;
if (~i2) NS = S1;
if (i2 && i1) NS = S2;
if (i2 && (~i1)) NS = ERROR;
end
S2: begin
S2_out;
if (i2) NS = S2;
if (~i2 && i1) NS = IDLE;
if (~i2 && (~i1)) NS = ERROR;
end
ERROR: begin
ERROR_out;
if (i1) NS = ERROR;
if (~i1) NS = IDLE;
end
endcase
end
// output task
task IDLE_out;
{o1,o2,err} = 3'b000;
endtask
task S1_out;
{o1,o2,err} = 3'b100;
endtask
task S2_out;
{o1,o2,err} = 3'b010;
endtask
task ERROR_out;
{o1,o2,err} = 3'b111;
endtask
endmodule
```
两段式写法是推荐的 FSM 描述方法之一,在此仔细讨论一下代码结构。两段式 FSM 的核心就是:**一个 always 模块采用同步时序描述状态转移;另一个模块采用组合逻辑判断状态转移条件,描述状态转移规律**。两段式写法可以概括为[图 6-5](图6-5) 所示的结构。
<a id="fig.6-5"></a>
![图 6-5 两段式FSM描述结构图](../images/post/2023-04-16-josh-verilog-part-6/2023-04-16-josh-verilog-part-6-050-TwoStageFSM.png){width=900px}
本例中,同步时序描述状态转移的 `always` 模块代码如下:
``` verilog state2.v
always @(posedge clk or negedge nrst)
if (!nrst)
CS <= IDLE;
else
CS <= NS;
```
其实这是一种**程式化的描述结构**,无论具体到何种 FSM 设计,都可以定义两个状态寄存器 `CS` 和 `NS`, 分别代表当前状态和下一状态 , 然后根据所需的复位方式(同步复位或异步复位),在时钟沿到达时将 `NS` 赋给 `CS` 。需要注意的是这个同步时序模块的赋值要**采用非阻塞赋值** `<=`。
本例中,另一个采用组合逻辑判断状态转移条件的 `always` 模块代码如下:
``` verilog state2.v
// combinational condition judgment
always @(nrst or CS or i1 or i2) begin
NS = 3'bx;
ERROR_out;
case (CS)
IDLE: begin
IDLE_out;
if (~i1) NS = IDLE;
if (i1 && i2) NS = S1;
if (i1 && ~i2) NS = ERROR;
end
S1: begin
S1_out;
if (~i2) NS = S1;
if (i2 && i1) NS = S2;
if (i2 && (~i1)) NS = ERROR;
end
S2: begin
S2_out;
if (i2) NS = S2;
if (~i2 && i1) NS = IDLE;
if (~i2 && (~i1)) NS = ERROR;
end
ERROR: begin
ERROR_out;
if (i1) NS = ERROR;
if (~i1) NS = IDLE;
end
endcase
end
```
这个使用组合逻辑判断状态转移条件的 `always` 模块也**可以看成格式化的书写结构**。其中 `always` 的敏感列表为当前状态 `CS`, 复位信号和输入条件(**如果是米里状态机,则必须有输入条件;如果是摩尔状态机,一般敏感表和后续逻辑判定没有输入**),请大家注意**电平敏感表必须列完整**。本例中这段电平敏感列表为:
``` verilog state2.v
always @(nrst or CS or i1 or i2)
```
一般来说,在这个组合 `always` 敏感表下先写一个默认的下一状态 `NS` 的描述,然后根据实际的状态转移条件由内部的 `case` 或者 `if ... else` 条件判断确定正确的转移。如本例中下面这段代码,
``` verilog state2.v
// ...
begin
NS = 3'bx;
ERROR_out;
case (CS)
// ...
```
推荐**在敏感表下的默认状态为不定状态 `X`**, 这样描述的好处有两个:第一在仿真时可以很好地考察所设计的 FSM 的完备性,如果所设计的 FSM 不完备,则会进入任意状态,仿真很容易发现;第二个好处是综合器对不定态 `X` 的处理是 “Don't Care”,即**任何没有定义的状态寄存器向最都会被忽略**。这里赋值不定态的效果和使用 `casez` 或 `casex` 替代 case 的效果非常相似。
在每个 `case` 模块内部的结构也非常相似,都是先描述当前状态的组合逻辑输出,然后根据输入条件(米里 FSM) 判定下一个状态。
该组合逻辑模块中所有的赋值推荐采用阻塞赋值 `=`。
{% note warning %}
请注意,虽然下一状态寄存器 `NS` 为寄存器类型,但是在两段式 FSM 的判断状态转移条件的 `always` 模块中,**实际上对应的真实硬件电路是纯组合逻辑电路**。
{% endnote %}
对于每个输出,一般用组合逻辑描述,比较简便的方法是用 `task/endtask` 将输出封装起来,这样不仅是写法简单,而且利于复用共同的输出。如本例中 `S1` 状态的输出被封装为 `S1_out`,在组合逻辑 `always` 模块中直接调用即可。
``` verilog
task IDLE_out;
{o1,o2,err} = 3'b000;
endtask
```
组合逻辑容易产生毛刺,因此如果时序允许,请尽量**对组合逻辑的输出插入一个寄存器节拍**,这样可以很好地保证输出信号的稳定性。
### 2.3.3. 三段式状态机描述方法(推荐写法)
两段式 FSM 描述方法虽然有很多好处,但是它有一个明显的弱点就是其输出一般使用组合逻辑描述,而组合逻辑易产生毛刺等不稳定因素,并且在 FPGA/CPLD 等逻辑器件中过多的组合逻辑会影响实现的速率(这点与 ASIC 设计不同)。所以在上节特别提到了在两段式 FSM 描述方法中,如果时序允许插入一个额外的时钟节拍,则尽量在后级电路对 FSM 的组合逻辑输出用寄存器寄存一个节拍,则可以有效地消除毛刺。但是很多情况下,设计并不允许额外的节拍插入(Latency),此时,解决之道就是采用三段式 FSM 描述方法。三段式描述方法与两段式描述方法相比,关键在于使用同步时序逻辑寄存 FSM 的输出。
本例的三段式描述代码如下:
``` verilog state3.v
// state3.v
// 3-paragraph method to describe FSM
// Describe sequential state transition in the 1st sequential always block
// State transition conditions in the 2nd combinational always block
// Describe the FSM out in the 3rd sequential always block
// Westor, Dec. 2006
// Verilog Usage Book
module state3 (
nrst,clk,
i1,i2,
o1,o2,
err
);
input nrst,clk;
input i1,i2;
output o1,o2,err;
reg o1,o2,err;
reg [2:0] NS,CS;
parameter [2:0] // one hot with zero idle
IDLE = 3'b000,
S1 = 3'b001,
S2 = 3'b010,
ERROR = 3'b100;
// 1st always block, sequential state transition
always @(posedge clk or negedge nrst)
if (!nrst)
CS <= IDLE;
else
CS <= NS;
// 2nd always block, combinational condition judgment
always @ (nrst or CS or i1 or i2) begin
NS = 3'bx;
case (CS)
IDLE: begin
if (~i1) NS = IDLE;
if (i1 && i2) NS = S1;
if (i1 && ~i2) NS = ERROR;
end
S1: begin
if (~i2) NS = S1;
if (i2 && i1) NS = S2;
if (i2 && (~i1)) NS = ERROR;
end
S2: begin
if (i2) NS = S2;
if (~i2 && i1) NS = IDLE;
if (~i2 && (~i1)) NS = ERROR;
end
ERROR: begin
if (i1) NS = ERROR;
if (~i1) NS = IDLE;
end
endcase
end
// 3rd always block, the sequential FSM output
always @(posedge clk or negedge nrst)
if (!nrst)
{o1,o2,err} <= 3'b000;
else begin
{o1,o2,err} <= 3'b000;
case (NS)
IDLE: {o1,o2,err} <= 3'b000;
S1: {o1,o2,err} <= 3'b100;
S2: {o1,o2,err} <= 3'b010;
ERROR: {o1,o2,err} <= 3'b111;
endcase
end
endmodule
```
三段式写法可以概括为[图 6-6](#fig.6-6) 描述的结构。
<a id="fig.6-6"></a>
![图 6-6 三段式FSM描述结构图](../images/post/2023-04-16-josh-verilog-part-6/2023-04-16-josh-verilog-part-6-060-ThreeStageFSM.png){width=1000px}
对比上节两段式 FSM 的描述,可以清晰发现三段式与两段式 FSM 描述的最大区别在于**两段式采用了组合逻辑输出**,而**三段式巧妙地根据下一状态的判断,用同步时序逻辑寄存 FSM 的输出**。本例中就是下面一段代码,
``` verilog
always @(posedge clk or negedge nrst)
if (!nrst)
{o1,o2,err} <= 3'b000;
else begin
{o1,o2,err} <= 3'b000;
case (NS)
IDLE: {o1,o2,err} <= 3'b000;
S1: {o1,o2,err} <= 3'b100;
S2: {o1,o2,err} <= 3'b010;
ERROR: {o1,o2,err} <= 3'b111;
endcase
end
```
大家可能会问,一段式写法也是用寄存器同步了 FSM 的输出,为什么前面介绍一段式的输出代码容易混淆,不利于维护呢?请大家对比一下这段一段式输出的代码,
``` verilog
case(NS)
IDLE: begin
if (~i1) begin{o1,o2,err}<=3'b000;NS <= IDLE; end
if (i1 && i2) begin{o1,o2,err}<=3'b100;NS <= S1; end
if (i1 && ~i2) begin{o1,o2,err}<=3'b111;NS <= ERROR;end
end
```
通过对比,可以清晰地看到:使用一段式建模 FSM 的寄存器输出的时候,**必须要综合考虑现态在何种状态转移条件下会进入哪些次态**,然后在每个现态的 `case` 分支下分别描述每个次态的输出,这显然不符合思维习惯;而三段式建模描述 FSM 的状态机输出时,**只需指定 `case` 敏感表为次态寄存器,然后直接在每个次态的 `case` 分支中描述该状态的输出即可**,根本不用考虑状态转移条件。本例的 FSM 很简单,如果设计的 FSM 相对复杂,三段式的描述优势就会凸显出来。
另一方面,三段式描述方法与两段式描述相比,虽然代码结构复杂了一些,但是换来的优势是使 FSM 做到了同步寄存器输出,消除了组合逻辑输出的不稳定与毛刺的隐患,而且更利于时序路径分组,一般来说在 FPGA/CPLD 等可编程逻辑器件上的综合与布局布线效果更佳。
{% note warning %}
请注意,在三段式 FSM 描述方法中,**判断状态转移的 `always` 模块的 `case` 语句判断的条件是当前状态 `CS`**,而**在同步时序 FSM 输出的 `always` 模块的 `case` 语句判断的条件是下一状态 `NS`**。
{% endnote %}
### 2.3.4. 3 种描述方法与状态机建模问题的引申
可以说合理的状态机描述与状态机的建模技巧是本章的重中之重。这里需要引申讨论几个问题。
#### 2.3.4.1. n 段式描述方法和 `always` 语法块的个数
通过学习,大家知道标准的一段式、两段式、三段式 FSM 描述方法分别使用了 1、2、3 个 `always` 语法块。但是请注意,这个命题的反命题不成立,不能说一段 FSM 的描述中使用了 n 个 `always` 语法块,就是 n 段式描述方法。这是因为**特指的一段式、两段式、三段式 FSM 描述方法中每个 `always` 语法块都有固定的描述内容和格式化的结构**,其实也就是通过这些特定的描述内容和格式化的结构,确立了 3 种 FSM 建模方式。
例如两段式写法中,第一个 `always` 模块格式化地使用同步时序电路描述次态寄存器到现态寄存器的转移;而第二个 `always` 模块格式化地使用纯组合逻辑描述状态转移条件。 也就是说两段式描述对应的建模方式的硬件电路就是[图 6-5](#fig.6-5) 所示的电路结构。其实从语法角度说,可以将一个 `always` 模块拆分成多个 `always` 模块,或者反之将多个 `always` 模块合并为一个 `always` 模块。所以请注意,**n 段式 FSM 描述方法强调的是一种建模思路,绝不是简单的 `always` 语法块个数**。
#### 2.3.4.2. FSM 的建模方式
反复强调的 n 段式描述方法其实是 FSM 的 3 种建模方式。大家回顾一下状态[转移图 6-3](#fig.6-3) 描述的 FSM,在学习本节之前,大家可能会产生各种不同的描述思路,通过本节的学习,希望大家能够自然而然地想到用[图 6-5](#fig.6-5)(对应两段式思路)和[图 6-6](#fig.6-6)(对应三段式思路)的结构建模。其实对于绝大多数 FSM,都可以采用[图 6-4](#fig.6-4)、[图 6-5](#fig.6-5) 或[图 6-6](#fig.6-6) 的结构建模。一般来说,推**荐使用后两种结构建模**。这是因为:两段式思路建模结构清晰,描述简洁,便于约束,而且如果允许输出逻辑、允许插入一个节拍,就可以通过插入输出寄存器改善输出逻辑的时序并避免组合逻辑的毛刺;三段式思路建模结构清晰,结构格式化,解决了不改变时序要求的前提下用寄存器做状态输出的问题。请大家仔细研究[图 6-4](#fig.6-4)、[图 6-5](#fig.6-5) 和[图 6-6](#fig.6-6) 体会 3 种建模方式。
#### 2.3.4.3. 一段式建模和三段式建模的关系
引申比较一下 3 种 FSM 建模的关系。请比较[图 6-4](#fig.6-4) 与[图 6-6](#fig.6-6),如果将[图 6-4](#fig.6-4) 的两部分组合逻辑合并起来,则三段式建模电路与一段式建模电路的结构完全一致了,如[图 6-7](#fig.6-7) 所示。反过来,可以看到三段式与一段式的最大区别在于:**使用一段式建模 FSM 的寄存器输出的时候,必须要综合考虑现态在何种状态转移条件下会进入哪些次态,然后在每个现态的 `case` 分支下分别描述每个次态的输出**,这显然不符合思维习惯;而**三段式建模校描述 FSM 的状态机输出时,只需指定 `case` 敏感表为次态寄存器,然后直接在每个次态的 `case` 分支中描述该状态的输出即可,根本不用考虑状态转移条件**。对于简单的 FSM,三段式建模的寄存器输出的优势还不是十分明显,但是对于复杂一些的 FSM,三段式建模的优势就会十分显著。
<a id="fig.6-7"></a>
![图 6-7 三段式建模结构与一段式建模结构的关系图](../images/post/2023-04-16-josh-verilog-part-6/2023-04-16-josh-verilog-part-6-070-ComparisonOfOneAndThreeStageFSM.png){width=1000px}
#### 2.3.4.4. 两段式建模和三段式建模的关系
从代码上看,三段式建模的前两段与两段式建模完全相同,仅仅多了一段寄存器 FSM 输出。一般来说,使用寄存器输出可以改善输出的时序条件,还能避免组合电路的毛刺,所以是更为推荐的描述方式。但是电路设计不是一成不变的,存某些情况下,两段式结构比三段式结构更有优势。请大家再分析一下[图 6-5](#fig.6-5) 和[图 6-6](#fig.6-6) 的结构,细心的读者会发现,**两段式用状态寄存器分割了两部分组合逻辑(状态转移条件组合逻辑和输出组合逻辑)**;而**三段式结构中,从输入到寄存器状态输出的路径上,要经过两部分组合逻辑(状态转移条件组合逻辑和输出组合逻辑)**,从时序上,这两部分组合逻辑完全可以看为一体。这样**这条路径的组合逻辑就比较繁杂,该路径的时序相对紧张**。也就是说,两段式建模中用状态寄存器分割了组合逻辑,而三段式将寄存器移到组合逻辑的最后端。**如果寄存器前的组合逻辑过于复杂,势必会成为整个设计的关键路径,此时就不宜再使用三段式建模,而要使用两段式建模**。解决两段式建模组合逻辑输出产生毛刺的方法是,额外的在 FSM 后级电路插入寄存器,调整时序,完成功能。
#### 2.3.4.5. 3 种描述 FSM 方法的比较
一般来说,3 种 FSM 描述方法可以用下表进行比较。但是请注意,任何一种描述的优劣只是一般规律,而不是绝对性规律。例如,一般来说不推荐一段式描述,但是如果 FSM 的结构十分简单,状态很少,状态转移条件和状态输出都十分简化,则使用一段式建模的效率很高。这些经验需要逐步积累,但是在这里推荐的是一般性规律,请结合电路,体会这几种 FSM 建模方法。
| <center>比较项目</center> | <center>一段式描述方法</center> | <center>两段式描述方法</center> | <center>三段式描述方法</center> |
| :---- | :-- | :-- | :-- |
| 推荐等级 | 不推荐 | 推荐 | 推荐 |
| 代码简洁程度<br>(对于相对复杂的 FSM 而言) | 冗长 | 最简洁 | 简洁 |
| `always` 模块个数 | 1 | 2 | 3 |
| 是否利于时序约束 | 不利于 | 利于 | 利于 |
| 是否有组合逻辑输出 | 可以无组合逻辑输出 | 多数情况有组合逻辑输出 | 无组合逻辑输出 |
| 是否利于综合与布局布线 | 不利于 | 利于 | 利于 |
| 代码的可靠性与可维护度 | 低 | 高 | 最好 |
| 代码风格的规范性 | 低,任意度大 | 格式化,规范 | 格式化,规范
## 2.4. 状态机设计的其他技巧
本小节讨论 FSM 设计的其他技巧。
### 2.4.1. FSM 的编码
Binary(二进制编码)、gray-code(格雷码)编码使用最少的触发器,较多的组合逻辑,而 one-hot(独热码)编码反之。one-hot 编码的最大优势在于状态比较时仅仅需要比较一个位,一定程度上简化了比较逻辑,减少了毛刺产生的概率。由于 CPLD 更多地提供组合逻辑资源,而 FPGA 更多地提供触发器资源,所以 **CPLD 多使用 gray-code**,而 **FPGA 多使用 one-hot 编码**。另一方面,**对于小型设计使用 gray-code 和 binary 编码更有效**,而**大型状态机使用 one-hot 更高效**。
在代码中添加综合器的综合约束属性或者在图形界面下设置综合约束属性可以比较方便地改变状态的编码。需要注意的是: Synplicity、Synopsys、Exemplar 等综合工具关于 FSM 的综合约束属性的语法格式各不相同。
### 2.4.2. FSM 初始化状态
一个完备的状态机(健壮性强)应该具备初始化状态和默认状态。当芯片加电或者复位后,状态机应该能够自动将所有判断条件复位,并进入初始化状态。需要注明的一点是,大多数 FPGA 有 GSR(Global Set/Reset)信号,当 FPGA 加电后, GSR 信号拉高,对所有的寄存器、RAM 等单元复位/置位,这时配置于 FPGA 的逻辑并未生效,所以不能保证正确地进入初始化状态。所以使用 GSR 企图进入 FPGA 的初始化状态,常常会产生种种不必要的麻烦。**一般的方法是采用异步复位信号**,当然也可以使用同步复位,但是要注意同步复位逻辑的设计。解决这个问题的**另一种方法是将默认的初始状态的编码设为全零**,这样 GSR 复位后,状态机自动进入初始状态。如 [2.3 小节](#2.3)所示的编码方法就是初始状态全零的 one-hot 编码方式。
### 2.4.3. FSM 状态编码定义
**状态机的定义可以用 `parameter` 定义,但是不推荐使用 `` `define`` 宏定义的方式**,因为 `` `define`` 宏定义在编译时自动替换整个设计中所定义的宏,而 `parameter` 仅定义模 块内部的参数,定义的参数不会与模块外的其他状态机混淆。例如,一个工程里面有两个 `module`,各包含一个 FSM,如果设计时都有 `IDLE` 这一名称的状态,使用 `` `define`` 宏定义就会混淆起来,而使用 `parameter` 则不会造成任何不良影响。
### 2.4.4. FSM 输出
如果使用二段式 FSM 描述 Mealy 状态机,输出逻辑可以用 `?` 语句描述,或者使用 `case` 语句判断转移条件与输入信号即可。如果输出条件比较复杂,而且多个状态共用某些输出,则建议使用 `task/endtask` 将输出封装起来,达到**模块复用**的目的。
### 2.4.5. 阻塞和非阻塞赋值
为了避免不必要的竞争冒险,不论是做两段式还是三段式 FSM 描述时,必须遵**循时序逻辑 `always` 模块使用非阻塞赋值 `<=`**,即当前状态向下一状态时序转移, 和寄存 FSM 输出等时序 `always` 模块中都要使用非阻塞赋值;而**组合逻辑 `always` 模块使用阻塞赋值 `=`**,即状态转移条件判断,组合逻辑输出等 `always` 模块中都要使用阻塞赋值。
### 2.4.6. FSM 的默认状态
**完整的状态机应该包含一个默认(default)状态**,当转移条件不满足,或者状态发生了突变时,要能保证逻辑不会陷入“死循环”。这是对状态机**健壮性**的一个重要要求,也就是常说的要具备“自恢复”功能。对编码 `case` 和 `if ... else` 语句要特别注意, **尽量使用完备的条件判断语句**。 Verilog 中,使用 `case` 语句的时候要用 `default` 建立默认状态。
大家可能注意到,在上节举例的 `case` 语句中,没有写 `default` 默认状态, 其实**可以将其中一个状态不编码,指定其为 `default` 默认状态**,则任何与所列状态机不匹配的状态都会转到 `default` 状态,从而增强了 FSM 的健壮性,另外**也可以添加一个额外的 `default` 状态**,一旦进入这个状态就会自动转到 `IDLE` 状态,从新启动状态机,这样做也增强了状态机的健壮性。
``` verilog
case (CS)
IDLE: begin
IDLE_out;
if (~i1) NS = IDLE;
if (i1 && i2) NS = S1;
if (i1 && ~i2) NS = ERROR;
end
S1: begin
S1_out;
if (~i2) NS = S1;
if (i2 && i1) NS = S2;
if (i2 && (~i1)) NS = ERROR;
end
S2: begin
S2_out;
if (i2) NS = S2;
if (~i2 && i1) NS = IDLE;
if (~i2 && (~i1)) NS = ERROR;
end
ERROR: begin
ERROR_out;
if (i1) NS = ERROR;
if (~i1) NS = IDLE;
end
default:begin
IDLE_out;
NS = IDLE;
end
endcase
```
{% note info %}
在 `case` 语句结构中增加 `default` 默认状态是推荐的代码风格。
{% endnote %}
### 2.4.7. Full Case 与 Parallel Case 综合属性
所谓 Full Case 是指:FSM 的所有编码向量都可以与 `case` 结构的某个分支或 `default` 默认情况匹配起来。如果一个 FSM 的状态编码是 8 bit,则对应的 256 个状态编码(全状态编码是 2^n^ 个)都可以与 `case` 的某个分支或者 `default` 映射起来。
所谓 Parallel Case 是指:在 `case` 结构中,每个 `case` 的判断条件表达式(即 [2.2 小节](#2.2) 描述的 `case_ expression`),有且仅有唯一的 `case` 语句的分支(即 [2.2 小节](#2.2) 描述的每个 `case_item`)与之对应,即两者关系是一一对应关系。
目前知名综合器如 Synplify Pro、 Precision RTL 和 Synopys 综合工具等都支持 “synthesis full_case”和“synthesis parallel_case”这些综合约束属性,**合理使用 Full Case 约束属性,可以增强设计的安全性**;**合理使用 Parallel Case 约束属性,可以改善状态机译码逻辑**。但是设计者必须具体情况具体分析,对于有的设计,这两条语句使用不当,会占用大量逻辑资源,并恶化 FSM 的时序表现。
# 3. 小结
状态机不仅是一种时序电路设计工具,它更是一种思想方法。状态机的本质就是对具有逻辑顺序或时序规律事件的一种描述方法。这个论断最重要的两个词就是“逻辑顺序”和“时序规律”,这两点就是状态机所要描述的核心和强项,换言之,所有具有逻辑顺序和时序规律的事情都适合用状态机描述。
根据 FSM 描述使用的 `always` 模块数和功能可以将 FSM 的描述分为 3 种写法:
- 不推荐使用一段式描述方法。因为一段式描述方法将状态转移判断的组合逻辑和状态寄存器转移的时序逻辑混写在同一个 `always` 模块中,不符合将时序和组合逻辑分开描述的 Coding Style(代码风格),而且在描述当前状态时要考虑下个状态的输出,整个代码不清晰,不利于维护、修改,不利于附加约束,并且不利于综合器和布局布线器对设计的优化。
- 推荐使用两段式状态机描述方法。两段式描述方法用 2 个 `always` 模块,其中一个 `always` 模块采用同步时序描述状态转移;另一个 `always` 模块采用组合逻辑判断状态转移条件,描述状态转移规律。这种方法使 FSM 描述清晰、简洁,易于维护,易于附加时序约束,使综合器和布局布线器更好的优化设计。
- 强烈推荐使用三段式描述方法。与一段式描述方法相比较,三段式 FSM 描述方法对 FSM 寄存器输出的描述只需判断下一状态,然后直接将下一状态的输出用寄存器输出即可,根本不用考虑状态转移条件(米里状态机)。与两段式描述相比,三段式虽然代码结构复杂了一些,但是换来的优势是使 FSM 做到了同步寄存器输出,消除了组合逻辑输出的不稳定与毛刺的隐患,而且更利于时序路径分组,一般来说在 FPGA/CPLD 等可编程逻辑器件上的综合与布局布线效果更佳。
# 参考文献
EDA 先锋工作室. *轻松成为设计高手——Verilog HDL 实用精解.* 北京航空航天大学出版社, 2012.
[Part 2——Verilog 语言基础]: https://josh-gao.top/posts/fd2ca242.html
[Part 3——描述方式和设计层次]: https://josh-gao.top/posts/fd117896.html
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,427 @@
---
title: "Josh's Note — 最优阵列处理<br>Part 1.1 频率-波数响应和波束方向图"
mathjax: true
comments: true
copyright: true
toc:
enable: true
number: true
wrap: true
expand_all: true
max_depth: 4
categories:
- - Josh 的学习笔记
- 最优阵列处理
- 阵列和空域滤波器
abbrlink: 8b61f5a7
date: 2023-04-18 23:57:47
tags:
- 阵列信号处理
- 频率-波数响应
- 波束方向图
---
&emsp;&emsp;假设空时场(space-time field)同时存在信号(signal)、噪声(noise)和/或干扰(interference),这些信号/干扰空时场中可能是重叠的。阵列(Array)可以利用信号的空域特征,对空时场域内的信号进行滤波,过滤的过程可以用角度或波数的函数来表示(in terms of a dependence upon angle or wavenumber)。从频域看,这种滤波通过使用复增益(complex gain)对阵列输出进行加权,可以根据信号的空域相关性对信号进行增强或抑制。对空时场进行空域滤波的目的是:使从一个或一组特定角度到来的信号通过有效的组合得到增强,抑制从其他角度到来的噪声或干扰。
<a id="fig.1-1-1"></a>
![图 1-1-1 球坐标系](../images/post/2023-04-18-josh-oap-part-1-1/2023-04-18-josh-oap-part-1-1-010-SphericalCoordinareSystem.png){width=600px}
&emsp;&emsp;在分析之前首先需要明确采用的坐标系,如[图 1-1-1](#fig.1-1-1) 所示,直角坐标系和球坐标系的关系也在其中标明:
$$\begin{equation}
\begin{aligned}
x &= r \sin\theta\cos\varphi \\
y &= r \sin\theta\sin\varphi \\
z &= r \cos\theta
\end{aligned}
\end{equation}$$
<!-- more -->
# 阵列的基本模型
<a id="fig.1-1-2"></a>
![图 1-1-2 $N$ 阵元阵列](../images/post/2023-04-18-josh-oap-part-1-1/2023-04-18-josh-oap-part-1-1-020-NElementArray.png){width=600px}
&emsp;&emsp;下面分析一个阵列对外部信号场的响应。阵列由一组全向阵元组成,阵元的位置为 $\left\{ \boldsymbol{p}_n \right\}_{n=0}^{N-1}$,如[图 1-1-2](#fig.1-1-2) 所示。阵列在各阵元处对信号场进行采样,产生一组信号,记为矢量 $\boldsymbol{f}\left(t, \boldsymbol{p}\right)$
$$\begin{equation}
\boldsymbol{f}(t, \boldsymbol{p}) = \left[
\begin{array}{c}
f\left(t, \boldsymbol{p}_0\right) \\
f\left(t, \boldsymbol{p}_1\right) \\
\vdots \\
f\left(t, \boldsymbol{p}_{N-1}\right) \\
\end{array}
\right]
\end{equation}$$
{% note warning %}
注意,这里并没有规定阵列的几何排布,因此下面的分析适用于所有阵列结构。
{% endnote %}
<a id="fig.1-1-3"></a>
![图 1-1-3 线性处理阵列](../images/post/2023-04-18-josh-oap-part-1-1/2023-04-18-josh-oap-part-1-1-030-ArrayWithLinearProcessing.png){width=600px}
&emsp;&emsp;将每个阵元的输出(即采样结果)通过冲激响应为 $h_n(t)$ 的线性时不变滤波器,求和可得阵列的输出 $y(t)$,如[图 1-1-3](#fig.1-1-3) 所示。假设观察间隔足够长(可以考虑为无限长),则阵列输出 $y(t)$ 可以写成卷积积分的形式:
$$\begin{equation}
y(t) = \sum_{n=0}^{N-1} \int_{-\infty}^{\infty} h_n (t-\tau)f\left(\tau,\boldsymbol{p}_n\right) \mathrm{d} \tau
\end{equation}$$
用矢量符号表示为(即将标量结果向矢量模型进行直接扩展,a straightforward extension of scalar results to the vector model)
<a id="VectorFormOfLinearArrayOutputInTimeDomain"></a>
$$\begin{equation} \label{VectorFormOfLinearArrayOutputInTimeDomain}
y(t) = \int_{-\infty}^{\infty} \boldsymbol{h}^\mathrm{T} (t-\tau) \boldsymbol{f}\left(\tau,\boldsymbol{p}\right) \mathrm{d} \tau
\end{equation}$$
其中
$$\begin{equation} \label{ImpulseResponse}
\boldsymbol{h}(t) = \left[ \begin{array}{c}
h_0(t) \\
h_1(t) \\
\vdots \\
h_{N-1}(t)
\end{array}
\right]
\end{equation}$$
也可以把式 $\eqref{VectorFormOfLinearArrayOutputInTimeDomain}$ 给出的阵列输出在变换域表示为
$$\begin{equation}
Y(\omega) = \boldsymbol{H}^\mathrm{T}(\omega) \boldsymbol{F}(\omega)
\end{equation}$$
其中
$$\begin{equation}
\boldsymbol{H} (\omega) = \int_{-\infty}^{\infty} \boldsymbol{h}(t) e^{-j\omega t} \mathrm{d} t
\end{equation}$$
$$\begin{equation} \label{SampleVectorInFreqDomain}
\boldsymbol{F} \left(\omega,\boldsymbol{p}\right) = \int_{-\infty}^{\infty} \boldsymbol{f}\left(t,\boldsymbol{p}\right) e^{-j\omega t} \mathrm{d} t
\end{equation}$$
在大多数情况下,可以去掉式 $\eqref{SampleVectorInFreqDomain}$ 中左边的 $\boldsymbol{p}$,直接使用 $\boldsymbol{F}(\omega)$ 。
# 信号到达不同阵元的时延
&emsp;&emsp;下面考虑如[图 1-1-4](#fig.1-1-4) 所示的简单的波束形成操作。假设外部信号是方向为 $\boldsymbol{a}$、时域频率(弧度)为 $\omega$ 的平面波,则在时域上每个阵元的输入信号可以用两种等效的方式进行表示。
<a id="fig.1-1-4"></a>
![图 1-1-4 具有平面波输入的阵列](../images/post/2023-04-18-josh-oap-part-1-1/2023-04-18-josh-oap-part-1-1-040-ArrayWithPlaneWaveInput.png){width=600px}
&emsp;&emsp;由于信号到达不同阵元的时间不同,设 $f(t)$ 是**在坐标系原点接收到的信号**,其在变换域表示为 $F (\omega)$,则
$$\begin{equation} \label{DelayedSignal}
\boldsymbol{f}(t, \boldsymbol{p}) = \left[
\begin{array}{c}
f\left(t - \tau_0\right) \\
f\left(t - \tau_1\right) \\
\vdots \\
f\left(t - \tau_{N-1}\right) \\
\end{array}
\right]
\end{equation}$$
其中时延(距离除以速度得到时间)
$$\begin{equation} \label{ExpressionOfDelayByDirection}
\tau_n = \frac{\boldsymbol{a}^\mathrm{T}\boldsymbol{p}_n}{c}
\end{equation}$$
其中 $c$ 是信号在介质中的传播速度,$\boldsymbol{a}$ 是一个单位矢量,表示为
$$\begin{equation}
\boldsymbol{a} = \left[ \begin{array}{c}
-\sin\theta\cos\varphi \\
-\sin\theta\sin\varphi \\
-\cos\theta
\end{array} \right]
\end{equation}$$
上式中的负号是考虑了 $\boldsymbol{a}$ 的方向。则 $\tau_n$ 可以进一步表示为:
$$\begin{equation} \label{RelativeDelay}
\tau_n = -\frac{1}{c}\left(\sin\theta\cos\varphi \cdot p_{x_n} + \sin\theta\sin\varphi \cdot p_{y_n} + \cos\theta \cdot p_{z_n} \right)
\end{equation}$$
如果定义对于每个轴的方向余弦(direction cosine)为
$$\begin{align}
u_x &= \sin\theta\cos\varphi \\
u_y &= \sin\theta\sin\varphi \\
u_z &= \cos\theta
\end{align}$$
则有
$$\begin{equation}
\boldsymbol{u} = -\boldsymbol{a}
\end{equation}$$
则式 $\eqref{RelativeDelay}$ 给出的相对时延可以写成
$$\begin{equation} \label{RelativeDelayWithDirectionCosine}
\tau_n = -\frac{1}{c}\left(u_x p_{x_n} + u_y p_{y_n} + u_z p_{z_n} \right) = -\frac{\boldsymbol{u}^\mathrm{T}\boldsymbol{p}_n}{c}
\end{equation}$$
根据式 $\eqref{DelayedSignal}$,$\boldsymbol{F}(\omega)$ 的第 $n$ 个分量为(利用 Fourier 变换的时移性质)
$$\begin{equation}
F_n(\omega) = \int_{-\infty}^{\infty} e^{j \omega t} f_n(t - \tau_n) \mathrm{d} t = e^{j \omega \tau_n} F (\omega)
\end{equation}$$
其中
$$\begin{equation}
\omega \tau_n = \frac{\omega}{c} \boldsymbol{a}^\mathrm{T}\boldsymbol{p}_n = -\frac{\omega}{c} \boldsymbol{u}^\mathrm{T}\boldsymbol{p}_n
\end{equation}$$
对于在局部均匀的介质(locally homogeneous medium)里传播的平面波,定义波数 $\boldsymbol{k}$ (在波传播的方向上单位长度内的周期数目)为
$$\begin{equation} \label{DefinitionOfWavenumber}
\boldsymbol{k} = \frac{\omega}{c} \boldsymbol{a} = \frac{2\pi}{\lambda} \boldsymbol{a} = -\frac{2\pi}{\lambda} \left[
\begin{array}{c}
\sin\theta\cos\varphi \\
\sin\theta\sin\varphi \\
\cos\theta
\end{array}
\right]
= -\frac{2\pi}{\lambda} \boldsymbol{u}
\end{equation}$$
其中,$\lambda$ 是对应于频率 $\omega$ 的波长,且波数的幅度由波动方程限定
$$\begin{equation} \label{WaveEquation}
\left| \boldsymbol{k} \right| = \frac{\omega}{c} = \frac{2\pi}{\lambda}
\end{equation}$$
所以,仅 $\boldsymbol{k}$ 的方向是变化的。比较式 $\eqref{ExpressionOfDelayByDirection}$ 和式 $\eqref{DefinitionOfWavenumber}$,有
$$\begin{equation}
\omega \tau_n = \boldsymbol{k}^\mathrm{T}\boldsymbol{p}_n
\end{equation}$$
定义
<a id="DefinitionOfArrayManifoldVector"></a>
$$\begin{equation} \label{DefinitionOfArrayManifoldVector}
\boldsymbol{v}_{\boldsymbol{k}}\left(\boldsymbol{k}\right) = \left[ \begin{array}{c}
e^{-j \boldsymbol{k}^\mathrm{T}\boldsymbol{p}_0} \\
e^{-j \boldsymbol{k}^\mathrm{T}\boldsymbol{p}_1} \\
\vdots \\
e^{-j \boldsymbol{k}^\mathrm{T}\boldsymbol{p}_{N-1}} \\
\end{array} \right]
\end{equation}$$
则 $\boldsymbol{F}(\omega)$ 可写为
$$\begin{equation}
\boldsymbol{F}(\omega) = F(\omega) \boldsymbol{v}_{\boldsymbol{k}}\left(\boldsymbol{k}\right)
\end{equation}$$
矢量 $\boldsymbol{v}_{\boldsymbol{k}}\left(\boldsymbol{k}\right)$ 包含了阵列的所有空间特征,称为**{% label primary @阵列流形矢量(array manifold vector) %}**,在阵列信号处理理论中具有非常核心的作用。下标 $\boldsymbol{k}$ 表示参数属于 $\boldsymbol{k}$ 空间。这个下标的作用是把它和以后将在阵列流形矢量中使用的其他变量相区分。
<a id="fig.1-1-5"></a>
![图 1-1-5 延时-求和波束形成器](../images/post/2023-04-18-josh-oap-part-1-1/2023-04-18-josh-oap-part-1-1-050-DelayAndSumBeamformer.png){width=600px}
&emsp;&emsp;如[图 1-1-5](#fig.1-1-5) 所示,把每个阵元的输入信号进行时移、相加、归一化,使得输出为 $f(t)$,其中
$$\begin{equation} \label{DelayAndSumBeamformer}
h_n(\tau) = \frac{1}{N} \delta(\tau + \tau_n)
\end{equation}$$
且
$$\begin{equation}
y(t) = f(t)
\end{equation}$$
上述处理器称为**{% label primary @延时求和波束形成器(delay-and-sum beamformer) %}**或**{% label primary @常规波束形成器(conventional beamformer) %}**。在实际中会在每个通道中加上一个共同的延时,使得[图 1-1-5](#fig.1-1-5) 中的操作是物理可实现的。
&emsp;&emsp;此外,还可以把式 $\eqref{DelayAndSumBeamformer}$ 在频域内写成简洁的矩阵形式。如果 $\boldsymbol{k}_\mathrm{s}$ 是我们所感兴趣的平面波信号的波数,则
$$\begin{equation}
\boldsymbol{H}^\mathrm{T} (\omega) = \frac{1}{N} \boldsymbol{v}_{\boldsymbol{k}}^\mathrm{H} \left( \boldsymbol{k}_\mathrm{s} \right)
\end{equation}$$
# 单位平面波模型
&emsp;&emsp;更一般的,要确定阵列对一个输入信号场 $\boldsymbol{f}(t, \boldsymbol{p})$ 的响应,可以通过之前给出的卷积求和操作来实现,但更有用的方法是确定阵列对单位平面波(unit plane wave)的响应,将响应表示为时域(弧度)频率 $\omega$ 和波数 $\boldsymbol{k}$ 的函数,然后将线性时不变系统中复指数基函数叠加分析的系统理论方法扩展到空时信号的情况。
&emsp;&emsp;取基函数
$$\begin{equation}
f_n\left( t, \boldsymbol{p}_n \right) = \exp \left[ j \left( \omega t - \boldsymbol{k}^\mathrm{T} \boldsymbol{p}_n\right) \right], \, n = 0, 1, \cdots, N-1
\end{equation}$$
或
$$\begin{equation}
\boldsymbol{f} \left( t, \boldsymbol{p} \right) = e^{j\omega t} \boldsymbol{v}_{\boldsymbol{k}}\left(\boldsymbol{k}\right)
\end{equation}$$
&emsp;&emsp;式 $\eqref{VectorFormOfLinearArrayOutputInTimeDomain}$ 中的阵列处理器对于一个平面波的响应为
$$\begin{equation} \label{ArrayResponseToUnitPlaneWaveInTimeDomain}
y \left( t, \boldsymbol{k} \right) = \boldsymbol{H}^\mathrm{T} (\omega) \boldsymbol{v}_{\boldsymbol{k}}\left(\boldsymbol{k}\right) e^{j\omega t}
\end{equation}$$
其中 $\boldsymbol{H} (\omega)$ 是式 $\eqref{ImpulseResponse}$ 中 $\boldsymbol{h}(t)$ 的傅里叶变换。
&emsp;&emsp;这里使用 $y \left( t, \boldsymbol{k} \right)$ 来强调输出和输入波数 $\boldsymbol{k}$ 的关系。时域上的相关性体现在输出是一个复指数,和输入平面波具有相同的频率。在频域内,$\eqref{ArrayResponseToUnitPlaneWaveInTimeDomain}$ 可以写成下面的形式:
$$\begin{equation} \label{ArrayResponseToUnitPlaneWaveInFreqDomain}
Y \left( \omega, \boldsymbol{k} \right) = \boldsymbol{H}^\mathrm{T} (\omega) \boldsymbol{v}_{\boldsymbol{k}}\left(\boldsymbol{k}\right)
\end{equation}$$
&emsp;&emsp;注意,$\omega$ 是对应输入频率的单一频率。阵列的空时处理完全可以由式 $\eqref{ArrayResponseToUnitPlaneWaveInFreqDomain}$ 的右端描述。把这一项定义为
$$\begin{equation} \label{FrequencyWavenumberResponse}
\boxed{\boldsymbol{\varUpsilon} \left( \omega, \boldsymbol{k} \right) \triangleq \boldsymbol{H}^\mathrm{T} (\omega) \boldsymbol{v}_{\boldsymbol{k}}\left(\boldsymbol{k}\right)}
\end{equation}$$
称之为阵列的**{% label primary @频率-波数响应函数(frequency-wavenumber response function) %}**。它描述了一个阵列对于波数为 $\boldsymbol{k}$、时域频率为 $\omega$ 的输入平面波的复增益,具有与线性、时不变系统的传递函数相同的解释(这里我们用了 $\boldsymbol{\varUpsilon} \left( \omega, \boldsymbol{k} \right)$, 是因为 $Y \left( \omega, \boldsymbol{k} \right)$ 在后面将要用于描述对任意输入的输出)。 $\boldsymbol{\varUpsilon} \left( \omega, \boldsymbol{k} \right)$ 是定义在整个 $\boldsymbol{k}$ 空间上的。$\eqref{FrequencyWavenumberResponse}$ 中的第二项 $\boldsymbol{v}_{\boldsymbol{k}}\left(\boldsymbol{k}\right)$ 是在式 $\eqref{DefinitionOfArrayManifoldVector}$ 中定义的阵列流形矢量。
&emsp;&emsp;频率-波数响应函数描述了阵列对任意一个平面波的响应。在大多数的实际物理应用中,时域频率 $\omega$ 和空域波数 $\boldsymbol{k}$ 通过平面波传播的波动方程形成了耦合关系。有时这是一个非常简单的关系,例如当一个平而波在均匀(且无限)的空间中传播时。在其他的情况下,可能是非常复杂的耦合关系,例如在水下声学和地震学中的分层介质模型中的情况。
&emsp;&emsp;一个阵列的**{% label primary @波束方向图(beam pattern) %}**定义的背景是平面波在局部均匀的介质中传播,约束的波动方程见式 $\eqref{WaveEquation}$。如式 $\eqref{WaveEquation}$ 所示,这约束了波数 $\boldsymbol{k}$ 的幅度。波束方向图是用入射方向表示的频率-波数响应函数,或者可以写成
$$\begin{equation}
B(\omega:\theta,\varphi) = \left. \boldsymbol{\varUpsilon} \left( \omega, \boldsymbol{k} \right) \right|_{\boldsymbol{k}=\frac{2\pi}{\lambda}\boldsymbol{a}(\theta,\varphi)}
\end{equation}$$
其中 $\boldsymbol{a}(\theta,\varphi)$ 是一个单位矢量,在球坐标系中对应的角度为 $\theta$ 和 $\varphi$。可以看到,**波束方向图是频率-波数响应在一个半径为 $2\pi /\lambda$ 的球上的值**。
&emsp;&emsp;阵列的波束方向图是确定阵列性能的关键要素。后续将会研究均匀加权线阵(uniformly weighted linear array)的波束方向图。
# 窄带假设
&emsp;&emsp;下面讨论 $f\left( t,\boldsymbol{p}_n \right)$ 是带通信号的情况,即
$$\begin{equation} \label{BandpassConstraint}
f\left( t,\boldsymbol{p}_n \right) = \sqrt{2} \Re\left\{ \tilde{f} \left( t,\boldsymbol{p}_n \right) e^{j \omega_c t}\right\}, \, n = 0, \cdots, N-1
\end{equation}$$
其中,$\omega_c$ 是载波频率,$\tilde{f} \left( t,\boldsymbol{p}_n \right)$ 是复包络。假设复包络的带限区域为
$$\begin{equation}
\left| \omega_L \right| \leqslant 2\pi B_s /2
\end{equation}$$
其中
$$\begin{equation}
\omega_L \triangleq \omega - \omega_c
\end{equation}$$
且 $\pi B_s$ 是一个常数,确定了复包络的最大带宽。
&emsp;&emsp;对于式 $\eqref{DelayedSignal}$ 中的平面波,式 $\eqref{BandpassConstraint}$ 成为
$$\begin{equation} \label{BandpassConstraintApproximation}
f\left( t,\boldsymbol{p}_n \right) = \sqrt{2} \Re\left\{ \tilde{f} \left( t - \tau_n \right) e^{j \omega_c \left( t - \tau_n \right)}\right\}, \, n = 0, \cdots, N-1
\end{equation}$$
其中,$\tau_n$ 由式 $\eqref{RelativeDelayWithDirectionCosine}$ 给出。
&emsp;&emsp;现在考虑信号跨越阵列传播的时间(the travel time across the array)。定义 $\Delta T_{nm} \left( \boldsymbol{u} \right)$ 为一个方向余弦为 $\boldsymbol{u}$ 的平面波在第 $n$ 个阵元和第 $m$ 个阵元之间的传播时间。则,
$$\begin{equation}
\Delta T_{\max} \triangleq \max_{n,m=0,\cdots,N-1;\boldsymbol{u}} \{\Delta T_{nm} \left( \boldsymbol{u} \right)\}
\end{equation}$$
是阵列的任意两个阵元之间的最大传播时间。对于一个线阵,这个最大值是当一个信号沿着阵列的轴线传播时(endfire),阵列两端阵元之间的传播时间。
&emsp;&emsp;假设原点位于阵列的重心,即
$$\begin{equation}
\sum_{n=0}^{N-1} \boldsymbol{p}_n = 0
\end{equation}$$
则式 $\eqref{RelativeDelayWithDirectionCosine}$ 给出的所有 $\tau_n$ 均满足
$$\begin{equation}
\tau_n \leqslant \Delta T_{\max},\, n = 0, \cdots, N-1
\end{equation}$$
&emsp;&emsp;在我们感兴趣的大多数情况下,复包络的带宽非常小,满足
$$\begin{equation}
\tilde{f}(t - \tau_n) \simeq \tilde{f}(t),\, n = 0, \cdots, N-1
\end{equation}$$
为了使上述近似有效,需要有
$$\begin{equation} \label{NarrowBandConstraint}
B_\mathrm{s}\cdot \Delta T_{\max} \ll 1
\end{equation}$$
定义复包络满足式 $\eqref{NarrowBandConstraint}$ 的带通信号为**{% label primary @窄带信号 %}**。后面我们会在有关最优处理器的内容中重新研究这个定义,并给出一个更好的量化的讨论。现在,直接采用式 $\eqref{NarrowBandConstraint}$ 。则式 $\eqref{BandpassConstraintApproximation}$ 简化为
$$\begin{equation}
f\left( t,\boldsymbol{p}_n \right) = \sqrt{2} \Re\left\{ \tilde{f} \left( t \right) e^{-j \omega_c \tau_n} e^{j \omega_c t } \right\}
\end{equation}$$
可以看到,在窄带的情况下,信号的延时可以用一个相移来近似。所以延时-求和波束形成器可以用一组移相器来代替延时线。结果得到的波束形成器在[图 1-1-6](#fig.1-1-6) 中给出。这种实现方式通常称为**{% label primary @相控阵 %}**,并在实际中得到了广泛的应用。
<a id="fig.1-1-6"></a>
![图 1-1-6 利用移相器实现的窄带波束形成器](../images/post/2023-04-18-josh-oap-part-1-1/2023-04-18-josh-oap-part-1-1-060-NarrowbandBeamformerImplementedUsingPhaseShifters.png){width=600px}
&emsp;&emsp;可以发现,在很多的应用中,我们都想要调整每个传感器输出的增益和相位,以得到一个理想的波束方向图。这就产生了在[图 1-1-6(a)](#fig.1-1-6) 中给出的窄带模型。$w_n^\ast$ 是复权值,可以用一个增益和移相器的级联来实现,如[图 1-1-6(b)](#fig.1-1-6) 所示。
<a id="fig.1-1-7"></a>
![图 1-1-7 一般窄带波束形成器](../images/post/2023-04-18-josh-oap-part-1-1/2023-04-18-josh-oap-part-1-1-070-GeneralNarrowbandBeamformer.png){width=600px}
&emsp;&emsp;另外一种实现的结构见[图 1-1-6(c)](#fig.1-1-6)。在一些情况下,我们利用正交解调,并在对基带信号进行复加权来实现波束形成器,实际是在一个正交分量上使用 $\Re[w_n^\ast]$ 进行加权,在另外一个正交分量上使用 $\Im[w_n^\ast]$ 进行加权,结果是相等的。
&emsp;&emsp;定义一个复数权矢量为
<a id="ComplexWeightVector"></a>
$$\begin{equation} \label{ComplexWeightVector}
\boldsymbol{w}^\mathrm{H} = [w_0^\ast, w_1^\ast, \cdots, w_{N-1}^\ast]
\end{equation}$$
则式 $\eqref{ArrayResponseToUnitPlaneWaveInTimeDomain}$ 成为
<a id="FrequencyWavenumberResponseWithComplexWeigh"></a>
$$\begin{equation}
y\left( t,\boldsymbol{k} \right) = \boldsymbol{w}^\mathrm{H} \boldsymbol{v}_{\boldsymbol{k}}\left( \boldsymbol{k} \right) e^{j\omega t}
\end{equation}$$
且
$$\begin{equation}
\varUpsilon \left(\omega, \boldsymbol{k} \right) = \boldsymbol{w}^\mathrm{H} \boldsymbol{v}_{\boldsymbol{k}}\left( \boldsymbol{k} \right)
\end{equation}$$
式 $\eqref{ComplexWeightVector}$ 中的定义等价于
<a id="NarrowBandComplexWeightVector"></a>
$$\begin{equation}
\boldsymbol{w}^\mathrm{H} = \boldsymbol{H}^\mathrm{T}(\omega_c)
\end{equation}$$
这里主要关注的是窄带模型,对于宽带信号,一种处理方法是利用离散傅里叶变换(DFT)把信号分解到更窄的频率柜 (frequency bin),每个频率柜内的信号是满足窄带条件的,因此所有的窄带结果可以直接得到应用。
# 参考文献
1. Harry L. Van Trees. *Optimum array processing: Part IV of detection, estimation, and modulation theory.* New York, NY, USA: John Wiley & Sons, 2002.
2. Harry L. Van Trees, 汤俊. *最优阵列处理技术.* 北京:清华大学出版社. 2008.
@@ -0,0 +1,337 @@
---
title: "Josh's Note — 最优阵列处理<br>Part 1.2 均匀线阵模型"
mathjax: true
comments: true
copyright: true
toc:
enable: true
number: true
wrap: true
expand_all: true
max_depth: 4
tags:
- 阵列信号处理
- 均匀线阵
- ULA
- 可视区域
categories:
- - Josh 的学习笔记
- 最优阵列处理
- 阵列和空域滤波器
abbrlink: de20fd09
date: 2023-04-20 00:14:31
---
# 均匀线阵的基本模型
&emsp;&emsp;**{% label primary @均匀线性阵列(uniform linear array, ULA) %}**如[图 1-2-1](#fig.1-2-1) 所示,其中有 $N$ 个位于 $z$ 轴上的阵元,阵元间距均匀,记为 $d$;这里将阵列的中心放在了坐标系的原点上,这种放置方法可以简化计算量。
<a id="fig.1-2-1"></a>
![图 1-2-1 放置在 $z$ 轴上的线阵](../images/post/2023-04-20-josh-oap-part-1-2/2023-04-20-josh-oap-part-1-2-010-LinearArrayAlongZAaxis.png){width=600px}
<!-- more -->
&emsp;&emsp;如[图 1-2-1](#fig.1-2-1),阵元的位置为
$$\begin{equation} \label{ElementLocation}
\begin{cases}
p_{x_n} = 0 \\
p_{y_n} = 0 \\
p_{z_n} = \left( n - \frac{N-1}{2} \right) d
\end{cases}
, \, n = 0,1,\cdots,N-1
\end{equation}$$
为了确定阵列流形矢量 $\boldsymbol{v}_{\boldsymbol{k}}\left(\boldsymbol{k}\right)$,把式 $\eqref{ElementLocation}$ 代入到[阵列流形矢量的定义][]中,得到
$$\begin{equation} \label{ManifoldVectorOfULA}
\boldsymbol{v}_{\boldsymbol{k}}\left(k_z\right) = \left[\begin{array}{c}
e^{j \left( \frac{N-1}{2} \right) k_z d} \\
e^{j \left( \frac{N-1}{2} - 1\right) k_z d} \\
\vdots \\
e^{-j \left( \frac{N-1}{2} \right) k_z d} \\
\end{array}\right]
\end{equation}$$
这里
$$\begin{equation}
k_z = -\frac{2\pi}{\lambda}\cos\theta = -k_0 \cos\theta
\end{equation}$$
其中波数的幅度
$$\begin{equation}
k_0 \triangleq \left| \boldsymbol{k} \right| = \frac{2\pi}{\lambda}
\end{equation}$$
注意,线阵在 $\varphi$ 方向是没有分辨能力的。将[复权矢量][]和式 $\eqref{ManifoldVectorOfULA}$ 代入[用复权矢量表示的波数-频率响应函数][],得到 ULA 在角度域的频率-波数响应函数
$$\begin{equation} \label{FWRFOfULAInAngleDomain}
\begin{aligned}
\boldsymbol{\varUpsilon}(\omega,k_z) &= \boldsymbol{w}^\mathrm{H}\boldsymbol{v}_{\boldsymbol{k}}\left(k_z\right) \\
&= \sum_{n=0}^{N-1} w_n^\ast e^{-j\left( n - \frac{N-1}{2} \right) k_z d}
\end{aligned}
\end{equation}$$
定义下面的变量也是很有用的(波数在 $z$ 轴上的投影,乘以阵元间距,也即扫过一个阵元间距时,波数的变化量在 $z$ 轴上的体现):
$$\begin{equation} \label{DefinitionOfWavenumberDiffOfTwoElements}
\psi = -k_z d = \frac{2\pi}{\lambda}\cos\theta\cdot d = \frac{2\pi}{\lambda}u_z d
\end{equation}$$
其中 $u_z$ 是方向余弦的 $z$ 方向分量,
$$\begin{equation}
u_z = \cos\theta
\end{equation}$$
将式 $\eqref{DefinitionOfWavenumberDiffOfTwoElements}$ 代入式 $\eqref{FWRFOfULAInAngleDomain}$,得到**在 $\psi$ 空间的频率-波数函数(frequency-wavenumber function in $\psi$-space)**
$$\begin{equation} \label{FWRFOfULAInWavenumberDomain}
\boldsymbol{\varUpsilon}_\psi(\psi) = e^{-j \frac{N-1}{2} \psi } \sum_{n=0}^{N-1} w_n^\ast e^{j n\psi}
\end{equation}$$
$\boldsymbol{\varUpsilon}(\omega,k_z)$ 和 $\boldsymbol{\varUpsilon}_\psi(\psi)$ 的定义域均为 $-\infty$ 到 $\infty$,但仅在区域 $0 \leqslant \theta \leqslant \pi$(或 $-1 \leqslant u_z \leqslant 1$ ) 内代表传播的信号,即有 $-\displaystyle\frac{2\pi d}{\lambda} \leqslant \psi \leqslant \frac{2\pi d}{\lambda}$,这个区域称为**{% label primary @可视区域(visible region) %}**。
&emsp;&emsp;可以观察到,若定义
$$\begin{equation}
z = e^{j \psi}
\end{equation}$$
$$\begin{equation} \label{FWRFOfULAInZDomain}
\boldsymbol{\varUpsilon}_z(z) = z^{- \frac{N-1}{2}} \sum_{n=0}^{N-1} w_n^\ast z^{n}
\end{equation}$$
则式 $\eqref{FWRFOfULAInZDomain}$ 可以写成
$$\begin{equation}
\boldsymbol{\varUpsilon}_z(z) = z^{- \frac{N-1}{2}} \left(\sum_{n=0}^{N-1} w_n z^{-n}\right)^\ast
\end{equation}$$
其中
$$\begin{equation}
W(z) = \sum_{n=0}^{N-1} w_n z^{-n}
\end{equation}$$
和 $z$ 变换的形式相似,且
$$\begin{equation} \label{FWRFOfULAInZDomainToWavenumberDomain}
\boldsymbol{\varUpsilon}_\psi(\psi) = \left. \boldsymbol{\varUpsilon}_z(z) \right|_{z=e^{j\psi}} = \left.\left(z^{- \frac{N-1}{2}} W^\ast(z)\right)\right|_{z=e^{j\psi}}
\end{equation}$$
是在 $\psi$ 空间的频率-波数响应。我们在后面将利用这个关系。
&emsp;&emsp;在式 $\eqref{FWRFOfULAInAngleDomain}$ 、式 $\eqref{FWRFOfULAInWavenumberDomain}$ 和式 $\eqref{FWRFOfULAInZDomainToWavenumberDomain}$ 中用三种不同的方式写出了频率-波数函数,尽管这可能显得引入了过多的符号,但我们将发现在不同的情况下,这些不同的形式都是有用的。
&emsp;&emsp;在 $\theta$ 和 $u$ 空间定义出阵列流形也是有用的
$$\begin{equation}
\left[ \boldsymbol{v}_\theta(\theta) \right] = e^{j\left( n - \frac{N-1}{2} \right) \frac{2\pi d}{\lambda} \cos \theta}, \, n = 0,\cdots, N-1
\end{equation}$$
$$\begin{equation}
\left[ \boldsymbol{v}_u(u) \right] = e^{j\left( n - \frac{N-1}{2} \right) \frac{2\pi d}{\lambda} u}, \, n = 0,\cdots, N-1
\end{equation}$$
也可以用三种形式写出波束方向图。频率-波数函数和波束方向图的关键区别是波束方向图的参量受限于实际的物理角度 $\theta$,所以,
$$\begin{equation}
B_\theta(\theta) = \boldsymbol{w}^\mathrm{H} \boldsymbol{v}_\theta(\theta) = e^{-j\left(\frac{N-1}{2} \right) \frac{2\pi d}{\lambda} \cos \theta} \sum_{n=0}^{N-1} w_n^\ast e^{j n \frac{2\pi d}{\lambda} \cos \theta}, \, 0 \leqslant \theta \leqslant \pi
\end{equation}$$
<a id="BeamPatternInDirectionCosineDomain"></a>
$$\begin{equation}
B_u(u) = \boldsymbol{w}^\mathrm{H} \boldsymbol{v}_u(u) = e^{-j\left(\frac{N-1}{2} \right) \frac{2\pi d}{\lambda} u} \sum_{n=0}^{N-1} w_n^\ast e^{j n \frac{2\pi d}{\lambda} u}, \, -1 \leqslant u \leqslant 1
\end{equation}$$
$$\begin{equation} \label{BeamPatternInWavenumberDomain}
B_\psi(\psi) = \boldsymbol{w}^\mathrm{H} \boldsymbol{v}_\psi(\psi) = e^{-j\left(\frac{N-1}{2} \right) \psi} \sum_{n=0}^{N-1} w_n^\ast e^{j n \psi}, \, -\frac{2\pi d}{\lambda} \leqslant \psi \leqslant \frac{2\pi d}{\lambda}
\end{equation}$$
当函数的变量很清楚时,我们将省略掉 $B(\,\cdot\,)$ 中的下标。
# 均匀线阵的阵列流形
&emsp;&emsp;对于均匀线阵,通常用 $\psi$ 表示阵列流形
$$\begin{equation}
\left[ \boldsymbol{v}_\psi(\psi) \right]_n = e^{j\left( n - \frac{N-1}{2} \right)\psi}, \, n = 0, 1, \cdots, N-1
\end{equation}$$
$$\begin{equation} \label{ManifoldVecOfULAWithConjugateSymmetry}
\boxed{\boldsymbol{v}_\psi(\psi) = \left[ \begin{array}{c}
e^{-j\left(\frac{N-1}{2} \right)\psi} &
e^{-j\left(\frac{N-3}{2} \right)\psi} &
\cdots &
e^{j\left(\frac{N-3}{2} \right)\psi} &
e^{j\left(\frac{N-1}{2} \right)\psi} &
\end{array} \right]^\mathrm{T}}
\end{equation}$$
可以看到 ULA 的阵列流形矢量具有**{% label primary @共扼对称性(conjugate symmetry) %}**。
{% tabs 阵列流形矢量具有共扼对称性 %}
<!-- tab $N$ 为偶数-->
当 $N$ 为偶数时,如果定义一个 $N/2$ 维的矢量 $\boldsymbol{v}_{\psi_1}(\psi)$,对应 $\boldsymbol{v}_\psi(\psi)$ 的前 $N/2$ 个元素,则有
$$\begin{equation}
\boldsymbol{v}_\psi(\psi) = \left[ \begin{array}{c}
\boldsymbol{v}_{\psi_1}(\psi) \\
\boldsymbol{J}\boldsymbol{v}_{\psi_1}^\ast(\psi)
\end{array} \right]
\end{equation}$$
<!-- endtab -->
<!-- tab $N$ 为奇数-->
当 $N$ 为奇数时,如果定义一个 $(N-1)/2$ 维的矢量 $\boldsymbol{v}_{\psi_1}(\psi)$,对应 $\boldsymbol{v}_\psi(\psi)$ 的前 $(N-1)/2$ 个元素,则有
$$\begin{equation}
\boldsymbol{v}_\psi(\psi) = \left[ \begin{array}{c}
\boldsymbol{v}_{\psi_1}(\psi) \\
1 \\
\boldsymbol{J}\boldsymbol{v}_{\psi_1}^\ast(\psi)
\end{array} \right]
\end{equation}$$
<!-- endtab -->
{% endtabs %}
其中交换矩阵(exchange matrix) $\boldsymbol{J}$
$$\begin{equation}
\boldsymbol{J} = \left[ \begin{array}{c}
0 & 0 & \cdots & 1 \\
\vdots & \vdots & & \vdots \\
0 & 1 & \cdots & 0 \\
1 & 0 & \cdots & 0 \\
\end{array} \right]
\end{equation}$$
在很多应用中,这种共轭对称性可以用于节省运算量和改进性能。例如,如果 $\boldsymbol{w}$ 也是共枙对称的,则当 $N$ 为偶数时,可以写成
$$\begin{equation} \label{ConjugateSymmetry}
\boldsymbol{w} = \left[ \begin{array}{c}
\boldsymbol{w}_1 \\
\boldsymbol{J}\boldsymbol{w}_1
\end{array} \right]
\end{equation}$$
在 $\psi$ 空间的波束方向图为
$$\begin{equation}
\begin{aligned}
B_\psi(\psi) &= \boldsymbol{w}^\mathrm{H}\boldsymbol{v}_\psi(\psi) \\
&= \left[\begin{array}{c}\boldsymbol{w_1}^\mathrm{H} & \boldsymbol{w_1}^\mathrm{T}\boldsymbol{J}\end{array}\right] \left[\begin{array}{c}\boldsymbol{v}_{\psi_1}(\psi) \\ \boldsymbol{J}\boldsymbol{v}_{\psi_1}^\ast(\psi)\end{array}\right] \\
&= \boldsymbol{w}_1^\mathrm{H} \boldsymbol{v}_{\psi_1}(\psi) + \boldsymbol{w_1}^\mathrm{T}\boldsymbol{v}_{\psi_1}^\ast(\psi) \\
&= 2 \Re\left[ \boldsymbol{w}_1^\mathrm{H} \boldsymbol{v}_{\psi_1}(\psi) \right]
\end{aligned}
\end{equation}$$
所以波束方向图是一个实函数。注意到,实对称的权矢量同样能够满足式 $\eqref{ConjugateSymmetry}$;当 $N$ 为奇数时,也有类似的结果。我们将发现很多其他的阵列结构也具有共枙对称性质。
&emsp;&emsp;式 $\eqref{ManifoldVecOfULAWithConjugateSymmetry}$ 强调了 $\boldsymbol{v}_\psi(\psi)$ 的共枙对称性质。也可以把 $\boldsymbol{v}_\psi(\psi)$ 写成
$$\begin{equation}
\boldsymbol{v}_\psi(\psi) = e^{-j\left(\frac{N-1}{2} \right)\psi} \left[ \begin{array}{c}
1 &
e^{j\psi} &
\cdots &
e^{j(N-1)\psi} &
\end{array} \right]^\mathrm{T}
\end{equation}$$
这个形式强调了 $\boldsymbol{v}_\psi(\psi)$ 的 Vandermonde 结构。
# 从波束方向图获得权矢量
&emsp;&emsp;下面讨论如何从特定的方向图 $B_\psi(\psi)$ 中获得权矢量 $\boldsymbol{w}$,我们从式 $\eqref{BeamPatternInWavenumberDomain}$ 中的关系开始
$$\begin{equation} \label{ShortBeamPatternInWavenumberDomain}
B_\psi(\psi) = \boldsymbol{w}^\mathrm{H} \boldsymbol{v}_\psi(\psi)
\end{equation}$$
假设 $B_\psi(\psi)$ 是已知的,我们想确定产生这个 $B_\psi(\psi)$ 的 $\boldsymbol{w}$。由于 $\boldsymbol{w}^\mathrm{H}$ 是一个 $1 \times N$ 维的矢量,因此如果知道 $B_\psi(\psi)$ 在 $N$ 个 $\psi$ 值上的值,就可以确定 $\boldsymbol{w}$。
&emsp;&emsp;对波束方向图在 $N$ 个 $\psi_i$ 上进行采样,这里要求 $\psi_i$ 必须是不同的,但不一定是等距的,记采样点处的波束方向图的值为 $B(\psi_i)$。根据式 $\eqref{ShortBeamPatternInWavenumberDomain}$,有
$$\begin{equation} \label{ElementOfShortBeamPatternInWavenumberDomain}
\boldsymbol{w}^\mathrm{H} \boldsymbol{v}(\psi_i) = B(\psi_i), \, i = 1, \cdots, N
\end{equation}$$
定义一个 $N \times N$ 维的阵列流形矩阵
$$\begin{equation}
\boldsymbol{V}(\psi) \triangleq \left[ \begin{array}{c}\boldsymbol{v}(\psi_1) & \cdots & \boldsymbol{v}(\psi_N)\end{array}\right]
\end{equation}$$
和一个 $1 \times N$ 维的波束方向图矩阵
$$\begin{equation}
\boldsymbol{B} \triangleq \left[ \begin{array}{c}B(\psi_1) & \cdots & B(\psi_N)\end{array}\right]
\end{equation}$$
则式 $\eqref{ElementOfShortBeamPatternInWavenumberDomain}$ 可以写成
$$\begin{matrix}
\boldsymbol{w}^\mathrm{H} \boldsymbol{V}(\psi) = \boldsymbol{B}
\end{matrix}$$
或
$$\begin{matrix}
\boldsymbol{V}^\mathrm{H}(\psi) \boldsymbol{w} = \boldsymbol{B}^\mathrm{H}
\end{matrix}$$
由于 $\boldsymbol{V}^\mathrm{H}(\psi)$ 是满秩的,所以
$$\begin{equation} \label{WeightVecCalculation}
\boxed{\boldsymbol{w} = \left[ \boldsymbol{V}^\mathrm{H}(\psi) \right]^{-1}\boldsymbol{B}^\mathrm{H}}
\end{equation}$$
尽管 $\psi_i$ 可以任意选择,但如果它们相距太近,那么阵列流形矢量将接近于线性相关,在式 $\eqref{WeightVecCalculation}$ 中的求逆可能会有数值计算的问题。如果采用均匀间距 $2\pi/N$,那么后续将会推导一个高效的权值计算算法。
&emsp;&emsp;我们特别感兴趣的一种情况是已经定义了波束方向图的 $N — 1$ 个零点。如果假设阵列的指向为正侧向(broadside,即阵列排布方向和信号来向垂直),令
$$\begin{equation}
\psi_1 = 0
\end{equation}$$
且 $\psi_2, \psi_3, \cdots, \psi_N$ 对应于零点的位置。假设期望方向的信号无失真通过,其他方向的信号全部抑制,则预期的归一化波束方向图为:
$$\begin{matrix}
\boldsymbol{B} = \left[ \begin{array}{c} 1 & 0 & \cdots & 0 \end{array} \right] = \boldsymbol{e}_1^\mathrm{T}
\end{matrix}$$
则式 $\eqref{WeightVecCalculation}$ 简化为
$$\begin{equation} \label{WeightVecCalculationWithAllZeroExceptMainAxis}
\boxed{\boldsymbol{w} = \left[ \boldsymbol{V}^\mathrm{H}(\psi) \right]^{-1}\boldsymbol{e}_1}
\end{equation}$$
后续将发现这些算法是非常有用的。
在式 $\eqref{WeightVecCalculation}$ 和式 $\eqref{WeightVecCalculationWithAllZeroExceptMainAxis}$ 中有两点需要强调:
1. 上述讨论已经假设 $B_\psi(\psi)$ 在式 $\eqref{ShortBeamPatternInWavenumberDomain}$ 中进行了定义,是由一个 $N \times 1$ 维复矢量 $\boldsymbol{w}$ 产生的。如果 $B_\psi(\psi)$ 是任意函数,且使用式 $\eqref{WeightVecCalculation}$,那么将产生一个方向图,和 $B(\psi_i), i = 1,\cdots,N$ 相匹配,但不一定和函数 $B_\psi(\psi)$ 相匹配。
2. 我们是在一个均匀线阵的背景下介绍这个结果的。但是,这个推导过程适用于任意结构的 $N$ 阵元阵列。
我们已经推导了阵列流形矢量、权值矢量和波束方向图之间的基本关系。下一节将考虑均匀加权的特殊情况。
# 参考文献
1. Harry L. Van Trees. *Optimum array processing: Part IV of detection, estimation, and modulation theory.* New York, NY, USA: John Wiley & Sons, 2002.
2. Harry L. Van Trees, 汤俊. *最优阵列处理技术.* 北京:清华大学出版社. 2008.
[阵列流形矢量的定义]: https://josh-gao.top/posts/8b61f5a7.html#DefinitionOfArrayManifoldVector
[复权矢量]: https://josh-gao.top/posts/8b61f5a7.html#ComplexWeightVector
[用复权矢量表示的波数-频率响应函数]: https://josh-gao.top/posts/8b61f5a7.html#FrequencyWavenumberResponseWithComplexWeigh
@@ -0,0 +1,633 @@
---
title: "Josh's Note — 最优阵列处理<br>Part 1.3 均匀加权线阵"
mathjax: true
comments: true
copyright: true
toc:
enable: true
number: true
wrap: true
expand_all: true
max_depth: 4
tags:
- 阵列信号处理
- 均匀加权线阵
- 3dB 带宽
- 第一零点波束宽度
- 旁瓣
- 栅瓣
- 瑞利限
categories:
- - Josh 的学习笔记
- 最优阵列处理
- 阵列和空域滤波器
abbrlink: aa32ec76
date: 2023-04-20 19:34:47
---
# 均匀加权线阵的频率-波数响应函数
&emsp;&emsp;现在把注意力集中到均匀加权线阵(Uniformly Weighted Linear Array)的情况,即
$$\begin{equation}
w_n = \frac{1}{N}, \, n = 0,1,\cdots,N-1
\end{equation}$$
$$\begin{equation}
\boldsymbol{w} = \frac{1}{N} \boldsymbol{1}
\end{equation}$$
其中 $\boldsymbol{1}$ 是 $N \times 1$ 维的单位矢量,则在 $\psi$ 空间的频率-波数响应函数可以写成(利用等比级数的求和公式)
$$\begin{equation}
\begin{aligned}
\boldsymbol{\varUpsilon}_\psi(\psi) &= \frac{1}{N} \sum_{n=0}^{N-1} e^{j \left(n - \frac{N-1}{2}\right)\psi} \\
&= \frac{1}{N} e^{-j \left(\frac{N-1}{2}\right)\psi} \sum_{n=0}^{N-1} e^{j n \psi} \\
&= \frac{1}{N} e^{-j \left(\frac{N-1}{2}\right)\psi} \left[ \frac{1-e^{jN\psi}}{1-e^{j\psi}} \right]
\end{aligned}
\end{equation}$$
或(利用欧拉公式)
$$\begin{equation}
\boldsymbol{\varUpsilon}_\psi(\psi) = \frac{1}{N} \frac{\sin\left( N \frac{\psi}{2} \right)}{\sin\frac{\psi}{2}}
\end{equation}$$
<!-- more -->
可以观察到:
- 当 $N$ 是奇数时,$\boldsymbol{\varUpsilon}_\psi(\psi)$ 是周期函数,周期为 $2\pi$;
- 当 $N$ 为偶数时,波瓣在 $\pm 2 \pi$、$\pm 6 \pi$ 处的值为负值,周期为 $4 \pi$;
- 对任意的 $N$,$\left|\boldsymbol{\varUpsilon}_\psi(\psi)\right|$ 的周期为 $2 \pi$。
当 $N = 11$ 时, $\boldsymbol{\varUpsilon}_\psi(\psi)$ 和 $\psi$ 的关系在[图 1-3-1](#fig.1-3-1) 中给出。[图 1-3-2](#fig.1-3-2) 给出了 $\left|\boldsymbol{\varUpsilon}_\psi(\psi)\right|$,单位为 dB,其中
$$\begin{equation}
\boldsymbol{\varUpsilon}_\mathrm{dB}(\psi) = 10 \log_{10} \left|\boldsymbol{\varUpsilon}(\psi)\right|^2
\end{equation}$$
<a id="fig.1-3-1"></a>
![图 1-3-1 $\boldsymbol{\varUpsilon}(\psi): \psi = \frac{2\pi}{\lambda} d \cos\theta, N=11$](../images/post/2023-04-20-josh-oap-part-1-3/2023-04-20-josh-oap-part-1-3-010-FrequencyWavenumberResponseFunction.svg){width=1000px}
<a id="fig.1-3-2"></a>
![图 1-3-2 用 dB 表示 $\left|\boldsymbol{\varUpsilon}(\psi)\right|$](../images/post/2023-04-20-josh-oap-part-1-3/2023-04-20-josh-oap-part-1-3-020-FrequencyWavenumberResponseFunctionInDB.svg){width=1000px}
{% note primary MATLAB Code %}
``` matlab fig2_1516.m
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Figure 2.15 & 2.16
% Beampattern of uniformly weighted linear array
% Xiaomin Lu
% Updated 1/5/99
% Last updated by K. Bell 7/22/01, 10/4/01
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear all
close all
N = 11; % 11 elements
% Note, Eq. (2.92) is in fact the standard Dirichlet function
% beam = diric(psi, N);
% if you don't have the signal processing toolbox, this does the same thing
psi = (-5:1/400:5)*pi;
beam = zeros(1,length(psi(:)));
y=sin(.5*psi);
i=find(abs(y)>1e-12); % set where x is not divisible by 2 pi
j=1:length(psi(:));
j(i)=[]; % complement set
beam(i)=sin((N/2)*psi(i))./(N*y(i));
beam(j)=sign(cos(psi(j)*((N+1)/2)));
plot(psi/pi, beam)
grid
xlabel('$\psi/\pi$','Interpreter','latex')
ylabel('Frequency wavenumber response function')
axis([-5 5 -0.4 1])
set(gcf,'Position',[0 0 1000 600])
figure
beam = 20*log10(abs(beam));
plot(psi/pi,beam);
xlabel('$\psi/\pi$','Interpreter','latex')
ylabel('Frequency wavenumber response function (dB)')
axis([-5 5 -25 0])
grid
set(gcf,'Position',[0 0 1000 600])
```
{% endnote %}
若不指定 $\boldsymbol{w}$ 的类型,则 $\boldsymbol{\varUpsilon}_\psi(\psi)$ 是复数,所以相位也应该画出来。但是,均匀加权线阵具有对称性,因此得到的频率-波数响应是实函数。
&emsp;&emsp;也可以用 $k_z$ 来表示频率-波数响应
$$\begin{equation}
\boldsymbol{\varUpsilon}(\omega:k_z) = \frac{1}{N} \frac{\sin\left( N k_z \frac{d}{2} \right)}{\sin \left(k_z\frac{d}{2}\right)}
\end{equation}$$
这里 $\boldsymbol{\varUpsilon}(\omega:k_z)$ 是周期函数,周期为 $2\pi/d$。
{% note warning %}
注意,响应函数仅依赖于波数分量 $k_z$,是 $k_z$ 的周期函数,间隔为 $2\pi/d$,这是线性阵列的一维特性导致的,所以该阵列仅能分析在 $k_z$ 方向上投影的波数分量。
{% endnote %}
# 均匀加权线阵的波束方向图
&emsp;&emsp;均匀加权线阵的波束方向图为
$$\begin{equation}
B_\theta(\theta) = \frac{1}{N} \frac{\sin\left(\frac{N}{2} \cdot \frac{2\pi}{\lambda} \cos \theta \cdot d \right)}{\sin \left( \frac{1}{2} \cdot \frac{2\pi}{\lambda} \cos\theta \cdot d\right)}, \quad 0 \leqslant \theta \leqslant \pi \\
\end{equation}$$
$$\begin{equation}
B_u(u) = \frac{1}{N} \frac{\sin\left(\frac{ \pi Nd}{\lambda} u \right)}{\sin \left( \frac{N d}{\lambda} u\right)}, \quad -1 \leqslant u \leqslant 1 \label{BeamPatternOfUWLAInDirectionCosineDomain}
\end{equation}$$
$$\begin{equation}
B_\psi(\psi) = \frac{1}{N} \frac{\sin\left(N\frac{\psi}{2}\right)}{\sin \left( \frac{\psi}{2} \right)}, \quad -\frac{2\pi d}{\lambda} \leqslant \psi \leqslant \frac{2\pi d}{\lambda} \label{BeamPatternOfUWLAInWaveNumberDomain}
\end{equation}$$
其中定义域分别为 $0 \leqslant \theta \leqslant \pi$、$-1 \leqslant u \leqslant 1$ 和 $-\displaystyle\frac{2\pi d}{\lambda} \leqslant \psi \leqslant \frac{2\pi d}{\lambda}$,称为**{% label primary @可视区域(visible region) %}**。
{% note info %}
函数 $B_u(u)$ 和 $B_\psi(\psi)$ 有时称为**{% label primary @阵列因子(Array Factor) %}**。这个量对非全向性阵元非常重要。
{% endnote %}
&emsp;&emsp;[图 1-3-3](#fig.1-3-3) 给出了 $B_\theta(\theta)$ 的极坐标形式,单位为 dB。如果在三维空间画出波束方向图,在[图 1-3-3](#fig.1-3-3) 中的图将对应沿着任意方位角 $\theta$ 切割得到的方向图。[图 1-3-4](#fig.1-3-4) 给出了波束方向图的幅度和不同变量之间的关系。
<a id="fig.1-3-3"></a>
![图 1-3-3 在极坐标系中画出 $B_\theta(\theta)$](../images/post/2023-04-20-josh-oap-part-1-3/2023-04-20-josh-oap-part-1-3-030-PloarPlotOfBeamPatternInAngleSpace.svg){width=800px}
{% note primary MATLAB Code %}
``` matlab fig2_17.m
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Figure 2.17
% Polar plot of B (Theta)
% Lillian Xu 1/5/99
% Updated by K. Bell 6/25/01
% Functions called: polardb
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear all
close all
N = 11; % Elements in array
d = 0.5; % spacing wrt wavelength
beamwidth = 2/(N*d); % null-to-null (LL BW is half this)
D=d*(-(N-1)/2:1:(N-1)/2); % element locations
ang = pi*(-1:0.001:1);
u = cos(ang);
n2=size(u,2);
AS = exp(-1i*2*pi*cos(90/180*pi)*D'); % BP points to 90 (broadside)
Au = exp(-1i*2*pi*D'*u);
B = real(AS'*Au)/N;
G = 20*log10((abs(B)));
h=polardb(ang,G,-40);
```
{% endnote %}
<a id="fig.1-3-4"></a>
![图 1-3-4 $d = \lambda/2, N=10$,线阵的 $\left|\boldsymbol{\varUpsilon}_\psi(\psi)\right|$](../images/post/2023-04-20-josh-oap-part-1-3/2023-04-20-josh-oap-part-1-3-040-AbsOfFWRFForALinearArray.svg){width=1000px}
{% note primary MATLAB Code %}
``` matlab fig2_18.m
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Figure 2.18
% beam patterns in different spaces
% Lillian Xiaolan Xu
% Last updated 09/07/2000
% updated by K. Bell 7/22/01, 10/4/01
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear all
close all
N = 10;
n = (-(N-1)/2:(N-1)/2).';
psi = pi*(-3:0.001:3);
w = 1/N*[ones(N,1)];
d = 1/2;
vv = exp(1i*2*d*n*psi);
B = (abs(w'*vv));
u1=-1;
u2=3;
y1=0;
y2=1;
subplot(4,1,1)
plot(-psi/d,B);
hold on
axis([u1*pi/d u2*pi/d y1 y2])
set(gca,'XTick',[-pi/d 0 pi/d 2*pi/d 3*pi/d])
set(gca,'YTick',[0 0.5 1])
set(gca,'XTickLabel',{'$-\pi/d$';'$0$';'$\pi/d$';'$2\pi/d$';'$3\pi/d$'}, ...
'TickLabelInterpreter','latex')
grid on
point=0.8;
point_up=0.84;
point_down=0.76;
plot([-pi/d pi/d],[point point],'--')
plot([-1*pi/d -0.9*pi/d],[point point_up])
plot([-1*pi/d -0.9*pi/d],[point point_down])
plot([0.9*pi/d pi/d],[point_up point])
plot([0.9*pi/d pi/d],[point_down point])
text(-0.3*pi/d,1.2,'Visible region')
plot([pi/d 3*pi/d],[point point],'--')
plot([pi/d 1.1*pi/d],[point point_up])
plot([pi/d 1.1*pi/d],[point point_down])
plot([2.9*pi/d 3*pi/d],[point_up point])
plot([2.9*pi/d 3*pi/d],[point_down point])
text(1.7*pi/d,1.2,'Virtual region')
legend({'$k_z$-space'},'Interpreter','latex')
subplot(4,1,2)
plot(psi,B);
hold on
axis([u1*pi u2*pi y1 y2])
set(gca,'XTick',[-pi 0 pi 2*pi 3*pi])
set(gca,'YTick',[0 0.5 1])
set(gca,'XTickLabel',{'$-\pi$';'$0$';'$\pi$';'$2\pi$';'$3\pi$'}, ...
'TickLabelInterpreter','latex')
grid on
legend({'$\psi$-space'},'Interpreter','latex')
subplot(4,1,3)
plot(psi/pi,B);
hold on
axis([u1 u2 y1 y2])
set(gca,'XTick',[-1 0 1 2 3])
set(gca,'YTick',[0 0.5 1])
grid on
legend({'$u$-space'},'Interpreter','latex')
theta = -180:0.1:360;
vv = exp(1i*2*d*n*pi*cos(theta/180*pi));
B = (abs(w'*vv));
subplot(4,1,4)
plot(theta,B);
hold on
axis([-180 180 y1 y2])
set(gca,'XTick',[-180 -90 0 90 180])
set(gca,'YTick',[0 0.5 1])
set(gca,'XTickLabel',{'$180^\circ$';'$90^\circ$';'$0^\circ$';'$-90^\circ$'; ...
'$-180^\circ$'},'TickLabelInterpreter','latex')
grid on
legend({'$\theta$-space'},'Interpreter','latex')
set(gcf,'Position',[0 0 800 800])
```
{% endnote %}
{% note info %}
虽然以上例子比较简单,但是可以用来展示线性阵列的一些重要特征。
{% endnote %}
# 波束方向图的参数
&emsp;&emsp;波束方向图的重要特征可以使用波束方向图的参数来描述。
1. 3dB 带宽(半功率波束宽度,half-power beamwidth,HPBW)
2. 到第一零点的距离(这个距离的两倍称为 $BW_{NN}$)
3. 到第一旁瓣的距离
4. 第一旁瓣的高度
5. 其余零点的位置
6. 旁瓣衰减的速率
7. 栅瓣(Grating lobes)
## 半功率波束宽度
&emsp;&emsp;为了说明前两个参数,考虑在[图 1-3-5](#fig.1-3-5) 中给出的原点附近的波束方向图。
<a id="fig.1-3-5"></a>
![图 1-3-5 波束方向图的主波束](../images/post/2023-04-20-josh-oap-part-1-3/2023-04-20-josh-oap-part-1-3-050-MainLobeOfBeamPattern.svg){width=700px}
{% note primary MATLAB Code %}
``` matlab fig2_19.m
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Figure 2.19
% Main lobe of beam pattern
% Kristine Bell
% Last updated 6/4/01, 10/4/01
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% bp_sect - plots conventional bp with sector
clear all
% close all
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Uniform Linear Array
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
N = 10; % Elements in array
d = 0.5; % spacing wrt wavelength
beamwidth = 2/(N*d); % null-to-null (LL BW is half this)
D=d*(-(N-1)/2:1:(N-1)/2); % element locations
u = -0.45:0.01:0.45;
AS = exp(-1i*2*pi*D'*0); % BP points to 0
Au = exp(-1i*2*pi*D'*u);
B = real(AS'*Au)/N; % BP
h=plot(u,B,'-');
set(h,'LineWidth',1.5)
hold on
% HPBW
I=find(B>=0.707);
plot([u(min(I)-1) u(max(I)+1)],[B(min(I)-1) B(max(I)+1)],'-')
plot(u(min(I)-1)*[1 1],B(min(I)-1)*[1 1]+0.03*[-1 1],'-')
plot(u(max(I)+1)*[1 1],B(max(I)+1)*[1 1]+0.03*[-1 1],'-')
plot([0.03 0.13],[0.72 0.845],'-')
text(0.155,0.84,'$\Delta u_1 = $HPBW','Interpreter','latex');
% BW-NN
plot([-0.2 0.2],[-0.3 -0.3],'-')
plot(-0.2*[1 1],-0.3*[1 1]+0.03*[-1 1],'-')
plot(0.2*[1 1],-0.3*[1 1]+0.03*[-1 1],'-')
text(-0.05,-0.35,'$\Delta u_2 = BW_{NN}$','Interpreter','latex');
% axes
plot([-1 1 ],[0 0],'-')
plot([0 0],[-0 1.1],'-')
% tick marks
plot(-0.4*[1 1],0.03*[-1 1])
plot(-0.2*[1 1],0.03*[-1 1])
plot(0.2*[1 1],0.03*[-1 1])
plot(0.4*[1 1],0.03*[-1 1])
yy = -0.1;
%tick labels
text(-0.45,yy,'$-2\frac{\lambda}{ND}$','Interpreter','latex');
text(-0.21,yy,'$-\frac{\lambda}{ND}$','Interpreter','latex');
text(-0.005,yy,'0','Interpreter','latex');
text(0.18,yy,'$\frac{\lambda}{ND}$','Interpreter','latex');
text(0.38,yy,'$2\frac{\lambda}{ND}$','Interpreter','latex');
text(0.01,1.1,'$B(u)$','Interpreter','latex')
hold off
axis([-0.42 0.42 -0.4 1.2])
set(gca,'Visible','off')
```
{% endnote %}
&emsp;&emsp;3dB 波束宽度是波束宽度的一个度量。定义为对应 $\left| B_u(u) \right|^2 = 0.5$ 或 $\left| B_u(u) \right| = 1/\sqrt{2}$ 的点。可以通过令波束方向图 $B_u(u)$(式 $\eqref{BeamPatternOfUWLAInDirectionCosineDomain}$)等于 $1/\sqrt{2}$,来求出 $u$ 空间的半功率点。对于 $N\geqslant 10$,通过解下面的方程可以得到一个很好的近似:
$$\begin{equation}
\frac{\pi N d}{\lambda} u = 1.4
\end{equation}$$
即有
<a id="ApproximationOfHPBW"></a>
$$\begin{equation} \label{ApproximationOfHPBW}
\Delta u_1 = 0.891 \frac{\lambda}{N d}
\end{equation}$$
我们把这个间隔称为**{% label primary @半功率波束宽度(half-power beamwidth,HPBW) %}**。当 $N$ 增加时,式 $\eqref{ApproximationOfHPBW}$ 中的常系数会稍稍减小。对于 $N > 30$,$0.886 \lambda/Nd$ 是一个更好的近似表达式。
&emsp;&emsp;[表 1-3-1](#table.1-3-1) 中列出了不同空间内 HPBW 的表达式。
<a id="table.1-3-1"></a>
<center><font color=#999>表 1-3-1 各个空间的半功率波束宽度</font></center>
|空间| 任意 $d$ | $d=\lambda/2$ |
| :--: | :------: | :------: |
| $u$ | $0.891 \frac{\lambda}{Nd}$ | $1.782 \frac{1}{N}$ |
| $\bar{\theta}$ [^1] | $2\sin^{-1} \left( 0.446 \frac{\lambda}{Nd} \right)$ | $2\sin^{-1} \left( 0.891 \frac{1}{N} \right)$ |
| 较小的 $\bar{\theta}$ | $\simeq 0.891 \frac{\lambda}{Nd}$ radians <br> $\simeq 51.05 \frac{\lambda}{Nd}$ degrees | $\simeq 1.782 \frac{1}{N}$ radians <br> $\simeq 102.1 \frac{1}{N}$ degrees |
| $\psi$ | $0.891 \frac{2\pi}{N}$ | $0.891 \frac{2\pi}{N}$ |
| $k_z$ | $0.891 \frac{2\pi}{dN}$ | $1.782 \frac{2\pi}{\lambda N}$ |
[^1]: 侧射角(broadside angle)的定义为 $\bar{\theta} = \pi/2 - \theta$
## 第一零点波束宽度
&emsp;&emsp;方向图的零点出现在当波束方向图 $B_u(u)$(式 $\eqref{BeamPatternOfUWLAInDirectionCosineDomain}$)的分子为零而分母不为零时,即
$$\begin{equation}
\sin \left( \frac{\pi N d}{\lambda} u \right) = 0
\end{equation}$$
成立的条件为
$$\begin{equation}
\frac{\pi N d}{\lambda} u = m\pi, \quad m = 1,2,\cdots
\end{equation}$$
则出现零点需要满足下面的两个条件:
$$\begin{equation}
u = m \frac{\lambda}{Nd}, \quad m = 1,2,\cdots
\end{equation}$$
且
$$\begin{equation}
u \ne m \frac{\lambda}{d}, \quad m = 1,2,\cdots
\end{equation}$$
则第一个零点的位置为 $\lambda/Nd$,即有
$$\begin{equation}
\Delta u_2 = 2 \frac{\lambda}{Nd}
\end{equation}$$
我们把 $\Delta u_2$ 称为零点-零点波束宽度(null-to-null beamwidth),用 $BW_{NN}$ 表示。 $BW_{NN}$ 的一半是到第一零点的距离 ($0.5 BW_{NN}$) 。这个量能够衡量阵列分辨两个不同平面波的能力,也称为{% label primary @瑞利限(Rayleigh resolution limit) %}。如果第二个波束方向图的峰值在第一个波束方向图的第一零点之外(间隔 $\geqslant \Delta u_2 / 2$),则认为这两个平面波是可以分辨的。在后面,我们将研究一个阵列的分辨能力的统计性度量。
{% note warning %}
注意到线阵在方位角方向($\varphi$)没有分辨能力,因为该阵列在 $x$ 和 $y$ 方向上没有扩展。我们将在后面详细讨论分辨率的问题。
{% endnote %}
&emsp;&emsp;[表 1-3-2](#table.1-3-2)中列出了在各个不同空间表示出的 $BW_{NN}$。
<a id="table.1-3-2"></a>
<center><font color=#999>表 1-3-2 各个空间的第一零点波束宽度</font></center>
|空间| 任意 $d$ | $d=\lambda/2$ |
| :--: | :------: | :------: |
| $u$ | $2 \frac{\lambda}{Nd}$ | $\frac{4}{N}$ |
| $\bar{\theta}$ | $2\sin^{-1} \left( \frac{\lambda}{Nd} \right)$ | $2\sin^{-1} \left( \frac{2}{N} \right)$ |
| 较小的 $\bar{\theta}$ | $\simeq 2 \frac{\lambda}{Nd}$ radians | $\simeq \frac{4}{N}$ radians |
| $\psi$ | $\frac{4\pi}{N}$ | $\frac{4\pi}{N}$ |
| $k_z$ | $\frac{4\pi}{dN}$ | $\frac{8\pi}{\lambda N}$ |
## 旁瓣的位置及其衰减速率
&emsp;&emsp;旁瓣极大值的位置出现在当波束方向图 $B_\psi(\psi)$(式 $\eqref{BeamPatternOfUWLAInWaveNumberDomain}$)中的分子逼近极大值的时候:
$$\begin{equation}
\sin \left( \frac{N \psi}{2} \right) = 1
\end{equation}$$
则此时有
$$\begin{equation}
\frac{N \psi}{2} = \pm \left( 2m+1 \right)\frac{\pi}{2}, \quad m = 1,2,\cdots
\end{equation}$$
也即在 $\psi$ 空间有
$$\begin{equation}
\psi = \pm \frac{2m+1}{N}\pi
\end{equation}$$
也即在 $u$ 空间有
$$\begin{equation}
u = \pm \frac{2m+1}{N}\frac{\lambda}{2d}
\end{equation}$$
则第一旁瓣的峰值出现在
$$\begin{equation}
\psi = \pm \frac{2\pi}{N}
\end{equation}$$
由于在极大值时,波束方向图 $B_\psi(\psi)$(式 $\eqref{BeamPatternOfUWLAInWaveNumberDomain}$)中的分子趋近为 1,因此极大值为
$$\begin{equation}
B_\psi \left( \pm \frac{3\pi}{N} \right) \approx \frac{1}{N \sin \left( \frac{3\pi}{2N} \right)}
\end{equation}$$
对于较大的 $N$,这个表达式可以进一步近似为
$$\begin{equation}
B_\psi \left( \pm \frac{3\pi}{N} \right) \approx \frac{3}{2\pi}
\end{equation}$$
计算得 -13.5dB。
{% note warning %}
这意味着一个信号如果在这个旁瓣的位置入射,且比位置在 $k_z = 0$ 的信号大 13.5dB,则这两个信号将产生相同的响应。主要的旁瓣出现在 $k_z = \pm(2m + 1) \pi/Nd$,旁瓣的水平衰减速率为 $1/(2m + 1)$。例如,第二旁瓣的高度为 -17.9dB。在实际中,这种旁瓣水平的分辨能力是不能被接受的,所以很少使用均匀加权。旁瓣控制在确定性阵列和自适应阵列设计中都是特别重要的问题。
{% endnote %}
## 栅瓣(Grating lobes)
<a id="fig.1-3-6"></a>
![图 1-3-6 阵元间距对波束方向图的影响:(a) $d=\lambda/4$;(b) $d=\lambda/2$;(c) $d=\lambda$](../images/post/2023-04-20-josh-oap-part-1-3/2023-04-20-josh-oap-part-1-3-060-%20EffectOfElementSpacingOnBeamPattern.svg){width=1000px}
{% note primary MATLAB Code %}
``` matlab fig2_20.m
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Figure 2.20
% Effect of element spacing on beam pattern
% Xin Zhang
% Lillian Xu updated 09/2000
% updated by K. Bell 7/22/2001, 10/4/01
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear all
close all
N = 10;
n = (-(N-1)/2:(N-1)/2).';
psi = pi*(-3:0.001:3);
w = 1/N*[ones(N,1)];
d = [1/4 1/2 1];
figure
for k =1:length(d)
vv = exp(1i*2*d(k)*n*psi);
B(k,:) = 20*log10(abs(w'*vv));
subplot(3,1,k)
plot(psi/pi,B(k,:));
hold on
plot([-1 -1],[-25 0],'--');
plot([1 1],[-25 0],'--');
axis([-3 3 -25 5])
set(gca,'YTick',[-25 -20 -15 -10 -5 0])
grid on
xlabel('$u$','Interpreter','latex')
if k == 1
plot([-1 1],[2.5 2.5])
plot([-1 -0.9],[2.5 0.5])
plot([-1 -0.9],[2.5 4.5])
plot([0.9 1],[0.5 2.5])
plot([0.9 1],[4.5 2.5])
text(-0.4,7,'Visible region')
end
hold off
end
set(gcf,'Position',[0 0 800 600])
```
{% endnote %}
&emsp;&emsp;在[图 1-3-6](#fig.1-3-6) 中,针对多种 $d/\lambda$ 的值,画出了 $\left| \boldsymbol{\varUpsilon}_u(u) \right|$。图中说明了“栅瓣”这个重要的概念,即和主波束一样高的波瓣。栅瓣发生在当波束方向图 $B_\psi(\psi)$(式 $\eqref{BeamPatternOfUWLAInWaveNumberDomain}$)中的分子和分母均为零的时候。栅瓣出现的间隔为
$$\begin{equation}
\frac{\psi}{2} = m \cdot \pi
\end{equation}$$
也即
$$\begin{equation}
\psi = m \cdot 2 \pi
\end{equation}$$
也即
$$\begin{equation}
u = m \cdot \frac{\lambda}{d}
\end{equation}$$
&emsp;&emsp;如果阵列的间距大于 $\lambda$,则栅瓣的峰值出现在信号传播区域以内,即在 $\left| u \right| \leqslant 1$ 的区域以内。这里就会出现峰值响应模糊的问题,只有当我们对信号的入射方向有先验信息的时候,才可能解决这个问题。
&emsp;&emsp;下一节将讨论阵列调向的问题,阵列调向使得在 $u$ 空间的频率-波数响应函数 $\left| \boldsymbol{\varUpsilon}_u(u) \right|$ 发生平移,这种平移导致栅瓣进入了可视区域以内。我们发现,如果阵列需要的调向范围为 $0^\circ \leqslant \theta \leqslant 180^\circ$ 则需要
$$\begin{equation}
\frac{d}{\lambda} \leqslant \frac{1}{2}
\end{equation}$$
也即
$$\begin{equation}
\lambda \leqslant \frac{\lambda}{2}
\end{equation}$$
&emsp;&emsp;通常,我们考虑满足 $d \leqslant \lambda/2$ 的阵列,并假设需要在整个球内进行调向。我们把满足 $d = \lambda/2$ 的均匀线阵称为**{% label primary @标准线阵(standard linear array) %}**。
{% note info %}
在时间序列分析中,当对时域波形欠采样时,会出现混迭问题。栅瓣的问题和时域混迭问题是等同的。
{% endnote %}
# 参考文献
1. Harry L. Van Trees. *Optimum array processing: Part IV of detection, estimation, and modulation theory.* New York, NY, USA: John Wiley & Sons, 2002.
2. Harry L. Van Trees, 汤俊. *最优阵列处理技术.* 北京:清华大学出版社. 2008.
@@ -0,0 +1,423 @@
---
title: "Josh's Note — 最优阵列处理<br>Part 1.4 阵列调向"
mathjax: true
comments: true
copyright: true
toc:
enable: true
number: true
wrap: true
expand_all: true
max_depth: 4
tags:
- 阵列信号处理
- 阵列调向
- 主响应轴
- 端射
- 侧射
- 扫描极限
- 可视区域
categories:
- - Josh 的学习笔记
- 最优阵列处理
- 阵列和空域滤波器
abbrlink: c2604c43
date: 2023-04-22 18:17:52
---
&emsp;&emsp;[1.1 节][]、[1.2 节][]和 [1.3 节][]已经考虑了最大响应在正侧向(broadside),即 $k_z=0$ 的阵列。在大多数应用中,我们希望能够把最大响应放置到,或者说调向(steer)到任意一个波数位置或方向上。有两种方法可以实现这个目标。直接的方法是改变传感器的位置,使得阵列的轴线和目标方向之间是垂直的,称为机械调向(mechanical steering)。当一个天线在物理上是可旋转的时候,我们可以采取这种方法,如雷达系统中抛物面孔径。通常机械调向的实现有很大的困难,原因可能是当处理长波长信号时所需阵列的物理维度较大,也可能是当传感器被移动时需要进行重新校准。
&emsp;&emsp;另外一个方法是引入时间延时(或在窄带的情况下,引入相移)来实现对一个阵列的**{% label primary @主响应轴 (main response axis,MRA) %}**进行调向。随着高速信号处理器的发展,电子调向(electronic steering)技术正在被更广泛地应用在阵列处理中,其不仅仅突破了机械调向的限制,还具有迅速改变响应函数的灵活能力。此外,在有些阵列中,在一个方向上采用机械调向,在其他的方向上采用电子调向。
&emsp;&emsp;本文首先考虑任意结构阵列,然后讨论均匀加权阵列的结果。
<!-- more -->
# 任意结构阵列的调向
<a id="fig.1-4-1"></a>
![图 1-4-1 利用延时实现阵列调向](../images/post/2023-04-22-josh-oap-part-1-4/2023-04-22-josh-oap-part-1-4-010-ArraySteeringWithDelays.png){width=700px}
&emsp;&emsp;[1.2 节][]开头的简单例子说明了把阵列调向某个特定方向的主要思想,调向在波数空间的影响是很直接的。考虑[图 1-4-1](#fig.1-4-1) 中的处理器,输入到调向环节的基函数为
$$\begin{equation}
f\left( t, \boldsymbol{p}\right) = e^{j\omega t} \boldsymbol{v}_{\boldsymbol{k}}\left(\boldsymbol{k}\right)
\end{equation}$$
我们希望当波数等于“目标”的波数时,即
$$\begin{equation}
\boldsymbol{k} = \boldsymbol{k}_\mathrm{T}
\end{equation}$$
输出是对齐的。我们把 $\boldsymbol{k}_\mathrm{T}$ 称为**{% label primary @所调方向(steering direction) %}**或在 $k$ 空间的**{% label primary @主响应轴(main response axis) %}**。可以使用一个 $N \times N$ 的对角调向矩阵(diagonal steering matrix)来完成这个操作
<a id="DiagonalSteeringMatrix"></a>
$$\begin{equation}
\boldsymbol{I}_\mathrm{s}\left(\boldsymbol{k}_\mathrm{T}\right) = \left[ \begin{matrix}
e^{j \boldsymbol{k}^\mathrm{T}_\mathrm{T}\boldsymbol{p}_1} & 0 & \cdots & 0 \\
0 & e^{j \boldsymbol{k}^\mathrm{T}_\mathrm{T}\boldsymbol{p}_2} & \cdots & 0 \\
\vdots & \vdots & & \vdots \\
0 & 0 & \cdots & e^{j \boldsymbol{k}^\mathrm{T}_\mathrm{T}\boldsymbol{p}_N}
\end{matrix} \right]
\end{equation}$$
得到的输出为
$$\begin{equation}
f_\mathrm{s}\left( t, \boldsymbol{p}\right) = e^{j\omega t} \boldsymbol{v}_{\boldsymbol{k}}\left(\boldsymbol{k} - \boldsymbol{k}_\mathrm{T}\right)
\end{equation}$$
总的频率-波数响应为
$$\begin{equation}
\boldsymbol{\varUpsilon} \left(\left. \omega, \boldsymbol{k} \right| \boldsymbol{k}_\mathrm{T} \right) = \boldsymbol{\varUpsilon} \left( \omega, \boldsymbol{k} - \boldsymbol{k}_\mathrm{T} \right)
\end{equation}$$
{% note info %}
阵列的响应函数仅是简单地平移到 $\boldsymbol{k}_\mathrm{T}$ 的位置,这是利用波数空间来解释阵列响应函数的好处之一。如果在波数空间考虑波束方向图,也会得到一个简单的平移关系。
{% endnote %}
# 均匀幅度加权的情况
&emsp;&emsp;当采用均匀幅度加权时,在[图 1-4-1](#fig.1-4-1) 中的两步的过程是不必要的。令
$$\begin{equation}
\boldsymbol{w} = \frac{1}{N} \boldsymbol{v}_{\boldsymbol{k}}\left(\boldsymbol{k}_\mathrm{T}\right)
\end{equation}$$
则有
$$\begin{equation}
B_\mathrm{c} \left( \boldsymbol{k}, \boldsymbol{k}_\mathrm{T} \right) = \frac{1}{N} \boldsymbol{v}_{\boldsymbol{k}}^\mathrm{H} \left(\boldsymbol{k}_\mathrm{T}\right) \boldsymbol{v}_{\boldsymbol{k}}\left(\boldsymbol{k}\right)
\end{equation}$$
称 $B_c \left( \boldsymbol{k}, \boldsymbol{k}_\mathrm{T} \right)$ 为**{% label primary @常规波束方向图(conventional beam pattern) %}**。我们将发现常规波束方向图是后面要讨论的很多最优处理内容的基础。
# 均匀线性阵列的调向
&emsp;&emsp;线性阵列的常规波束方向图为
$$\begin{equation}
B_{\psi\mathrm{c}}\left( \psi : \psi_\mathrm{T} \right) = \frac{1}{N} \boldsymbol{v}_\psi^\mathrm{H} \left(\psi_\mathrm{T}\right) \boldsymbol{v}_\psi\left(\psi\right)
\end{equation}$$
$$\begin{equation}
B_{u\mathrm{c}}\left( u : u_\mathrm{T} \right) = \frac{1}{N} \boldsymbol{v}_u^\mathrm{H} \left(u_\mathrm{T}\right) \boldsymbol{v}_u\left(u\right)
\end{equation}$$
对于均匀线性阵列(阵元间距相同),有
$$\begin{equation}
B_{\psi\mathrm{c}}\left( \psi : \psi_\mathrm{T} \right) = \frac{1}{N} \frac{\sin\left( N \frac{\psi-\psi_\mathrm{T}}{2} \right)}{\sin\left(\frac{\psi-\psi_\mathrm{T}}{2} \right)} \label{SteeredBeamPatternInWavenumberDomain}
\end{equation}$$
$$\begin{equation}
B_{u\mathrm{c}}\left( u : u_\mathrm{T} \right) = \frac{1}{N} \frac{\sin\left[ \frac{\pi Nd}{\lambda} (u - u_\mathrm{T}) \right]}{\sin\left[ \frac{\pi d}{\lambda} (u - u_\mathrm{T}) \right]} \label{SteeredBeamPatternInDirectionCosineDomain}
\end{equation}$$
式 $\eqref{SteeredBeamPatternInWavenumberDomain}$ 或式 $\eqref{SteeredBeamPatternInDirectionCosineDomain}$ 均对应方向图的平移,其形状并没有改变。这种没有畸变的平移性质是在 $\psi$ 空间或 $u$ 空间处理的众多优点之一。
&emsp;&emsp;当我们对阵列调向,并使得主响应轴对准 $\bar{\theta}_0$ 时(其中 $\bar{\theta}_0$ 是从正侧向(broadside)测得的角度),波束方向图将发生平移,使得中心峰值位于 $u_0 = \sin\bar{\theta}_0$。同时,这个平移也**使栅瓣发生移动**。
&emsp;&emsp;[图 1-4-2](#fig.1-4-2) 说明了调向对波束方向图的影响。[图 1-4-2(a)](#fig.1-4-2) 给出了 $d=2\lambda/3$ 和 $\bar\theta = 30^\circ$ 时的波束方向图。我们看到,在这种调向的情况下,栅瓣位于可视区域的边缘。[图 1-4-2(b)](#fig.1-4-2) 给出了 $d=\lambda/2$ 和 $\bar\theta = 90^\circ$ 时的波束方向图,栅瓣同样位于可视区域的边缘。
<a id="fig.1-4-2"></a>
![图 1-4-2 阵列调向对栅瓣的影响:$N=10$,(a) $d=2\lambda/3, \bar\theta = 30^\circ$;(b) $d=\lambda/2, \bar\theta = 90^\circ$](../images/post/2023-04-22-josh-oap-part-1-4/2023-04-22-josh-oap-part-1-4-020-%20EffectOfSteeringOnTheGratingLobes.svg){width=1000px}
{% note primary MATLAB Code%}
``` matlab fig2_22.m
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Figure 2.22
% Effect of element spacing on beam pattern
% Lillian Xu
% Last updated by K. Bell 7/22/01, 10/4/01
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear all
close all
N=10;
n=(-(N-1)/2:(N-1)/2)';
w=ones(N,1)/N;
u=-3:0.01:3;
d=[2/3 1/2];
theta=[30 90];
figure
s = ['(a)';'(b)'];
for m=1:2
beam=(w.*exp(1i*2*pi*n*d(m)*sin(theta(m)/180*pi)))' ...
*exp(1i*2*pi*n*d(m)*u);
subplot(2,1,m);
plot(u,20*log10(abs(beam)));
hold on
axis([-3 3 -25 5])
ylabel('Beam pattern (dB)')
xlabel('$u$','Interpreter','latex')
text(0,-32,s(m,:),'HorizontalAlignment','center')
% title(['N=',num2str(N),', d=',num2str(d(m),2),' lambda, theta-Bar=', ...
% num2str(theta(m)),' degrees'])
grid on
end
set(gcf,'Position',[0 0 800 600])
```
{% endnote %}
&emsp;&emsp;通常,为了避免栅瓣进入可视区域,需要有
$$\begin{equation}
\frac{d}{\lambda} \leqslant \frac{1}{1 + \left| \sin\bar\theta_{\max} \right|}
\end{equation}$$
其中, $\bar\theta_{\max}$ 是阵列将要调向的最大角度。这个结果可以令 $\bar\theta_\mathrm{T} = \bar\theta_{\max}$,计算第一个栅瓣的位置和 $\frac{d}{\lambda}$ 的关系而得到。所以,如果阵列需要的所调方向为 $-90^\circ \leqslant \bar\theta \leqslant 90^\circ$,则有
$$\begin{equation}
d \leqslant \frac{\lambda}{2}
\end{equation}$$
{% note warning %}
虽然研究在 $\psi$ 空间或 $u$ 空间的特性是很有用的,但必须要注意信号实际是从 $(\theta, \varphi)$ 空间产生的,我们需要理解在这个空间的特性,这一点很重要。
{% endnote %}
&emsp;&emsp;在 $\theta$ 空间(即角度空间),有
$$\begin{equation}
B_{\theta\mathrm{c}}\left( \theta : \theta_\mathrm{T} \right) = \frac{1}{N} \frac{\sin\left[ \frac{\pi Nd}{\lambda} (\cos\theta - \cos\theta_\mathrm{T}) \right]}{\sin\left[ \frac{\pi d}{\lambda} (\cos\theta - \cos\theta_\mathrm{T}) \right]} \label{SteeredBeamPatternInAngleDomain}
\end{equation}$$
我们在 $\theta$ 空间画出 $B_{\theta\mathrm{c}}$,由于和 $\theta$ 的关系,方向图的形状将随之发生改变。[图 1-4-3](#fig.1-4-3) 给出了 $\theta_\mathrm{T} = 30^\circ$ 和 $d=\lambda/2$ 的波束方向图。把这个方向图和[图 1-3-3][] 中的方向图进行比较,
可以看到主波束的波束宽度有所增加。
<a id="fig.1-4-3"></a>
![图 1-4-3 10 阵元均匀阵列($d = \lambda/2$)扫描到 30°(和正侧向夹角为 60°)时的波束方向图](../images/post/2023-04-22-josh-oap-part-1-4/2023-04-22-josh-oap-part-1-4-030-BeamPatternFor10ElementUniformArrayScannedTo30Degree.svg){width=800px}
{% note primary MATLAB Code %}
``` matlab fig2_23.m
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Figure 2.23
% Beam pattern for 10-element uniform array (d=lambda/2)
% scanned to 30 degrees (60 degrees from broadside)
% Xin Zhang 1/20/99
% Last updated by K. Bell 6/25/01
% Functions called: polardb
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear all
close all
N = 10;
n = (-(N-1)/2:(N-1)/2).';
theta = pi*(-1:0.001:1);
u = cos(theta);
d = 1/2;
vv = exp(1i*2*pi*d*n*u);
theta_T = 30/180*pi;
w = 1/N*ones(N,1).*exp(1i*n*pi*cos(theta_T));
B = w'*vv;
B = 10*log10(abs(B).^2);
figure
h=polardb(theta,B,-40);
hold off
```
{% endnote %}
&emsp;&emsp;为了研究在 $\theta$ 空间的半功率带宽情况,我们利用式 $\eqref{SteeredBeamPatternInAngleDomain}$ 和 [$N \geqslant 10$ 时半功率带宽的估算式][],可以得到在 $u$ 空间的左右半功率点分别为
$$\begin{equation}
u_\mathrm{L} = u_\mathrm{T} - 0.450 \frac{\lambda}{Nd}
\end{equation}$$
$$\begin{equation}
u_\mathrm{R} = u_\mathrm{T} + 0.450 \frac{\lambda}{Nd}
\end{equation}$$
或在 $\theta$ 空间($\theta_\mathrm{L}$ 对应 $u_\mathrm{R}$,$\theta_\mathrm{R}$ 对应 $u_\mathrm{L}$)有
$$\begin{equation}
\cos\theta_\mathrm{R} = \cos\theta_\mathrm{T} - 0.450 \frac{\lambda}{Nd}
\end{equation}$$
$$\begin{equation} \label{LeftHalfPowerPointInAngleDomain}
\cos\theta_\mathrm{L} = \cos\theta_\mathrm{T} + 0.450 \frac{\lambda}{Nd}
\end{equation}$$
所以,对于 $0 \leqslant \theta \leqslant \pi$,$\theta_\mathrm{L}, \theta_\mathrm{R} \geqslant 0$,在 $\theta$ 空间的半功率波束宽度为
$$\begin{equation} \label{HPBWOfUWLA}
\theta_\mathrm{H} = \theta_\mathrm{R} - \theta_\mathrm{L} = \cos^{-1} \left[ \cos\theta_\mathrm{T} - 0.450 \frac{\lambda}{Nd} \right] - \cos^{-1} \left[ \cos\theta_\mathrm{T} + 0.450 \frac{\lambda}{Nd} \right]
\end{equation}$$
&emsp;&emsp;除了当 $\theta_\mathrm{T} = 0$ 或 $\pi$(端射,endfire,信号入射方向与阵元排布方向平行)的情况,定义 $\theta_\mathrm{L}$ 为最接近 $\theta = 0$ 的半功率点。当波束从正侧向($\theta_\mathrm{T} = \pi/2$)调向 $z$ 轴的正半轴(端射,$\theta_\mathrm{T} = 0$)时,波束变宽。在某点上,如式 $\eqref{LeftHalfPowerPointInAngleDomain}$
中所示,$\theta_\mathrm{L}$ 等于 0。在该点以外,在波束的那一边再也没有半功率点。 Elliott[^1] 把这个点称为扫描极限(scan limit)。
&emsp;&emsp;Elliot [^1] 画出了式 $\eqref{HPBWOfUWLA}$ 和式 $\eqref{HPBWOfEndfireUWLA}$ 中给出的波束宽度,并在[图 1-4-4](#fig.1-4-4) 中给出。
<a id="fig.1-4-4"></a>
![图 1-4-4 HPBW 和阵列调向角的关系:标准线阵,采用均匀加权](../images/post/2023-04-22-josh-oap-part-1-4/2023-04-22-josh-oap-part-1-4-040-HPBWVersusSteeringAngleStandardUWLA.svg){width=1000px}
{% note primary MATLAB Code %}
``` matlab fig2_24.m
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Figure 2.24
% HPBW versus steering angle
% Lillian Xu
% Modified by Xin Zhang
% Last updated by L. Xu 11/30/00, K. Bell 7/22/01, 10/4/01, 10/17/01
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear all;
close all;
Nd_set=[1000:-5:700 700:-0.5:200 200:-0.05:20 15:-0.005:1];
theta_deg=[2.5 5 10 20 30 45 90];
%theta_deg=[2.5 5 10 20 30 45 60 90];
theta_set=theta_deg*pi/180;
figure
for num=1:size(theta_set,2)
theta=theta_set(num);
bw=0;
for num1=1:size(Nd_set,2)
Nd=Nd_set(num1);
r=cos(theta)+0.443/Nd;
if abs(r)<=1
bw(num1)=acos(r)-acos(cos(theta)-0.443/Nd);
end
end
loglog(Nd_set(1:size(bw,2)),abs(bw*180/pi));
hold on
rightpoint=abs(bw(1)*180/pi);
text(1040,rightpoint,[num2str(theta_deg(num)),'$^\circ$'],Interpreter='latex'); % used to be 7
end
axis([1 1000 0.04 100])
xlabel('$Nd/\lambda$','Interpreter','latex')
ylabel('3-dB beamwidth in degrees')
scanlimit=-acos(1-2*0.443./Nd_set);
loglog(Nd_set,abs(scanlimit*180/pi),'--')
Endfire = 2*acos(1-0.433./Nd_set);
loglog(Nd_set,abs(Endfire*180/pi))
rightpoint=abs(Endfire(1)*180/pi);
text(1040,rightpoint,'$\theta=0^\circ$',Interpreter='latex'); % used to be 7
%title('HPBW versus steering angle: standard linear array with uniform weighting')
text(12,35,'Endfire')
text(12,14.4,'Scan limit')
text(12,1.8,'Broadside')
grid on;
set(gcf,'Position',[0 0 800 500])
```
{% endnote %}
&emsp;&emsp;当波束调向到正侧向的附近($\bar{\theta}_\mathrm{T}$ 的值很小)且 $Nd \gg \lambda$ 时,$\theta_\mathrm{H}$ 很小,利用小角度展开形式得到
$$\begin{equation} \label{HPBWWithSmallAngle}
\theta_\mathrm{H} \approx 0.891 \frac{\lambda}{Nd} \sec \bar\theta_\mathrm{T}
\end{equation}$$
式 $\eqref{HPBWWithSmallAngle}$ 的意义在[图 1-4-5](#fig.1-4-5) 中比较明显。有效的阵列长度缩减了 $\cos\bar\theta_\mathrm{T}$ 倍。
<a id="fig.1-4-5"></a>
![图 1-4-5 长度降低了 $\cos\bar\theta_\mathrm{T}$ 倍的等效阵列](../images/post/2023-04-22-josh-oap-part-1-4/2023-04-22-josh-oap-part-1-4-050-EffectiveArrayLength.png){width=600px}
&emsp;&emsp;对于 $Nd \geqslant 5\lambda$,在正侧向附近,式 $\eqref{HPBWWithSmallAngle}$ 的误差在 0.2% 以内,在扫描极限附近,误差在 4% 以内。
&emsp;&emsp;当 $\theta_\mathrm{T} = 0$ 或 $\pi$ 时,最大响应轴的指向沿着阵列的轴线,此时称为一个端射阵列(endfire array)。一个标准 10 阵元端射阵列的波束方向图在[图 1-4-6](#fig.1-4-6) 中给出。在这种情况下,有
$$\begin{equation} \label{HPBWOfEndfireUWLA}
\theta_\mathrm{H} = 2 \cos^{-1} \left[ 1 - 0.450 \frac{\lambda}{Nd} \right], \quad \theta_\mathrm{T} = 0 \text{或} \pi
\end{equation}$$
<a id="fig.1-4-6"></a>
![图 1-4-6 一个标准 10 阵元线阵。采用均匀幅度加权时在端射时的波束方向图](../images/post/2023-04-22-josh-oap-part-1-4/2023-04-22-josh-oap-part-1-4-060-BeamPatternOfStandard10ElementUWLAAtEndfire.svg){width=800px}
{% note primary MATLAB Code %}
``` matlab fig2_26.m
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Figure 2.26
% Beam pattern of a standard 10-element linear array
% with uniform amplitude weighting at end-fire
% Xin Zhang 1/20/99
% Last updated by K. Bell 6/25/01
% Functions called: polardb
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear all
close all
N = 10;
n = (-(N-1)/2:(N-1)/2).';
theta = pi*(-1:0.001:1);
u = cos(theta);
d = 1/2;
vv = exp(1i*2*pi*d*n*u);
theta_T = 0/180*pi;
w = 1/N*ones(N,1).*exp(1i*n*pi*cos(theta_T));
B = w'*vv;
B = 10*log10(abs(B).^2);
figure
h=polardb(theta,B,-40);
hold off
```
{% endnote %}
可以把式 $\eqref{HPBWOfEndfireUWLA}$ 写成
$$\begin{equation}
1 - \cos \left( \frac{\theta_\mathrm{H}}{2} \right) = 0.450 \frac{\lambda}{Nd}
\end{equation}$$
或
$$\begin{equation} \label{SineOfHPBWOfEndfireUWLA}
\sin \left( \frac{\theta_\mathrm{H}}{4} \right) = \sqrt{\frac{0.450}{2}\cdot \frac{\lambda}{Nd}}
\end{equation}$$
对于 $Nd \gg \lambda$,$\theta_\mathrm{H}$ 很小,则式 $\eqref{SineOfHPBWOfEndfireUWLA}$ 成为
$$\begin{equation} \label{ApproximationOfHPBWOfEndfireUWLA}
\theta_\mathrm{H} = 2 \sqrt{0.890 \frac{\lambda}{Nd}}
\end{equation}$$
对于 $Nd \gg 5\lambda$,式 $\eqref{ApproximationOfHPBWOfEndfireUWLA}$ 的误差小于 1%。
&emsp;&emsp;类似的,方向图的第一零点的位置为
$$\begin{equation}
\theta_\mathrm{null} = \sqrt{2 \frac{\lambda}{Nd}}
\end{equation}$$
&emsp;&emsp;所以,一个线阵在端射位置的分辨率随 $Nd/\lambda$ 的平方根的倒数变化,而在正侧向的时候是线性的关系。
# 参考文献
1. Harry L. Van Trees. *Optimum array processing: Part IV of detection, estimation, and modulation theory.* New York, NY, USA: John Wiley & Sons, 2002.
2. Harry L. Van Trees, 汤俊. *最优阵列处理技术.* 北京:清华大学出版社. 2008.
[1.1 节]: https://josh-gao.top/posts/8b61f5a7.html
[1.2 节]: https://josh-gao.top/posts/de20fd09.html
[1.3 节]: https://josh-gao.top/posts/aa32ec76.html
[图 1-3-3]: https://josh-gao.top/posts/aa32ec76.html#fig.1-3-3
[$N \geqslant 10$ 时半功率带宽的估算式]: https://josh-gao.top/posts/aa32ec76.html#ApproximationOfHPBW
[^1]: R. S. Elliott. *Antenna Theory and Design.* Prentice-Hall, Englewood Cliffs, New Jersey, 1981.
@@ -0,0 +1,522 @@
---
title: "Josh's Note — 最优阵列处理<br>Part 1.5 阵列性能度量指标"
mathjax: true
comments: true
copyright: true
toc:
enable: true
number: true
wrap: true
expand_all: true
max_depth: 4
tags:
- 阵列信号处理
- 阵列性能
categories:
- - Josh 的学习笔记
- 最优阵列处理
- 阵列和空域滤波器
abbrlink: 6a7100b0
date: 2023-04-24 11:50:37
---
&emsp;评估阵列性能的方法有很多,不同方法会量化阵列的不同重要特性,比如阵列对信号的响应,或是阵列的敏感度。在之前的讨论中,第一零点间距是波束宽度,也即频率-波数响应分辨率的度量指标;主旁瓣高度是均匀加权线阵的一种度量指标。本文讨论三个常用的阵列性能度量指标:
1. 方向性(Directivity)
2. 对空域自噪声的阵列增益 (Array gain versus spatially white noise,$A_w$)
3. 敏感度(Sensitivity)和容错因子(Tolerance Factor)
<!-- more -->
# 方向性
&emsp;&emsp;方向性是阵列和孔径常用性能度量指标。下面首先在给出一般情况下的定义,然后讨论线性阵列的特殊情况。
## 方向性的定义
&emsp;&emsp;定义**{% label primary @功率方向图(power pattern) %}** $P(\theta,\varphi)$ 为波束方向图 $B(\omega : \theta, \varphi)$ 幅度的平方,即
$$\begin{equation}
P(\theta,\varphi) = \left| B(\omega : \theta, \varphi) \right|^2
\end{equation}$$
其中省略了 $P(\theta,\varphi)$ 和频率的关系,则方向性 $D$ 定义为
$$\begin{equation}
D = \frac{P(\theta_\mathrm{T},\varphi_\mathrm{T})}{ \displaystyle\frac{1}{4\pi} \int_0^\pi \int_0^{2\pi} \sin \theta \cdot P(\theta,\varphi) \,\mathrm{d} \varphi \,\mathrm{d} \theta}
\end{equation}$$
其中 $(\theta_\mathrm{T},\varphi_\mathrm{T})$ 是主响应轴(main response axis,MRA)的指向。
- 对于发射天线,$D$ 代表最大发射密度(单位立体角发射功率)和平均发射密度(球面平均发射功率)的比值。
- 对于接收天线,分母代表阵列/孔径对全向噪声(在球内均匀分布的噪声)的输出噪声功率,分子代表从 $(\theta_\mathrm{T},\varphi_\mathrm{T})$ 方向入射的信号的功率,所以 $D$ 可以理解为对全向噪声的阵列增益。
&emsp;&emsp;假设权值做了归一化,使得 $P_n(\theta_\mathrm{T},\varphi_\mathrm{T}) = 1$,则方向性可以进一步写成
$$\begin{equation}
D = \left\{ \frac{1}{4\pi} \int_0^\pi \int_0^{2\pi} \sin \theta \cdot P(\theta,\varphi) \,\mathrm{d} \varphi \,\mathrm{d} \theta \right\}^{-1}
\end{equation}$$
## 线阵的情况
&emsp;&emsp;对于线性阵列,有
$$
B(\theta,\varphi) = B(\theta)
$$
则线阵的方向性
$$\begin{align}
D &= \left\{ \frac{1}{2} \int_0^\pi \left| B(\theta) \right|^2 \sin \theta \,\mathrm{d} \theta \right\}^{-1} \\
&= \left\{ \frac{1}{2} \int_{-1}^1 \left| B(u) \right|^2 \,\mathrm{d} u \right\}^{-1}
\end{align}$$
&emsp;&emsp;利用 [$u$ 空间的波束方向图的表达式][],$u$ 空间线阵的方向性可以用阵列权值表示为
$$
D = \left\{ \frac{1}{2} \int_{-1}^1 \sum_{n=0}^{N-1}w_n^\ast e^{jn\left( \frac{2\pi d}{\lambda} \right) \left( u - u_\mathrm{T} \right)} \sum_{m=0}^{N-1} w_m e^{-jm\left( \frac{2\pi d}{\lambda} \right) \left( u - u_\mathrm{T} \right)} \,\mathrm{d} u \right\}^{-1}
$$
其中 $u_\mathrm{T}$ 是 $u$ 空间内的阵列的所调方向。交换积分和求和的顺序,积分得到
$$\begin{equation} \label{DirectivityOfLA}
D = \left\{ \sum_{n=0}^{N-1} \sum_{m=0}^{N-1} w_m w_n^\ast e^{j \left( \frac{2\pi d}{\lambda} \right) (m-n) u_\mathrm{T} } \mathrm{sinc} \left( \frac{2\pi d}{\lambda} (n-m)\right) \right\}^{-1}
\end{equation}$$
&emsp;&emsp;为了使表达式更加简洁,定义几个矩阵。定义 $\mathbf{sinc}$ 矩阵的第 $n,m$ 个元素为
$$
\left[ \mathbf{sinc} \right]_{nm} \triangleq \mathrm{sinc} \left( \frac{2\pi d}{\lambda} (n-m)\right)
$$
[对角调向矩阵][] 在 $u$ 空间的表示形式为
$$
\boldsymbol{I}_{\mathrm{s}u} = \mathrm{diag}\left( 1, e^{j \frac{2\pi d}{\lambda}u_\mathrm{T}} , e^{j \frac{2\pi d}{\lambda} 2u_\mathrm{T}}, \cdots, , e^{j \frac{2\pi d}{\lambda}(N-1)u_\mathrm{T}} \right)
$$
则
$$\begin{equation}
D = \boldsymbol{I}_{\mathrm{s}u} \boldsymbol{w}^\mathrm{H} \left[ \mathbf{sinc} \right] \boldsymbol{w} \boldsymbol{I}_{\mathrm{s}u}^\mathrm{H}
\end{equation}$$
由于调向运算通常在权值矢量中包含[^1]
$$\begin{equation}
\boldsymbol{w}_\mathrm{s} = \boldsymbol{w}\boldsymbol{I}_{\mathrm{s}u}^\mathrm{H}
\end{equation}$$
则
$$\begin{equation}
D = \boldsymbol{w}_\mathrm{s}^\mathrm{H} \left[ \mathbf{sinc} \right] \boldsymbol{w}_\mathrm{s}
\end{equation}$$
## 标准线阵的情况
&emsp;&emsp;标准线阵(standard linear array)是我们所感兴趣的一个特殊情况。如果 $d = \lambda/2$,则方向性
$$
D = \left\{ \sum_{n=0}^{N-1} \sum_{m=0}^{N-1} w_m w_n^\ast e^{j \pi (m-n) u_\mathrm{T} } \mathrm{sinc} \left( \pi (n-m)\right) \right\}^{-1}
$$
当 $m = n$ 时,$\mathrm{sinc}$ 函数等于 1,当 $m \ne n$ 时,$\mathrm{sinc}$ 函数等于 0,所以方向性可以进一步简化为
$$\begin{equation}
D = \left\{ \sum_{n=0}^{N-1} \left| w_n \right|^2 \right\} = \left( \boldsymbol{w}^\mathrm{H}\boldsymbol{w} \right)^{-2} = \left\{ \left\| \boldsymbol{w} \right \|^2 \right\}^{-1}
\end{equation}$$
其中
$$\begin{equation}
\left\| \boldsymbol{w} \right \| = \left( \boldsymbol{w}^\mathrm{H}\boldsymbol{w} \right)^{\frac{1}{2}}
\end{equation}$$
是矢量 $\boldsymbol{w}$ 的 2-模。因此**标准线阵的方向性是权值矢量幅度平方的倒数**。且**标准线的方向性不依赖于阵列的指向**,当阵列指向从阵列的正侧向(broadside)移开时。波束变宽,但是 $\varphi$ 的积分范围减小。
&emsp;&emsp;对于 $d \ne \lambda/2$,利用式 $\eqref{DirectivityOfLA}$ 给出的线阵方向性的定义,方向性将和阵列的指向有关。
&emsp;&emsp;对于均匀加权的标准线阵(UWLA),$w_n = 1/N$,所以
$$
\sum_{n=0}^{N-1} \left| w_n \right|^2 = \frac{1}{N}
$$
所以
$$\begin{equation}
D = N
\end{equation}$$
&emsp;&emsp;均匀加权使得标准线阵的方向性最大,下面给出简单证明。
> &emsp;&emsp;采用 Lagrange 乘子法进行证明。待求解的问题可以表述为
>
> $$
> \min_{w_n} \sum_{n=0}^{N-1} \left| w_n \right|^2, \quad \mathrm{s.t.} \sum_{n=0}^{N-1} w_n = 1
> $$
>
> 约束条件保证了波束方向图在 $u_\mathrm{T}$ 方向的值为 1。令
>
> $$
> F = \sum_{n=0}^{N-1} \left| w_n \right|^2 + \lambda \left( \sum_{n=0}^{N-1} w_m - 1 \right)
> $$
>
> 其中 $\lambda$ 是 Lagrange 乘子。对 $w_n$ 求导,并令结果等于零,得到
>
> $$
> w_n^\ast = -\lambda
> $$
>
> 也即
>
> $$
> w_n = -\lambda^\ast
> $$
>
> 把所得结果代入约束条件,得到 $\lambda = -\displaystyle\frac{1}{N}$,则有
>
> $$
> w_n = \frac{1}{N}
> $$
>
> 此即为我们想要得到的结果。
{% note info %}
对于非均匀加权的情况,阵列的方向性总是减小的。它是以半波长度量的阵列长度的函数,加上一个由于非均匀加权而产生的部分。
{% endnote %}
&emsp;&emsp;一个**标准均匀加权线阵**的方向性可以和半功率带宽 HPBW,或者第一零点波束宽度$BW_{NN}$ 相联系起来。根据[各个空间的第一零点波束宽度表][], 有
$$\begin{equation}
D = \frac{4}{BW_{NN}}
\end{equation}$$
其中,$BW_{NN}$ 是在 $u$ 空间的值。
&emsp;&emsp;方向性经常用 dB 来表示,并称之为**{% label primary @方向性指数(directivity index) %}**:
$$\begin{equation}
DI = 10 \lg D
\end{equation}$$
可以把 $DI$ 写成
$$\begin{equation}
DI = 10 \lg N + 10 \lg(g(\boldsymbol{w}))
\end{equation}$$
其中第二项是权值的函数。对于非均匀加权($w_n \ne N^{-1}$),$DI$ 将会减小。
# 对空域白噪声的阵列增益($A_w$)
&emsp;&emsp;阵列处理的一个目标是通过相干地累加信号和不相干地累加噪声来改善**{% label primary @信噪比(signal-to-noise ratio,SNR) %}**,阵列增益可以度量信噪比的改善程度。这是阵列性能的一个重要度量指标,后面我们会深入地讨论这个问题。阵列增益的一般定义要到介绍了谱协方差矩阵(用于描述噪声过程的空域统计特性)后给出。这里仅给出阵列增益的一个应用范围受限的定义。
&emsp;&emsp;假设每个阵元的输入由一个从主响应轴入射的平面波和一个噪声过程组成,各阵元的噪声过程是不相关的(空域白噪声),则各阵元的输入信号
$$\begin{equation}
x_n (t) = f(t - \tau_n) + n_n(t), \quad n = 0,\cdots,N-1
\end{equation}$$
每个阵元上信号谱和噪声谱的比值,也即输入信噪比为
$$\begin{equation}
\mathrm{SNR}_\mathrm{in} (\omega) = \frac{S_f(\omega)}{S_n (\omega)}
\end{equation}$$
其中下标 “$\mathrm{in}$” 表示输入,假设每个阵元的噪声谱相同。
&emsp;&emsp;下面推导使用权值和输入谱矩阵来描述输出谱的表达式。根据[阵列输出的向量形式][], 有
$$
y(t) = \int_{-\infty}^{\infty} \boldsymbol{h}^\mathrm{T} (\tau) \boldsymbol{x}\left(t - \tau\right) \mathrm{d} \tau
$$
假设 $x(t)$ 是零均值宽平稳的,输出 $y(t)$ 的自相关函数
$$
R_{y}(\tau) = E[y(t)y^\ast(t-\tau)]
$$
$y(t)$ 的谱为
$$\begin{aligned}
S_y (\omega) &= \int_{-\infty}^{\infty} e^{-j\omega \tau} R_{y}(\tau) \, \mathrm{d} \tau \\
&= \int_{-\infty}^{\infty} e^{-j\omega\tau} \, \mathrm{d} \tau \int_{-\infty}^{\infty} \boldsymbol{h}^\mathrm{T} (\alpha) \, \mathrm{d} \alpha \int_{-\infty}^{\infty} E \left[ \boldsymbol{x} (t-\alpha) \boldsymbol{x}^\mathrm{H} (t-\tau-\beta)\right] \boldsymbol{h}^\ast(\beta) \, \mathrm{d} \beta \\
&= \int_{-\infty}^{\infty} \boldsymbol{h}^\mathrm{T} (\alpha) e^{-j\omega\alpha} \, \mathrm{d} \alpha \int_{-\infty}^{\infty} \boldsymbol{R}_x (z) e^{-j\omega z} \, \mathrm{d} z \int_{-\infty}^{\infty} \boldsymbol{h}^\ast(\beta) e^{-j\omega \beta} \, \mathrm{d} \beta
\end{aligned}$$
也即
$$\begin{equation}
S_y (\omega) = \boldsymbol{H}^\mathrm{T} (\omega) \boldsymbol{S}_x(\omega) \boldsymbol{H} ^\ast (\omega)
\end{equation}$$
对于窄带波束形成器,利用[窄带假设下的复加权的表达式][],可得
$$\begin{equation}
S_y (\omega) = \boldsymbol{w}^\mathrm{H} \boldsymbol{S}_x(\omega) \boldsymbol{w}
\end{equation}$$
为了计算由于信号而产生的输出,对 $\boldsymbol{w}$ 施加**{% label primary @无畸变/失真约束(distortionless constraint) %}**
$$\begin{equation}
\boldsymbol{w}^\mathrm{H} \boldsymbol{v}_{\boldsymbol{k}} \left( \boldsymbol{k}_\mathrm{s} \right) = 1
\end{equation}$$
表示从 $\boldsymbol{k}_\mathrm{s}$ 方向入射的任意信号将无畸变地通过波束形成器。在后续的讨论中这个条件经常使用。
&emsp;&emsp;输入信号谱
$$\begin{equation}
\boldsymbol{S}_{\boldsymbol{f}}(\omega) = \boldsymbol{v}_{\boldsymbol{k}} \left( \boldsymbol{k}_\mathrm{s} \right) S_f(\omega) \boldsymbol{v}_{\boldsymbol{k}}^\mathrm{H} \left( \boldsymbol{k}_\mathrm{s} \right)
\end{equation}$$
则输出信号谱为
$$\begin{equation}
\begin{aligned}
S_{y_\mathrm{s}} &= \boldsymbol{w}^\mathrm{H} \boldsymbol{v}_{\boldsymbol{k}} \left( \boldsymbol{k}_\mathrm{s} \right) S_f (\omega) \boldsymbol{v}_{\boldsymbol{k}}^\mathrm{H} \left( \boldsymbol{k}_\mathrm{s} \right) \boldsymbol{w} \\
&= S_f(\omega)
\end{aligned}
\end{equation}$$
&emsp;&emsp;输出噪声谱为
$$\begin{equation}
S_{y_\mathrm{n}} = \boldsymbol{w}^\mathrm{H} \boldsymbol{S_{\boldsymbol{n}}} (\omega) \boldsymbol{w}
\end{equation}$$
其中 $\boldsymbol{S_{\boldsymbol{n}}} (\omega)$ 是输入噪声过程的谱矩阵。对于空域白噪声,若各阵元的噪声谱相同,有
$$\begin{equation}
S_{\boldsymbol{n}} = S_n (\omega) \boldsymbol{I}
\end{equation}$$
则输出噪声谱
$$\begin{equation}
S_{y_n} = \left\| \boldsymbol{w} \right\|^2 S_n(w) = \sum_{n=0}^{N-1} \left| w_n \right|^2 S_n(\omega)
\end{equation}$$
所以
$$\begin{equation}
\mathrm{SNR_o}(\omega) = \frac{1}{\displaystyle\sum_{n=0}^{N-1} \left| w_n \right|^2} \frac{S_f(\omega)}{S_n(\omega)}
\end{equation}$$
其中,下标“$\mathrm{o}$”代表输出。
&emsp;&emsp;阵列增益 $A_w$ 反映了阵列带来的 SNR 改善程度,定义为阵列输出 SNR 和一个阵元上输入 SNR 的比值。
$$\begin{equation}
A_w = \frac{\mathrm{SNR_o}(\omega)}{\mathrm{SNR_{in}}(\omega)} = \frac{1}{\displaystyle \sum_{n=0}^{N-1} \left| w \right|^2} = \left( \sum_{n=0}^{N-1} \frac{1}{\left| w_n \right|^2} \right) ^{-1} = \left\| \boldsymbol{w} \right\| ^{-2}
\end{equation}$$
下标“$w$”表示空域不相关的噪声输入,**噪声的时域频谱不一定是平坦的**。
&emsp;&emsp;观察阵列增益的定义式可以得到以下三个有用的结果:
1. 只要满足
$$
\left| \boldsymbol{w}^\mathrm{H}\boldsymbol{v}_{\boldsymbol{k}} \left( \boldsymbol{k}_\mathrm{s} \right) \right|^2 = 1
$$
这个结果就适用于任意的阵列结构。
2. 对于标准线阵(阵元间距为 $d=\lambda/2$),白噪声阵列增益 $A_w$ 等于阵列方向性 $D$。
3. 对于非均匀线阵 $d \ne \lambda/2$,$D$ 是对全向噪声的阵列增益 $A_\mathrm{iso}$,而非白噪声增益 $A_w$。
&emsp;&emsp;对于均匀加权阵列,有
$$
w_n = \frac{1}{N}, \quad n = 0,\cdots,N-1
$$
且 $A_w = N$(或单位为 $\mathrm{dB}$ 时,为 $10 \log N$)。直接利用 Schwarz 不等式,可以得到 $A_w \leqslant N$。所以,如果要在空域不相关噪声下使阵列增益最大,均匀加权阵列是最优的。
# 敏感度和容错因子
<a id="fig.1-5-1"></a>
![图 1-5-1 具有阵元位置误差的阵列](../images/post/2023-04-24-josh-oap-part-1-5/2023-04-24-josh-oap-part-1-5-010-ArrayWithPositionErrors.png){width=700px}
&emsp;&emsp;后面会分析最优处理器对于增益和相位误差、传感器定位不准确等因素的敏感度。这里总结一下[图 1-5-1](#fig.1-5-1) 中阵列的典型结果,设计的目标是使得在没有阵列扰动的情况下,从正侧向入射到阵列的信号无畸变地通过,即有
$$
\boldsymbol{w}^\mathrm{H} \cdot \boldsymbol{1} F(\omega) = F(\omega)
$$
现在考虑滤波器扰动和阵列位置扰动的影响。
## 滤波器扰动(Filter Perturbations)
&emsp;&emsp;假设理想的矩阵滤波器为 $\boldsymbol{w}^n$,把 $\boldsymbol{w}^n$ 的第 $i$ 个元素表示为 $w_i^n$,则理想的权值可表示为
$$\begin{equation}
(w_i^n)^\ast = g_i^n e^{-j \varphi_i^n}
\end{equation}$$
实际的权值可表示为
$$\begin{align}
w_i^\ast &= g_i e^{-j \varphi_i} \notag \\
&= g_i^n (1 + \Delta g_i) e^{-j (\varphi_i^n + \Delta \varphi_i)}
\end{align}$$
其中 $\Delta g_i$ 和 $\Delta \varphi_i$ 是随机变量。
## 阵列位置扰动(Array Location Perturbations)
&emsp;&emsp;假设理想的阵元位置为 $\boldsymbol{p}_i^n$,实际阵元位置为
$$\begin{equation}
\boldsymbol{p_i} = \boldsymbol{p}_i^n + \Delta \boldsymbol{p}_i
\end{equation}$$
所以理想的模型可能会产生三种变化
$$
g_i = g_i^n (1 + \Delta g_i)
$$
$$
\varphi_i = \varphi_i^n + \Delta \varphi_i
$$
$$
\boldsymbol{p_i} = \boldsymbol{p}_i^n + \Delta \boldsymbol{p}_i
$$
前两种变化可能是由于阵元的增益和相位改变,或者是由于阵元增益和相位不准确造成的。最后一种变化是由于对阵元的位置缺乏精确了解造成的。假设 $\{ \Delta g_i \}_{i=0}^{N-1}$、$\{ \varphi_i \}_{i=0}^{N-1}$ 和 $\{ \boldsymbol{p_i} \}_{i=0}^{N-1}$ 是统计独立、零均值的高斯随机变量,下面在阵列存在这些变化的情况下分析波束方向图的变化情况。
&emsp;&emsp;理想波束方向图为
$$\begin{align}
B^{(n)}(\boldsymbol{k}) &= (\boldsymbol{w}^n)^\mathrm{H}\boldsymbol{v}(\boldsymbol{k}) \notag \\
&= \sum_{i=0}^{N-1} g_i^n \exp (j\varphi_i^n - j \boldsymbol{k}^\mathrm{T} \boldsymbol{p}_i^n)
\end{align}$$
实际波束方向图是一个随机函数,其幅度平方的期望值可以写成
$$\begin{aligned}
\overline{\left| B (\boldsymbol{k}) \right| ^2} & \triangleq && E \left\{ \left| B (\boldsymbol{k}) \right| ^2 \right\} \notag \\
&=&& E \left\{ \sum_{i=0}^{N-1} \sum_{l=0}^{N-1} g_i \exp(j\varphi_i^n - j \boldsymbol{k}^\mathrm{T} \boldsymbol{p}_i^n) \cdot g_l (-j\varphi_l^n + j \boldsymbol{k}^\mathrm{T} \boldsymbol{p}_l^n) \right\} \\
&=&& \sum_{i=0}^{N-1} \sum_{l=0}^{N-1} E \left\{ g_i^n (1 + \Delta g_i) g_l^n (1 + \Delta g_l) \right. \notag \\
& && \cdot \exp\left[ j (\varphi_i^n + \Delta \varphi_i - \varphi_l^n - \Delta \varphi_l) \right]\left. \right. \notag \\
& && \left. \cdot \exp \left[ -j \boldsymbol{k}^\mathrm{T} \left( \boldsymbol{p}_i^n + \Delta \boldsymbol{p}_i - \boldsymbol{p}_l^n - \Delta \boldsymbol{p}_l \right) \right] \right\}
\end{aligned}$$
&emsp;&emsp;定义
$$\begin{cases}
\alpha_{il} = E \left\{ (1 + \Delta g_i)(1 + \Delta g_l) \exp[j(\Delta \varphi_i - \Delta \varphi_l)] \right\} \\
\beta_{il}(\boldsymbol{k}) = E \left\{ \exp[-j\boldsymbol{k}^\mathrm{T}(\Delta \boldsymbol{p}_i - \Delta \boldsymbol{p}_l)] \right\}
\end{cases}$$
利用独立高斯随机变栨的假设,有
$$
\alpha_{il} = \begin{cases}
\exp (-\sigma_{\varphi}^2), & i \ne l \\
1 + \sigma_g^2, & i = l
\end{cases}
$$
$$
\beta_{il}(\boldsymbol{k}) = \begin{cases}
\exp (-\sigma_p^2 |\boldsymbol{k}|^2) = \exp \left( - \left[ \displaystyle\frac{2\pi\sigma_p}{\lambda}^2 \right] \right) \triangleq \exp (-\sigma_\lambda^2), & i \ne l \\
1 , & i = l
\end{cases}
$$
在 $\beta_{il}(\boldsymbol{k})$ 的表达式中,假设每个分量 $\Delta \boldsymbol{p}_i$ 的方差等于 $\sigma_p^2$,$\sigma_\lambda^2$ 是以波长进行归一化的方差。则
$$\begin{align}
\overline{\left| B (\boldsymbol{k}) \right| ^2} &=&& \sum_{i=0,i\ne l}^{N-1}\sum_{l=0}^{N-1} \left\{ g_i^n g_l^n \exp (j\varphi_i^n- j\varphi_l^n) \exp \left[ -j \boldsymbol{k}^\mathrm{T} \left( \boldsymbol{p}_i - \boldsymbol{p}_l \right)\right] \right. \notag \\
& && \cdot \left. \exp [-(\sigma_\varphi^2+\sigma_\lambda^2)] \right\}+ \sum_{i=0}^{N-1} (1+\sigma_g^2)(g_i^n)^2 \notag \\
&=&& \left| B^{(n)}(\boldsymbol{k}) \right| ^2 \exp [-(\sigma_\varphi^2+\sigma_\lambda^2)] \notag \\
& && + \sum_{i=0}^{N-1} (g_i^n)^2 \{(1+\sigma_g^2) - \exp [-(\sigma_\varphi^2+\sigma_\lambda^2)] \}
\end{align}$$
其中 $\sigma_\varphi^2$、$\sigma_\lambda^2$ 和 $\sigma_g^2$ 表示对应的随机变量的方差。
&emsp;&emsp;从实际波束方向图的表达式可以看出,随机变化引入了两种影响。第一项使波束方向图在 $\boldsymbol{k}$ 空间均匀衰减,这种均匀性是随机变量独立于 $\boldsymbol{k}$ 的假设造成的,意味着波束方向图具有统计偏差,使得主响应轴方向的波束方向图的期望值小于 $1$。第二项更为关键,定义**{% label primary @敏感度函数 %}**为
$$\begin{equation}
T_\mathrm{se} = \sum_{i=0}^{N-1} \left| w_i^n \right| ^2 = \sum_{i=0}^{N-1} (g_i^n)^2
\end{equation}$$
则第二项成为
$$
\overline{\left| B_2 (\boldsymbol{k}) \right| ^2} = T_\mathrm{se} \{(1+\sigma_g^2) - \exp [-(\sigma_\varphi^2+\sigma_\lambda^2)] \}
$$
若方差较小,则
$$
\overline{\left| B_2 (\boldsymbol{k}) \right| ^2} = T_\mathrm{se} \{\sigma_g^2 + \sigma_\varphi^2 + \sigma_\lambda^2 \}
$$
注意到 $T_\mathrm{se}$ 是白噪声增益的逆,也即
$$\begin{equation}
T_\mathrm{se} = [A_w] ^{-1} = \left\| \boldsymbol{w} \right\|^2
\end{equation}$$
所以当白噪声增益增加时,敏感度减小。对于 $N$ 元阵列,白噪声增益最大为 $N$, 对应均匀加权的情况。所以,任意一个具有非均匀加权的阵列对参数的变化将比均匀加权阵列更敏感。第二项均匀地提高了旁瓣区域的期望值,在整个 $\boldsymbol{k}$ 空间产生了主要的影响。在很多阵列设计的问题中,我们希望能在一个干扰信号的方向放置一个完全零点(perfect null),使得 $|B(\boldsymbol{k})|^2 = 0$,如果 $(\sigma_\varphi^2, \sigma_\lambda^2, \sigma_g^2)$ 中的任何一个变量不为零,则不可能得到一个完全零点。
&emsp;&emsp;方向图期望值的下限依赖于敏感度函数 $T_\mathrm{se}$ 和扰动的方差,限制了方向图零点的深度[^2]。
> &emsp;&emsp;下面举例分析。假设
>
> $$
> \sigma_T^2 \triangleq \sigma_g^2 + \sigma_\varphi^2 + \sigma_\lambda^2 = 0.01
> $$
>
> 则 $A_w$ 必须大于或等于 $100$,才能在方向图上得到 $-40\text{dB}$ 的零陷。这需要均匀加权阵列至少具有 $100$ 个阵元,非均匀加权的阵列将需要更多阵元。
&emsp;&emsp;当设计最优阵列时,我们经常采用**{% label primary @敏感度约束 %}**
$$\begin{equation}
T_\mathrm{se} = \left\| \boldsymbol{w} \right\|^2 \leqslant T_\mathrm{o}
\end{equation}$$
其中 $T_\mathrm{o}$ 是一个使得阵列的性能对扰动更加稳健的常数。上述约束也可以表述为**{% label primary @白噪声增益约束 %}**
$$\begin{equation}
A_w = (\left\| \boldsymbol{w} \right\|^2) ^{-1} \geqslant T_\mathrm{o}^{-1}
\end{equation}$$
# 总结
&emsp;&emsp;本文给出了三个重要的阵列性能度量指标。我们看到权值矢量 $\boldsymbol{w}$ 的模在所有的三个度量指标中都出现了
1. 对于标准线阵,方向性 $D = \left\| \boldsymbol{w} \right\|^{-2} \leqslant N$;
2. 对于任意阵列结构,白噪声阵列增益 $A_w = \left\| \boldsymbol{w} \right\|^{-2}$;
3. 对于任意阵列结构,敏感度函数 $T_\mathrm{se} = A_w^{-1} = \left\| \boldsymbol{w} \right\|^2$。
可见 $\left\| \boldsymbol{w} \right\|^2$ 在很多讨论中都起着非常核心的作用。
# 参考文献
1. Van Trees, Harry L. _Optimum array processing: Part IV of detection, estimation, and modulation theory._ John Wiley & Sons, 2002.
2. Van Trees, Harry L, 汤俊. _最优阵列处理技术._ 清华大学出版社. 2008.
[$u$ 空间的波束方向图的表达式]: https://josh-gao.top/posts/de20fd09.html#BeamPatternInDirectionCosineDomain
[对角调向矩阵]: https://josh-gao.top/posts/c2604c43.html#DiagonalSteeringMatrix
[各个空间的第一零点波束宽度表]: https://josh-gao.top/posts/aa32ec76.html#table.1-3-2
[阵列输出的向量形式]: https://josh-gao.top/posts/8b61f5a7.html#VectorFormOfLinearArrayOutputInTimeDomain
[窄带假设下的复加权的表达式]: https://josh-gao.top/posts/8b61f5a7.html#NarrowBandComplexWeightVector
[^1]: 在大多数情况下,我们去掉下标 “$s$”,因为假设 $\boldsymbol{w}$ 是包含调向的。
[^2]: 在数学上,零点意味 $B(\boldsymbol{k}) = 0$,但是实际方向图具有非零的值,该值和 $B(\boldsymbol{k}_\mathrm{T})$ 的值的比值称为**{% label primary @零点深度 %}**。
@@ -0,0 +1,117 @@
---
title: Git 删除已提交的大文件
mathjax: false
comments: true
copyright: true
toc:
enable: true
number: true
wrap: true
expand_all: true
max_depth: 4
tags:
- Git
categories:
- Git
abbrlink: a587d6e6
date: 2023-05-14 14:30:08
---
在使用 git 管理代码仓库的时候,有可能不小心提交了一些大文件,虽然后来从工作区删除了,但是已经于事无补,大文件的历史记录仍然保存在 git 仓库里。以下提供了基于文件大小排序的 Git 仓库文件搜索和删除方法。
# 查找大文件
在 Git 仓库目录下执行命令对归档的文件进行排序,并给出文件大小前 5 的文件 ID 等信息:
``` bash
git verify-pack -v .git/objects/pack/pack-*.idx | sort -k 3 -g | tail -5
```
输出结果如下,依次是文件 ID、文件类型、文件字节数、`size-in-packfil` 和 `offset-in-packfile`:
``` plain Example Output
10eaa37e6e1999cf5652e9b4c6b3ca5fa43a90b1 blob 14873202 11312961 77109113
c8aeb64369be1be657633e92d07dc49ed91fbdc1 blob 14873202 11313163 23914709
1ed41690c8dced0c2ac10b41fafbf23b72a081fd blob 17416456 749732 16400558
b7cb7ef09404b7514d04a5d0f56a7a99e96c072d blob 26776467 1877027 96312339
66e27e2c0159a8439a744d57f058d63dbe192e95 blob 552933714 543247488 117101156
```
<!-- more -->
根据文件的 ID(SHA1),查找文件路径:
``` bash
git rev-list --objects --all | grep <targrt_file_ID>
```
示例输入如下:
``` bash Example Input
git rev-list --objects --all | grep 66e27e2c0159a8439a744d57f058d63dbe192e95
```
输出结果如下,以此是文件 ID 和文件路径:
``` plain Example Output
66e27e2c0159a8439a744d57f058d63dbe192e95 projects/duifei/duifei_online_acq_par/duifei_online_acq_par_20230511.xpr.zip
```
# 将要删除的大文件从各个分支中移除
执行下面命令,将文件从分支的提交中移除
``` bash
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch <target_file_path>' --prune-empty --tag-name-filter cat -- --all
```
示例输入如下:
``` bash Example Input
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch projects/duifei/duifei_online_acq_par/duifei_online_acq_par_20230511.xpr.zip' --prune-empty --tag-name-filter cat -- --all
```
示例输出如下:
``` plain Example Output
WARNING: git-filter-branch has a glut of gotchas generating mangled history
rewrites. Hit Ctrl-C before proceeding to abort, then use an
alternative filtering tool such as 'git filter-repo'
(https://github.com/newren/git-filter-repo/) instead. See the
filter-branch manual page for more details; to squelch this warning,
set FILTER_BRANCH_SQUELCH_WARNING=1.
Proceeding with filter-branch...
Rewrite 28271ddd7ce45bc13561bc7343664d937c267a2f (4/10) (1 seconds passed, remaining 1 predicted) rm 'projects/duifei/duifei_online_acq_par/duifei_online_acq_par_20230511.xpr.zip'
Rewrite e6b6be1ada32ad2eff5f52b45372ed9274a04f30 (9/10) (1 seconds passed, remaining 0 predicted)
Ref 'refs/heads/master' was rewritten
WARNING: Ref 'refs/remotes/github/master' is unchanged
Ref 'refs/remotes/jgnas/master' was rewritten
Ref 'refs/remotes/localhost/master' was rewritten
Ref 'refs/remotes/origin/master' was rewritten
```
# 删除缓存下来的 ref 和 git 操作记录
``` bash
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all
```
# 垃圾回收
上面 2 步把大文件的索引都切断了,这个时候进行垃圾回收,就可以很明显看到效果。
``` bash
git gc --prune=now
```
这时候的仓库中的大文件就已经被删除了,把仓库**推送到新的远程仓库**或者**强制推送到现在的远程仓库**都是可以的。
``` bash
git push --force
```
# 参考
[删除 git 仓库中无用大文件](https://www.cnblogs.com/oloroso/p/13367120.html)
@@ -0,0 +1,948 @@
---
title: strike
comments: true
copyright: true
toc:
enable: true
number: false
wrap: true
expand_all: true
max_depth: 3
tags:
- 牛津5000
- 英语词汇
categories:
- 英语学习
abbrlink: dc727c0
date: 2023-05-21 20:44:58
---
# Verb
## Pronunciation
- BrE: /straɪk/
- NAmE: /straɪk/
## Verb Forms
- present simple I / you / we / they **strike**
- BrE: /straɪk/
- NAmE: /straɪk/
- he / she / it **strikes**
- BrE: /straɪks/
- NAmE: /straɪks/
- past simple **struck**
- BrE: /strʌk/
- NAmE: /strʌk/
- past participle **struck**
- BrE: /strʌk/
- NAmE: /strʌk/
- -ing form **striking**
- BrE: /ˈstraɪkɪŋ/
- NAmE: /ˈstraɪkɪŋ/
## Explanation
### {% label primary@hit somebody/something 击打;碰撞 %}
1. **{% label @B2 %}** \[transitive, intransitive\] (*formal*) to hit somebody/something hard or with force 撞;碰;撞击;碰撞
<!-- more -->
- **strike somebody/something** *The ship struck a rock.* 船触礁了。
- *The child ran into the road and was **struck by a car**.* 孩子跑到公路上给车撞了。
- *The tree was **struck by lightning**.* 树遭到雷击。
- *Warplanes struck several targets in the city.* 战机轰炸了城市里的几个目标。
- **strike somebody/something + adv./prep.** *He fell, striking his head on the edge of the table.* 他摔倒了,头碰在桌子边上。
- *He was struck in the head by a bullet.* 他被子弹击中头部。
- *The stone struck her on the forehead.* 那块石头击中她的额头。
- **strike against something** *The oar struck against something hard.* 桨重重地砸在了一件硬东西上。
{% note primary Synonyms **hit**%}
knock | bang | strike | bump | bash
These words all mean to come against something with a lot of force.
- **hit** to come against somebody/​something with force, especially causing damage or injury:
- *The boy was hit by a speeding car.* 男孩被超速行驶的汽车撞倒了。
- **knock** to hit something so that it moves or breaks; to put somebody/​something into a particular state or position by hitting them/​it:
- *Someone had knocked a hole in the wall.* 有人在墙上打了个洞。
- **bang** to hit something in a way that makes a loud noise:
- *The baby was banging the table with his spoon.* 婴孩用调羹敲打着桌子。
- **fling** to throw somebody/​something somewhere with a lot of force, especially because you are angry or in a hurry:
- *She flung the letter down onto the table.* 她把信摔在桌子上。
- **strike** (*formal*) to hit somebody/​something hard: 指猛烈地撞、碰、撞击、碰撞:
- *The ship struck a rock.* 船触礁了。
- **bump** to hit somebody/​something by accident:
- *In the darkness I bumped into a chair.* 我在黑暗中撞上了一把椅子。
- **bash** (*informal*) to hit against something very hard: 指猛击、猛撞:
- *I braked too late, bashing into the car in front.* 我刹车太晚,撞上了前面的车。
- Patterns
- to hit/​knock/​bang/​bump/​bash **against** somebody/​something
- to knock/​bang/​bump/​bash **into** somebody/​something
- to hit/​strike the **ground/​floor/​wall**
{% endnote %}
{% note primary Oxford Collocations Dictionary %}
- **adverb**
- firmly
- hard
- deep
- …
- **verb + strike**
- be about to
- be going to
- be ready to
- …
- **preposition**
- against
- at
- on
- …
- **phrases**
- be struck by lightning
- get struck by lightning
- be struck down by something
- …
{% endnote %}
2. **{% label @B2 %}** \[transitive\] (*formal*) to hit somebody/something with your hand or a weapon 打;击
- **strike somebody/something** *She struck him in the face.* 她掴了他一记耳光。
- *He struck the table with his fist.* 他用拳头打桌子。
- *Who struck the first blow* (= started the fight)? 是谁先动手的?
- *Did she ever strike you?* 她打过你吗?
- **strike somebody/something sth** He struck her two blows on the leg. 他在她腿上打了两下。
{% note primary Oxford Collocations Dictionary %}
- **adverb**
- firmly
- hard
- deep
- …
- **verb + strike**
- be about to
- be going to
- be ready to
- …
- **preposition**
- against
- at
- on
- …
- **phrases**
- be struck by lightning
- get struck by lightning
- be struck down by something
- …
{% endnote %}
### {% label primary@kick/hit ball 踢球;击球 %}
3. \[transitive\] **strike something (+ adv./prep.)** (*formal*) to hit or kick a ball, etc. 击打,踢(球等)
- *He walked up to the penalty spot and struck the ball firmly into the back of the net.* 他走到罚球点,稳稳地把球踢入网内。
### {% label primary@attack 攻击 %}
4. **{% label @B2 %}** \[intransitive\] to attack somebody/something, especially suddenly 突击;攻击
- *The lion crouched ready to strike.* 狮子蹲身准备袭击。
- *Police fear that the killer may strike again.* 警方担心杀人犯可能再次下手。
- *The guerrillas struck with deadly force.* 游击队发起强势进攻。
**Topics** [War and conflict](https://www.oxfordlearnersdictionaries.com/topic/war-and-conflict?level=b2) **{% label @B2 %}**
{% note primary Oxford Collocations Dictionary %}
- **adverb**
- firmly
- hard
- deep
- …
- **verb + strike**
- be about to
- be going to
- be ready to
- …
- **preposition**
- against
- at
- on
- …
- **phrases**
- be struck by lightning
- get struck by lightning
- be struck down by something
- …
{% endnote %}
### {% label primary@of disaster/disease 灾难;疾病 %}
5. **{% label @B2 %}** \[intransitive, transitive\] to happen suddenly and have a harmful or damaging effect on somebody/something 侵袭;爆发
- *Two days later **tragedy struck**.* 两天后悲剧发生了。
- ***Disaster struck** again when their best player was injured.* 灾难又一次发生了,他们最好的队员受伤了。
- **strike somebody/something** *The area was struck by an outbreak of cholera.* 那一地区爆发了霍乱。
{% note primary Extra Examples %}
- *A hurricane is about to strike Jamaica.* 飓风即将袭击牙买加。
- *Earthquakes can strike without warning.* 地震可能没有任何预兆就发生。
- *The disease first struck her 10 years ago.* 这种疾病第一次袭击她是在 10 年前。
{% endnote %}
### {% label primary@thought/idea/impression 想法;念头;印象 %}
6. **{% label @B2 %}** \[transitive\] (not used in the progressive tenses 不用于进行时) (of a thought or an idea 想法或念头) to come into somebody’s mind suddenly 突然想到;一下子想起;猛地意识到
- **strike somebody** *An awful thought has just struck me.* 刚才我脑子里突然闪过一个可怕的念头。
- *I was struck by her resemblance to my aunt.* 我猛然发现她长得跟我姑姑很像。
- *One thing that really struck me was how calm he appeared.* 他看起来如此平静,着实给我留下了深刻印象。
- **it strikes somebody how, what, etc…** *It suddenly struck me how we could improve the situation.* 我一下子明白我们如何能改善局面了。
{% note primary Oxford Collocations Dictionary %}
- **adverb**
- immediately
- suddenly
- just
- …
- **preposition**
- as
{% endnote %}
7. **{% label @B2 %}** \[transitive\] to give somebody a particular impression 给(某人以…)印象;让(某人)觉得
- **strike somebody** *Another part of his comment struck me.* 他评论的另一部分打动了我。
- **strike somebody as something** *His reaction struck me as odd.* 他的反应令我诧异。
- *She strikes me as a very efficient person.* 在我眼里,她是个很干练的人。
- *How does the idea strike you*? 你觉得这个主意怎么样?
- **it strikes somebody that…** *It strikes me that nobody is really in favour of the changes.* 我觉得没人真正赞成这些变动。
{% note primary Extra Examples %}
- *He always struck me as being rather stupid.* 他总是让我感觉傻乎乎的。
- *It struck me as strange that there was no one there.* 那里空无一人,我感到有些奇怪
{% endnote %}
{% note primary Oxford Collocations Dictionary %}
- **adverb**
- immediately
- suddenly
- just
- …
- **preposition**
- as
{% endnote %}
### {% label primary@of workers 工人 %}
8. **{% label @B2 %}** \[intransitive\] to refuse to work because of an argument over pay or conditions 罢工
- *Over 100,000 civil servants are set to strike on Tuesday.* 10 万多名公务员确定要在星期二举行罢工。
- **strike over something** *Drivers are threatening to strike over pay.* 司机们威胁要就工资问题举行罢工。
- **strike for something** *The union has voted to strike for a pay increase of 6%.* 工会投票决定罢工,要求加薪 6%。
- *Striking workers picketed the factory.* 罢工的工人在工厂附近设置了纠察队
{% note primary Wordfinder %}
ballot | closed shop | collective bargaining | industrial action | labour | picket | protest | representative | strike | union
{% endnote %}
**Topics** [Social issues](https://www.oxfordlearnersdictionaries.com/topic/social-issues?level=b2) **{% label @B2 %}**, [Working life](https://www.oxfordlearnersdictionaries.com/topic/working-life?level=b2) **{% label @B2 %}**
{% note primary Oxford Collocations Dictionary %}
- **verb + strike**
- threaten to
- vote to
- be set to
- …
- **preposition**
- against
- for
- in protest at
- …
- **phrases**
- the right to strike
{% endnote %}
### {% label primary@of light 光 %}
9. \[transitive\] **strike something** to fall on a surface 照在…上;照射
- *The windows sparkled as the sun struck the glass.* 阳光照得玻璃窗熠熠闪光。
### {% label primary@dumb/deaf/blind 哑;聋;瞎 %}
10. \[transitive\] **strike somebody + adj.** [usually passive] to put somebody suddenly into a particular state 顿时使处于某状态
- *to be struck dumb/deaf/blind* 一时什么也说不出/听不见/看不见
### {% label primary@match 火柴 %}
11. \[transitive, intransitive\] **strike (something)** to rub something such as a match against a surface so that it produces a flame; to produce a flame when rubbed against a rough surface 擦,划(火柴);击出(火星)
- *to strike a match on a wall* 在墙上擦火柴
- *The sword struck sparks off the stone floor.* 剑砍在石头地板上,火星飞溅。
- *The matches were damp and he couldn't make them strike.* 火柴受潮了,他划不着。
### {% label primary@of clock 钟 %}
12. \[intransitive, transitive\] to show the time by making a ringing noise, etc. 敲;鸣;报时
{% note primary **synonym** chime %}
- BrE: /tʃaɪm/
- NAmE: /tʃaɪm/
\[intransitive, transitive\] (of a bell or a clock 铃或时钟) to ring; to show the time by making a ringing sound 鸣响;敲响;报时
- *I heard the clock chime.* 我听见钟响报时。
- *Eight o'clock had already chimed.* 已敲过八点钟了。
- **chime something** *The clock chimed midday.* 时钟响过正午十二点。
{% endnote %}
- *Did you hear the clock strike?* 你听见钟响了吗?
- *Four o’clock had just struck.* 那时候时钟刚刚敲过4点。
- **strike something** *The clock has just struck three.* 时钟刚刚敲过三点。
### {% label primary@make sound 发出声音 %}
13. \[transitive\] **strike something** to produce a musical note, sound, etc. by pressing a key or hitting something 弹奏;奏响;发出(声音)
- *She struck a chord on the piano and the children began to sing.* 她在钢琴上奏出和弦,孩子们开始唱歌。
{% note primary Oxford Collocations Dictionary %}
- **adverb**
- firmly
- hard
- deep
- …
- **verb + strike**
- be about to
- be going to
- be ready to
- …
- **preposition**
- against
- at
- on
- …
- **phrases**
- be struck by lightning
- get struck by lightning
- be struck down by something
- …
{% endnote %}
### {% label primary@gold/oil, etc. 金、石油等 %}
14. \[transitive\] **strike something** to discover gold, oil, etc. by digging or drilling 开采出;钻探到
- *They had struck oil!* 他们开采出了石油!
### {% label primary@go with purpose 有目的地走 %}
15. \[intransitive\] **strike + adv./prep.** to go somewhere with great energy or purpose 行进;加劲走
- *We left the road and **struck off** across the fields.* 我们下了公路,穿过旷野往前走。
- *He **struck out*** (= started swimming) *towards the shore.* 他朝岸边游去。
- *The German army struck deep into northern France.* 德国军队深入法国北方实施打击。
## Word Origin
Old English *strīcan* ‘go, flow’ and ‘rub lightly’, of West Germanic origin; related to German *streichen* ‘to stroke’, also to **stroke**. The sense ‘deliver a blow’ dates from Middle English.
## Idioms
- **be struck by/on/with somebody/something**
(*informal*) to be impressed or interested by somebody/something; to like somebody/something very much 被某人(或某物)打动;迷恋某人(或某物)
- *I was struck by her youth and enthusiasm.* 她年轻热情,把我迷住了。
- *We're not very struck on that new restaurant.* 我们不大看得上那家新餐馆。.
{% note primary Extra Examples %}
- *I was particularly struck by the sound of the birds.* 鸟的叫声尤其让我印象深刻。
- *Joan was struck quite forcibly by the silence.* 那种静默给琼留下了深刻的印象。
{% endnote %}
- **drive/strike a hard bargain**
to argue in an aggressive way and force somebody to agree on the best possible price or arrangement 狠狠地杀价
**Topics** [Discussion and agreement](https://www.oxfordlearnersdictionaries.com/topic/discussion-and-agreement?level=c2) **{% label @C2 %}**
- **hit/strike home**
if a remark, etc. **hits/strikes home**, it has a strong effect on somebody, in a way that makes them realize what the true facts of a situation are (言语等)正中要害,说到点子上
- *Her face went pale as his words hit home.* 他的话切中要害,她的脸变白了。
- **hit/strike pay dirt**
(*informal*) to suddenly be in a successful situation, especially one that makes you rich 骤然成功;暴富
- *The band really hit pay dirt with their last album.* 这个乐队的上一张专辑确实很畅销。
**Topics** [Success](https://www.oxfordlearnersdictionaries.com/topic/success?level=c2) **{% label @C2 %}**
- **hit/strike the right/wrong note**
(*especially British English*) to do, say or write something that is suitable/not suitable for a particular occasion 做(或说、写)得得体/不得体
- *It is a bizarre tale and the author hits just the right note of horror and disbelief.* 这是一个离奇的故事,作者恰到好处地表达了恐惧和怀疑。
- *Unfortunately, the president struck the wrong note in his speech, ignoring the public mood.* 不幸的是,总统在他的演讲中打错了音,忽略了公众的情绪。
- **hit/strike the woodwork**
(*British English, informal*) to hit the wooden frame of the goal in the game of football (soccer), instead of scoring a goal 交好运
- *She hit the woodwork twice before scoring.* 得分前她击中了两次门框。
- **lightning never strikes (in the same place) twice**
(*saying*) an unusual or unpleasant event is not likely to happen in the same place or to the same people twice 倒霉的事不可能在同一场所(或同一人身上)重复发生;一事不过二
- **sound/strike a note (of something)**
to express feelings or opinions of a particular kind 表达某种情感(或观点)
- *She sounded a note of warning in her speech.* 她在讲话中透出了警告的意味。
- *The touch of cynicism struck a slightly sour note.* 冷嘲热讽的味道略带酸味。
{% note primary Extra Examples %}
- *He sounded a cautionary note.* 他的声音带有一种提醒的意味。
- *His opening remarks struck the right note.* 他的开幕词讲得十分得体。
{% endnote %}
**Topics** [Opinion and argument](https://www.oxfordlearnersdictionaries.com/topic/opinion-and-argument?level=c2) **{% label @C2 %}**
- **strike a balance (between A and B)**
to manage to find a way of being fair to two things that are opposed to each other; to find an acceptable position that is between two things (在对立二者之间)找到折中办法;平衡(对立的双方)
- *We need to strike a balance between these conflicting interests.* 我们需要在这些利益冲突中找到平衡。
- **strike a bargain/deal (with somebody/something)**
to make an agreement with somebody in which both sides have an advantage 达成(对双方都有利的)协议
- *Perhaps we could strike a bargain.* 也许我们可以达成协议。
- *The United States has struck a historic deal with India.* 美国与印度达成了一项历史性协议。
**Topics** [Discussion and agreement](https://www.oxfordlearnersdictionaries.com/topic/discussion-and-agreement?level=c2) **{% label @C2 %}**
- **strike a blow for/against/at something**
to do something in support of/against a belief, principle, etc. 维护(或损害)某种信念或原则等
- *He felt that they had struck a blow for democracy.* 他感觉他们维护了民主制度。
- **strike/touch a chord (with somebody)**
to say or do something that makes people feel sympathy or enthusiasm 引起同情(或共鸣)
- *The speaker had obviously struck a chord with his audience.* 讲演者显然已引起了听众的共鸣。
- **strike fear, etc. into somebody/sb’s heart**
(*formal*) to make somebody be afraid, etc. 使某人感到恐惧等
- *The sound of gunfire struck fear into the hearts of the villagers.* 炮声使村民心惊胆战。
- **strike gold**
to find or do something that brings you a lot of success or money 打开成功(或财富)之门;踏上通往成功(或财富)之路
- *He has struck gold with his latest novel.* 他凭借最新的一部小说叩开了成功之门。
**Topics** [Success](https://www.oxfordlearnersdictionaries.com/topic/success?level=c2) **{% label @C2 %}**
- **strike/hit home**
if a remark, etc. strikes/hits home, it has a strong effect on somebody, in a way that makes them realize what the true facts of a situation are (言语等)正中要害,说到点子上
- *His face went pale as her words struck home.* 当她的话击中要害时,他的脸色变得苍白。
- **strike it rich**
(*informal*) to get a lot of money, especially suddenly or unexpectedly 暴富;(意外)发大财
- **strike (it) lucky**
(*informal*) to have good luck 交好运
- *We certainly struck it lucky with the weather.* 我们真幸运,遇上了好天气。
- **strike a nerve (with somebody)**
to have a strong effect (言语等)正中要害,说到点子上
- *His work strikes a nerve with people who are attracted to nostalgia.* 他的作品触动了怀旧人群的神经。
- *It seems I struck a nerve with my last post about cell phones.* 我上一篇关于手机的帖子似乎触动了我的神经。
- *Nissan may well strike a popular nerve here.* 日产汽车很可能会触动这里的一根大众神经。
- **strike/hit pay dirt**
(*informal*) to suddenly be in a successful situation, especially one that makes you rich 骤然成功;暴富
- *The band really struck pay dirt with their last album.* 这个乐队的上一张专辑确实赚了不少钱。
**Topics** [Success](https://www.oxfordlearnersdictionaries.com/topic/success?level=c2) **{% label @C2 %}**
- **strike a pose/an attitude**
to hold your body in a particular way to create a particular impression 摆出某种姿态
- *to strike a dramatic pose* 摆出戏剧性的姿势
- *(figurative) He strikes an attitude of bravery and lonely defiance.* 他表现出勇敢和孤独的反抗态度。
- **strike/hit the right/wrong note**
(*especially British English*) to do, say or write something that is suitable/not suitable for a particular occasion 做(或说、写)得得体/不得体
- *It is a bizarre tale and the author strikes just the right note of horror and disbelief.* 这是一个离奇的故事,作者恰到好处地表达了恐惧和怀疑。
- **strike while the iron is hot**
(*saying*) to make use of an opportunity immediately 趁热打铁
- **within striking distance (of something)**
near enough to be reached or attacked easily; near enough to reach or attack something easily 近在咫尺;在攻击距离之内
- *The beach is within striking distance.* 海滩近在咫尺。
- *The cat was now within striking distance of the duck.* 此时,猫就在可攻击鸭子的距离内。
## Phrasal Verbs
### strike at
- **strike at somebody/something**
1. to try to hit somebody/something, especially with a weapon 朝…打去
- *He struck at me repeatedly with a stick.* 他拿着棍子一再朝我打过来。
2. to cause damage or have a serious effect on somebody/something 损害;有损于;严重影响到
- *to strike at the root of the problem* 从根源入手解决问题
- *criticisms that **strike at the heart of** the party’s policies* 直指该党政策之要害的批评意见
### strike back
- **strike back (at/against somebody)**
to try to harm somebody in return for an attack or injury you have received 反击;回击
### strike down
- **strike somebody down** [usually passive]
1. (of a disease, etc.疾病等) to make somebody seriously ill; to kill somebody 摧垮;使病倒;使丧命
- *He was struck down by cancer at the age of thirty.* 他三十岁那年被癌症夺去了性命。
- *He was struck down with food poisoning.* 他因食物中毒卧床不起。
2. to hit somebody very hard, so that they fall to the ground 击倒,撞倒(某人)
- **strike something ↔ down**
(*especially North American English*) to decide that a law is illegal and should not apply 取消,撤销(法规)
- *The Supreme Court struck down a Texas state law.* 最高法院撤销了得克萨斯州的一条法律。
- *The law was struck down as unconstitutional.* 这项法律因违宪而被否决。
### strike off
- **strike something ↔ off**
to remove something with a hard hit; to cut something off 打掉;砍掉;砍下
- *He struck off the rotten branches with an axe.* 他用斧子把枯树枝砍掉。
- **strike somebody/something off (something)**
(also **strike somebody/something from something**)
to remove somebody/something’s name from something, such as the list of members of a professional group把某人(或某事物)除名
- *Strike her name off the list.* 把她的名字从名单上删掉。
- *The doctor was struck off* (= not allowed to continue to work as a doctor) *for incompetence.* 那名医生因不称职而被取消了执业资格。
### strike out
- **strike out**
1. to start being independent 独立出去;自立谋生
- I knew it was time I struck out on my own. 我知道我该独立谋生了。
2. (*North American English, informal*) to fail or be unsuccessful 失败;砸锅
- The movie struck out and didn't win a single Oscar. 那部影片砸锅了,奥斯卡奖一项都没得着。
**Topics** [Difficulty and failure](https://www.oxfordlearnersdictionaries.com/topic/difficulty-and-failure?level=c2) **{% label @C2 %}**
- **strike out (at somebody/something)**
1. to aim a sudden violent hit at somebody/something (奋力朝某处)去;赶往(某处)
- *He lost his temper and struck out wildly.* 他发了脾气,大打出手。
2. to criticize somebody/something, especially in a public speech or in a book or newspaper (尤指公开)抨击
- *In a recent article she strikes out at her critics.* 她最近写了一篇文章,对批评她的人予以驳斥。
- **strike out | strike somebody ↔ out**
(in baseball 棒球) to fail to hit the ball three times and therefore not be allowed to continue hitting; to make somebody do this (使)三击不中出局,三振出局
{% note primary **related noun** strikeout %}
- BrE: /ˈstraɪkaʊt/
- NAmE: /ˈstraɪkaʊt/
(in baseball 棒球) a situation in which the player who is supposed to be hitting the ball has to stop because he or she has tried to hit the ball three times and failed (三击不中) 出局;三振出局
{% endnote %}
**Topics** [Sports: ball and racket sports](https://www.oxfordlearnersdictionaries.com/topic/sports-ball-and-racket-sports?level=c2) **{% label @C2 %}**
- **strike something ↔ out/through**
to remove something by drawing a line through it 画掉;删去
{% note primary **synonym** cross something ↔ out/through %}
to draw a line through a word, usually because it is wrong 画掉,删掉(错字)
{% endnote %}
- *The editor struck out the whole paragraph.* 编辑把整段全部删去了
### strike through
- **strike something ↔ out/through**
to remove something by drawing a line through it 画掉;删去
{% note primary **synonym** cross something ↔ out/through %}
to draw a line through a word, usually because it is wrong 画掉,删掉(错字)
{% endnote %}
- *The editor struck out the whole paragraph.* 编辑把整段全部删去了
### strike up
- **strike up (with something) | strike up something**
(of a band, an orchestra, etc.乐队等) to begin to play a piece of music 开始演奏
- *The orchestra struck up and the curtain rose.* 管弦乐队奏起音乐,幕启。
- *The band struck up a waltz.* 乐队奏起一支华尔兹舞曲。
- **strike up something (with somebody)**
to begin a friendship, a relationship, a conversation, etc. (和某人)建立友谊,开始来往,交谈起来
- *He would often strike up conversations with complete strangers.* 他爱和完全不相识的人攀谈。
# Noun
## Pronunciation
- BrE: /straɪk/
- NAmE: /straɪk/
## Explanation
### {% label primary@of workers 工人 %}
1. **{% label @B2 %}** a period of time when an organized group of employees of a company stops working because of an argument over pay or conditions 罢工;罢课;罢市
- *the miners'/firefighters'/teachers' strike* 矿工/消防员/教师罢工
- *a strike by teachers* 教师举行的罢课
- *a **one-day strike*** 罢工一天
- *an unofficial strike* 未经批准的罢工
- *Union leaders **called a strike**.* 工会领导人号召罢工。
- *Air traffic controllers are threatening to **go on strike**.* 空中交通管制员威胁要罢工。
- *Half the workforce are now **(out) on strike**.* 现在有半数职工罢工。
- *to come out on strike* 举行罢工
- *The train drivers have voted to **take strike action**.* 火车司机投票表决采取罢工行动。
- *The student union has called for a **rent strike*** (= a refusal to pay rent as a protest). 学生会呼吁拒缴房租。
{% note primary **see also** climate strike, general strike, hunger strike %}
- climate strike
- BrE: /ˈklaɪmət straɪk/
- NAmE: /ˈklaɪmət straɪk/
the act of not going to school or work in order to join a public protest to demand action against climate change 气候罢工:为了参加公众抗议而要求采取行动以应对气候变化的不上学或工作的行为
- *Millions of people around the world joined the climate strike on Friday.* 周五,全世界数百万人加入了气候罢工。
- general strike
- BrE: /ˌdʒenrəl ˈstraɪk/
- NAmE: /ˌdʒenrəl ˈstraɪk/
a period of time when most or all of the workers in a country go on strike 总罢工
- hunger strike
- BrE: /ˈhʌŋɡə straɪk/
- NAmE: /ˈhʌŋɡər straɪk/
\[countable, uncountable\] the act of refusing to eat for a long period of time in order to protest about something 绝食(抗议)
- *to **be on/go on hunger strike*** 进行绝食抗议
{% endnote %}
{% note primary Extra Examples %}
- *More train strikes are threatened.* 铁路工人威胁要举行更多罢工。
- *The New York transit strike is in its second day.* 纽约公交工人的罢工进入了第二天。
- *The army was used to help break the strike.* 当局动用了军队来终止罢工。
- *The new government banned strikes.* 新政府禁止罢工。
- *The shipyard voted to launch a sympathy strike in support of the machinists.* 造船厂投票决定举行罢工,以声援机械师。
- *The strike paralysed the port.* 罢工使港口陷于瘫痪。
- *The first wave of strikes began in January.* 第一波罢工始于 1 月份。
- *Miners staged a one-day strike in support of the steel workers.* 矿工罢工一天以声援钢铁工人。
- *The union held a national strike ballot on the issue.* 工会就这个问题举行了全国罢工投票。
{% endnote %}
**Topics** [Working life](https://www.oxfordlearnersdictionaries.com/topic/working-life?level=b2) **{% label @B2 %}**, [Social issues](https://www.oxfordlearnersdictionaries.com/topic/social-issues?level=b2) **{% label @B2 %}**
{% note primary Oxford Collocations Dictionary %}
- **adjective**
- long
- short
- one-day
- …
- **… of strikes**
- series
- wave
- **verb + strike**
- be on
- come out on
- go on
- …
- **strike + verb**
- occur
- take place
- start
- …
- **strike + noun**
- action
- threat
- ballot
- …
- **preposition**
- during a/​the strike
- strike against
- strike by
- …
- **phrases**
- a ballot for a strike
- a ballot for strike action
- the threat of strikes
- …
{% endnote %}
### {% label primary@attack 攻击 %}
2. **{% label @B2 %}** a military attack, especially by aircraft dropping bombs 军事进攻;袭击;(尤指)空袭
- *They decided to launch a **pre-emptive strike**.* 他们决定发动先发制人的攻击。
- **strike against somebody/something** *Diplomatic efforts have averted a **military strike** against the country.* 外交努力避免了对该国的军事打击。
- *The President ordered **missile strikes** against them in retaliation for the earlier bombing.* 总统下令对他们进行导弹袭击,以报复早些时候的轰炸。
{% note primary **see also** air strike, first strike %}
- air strike
- BrE: /ˈeə straɪk/
- NAmE: /ˈer straɪk/
an attack made by aircraft 空中打击;空袭
- first strike
- BrE: /ˌfɜːst ˈstraɪk/
- NAmE: /ˌfɜːrst ˈstraɪk/
an attack on an enemy made before they attack you 先发制人;首先发起攻击
- *the threat of a strategic first strike* 战略先发制人的威胁
{% endnote %}
**Topics** [War and conflict](https://www.oxfordlearnersdictionaries.com/topic/war-and-conflict?level=b2) **{% label @B2 %}**
{% note primary Oxford Collocations Dictionary %}
- **adjective**
- air
- missile
- nuclear
- …
- **verb + strike**
- carry out
- launch
- make
- …
- **strike + verb**
- force
- aircraft
- **preposition**
- in a/​the strike
- strike against
- strike on
- …
{% endnote %}
### {% label primary@hitting/kicking 击;踢 %}
3. \[usually singular\] an act of hitting or kicking something/somebody 击;打;踢
- *His spectacular strike in the second half made the score 2–0.* 他在下半场令人叹为观止的一脚射门把比分改写为 2:0。
{% note primary **see also** bird strike, lightning %}
- bird strike
- BrE: /ˈbɜːd straɪk/
- NAmE: /ˈbɜːrd straɪk/
an occasion when a bird hits an aircraft 鸟撞击飞机事故;鸟击
- *The aircraft suffered multiple bird strikes immediately after take-off.* 飞机起飞后立即遭到多次鸟撞。
- lightning
- BrE: /ˈlaɪtnɪŋ/
- NAmE: /ˈlaɪtnɪŋ/
\[uncountable\] a flash, or several flashes, of very bright light in the sky caused by electricity闪电
- *a **flash of lightning*** 一道闪电
- *a violent storm with **thunder and lightning*** 夹着雷鸣电闪的暴风雨
- *He was **struck by lightning** and killed*. 他被闪电击中而死。
- ***Lightning strikes** caused scores of fires across the state.* 雷击给整个州造成了多起火灾。
{% endnote %}
### {% label primary@in baseball 棒球 %}
4. an unsuccessful attempt to hit the ball 击球未中
**Topics** [Sports: ball and racket sports](https://www.oxfordlearnersdictionaries.com/topic/sports-ball-and-racket-sports?level=c2) **{% label @C2 %}**
### {% label primary@in bowling 保龄球 %}
5. a situation in tenpin bowling when a player knocks down all the pins with the first ball 全中(第一球撞倒全部十柱球)
### {% label primary@discovery of oil 石油的发现 %}
6. \[usually singular\] a sudden discovery of something valuable, especially oil (珍贵东西的)意外发现;(尤指石油的)发现
{% note primary Oxford Collocations Dictionary %}
- **adjective**
- air
- missile
- nuclear
- …
- **verb + strike**
- carry out
- launch
- make
- …
- **strike + verb**
- force
- aircraft
- **preposition**
- in a/​the strike
- strike against
- strike on
- …
{% endnote %}
### {% label primary@bad thing/action 坏事;不利的行动 %}
7. **strike (against somebody/something)** (*North American English*) a bad thing or action that damages somebody/something’s reputation (有损声誉的)不利因素,打击
- *The amount of fuel that this car uses is a big strike against it.* 耗油量大是这辆车的一大缺点。
## Word Origin
Old English *strīcan* ‘go, flow’ and ‘rub lightly’, of West Germanic origin; related to German *streichen* ‘to stroke’, also to **stroke**. The sense ‘deliver a blow’ dates from Middle English.
## Idioms
- **three strikes and you’re out | the three strikes rule**
used to describe a law that says that people who commit three crimes will go straight to prison 三振出局法(三次犯罪即入狱的法律)
# 惯用法
1. A struck B 是“A 打 B 一下”。A struck *at* B 是“A 做出打 B 的动作(未必打着 B)”。
2. The idea strikes me as (*being*) original 里的 being 可有可无。
3. on strike(罢工)是英美通用的,但在美国往往说 on *a* strike。
# Reference
1. Diana Lea, Jennifer Bradbery. *Oxford Advanced Learner's Dictionary, 10th edition.* Oxford University Press, 2020.
2. Margaret Deuter, Jennifer Bradbery, Joanna Turnbull. *牛津高阶英汉双解词典,第 9 版.* 商务印书馆, 2018.
3. 葛传槼. *葛传槼英语惯用法词典.* 上海译文出版社, 2012.
@@ -0,0 +1,180 @@
---
title: resort
mathjax: false
comments: true
copyright: true
toc:
enable: true
number: false
wrap: true
expand_all: true
max_depth: 3
tags:
- 牛津5000
- 英语词汇
categories:
- 英语学习
abbrlink: d69ad86a
date: 2023-05-25 23:10:01
---
# Noun
## Pronunciation
- BrE: /rɪˈzɔːt/
- NAmE: /rɪˈzɔːrt/
## Explanation
1. **{% label @B2 %}** \[countable\] a place where a lot of people go on holiday 旅游胜地;度假胜地
- ***seaside/mountain resorts*** 海滨/山区度假胜地
- *They spent a month at a fashionable **ski resort** in Switzerland.* 他们在瑞士一个时尚的滑雪胜地呆了一个月。
- *a popular **tourist resort*** 受欢迎的旅游胜地
- *(British English also)* *a popular **holiday resort*** 受欢迎的旅游胜地
- *the **resort town** of Byron Bay* 度假小镇拜伦贝城
- *destination resorts such as Atlantis in the Bahamas* 巴哈马亚特兰蒂斯之类的度假胜地
<!-- more -->
{% note primary Wordfinder %}
abroad | backpack | border | guide | passport | resort | sightseeing | tourist | travel | visa
{% endnote %}
{% note primary Collocations **Travel and tourism 旅游和旅游业** %}
- **Holidays/​vacations 假期**
- **have/​take** *(British English)* a holiday/*(North American English)* a vacation/​a break/​a day off/*(British English)* a gap year 休假;短期休假;休一天假;休空缺年假
- **go on/​be on** holiday/​vacation/​leave/​honeymoon/​safari/​a trip/​a tour/​a cruise/​a pilgrimage 去/在度假/休假/度蜜月/游猎/旅游/观光/乘船游览/朝圣
- **go** backpacking/​camping/​hitchhiking/​sightseeing 去背包旅行/露营/搭顺风车旅行/观光游览
- **plan** a trip/​a holiday/​a vacation/​your itinerary 计划旅行/假期/行程
- **book** accommodation/​a hotel room/​a flight/​tickets 预订住宿/酒店房间/航班/票
- **have/​make/​cancel** a reservation/(*especially British English)* booking 预订;取消预订
- **rent** a villa/*(both British English)* a holiday home/​a holiday cottage 租一座度假别墅/一个度假住所/一座度假小别墅
- *(especially British English)* **hire/** *(especially North American English)* **rent** a car/​bicycle/​moped 租借一辆汽车/自行车/摩托自行车
- **stay in** a hotel/​a bed and breakfast/​a youth hostel/​a villa/*(both British English)* a holiday home/​a caravan 住在酒店/提供住宿和早餐的旅馆/青年旅舍/度假别墅/度假住所/旅行拖车里
- **cost/​charge $100 a/​per night for** a single/​double/​twin/​standard/*(British English)* en suite room 单人房/双人房/标间/套房一晚花费/要价 100 美元
- **check into/​out of** a hotel/​a motel/​your room 入住/结账离开酒店/汽车旅馆/房间
- **pack/​unpack** your suitcase/​bags 把东西装进手提箱/旅行包;取出手提箱/旅行包里的东西
- **call/​order** room service 打电话叫/叫客房服务
- **cancel/​cut short** a trip/​holiday/​vacation 取消/缩短旅程/假期
- **Foreign travel 出国旅行**
- **apply for/​get/​renew** a/​your passport 申请/拿到/续签护照
- **take out/​buy/​get** travel insurance 获得/购买/取得旅游保险
- **catch/​miss** your plane/​train/​ferry/​connecting flight 赶上/错过飞机/火车/渡船/转乘航班
- **fly (in)/travel in** business/​economy class 乘坐商务/经济舱飞行/旅行
- **make/​have** a brief/​two-day/​twelve-hour stopover/*(North American English also)* layover in Hong Kong 在香港作短暂的/两天的/十二小时的中途停留
- **experience/​cause/​lead** to delays 遇上/引起/导致延误
- **check (in)/collect/​get/​lose** (your) *(especially British English)* luggage/*(especially North American English)* baggage 托运/取/弄丢行李
- **be charged for/​pay** excess baggage 被收取/支付超重行李费
- **board/​get on/​leave/​get off** the aircraft/​plane/​ship/​ferry 上/下飞机/船/渡船
- **taxi down/​leave/​approach/​hit/​overshoot** the runway 在跑道上滑行;离开/接近/降落在/冲出跑道
- **experience/​hit/​encounter** severe turbulence 遇到强烈的气流
- **suffer from/​recover from/​get over** your jet lag/​travel sickness 遭受时差反应/晕车;从时差反应/晕车恢复过来;克服时差反应/晕车
- **The tourist industry 旅游业**
- **attract/​draw/​bring** tourists/​visitors 吸引游客
- **encourage/​promote/​hurt** tourism 鼓励/促进/损害旅游业
- **promote/​develop** ecotourism 促进/发展生态旅游
- **build/​develop/​visit** a tourist/​holiday/*(especially British English)* seaside/​beach/​ski resort 建立/开发/参观旅游/假日/海滨/海滩/滑雪胜地
- **work for/​be operated by** a major hotel chain 就职于一家大型连锁酒店;由一家大型连锁酒店经营
- **be served by/​compete with** low-cost/*(especially North American English)* low-fare/​budget airlines 由廉价航空公司提供服务;与廉价航空公司竞争
- **book something through/​make a booking through/​use** a travel agent 通过旅行社预订;经旅行社代办
- **contact/​check with** your travel agent/​tour operator 联系旅行社;向旅行社咨询
- **book/​be on/​go on** a package deal/​holiday/​tour 预订/进行/去包价旅游
- **buy/​bring back** (tacky/​overpriced) souvenirs 购买/带回(低劣的/定价过高的)纪念品
{% endnote %}
**Topics** [Holidays](https://www.oxfordlearnersdictionaries.com/topic/holidays?level=b2) **{% label @B2 %}**
2. \[uncountable\] resort to something the act of using something, especially something bad or unpleasant, because nothing else is possible 诉诸;求助;采取
{% note primary **synonym** recourse %}
- BrE: /rɪˈkɔːs/
- NAmE: /ˈriːkɔːrs/
\[uncountable\] *(formal)* the fact of having to, or being able to, use something that can provide help in a difficult situation依靠;依赖;求助
- *Your only recourse is legal action.* 你的唯一依靠就是诉诸法律。
- **recourse to something** *The government, when necessary, has recourse to the armed forces.* 政府在必要时可以动用军队。
- **without recourse to something** *She made a complete recovery without recourse to surgery.* 她未做手术就完全恢复了健康。
{% endnote %}
- *There are hopes that the conflict can be resolved without resort to violence.* 冲突有望不需要诉诸武力而得到解决。
3. **the first/last/final resort** the first or last course of action that you should or can take in a particular situation 应急措施;可首先(或最后)采取的手段
- *Strike action should be regarded as a last resort, when all attempts to negotiate have failed.* 罢工应该是最后一着,在所有的谈判努力都告失败时才使用。
- *In the last resort (= in the end) everyone must decide for themselves.* 最后人人都得自己作决定。
## Word Origin
late Middle English (denoting something one can turn to for assistance): from Old French *resortir*, from *re-* ‘again’ + *sortir* ‘come or go out’. The sense ‘place frequently visited’ dates from the mid 18th cent.
# Verb
## Pronunciation
- BrE: /rɪˈzɔːt/
- NAmE: /rɪˈzɔːrt/
## Verb Forms
- present simple I / you / we / they **resort**
- /rɪˈzɔːt/
- /rɪˈzɔːrt/
- he / she / it **resorts**
- /rɪˈzɔːts/
- /rɪˈzɔːrts/
- past simple **resorted**
- /rɪˈzɔːtɪd/
- /rɪˈzɔːrtɪd/
- past participle **resorted**
- /rɪˈzɔːtɪd/
- /rɪˈzɔːrtɪd/
- -ing form **resorting**
- /rɪˈzɔːtɪŋ/
- /rɪˈzɔːrtɪŋ/
## Phrasal Verbs
### resort to
- **resort to something**
to make use of something, especially something bad, as a means of achieving something, often because there is no other possible solution诉诸;求助于;依靠
{% note primary **synonym** recourse %}
- BrE: /rɪˈkɔːs/
- NAmE: /ˈriːkɔːrs/
\[uncountable\] *(formal)* the fact of having to, or being able to, use something that can provide help in a difficult situation依靠;依赖;求助
- *Your only recourse is legal action.* 你的唯一依靠就是诉诸法律。
- **recourse to something** *The government, when necessary, has recourse to the armed forces.* 政府在必要时可以动用军队。
- **without recourse to something** *She made a complete recovery without recourse to surgery.* 她未做手术就完全恢复了健康。
{% endnote %}
- *They felt obliged to resort to violence.* 他们觉得有必要诉诸暴力。
- *They achieved their demands without having to resort to force.* 他们没有诉诸武力就实现了他们的要求。
- *We had to resort to another loan from the bank.* 我们不得不求助于银行的另一笔贷款。
- **resort to doing something** *We may have to resort to using untrained staff.* 我们也许只能使用未受过训练的员工了。
# Reference
1. Diana Lea, Jennifer Bradbery. *Oxford Advanced Learner's Dictionary, 10th edition.* Oxford University Press, 2020.
2. Margaret Deuter, Jennifer Bradbery, Joanna Turnbull. *牛津高阶英汉双解词典,第 9 版.* 商务印书馆, 2018.
@@ -0,0 +1,334 @@
---
title: bound
mathjax: false
comments: true
copyright: true
toc:
enable: true
number: false
wrap: true
expand_all: true
max_depth: 3
tags:
- 牛津5000
- 英语词汇
categories:
- 英语学习
abbrlink: a50e7db6
date: 2023-06-01 10:54:03
---
# Adjective
**see also [bind][]**
## Pronunciation
- BrE: /baʊnd/
- NAmE: /baʊnd/
## Explanation
\[not before noun\]
1. **{% label @B2 %}** **bound to do/be something** certain or likely to happen, or to do or be something一定会;很可能会
- *There are bound to be changes when the new system is introduced.* 引进新系统后一定会发生变化。
- *It's bound to be sunny again tomorrow.* 明天肯定又是阳光灿烂。
- *You've done so much work—you're bound to pass the exam.* 你下了这么大功夫,考试准能及格。
- *It was bound to happen sooner or later* (= we should have expected it). 这事迟早都是要发生的。
- *These problems were almost bound to arise.* 这些问题几乎注定了会出现。
- *You're bound to be nervous the first time* (= it's easy to understand). 第一次总是会紧张的。
<!-- more -->
{% note primary Synonyms **certain**%}
bound | sure | definite | guaranteed
These are all words describing something that will definitely happen or is definitely true.
- **certain** that you can rely on to happen or be true:
- *It’s certain that they will agree.* 他们肯定会同意。
- *They are certain to agree.* 他们肯定会同意。
- **bound** \[not before noun\] certain to happen, or to do or be something. 指肯定会、一定会
> Bound is **only used in the phrase** *bound to do/​be, etc.*:
>
> - *You’ve done so much work—you’re bound to pass the exam.*
> - *There are bound to be changes when the new system is introduced.*
- **sure** certain to happen or be true; that can be trusted or relied on:
- *She’s sure to be picked for the team.* 她肯定会入选该队。
- *It’s sure to rain.* 必定会下雨。
- **definite** (*rather informal*) certain to happen; that is not going to change:指必将发生、不会改变:
- *Is it definite that he’s leaving?* 他肯定要离开吗?
- **strike** (*formal*) to hit somebody/​something hard: 指猛烈地撞、碰、撞击、碰撞:
- *The ship struck a rock.* 船触礁了。
- **guaranteed** certain to have a particular result:
- *That kind of behaviour is guaranteed to make him angry.* 那样的行为肯定会让他生气。
- Patterns
- certain/​sure **of** something
- certain/​bound/​sure/​guaranteed **to do something**
- certain/​definite **that…**
- I **couldn’t say for** certain/​sure/​definite.
{% endnote %}
**Topics** [Doubt, guessing and certainty B2][] **{% label @B2 %}**
{% note primary Oxford Collocations Dictionary %}
- **verbs**
- be
- seem
- **adverb**
- almost
{% endnote %}
2. **{% label @C1 %}** forced to do something by law, duty or a particular situation 受(法律、义务或情况)约束(必须做某事);有义务(做某事)
- **bound by something** *We are not bound by the decision.* 我们不受该决定的约束。
- *You are bound by the contract to pay before the end of the month.* 按照合同规定,你必须在月底前付款。
- **bound (by something) to do something** (*formal*) *I am **bound to say** I disagree with you on this point.* 我觉得有必要指出,在这一点上我不同意你的观点。
- *They are legally bound to appear in court.* 他们依法必须出庭。
{% note primary Extra Examples %}
- *He was legally bound to report them to the authorities.* 他有法律义务将这些报告给当局。
- *Officials are bound by law to investigate any possible fraud.* 法律规定官员有义务调查任何可能的欺诈行为。
- *The country will not **be held bound** by a treaty signed by the previous regime.* 国家不会为前政权签署的条约所束缚。
- *The president said the country could not be held bound by a treaty signed by the previous regime.* 总统说,国家不应为前政权签署的条约所束缚。
- *We are legally bound by this decision.* 我们在法律上受这一决定的束缚。
{% endnote %}
{% note primary Oxford Collocations Dictionary %}
- **verbs**
- be
- feel
- become
- …
- **adverb**
- absolutely
- irrevocably
- by law
- …
- **preposition**
- by
{% endnote %}
3. (in compounds) prevented from going somewhere or from working normally by the conditions mentioned 因…受阻(或不能正常工作)
- *Strike-bound travellers face long delays.* 因罢工滞留的旅客要耽搁很长时间。
- *fogbound airports* 因雾不能正常作业的机场
{% note primary Oxford Collocations Dictionary %}
- **verbs**
- be
- **adverb**
- homeward
- outward
- **preposition**
- for
{% endnote %}
4. (also in compounds) travelling, or ready to travel, in a particular direction or to a particular place 正旅行去(某地);准备前往(某地)
- *homeward bound* (= going home) 在回家途中
- *Paris-bound* 前往巴黎的
- ***northbound/southbound/eastbound/westbound*** 向北/向南/向东/向西行进的
- **bound for…** *a plane bound for Dublin* 开往都柏林的飞机
- *tourists who are bound for Europe* 前往欧洲的游客
- *college-bound high school students* 上大学的高中生
{% note primary Oxford Collocations Dictionary %}
- **verbs**
- be
- **adverb**
- homeward
- outward
- **preposition**
- for
{% endnote %}
## Word Origin
*adjective* sense 4 Middle English *boun* (in the sense ‘ready, dressed’), from Old Norse *búinn*, past participle of *búa* ‘get ready’; the final *-d* is euphonic, or influenced by other adjective senses of **bound**.
## Idioms
1. **be bound together by/in something**
to be closely connected 因…(或在…方面)密切联系
- *communities bound together by customs and traditions* 因习俗和传统而结合在一起的社区
2. **be bound up in something**
very busy with something; very interested or involved in something 忙于某事;热衷于某事
- *He's too bound up in his work to have much time for his children.* 他工作太忙,没有很多时间陪孩子们。
3. **bound and determined**
(*North American English*) very determined to do something矢志不渝;下定决心
- *I came here bound and determined to put the last 12 months behind me.* 我来到这里,下定决心把过去的12个月抛在脑后。
4. **bound up with something**
closely connected with something 和某事密切相关
- *From that moment my life became inextricably bound up with hers.* 从那一刻起,我的一生就和她结下不解之缘。
5. **(feel) honour-bound to do something**
(*formal*) to feel that you must do something because of your sense of moral duty (感到)道义上应做某事
- *She felt honour-bound to attend as she had promised to.* 她觉得既然答应了就应该出席。
- *He felt honour bound to help her.* 他觉得在道义上应该帮助她。
{% note primary **compare** duty-bound %}
\[not before noun\] (*formal*) having to do something because it is your duty 责无旁贷;义不容辞
{% endnote %}
**Topics** [Permission and obligation][] **{% label @C2 %}**
6. **I’ll be bound**
(*old-fashioned, British English, informal*) I feel sure我敢肯定
- They’re up to some mischief, I’ll be bound!我敢肯定,他们在搞恶作剧!
**Topics** [Doubt, guessing and certainty C2][] **{% label @C2 %}**
# Verb
**see also [bind][]**
## Pronunciation
- BrE: /baʊnd/
- NAmE: /baʊnd/
## Verb Forms
- present simple I / you / we / they bound
- BrE: /baʊnd/
- NAmE: /baʊnd/
- he / she / it bounds
- BrE: /baʊndz/
- NAmE: /baʊndz/
- past simple bounded
- BrE: /ˈbaʊndɪd/
- NAmE: /ˈbaʊndɪd/
- past participle bounded
- BrE: /ˈbaʊndɪd/
- NAmE: /ˈbaʊndɪd/
- -ing form bounding
- BrE: /ˈbaʊndɪŋ/
- NAmE: /ˈbaʊndɪŋ/
## Explanation
1. \[transitive\] **+ adv./prep.** to run with long steps, especially in an enthusiastic way 跳跃着跑
- *The dogs bounded ahead.* 那些狗在前面蹦蹦跳跳地跑。
{% note primary Extra Examples %}
- *He bounded back to meet us.* 他跳回来迎接我们。
- *Louis came bounding down the stairs.* 路易斯蹦蹦跳跳地下了楼
- *The dog bounded up to him.* 那只狗向他扑来。
- *A man bounded up to her and shook her hand.* 一个男人跳到她面前和她握手。
- *He braked sharply as a deer bounded across the road.* 当一只鹿飞奔过马路时,他猛地刹车。
{% endnote %}
2. \[transitive, usually passive\] (*formal*) to form the edge or limit of an area 形成…的边界(或界限)
- **be bounded by something** *The field was bounded on the left by a wood.* 那片地左边依傍着一片树林。
## Word Origin
*verb* sense 1 early 16th cent. (as a noun): from French *bond* (noun), *bondir* (verb) ‘resound’, later ‘rebound’, from late Latin *bombitare*, from Latin *bombus* ‘humming’. *verb* sense 2 Middle English (in the senses ‘landmark’ and ‘borderland’): from Old French *bodne*, from medieval Latin *bodina*, earlier *butina*, of unknown ultimate origin.
# Noun
**see also [bind][]**
## Pronunciation
- BrE: /baʊnd/
- NAmE: /baʊnd/
## Explanation
1. a high or long jump 蹦跳;跳跃
- *The dog cleared the gate in one bound.* 那狗一跳就越过了栅门。
{% note primary **see also** bounds %}
- BrE: /baʊndz/
- NAmE: /baʊndz/
\[plural\]
the accepted or furthest limits of something 限制范围;极限
- ***beyond/outside/within the bounds of** decency* 没体统;有体统
- *I am afraid your behaviour was beyond the bounds of decency.* 恐怕你的行为超出了体面的范围。
- *Public spending must be kept within reasonable bounds.* 公共开支必须控制在合理的范围内。
- *It was not **beyond the bounds of possibility** that they would meet again one day.* 他们有一天会再度相遇,这不是没有可能。
- *His enthusiasm **knew no bounds*** (= was very great). 他有无限热情。
{% endnote %}
## Word Origin
noun early 16th cent. (as a noun): from French *bond* (noun), *bondir* (verb) ‘resound’, later ‘rebound’, from late Latin *bombitare*, from Latin *bombus* ‘humming’.
## Idioms
1. **by/in leaps and bounds**
very quickly; in large amounts 非常迅速;飞跃地;突飞猛进;大量地
- *Her health has improved in leaps and bounds.* 她的健康已迅速好转。
- *His technique has come on in leaps and bounds this season.* 这个赛季他的技术突飞猛进。
# 惯用法
bound 后面接不定式从前在英国作“将不得不……”解,在美国作“决意……”解,如 He is bound to come 在英国是“他将不得不来”,在美国是“他决意来”。但现在似乎在英美通常都作“一定将……”解,如 It is bound to rain 是“肯定会下雨”。
# Reference
1. Diana Lea, Jennifer Bradbery. *Oxford Advanced Learner's Dictionary, 10th edition.* Oxford University Press, 2020.
2. Margaret Deuter, Jennifer Bradbery, Joanna Turnbull. *牛津高阶英汉双解词典,第 9 版.* 商务印书馆, 2018.
3. 葛传槼. *葛传槼英语惯用法词典.* 上海译文出版社, 2012.
[bind]: https://www.oxfordlearnersdictionaries.com/definition/english/bind_1
[Doubt, guessing and certainty B2]: https://www.oxfordlearnersdictionaries.com/topic/doubt-guessing-and-certainty?level=b2
[Permission and obligation]: https://www.oxfordlearnersdictionaries.com/topic/permission-and-obligation?level=c2
[Doubt, guessing and certainty C2]: https://www.oxfordlearnersdictionaries.com/topic/doubt-guessing-and-certainty?level=c2
@@ -0,0 +1,800 @@
---
title: "Josh's Note — 最优阵列处理<br>Part 2.1 谱加权"
mathjax: true
comments: true
copyright: true
toc:
enable: true
number: false
wrap: true
expand_all: true
max_depth: 4
categories:
- - Josh 的学习笔记
- 最优阵列处理
- 线形阵列和孔径的合成
tags:
- 阵列信号处理
- 谱加权
- 线阵
abbrlink: 61f0754c
date: 2023-06-19 16:25:26
---
&emsp;&emsp;谱加权(Spectral Weighting)技术主要研究对如何每个传感器输出进行加权,以获得具有理想性质的频率-波数响应和波束方向图。加权的过程在一些文献中也称为锐化 (tapering) 或赋形 (shading) 。许多阵列加权技术等价于时间序列谱分析中的加窗或锐化 (Taper) 技术。
&emsp;&emsp;对于一个阵元间距小于或等于 $\lambda/2$ 的线阵,由于不需要考虑栅瓣和空域混迭,可以直接应用连续函数的傅里叶变换理论对权重和频率-波数响应之间存在的傅里叶变换关系进行分析。本文关注线性阵列,讨论如何在降低旁瓣的同时使主瓣宽度的增长最小(最小化方向性损失),将尝试不同的权值矢量,并分析它们的性能。
&emsp;&emsp;考虑傅里叶变换对
$$\begin{equation}
\varUpsilon(\omega,k) = \int_{-\infty}^\infty w_a^\ast (z) e^{-jkz}\, \mathrm{d}z
\end{equation}$$
$$\begin{equation}
w_a^\ast (z) = \frac{1}{2\pi} \int_{-\infty}^\infty \varUpsilon(\omega,k) e^{jkz}\, \mathrm{d}k
\end{equation}$$
其中省略了 $k_z$ 的下标 $z$。
<!-- more -->
# 1. 均匀加权
&emsp;&emsp;均匀权值为
$$\begin{equation}
w_n = \frac{1}{N}, \quad n = 0,\cdots,N-1
\end{equation}$$
在 $u$ 空间的波束方向图为
$$\begin{equation}
\begin{aligned}
B_u(u) &= \frac{1}{N} \frac{\sin\left( \displaystyle\frac{\pi Nd}{\lambda} u \right)}{\sin\left( \displaystyle\frac{\pi d}{\lambda} u \right)} \\
&= \boldsymbol{w}^\mathrm{H}\boldsymbol{v}_u(u) = e^{-j\left(\frac{N-1}{2} \right) \frac{2\pi d}{\lambda} u} \sum_{n=0}^{N-1} w_n^\ast e^{j n \frac{2\pi d}{\lambda} u}
\end{aligned}
\end{equation}$$
对于**标准线阵**,有
$$\begin{equation}
B_u(u) = \frac{1}{N} \frac{\sin\left( \displaystyle\frac{\pi Nu}{2} \right)}{\sin\left( \displaystyle\frac{\pi u}{2} \right)}
\end{equation}$$
方向性
$$\begin{equation}
D = N
\end{equation}$$
由于下面经考虑实对称的权值,因此将阵元的位置也对称地进行表示,第 $n$ 个阵元的位置表示为
$$\begin{equation}
\tilde{n} = n - \frac{N-1}{2}, \quad n = 0,\cdots,N-1,\quad \tilde{n} = -\frac{N-1}{2}, \cdots, \frac{N-1}{2}
\end{equation}$$
# 2. Cosine 加权
&emsp;&emsp;当 $N$ 为奇数时,Cosine 权值为
$$\begin{equation}
w(\tilde{n}) = \sin\left( \frac{\pi}{2N} \right)\cos\left( \pi\frac{\tilde{n}}{N} \right), \quad -\frac{N-1}{2} \leqslant \tilde{n} \leqslant \frac{N-1}{2}
\end{equation}$$
其中归一化因子 $\sin\left( \displaystyle\frac{\pi}{2N} \right)$ 是一个常数,使得 $B_u (0) = 1$。把 Cosine 写成指数形式,有
$$\begin{equation}
w(\tilde{n}) = \sin\left( \frac{\pi}{2N} \right)\left[ \frac{e^{j\frac{\pi\tilde{n}}{N}} + e^{-j\frac{\pi\tilde{n}}{N}}}{2} \right], \quad -\frac{N-1}{2} \leqslant \tilde{n} \leqslant \frac{N-1}{2}
\end{equation}$$
利用指数形式的阵列流形矢量,可得波束方向图
$$\begin{equation}
B_u(u) = \frac{1}{2} \sin\left( \frac{\pi}{2N} \right) \left\{ \sum_{\tilde{n} = -\frac{N-1}{2}}^{\frac{N-1}{2}} e^{j\frac{\pi \tilde{n}}{N}} e^{-j \tilde{n} \pi u} + \sum_{\tilde{n} = -\frac{N-1}{2}}^{\frac{N-1}{2}} e^{-j\frac{\pi \tilde{n}}{N}} e^{-j \tilde{n} \pi u} \right\}
\end{equation}$$
其中第一项和第二项分别对应指向 $u_s = 1/N$ 和 $u_s = -1/N$ 的常规波束方向图,因此
$$\begin{equation}
B_u(u) = \frac{1}{2} \sin\left( \frac{\pi}{2N} \right) \left\{ \frac{\sin\left( \displaystyle\frac{N\pi}{2} \left( u - \frac{1}{N} \right) \right)}{\sin\left( \displaystyle\frac{\pi}{2} \left( u - \frac{1}{N} \right) \right)} + \frac{\sin\left( \displaystyle\frac{N\pi}{2} \left( u + \frac{1}{N} \right) \right)}{\sin\left( \displaystyle\frac{\pi}{2} \left( u + \frac{1}{N} \right) \right)} \right\}
\end{equation}$$
下面将要介绍的很多方向图都是常规波束的叠加。[图 2-1-1](#fig.2-1-1) 给出了一个 11 阵元阵列使用 Cosine 加权得到的波束方向图,同时还给出了常规波束方向图作为参考。可以看到,旁瓣得到了降低,但是主波束变得更宽。两个波束方向图的参数为
| 加权方式 | HPBW | $BW_{NN}$ | 第一旁瓣高度 | $D_N$[^1] |
| :--: | :--: | :--: | :--: | :--: |
| Uniform | $0.89 \displaystyle\frac{2}{N}$ | $2.0 \displaystyle\frac{2}{N}$ | $-13.0 \text{dB}$ | $1$ |
| Cosine | $1.18 \displaystyle\frac{2}{N}$ | $3.0 \displaystyle\frac{2}{N}$ | $-23.5 \text{dB}$ | $0.816$ |
<a id="fig.2-1-1"></a>
![图 2-1-1 均匀加权和 Cosine 加权的波束方向图: $N = 11$](../images/post/2023-06-19-josh-oap-part-2-1/2023-06-19-josh-oap-part-2-1-010-BeamPatternForUniformAndCosineWeighting.svg){width=700px}
{% note primary MATLAB Code %}
``` matlab fig3_01.m
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Figure 3.1
% Cosine weighting: Array beam patterns
% Kristine Bell
% Modified by Xin Zhang 3/17/99
% Lillian 04/16/2001, K. Bell 7/20/01, K. Bell 9/30/01
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear all
close all
M=11;
d=0.5; % sensor spacing wrt wavelength
D = (-(M-1)/2:1:(M-1)/2)*d; % sensor positions in wavelengths
% weights, normalized so that w(0)=1
W_unf = ones(1,M);
W_cos = cos(pi*D*2/M);
% Beampatterns
u = 0:0.001:1;
A = exp(-1i*2*pi*D.'*u);
G_unf = W_unf*A;
G_unf = G_unf/(max(abs(G_unf)));
G_cos = W_cos*A;
G_cos = G_cos/(max(abs(G_cos)));
figure
% array only
clf
plot(u,20*log10(abs(G_unf)),'--')
hold on
plot(u,20*log10(abs(G_cos)),'-')
hold off
axis([0 1 -80 0])
%title([int2str(M) ' element array'])
h=legend('Uniform','Cosine');
xlabel('$u$','Interpreter','latex')
ylabel('Beam pattern (dB)')
```
{% endnote %}
# 3. 升 Cosine 加权
&emsp;&emsp;可以把矩形均匀加权和 Cosine 加权组合起来,获得两种加权方法一些理想性质的组合。对应的阵列加权为
$$\begin{equation}
w(\tilde{n}) = c(p) \left( p + (1-p) \cos \left( \pi \frac{\tilde{n}}{N} \right)\right), \quad \tilde{n} = -\frac{N-1}{2}, \cdots, \frac{N-1}{2}
\end{equation}$$
其中归一化常数
$$\begin{equation}
c(p) = \frac{p}{N} + \frac{1-p}{2} \sin\left( \frac{\pi}{2N} \right)
\end{equation}$$
使得 $B_u(0) = 1$。
&emsp;&emsp;在[图 2.1.2](#fig.2-1-2) 中给出了 $p = 0.31, 0.17, 0$ 时的升 Cosine 加权的波束方向图。当 $p$ 减小时,第一旁瓣的高度减小,主波束宽度增加。波束方向图参数如下:
| $p$ | HPBW | $BW_{NN}$ | 第一旁瓣高度 | $D_N$ |
| :--: | :--: | :--: | :--: | :--: |
| 0.31 | $1.03 \displaystyle\frac{2}{N}$ | $2.50 \displaystyle\frac{2}{N}$ | $-20.0 \text{dB}$ | $0.928$ |
| 0.17 | $1.09 \displaystyle\frac{2}{N}$ | $3.70 \displaystyle\frac{2}{N}$ | $-22.0 \text{dB}$ | $0.886$ |
| 0 | $1.18 \displaystyle\frac{2}{N}$ | $3.00 \displaystyle\frac{2}{N}$ | $-23.5 \text{dB}$ | $0.816$ |
<a id="fig.2-1-2"></a>
![图 2-1-2 升 Cosine 加权的波束方向图: $N = 11$](../images/post/2023-06-19-josh-oap-part-2-1/2023-06-19-josh-oap-part-2-1-020-BeamPatternForRaisedCosineWeighting.svg){width=700px}
{% note primary MATLAB Code %}
``` matlab fig3_02.m
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Figure 3.2
% Raised cosine weighting function
% Kristine Bell
% Modified by Xin Zhang 3/17/99
% Lillian Xu 04/16/2001, K. Bell 7/20/01, 9/30/01
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear all
close all
M=11;
d=0.5; % sensor spacing wrt wavelength
D = (-(M-1)/2:1:(M-1)/2)*d; % sensor positions in wavelengths
% weights, normalized so that w(0)=1
p=[0;0.17;0.31;1];
W_rcos = p*ones(1,M)+(ones(4,1)-p)*cos(pi*D*2/M);
% Beampatterns
u = 0:0.001:1;
c=p+(ones(4,1)-p)*2/pi;
A = exp(-1i*2*pi*D.'*u);
G_rcos = W_rcos*A;
for m=1:4
G_rcos(m,:) = G_rcos(m,:)/(max(abs(G_rcos(m,:))));
end
figure
clf
plot(u,20*log10(abs(G_rcos(3,:))),'-.')
hold on
plot(u,20*log10(abs(G_rcos(2,:))),'--')
plot(u,20*log10(abs(G_rcos(1,:))),'-')
hold off
axis([0 1 -80 0])
h=legend({'$p=0.31$','$p=0.17$','$p=0$'},'Interpreter','latex');
xlabel('$u$','Interpreter','latex')
ylabel('Beam pattern (dB)')
```
{% endnote %}
&emsp;&emsp;至此,我们已经可以使 HPBW 变窄,并使得第一旁瓣比均匀分布的情况要低得多。
# 4. Cosine$^m$ 加权
&emsp;&emsp;下面考虑一系列 Cosine 加权,形式为 $\cos^m(\pi \tilde{n} / N)$。阵列的权值为
$$\begin{equation}
w_m(\tilde{n}) = \begin{cases}
c_2 \cos^2 \left( \displaystyle \frac{\pi \tilde{n}}{N} \right),\quad m = 2 \\
c_3 \cos^3 \left( \displaystyle \frac{\pi \tilde{n}}{N} \right),\quad m = 3 \\
c_4 \cos^4 \left( \displaystyle \frac{\pi \tilde{n}}{N} \right),\quad m = 4 \\
\end{cases}
\end{equation}$$
其中 $c_2, c_3, c_4$ 是归一化常数。
&emsp;&emsp;$m=2$ 时的加权有时称为是 Hann 加权[^2]。同样,波束方向图可以利用 Cosine 函数的指数形式来计算。波束方向图在[图 2.1.3](#fig.2-1-3) 中给出。当 $m$ 增加时,旁瓣减小,但是主波束变宽。波束方向图的参数为:
| $m$ | HPBW | $BW_{NN}$ | 第一旁瓣高度 | $D_N$ |
| :--: | :--: | :--: | :--: | :--: |
| 2 | $1.44 \displaystyle\frac{2}{N}$ | $4 \displaystyle\frac{2}{N}$ | $-31.4 \text{dB}$ | $0.667$ |
| 3 | $1.66 \displaystyle\frac{2}{N}$ | $5 \displaystyle\frac{2}{N}$ | $-39.4 \text{dB}$ | $0.576$ |
| 4 | $1.85 \displaystyle\frac{2}{N}$ | $6 \displaystyle\frac{2}{N}$ | $-46.7 \text{dB}$ | $0.514$ |
<a id="fig.2-1-3"></a>
![图 2-1-3 Cosine$^m$ 加权的波束方向图: $N = 11$](../images/post/2023-06-19-josh-oap-part-2-1/2023-06-19-josh-oap-part-2-1-030-BeamPatternForCosineMWeighting.svg){width=700px}
{% note primary MATLAB Code %}
``` matlab fig3_03.m
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Figure 3.3
% Cosine^m weighting: m = 2,3,and 4
% Kristine Bell
% Modified by Xin Zhang 3/17/99
% Lillian Xu 04/16/2001, K. Bell 7/20/01, 9/30/01
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear all
close all
M=11;
d=0.5; % sensor spacing wrt wavelength
D = (-(M-1)/2:1:(M-1)/2)*d; % sensor positions in wavelengths
% weights, normalized so that w(0)=1
W_cos2 = cos(pi*D*2/M).^2;
W_cos3 = cos(pi*D*2/M).^3;
W_cos4 = cos(pi*D*2/M).^4;
% Beampatterns
u = 0:0.001:1;
A = exp(-1i*2*pi*D.'*u);
G_cos2 = W_cos2*A;
G_cos2 = G_cos2/(max(abs(G_cos2)));
G_cos3 = W_cos3*A;
G_cos3 = G_cos3/(max(abs(G_cos3)));
G_cos4 = W_cos4*A;
G_cos4 = G_cos4/(max(abs(G_cos4)));
figure
clf
plot(u,20*log10(abs(G_cos2)),'--')
hold on
plot(u,20*log10(abs(G_cos3)),'-')
plot(u,20*log10(abs(G_cos4)),'-.')
hold off
axis([0 1 -80 0])
h=legend({'$m=2$','$m=3$','$m=4$'},'Interpreter','latex');
xlabel('$u$','Interpreter','latex')
ylabel('Beam pattern (dB)')
```
{% endnote %}
# 5. 升 Cosine 平方加权
&emsp;&emsp;升 Cosine 平方系列的加权为
$$\begin{equation}
\begin{aligned}
w(\tilde{n}) &= c_2 (p) \left\{ p + (1-p) \cos^2 \left( \frac{\pi \tilde{n}}{N} \right) \right\} \\
&= \frac{c_2(p)}{2} \left\{ (1+p) + (1-p) \cos \left( \frac{2 \pi \tilde{n}}{N} \right) \right\}, \quad \tilde{n} = -\frac{N-1}{2}, \cdots, \frac{N-1}{2}
\end{aligned}
\end{equation}$$
其中 $c_2 (p)$ 是归一化常数。下面考虑一个特别的加权,称为 Hamming 加权。
# 6. Hamming 加权
&emsp;&emsp;Hamming 加权利用了矩形方向图和 Cosine 平方方向图的特点,在第一旁瓣的峰值上放置了一个零点。加权函数为
$$\begin{equation}
w(\tilde{n}) = g_0 + g_1 \cos \left( \frac{2 \pi \tilde{n}}{N} \right), \quad \tilde{n} = -\frac{N-1}{2}, \cdots, \frac{N-1}{2}
\end{equation}$$
选择系数 $g_0$ 和 $g_1$ 的使 $u = 3/N$ 的位置上有一个零点,并将正侧向的响应归一化,有
$$\begin{equation}
w(\tilde{n}) = 0.54 + 0.46 \cos \left( \frac{2 \pi \tilde{n}}{N} \right), \quad -\frac{N-1}{2} \leqslant \tilde{n} \leqslant \frac{N-1}{2}
\end{equation}$$
对应升 Cosine 平方加权中 $p = 0.08$ 的情况,得到的波束方向图是三个常规波束方向图的和
$$\begin{equation}
B_u(u) = 0.54 \frac{\sin\left(\displaystyle\frac{N\pi u}{2}\right)}{\sin\left(\displaystyle\frac{\pi u}{2}\right)} + 0.23 \left[ \frac{\sin\left( \displaystyle\frac{N\pi}{2} \left( u - \frac{2}{N} \right) \right)}{\sin\left( \displaystyle\frac{\pi}{2} \left( u - \frac{2}{N} \right) \right)} + \frac{\sin\left( \displaystyle\frac{N\pi}{2} \left( u + \frac{2}{N} \right) \right)}{\sin\left( \displaystyle\frac{\pi}{2} \left( u + \frac{2}{N} \right) \right)} \right]
\end{equation}$$
&emsp;&emsp;[图 2.1.4](#fig.2-1-4) 给出了 Hamming 加权、Hann 加权和 Blackman-Harris 加权的波束方向图。第一个零点的位置在 $u = 4/N$,第一个非零旁瓣的高度为 $-39.5\text{dB}$。由于加权具有步进不连续性(step discontinuity),旁瓣的衰减渐近为 $O(1/n)$。但是,第一个旁瓣被完全对消掉了,尽管剩余的旁瓣衰减得比较慢,它们的幅度都不是很高。而且注意到 Hamming 窗的波束宽度小于 Hann 加权的波束宽度,且第一旁瓣更低。
<a id="fig.2-1-4"></a>
![图 2-1-4 Hann 加权、Hamming 加权和 Blackman-Harris 加权的波束方向图: $N = 11$](../images/post/2023-06-19-josh-oap-part-2-1/2023-06-19-josh-oap-part-2-1-040-BeamPatternForHannHammingAndBlackmanHarrisWeighting.svg){width=700px}
{% note primary MATLAB Code %}
``` matlab fig3_04.m
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Figure 3.4
% Beam patterns for Hann, Hamming, and Blackman-Harris
% Kristine Bell
% Modified by Xin Zhang 3/17/99
% Lillian Xu 04/16/2001, K. Bell 7/20/01, 9/30/01
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Hann, Hamming, Blackman-Harris
% M-element array, d=lambda/2
clear all
close all
M=11;
d=0.5; % sensor spacing wrt wavelength
D = (-(M-1)/2:1:(M-1)/2)*d; % sensor positions in wavelengths
% weights, normalized so that w(0)=1
W_Hann = 0.5*(ones(1,M)+cos(2*pi*D*2/M));
W_Hamm = 0.54*ones(1,M)+0.46*cos(2*pi*D*2/M);
W_BH = 0.42*ones(1,M)+0.5*cos(2*pi*D*2/M)+0.08*cos(4*pi*D*2/M);
% Beampatterns
u = 0:0.001:1;
A = exp(-1i*2*pi*D.'*u);
G_Hann = W_Hann*A;
G_Hann = G_Hann/(max(abs(G_Hann)));
G_Hamm = W_Hamm*A;
G_Hamm = G_Hamm/(max(abs(G_Hamm)));
G_BH = W_BH*A;
G_BH = G_BH/(max(abs(G_BH)));
figure
clf
plot(u,20*log10(abs(G_Hann)),'--')
hold on
plot(u,20*log10(abs(G_Hamm)),'-')
plot(u,20*log10(abs(G_BH)),'-.')
hold off
axis([0 1 -80 0])
h=legend('Hann','Hamming','Blackman-Harris');
xlabel('$u$','Interpreter','latex')
ylabel('Beam pattern (dB)')
```
{% endnote %}
# 7. Blackman-Harris 加权
&emsp;&emsp;Blackman-Harris 加权把加权过程扩展到了更高阶谐波的情况,并在前两个旁瓣的峰值位置上放置了零点。加权函数为
$$\begin{equation}
w(\tilde{n}) = 0.42 + 0.5 \cos\left( \frac{2\pi \tilde{n}}{N} \right) + 0.08 \cos\left( \frac{4\pi \tilde{n}}{N} \right), \quad \tilde{n} = -\frac{N-1}{2}, \cdots, \frac{N-1}{2}
\end{equation}$$
对应的波束方向图是多个常规波束方向图的和,已在[图 2.1.4](#fig.2-1-4) 中给出
$$\begin{equation}
\begin{aligned}
B_u(u) =& 0.42 \frac{\sin\left( \displaystyle\frac{N\pi u}{2} \right)}{\sin\left( \displaystyle\frac{\pi u}{2} \right)} + 0.25 \left[ \frac{\sin\left( \displaystyle\frac{N\pi}{2} \left( u - \frac{2}{N} \right) \right)}{\sin\left( \displaystyle\frac{\pi}{2} \left( u - \frac{2}{N} \right) \right)} + \frac{\sin\left( \displaystyle\frac{N\pi}{2} \left( u + \frac{2}{N} \right) \right)}{\sin\left( \displaystyle\frac{\pi}{2} \left( u + \frac{2}{N} \right) \right)} \right] \\
&+ 0.04 \left[ \frac{\sin\left( \displaystyle\frac{N\pi}{2} \left( u - \frac{2}{N} \right) \right)}{\sin\left( \displaystyle\frac{\pi}{2} \left( u - \frac{2}{N} \right) \right)} + \frac{\sin\left( \displaystyle\frac{N\pi}{4} \left( u + \frac{4}{N} \right) \right)}{\sin\left( \displaystyle\frac{\pi}{4} \left( u + \frac{4}{N} \right) \right)} \right]
\end{aligned}
\end{equation}$$
波束方向图的参数为
| 加权方式 | HPBW | $BW_{NN}$ | 第一旁瓣高度 | $D_N$ |
| :--: | :--: | :--: | :--: | :--: |
| Hann | $1.44 \displaystyle\frac{2}{N}$ | $4.0 \displaystyle\frac{2}{N}$ | $-31.4 \text{dB}$ | $0.667$ |
| Hamming | $1.31 \displaystyle\frac{2}{N}$ | $4.0 \displaystyle\frac{2}{N}$ | $-39.5 \text{dB}$ | $0.730$ |
| Blackman-Harris | $1.65 \displaystyle\frac{2}{N}$ | $6.0 \displaystyle\frac{2}{N}$ | $-56.6 \text{dB}$ | $0.577$ |
至此,所有的加权方法都是基于各种正弦函数进行的。现在看看其他类型的阵列加权技术,试试能否更好在波束宽度和旁瓣之间的获得折中。
# 8. 长球函数 (Prolate Spheroidal Functions)
&emsp;&emsp;在设计加权方案时,我们的目标是使得一个给定角度范围内的能量占总能量的比例最大,也即最大化如下比值
$$\begin{equation}
\alpha = \frac{\displaystyle\iint_{\varOmega_1}\left| B(\theta,\varphi) \right|^2 \sin\theta\,\mathrm{d}\theta\,\mathrm{d}\varphi}{\displaystyle\int_0^\pi \int_0^{2\pi}\left| B(\theta,\varphi) \right|^2 \sin\theta\,\mathrm{d}\varphi\,\mathrm{d}\theta}
\end{equation}$$
其中 $\varOmega_1$ 是主波束周围的一个区域。对于标准线性阵列,可以写成
$$\begin{equation}
\alpha = \frac{\displaystyle\int_{-\psi_0}^{\psi_0}\left| B(\psi) \right|^2\,\mathrm{d}\psi}{\displaystyle\int_{-\pi}^{\pi}\left| B(\psi) \right|^2\,\mathrm{d}\psi}
\end{equation}$$
其分子和分母部分可分别写为
$$\begin{align}
&\alpha_N &&\xlongequal{B(\psi) = \boldsymbol{w}^\mathrm{H}\boldsymbol{v}_\psi(\psi)} \int_{-\psi_0}^{\psi_0}\boldsymbol{w}^\mathrm{H}\boldsymbol{v}_\psi(\psi) \boldsymbol{v}_\psi^\mathrm{H}(\psi)\boldsymbol{w}\,\mathrm{d}\psi \notag \\
& &&= \boldsymbol{w}^\mathrm{H} \left[ \int_{-\psi_0}^{\psi_0} \boldsymbol{v}_\psi(\psi) \boldsymbol{v}_\psi^\mathrm{H}(\psi) \,\mathrm{d}\psi \right]\boldsymbol{w} \notag \\
& &&= \boldsymbol{w}^\mathrm{H}\boldsymbol{A}\boldsymbol{w} \\
&\alpha_D &&\xlongequal{B(\psi) = \boldsymbol{w}^\mathrm{H}\boldsymbol{v}_\psi(\psi)} \int_{-\pi}^{\pi}\boldsymbol{w}^\mathrm{H}\boldsymbol{v}_\psi(\psi) \boldsymbol{v} \notag \\
& &&= \boldsymbol{w}^\mathrm{H}\boldsymbol{A}\boldsymbol{w}
\end{align}$$
其中
$$\begin{align}
\boldsymbol{A} &\triangleq \int_{-\psi_0}^{\psi_0} \boldsymbol{v}_\psi(\psi) \boldsymbol{v}_\psi^\mathrm{H}(\psi) \,\mathrm{d}\psi \\
\boldsymbol{B} &\triangleq \int_{-\pi}^{\pi} \boldsymbol{v}_\psi(\psi) \boldsymbol{v}_\psi^\mathrm{H}(\psi) \,\mathrm{d}\psi = 2\pi \boldsymbol{I}
\end{align}$$
$$\begin{equation}
[\boldsymbol{A}]_{mn} = \int_{-\psi_0}^{\psi_0} e^{jm\psi} e^{-jn\psi} \,\mathrm{d}\psi = \frac{2\sin ((m-n)\psi_0)}{m-n} = 2\psi_0 \,\mathrm{sinc}((m-n)\psi_0)
\end{equation}$$
因此
$$\begin{equation}
\alpha = \frac{\boldsymbol{w}^\mathrm{H}\boldsymbol{A}\boldsymbol{w}}{2\pi \boldsymbol{w}^\mathrm{H}\boldsymbol{w}}
\end{equation}$$
为了使 $\alpha$ 最大,求取矩阵 $\boldsymbol{A}$ 的特征值和特征矢量
$$\begin{equation}
2\pi \lambda \boldsymbol{w} = \boldsymbol{A} \boldsymbol{w}
\end{equation}$$
并选择对应于最大特征值 $\lambda$ 的特征矢量,将 $[\boldsymbol{A}]_{mn}$ 代入得到
$$\begin{equation}
\label{DPSS}
\sum_{n=1}^N \frac{\sin ((m-n)\psi_0)}{m-n} w_n = \pi \lambda \omega_m,\quad m = 1,2,\cdots,N
\end{equation}$$
利用式 $\eqref{DPSS}$ 计算出的权值(或序列)称为**{% label primary @离散长球序列(Discrete Prolate Spheroidal Sequences, DPSS %}**,对应的波束方向图称为**{% label primary @离散长球函数(Discrete Prolate Spheroidal Functions)%}**。离散长球序列也称为**{% label primary @Slepian 序列 %}**。
&emsp;&emsp;[图 2.1.5](#fig.2-1-5) 给出了几个代表性的离散长球序列(归一化到 $w_6$),[图 2.1.6](#fig.2-1-6) 给出了对应的波束方向图:
- 当 $\psi_0$ 接近于零的时候,$w_0$ 趋近于均匀加权,因为此时使方向性最大;
- 对于 $\psi_0 = 0.2\pi$,大多数的能量集中在主波束,波束宽度略增大,旁瓣在 $-20\text{dB}$ 以下;
- 对于$\psi_0 = 0.4\pi$,旁瓣为 $-53\text{dB}$,但波束更宽。
DPSS 加权的波束方向图参数为:
| $\psi_0$ | HPBW | $BW_{NN}$ | 第一旁瓣高度 | $D_N$ |
| :--: | :--: | :--: | :--: | :--: |
| $0.1\pi$ | $\displaystyle\frac{0.02}{N}$ | $\displaystyle\frac{1.40\pi}{N}$ | $-15.6 \text{dB}$ | $0.981$ |
| $0.2\pi$ | $\displaystyle\frac{2.20}{N}$ | $\displaystyle\frac{1.79\pi}{N}$ | $-24.7 \text{dB}$ | $0.869$ |
| $0.4\pi$ | $\displaystyle\frac{2.86}{N}$ | $\displaystyle\frac{2.97\pi}{N}$ | $-52.2 \text{dB}$ | $0.665$ |
<a id="fig.2-1-5"></a>
![图 2-1-5 离散长球序列: $\psi_0=0.1\pi,0.2\pi,0.4\pi$](../images/post/2023-06-19-josh-oap-part-2-1/2023-06-19-josh-oap-part-2-1-050-DiscreteProlateSpheroidalSequences.svg){width=700px}
<a id="fig.2-1-6"></a>
![图 2-1-6 DPSS 加权的波束方向图和 $\psi_0$ 的关系: $N = 11$](../images/post/2023-06-19-josh-oap-part-2-1/2023-06-19-josh-oap-part-2-1-060-BeamPatternForDPSSWeighting.svg){width=700px}
{% note primary MATLAB Code %}
``` matlab fig3_05_06_13.m
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Figure 3.5
% DPSS psi0=0.1pi,0.2pi, and 0.4pi
% Figure 3.6
% Beampattern of a standard 11-element linear array as a function
% Figure 3.13
% Zero plots for DPSS(0.1pi,0.2pi,0.4pi) weightings
%
% Lillian Xiaolan Xu
% Updated 4/14/99
% Lillian Xu 04/16/2001, K. Bell 7/22/01, 9/30/01
% Functions called: DPSS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
close all
clear all
N=11;
us=0; % should change us between 0 and 0.2
u=-1:0.001:1;
n=conj(-(N-1)/2:(N-1)/2)';
vs=exp(1i*n.*pi.*us);
%------------------------ DPSS Weighting
psi0=[0.1 0.2 0.4]*pi;
w1=DPSS(psi0(1),N);
w2=DPSS(psi0(2),N);
w3=DPSS(psi0(3),N);
z1=roots(w1);
z2=roots(w2);
z3=roots(w3);
w1=w1/max(w1);
w2=w2/max(w2);
w3=w3/max(w3);
m=-5:5;
figure
h1 = plot(m,w1);
hold on;
h2 = plot(m,w1,'o');
h3 = plot(m,w2,'--');
h4 = plot(m,w2,'o');
h5 = plot(m,w3,'-.');
h6 = plot(m,w3,'o');
hold off
h=legend([h1 h3 h5],{'$\psi_0=0.1\pi$','$\psi_0=0.2\pi$', ...
'$\psi_0=0.4\pi$'},Interpreter="latex");
%title('DPSS for 11 elements');
xticks(-5:5);
xlabel('Sensors');
ylabel('Weighting');
grid on
%-----------------------------------------------------------%
% ---------------- Zero Plot.
figure
%%%%%%%%%%%% plot 1
subplot(1,2,1);
plot(real(z1),imag(z1),'o');
axis([-1.2 1.2 -1.2 1.2])
axis('square')
grid on;
title('$\psi_0=0.1\pi$','Interpreter','latex');
xlabel('Real')
ylabel('Imaginary')
theta=2*pi*(0:0.01:1);
hold on
plot(cos(theta),sin(theta),'--');
hold off
%%%%%%%%%%%% plot 2
subplot(1,2,2);
plot(real(z3),imag(z3),'o');
grid on;
axis([-1.2 1.2 -1.2 1.2])
axis('square')
title('$\psi_0=0.4\pi$','Interpreter','latex');
xlabel('Real')
ylabel('Imaginary')
theta=2*pi*(0:0.01:1);
hold on
plot(cos(theta),sin(theta),'--');
hold off
w1=w1./sum(w1);
w2=w2./sum(w2);
w3=w3./sum(w3);
b=0;
for m=1:N
b=b+w1(m)*exp(1i*(-(N+1)/2+m)*pi*u);
end
bdb1=20*log10(abs(b));
b1=real(b);
b=0;
for m=1:N
b=b+w2(m)*exp(1i*(-(N+1)/2+m)*pi*u);
end
bdb2=20*log10(abs(b));
b2=real(b);
b=0;
for m=1:N
b=b+w3(m)*exp(1i*(-(N+1)/2+m)*pi*u);
end
bdb3=20*log10(abs(b));
b3=real(b);
figure
plot(u,bdb1,u,bdb2,'--',u,bdb3,'-.');
hold on
h=legend({'$\psi_0=0.1\pi$','$\psi_0=0.2\pi$','$\psi_0=0.4\pi$'}, ...
Interpreter="latex");
axis([-1 1 -80 0])
grid on
xlabel('$u$','Interpreter','latex')
ylabel('Beam pattern (dB)')
```
{% endnote %}
# 9. Kaiser 加权
&emsp;&emsp;Kaiser 利用 Bessel 函数提出了一个相对简单的长球序列的近似方法,在谱分析、滤波器设计和其他领域中,这种加权得到了广泛的应用。Kaiser 加权函数为
$$\begin{equation}
w(\tilde{n}) = I_0 \left( \beta \sqrt{1 - \left[ \frac{2\tilde{n}}{N} \right] ^2 } \right), \quad -\frac{N-1}{2} \leqslant \tilde{n} \leqslant \frac{N-1}{2}
\end{equation}$$
其中 $I_0(x)$ 是零阶修正 Bessel 函数,参数 $\beta$ 决定了波束方向图在旁瓣峰值高度和主波束宽度之间的性能折中程度。
&emsp;&emsp;[图 2.1.7(a)](#fig.2-1-7) 给出了 $N=11$ 情况下 $\beta=3$ 和 $\beta=6$ 时的权值(归一化到 $w_6$),[图 2.1.7(b)](#fig.2-1-7) 给出了对应的波束方向图。注意到当 $\beta$ 减小时,权函数接近于均匀加权。当 $N = 11$ 时 Kaiser 加权的波束方向图参数为:
| $\beta$ | HPBW | $BW_{NN}$ | 第一旁瓣高度 | $D_N$ |
| :--: | :--: | :--: | :--: | :--: |
| $3$ | $\displaystyle\frac{2.18}{N}$ | $\displaystyle\frac{1.75\pi}{N}$ | $-23.7 \text{dB}$ | $0.882$ |
| $6$ | $\displaystyle\frac{2.80}{N}$ | $\displaystyle\frac{2.76\pi}{N}$ | $-44.4 \text{dB}$ | $0.683$ |
<a id="fig.2-1-7"></a>
![图 2-1-7 Kaiser 加权: (a) $\beta=3$ 和 $6$ 时的权值;(b) $\beta=3$ 和 $6$ 时的波束方向图](../images/post/2023-06-19-josh-oap-part-2-1/2023-06-19-josh-oap-part-2-1-070-KaiserWeighting.svg){width=700px}
{% note primary MATLAB Code %}
``` matlab fig3_07.m
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Figure 3.7
% Kaiser weighting
% (a)weighting for beta = 3 and 6
% (b)Beam patterns for beta = 3 and 6
% Xin Zhang updated 3/17/99
% Lillian Xiaolan Xu updated 09/20/2000
% Lillian Xiaolan Xu updated 04/16/2001, K. Bell 7/20/01, 9/30/01
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear all;
close all;
N = 11;
Zl = (N-1)/2;
beta1 = 3;
beta2 = 6;
for n = -(N-1)/2:(N-1)/2
x = 1-(2*n/N)^2;
wn1(n+1+(N-1)/2,1) = besseli(0,beta1*sqrt(x));
end
for n = -(N-1)/2:(N-1)/2
x = 1-(2*n/N)^2;
wn2(n+1+(N-1)/2,1) = besseli(0,beta2*sqrt(x));
end
nn = -Zl/2:1/2:Zl/2;
u=(-1:0.001:1);
amf=(-(N-1)/2:(N-1)/2)';
Vo=exp(1i*amf*pi*u);
w1=wn1/sum(wn1);
w2=wn2/sum(wn2);
Beam1=20*log10(abs(w1'*Vo));
Beam2=20*log10(abs(w2'*Vo));
bes1 = besseli(0,beta1);
bes2 = besseli(0,beta2);
wn1 = wn1/bes1;
wn2 = wn2/bes2;
figure
subplot(2,1,1)
plot(nn,wn1,'-',nn,wn2,'--')
xlabel('$z/\lambda$','Interpreter','latex')
ylabel('Weights')
%title('Kaiser Window for 11 elements')
hold on;
plot(nn,wn1,'o')
plot(nn,wn2,'o')
axis([-2.5 2.5 -0.02 1.02])
hold off;
legend({'$\beta = 3$','$\beta = 6$'},Interpreter="latex");
text(-0.0625,-0.28,'(a)')
subplot(2,1,2)
plot(u,Beam1,'-',u,Beam2,'--')
h=legend({'$\beta = 3$','$\beta = 6$'},Interpreter="latex");
axis([-1 1 -60 0])
text(-0.025,-75,'(b)')
xlabel('$u$','Interpreter','latex')
ylabel('Beam pattern (dB)')
set(gcf,'Position',[0 0 600 600])
```
{% endnote %}
&emsp;&emsp;[图 2.1.8](#fig.2-1-8) 给出了固定 $\beta=3$,$N=11,21$ 和 $41$ 时的波束方向图,三种情况具有相同的最高旁瓣。当 $N$ 改变时,最高旁瓣对应的 $u$ 值发生改变。
<a id="fig.2-1-8"></a>
![图 2-1-8 Kaiser 加权的波束方向图:$\beta = 3$,$N=11,21$ 和 $41$](../images/post/2023-06-19-josh-oap-part-2-1/2023-06-19-josh-oap-part-2-1-080-BeamPatternsForKaiserWeighting.svg){width=700px}
{% note primary MATLAB Code %}
``` matlab fig3_08.m
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Figure 3.8
% Beam patterns for Kaiser weighting
% beta = 3, N = 11, 21, and 41
% Xin Zhang
% Last updated 04/16/2001 Lillian Xu, K. Bell 7/20/01,9/30/01
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear all;
close all;
N1 = 11;
N2 = 21;
N3 = 41;
beta = 3;
bes = besseli(0,beta);
for n = -(N1-1)/2:(N1-1)/2
x = 1-(2*n/N1)^2;
wn1(n+1+(N1-1)/2) = besseli(0,beta*sqrt(x));
end
wn1 = wn1'/bes;
for n = -(N2-1)/2:(N2-1)/2
x = 1-(2*n/N2)^2;
wn2(n+1+(N2-1)/2) = besseli(0,beta*sqrt(x));
end
wn2 = wn2'/bes;
for n = -(N3-1)/2:(N3-1)/2
x = 1-(2*n/N3)^2;
wn3(n+1+(N3-1)/2) = besseli(0,beta*sqrt(x));
end
wn3 = wn3'/bes;
u=(-1:0.001:1);
amf1=(-(N1-1)/2:(N1-1)/2)';
Vo1=exp(1i*amf1*pi*u);
amf2=(-(N2-1)/2:(N2-1)/2)';
Vo2=exp(1i*amf2*pi*u);
amf3=(-(N3-1)/2:(N3-1)/2)';
Vo3=exp(1i*amf3*pi*u);
wn1=wn1/sum(wn1);
wn2=wn2/sum(wn2);
wn3=wn3/sum(wn3);
Beam1=20*log10(abs(wn1'*Vo1));
Beam2=20*log10(abs(wn2'*Vo2));
Beam3=20*log10(abs(wn3'*Vo3));
plot(u,Beam3,'-',u,Beam2,'--',u,Beam1,'-.')
h=legend({'$N = 41$','$N = 21$','$N = 11$'},Interpreter="latex");
axis([-1 1 -50 0])
xlabel('$u$','Interpreter','latex')
ylabel('Beam pattern (dB)')
```
{% endnote %}
# 参考文献
1. Harry L. Van Trees. *Optimum array processing: Part IV of detection, estimation, and modulation theory.* New York, NY, USA: John Wiley & Sons, 2002.
2. Harry L. Van Trees, 汤俊. *最优阵列处理技术.* 北京:清华大学出版社. 2008.
[^1]: 参数 $D_N$ 是阵列的归一化方向性。它是相对于一个均匀加权阵列的方向性进行归一化的。对于标准线阵, $D_N$ 也是归一化的白噪声增益。
[^2]: 这个权值是奥地利气象学家 Von Hann 提出的,有时也称为 Hanning 加权。
@@ -0,0 +1,326 @@
---
title: 'Source Localization and Sensing: A Nonparametric Iterative Adaptive Approach Based on Weighted Least Squares'
mathjax: true
comments: true
copyright: true
toc:
enable: true
number: true
wrap: true
expand_all: true
max_depth: 4
tags:
- IAA-APES
- BIC
- RELAX
- DoA
- 波达方向估计
categories:
- - Josh 的学习笔记
- 论文阅读
abbrlink: 304dacfb
date: 2024-01-30 17:12:58
---
# Meta Data
* Title: Source Localization and Sensing: A Nonparametric Iterative Adaptive Approach Based on Weighted Least Squares
* Journal: IEEE Transactions on Aerospace and Electronic Systems
* Date: 2010
* Author:
* Tarik Yardibi: Department of Electrical and Computer Engineering, University of California
* Jian Li: Department of Electrical and Computer Engineering, University of California
* [Connected Papers:](https://www.connectedpapers.com/main/e2ca1a746f52d906458fb8ffc0d33e21b7877aa4/Source-Localization-and-Sensing%3A-A-Nonparametric-Iterative-Adaptive-Approach-Based-on-Weighted-Least-Squares/graph)
![Connected Papers 引用关系](../images/post/2024-01-30-paper-yardibiSourceLocalizationSensing2010/2024-01-30-paper-yardibiSourceLocalizationSensing2010-010-ConnectedPaper.png){width=1200}
<!-- more -->
# Abs & Intro
* 背景:
* 阵列处理面临的问题:快拍数不足、低 SNR、邻近源
* 场景:水下阵列、SISO 雷达/声纳范围-多普勒成像、MISO 通信的信道估计
* 基本阵列处理方法:
* DAS:最基本的方法,分辨率低,旁瓣高
* 标准 Capon 波束成形器 (SCB)、MUSIC:对不想干信源,在快拍数足够多时具有超分辨能力
* 存在的问题:快拍数不足时、相干信源、低 SNR 时无法使用
* 稀疏信号表出方法:
* 原因:实际源的数量远小于可能的方向;
* 优点:可以处理很少快拍的情况,即使只有一个快拍
* 缺点:计算时间过长,需要调谐一个或数个超参数
* 问题:快拍数不足时难以估计信源参数
* 方法:
* 基本算法:
* **方法**:提出了一种***非参数化、无超参数、基于最小二乘的迭代自适应方法***,用于阵列处理中的幅度和相位估计(Iterative Adaptive Approach for Amplitude and Phase EStimation, IAA-APES)。
* **效果**:IAA-APES 可以在少量快拍数据(甚至只有一个快拍)、不相干、部分相干和相干源以及任意阵列几何结构的情况下表现出良好的性能。
* **扩展应用**:IAA-APES 还可应用于主动感知(Active Sensing)应用,包括 SISO 雷达/声纳范围-多普勒成像以及用于通信的 MISO 信道估计。
* 扩展算法:
* IAA-APES 可以通过模型阶数选择工具贝叶斯信息准则(Bayesian Information Criterion, BIC)扩展以获得稀疏结果,进而进行点源估计(point source estimation)。
* 可以进一步通过应用基于参数松弛的循环方法(RELAX)来改进 IAA-APES\&BIC 估计的分辨率和准确性。
# Method
## Passive Sensing
### 基本模型
![远场线阵模型](../images/post/2024-01-30-paper-yardibiSourceLocalizationSensing2010/2024-01-30-paper-yardibiSourceLocalizationSensing2010-020-FarFiledLinearArray.png){width=500}
假设有 $K$ 个信源,位于 $\boldsymbol{\theta}\triangleq[\theta_1,\cdots,\theta_K]$,设快拍数为 $N$,则到达 $M$ 元阵列的接收快拍可表示为 $M$ 维矢量
$$
\mathbf{y}(n) = \mathbf{A}(\boldsymbol{\theta}) \mathbf{s}(n)+\mathbf{e}(n),\quad n=1,\cdots,N
$$
其中
* 阵列流形/导向矩阵:$\mathbf{A}(\boldsymbol{\theta})\triangleq[\mathbf{a}(\theta_1),\cdots,\mathbf{a}(\theta_K)]$,$\{\mathbf{a}(\theta_k)\in\mathbb{C}^{M\times 1}\}_{k=1}^K$,由阵列几何结构和信源的相对位置关系决定
* 信源:$\mathbf{s}(n)\triangleq[s_1(n),\cdots,s_K(n)]^\mathrm{T}$
* 噪声:$\mathbf{e}(n)\triangleq[e_1(n),\cdots,e_M(n)]^\mathrm{T}$
由于实际信号数量未知,因此 $K$ 可以看做是扫描格点的数量,这也是稀疏算法可以在 DOA 估计中应用的原因。
### IAA-APES
> IAA-APES 是一种基于加权最小二乘(Weighted Least Square, WLS)的数据相关非参数化算法。
将每个格点的功率记在对角阵的对角线元素中:$\mathbf{P}\in\mathbb{C}^{K\times K}$
$$
P_k = \frac{1}{N}\sum_{n=1}^N | s_k(n)|^2, \quad k = 1,\cdots,K
$$
则干扰(对于当前方向 $\theta_k$ 而言,其他方向的信号也算作干扰)和噪声协方差矩阵 $\mathbf{Q}(\theta_k)\in\mathbb{C}^{M\times M}$
$$
\begin{align*}
\mathbf{Q}(\theta_k) &= \mathbb{E}[\mathbf{y}(n)\mathbf{y}^{\mathrm{H}}(n)] - \mathbb{E}\left[\left(\mathbf{a}\left(\theta_k\right)\mathbf{s}(n)\right)(\mathbf{a}(\theta_k)\mathbf{s}(n))^{\mathrm{H}}\right]\\
&= \mathbb{E}\left[\mathbf{A}\left(\theta\right)\mathbf{s}(n)\mathbf{s}^{\mathrm{H}}(n)\mathbf{A}^\mathrm{H}(\theta)\right] - \mathbb{E}\left[\mathbf{a}\left(\theta_k\right)\mathbf{s}(n)\mathbf{s}^{\mathrm{H}}(n)\mathbf{a}^{\mathrm{H}}(\theta_k)\right]\\
&=\mathbf{A}(\boldsymbol{\theta}) \mathbf{P} \mathbf{A}^{\mathrm{H}}(\boldsymbol{\theta}) - P_k \mathbf{a}\left(\theta_k\right) \mathbf{a}^{\mathrm{H}}\left(\theta_k\right) \\
&\triangleq \mathbf{R} - P_k \mathbf{a}\left(\theta_k\right) \mathbf{a}^{\mathrm{H}}\left(\theta_k\right)
\end{align*}
$$
则 WLS 的代价函数为
$$
\sum_{n=1}^N \left\| \mathbf{y}(n) - s_k(n) \mathbf{a}(\theta_k) \right\|^2_{\mathbf{Q}^{-1}(\theta_k)}
$$
其中 $\left\| \mathbf{x} \right\|^2_{\mathbf{Q}^{-1}(\theta_k)}\triangleq\mathbf{x}^{\mathrm{H}}\mathbf{Q}^{-1}(\theta_k)\mathbf{x}$。
> ![ChatGPT 问答](../images/post/2024-01-30-paper-yardibiSourceLocalizationSensing2010/2024-01-30-paper-yardibiSourceLocalizationSensing2010-030-ChatGPT1.png){width=700px}
>
> ![ChatGPT 问答](../images/post/2024-01-30-paper-yardibiSourceLocalizationSensing2010/2024-01-30-paper-yardibiSourceLocalizationSensing2010-040-ChatGPT2.png){width=700px}
最小化 WLS 的代价函数可得
$$
\begin{align*}
\hat{s}_k(n) &= \frac{\mathbf{a}^{\mathrm{H}}(\theta_k) \mathbf{Q}^{-1}(\theta_k) \mathbf{y}(n)}{\mathbf{a}^{\mathrm{H}}(\theta_k) \mathbf{Q}^{-1}(\theta_k) \mathbf{a}(\theta_k)} \\
&= \frac{\mathbf{a}^{\mathrm{H}}(\theta_k) \mathbf{R}^{-1} \mathbf{y}(n)}{\mathbf{a}^{\mathrm{H}}(\theta_k) \mathbf{R}^{-1} \mathbf{a}(\theta_k)} \\
\end{align*}, \quad n = 1,\cdots,N
$$
且对于每个扫描格点,$\{\hat{s}(n)\}_{k=1}^K$ 可以并行计算,因此可在并行硬件上实现。
![IAA-APES 算法](../images/post/2024-01-30-paper-yardibiSourceLocalizationSensing2010/2024-01-30-paper-yardibiSourceLocalizationSensing2010-050-IAA-APES.png){width=600px}
* IAA-APES 由上表给出,由于 IAA-APES 需要 $\mathbf{R}$,且 $\mathbf{R}$ 依赖于未知信号功率,因此必须用迭代来实现。
* $\mathbf{P}$ 和 $\mathbf{R}$ 由信号的估计得出,而非直接由快拍得出。
* 初始 $P_k$ 由 DAS 获得,并进行归一化
$$
\begin{align*}
\hat{P}_k &= \displaystyle\frac{1}{(\mathbf{a}^{\mathrm{H}}(\theta_k)\mathbf{a}(\theta_k))^2 N} \sum_{n=1}^{N}\left| \mathbf{a}^{\mathrm{H}}(\theta_k) \mathbf{y}(n) \right|^2
\\
&=\displaystyle\frac{1}{(\mathbf{a}^{\mathrm{H}}(\theta_k)\mathbf{a}(\theta_k))^2 N} \sum_{n=1}^{N}\left| \mathbf{a}^{\mathrm{H}}(\theta_k) \mathbf{a}(\theta_k) \mathbf{s}(n) \right|^2 \\
\end{align*}
$$
* 经验结论:IAA-APES 的性能在 15 次迭代后就提升不大了。
* 由于 $\mathbf{P}$ 具有对角结构,所以对少量快拍和相干源都适用。
### IAA-APES\&BIC
引入模型阶数选择工具(model-order selection tool) BIC。
工作原理:令 $\mathcal{P}$ 为从 IAA-APES 空间功率谱估计中选择的峰值的索引集合;令 $\mathcal{I}$ 为到目前为止由 BIC 算法选择的峰值的索引集合。IAA-APES\&BIC 算法的工作原理如下:首先,从集合 $\mathcal{P}$ 中选择具有最小 BIC 值的峰值。然后,从集合 $\mathcal{P}-\mathcal{I}$ 中选择第二个峰值,它与第一个峰值一起使 BIC 值最小,依此类推,直到 BIC 值不再减小。
![IAA-APES&BIC 算法](../images/post/2024-01-30-paper-yardibiSourceLocalizationSensing2010/2024-01-30-paper-yardibiSourceLocalizationSensing2010-060-IAA-APES-BIC.png){width=600px}
其中
* $\text{BIC}_i(\eta) = 2MN \ln \left( \displaystyle\sum_{n=1}^N \left\| \mathbf{y}(n) - \sum_{j \in \{ \mathcal{I} \cup i \}} \mathbf{a}(\theta_j) \hat{\mathbf{s}}_j (n) \right\|_2^2 \right) + 3\eta \ln (2MN)$
* 也即,将使得接收快拍 $\mathbf{y}(n)$ 和估计信号 $\displaystyle\sum_{j \in \{ \mathcal{I} \cup i \}} \mathbf{a}(\theta_j) \hat{\mathbf{s}}_j (n)$ 的距离最小的 index 作为峰值的 index
* $\eta = |\mathcal{I}| + 1$,$|\mathcal{I}|$ 表示集合 $\mathcal{I}$ 的大小
* $i$ 表示当前峰的 index
* $\{\hat{\mathbf{s}}_j (n)\}_{n=1}^N$ 是 IEE-APES 在 $\theta_j,j\in\{\mathcal{I}\cup i\}$ 方向的波形估计
* 第二项不影响峰值选择(选多少个峰),但是影响峰值数量的选择(留多少个峰)
### IAA-APES\&RELAX
RELAX 是一种参数循环算法,需要预先知道源数量。
工作原理:在 IAA-APEX 搜索结果的基础上,在每个峰的周围细化角度进行搜索,以功率为依据,修正信号来向和 DOA 估计波形。当两次估计的差小于一定门限(e.g. $5\times10^4$)时可认为收敛。
![IAA-APES&BIC 算法](../images/post/2024-01-30-paper-yardibiSourceLocalizationSensing2010/2024-01-30-paper-yardibiSourceLocalizationSensing2010-070-IAA-APES-RELAX.png){width=600px}
## Active Sensing
# Simulation
## Passive Sensing
* 对比方法:
* DAS
* IAA-APES
* IAA-APES\&RELAX
* M-FOCUSS(Multiple-snapshot Focal Underdetermined System Solution):稀疏参数 $p=0.8$,根据实际源的位置精调正则化参数 $\lambda$ 以获得最佳结果,因此 impractical
* M-SBL(Sparse Bayesian Learning)
* $\ell_1$-SVD(Singular Value Decomposition):假定源数量已知,精调超参数,impractical
* 仿真条件:
* 扫描格点:1°\~180°范围,1°步进
* ULA,12个阵元,半波长间距
* 噪声:均值为零、方差为 $\sigma^2$ 的圆周对称独立同分布复高斯随机过程
* 信号:
* 远场、窄带:
* 功率归一化,使得 $\displaystyle\frac{1}{N}\sum_{n=1}^{N}|s_k(n)|^2=P_k,k=1,\cdots,K_0$,其中 $N$ 是快拍数,$K_0$ 是实际信源个数;
* 信噪比定义为 $\text{SNR}_{\text{dB}}=10 \log_{10} \displaystyle\frac{P_k}{\sigma^2},k=1,\cdots,K_0$
* 仿真结果
* Case 1:
* 三个***不相干***的源,分别位于 60°、82° 和 90°,SNR 分别为 5dB、10dB 和 10dB,单次迭代所用快拍数 $N=3$,每种方法 10 次仿真
* 各种方法 DOA 估计结果:
* DAS:可能混叠
* IAA-APES
* IAA-APES\&RELAX:可以准确判断信源个数、方向和功率
* M-FOCUSS、M-SBL、$\ell_1$-SVD:均不准确
![Three uncorrelated sources at 60° (5 dB power), 82° (10 dB power), and 90° (10 dB power), as represented by circles and vertical dotted lines in each plot. $N = 3$, the noise power is 0 dB (which results in minimum SNR of 5 dB), and 10 Monte-Carlo trials are shown. (a) DAS spatial estimate. (b) IAA-APES spatial estimate. (c) IAA-APES&RELAX point source estimates. (d) M-FOCUSS spatial estimate. (e) M-SBL spatial estimate. (f) $\ell_1$-SVD spatial estimate.](../images/post/2024-01-30-paper-yardibiSourceLocalizationSensing2010/2024-01-30-paper-yardibiSourceLocalizationSensing2010-080-Sim-PS-Case1.png){width=800px}
* Case 2:
* 三个***相干***的源,分别位于 60°、80° 和 90°,SNR 分别为 10dB、10dB 和 10dB,单次迭代所用快拍数 $N=3$,每种方法 10 次仿真;
* 各种方法 DOA 估计结果:
* DAS:完全混叠
* IAA-APES
* IAA-APES\&RELAX:可以准确判断信源个数、方向和功率
* M-FOCUSS、M-SBL、$\ell_1$-SVD:均不准确
![Three coherent sources at 60°, 80°, and 90°, each with 10 dB power, as represented by circles and vertical dotted lines in each plot. $N = 3$, noise power is 0 dB (SNR = 10 dB), and 10 Monte-Carlo trials are shown. (a) DAS spatial estimate. (b) IAA-APES spatial estimate. (c) IAA-APES&RELAX point source estimates. (d) M-FOCUSS spatial estimate. (e) M-SBL spatial estimate. (f) $\ell_1$-SVD spatial estimate.](../images/post/2024-01-30-paper-yardibiSourceLocalizationSensing2010/2024-01-30-paper-yardibiSourceLocalizationSensing2010-090-Sim-PS-Case2.png){width=800px}
* Case 3:
* 两个***不相干***的源,分别位于 77.51° 和 90.51°(避开 1° 的格点),单次迭代所用快拍数 $N=1$,每种方法 100 次仿真;
* IAA-APES\&RELAX:原条件
* FOCUSS、$\ell_1$-SVD:分辨率 0.01°,950 个格点,即 $K=950$,均具有两个超参数需要根据不同场景调节
* SBL:复杂度过大,不展示
* 结果:各算法在不同 SNR 下的 (a) 角度估计的总均方误差和 CRB;(b) 角度估计总偏差
* IAA-APES\&RELAX:低 SNR 下表现更好
![Two uncorrelated sources at 77.51° and 90.51° with $N = 1$. (a) Total angle estimation MSE in dB together with CRB. (b) Total angle estimation bias versus SNR. Each point is average of 100 Monte-Carlo trials. Recall that FOCUSS is single snapshot version of M-FOCUSS.](../images/post/2024-01-30-paper-yardibiSourceLocalizationSensing2010/2024-01-30-paper-yardibiSourceLocalizationSensing2010-100-Sim-PS-Case3.png){width=800px}
* 复杂度分析:假设 $K\gg M$,也即格点数远大于阵元数
* IAA-APES:每次迭代 $\mathcal{O}(M^2K)$
* IAA-APES\&BIC:每次迭代 $\mathcal{O}(M^2K)$,由 BIC 导致的复杂度增加相比原复杂度可以忽略不计
* IAA-APES\&RELAX:取决于 IAA-APES\&BIC 得到的信源个数、终止条件和所选用的方法
* M-FOCUSS、M-SBL:每次迭代 $\mathcal{O}(M^2K)$
* $\ell_1$-SVD:每次迭代 $\mathcal{O}(M^2K_{\text{SVD}}^3)$,其中$K_{\text{SVD}}$ 是估计的信源个数
在作者的实验过程中:
* RELAX 通常比 IAA-APES 更快收敛
* IAA-APES 总是比 M-FOCUSS、M-SBL 和 $\ell_1$-SVD 更快收敛,特别是当 SNR 较低时
## Active Sensing
### SISO Range-Doppler Imaging
![SISO range-Doppler imaging with three 5 dB and six 25 dB targets, indicated by circles. Noise power is 0 dB, resulting in minimum SNR of 5 dB. (a) Ground truth with power levels. (b) Matched filter. (c) MP and ground truth. (d) OMP and ground truth. (e) LSMP and ground truth. (f) IAA-APES. (g) IAA-APES&BIC and ground truth. (h) IAA-APES&RELAX and ground truth. All power levels are in dB.](../images/post/2024-01-30-paper-yardibiSourceLocalizationSensing2010/2024-01-30-paper-yardibiSourceLocalizationSensing2010-110-Sim-AS-Case1.png){width=800px}
### MISO Communication Channel Estimation
![MISO channel estimation with six transmitters and one receiver. Channel taps are indicated by circles. Channel tap power levels are in range of -30 dB to 0 dB, and noise level is -20 dB, which results in -10 dB minimum SNR. Estimates for first channel via (a) MP, (b) OMP, (c) LSMP, and (d) IAA-APES&BIC. All power levels are in dB.](../images/post/2024-01-30-paper-yardibiSourceLocalizationSensing2010/2024-01-30-paper-yardibiSourceLocalizationSensing2010-120-Sim-AS-Case2.png){width=800px}
# Conclusion
> IAA-APES is believed to be a viable candidate for practical applications since it does not require any hyperparameters, has a simple formulation, provides superresolution, facilitates parallel processing, and shows good performance.
# Reference
1. T. Yardibi, J. Li, P. Stoica, M. Xue, and A. B. Baggeroer, “Source Localization and Sensing: A Nonparametric Iterative Adaptive Approach Based on Weighted Least Squares,” IEEE Transactions on Aerospace and Electronic Systems, vol. 46, no. 1, pp. 425–443, Jan. 2010, doi: 10.1109/TAES.2010.5417172.
+439
View File
@@ -0,0 +1,439 @@
---
title: MVDR 算法仿真
mathjax: true
comments: true
copyright: true
toc:
enable: true
number: true
wrap: true
expand_all: true
max_depth: 4
abbrlink: 86ade7bc
date: 2024-02-01 10:09:39
tags:
- Beamforming
- 波束成形
- MVDR
- 误码率分析
categories:
- - Josh 的学习笔记
- 算法仿真
---
&emsp;&emsp;MVDR (Minimum Variance Distortionless Response,最小方差无失真响应)算法是 Capon 于 1969 年提出的经典波束形成算法,其解决的是无失真约束下输出噪声加干扰功率最小化问题。
# 阵列模型
&emsp;&emsp;首先对阵列接收信号进行建模。假设 $N$ 元阵列天线在 $t$ 时刻的阵列接收信号和阵列输出信号分别为 $\mathbf{x}(t)$ 和 $y(t)$,则对于 $K$ 个入射信号,有
$$\begin{equation}
\begin{cases}
\mathbf{x}(t) = \mathbf{A}(\boldsymbol{\theta})\mathbf{s}(t) + \mathbf{n}(t) \\
y(t) = \mathbf{w}^\mathrm{H}\mathbf{x}(t)
\end{cases},\quad t = 1,\cdots,T
\end{equation}$$
其中
- 阵列接收信号 $\mathbf{x}(t) = [x_1(t),\cdots,x_N(t)]^\mathrm{T}\in\mathbb{C}^{N\times 1}$
- 噪声 $\mathbf{n}(t) = [n_1(t),\cdots,n_N(t)]^\mathrm{T}\in\mathbb{C}^{N\times 1}$
- 入射信号 $\mathbf{s}(t) = [s_1(t),\cdots,s_K(t)]^\mathrm{T}\in\mathbb{C}^{K\times 1}$
- 阵列流形矩阵 $\mathbf{A}(\boldsymbol{\theta}) = [\mathbf{a}(\theta_1),\cdots,\mathbf{a}(\theta_K)]\in \mathbb{C}^{N\times K}$,导向矢量 $\mathbf{a}(\theta_i)\in\mathbb{C}^{N\times 1}$,$K$ 个信号来向集合 $\boldsymbol{\theta} = \{\theta_i\}_{i=1}^K$
- 波束形成复加权 $\mathbf{w} = [w_1,\cdots,w_N]^\mathrm{T}$
<!-- more -->
# MVDR 算法简述
&emsp;&emsp;假设第 1 个信号是期望信号(desired signal),令其导向矢量 $\mathbf{a}_\mathrm{d} = \mathbf{a}(\theta_1)$,则阵列接收信号可以进一步写为
$$\begin{equation}
\mathbf{x}(t) = \underset{\mathbf{x}_\mathrm{d}(t)}{\underbrace{\mathbf{a}_\mathrm{d}s_1(t)}}
+
\underset{\mathbf{x}_\mathrm{i+n}(t)}{\underbrace{\sum_{k=2}^{K}\mathbf{a}(\theta_k)s_k(t) + \mathbf{n}(t)}}
\end{equation}$$
至此,可以给出 MVDR 问题的基本表述
$$\begin{equation}
\begin{aligned}
&\underset{\mathbf{w}}{\text{minimize}} &&\mathbf{w}^\mathrm{H}\mathbf{R}_{\mathrm{i+n}}\mathbf{w}
\\
&\text{subject to} && \mathbf{w}^\mathrm{H}\mathbf{a}_\mathrm{d} = 1
\end{aligned}
\end{equation}$$
其闭式解可以由 Lagrange 乘子法得到
$$\begin{equation}
\mathbf{w} = \alpha\mathbf{R}_{\mathrm{i+n}}^{-1}\mathbf{a}_\mathrm{d}
\end{equation}$$
其中
- 噪声加干扰协方差矩阵 $\mathbf{R}_{\mathrm{i+n}} = \displaystyle\frac{1}{T} \sum_{t=1}^{T}\mathbf{x}_\mathrm{i+n}(t)\mathbf{x}_\mathrm{i+n}^\mathrm{H}(t)$
- 归一化因子(使得复加权对于期望信号的增益为 1) $\alpha = \displaystyle\frac{1}{\mathbf{a}_\mathrm{d}^\mathrm{H}\mathbf{R}_{\mathrm{i+n}}^{-1}\mathbf{a}_\mathrm{d}}$
# MVDR 算法仿真
&emsp;&emsp;使用 ULA(Uniform Linear Array,均匀线阵)对 MVDR 算法进行仿真,阵元间距为半波长。
## 理想情况
&emsp;&emsp;在理想情况下,各阵元的位置与预期一致,各阵元的复加权器是没有误差的,目标信号来向与期望方向一致,且信号和干扰加噪声可以分离。
### 空域谱
&emsp;&emsp;Capon 空域谱表示 MVDR 复加权在整个空域范围内的响应。假设 1 个信号和 6 个干扰同时入射,信噪比 $\mathrm{SNR}=30\mathrm{dB}$,干噪比 $\mathrm{INR} = 70\mathrm{dB}$,信号和干扰来向在 $[0^\circ,180^\circ]$ 内服从均匀分布,使用 1000 个快拍进行仿真。
&emsp;&emsp;得到的空域谱如[图 1](#fig.1),其中期望来向用红色点划线表示,干扰来向用绿色点划线表示。仿真同时还计算了输出 SINR,用于衡量残余干扰的大小。
<a id="fig.1"></a>
![图 1 理想 Capon 谱](../images/post/2024-02-01-algo-MVDR/2024-02-01-algo-MVDR-010-IdealCaponSpectrum.svg){width=700px}
{% note primary MATLAB Code %}
``` matlab mvdr_spec.m
%% High-Resolution Frequency-Wavenumber Spectrum Analysis
% J. Capon, “High-Resolution Frequency-Wavenumber Spectrum Analysis,” _Proceedings
% of the IEEE_, vol. 57, no. 8, pp. 1408–1418, Aug. 1969, doi: <https://doi.org/10.1109/PROC.1969.7278
% 10.1109/PROC.1969.7278>.
%
% H. L. Van Trees, _Optimum Array Processing: Part IV of Detection, Estimation,
% and Modulation Theory_. New York, NY: Wiley, 2002.
clear
close all
%% Parameters
rng(253)
% Array Parameters
% elements in array
elemNum = 12;
% spacing wrt wavelength
elemSpac = 0.5;
% element locations
elemLoc = 0:elemSpac:(elemNum-1)*elemSpac;
% Signal Parameters
% signal number
sigNum = 6;
% direction of arrival
sigAng = rand(1,sigNum)*180;
% signal to noise ratio
snr = [30,70];
% sample number
sampleNum = 1000;
% parameter match check
if (length(snr) ~= sigNum) | (length(sigAng) ~= sigNum)
disp('WARN: Signal number and parameter number NOT match.')
end
%% Impinging Waves/Signals
% Transmitted Signals
% wave generation, here are some sets of uncorrelated white noise
txWave = randn(sigNum,sampleNum);
% transmit power control based on given snr
if length(snr) == 1
txWave = db2mag(snr)*txWave;
elseif length(snr) >= sigNum
if length(snr) > sigNum
disp('WARN: Extra SNRs are ignored.')
end
for i = 1:sigNum
txWave(i,:) = db2mag(snr(i))*txWave(i,:);
end
elseif length(snr) < sigNum
disp('WARN: The last SNR is used for the rest of the signals.')
for i = 1:sigNum
if i <= length(snr)
txWave(i,:) = db2mag(snr(i))*txWave(i,:);
else
txWave(i,:) = db2mag(snr(end))*txWave(i,:);
end
end
end
% Array Manifold Matrix
% For each signal, the array manifold vector is
%
% $$\mathbf{a}\left(\theta \right)=\exp \left(-j\frac{2\pi \mathbf{d}}{\lambda
% \;}\cos \theta \;\right)$$
%
% in which the element locations are
%
% $$\mathbf{d}={\left\lbrack 0,\frac{\lambda }{2},\cdots ,\left(N-1\right)\frac{\lambda
% }{2}\right\rbrack }^{\mathrm{T}}$$
if length(sigAng) > sigNum
disp('WARN: Extra angles are ignored.')
elseif length(sigAng) < sigNum
disp('ERROR: Angle number is less than signal number.')
return
end
arrayMF = exp(-1i*pi*elemLoc'*cos(sigAng(1:sigNum)/180*pi));
if sigNum > 1
% signal & interference manifold vector
sigMF = arrayMF(:,1);
intMF = arrayMF(:,2:end);
% impinging signal & interference
rxSig = sigMF*txWave(1,:);
rxIpn = intMF*txWave(2:end,:) + randn(elemNum,sampleNum);
else
% signal manifold vector
sigMF = arrayMF;
% impinging signal
rxSig = sigMF*txWave;
rxIpn = randn(elemNum,sampleNum);
end
% Received Wave
rxWave = rxSig + randn(elemNum,sampleNum);
%% Array Processing
% The MVDR problem is to minimize output interference-plus-noise power under
% distortionless contraint of target signal
%
% $$\begin{array}{l}\underset{\mathbf{w}}{\mathrm{minimize}\;\;} \;{\mathbf{w}}^{\mathrm{H}}
% {\mathbf{R}}_{\mathrm{i}+\mathrm{n}} \mathbf{w}\\\mathrm{subecto}\;\mathrm{to}\;\;{\mathbf{w}}^{\mathrm{H}}
% \mathbf{a}=1\end{array}$$
%
% The problem can be solve using the Lagrange multiplier method, and the solution
% is
%
% $$\mathbf{w}=\alpha {\mathbf{R}}_{\mathrm{i}+\mathrm{n}}^{-1} \mathbf{a}$$
%
% where $\alpha \;$is the normalization factor that ensures the power of array
% input and output desired signal remains unchanged
%
% $$\alpha =\frac{1}{{\mathbf{a}}^{\mathrm{H}} {\mathbf{R}}_{\mathrm{i}+\mathrm{n}}
% \mathbf{a}}$$
% interference-plus-noise covariance matrix
ipnCovar = rxIpn*rxIpn';
% MVDR weight vector
weight = ipnCovar\sigMF/(sigMF'*(ipnCovar\sigMF));
% = inv(ipnCovar)*sigMF/(sigMF'*inv(ipnCovar)*sigMF);
% output SINR
sinrOut = pow2db(var(weight'*rxSig)/var(weight'*rxIpn));
%% Spectrum & Figure
% scan grid
scanGrid = 0:0.1:180;
% spectrum
spec = zeros(size(scanGrid));
for i = 1:length(scanGrid)
% steering vector
scanMF = exp(-1i*pi*elemLoc'*cos(scanGrid(i)/180*pi));
% MVDR spectrum
spec(i) = weight'*scanMF;
end
% normalized spectrum
specNorm = pow2db(abs(spec));
% spectrum & signal location indicator
plot(scanGrid,specNorm)
hold on
for i = 1:sigNum
if i == 1
plot([sigAng(i),sigAng(i)],[max(specNorm),min(specNorm)],'-.r');
else
plot([sigAng(i),sigAng(i)],[max(specNorm),min(specNorm)],'-.g');
end
end
hold off
legend({'Capon Spec','Desired','Interference'},Location="southeast")
axis tight
title('Ideal Capon Spectrum')
xlabel('Degree/°')
ylabel('Magnitude/dB')
grid on
grid minor
```
{% endnote %}
### 分辨率
&emsp;&emsp;MVDR 算法的分辨率用来衡量 MVDR 算法对接近目标方向的干扰的抑制能力。假设 1 个信号和 1 个干扰同时入射,信噪比 $\mathrm{SNR}=0 \mathrm{dB}$,干噪比 $\mathrm{INR} = 70\mathrm{dB}$,假定目标来向为 90°,干扰和信号来向差在 0°~50° 范围内扫描,对阵元数 $N=4,8,12,16$ 四种情况进行仿真。
&emsp;&emsp;[图 2](#fig.2) 以 MVDR 算法的输出 SINR 作为指标,给出了随期望、干扰信号来向的角度差的变化曲线,其中输出 SINR 归一化到 0 dB,便于不同阵元数情况的对比。点划线给出了低于理想 SINR 3 dB 的值,将点划线和实线的交点作为 MVDR 算法的分辨率。
<a id="fig.2"></a>
![图 2 Capon 分辨率](../images/post/2024-02-01-algo-MVDR/2024-02-01-algo-MVDR-020-IdealCaponResolution.svg){width=700px}
{% note primary MATLAB Code %}
``` matlab mvdr_resolution.m
%% High-Resolution Frequency-Wavenumber Spectrum Analysis
% J. Capon, “High-Resolution Frequency-Wavenumber Spectrum Analysis,” _Proceedings
% of the IEEE_, vol. 57, no. 8, pp. 1408–1418, Aug. 1969, doi: <https://doi.org/10.1109/PROC.1969.7278
% 10.1109/PROC.1969.7278>.
%
% H. L. Van Trees, _Optimum Array Processing: Part IV of Detection, Estimation,
% and Modulation Theory_. New York, NY: Wiley, 2002.
clear
close all
rng(253)
%% Scan Configuration
elemNumArr = [4,8,12,16];
intAngArr = 0.1:0.1:50;
sinrOut = zeros(length(elemNumArr),length(intAngArr));
for elemNumIdx = 1:length(elemNumArr)
for intAngIdx = 1:length(intAngArr)
%% Array Parameters
% elements in array
elemNum = elemNumArr(elemNumIdx);
% spacing wrt wavelength
elemSpac = 0.5;
% element locations
elemLoc = 0:elemSpac:(elemNum-1)*elemSpac;
% Signal Parameters
% signal number
sigNum = 2;
% direction of arrival
desAng = 90;
sigAng = [desAng,desAng+intAngArr(intAngIdx)];
% signal to noise ratio
snr = [0,70];
% sample number
sampleNum = 1024;
%% Impinging Waves/Signal
% wave generation, here are some sets of uncorrelated white noise
txWave = randn(sigNum,sampleNum);
% transmit power control based on given snr
if length(snr) == 1
txWave = db2mag(snr)*txWave;
elseif length(snr) >= sigNum
if length(snr) > sigNum
disp('WARN: Extra SNRs are ignored.')
end
for i = 1:sigNum
txWave(i,:) = db2mag(snr(i))*txWave(i,:);
end
elseif length(snr) < sigNum
disp('WARN: The last SNR is used for the rest of the signals.')
for i = 1:sigNum
if i <= length(snr)
txWave(i,:) = db2mag(snr(i))*txWave(i,:);
else
txWave(i,:) = db2mag(snr(end))*txWave(i,:);
end
end
end
%% Array Manifold Matrix
if length(sigAng) > sigNum
disp('WARN: Extra angles are ignored.')
elseif length(sigAng) < sigNum
disp('ERROR: Angle number is less than signal number.')
return
end
arrayMF = exp(-1i*pi*elemLoc'*cos(sigAng(1:sigNum)/180*pi));
% signal & interference manifold vector
sigMF = arrayMF(:,1);
intMF = arrayMF(:,2:end);
% impinging signal & interference
rxSig = sigMF*txWave(1,:);
rxIpn = intMF*txWave(2:end,:) + randn(elemNum,sampleNum);
%% AWGN Channel & Received Wave
rxWave = rxSig + randn(elemNum,sampleNum);
%% Array Processing
% interference-plus-noise covariance matrix
ipnCovar = rxIpn*rxIpn';
% MVDR weight vector
weight = ipnCovar\sigMF/(sigMF'*(ipnCovar\sigMF));
% = inv(ipnCovar)*sigMF/(sigMF'*inv(ipnCovar)*sigMF);
% normalized output SINR
sinrIdeal = snr(1)+pow2db(elemNum);
sinrOut(elemNumIdx,intAngIdx) = pow2db(var(weight'*rxSig)/ ...
var(weight'*rxIpn)) - sinrIdeal;
end
plot(intAngArr,smoothdata(sinrOut(elemNumIdx,:)),DisplayName=['$N=', ...
num2str(elemNumArr(elemNumIdx)),'$'])
hold on
end
%% figures
plot([min(intAngArr),max(intAngArr)],[-3,-3],HandleVisibility="off")
hold off
title('MVDR Output SINR v.s. Angular Difference')
xlabel('Angular Difference between Desired and Interference Signal (°)')
ylabel('Normalized Output SINR (dB)')
ylim([-5 max(smoothdata(sinrOut,2),[],'all')+1])
legend(Interpreter="latex",Location="southeast");
grid on
```
{% endnote %}
### 理想误码率
## 失配情况
### 分辨率
### 误码率
# Reference
1. J. Capon, “High-Resolution Frequency-Wavenumber Spectrum Analysis,” _Proceedings of the IEEE_, vol. 57, no. 8, pp. 1408–1418, Aug. 1969, doi: [10.1109/PROC.1969.7278](https://doi.org/10.1109/PROC.1969.7278).
2. H. L. Van Trees, _Optimum Array Processing: Part IV of Detection, Estimation, and Modulation Theory_. New York, NY: Wiley, 2002.
+371
View File
@@ -0,0 +1,371 @@
---
title: Josh's Note — 凸优化<br>Part 1.2 凸集—一些重要的凸集
mathjax: true
comments: true
copyright: true
toc:
enable: true
number: false
wrap: true
expand_all: true
max_depth: 4
categories:
- - Josh 的学习笔记
- 凸优化
- 凸集
- - 数学
- 凸优化
tags:
- 凸优化
- 凸集
- 射线
- 超平面
- 半空间
- Euclid球
- 椭球
- 范数球
- 范数锥
- 二阶锥
- 多面体
- 单纯形
- 半正定锥
abbrlink: 9293b739
date: 2024-06-08 14:57:52
---
$\newcommand{\bfR}{\mathbf{R}}
\newcommand{\bfS}{\mathbf{S}}
\newcommand{\TT}{\mathrm{T}}
\newcommand{\E}{\mathcal{E}}
\newcommand{\P}{\mathcal{P}}
\def\conv{\mathop{\bf conv}}$&emsp;&emsp;本文将描述一些重要的凸集。首先介绍一些简单的例子。
- 空集 $\emptyset$、任意一个点(即单点集(singleton))$\{x_0\}$ 、全空间 $\bfR^n$ 都是 $\bfR^n$ 的仿射(自然也是凸的)子集。
- 任意直线是仿射的。如果直线通过零点,则是子空间,因此,也是凸锥。
- 一条线段是凸的,但不是仿射的(除非退化为一个点)。
- 一条**射线**(*ray*),即具有形式 $\left\{x_0 + \theta v\mid \theta \geqslant 0 \right\}, v \ne 0$ 的集合,是凸的,但不是仿射的。如果射线的基点 $x_0$ 是 $0$,则它是凸锥。
- 任意子空间是仿射的、凸锥(自然是凸的)。
<!-- more -->
# 1. 超平面与半空间
&emsp;&emsp;**超平面**(*hyperplane*)是具有如下形式的集合
$$
\left\{ x\mid a^\TT x = b \right\}
$$
其中 $a \in \bfR^n, a \ne 0$ 且 $b \in \bfR$。解析地来看,超平面是关于 $x$ 的非平凡线性方程的解空间(因此是一个仿射集合)。几何上,超平面 $\left\{ x\mid a^\TT x = b \right\}$ 可以理解为与给定向量 $a$ 的内积为常数的点的集合;也可以看成法线方向为 $a$ 的超平面,而常数 $b \in \bfR$ 决定了这个平面从原点的偏移。为更好地理解几何含义,可以将超平面表示成
$$
\left\{ x\mid a^\TT (x - x_0) = 0 \right\}
$$
其中 $x_0$ 是超平面上的任意一点(即任意满足 $a^\TT x_0 = b$ 的点)。进一步,可以表示为
$$
\left\{ x\mid a^\TT (x - x_0) = 0 \right\} = x_0 + a^\perp
$$
其中 $a^\perp$ 表示 $a$ 的正交补,即与 $a$ 正交的向量的集合:
$$
a^\perp = \left\{ v\mid a^\TT v = 0 \right\}
$$
从中可以看出,超平面由偏移 $x_0$ 加上所有正交于(法)向量 $a$ 的向量构成,具体可见[图 6](#图6) 。
<a id="图6"></a>
![图 6. $\bfR^2$ 中由法向量 $a$ 和超平面上一点 $x_0$ 确定的超平面。对于超平面上任意一点 $x$,$x - x_0$(如深色箭头所示)都垂直于 $a$。](../images/post/2024-06-08-josh-cvx-1-2/2024-06-08-josh-cvx-1-2-060-HyperplaneInR2.png){width=400px}
&emsp;&emsp;一个超平面将 $\bfR^n$ 划分为两个**半空间**(*halfspaces*)。(闭的)半空间是具有下列形式的集合,
$$\begin{equation}\label{HalfSpace}
\left\{x\mid a^\TT x \leqslant b \right\}
\end{equation}
$$
即(非平凡的)线性不等式的解空间,其中 $a\ne 0$。半空间是凸的,但不是仿射的,如[图 7](#图7) 所示。
<a id="图7"></a>
![图 7. $\bfR^2$ 上由 $a^\TT x = b$ 定义的超平面决定了两个半空间。由 a^\TT x \geqslant b 决定的半空间(无阴影)是向 $a$ 扩展的半空间。由 a^\TT x \leqslant b 确定的半空间(阴影所示)向 $-a$ 方向扩展。向量 $a$ 是这个半空间向外的法向量。](../images/post/2024-06-08-josh-cvx-1-2/2024-06-08-josh-cvx-1-2-070-AHyperplaneAndTwoHalfspaces.png){width=400px}
&emsp;&emsp;半空间 $\eqref{HalfSpace}$ 也可以表示为
$$
\left\{x\mid a^\TT (x - x_0) \leqslant 0 \right\}
$$
其中 $x_0$ 是相应超平面上的任意一点,即 $x_0$ 满足 $a^\TT x_0 = b$。上式有一个简单的几何解释:半空间由 $x_0$ 加上任意与(向外的法)向量 $a$ 呈钝角(或直角)的向量组成,如[图 8](#图8) 所示。
<a id="图8"></a>
![图 8. 阴影所示集合是由 $a^\TT (x - x_0) \leqslant 0$ 决定的半空间。向量 $x_1 - x_0$ 与 $a$ 的夹角为锐角,所以 $x_1$不在这个半空间中。向量 $x_2 - x_1$ 与 $a$ 的夹角为钝角,所以 $x_2$ 在半空间中。](../images/post/2024-06-08-josh-cvx-1-2/2024-06-08-josh-cvx-1-2-080-VectorsAndHalfspaces.png){width=400px}
&emsp;&emsp;半空间 $\eqref{HalfSpace}$ 的边界是超平面 $\left\{x\mid a^\TT x = b \right\}$。集合 $\left\{x\mid a^\TT x < b \right\}$ 是半空间 $\left\{x\mid a^\TT x \leqslant b \right\}$ 的内部,称为**开半空间**(*open halfspace*)。
# 2. Euclid球和椭球
&emsp;&emsp;$\bfR^n$ 中的空间 **Euclid 球**(*Euclidean ball*)(或简称为球)具有下面的形式:
$$
B(x_c,r) = \left\{x\mid \left\| x - x_c \right\|_2 \leqslant r \right\} = \left\{ x\mid (x-x_c)^\TT(x-x_c) \leqslant r^2 \right\}
$$
其中 $r > 0$,$\| \cdot \|_2$ 表示 Euclid 范数,即 $\|u\|_2 = (u^\TT u)^{1/2}$。向量 $x_r$ 是**球心**(*center*),标量 $r$ 为**半径**(*radius*)。$B (x_c, r)$ 由距离球心 $x_r$ 距离不超过 $r$ 的所有点组成。 Euclid 球的另一个常见的表达式为:
$$
B(x_c,r) = \left\{ x_c + ru\mid \|u\|_2 \leqslant 1 \right\}
$$
&emsp;&emsp;Euclid 球是凸集,即如果 $\|x_1-x_2\|\leqslant r$,$\|x_2-x_c\|\leqslant r$,并且 $0 \leqslant \theta \leqslant 1$,那么
$$\begin{aligned}
\left\| \theta x_1 + (1- \theta)x_2 - x_c\right\|_2 &= \left\| \theta(x_1 - x_c) + (1-\theta)(x_2 - x_c)\right\|_2
\\
&\leqslant \theta \left\|x_1 - x_c\right\|_2 + (1-\theta) \left\| x_2 - x_c \right\|_2
\\
& \leqslant r
\end{aligned}$$
(这里利用了 $\| \cdot \|_2$ 的齐次性和三角不等式。)
&emsp;&emsp;一类相关的凸集是**椭球**(*ellipsoid*),它们具有如下的形式:
$$\begin{equation}\label{ellipsoid-1}
\E = \left\{ x\mid (x-x_c)^\TT P^{-1}(x-x_c) \leqslant 1 \right\}
\end{equation}$$
其中 $P = P^\TT \succ 0$,即 $P$ 是对称正定矩阵。向量 $x_c \in \bfR^n$ 为椭球的中心。矩阵 $P$ 决定了椭球从 $x_c$ 向各个方向扩展的幅度。$\E$ 的半轴长度由 $\sqrt{\lambda_i}$ 给出,这里 $\lambda_i$ 为 $P$ 的特征值。球可以看成 $P = r^2I$ 的椭球。[图 9](#图9) 给出了 $\bfR^2$ 上的一个椭球。
<a id="图9"></a>
![图 9. 阴影所示为 $\bfR^2$ 中的一个椭球。中心 $x_c$ 由点显示,两个半轴由线段显示](../images/post/2024-06-08-josh-cvx-1-2/2024-06-08-josh-cvx-1-2-090-EllipsoidInR2.png){width=300px}
&emsp;&emsp;椭球另一个常用的表示形式是
$$\begin{equation}\label{ellipsoid-2}
\E = \left\{ x_c + Au\mid \|u\|_2 \leqslant 1 \right\}
\end{equation}$$
其中 $A$ 是非奇异的方阵。在此类表示形式中,可以不失一般性地假设 $A$ 对称正定。取 $A=P^{1/2}$,这个表达式给出了由式 $\eqref{ellipsoid-1}$ 定义的椭球。当式 $\eqref{ellipsoid-2}$ 中的矩阵 $A$ 为对称半正定矩阵,但奇异时,集合 $\eqref{ellipsoid-2}$ 称为**退化的椭球**(*degenerate ellipsoid*),其仿射维数等于 $A$ 的秩。退化的椭球也是凸的。
# 3. 范数球和范数锥
&emsp;&emsp;设 $\| \cdot \|$ 是 $\bfR^n$ 中的范数。由范数的一般性质可知,以 $r$ 为半径,$x_c$ 为球心的**范数球**(*norm ball*) $\left\{ x\mid \|x-x_c\| \leqslant r \right\}$ 是凸的。关于范数 $\| \cdot \|$ 的**范数锥**(*norm cone*)是集合
$$
C = \left\{ (x,t)\mid \|x\| \leqslant t \right\} \subseteq \bfR^{n+1}
$$
顾名思义,它是一个凸锥。
> **举例**&emsp;**二阶锥**(*second-order cone*)是由 Euclid 范数定义的范数锥,即
>
> $$\begin{aligned}
> C &= \left\{ (x,t) \in \bfR^{n+1}\mid \|x\|_2 \leqslant t\right\}
> \\
> &= \left\{ \left[\begin{array}{c}
> x \\ t
> \end{array} \right]\middle| \left[\begin{array}{c}
> x \\ t
> \end{array} \right]^\TT\left[\begin{array}{c}
> I & 0 \\ 0 & -1
> \end{array} \right] \left[\begin{array}{c}
> x \\ t
> \end{array} \right] \leqslant 0,\ t\geqslant 0 \right\}
> \end{aligned}$$
>
> 二阶锥的其他名字也常常被使用。它由二次不等式定义,因此也被称为**二次锥**(*quadratic cone*)。同时,也称其为 **Lorentz 锥**(*Lorentz cone*)或**冰激凌锥**(*ice-cream cone*)。[图 10](#图10) 显示了 $\bfR^3$ 上一个的二阶锥。
>
> <a id="图10"></a>
>
> ![图 10. $\bfR^3$ 中二阶锥 $\left\{(x_1,x_2,t)\mid (x_1^2 + x_2^2)^{1/2} \leqslant t\right\}$ 的边界](../images/post/2024-06-08-josh-cvx-1-2/2024-06-08-josh-cvx-1-2-100-BoundaryOfSecondOrderCone.png){width=500px}
# 4. 多面体
&emsp;&emsp;**多面体**(*polyhedron*)被定义为有限个线性等式和不等式的解集:
$$\begin{equation}\label{polyhedron-1}
\P = \left\{ x\mid a_j^\TT x \leqslant b_j,\ j = 1,\cdots,m,\ c_j^\TT x = d_j,\ j = 1,\cdots,p\right\}
\end{equation}$$
因此,多面体是有限个半空间和超平面的交集。仿射集合(例如子空间、超平面、直线)、射线、线段和半空间都是多面体。显而易见,多面体是凸集。有界的多面体有时也称为**多胞形**(*polytope*),但也有一些作者反过来使用这两个概念(即用多胞形表示具有 $\eqref{polyhedron-1}$ 形式的集合,而当其有界时称为多面体)。[图 11](#图11) 显示了一个由五个半空间的交集定义的多面体。
<a id="图11"></a>
![图 11. 多面体 $\P$(阴影所示)是外法向量为 $a_1,\cdots,a_5$ 的五个半空间的交集。](../images/post/2024-06-08-josh-cvx-1-2/2024-06-08-josh-cvx-1-2-110-Polyhydron.png){width=400px}
&emsp;&emsp;可以方便地使用紧凑表达式
$$\begin{equation}\label{polyhedron-2}
\P = \left\{ x\mid Ax \preceq b,\ Cx = d \right\}
\end{equation}$$
来表示 $\eqref{polyhedron-1}$,其中
$$
A = \left[\begin{array}{c}
a_1^\TT \\ \vdots \\ a_m^\TT
\end{array}\right],\qquad C = \left[\begin{array}{c}
c_1^\TT \\ \vdots \\ c_p^\TT
\end{array}\right]
$$
此处的 $\preceq$ 代表 $\bfR^m$ 上的**向量不等式**(*vector inequality*)或**分量不等式**(*componentwise inequality*):$u \preceq v$ 表示 $u_i \leqslant v_i, i = 1,\cdots, m$。
> **举例**&emsp;**非负象限**(*nonnegative orthant*)是具有非负分量的点的集合,即
>
> $$
> \bfR_+^n = \left\{ x\in\bfR^n\mid x_i \geqslant 0,\ i = 1,\cdots,n \right\} = \left\{ x\in \bfR^n\mid x \succeq 0 \right\}
> $$
>
> (此处 $\bfR_+$ 表示非负实数的集合,即 $\bfR_+ = \left\{ x\in\bfR\mid x \geqslant 0 \right\}$。)非负象限既是多面体也是锥(因此称为**多面体锥**(*polyhedral cone*))。
## 4.1 单纯形
&emsp;&emsp;**单纯形**(*simplex*)是一类重要的多面体。设 $k+1$ 个点 $v_0,\cdots,v_k \in \bfR^n$ 仿射独立,即 $v_1 - v_0, \cdots, v_k-v_0$ 线性独立,那么,这些点决定了一个单纯形:
$$\begin{equation}\label{simplex}
C = \conv{\{v_0,\cdots,v_k\}} = \left\{ \theta_0v_0 + \cdots + \theta_k v_k\mid \theta \succeq 0,\ \mathbf{1}^\TT\theta = 1 \right\}
\end{equation}$$
其中 $\mathbf{1}$ 表示所有分量均为 $1$ 的向量。这个单纯形的仿射维数为 $k$,因此也称为 $\bfR^n$ 空间的 $k$ 维单纯形。
> **举例**&emsp;**一些常见的单纯形**。1 维单纯形是一条线段;2 维单纯形是一个三角形(包含其内部); 3 维单纯形是一个四面体。
>
> **单位单纯形**(*unit simplex*)是由零向量和单位向量 $\mathbf{0}, e_1,\cdots, e_n \in \bfR^n$ 决定的 $n$ 维单纯形。它可以表示为满足下列条件的向量的集合:
>
> $$
> x \succeq 0,\qquad \mathbf{1}^\TT x\leqslant 1
> $$
>
> **概率单纯形**(*probability simplex*)是由单位向量 $e_1,\cdots, e_n \in \bfR^n$ 决定的 $n - 1$ 维单纯形。它是满足下列条件的向量的集合:
>
> $$
> x \succeq 0,\qquad \mathbf{1}^\TT x= 1
> $$
>
> 概率单纯形中的向量对应于含有 $n$ 个元素的集合的概率分布,$x_i$ 可理解为第 $i$ 个元素的概率。
&emsp;&emsp;为了用多面体来描述单纯形 $\eqref{simplex}$,采用以下步骤将其变换为 $\eqref{polyhedron-2}$ 的形式。由定义可知,$x\in C$ 的充要条件是,对于某些 $\theta\succeq 0, \mathbf{1}^\TT\theta=1$, 有 $x = \theta_0 v_0 + \theta_1 v_1 + \cdots + \theta_k v_k$。等价地,如果定义 $y = (\theta_1,\cdots,\theta_k)$ 和
$$
B = \left[ \begin{array}{c}
v_1-v_0 & \cdots & v_k-v_0
\end{array} \right] \in \bfR ^{n\times k}
$$
则 $x\in C$ 的充要条件是
$$\begin{equation}\label{IFFCondition}
x = v_0 + By
\end{equation}
$$
对于 $y \succeq 0$,$\mathbf{1}^\TT y \leqslant 1$ 成立。注意到 $v_0,\cdots,v_k$ 仿射独立意味着矩阵 $B$ 的秩为 $k$。因此,存在非奇异矩阵 $A=(A_1,A_2)\in\bfR^{n\times n}$ 使得
$$
AB = \left[ \begin{array}{c}
A_1 \\ A_2
\end{array} \right] B = \left[ \begin{array}{c}
I \\ 0
\end{array} \right]
$$
用 $A$ 左乘 $\eqref{IFFCondition}$,得到
$$
A_1 x = A_1 v_0 + y,\qquad A_2 x = A_2 v_0
$$
从中可以看出,$x\in C$ 当且仅当 $A_2 x = A_2 v_0$ 并且向量 $y = A_1 x - A_1 v_0$ 满足 $y\succeq 0$ 和 $\mathbf{1}^\TT y \leqslant 1$。换言之得到了 $x\in C$ 的充要条件,
$$
A_2 x = A_2 v_0, \qquad A_1 x \succeq A_1 v_0, \qquad \mathbf{1}^\TT A_1 x \leqslant 1 + \mathbf{1}^\TT A_1 v_0
$$
这些是 $x$ 的线性等式和不等式,因此,描述了一个多面体。
## 4.2 多面体的凸包描述
&emsp;&emsp;有限集合 $\{v_1,\cdots,v_k\}$ 的凸包是
$$
\conv\{v_1,\cdots,v_k\} = \left\{ \theta_1 v_1 + \cdots + \theta_k v_k\mid \theta \succeq 0, \ \mathbf{1}^\TT \theta = 1 \right\}
$$
它是一个有界的多面体,但是(除非是例如单纯形这样的特殊情况)无法简单地用形如 $\eqref{polyhedron-1}$ 的式子,即用线性等式和不等式的集合将其表示。
&emsp;&emsp;凸包表达式的一个扩展表示是,
$$\begin{equation}\label{ExtendedHull}
\left\{ \theta_1 v_1 + \cdots + \theta_k v_k\mid \theta_1 + \cdots + \theta_m = 1,\ \theta_i\geqslant 0, \ i=1,\cdots,k \right\}
\end{equation}$$
其中 $m\leqslant k$。此处我们考虑 $v_i$ 的非负线性组合,但是仅仅要求前 $m$ 个系数之和为一。此外,我们可以将 $\eqref{ExtendedHull}$ 解释为点 $v_1,\cdots,v_m$ 的凸包加上点 $v_{m+1},\cdots,v_k$ 的锥包。集合 $\eqref{ExtendedHull}$ 定义了一个多面体,反之亦然,每个多面体都可以表示为此类形式(虽然这一点此处并未证明)。
&emsp;&emsp;“如何表示多面体”这一问题的求解是十分巧妙的,并且有一些非常实用的结果。一个简单的例子是定义在 $\ell_\infty$-范数空间的 $\bfR^n$ 上的单位球,
$$
C = \left\{x\mid |x_i| \leqslant 1, \ i = 1,\cdots n\right\}
$$
$C$ 可以由 $2n$ 个线性不等式 $\pm e_i^\TT x \leqslant 1$ 表示为 $\eqref{polyhedron-1}$ 的形式,其中 $e_i$ 表示第 $i$ 维的单位向量。为了将其描述为形如 $\eqref{ExtendedHull}$ 的凸包,需要至少 $2^n$ 个点:
$$
C = \conv\{v_1,\cdots,v_{2^n}\}
$$
其中 $v_1,\cdots,v_{2^n}$ 是以 $1$ 和 $-1$ 为分量的全部向量,共 $2^n$ 个。可见,当 $n$ 很大时,这两种描述方式的规模相差极大。
# 5. 半正定锥
&emsp;&emsp;用 $\bfS^n$ 表示对称 $n\times n$ 矩阵的集合,即
$$
\bfS^n = \left\{ X \in \bfR ^{n\times n}\mid X = X^\TT \right\}
$$
这是一个维数为 $n(n + 1)/2$ 的向量空间。用 $\bfS^n_+$ 表示对称半正定矩阵的集合:
$$
\bfS^n_+ = \left\{ X \in \bfS^n\mid X \succeq 0 \right\}
$$
用 $\bfS^n_{++}$ 表示对称正定矩阵的集合:
$$
\bfS^n_{++} = \left\{ X \in \bfS^n\mid X \succ 0 \right\}
$$
(这些符号与 $\bfR_+$ 相对应:$\bfR_+$ 表示非负实数,而 $\bfR_{++}$ 表示正实数。)
&emsp;&emsp;集合 $\bfS^n_+$ 是一个凸锥:如果 $\theta_1,\theta_2 \geqslant 0$ 并且 $A,B\in\bfS^n_+$,那么 $\theta_1 A + \theta_2 B\in\bfS^n_+$。从半正定矩阵的定义可以直接得到:对于任意 $x \in \bfR^n$,如果 $A\succeq 0$,$B\succeq 0$ 并且 $\theta_1,\theta_2 \geqslant 0$,那么有
$$
x^\TT (\theta_1 A + \theta_2 B)x = \theta_1 x^\TT A x + \theta_2 x^\TT Bx \geqslant 0
$$
> **举例**&emsp;$\bfS^2$ 上的**半正定锥**(*Positive semidefinite cone*)。我们有
>
> $$
> X = \left[\begin{array}{c}
x & y \\ y & z
\end{array}\right] \in \bfS^2_+ \quad \Longleftrightarrow \quad x\geqslant 0, \quad z \geqslant 0, \quad xz\geqslant y^2
> $$
>
> [图 12](#图12) 给出了这个锥的边界,按 $(x,y,z)$ 表示在 $\bfR^3$ 中。
>
> <a id="图12"></a>
>
> ![图 12. $\bfS^2$ 中半正定锥的边界。](../images/post/2024-06-08-josh-cvx-1-2/2024-06-08-josh-cvx-1-2-120-BoundaryOfPostiveSemidefiniteCone.png){width=500px}
# 参考文献
1. Stephen P. Boyd and Lieven Vandenberghe, *Convex optimization*. Cambridge, UK: Cambridge University Press, 2004.
2. Stephen P. Boyd and Lieven Vandenberghe, *凸优化*. 北京: 清华大学出版社, 2013.
+322
View File
@@ -0,0 +1,322 @@
---
title: Josh's Note — 凸优化<br>Part 1.3 凸集—保凸运算
mathjax: true
comments: true
copyright: true
toc:
enable: true
number: false
wrap: true
expand_all: true
max_depth: 4
categories:
- - Josh 的学习笔记
- 凸优化
- 凸集
- - 数学
- 凸优化
tags:
- 凸优化
- 凸集
- 保凸运算
- 交集
- 仿射函数
- 伸缩
- 平移
- 线性分式
- 透视函数
abbrlink: a4a69a4f
date: 2024-06-08 23:27:19
---
$
\newcommand{\bfR}{\mathbf{R}}
\newcommand{\bfS}{\mathbf{S}}
\newcommand{\TT}{\mathrm{T}}
\newcommand{\H}{\mathcal{H}}
\newcommand{\E}{\mathcal{E}}
\newcommand{\P}{\mathcal{P}}
\def\dom{\mathop{\bf dom}}
\def\prob{\mathop{\bf prob}}
$&emsp;&emsp;本文将描述一些保凸运算,利用保凸运算可以使用凸集构造出其他凸集。这些运算与[*Part 1.2 凸集—一些重要的凸集*](https://josh-gao.top/posts/9293b739.html)中描述的凸集的简单例子一起构成了凸集的演算,可以用来确定或构建集合的凸性。
# 1. 交集
&emsp;&emsp;交集运算是保凸的:如果 $S_1$ 和 $S_2$ 是凸集,那么 $S_1 \cap S_2$ 也是凸集。这个性质可以扩展到无穷个集合的交:如果对于任意 $\alpha\in A$,$S_\alpha$ 都是凸的,那么 $\displaystyle \bigcap_{\alpha \in A} S_\alpha$ 也是凸集。(子空间、仿射集合和凸锥对与任意交运算也是封闭的。)举一个简单的例子,多面体是半空间和超平面(它们都是凸集)的交集,因而是凸的。
> **举例**&emsp;半正定锥 $\bfS^n_+$ 可以表示为
>
> $$
> \bigcap_{z\ne 0} \left\{ X \in \bfS^n\mid z^\TT Xz \geqslant 0 \right\}
> $$
>
> 对于任意 $z\ne 0$,$z^\TT Xz$ 是关于 $X$ 的(不恒等于零的)线性函数,因此集合
>
> $$
> \left\{ X \in \bfS^n\mid z^\TT Xz \geqslant 0 \right\}
> $$
>
> 实际上就是 $\bfS^n$ 的半空间。由此,半正定锥是无穷个半空间的交集,因此是凸的。
<!-- more -->
> **举例** &emsp;考虑集合
>
> $$\begin{equation}\label{example2.8}
> S = \left\{ x \in \bfR^m\mid |p(t)|\leqslant 1\ 对于\ |t| \leqslant \pi/3 \right\}
> \end{equation}$$
>
> 其中 $p(t) = \displaystyle\sum_{k=1}^m x_k \cos kt$。集合 $S$ 可以表示为无穷个**平板**(*slab*)的交集:$S = \displaystyle \bigcap_{|t|\leqslant\pi/3} S_t$,其中
>
> $$
> S_t = \left\{x\mid -1\leqslant (\cos t,\cdots, \cos mt)^\TT x \leqslant 1\right\}
> $$
>
> 因此,$S$ 是凸的。对于 $m=2$ 的情况,它的定义和集合可见[图 13](#图13) 和[图 14](#图14)。
>
> <a id="图13"></a>
>
> ![图 13. $\eqref{example2.8}$ 定义的集合 ($m=2$) 中的点的三角多项式。虚线所示的三角多项式是另外两个的平均。](../images/post/2024-06-08-josh-cvx-1-3/2024-06-08-josh-cvx-1-3-130-ThreeTrigonometricPolynomials.png){width=500px}
>
> <a id="图14"></a>
>
> ![图 14. 图中央的白色区域显示了 $m=2$ 情况下 $\eqref{example2.8}$ 定义的集合 $S$。这个集合是无限多个(图中显示了其中 20 个)平板的交集,所以是凸的。](../images/post/2024-06-08-josh-cvx-1-3/2024-06-08-josh-cvx-1-3-140-TheSetS.png){width=470px}
&emsp;&emsp;在上面这些例子中,我们通过将集合表示为(可能无穷多个)半空间的交集来表明集合的凸性。反过来我们也将看到:每一个闭的凸集 $S$ 是(通常为无限多个)半空间的交集。事实上,一个闭集 $S$ 是包含它的所有半空间的交集:
$$
S = \bigcap \left\{ \H\mid \H\ 是半空间,\ S\subseteq \H \right\}
$$
# 2. 仿射函数
&emsp;&emsp;函数 $f: \bfR^n \to \bfR^m$ 是**仿射**(*affine*)的,如果它是一个线性函数和一个常数的和,即具有 $f(x) = Ax+ b$ 的形式,其中 $A \in \bfR^{m\times n}$,$b \in \bfR^m$。假设 $S \subseteq \bfR^n$ 是凸的,并且 $f: \bfR^n \to \bfR^m$ 是仿射函数。那么,$S$ 在 $f$ 下的象
$$
f(S) = \left\{ f(x)\mid x\in S \right\}
$$
是凸的。类似地,如果 $f:\bfR^k\to\bfR^n$ 是仿射函数,那么 $S$ 在 $f$ 下的原象
$$
f^{-1}(S) = \left\{ x\mid f(x)\in S \right\}
$$
是凸的。
&emsp;&emsp;两个简单的例子是**伸缩**(*scaling*)和**平移**(*translation*)。如果 $S \subseteq \bfR^n$ 是凸集,$\alpha \in \bfR$ 并且 $a \in \bfR^n$,那么,集合 $\alpha S$ 和 $S+a$ 是凸的,其中
$$
\alpha S = \left\{ \alpha x\mid x \in S \right\},\qquad S + a = \left\{ x + a\mid x \in S \right\}
$$
一个凸集向它的某几个坐标的**投影**(*projection*)是凸的,即:如果 $S \subseteq \bfR^m \times \bfR^n$ 是凸集,那么
$$
T = \left\{ x_1\in \bfR^m\mid (x_1,x_2)\in S\ 对于某些\ x_2 \in \bfR^n \right\}
$$
是凸集。
&emsp;&emsp;两个集合的**和**(*sum*)可以定义为:
$$
S_1 + S_2 = \left\{ x + y\mid x \in S_1, y \in S_2\right\}
$$
如果 $S_1$ 和 $S_2$ 是凸集,那么,$S_1 + S_2$ 是凸的。可以看出,如果 $S_1$ 和 $S_2$ 是凸的,那么其直积或 Cartesian 乘积
$$
S_1 \times S_2 = \left\{ (x_1,x_2)\mid x_1\in S_1, x_2\in S_2 \right\}
$$
也是凸集。这个集合在线性函数 $f(x_1,x_2) = x_1+x_2$ 下的象是和 $S_1 + S_2$。
&emsp;&emsp;也可以考虑 $S_1,S_2 \in \bfR^m \times \bfR^n$ 的**部分和**(*partial sum*),定义为
$$
S = \left\{ (x,y_1 + y_2)\mid (x,y_1)\in S_1,\ (x,y_2)\in S_2 \right\}
$$
其中 $x\in\bfR^n$,$y_i \in \bfR^m$。$m=0$ 时,部分和给出了 $S_1$ 和 $S_2$的交集;$n=0$ 时,部分和等于集合之和。凸集的部分和是凸集。
> **举例**&emsp;**多面体**。$\{ x\mid Ax \preceq b, Cx = d \}$ 可以表示为非负象限和原点的 Cartesian 乘积在仿射函数 $f(x) = (b -Ax, d - Cx)$ 下的原象:
>
> $$
> \{x\mid Ax\preceq b, Cx = d\} = \{ x\mid f(x) \in \bfR^m_+ \times \{0\}\}
> $$
>
> {% note info %}这里可以这样理解:函数 $f(x) = (b -Ax, d - Cx)$ 在条件 $Ax \preceq b, Cx = d$ 下的值域为 $\mathbf{R}^m_+ \times \{0\}$。{% endnote %}
> **举例**&emsp;**线性矩阵不等式的解**。条件
>
> $$\begin{equation}
> A(x) = x_1 A_1 + \cdots + x_nA_n \preceq B
> \end{equation}$$
>
> 称为关于 $x$ 的**线性矩阵不等式**(*Linear Matrix Inequality, LMI*),其中 $B,A_i \in \bfS^m$(注意它与有序线性不等式
>
> $$
> a^\TT x = x_1a_1+\cdots x_na_n \leqslant b
> $$
>
> 的相似性,其中 $b,a_i\in \bfR$。)
>
> 线性矩阵不等式的解 $\{ x\mid A(x) \preceq B\}$ 是凸集。事实上,它是半正定锥在由 $f(x) = B-A(x)$ 给定的仿射映射 $f: \bfR^n \to \bfS^m$ 下的原象。
> **举例**&emsp;**双曲锥**。集合
>
> $$
> \{ x\mid x^\TT Px \leqslant (c^\TT x) ^2, c^\TT x \geqslant 0 \}
> $$
>
> 是凸集,其中 $P\in\bfS^n_+$,$c\in\bfR$。这是因为它是二阶锥
>
> $$
> \{ (z,t)\mid z^\TT z \leqslant t ^2 , t \geqslant 0 \}
> $$
>
> 在仿射函数 $f(x) = (P^{1/2}x,c^\TT x)$ 下的原象。
> **举例**&emsp;**椭球**。椭球
>
> $$
> \E = \{ x\mid (x-x_c)^\TT P^{-1} (x-x_c) \leqslant 1 \}
> $$
>
> 是单位 Euclid 球 $\{ u\mid \|u\|_2 \leqslant 1 \}$ 在仿射映射 $f(u) = P^{1/2}u + x_c$ 下的象, 其中 $P \in \bfS^n_{++}$。(同时也是单位球在仿射映射 $g(x) = P^{-1/2}(x — x_c)$ 下的原象。)
# 3. 线性分式及透视函数
&emsp;&emsp;本节将讨论一类称为**线性分式**(*linear-fractional*)的函数,它比仿射函数更普遍,并且仍然保凸。
## 3.1 透视函数
&emsp;&emsp;定义 $P:\bfR^{n+1}\to\bfR^n$,$P(z,t) = z/t$ 为**透视函数**(*perspective function*),其定义域为 $\dom P = \bfR^n \times \bfR_{++}$。(此处的 $\bfR_{++}$ 表示正实数集合,即 $\bfR_{++} = \{ x\in\bfR\mid x > 0 \}$。)透视函数对向量进行伸缩(scale),或称为规范化(normalize),使得最后一维分量为1 并舍弃之。
> **注释**&emsp;我们用小孔成象来解释透视函数。($\bfR^3$ 中的)小孔照相机由一个不透明的水平面 $x_3 = 0$ 和一个在原点的小孔组成,光线通过这个小孔在 $x_3 = -1$ 呈现出一个水平图像。在相机上方 $x$($x_3 > 0$)处的一个物体,在相平面的点 $-(x_1/x_3,x_2/x_3,1)$ 处形成一个图像。忽略象点的最后一维分量(因为它恒等于 $-1$),$x$ 处的点的象在象平面上呈现于 $y=-(x_1/x_3,x_2/x_3)$ 处。[图 15](#图15)显示了这个过程。
>
> <a id="图15"></a>
>
> ![图 15. 透视函数的小孔成象解释。深色的水平直线表示 $\bfR^3$ 中的平面 $x_3 = 0$,除了在原点处有一个小孔外,它是不透光的。平面之上的物体或光源呈现在浅色水平直线所示的象平面 $x_3 = -1$ 上。源位置向其象位置的映射对应于透视函数。](../images/post/2024-06-08-josh-cvx-1-3/2024-06-08-josh-cvx-1-3-150-PinHoleCameraInterpretationOfPerspectiveFuncation.png){width=500px}
&emsp;&emsp;如果 $C \subseteq \dom P$ 是凸集,那么它的象
$$
P(C) = \{ P(x)\mid x\in C \}
$$
也是凸集。这个结论很直观:通过小孔观察一个凸的物体,可以得到凸的象。为解释这个事实,我们将说明在透视函数作用下,线段将被映射成线段。(也可以这样理解,通过小孔,一条线段的象是一条线段。)
> **解释**&emsp;假设 $x = (\tilde{x},x_{n+1})$,$y = (\tilde{y}, y_{n+1}) \in \bfR^{n+1}$,并且 $x_{n+1}>0$,$y_{n+1}>0$ 。那么,对于 $0 \leqslant \theta \leqslant 1$
>
> $$
> P(\theta x + (1-\theta)y) = \frac{\theta\tilde{x}+ (1-\theta)\tilde{y}}{\theta x_{n+1} + (1-\theta)y_{n+1}} = \mu P(x) + (1-\mu) P(y)
$$
>
> 其中
>
> $$
> \mu = \frac{\theta x_{n+1}}{\theta x_{n+1} + (1-\theta) y_{n+1}}\in[0,1]
> $$
>
> $\theta$ 和 $\mu$ 之间的关系是单调的:当 $\theta$ 在 $0$、$1$ 间变化时(形成线段 $[x,y]$),$\mu$ 也在 $0$、$1$ 间变化(形成线段 $[P(x),P(y)]$。这说明 $P([x,y]) = [P(x),P(y)]$。
&emsp;&emsp;现在假设 $C$ 是凸的,并且有 $C \subseteq \dom P$(即对于所有 $x\in C$,$x_{n+1} > 0$)及 $x,y\in C$。为显示 $P(C)$ 的凸性,需要说明线段 $[P(x), P(y)]$ 在 $P(C)$ 中。这条线段是线段 $[x,y]$ 在 $P$ 的象,因而属于 $P(C)$。
&emsp;&emsp;一个凸集在透视函数下的原象也是凸的:如果 $C\subseteq \bfR^n$ 为凸集,那么
$$
P^{-1}(C) = \{ (x,t)\in\bfR^{n+1}\mid x/t\in C, t > 0 \}
$$
是凸集。为证明这点,假设 $(x,t)\in P^{-1}(C)$,$(y,s)\in P^{-1}(C)$,$0 \leqslant \theta \leqslant 1$。我们需要说明
$$
\theta(x,t) + (1-\theta)(y,s) \in P^{-1} (C)
$$
即
$$
\frac{\theta x + (1-\theta)y}{\theta t + (1-\theta)s} \in C
$$
(显然,$\theta t+(1-\theta)s>0$)。这可从下式看出,
$$
\frac{\theta x+(1-\theta)y}{\theta t+(1-\theta)s}=\mu(x/t)+(1-\mu)(y/s)
$$
其中
$$
\mu=\frac{\theta t}{\theta t+(1-\theta)s}\in[0,1]
$$
## 3.2 线性分式函数
&emsp;&emsp;**线性分式函数**(*linear-fractional function*)由透视函数和仿射函数复合而成。设 $g:\bfR^n \to \bfR^{m+1}$ 是仿射的,即
$$\begin{equation}\label{AffineFunction}
g(x) = \left[\begin{array}{c}
A \\ c^\TT
\end{array}\right]x + \left[\begin{array}{c}
b \\ d
\end{array}\right]
\end{equation}$$
其中 $A \in \bfR ^{m\times n}$,$b \in \bfR^m$,$c \in \bfR^n$ 并且 $d\in\bfR^n$。则由 $f =P\circ g$ 给出的函数 $f:\bfR^n \to \bfR^m$
$$\begin{equation}\label{LinearFractionalFunction}
f(x) = (Ax+b)/(c^\TT x + d),\qquad \dom f = \{x\mid c^\TT x + d > 0\}
\end{equation}$$
称为**线性分式**(*linear-fractional*)(或**投射**(*projective*))函数。如果 $c = 0$,$d > 0$,则 $f$ 的定义域为 $\bfR^n$ 并且 $f$ 是仿射函数。因此,我们可以将仿射和线性函数视为特殊的线性分式函数。
> **注释**&emsp;**投射解释**。可以很方便地将一个线性分式函数表示为:将矩阵
>
> $$\begin{equation}
> Q = \left[\begin{array}{c}
> A & b \\ c^\TT & d
> \end{array}\right] \in \bfR^{(m+1)\times (n+1)}
> \end{equation}$$
>
> 作用于(即左乘)点 $(x,1)$,得到 $(Ax + b,c^\TT x + d)$;然后将所得结果做伸缩变换或归一化,以使得其最后一个分量为一,得到 $(f(x), 1)$。
>
> 也可以从儿何上进行解释,即这个表达式将 $\bfR^n$ 与 $\bfR^{n+1}$ 空间上的一组射线联系了起来。也就是说,对于 $\bfR^n$ 空间的一个点 $z$,我们可以构造一个 $\bfR^{n+1}$ 空间的(开)射线 $\P(z) = \{t(z,1)\mid t > 0\}$。这条射线上每个点的最后一个分量均是正值。反之, $\bfR^{n+1}$ 空间中每条以原点为顶点并且最后一个分量为正值的射线均可以由一些 $v\in\bfR^n$ 表示为 $\P(v) = \{t(v, 1)\mid t \geqslant 0\}$。$\P$ 表示了 $\bfR^n$ 与最后一个分量为正的射线之间的(投射)关系,这种关系是一一对应和满的。
>
> 线性分式函数 $\eqref{LinearFractionalFunction}$ 可以表示为
>
> $$
> f(x) = \P^{-1}(Q\P(x))
> $$
>
> 因此,从 $x\in\dom f$ 出发,即由一个满足 $c^\TT x +d > 0$ 的点,可以得到 $\bfR^{n+1}$ 空间的一条射线 $\P(x)$。将线性变换矩阵 $Q$ 作用于这条射线,就可以得到另一条射线 $Q\P(x)$。因为 $x \in \dom f$,这条射线的最后一个分量为正。最后,我们也可以通过逆投射变换恢复出 $f(x)$。
&emsp;&emsp;类似于透视函数,线性分式函数也是保凸的。如果 $C$ 是凸集并且在 $f$ 的定义域中(即任意 $x\in C$ 满足 $c^\TT x+d > 0$),那么 $C$ 的象 $f(C)$ 也是凸集。根据前述的结果可以直接得到这个结论: $C$ 在仿射映射 $\eqref{AffineFunction}$ 下的象是凸的,并且在透视函数 $P$ 下的映射(即 $f(C)$)是凸的。类似地,如果 $C \subseteq \bfR^m$ 是凸集,那么其原象 $f^{-1}(C)$ 也是凸的。
> **举例**&emsp;**条件概率**。设 $u$ 和 $v$ 是分别在 $\{1, \cdots, n\}$ 和 $\{1, \cdots, m\}$ 中取值的随机变量,并且 $p_{ij}$ 表示概率 $\prob(u = i,v = j)$。那么条件概率 $f_{ij} = \prob(u = i\mid v = j)$ 由下式给出
>
> $$
> f_{ij} = \frac{p_{ij}}{\displaystyle\sum_{k=1}^n p_{kj}}
> $$
>
> 因此,$f$ 可以通过一个线性分式映射从 $p$ 得到。
>
> 可以知道,如果 $C$ 是一个关于 $(u,v)$ 的联合密度的凸集,那么相应的 $u$ 的条件密度(给定 $v$)的集合也是凸集。
&emsp;&emsp;[图 16](#图16) 表示了集合 $C\subseteq \bfR^2$ 及其在下面的线性分式函数下的象
$$
f(x) = \frac{1}{x_1 + x_2 + 1} x,\qquad \dom f = \{(x_1,x_2)\mid x_1+x_2+1>0\}
$$
<a id="图15"></a>
![图 16. **左**:集合 $C\subseteq \bfR^2$。虚线显示了线性分式函数 $f(x) = x/(x_1 + x_2 + 1)$ 的定义域的边界,其中 $\dom f = \{(x_1,x_2)\mid x_1+x_2+1>0\}$。**右**:$C$ 在 $f$ 下的象。虚线显示了 $f^{-1}$ 的定义域的边界。](../images/post/2024-06-08-josh-cvx-1-3/2024-06-08-josh-cvx-1-3-160-ASetAndItsImageUnderLFF.png){width=800px}
# 参考文献
1. Stephen P. Boyd and Lieven Vandenberghe, *Convex optimization*. Cambridge, UK: Cambridge University Press, 2004.
2. Stephen P. Boyd and Lieven Vandenberghe, *凸优化*. 北京: 清华大学出版社, 2013.
+160
View File
@@ -0,0 +1,160 @@
---
title: Josh's Note — 凸优化<br>Part 1.4 凸集—广义不等式
mathjax: true
comments: true
copyright: true
toc:
enable: true
number: false
wrap: true
expand_all: true
max_depth: 4
categories:
- - Josh 的学习笔记
- 凸优化
- 凸集
- - 数学
- 凸优化
tags:
- 凸优化
- 凸集
- 广义不等式
- 正常锥
- 最小元
- 极小元
- 最大元
- 极大元
abbrlink: aff3a091
date: 2024-06-12 16:49:26
---
# 1. 正常锥与广义不等式
$
\newcommand{\bfR}{\mathbf{R}}
\newcommand{\bfS}{\mathbf{S}}
\newcommand{\E}{\mathcal{E}}
\newcommand{\TT}{\mathrm{T}}
\def\iint{\mathop{\bf int}}
$&emsp;&emsp;称锥 $K \subseteq \bfR^n$ 即为**正常锥**(*proper cone*),如果它满足下列条件
- K 是凸的。
- K 是闭的。
- K 是**实**(*solid*)的,即具有非空内部。
- K 是**尖**(*pointed*)的,即不包含直线(或者等价地,$x\in K, -x \in K \Longrightarrow x = 0$)。
正常锥 $K$ 可以用来定义**广义不等式**(*generalized inequality*),即 $\bfR^n$ 上的偏序关系。这种偏序关系和 $\bfR$ 上的标准序有很多相同的性质。用正常锥 $K$ 可以定义 $\bfR^n$ 上的偏序关系如下
$$
x \preceq_K y \Longleftrightarrow y - x \in K
$$
$y \preceq_K x$ 也可以写为 $x \succeq_K y$。类似地,定义相应的严格偏序关系为
$$
x \prec_K y \Longleftrightarrow y - x \in \iint K
$$
并且可以同样地定义 $x \succ_K y$。(为将广义不等式 $\preceq_K$ 与严格的广义不等式区分开,有时也称 $\preceq_K$ 为不严格的广义不等式)。
<!-- more -->
&emsp;&emsp;当 $K = \bfR_+$ 时,偏序关系 $\preceq_K$ 就是通常意义上 $\bfR$ 中的序 $\leqslant$;相应地,严格偏序关系 $\prec_K$ 与 $\bfR$ 上的严格序 $<$ 相同。因此,广义不等式包含了 $\bfR$ 上的(不严格和严格)不等式,它是广义不等式的一种特殊情况。
> **举例**&emsp;**非负象限及分量不等式**。非负象限 $K = \bfR^n_+$ 是一个正常锥。相应的广义不等式 $\preceq_K$ 对应于向量间的分量不等式,即 $x \preceq_K y$ 等价于 $x_i \leqslant y_i, i = 1,\cdots,n$。相应地,其严格不等式对应于严格的分量不等式,即 $x \prec_K y$ 等价于 $x_i < y_i, i = 1,\cdots,n$。
>
> 我们会经常使用对应于非负象限的不严格和严格的偏序关系,因此省略下标 $K$。当 $\preceq$ 或 $\prec$ 出现在向量间的时候,该符号应被理解为分量不等式。
> **举例**&emsp;**半正定锥和矩阵不等式**。半正定锥是 $\bfS^n$ 空间中的正常锥,相应的广义不等式 $\preceq_K$ 就是通常的矩阵不等式,即 $X \preceq_K Y$ 等价于 $Y - X$ 为半正定矩阵。(在 $\bfS^n$ 中)$\bfS^n_+$ 的内部由正定矩阵组成,因此严格广义不等式也等同于通常的对称矩阵的严格不等式,即 $X \prec_K Y$ 等价于 $Y - X$ 为正定矩阵。
>
> 这里,也是由于经常使用这种偏序关系,因此省略其下标,即对于对称矩阵,我们将广义不等式简写为 $X \preceq Y$ 或 $X \prec Y$, 它们表示关于半正定锥的广义不等式。
> **举例**&emsp;**$[0, 1]$ 上非负的多项式锥**。$K$ 定义如下
>
> $$\begin{equation}
> K = \{ c\in\bfR^n\mid c_1 + c_2 t + \cdots + c_n t^{n-1} \geqslant 0\ 对于\ t \in [0,1]\}
> \end{equation}$$
>
> 即 $K$ 是 $[0, 1]$ 上最高 $n - 1$ 阶的非负多项式(系数)锥。可以看出 $K$ 是一个正常锥,其内部是 $[0, 1]$ 上为正的多项式的系数集合。
>
> 两个向量 $c, d \in \bfR^n$ 满足 $c \preceq_K d$ 的充要条件是,对于所有 $t \in [0, 1]$ 有
>
> $$
> c_1 + c_2 t + \cdots + c_n t^{n-1} \leqslant d_1 + d_2 t + \cdots + d_n t^{n-1}
> $$
## 1.1 广义不等式的性质
&emsp;&emsp;广义不等式 $\preceq_K$ 满足许多性质,例如
- **$\preceq_K$ 对于加法是保序的**:如果 $x \preceq_K y$ 并且 $u \preceq_K v$,那么 $x + u \preceq_K y + v$。
- **$\preceq_K$ 具有传递性**:如果 $x \preceq_K y$ 并且 $y \preceq_K z$,那么 $x \preceq_K z$。
- **$\preceq_K$ 对于非负数乘是保序的**:如果 $x \preceq_K y$ 并且 $\alpha \geqslant 0$,那么 $\alpha x \preceq_K \alpha y$。
- **$\preceq_K$ 是自反的**:$x \preceq_K x$。
- **$\preceq_K$ 是反对称的**:如果 $x \preceq_K y$ 并且 $y \preceq_K x$,那么 $x = y$。
- **$\preceq_K$ 对于极限运算是保序的**:如果对于 $i = 1,2,\dots$ 均有 $x_i \preceq_K y_i$,当 $i \to \infty$ 时,有 $x_i \to x$ 和 $y_i \to y$,那么 $x \preceq_K y$。
相应的广义不等式 $\prec_K$ 也满足一些性质,例如
- 如果 $x \prec_K y$,那么 $x \preceq_K y$。
- 如果 $x \prec_K y$ 并且 $u \prec_K v$, 那么 $x + u \prec_K y + v$。
- 如果 $x \prec_K y$ 并且 $\alpha > 0$,那么 $\alpha x \prec_K \alpha y$。
- $x \nprec_K x$。
- 如果 $x \prec_K y$,那么对于足够小的 $u$ 和 $v$ 有 $x + u \prec_K y + v$。
这些性质可以从 $\preceq_K$ 和 $\prec_K$ 的定义以及正常锥的性质中直接得到。
# 2. 最小与极小元
&emsp;&emsp;广义不等式的符号($\preceq_K$,$\prec_K$)似乎表明它们与 $\bfR$ 上的普通不等式($\leqslant$,$<$)有着相同的性质。虽然普通不等式的许多性质对于广义不等式确实成立,但很多重要的性质并不如此。最明显的区别在于,$\bfR$ 上的 $\leqslant$ 是一个**线性序**(*linear ordering*),即任意两点都是**可比的**(*comparable*),也就是说 $x\leqslant y$ 和 $y \leqslant x$ 二者必居其一。这个性质对于其他广义不等式并不成立。这导致了最小、最大这些概念在广义不等式环境下变得更加复杂。本节将对此进行简要的讨论。
&emsp;&emsp;如果对于每个 $y \in S$,均有 $x \preceq_K y$,称 $x\in S$ 是 $S$(关于广义不等式 $\preceq_K$)的**最小元**(*minimum element*)。类似地,我们可以定义关于广义不等式的**最大元**(**maximum element**)。如果一个集合有最小(或最大)元,那么它们是唯一的。
&emsp;&emsp;相对应的概念是**极小元**(*minimal element*)。如果 $y \in S$,$y \preceq_K x$ 可以推得 $y=x$,那么称 $x\in S$ 是 $S$ 上(关于广义不等式 $\preceq_K$)的**极小元**(*minimal element*)。同样地,可以定义**极大元**(*maximal element*)。一个集合可以有多个极小(或极大)元。
&emsp;&emsp;可以用简单的集合符号对最小元和极小元进行描述。元素 $x\in S$ 是 $S$ 中的一个最小元,当且仅当
$$
S \subseteq x + K
$$
这里 $x+K$ 表示可以与 $x$ 相比并且大于或等于(根据 $\preceq_K$)$x$ 的所有元素。元素 $x\in S$ 是极小元,当且仅当
$$
(x - K) \cap S = \{x\}
$$
这里 $x-K$ 表示可以与 $x$ 相比并且小于或等于(根据立$\preceq_K$)$x$ 的所有元素,它与 $S$ 的唯一共同点即是 $x$。
&emsp;&emsp;$K=\bfR^n$ 导出的实际上就是 $\bfR$ 上一般的序。此时,极小和最小的概念是一致的,也符合集合最小元素的通常定义。
> **举例**&emsp;考虑锥 $\bfR^2_+$,它导出的是 $\bfR^2$ 上的关于分量的不等式。对此,可以给出一些关于极小元和最小元的简单的几何描述。不等式 $x \preceq y$ 的含义是 $y$ 在 $x$ 之上、之右。$x \in S$是集合 $S$ 的最小元,表明 $S$ 的其他所有点都在它之上、之右。而 $x$ 为集合 $S$ 的极小元,是指 $S$ 中没有任何一个点在 $x$ 之下、之左,其区别可见[图 17](#图17)。
>
> <a id="图17"></a>
>
> ![图 17. **左**:集合出关于 $\bfR^2$ 上的分量不等式有最小元 $x_1$。集合 $x_1+K$ 由浅色阴影所示;$x_1$ 是 $S_1$ 的最小元,因为 $S_1 \subseteq x_1 + K$。**右**:点 $x_2$ 是 $S_2$ 的极小元。集合 $x_2-K$ 由浅色阴影所示。点 $x_2$ 是极小的,因为 $x_2-K$ 和 $S_2$ 只相交于 $x_2$](../images/post/2024-06-12-josh-cvx-1-4/2024-06-12-josh-cvx-1-4-170-MinimalAndMinimum.png){width=700px}
> **举例**&emsp;**对称矩阵集合中的最小元和极小元**。用 $A \in \bfS^n_{++}$ 表示一个圆心在原点的椭圆,即
>
> $$
> \E_A = \{ x\mid x^\TT A^{-1} x \leqslant 1 \}
> $$
>
> 我们知道 $A \preceq B$ 等价于 $\E_A \subseteq \E_B$。
>
> 给定 $v_1,\cdots,v_k \in \bfR^n$ 并定义
>
> $$
> S = \{ P \in \bfS ^n_{++}\mid v_i^\TT P^{-1} v_i \leqslant 1,\ i = 1,\dots k \}
> $$
>
> 它对应于包含了点 $v_1,\cdots,v_k$ 的椭圆的集合。集合 $S$ 没有最小元:对于任意包含点$v_1,\cdots,v_k$ 的椭圆,总可以找到另一个包含这些点但不可比的椭圆。一个椭圆是极小的,如果它包含这些点但没有更小的椭圆也包含这些点。[图 18](#图18)显示了 $\bfR^2$ 上 $k = 2$ 时的一个例子。
>
> <a id="图18"></a>
>
> ![图 18. $\bfR^2$ 中的三个椭球,它们均以原点(图中较低的点所示)为中心,并且包含较高处的点。椭球 $\E_1$ 不是极小的,因为存在包含这些点并且更小的椭球(例如,$\E_3$)。由于同样的原因,$\E_3$ 也不是极小的。椭球 $\E_2$ 是极小的,因为没有其他(以原点为中心)包含这些点并被 $\E_2$ 包含的椭球。](../images/post/2024-06-12-josh-cvx-1-4/2024-06-12-josh-cvx-1-4-180-ThreeEllipsoids.png){width=300px}
# 参考文献
1. Stephen P. Boyd and Lieven Vandenberghe, *Convex optimization*. Cambridge, UK: Cambridge University Press, 2004.
2. Stephen P. Boyd and Lieven Vandenberghe, *凸优化*. 北京: 清华大学出版社, 2013.
+190
View File
@@ -0,0 +1,190 @@
---
title: Josh's Note — 凸优化<br>Part 1.5 凸集—分离与支撑超平面
mathjax: true
comments: true
copyright: true
toc:
enable: true
number: false
wrap: true
expand_all: true
max_depth: 4
categories:
- - Josh 的学习笔记
- 凸优化
- 凸集
- - 数学
- 凸优化
tags:
- 凸优化
- 凸集
abbrlink: bc5bb04
date: 2024-06-12 18:29:40
---
# 1. 超平面分离定理
$
\newcommand{\bfR}{\mathbf{R}}
\newcommand{\TT}{\mathrm{T}}
\newcommand{\d}{\mathrm{d}}
\def\dist{\mathop{\bf dist}}
\def\iint{\mathop{\bf int}}
\def\bd{\mathop{\bf bd}}
\def\cl{\mathop{\bf cl}}
$&emsp;&emsp;本节将阐述一个在之后非常重要的想法:用超平面或仿射函数将两个不相交的凸集分离开来。其基本结果就是**超平面分离定理**(*separating hyperplane theorem*):假设 $C$ 和 $D$ 是两个不相交的凸集,即 $C \cap D = \emptyset$,那么存在 $a \ne 0$ 和 $b$ 使得对于所有 $x\in C$ 有 $a^\TT x \leqslant b$,对于所有 $x\in D$ 有 $a^\TT x \geqslant b$。换言之,仿射函数 $a^\TT x-b$ 在 $C$ 中非正,而在 $D$ 中非负。超平面 $\{ x\mid a^\TT x = b \}$ 称为集合 $C$ 和 $D$ 的**分离超平面**(*separating hyperplane*),或称超平面**分离**(*separate*)了集合 $C$ 和 $D$,如[图 19](#图19)。
<a id="图19"></a>
![图 19. 超平面 $\{ x\mid a^\TT x = b \}$ 分离了两个不相交的凸集 $C$ 和 $D$。仿射函数 $a^\TT x-b$ 在 $C$ 上非正而在 $D$ 上非负。](../images/post/2024-06-12-josh-cvx-1-5/2024-06-12-josh-cvx-1-5-190-Hyperplane.png){width=400px}
<!-- more -->
## 1.1 超平面分离定理的证明
&emsp;&emsp;这里我们考虑一个特殊的情况下的证明。假设 $C$ 和 $D$ 的(Euclid)**距离**(*distance*)为正,这里的距离定义为
$$
\dist(C,D) = \inf\{ \|u,v\|_2\mid u \in C,\ v \in D\}
$$
并且存在 $c\in C$ 和 $d\in D$ 达到这个最小距离,即 $\|c-d\|_2=\dist(C,D)$。(这些条件是可以被满足的,例如当 $C$ 和 $D$ 是闭的并且其中之一是有界的。)
&emsp;&emsp;定义
$$
a = d - c,\qquad b = \frac{\|d\|_2^2 - \|c\|_2^2}{2}
$$
我们将显示仿射函数
$$
f(a) = a^\TT x - b = (d-c)^\TT(x - (1/2)(d+c))
$$
在 $C$ 中非正而在 $D$ 中非负,即超平面 $\{ x\mid a^\TT x = b \}$ 分离了 $C$ 和 $D$。这个超平面与连接 $c$ 和 $d$ 之间的线段相垂直并且穿过其中点,如[图 20](#图20) 所示。
<a id="图20"></a>
![图 20. 两个凸集间分离超平面的构造。$c \in C$ 和 $d\in D$ 是两个集合中最靠近彼此的一个点对。分离超平面垂直并且等分 $c$ 和 $d$ 之间的线段。](../images/post/2024-06-12-josh-cvx-1-5/2024-06-12-josh-cvx-1-5-200-SeparateHyperplane.png){width=400px}
&emsp;&emsp;首先证明 $f$ 在 $D$ 中非负。关于 $f$ 在 $C$ 中非正的证明是相似的(只需将 $C$ 和 $D$ 交换并考虑 $-f$ 即可)。
> **证明**&emsp;假设存在一个点 $u\in D$,并且
>
> $$\begin{equation}\label{ufunction}
> f(u) = (d-c)^\TT (u - (1/2)(d+c)) < 0
> \end{equation}$$
>
> 可以将 $f(u)$ 表示为
>
> $$
> f(u) = (d-c)^\TT (u - d + (1/2)(d-c)) = (d-c)^\TT(u-d) + (1/2) \| d-c \|_2^2
> $$
>
> 可以看出式 $\eqref{ufunction}$ 意味着 $(d-c)^\TT(u-d) < 0$。于是,观察到
>
> $$
> \left. \frac{\d}{\d t} \|d + t(u-d) - c\|_2^2 \right|_{t=0} = 2(d-c)^\TT(u-d) < 0
> $$
>
> 因此,对于足够小的 $t>0$ 及 $t\leqslant 1$,有
>
> $$
> \| d + t(u-d) - c \|_2 < \| d -c \|_2
> $$
>
> 即点 $d+t(u-d)$ 比 $d$ 更靠近 $c$。因为 $D$ 是包含 $d$ 和 $u$ 的凸集,我们有 $d+t(u-d) \in D$。但这是不可能的,因为根据假设,$d$ 应当是 $D$ 中离 $C$ 最近的点。
> **举例**&emsp;**仿射集与凸集的分离**。设 $C$ 是凸集,而 $D$ 是仿射的,即 $D = \{ Fu + g\mid u \in \bfR^m\}$,其中 $F \in \bfR^{n\times m}$。设 $C$ 和 $D$ 不相交,那么根据超平面分离定理,存在 $a \ne 0$ 和 $b$ 使得对于所有 $x \in C$ 有 $a^\TT x \leqslant b$,对于所有 $x \in D$ 有 $a^\TT x \geqslant b$。
>
> 这里 $a^\TT x \geqslant b$ 对于所有 $x \in D$ 均成立,表明对于任意 $u \in \bfR^m$ 均有 $a^\TT Fu \geqslant b - a^\TT g$。但是在 $\bfR^m$ 上,只有当一个线性函数为零时,它才是有界的。因此,可以推知 $a^\TT F=0$ (并且因此有 $b \leqslant a^\TT g$)。
>
> 所以可知,存在 $a \ne 0$ 使得 $F^\TT a =0$ 和 $a^\TT x \leqslant a^\TT g$ 对于所有 $x\in C$ 均成立。
## 1.2 严格分离
&emsp;&emsp;如果之前构造的分离超平面满足更强的条件,即对于任意 $x\in C$ 有 $a^\TT x < b$ 并且对于任意 $x\in D$ 有 $a^\TT x > b$, 则称其为集合 $C$ 和 $D$ 的**严格分离**(*strict separation*)。简单的例子就可以看出,对于一般的情况,不相交的凸集并不一定能够被超平面严格分离(即使集合是闭集)。但是,在很多特殊的情况下,可以构造严格分离。
> **举例**&emsp;**点和闭凸集的严格分离**。令 $C$ 为闭凸集,而 $x_0 \notin C$,那么存在将 $x_0$ 与 $C$ 严格分离的超平面。
>
> 为说明这一点,需要注意,对于足够小的 $\epsilon > 0$,存在两个不相交的集合 $C$ 和 $B(x_0, \epsilon)$。根据超平面分离定理,存在 $a \ne 0$ 和 $b$,使得对于任意 $x\in C$ 有 $a^\TT x \leqslant b$;对于任意 $x \in B(x_0, \epsilon)$ 有 $a^\TT x \geqslant b$。
>
> 利用 $B(x_0, \epsilon) = \{ x_0 + u\mid \|u\|_2 \leqslant \epsilon \}$,可以将前述第二个条件表示为
>
> $$
> a^\TT (x_0 + u) \geqslant b\ 对于所有\ \|u\|_2 \leqslant \epsilon
> $$
>
> $u = -\epsilon a / \|a\|_2$ 极小化了上式的左端,代入可得
>
> $$
> a^\TT x_0 - \epsilon \| a \|_2 \geqslant b
> $$
>
> 所以,仿射函数
>
> $$
> f(x) = a^\TT x - b - \epsilon \|a\|_2/2
> $$
>
> 在 $C$ 上是负的,而在 $x_0$ 点是正的。
>
> 由此可以得到前面已提及的事实:一个闭凸集是包含它的所有半空间的交集。事实上,令 $C$ 为闭和凸的,$S$ 为所有包含 $C$ 的半空间。显然,$x\in C \Rightarrow x \in S$。为证明反方向,假设存在 $x\in S$ 并且 $x \notin C$。根据严格分离的结果,存在一个将 $x$ 与 $C$ 严格分离的超平面,即存在一个包含 $C$ 但不包含 $x$ 的半空间。也就是说,$x \notin S$。
## 1.3 超平面分离定理的逆定理
&emsp;&emsp;超平面分离定理的逆定理(即分离超平面的存在表明 $C$ 和 $D$ 不相交)是不成立的,除非在凸性之外再给 $C$ 或 $D$ 附加其他约束。
> **反例**&emsp;考虑 $C = D = \{0\} \subseteq \bfR$,超平面 $x=0$ 可以分离 $C$ 和 $D$。
&emsp;&emsp;通过给 $C$ 和 $D$ 增加一些条件,可以得到超平面分离定理的多种逆定理。
> **举例**&emsp;设 $C$ 和 $D$ 是凸集,$C$ 是开集,如果存在一个仿射函数 $f$,它在 $C$ 中非正而在 $D$ 中非负,那么 $C$ 和 $D$ 不相交。(为说明此结论,首先可知 $f$ 在 $C$ 上是负的。否则,如果 $f$ 在 $C$ 中的某一点为零,那么 $f$ 在这个点附近会取得正值,这与前述矛盾。因此 $C$ 和 $D$ 一定是不相交的,因为 $f$ 在 $C$ 中为负,而在 $D$ 中非负。)将逆定理与超平面分离定理相结合,我们可以得到下面的结论:任何两个凸集 $C$ 和 $D$,如果其中至少有一个是开集,那么当且仅当存在分离超平面时,它们不相交。
> **举例**&emsp;**严格线性不等式的择一定理**。我们导出严格线性不等式
>
> $$\begin{equation}\label{StrictLinearInequality}
> Ax \prec b
> \end{equation}$$
>
> 有解的充要条件。该不等式不可行的充要条件是(凸)集
>
> $$
> C = \{ b = Ax\mid x \in \bfR^n\},\qquad D = \bfR^m_{++} = \{ y \in \bfR^m\mid y \succ 0 \}
> $$
>
> 不相交。集合 $D$ 是开集,而 $C$ 是仿射集合。根据前述的结论,$C$ 和 $D$ 不相交的充要条件是,存在分离超平面,即存在非零的 $\lambda \in \bfR^m$ 和 $\mu \in \bfR$ 使得 $C$ 中 $\lambda^\TT y \leqslant \mu$ 而 $D$ 中 $\lambda^\TT y \geqslant \mu$。
>
> 这些条件可以被简化。第一个条件意味着对于所有 $x$ 都有 $\lambda^TT (b - Ax) \leqslant \mu$。这表明 $A^\TT \lambda = 0$,$\lambda^\TT b \leqslant \mu$。第二个不等式意味着 $\lambda^\TT y \geqslant \mu$ 对于所有 $y \succ 0$ 均成立。这表明 $\mu \leqslant 0$ 且 $\lambda \preceq 0$,$\lambda\ne 0$。
>
> 将这些结果放在一起,我们可以得知严格不等式组 $\eqref{StrictLinearInequality}$ 无解的充要条件是存在 $\lambda \in \bfR^m$ 使得
>
> $$\begin{equation}\label{IFFCondition}
> \lambda = 0,\qquad \lambda\succeq 0,\qquad A^\TT \lambda = 0,\qquad \lambda^\TT b \leqslant 0
> \end{equation}$$
>
> 这些不等式和等式关于 $\lambda\in\bfR^m$ 也是线性的。我们称式 $\eqref{StrictLinearInequality}$ 和式 $\eqref{IFFCondition}$ 构成一对**择一选择**(alternatives):对于任意的 $A$ 和 $b$,两者中仅有一组有解。
# 2. 支撑超平面
&emsp;&emsp;设 $C \subseteq \bfR^n$ 而 $x_0$ 是其边界 $\bd C$ 上的一点,即
$$
x_0 \in \bd C = \cl C\ \backslash\ \iint C
$$
如果 $a \ne 0$,并且对任意 $x \in C$ 满足 $a^\TT x \leqslant a^\TT x_0$,那么称超平面 $\{ x\mid a^\TT x = a^\TT x_0 \}$ 为集合 $C$ 在点 $x_0$ 处的**支撑超平面**(*supporting hyperplane*)。这等于说点 $x_0$ 与集合 $C$ 被超平面 $\{ x\mid a^\TT x = a^\TT x_0 \}$ 所分离。其几何解释是超平面 $\{ x\mid a^\TT x = a^\TT x_0 \}$ 与 $C$ 相切于点 $x_0$,而且半空间 $\{ x\mid a^\TT x \leqslant a^\TT x_0 \}$ 包含 $C$,如[图 21](#图21)。
<a id="图21"></a>
![图 21. 超平面 $\{ x\mid a^\TT x = a^\TT x_0 \}$ 在 $x_0$ 处支撑 $C$。](../images/post/2024-06-12-josh-cvx-1-5/2024-06-12-josh-cvx-1-5-210-SupportingHyperplane.png){width=400px}
&emsp;&emsp;一个基本的结论,称为**支撑超平面定理**(*supporting hyperplane theorem*),表明对于任意非空的凸集 $C$ 和任意 $x_0 \in \bd C$,在 $x_0$ 处存在 $C$ 的支撑超平面。支撑超平面定理从超平面分离定理很容易得到证明。需要区分两种情况。如果 $C$ 的内部非空,对于 $\{x_0\}$ 和 $\iint C$ 应用超平面分离定理可以直接得到所需的结论。如果 $C$ 的内部是空集,则 $C$ 必处于小于 $n$ 维的一个仿射集合中,并且任意包含这个仿射集合的超平面一定包含 $C$ 和 $x_0$,这是一个(平凡的)支撑超平面。
&emsp;&emsp;支撑超平面定理也有一个不完全的逆定理:如果一个集合是闭的,具有非空内部,并且其边界上每个点均存在支撑超平面,那么它是凸的。
# 参考文献
1. Stephen P. Boyd and Lieven Vandenberghe, *Convex optimization*. Cambridge, UK: Cambridge University Press, 2004.
2. Stephen P. Boyd and Lieven Vandenberghe, *凸优化*. 北京: 清华大学出版社, 2013.
+199
View File
@@ -0,0 +1,199 @@
---
title: Josh's Note — 凸优化<br>Part 1.6 凸集—对偶锥与广义不等式
mathjax: true
comments: true
copyright: true
toc:
enable: true
number: true
wrap: true
expand_all: true
max_depth: 4
categories:
- - Josh 的学习笔记
- 凸优化
- 凸集
- - 数学
- 凸优化
tags:
- 凸优化
- 凸集
abbrlink: b2aac0f7
date: 2024-06-13 10:57:38
---
# 1. 对偶锥
$
\newcommand{\bfR}{\mathbf{R}}
\newcommand{\bfS}{\mathbf{S}}
\newcommand{\TT}{\mathrm{T}}
\def\tr{\mathop{\bf tr}}
\def\iint{\mathop{\bf int}}
$&emsp;&emsp;令 $K$ 为一个锥。集合
$$\begin{equation}
K^\ast = \{ y\mid x^\TT y \geqslant 0,\ \forall x \in K \}
\end{equation}$$
称为 K 的**对偶锥**(*dual cone*)。顾名思义,$K^\ast$ 是一个锥,并且它总是凸的,即使 $K$ 不是凸锥。
&emsp;&emsp;从几何上看,$y \in K^\ast$ 当且仅当 $-y$ 是 $K$ 在原点的一个支撑超平面的法线,如[图 22](#图22) 所示。
<a id="图22"></a>
![图 22. **左**:以 $y$ 为内法向量的半空间包含锥 $K$,因此,$y \in K^\ast$。**右**:以 $z$ 为内法向量的半空间不包含 $K$,因此,$z \notin K^\ast$。](../images/post/2024-06-13-josh-cvx-1-6/2024-06-13-josh-cvx-1-6-220-DualCone.png){width=600px}
> **举例**&emsp;**子空间**。子空间 $V \subseteq \bfR^n$(这是一个锥)的对偶锥是其正交补 $V^\perp = \{y\mid y^\TT v = 0,\ \forall v \in V\}$。
<!-- more -->
> **举例**&emsp;**非负象限**。锥 $\bfR^n_+$ 的对偶是它本身:
>
> $$
> y^\TT x \geqslant 0,\ \forall x \succeq 0 \Longleftrightarrow y \succeq 0
> $$
>
> 称这种锥**自对偶**(*self-dual*)。
> **举例**&emsp;**半正定锥**。在 $n \times n$ 对称矩阵的集合 $\bfS^n$ 上,其标准内积 $\tr(XY) = \displaystyle\sum_{i,j=1}^{n} X_{ij}Y_{ij}$。半正定锥 $\bfS^n_+$ 是自对偶的,即对于任意的 $X,Y\in\bfS^n$
>
> $$
> \tr (XY) \geqslant 0,\ \forall X \succeq 0 \Longleftrightarrow Y \succeq 0
> $$
>
> 下面说明这一结论。
>
> > **证明**&emsp;假设 $Y \notin \bfS^n_+$,那么存在 $q \in \bfR^n$ 并且
> >
> > $$
> > q^\TT Yq = \tr (qq^\TT Y) < 0
> > $$
> >
> > 于是半正定矩阵 $X = qq^\TT$ 满足 $\tr(XY) < 0$,由此可知 $Y \notin (\bfS^n_+)^\ast$。
> >
> > 假设 $X,Y\in\bfS^n_+$,可以利用特征值分解将 $X$ 表述为 $X = \displaystyle\sum_{i=1}^n \lambda_i q_i q_i^\TT$,其中(特征值)$\lambda_i \geqslant 0,\ i = 1,\cdots,n$。于是有
> >
> > $$
> > \tr (XY) = \tr \left( Y \sum_{i=1}^n \lambda_i q_i q_i^\TT \right) = \sum_{i=1}^n \lambda_i q^\TT Y q_i \geqslant 0
> > $$
> >
> > 以上表明 $Y \in (\bfS^n_+)^\ast$。
> **举例**&emsp;**范数锥的对偶**。令 $\|\cdot\|$ 为定义在 $\bfR^n$ 上的范数。与之相关的锥 $K = \{ (x,t) \in \bfR^{n+1}\mid \|x\|\leqslant t \}$ 的对偶锥由其对偶范数定义,
>
> $$
> K^\ast = \{(u,v) \in \bfR^{n+1}\mid \|u\|_\ast \leqslant v\}
> $$
>
> 这里的对偶范数由 $\|u\|_\ast = \sup\{u^\TT x\mid \| x \|\leqslant 1\}$ 给出。
>
> 为证明这个结论,我们需要说明
>
> $$\begin{equation}\label{DualOfNormCone}
> x^\TT u + tv \geqslant 0\ 只要\ \|x\|\leqslant t \Longleftrightarrow \|u\|_\ast \leqslant v
> \end{equation}$$
>
> > **证明**&emsp;首先,证明由右端关于 $(u,v)$ 的条件可以得出左端的条件。设 $\|u\|_\ast \leqslant v$,并且对于一些 $t>0$ 有 $\|x\| \leqslant t$。(如果 $t = 0$,$x$ 必须是零,因此显然有 $u^\TT x + vt \geqslant 0$。)根据对偶锥的定义以及 $\|-x/t\|\leqslant 1$,我们有
> >
> > $$
> > u^\TT (-x/t) \leqslant \|u\|_\ast \leqslant v
> > $$
> >
> > 因此,$u^\TT x + vt \geqslant 0$。
> >
> > 其次,我们证明 $\eqref{DualOfNormCone}$ 左端的条件可以导出 $\eqref{DualOfNormCone}$ 右端的条件。假设 $\|u\|_\ast> v$,即右端不成立。那么,根据对偶锥的定义,存在 $x$ 满足 $\|x\|\leqslant 1$ 及 $x^\TT u > v$。取 $t=1$,我们有
> >
> > $$
> > u^\TT (-x) + v < 0
> > $$
> >
> > 这与 $\eqref{DualOfNormCone}$ 的左端相矛盾。
&emsp;&emsp;对偶锥满足一些性质,例如
- $K^\ast$ 是闭凸锥。
- $K_1 \subseteq K_2$ 可导出 $K_2^\ast \subseteq K_1^\ast$。
- 如果 $K$ 有非空内部,那么 $K^\ast$ 是尖的。
- 如果 $K$ 的闭包是尖的,那么 $K^\ast$ 有非空内部。
- $K^{\ast\ast}$ 是 $K$ 的凸包的闭包。(因此,如果 $K$ 是凸和闭的,则 $K^{\ast\ast} = K$。)这些性质表明如果 $K$ 是一个正常锥,那么它的对偶 $K^\ast$ 也是,进一步地,有 $K^{\ast\ast} = K$。
# 2. 广义不等式的对偶
&emsp;&emsp;现在假设凸锥 $K$ 是正常锥,因此它可以导出一个广义不等式 $\preceq_K$。其对偶锥 $K^\ast$ 也是正常的,所以也能导出一个广义不等式。我们称广义不等式立 $\preceq_{K^\ast}$ 为广义不等式 $\preceq_K$ 的**对偶**(*dual*)。
&emsp;&emsp;关于广义不等式及其对偶有一些重要的性质
- $x \preceq_K y$ 当且仅当对于任意 $\lambda \succeq_{K^\ast}$,有 $\lambda^\TT x \leqslant \lambda^\TT y$。
- $x \prec_K y$ 当且仅当对于任意 $\lambda \succeq_{K^\ast}$ 和 $\lambda\ne 0$,有 $\lambda^\TT T x < \lambda^\TT y$。
&emsp;&emsp;因为 $K = K^{\ast\ast}$,与 $\preceq_{K^\ast}$ 相关的对偶广义不等式为 $\preceq_{K}$,因此交换广义不等式及其对偶后,这些性质依然成立。作为一个具体的例子,我们可知 $\lambda\preceq_{K^\ast} \mu$ 的充要条件是对于所有 $x \succeq_K 0$ 有 $\lambda^\TT x \leqslant \mu^\TT x$。
> **举例**&emsp;**线性严格广义不等式的择一定理**。设 $K \subseteq \bfR^m$ 为正常锥。考虑严格广义不等式
>
> $$\begin{equation}\label{StrictGeneralInequality}
> Ax \prec_K b
> \end{equation}$$
>
> 其中 $x \in \bfR^n$
>
> 下面推导对于这个不等式的择一定理。假设它是不可行的,即仿射集合 $\{b-Ax\mid x\in\bfR^n\}$ 与开凸集 $\iint K$ 不相交。那么存在一个分离超平面,即非零的 $\lambda\in\bfR^m$ 和 $\mu\in \bfR$ 使得对于任意 $x$ 有灯 $\lambda^\TT(b-Ax) \leqslant \mu$,对于任意 $y \in \iint K$ 有 $\lambda^\TT y \geqslant \mu$。第一个条件表明 $A^\TT \lambda = 0$ 及 $\lambda^\TT b \leqslant \mu$。第二个条件表明对于任意 $y\in K$ 有 $\lambda^\TT y \geqslant \mu$,这种情况仅当 $\lambda \in K^\ast$ 和 $\mu \leqslant 0$ 时才可能发生。
>
> 综上,我们可知当 $\eqref{StrictGeneralInequality}$ 不可行时,存在 $\lambda$ 使得
>
> $$\begin{equation}\label{StrictGeneralInequalityInfeasible}
> \lambda \ne 0,\qquad \lambda \preceq_{K^\ast} 0,\qquad A^\TT \lambda = 0,\qquad \lambda^\TT b \leqslant 0
> \end{equation}$$
>
> 现在我们证明反方向,即如果 $\eqref{StrictGeneralInequalityInfeasible}$ 成立,那么,不等式组 $\eqref{StrictGeneralInequality}$ 不可能可行。假设不等式均成立,因为 $\lambda\ne 0$,$\lambda \succeq_{K^\ast}$ 及 $b - Ax \succ_K 0$,我们有 $\lambda^\TT (b-Ax)>0$。但是根据 $A^\TT \lambda = 0$,我们可以找到 $\lambda^\TT (b-Ax) = \lambda^\TT b \leqslant 0$,而这是一个矛盾。
>
> 因此,不等式组 $\eqref{StrictGeneralInequality}$ 和 $\eqref{StrictGeneralInequalityInfeasible}$ 构成一对择一:对于任意 $A, b$,它们中仅有一个是可行的。(这是严格线性不等式的择一定理的推广;严格线性不等式的择一定理是 $K = \bfR^m_+$ 时的特殊情况。)
# 3. 对偶不等式定义的最小元和极小元
&emsp;&emsp;可以利用对偶广义不等式来刻画集合 $S\subseteq\mathbf{R}^m$(可能非凸)关于正常锥 $K$ 导出的广义不等式的最小元和极小元。
## 3.1 最小元的对偶性质
&emsp;&emsp;首先考虑**最小**(*minimum*)元的性质。$x$ 是 $S$ 上关于广义不等式 $\preceq _K$ 的最小元的充要条件是,对于所有 $\lambda\succ_{K^*}0$,$x$ 是在 $z\in S$ 上极小化 $\lambda^\TT z$ 的唯一最优解。几何上看,这意味着对于任意 $\lambda\succ_{K^*}0$,超平面
$$
\{z\mid \lambda^\TT (z-x)=0\}
$$
是在 $x$ 处对 $S$ 的一个严格支撑超平面。(用严格支撑超平面表明这个超平面与 $S$ 只相交于 $x$。)注意此处并不要求 $S$ 是凸集。这可由[图 23](#图23)来表示。
<a id="图23"></a>
![图 23. 最小元的对偶性质。点 $x$ 是集合 $S$ 中关于 $\mathbf{R}_+^2$ 的极小元。这等价于:对于任意 $\lambda\succ0$,超平面 $\{z\mid\lambda^\TT (z-x)=0\}$ 在 $x$ 处对 $S$ 严格支撑,即在超平面的一边包含了 $S$,并只在 $x$ 处与 $S$ 接触。](../images/post/2024-06-13-josh-cvx-1-6/2024-06-13-josh-cvx-1-6-230-DualCharacterizationOfMinimumElement.png){width=400px}
&emsp;&emsp;为说明这个结论,设 $x$ 是 $S$ 的最小元,即对于任意 $z\in S$ 有 $x\preceq_Kz$,同时,令 $\lambda\succ_{K^*} 0$,而$z\in S$,$z\neq x$。因为 $x$ 是 $S$ 上的最小元,所以有 $z-x\succeq_K0$。根据 $\lambda\succ_{K^*}0$ 及 $z-x\succeq_K0$,$z-x\neq0$,可以得到 $\lambda^\TT (z-x)>0$。因为 $z$ 是 $S$ 上任意一个不等于 $x$ 的元素,所以 $x$ 是在 $z\in S$ 上极小化 $\lambda^\TT z$ 的唯一解。反之,假设对于所有 $\lambda\succ_{K^*}0$,$x$ 是 $z\in S$ 上极小化 $\lambda^\TT z$ 的唯一解,但 $x$ 不是 $S$ 的最小元。那么存在 $z\in S$ 满足 $z\nsucceq_Kx$。因为 $z-x\nsucceq_K0$,存在 $\tilde{\lambda}\succeq_{K^*} 0$ 并且 $\tilde{\lambda}^\TT(z-x)<0$。因此,对于 $\lambda\succ_{K^*} 0$,在 $\tilde{\lambda}$ 的邻域内有 $\lambda^\TT (z-x)<0$。这与 $x$ 是 $S$ 上极小化 $\lambda^\TT z$ 的唯一解相矛盾。
## 3.2 极小元的对偶性质
&emsp;&emsp;现在讨论**极小**(*minimal*)元的类似性质。此时,在必要和充分条件间存在一定的间隙。如果 $\lambda\succ_{K^*} 0$ 并且 $x$ 在 $z\in S$ 上极小化 $\lambda^\TT z$,那么 $x$ 是极小的,如[图 24](#图24)所示。
<a id="图24"></a>
![图 24. 集合 $S\subseteq\mathbf{R}^2$。其关于 $\mathbf{R}_+^2$ 的极小点集合由其边界的(左下)深色部分所示。$S$ 上极小化 $\lambda_1^\TT z$ 的解为 $x_1$,因为 $\lambda_1\succ0$,所以 $x_1$ 是极小的。$S$ 上极小化 $\lambda_2^\TT z$ 的解为 $x_2$,因为 $\lambda_2\succ0$,所以它是 $S$ 的另一个极小点。](../images/post/2024-06-13-josh-cvx-1-6/2024-06-13-josh-cvx-1-6-240-ASetAndItsSetOfMinimalPoints.png){width=400px}
> **证明**&emsp;假设 $\lambda\succ_{K^*} 0$ 并且 $x$ 在 $S$ 上极小化 $\lambda^\TT z$,但 $x$ 不是极小元,即存在 $z\in S$ 满足 $z\neq x$,$z\preceq_Kx$。那么 $\lambda^\TT (x-z)>0$,这与我们的假设,即 $x$ 在 $S$ 上极小化了 $\lambda^\TT z$,相矛盾。
&emsp;&emsp;其逆命题在一般情况下不成立:$S$ 上的极小元 $x$ 可以对于任何 $\lambda$ 都不是 $z\in S$ 上极小化 $\lambda^\TT z$ 的解,如[图 25](#图25)所示。此图表明了凸性在这个逆定理中的重要作用,当凸性成立时,逆定理是成立的。假设集合 $S$ 是凸集,可以说对于任意极小元 $x$,存在非零的 $\lambda\succeq_{K^*} 0$ 使得 $x$ 在 $z\in S$ 上极小化 $\lambda^\TT z$。
<a id="图25"></a>
![图 25. 点 $x$ 是 $S\subseteq\mathbf{R}^2$ 关于 $\mathbf{R}_+^2$ 的极小元。但是,不存在 $\lambda$,使得 $x$ 在 $z\in S$ 上极小化 $\lambda^\TT z$](../images/post/2024-06-13-josh-cvx-1-6/2024-06-13-josh-cvx-1-6-250-MinimalElement.png){width=350px}
> **证明**&emsp;假设 $x$ 是极小的,也就是说 $((x-K)\setminus\{x\})\cap S=\emptyset$。对凸集 $(x-K)\setminus\{x\}$ 和 $S$ 应用超平面分离定理,可以得出:存在 $\lambda\neq0$ 和 $\mu$,使得对于所有 $y\in K$ 有 $\lambda^\TT (x-y)\leqslant\mu$,对于所有 $z\in S$ 有 $\lambda^\TT z\geqslant\mu$。根据第一个不等式,可知 $\lambda\succeq_{K^*} 0$。由于 $x\in S$ 和 $x\in x-K$,所以有 $\lambda^\TT x=\mu$,所以第二个不等式表明 $\mu$ 是 $S$ 上 $\lambda^\TT z$ 的最小值。因此,$x$ 是 $S$ 上极小化 $\lambda^\TT z$ 的一个解,这里 $\lambda\neq0$,$\lambda\succeq_{K^*}0$。
&emsp;&emsp;这个逆定理无法加强为 $\lambda\succ_{K^*} 0$。反例表明,凸集 $S$ 上的极小元 $x$,可以对于任意 $\lambda\succ_{K^*}0$,都不是 $z\in S$ 中极小化 $\lambda ^\TT z$ 的解(参见[图 26,左图](#图26))。同时,并不是对于任意 $\lambda\succeq_{K^*} 0$,在 $z\in S$ 上极小化 $\lambda^\TT z$ 的解都一定是极小的(参见[图 26,左图](#右26))。
<a id="图26"></a>
![图 26. **左**:点 $x_1\in S_1$ 是极小的,但对于任意 $\lambda\succ0$,它都没有在 $S_1$ 上极小化 $\lambda^\TT z$。(但是,对于 $\lambda=(1,0)$,它确实在所有 $z\in S_1$中极小化了$\lambda^\TT z$。)**右**:点 $x_2\in S_2$ 不是极小的,但对于 $\lambda=(0,1)\succeq0$,它确实在所有 $z\in S_2$ 中极小化了$\lambda^\TT z$。](../images/post/2024-06-13-josh-cvx-1-6/2024-06-13-josh-cvx-1-6-260-MinimalAndMinimizer.png){width=700px}
# 参考文献
1. Stephen P. Boyd and Lieven Vandenberghe, *Convex optimization*. Cambridge, UK: Cambridge University Press, 2004.
2. Stephen P. Boyd and Lieven Vandenberghe, *凸优化*. 北京: 清华大学出版社, 2013.
+569
View File
@@ -0,0 +1,569 @@
---
title: Josh's Note — 凸优化<br>Part 2.1 凸函数—基本性质和例子
mathjax: true
comments: true
copyright: true
toc:
enable: true
number: false
wrap: true
expand_all: true
max_depth: 4
categories:
- - Josh 的学习笔记
- 凸优化
- 凸函数
- - 数学
- 凸优化
tags:
- 凸优化
- 凸函数
abbrlink: 320f661c
date: 2024-06-14 20:29:26
---
# 1. 定义
$
\newcommand{\TT}{\mathrm{T}}
\newcommand{\dd}{\mathrm{d}}
\def\dom{\mathop{\bf dom}}
\def\diag{\mathop{\bf diag}}
\def\epi{\mathop{\bf epi}}
\def\hypo{\mathop{\bf hypo}}
\def\prob{\mathop{\bf prob}}
$&emsp;&emsp;函数 $f:\mathbf{R}^n\to\mathbf{R}$ 是**凸**(*Convex*)的,若 $\dom f$ 是凸集,且对于任意 $x,y\in\dom f$ 和任意 $0\leqslant\theta\leqslant1$,有
$$\begin{equation}\label{DefinitionOfConvexFunction}
f(\theta x+(1-\theta)y)\leqslant\theta f(x)+(1-\theta)f(y)
\end{equation}$$
&emsp;&emsp;从几何意义上看,上述不等式意味着点 $(x,f(x))$ 和 $(y,f(y))$ 之间的线段,即从 $x$ 到 $y$ 的**弦**(*chord*),在函数 $f$ 的图像上方(如[图 1](#图1)所示)。称函数 $f$ 是**严格凸**(*strictly convex*)的,若式 $\eqref{DefinitionOfConvexFunction}$ 中的不等式当 $x\neq y$ 以及 $0<\theta<1$ 时严格成立。称函数 $f$ 是**凹**(*concave*)的,若函数 $-f$ 是凸的;称函数 $f$ 是**严格凹**(*strictly concave*)的,若 $-f$ 严格凸。
<a id="图1"></a>
![图 1. 凸函数示意图。图上任意两点之间的弦(即线段)都在函数图像之上。](../images/post/2024-06-14-josh-cvx-2-1/2024-06-14-josh-cvx-2-1-010-ConvexFunction.png){width=400px}
<!-- more -->
&emsp;&emsp;对于仿射函数,式 $\eqref{DefinitionOfConvexFunction}$ 始终可以取等号,因此所有的[仿射函数][](包括线性函数)是既凸且凹的。反之,若某个函数是既凸又凹的,则其是仿射函数。
&emsp;&emsp;函数是凸的,当且仅当其在与其定义域相交的任何直线上都是凸的。换言之,函数 $f$ 是凸的,当且仅当对于任意 $x\in\dom f$ 和任意向量 $v$,函数 $g(t)=f(x+tv)$ 是凸的(其定义域为 $\{t\mid x+tv\in\dom f\}$)。这个性质非常有用,因为它让我们可以通过将函数限制在直线上来判断其是否是凸函数。
{% note info 注解 %}
这里可能是由于翻译问题导致不是很好理解,我们先看原文:
> A function is convex if and only if it is convex when restricted to any line that
intersects its domain. In other words $f$ is convex if and only if for all $x\in\mathbf{dom}\, f$ and all $v$, the function $g(t) = f(x + tv)$ is convex (on its domain, $\{t\mid x+tv\in\mathbf{dom}\, f\}$). This property is very useful, since it allows us to check whether a function is convex by restricting it to a line.
仍然不是很好理解。因此询问 ChatGPT 得到如下解释:
- 限制在直线上:考虑一个函数 $f$ 和其定义域内的任意一点 $x$。再选择一个任意方向向量 $v$。我们沿着这个方向 $v$ 从点 $x$ 出发,得到一条直线。任何点 $x+tv$(其中 $t$ 是一个实数)都在这条直线上。这就叫做将函数限制在直线上。
- 直线上的函数:我们定义一个新的函数 $g(t)=f(x+tv)$。这个新的函数 $g(t)$ 表示原函数 $f$ 在直线 $x+tv$ 上的值。
- 检查凸性:若对于任意 $x$ 和 $v$,新的函数 $g(t)$ 是凸的,则我们就说原函数 $f$ 是凸的。也就是说,若 $f$ 在所有限制的直线上都是凸的,则 $f$ 本身就是凸的。
通过限制在直线上,我们将原来的多变量问题简化为单变量问题。对于单变量函数,判断凸性要比多变量情况简单得多。这使得我们可以用更简单的方法来判断一个函数是否是凸的。
> **举例**&emsp;假设我们有一个二次函数 $f(x)=x_1^2+x_2^2$。我们选一个点 $x=(a,b)$ 和一个方向 $v=(c,d)$,沿着这个方向得到直线 $(a,b)+t(c,d)$,然后我们可以定义一个新函数:
>
> $$
> g(t)=f((a,b)+t(c,d))=f(a+tc,b+td)=(a+tc)^2+(b+td)^2
> $$
>
> 我们需要检查这个新函数 $g(t)$ 是否是凸的。若对所有 $x$ 和 $v$ 新函数 $g(t)$ 都是凸的,则原函数 $f$ 就是凸的。在这个例子中,显然 $g(t)=(a+tc)^2+(b+td)^2$ 是一个关于 $t$ 的二次函数,它是凸的。因此,原函数 $f(x)=x_1^2+x_2^2$ 是凸的。
总的来说,"将函数限制在直线上"意味着通过沿着任意方向取直线来简化判断多变量函数的凸性,从而可以更方便地确定函数的整体凸性。
{% endnote %}
&emsp;&emsp;对凸函数的**分析**(*analysis*)已经相当地透彻,这里不再继续深入。例如有这样一个简单的结论,凸函数在其定义域相对内部是连续的;它只可能在相对边界上不连续。
# 2. 扩展值延伸
&emsp;&emsp;通常可以定义凸函数在定义域外的值为 $\infty$,从而将这个凸函数延伸至全空间 $\mathbf{R}^n$。若 $f$ 是凸函数,我们定义它的**扩展值延伸**(*extended-value extension*)$\tilde{f}:\mathbf{R}^n\to\mathbf{R}\cup\{\infty\}$ 如下
$$
\tilde{f}(x)=\begin{cases}
f(x)&x\in\textbf{dom}f\\\infty&x\not\in\textbf{dom}f
\end{cases}
$$
延伸函数 $\tilde{f}$ 是定义在全空间 $\mathbf{R}^n$ 上的,取值集合为 $\mathbf{R}\cup\{\infty\}$。我们也可以从延伸函数 $\tilde{f}$ 的定义中确定原函数 $f$ 的定义域,即 $\dom f=\{x\mid\tilde{f}(x)<\infty\}$。
&emsp;&emsp;这种延伸可以简化符号描述,此时我们就不需要明确描述定义域或者每次提到 $f(x)$ 时都限定“对于所有的 $x\in\dom f$”。以基本不等式 $\eqref{DefinitionOfConvexFunction}$ 为例,对于延伸函数 $\tilde{f}$,可以描述为:对于**任意**(*any*)$x$ 和 $y$,以及 $0<\theta<1$,有
$$
\tilde{f}(\theta x+(1-\theta)y)\leqslant\theta\tilde{f}(x)+(1-\theta)\tilde{f}(y)
$$
(当 $\theta=0$ 或 $\theta=1$ 时不等式总成立。)当然此时应当利用扩展运算和扩展序来理解这个不等式。
- 若 $x$ 和 $y$ 在 $\dom f$ 内,上述不等式即为不等式 $\eqref{DefinitionOfConvexFunction}$;
- 若 $x$ 或 $y$ 在 $\dom f$ 外,上述不等式的右端为 $\infty$,不等式仍然成立。
> **举例**&emsp;设 $f_1$ 和 $f_2$ 是 $\mathbf{R}^n$ 上的两个凸函数。逐点和函数 $f=f_1+f_2$ 的定义域为 $\dom f=\dom f_1\cap\dom f_2$,对于任意 $x\in\dom f$,有 $f(x)=f_1(x)+f_2(x)$。利用扩展值延伸我们可以简单地描述为,对于任意 $x$,$\tilde{f}(x)=\tilde{f}_1(x)+\tilde{f}_2(x)$。在这个方程里,函数 $f$ 的定义域被自动定义为 $\dom f=\dom f_1\cap\dom f_2$,因为当 $x\not\in\dom f_1$ 或者 $x\not\in\dom f_2$ 时,$\tilde{f}(x)=\infty$。在此例中,我们就可以利用扩展运算来自动定义定义域。
&emsp;&emsp;在不会造成歧义的情况下,可以用同样的符号来表示一个凸函数及其延伸函数。即假设所有的凸函数都隐含地被延伸了,也就是在定义域外都被定义为 $\infty$。
> **举例**&emsp;**凸集的示性函数**。设 $C\subseteq\mathbf{R}^n$ 是一个凸集,考虑(凸)函数 $I_C$,其定义域为 $C$,对于所有的 $x\in C$,有 $I_C(x)=0$。换言之,此函数在集合 $C$ 上一直为零。其扩展值延伸可以描述如下
>
> $$
> \tilde{I}_C(x)=\begin{cases}0&x\in C\\\infty&x\not\in C.\end{cases}
> $$
>
> 凸函数 $\tilde{I}_C$ 被称作集合 $C$ 的**示性函数**(*indicator function*)。
>
> 利用示性函数 $\tilde{I}_C$,可以更加灵活地定义符号描述。例如,对于在集合 $C$ 上极小化函数 $f$ 的问题(假设 $f$ 定义在整个 $\mathbf{R}^n$ 空间),可以给出等价的问题,即在 $\mathbf{R}^n$ 上极小化函数 $f+\tilde{I}_C$。事实上,按照不会造成歧义的约定,函数 $f+\tilde{I}_C$ 等价于定义在集合 $C$ 上的函数 $f$。
&emsp;&emsp;类似地,可以通过定义凹函数在定义域外都为 $-\infty$ 对其进行延伸。
# 3. 一阶条件
&emsp;&emsp;假设 $f$ 可微(即其梯度 $\nabla f$ 在开集 $\dom f$ 内处处存在),则函数 $f$ 是凸函数的充要条件是 $\dom f$ 是凸集且对于任意 $x,y\in\dom f$,下式成立
$$\begin{equation}\label{FirstOrderCondition}
f(y)\geqslant f(x)+\nabla f(x)^\TT (y-x)
\end{equation}$$
[图 2](#图2) 描述了上述不等式,也即沿函数上任意一点作切线,函数始终位于切线上方。
<a id="图2"></a>
![图 2. 若函数 $f$ 是凸的且可微,则对于任意 $x,y\in\dom f$,有 $f(x)+\nabla f(x)^\TT(y-x)\leqslant f( y)$。](../images/post/2024-06-14-josh-cvx-2-1/2024-06-14-josh-cvx-2-1-020-FirstOrderCondition.png){width=500px}
&emsp;&emsp;由 $f(x)+\nabla f(x)^\TT (y-x)$ 得出的仿射函数 $y$ 即为函数 $f$ 在点 $x$ 附近的 Taylor 近似。不等式 $\eqref{FirstOrderCondition}$ 表明,对于一个凸函数,其一阶 Taylor 近似实质上是原函数的一个**全局下估计**(*global underestimator*)。反之,若某个函数的一阶 Taylor 近似总是其全局下估计,则这个函数是凸的。
&emsp;&emsp;不等式 $\eqref{FirstOrderCondition}$ 说明从一个凸函数的**局部信息**(*local information*)(即它在某点的函数值及导数),可以得到一些**全局信息**(*global information*)(如它的全局下估计)。这也许是凸函数的最重要的信息,由此可以解释凸函数以及凸优化问题的一些非常重要的性质。
> **举例**&emsp;由不等式 $\eqref{FirstOrderCondition}$ 可以知道,若 $\nabla f(x)=0$,则对于所有的 $y\in\dom f$,存在 $f(y)\geqslant f(x)$,即 $x$ 是函数 $f$ 的全局极小点。
&emsp;&emsp;严格凸性同样可以由一阶条件刻画:函数 $f$ 严格凸的充要条件是 $\dom f$ 是凸集且对于任意 $x,y\in\dom f$,$x\neq y$,有
$$\begin{equation}\label{StrictFirstOrderCondition}
f(y)>f(x)+\nabla f(x)^\TT (y-x)
\end{equation}$$
&emsp;&emsp;对于凹函数,亦存在与之对应的一阶条件:函数 $f$ 是凹函数的充要条件是 $\dom f$ 是凸集且对于任意 $x,y\in\dom f$,下式成立
$$
f(y)\leqslant f(x)+\nabla f(x)^\TT (y-x)
$$
## 3.1 一阶凸性条件的证明
&emsp;&emsp;为了证明式 $\eqref{FirstOrderCondition}$,先考虑 $n=1$ 的情况:我们证明可微函数 $f:\mathbf{R}\to\mathbf{R}$ 是凸函数的充要条件是对于 $\dom f$ 内的任意 $x$ 和 $y$,有
$$\begin{equation}\label{FirstOrderConditionWhenNEquals1}
f(y)\geqslant f(x)+f'(x)(y-x)
\end{equation}$$
&emsp;&emsp;首先证明必要性。假设 $f$ 是凸函数,且 $x,y\in\dom f$。因为 $\dom f$ 是凸集(某个区间),对于任意 $0<t\leqslant1$,我们有 $x+t(y-x)\in\dom f$,由函数 $f$ 的凸性可得
$$
f(x+t(y-x))\leqslant(1-t)f(x)+tf(y)
$$
将上式两端同除 $t$ 可得
$$
f(y)\geqslant f(x)+\frac{f(x+t(y-x))-f(x)}{t}
$$
令 $t\to 0$,可以得到不等式 $\eqref{FirstOrderConditionWhenNEquals1}$。
&emsp;&emsp;为了证明充分性,假设对 $\dom f$(某个区间)内的任意 $x$ 和 $y$,函数满足不等式 $\eqref{FirstOrderConditionWhenNEquals1}$。选择任意 $x\neq y$,$0\leqslant\theta\leqslant1$,令 $z=\theta x+(1-\theta)y$。两次应用不等式 $\eqref{FirstOrderConditionWhenNEquals1}$ 可得
$$
f(x)\geqslant f(z)+f'(z)(x-z),\quad f(y)\geqslant f(z)+f'(z)(y-z)
$$
将第一个不等式乘以 $\theta$,第二个不等式乘以 $1-\theta$,并将二者相加可得
$$
\theta f(x)+(1-\theta)f(y)\geqslant f(z)
$$
从而说明了函数 $f$ 是凸的。
&emsp;&emsp;现在来证明一般情况,即 $f:\mathbf{R}^n\to\mathbf{R}$。设 $x,y\in\mathbf{R}^n$,考虑过这两点的直线上的函数 $f$,即函数 $g(t)=f(ty+(1-t)x)$,此函数对 $t$ 求导可得 $g'(t)=\nabla f(ty+(1-t)x)^\TT(y-x)$。
&emsp;&emsp;首先假设函数 $f$ 是凸的,则函数 $g$ 是凸的,由前面的讨论可得 $g(1)\geqslant g(0)+g'(0)$,即
$$
f(y)\geqslant f(x)+\nabla f(x)^\TT (y-x)
$$
再假设此不等式对于任意 $x$ 和 $y$ 均成立,因此若 $ty+(1-t)x\in\dom f$ 以及 $\tilde{t}y+(1-\tilde{t})x\in\dom f$,有
$$
f(ty+(1-t)x)\geqslant f(\tilde{t}y+(1-\tilde{t})x)+\nabla f(\tilde{t}y+(1-\tilde{t})x)^\TT (y-x)(t-\tilde{t})
$$
即 $g(t)\geqslant g(\tilde{t})+g'(\tilde{t})(t-\tilde{t})$,说明了函数 $g$ 是凸的。
# 4 二阶条件
&emsp;&emsp;现在假设函数 $f$ 二阶可微,即对于开集 $\dom f$ 内的任意一点,它的 **Hessian 矩阵**或者二阶导数 $\nabla^2f$ 存在,则函数 $f$ 是凸函数的充要条件是,其 Hessian 矩阵是半正定阵:即对于所有的 $x\in\dom f$,有
$$
\nabla^2f(x)\succeq0
$$
对于 $\mathbf{R}$ 上的函数,上式可以简化为一个简单的条件 $f''(x)\geqslant0$($\dom f$ 是凸的,即一个区间),此条件说明函数 $f$ 的导数是非减的。条件 $\nabla^2f(x)\succeq0$ 从几何上可以理解为函数图像在点 $x$ 处具有正(向上)的曲率。
&emsp;&emsp;类似地,函数 $f$ 是凹函数的充要条件是,$\dom f$ 是凸集且对于任意 $x\in$ $\dom f$,$\nabla ^{2}f( x)$ $\preceq$ 0。严格凸的条件可以部分由二阶条件刻画。若对于任意的 $x\in\dom f$ 有 $\nabla^2f(x)\succ0$,则函数 $f$ 严格凸。反过来则不一定成立:例如,函数 $f:\mathbf{R}\to\mathbf{R}$,其表达式为 $f(x)=x^4$,它是严格凸的,但是在 $x=0$ 处,二阶导数为零。
> **举例**&emsp;**二次函数**。考虑二次函数 $f:\mathbf{R}^n\to\mathbf{R}$,其定义域为 $\dom f=\mathbf{R}^n$,其表达式为
>
> $$
> f(x)=(1/2)x^\TT Px+q^\TT x+r
> $$
>
> 其中 $P\in\mathbf{S}^{n}$,$q\in\mathbf{R}^{n}$,$r\in\mathbf{R}$。因为对于任意 $x$,$\nabla^2f(x)=P$,所以函数 $f$ 是凸的,当且仅当 $P\succeq0$($f$ 是凹的当且仅当 $P\preceq0$)。
>
> 对于二次函数,严格凸比较容易表达:函数 $f$ 是严格凸的,当且仅当 $P\succ0$(函数是严格凹的当且仅当 $P\prec0$)。
> **注释**&emsp;在判断函数的凸性和凹性时,不管是一阶条件还是二阶条件,$\dom f$ 必须是凸集这个前提条件必须满足。例如,考虑函数 $f(x)=1/x^2$,其定义域为 $\dom f=\{x\in$ $\mathbf{R}\mid x\neq0\}$,对于所有 $x\in\dom f$ 均满足 $f''(x)>0$,但是函数 $f(x)$ 并不是凸函数。
# 5. 例子
&emsp;&emsp;前文已经提到所有的线性函数和仿射函数均为凸函数(同时也是凹函数),并描述了凸和凹的二次函数。本节绘出更多的凸函数和凹函数的例子。
## $\mathbf{R}$ 上的例子
&emsp;&emsp;首先考虑 $\mathbf{R}$ 上的一些函数,其自变量为 $x$。
- **指数函数**(*Exponential*)。对任意 $a\in\mathbf{R}$,函数 $e^{ax}$ 在 $\mathbf{R}$ 上是凸的。
- **幂函数**(*Power*)。当 $a\geqslant1$ 或 $a\leqslant0$ 时,$x^a$ 在 $\mathbf{R}_{++}$ 上是凸函数;当 $0\leqslant a\leqslant1$ 时,$x^a$ 在 $\mathbf{R}_{++}$ 上是凹函数。
- **绝对值幂函数**(*Power of absolute value*)。当 $p\geqslant1$ 时,函数 $|x|^p$ 在 $\mathbf{R}$ 上是凸函数。
- **对数函数**(*Logarithm*)。函数 $\log x$ 在 $\mathbf{R}_{++}$ 上是凹函数。
- **负熵**(*Negative entropy*)。函数 $x\log x$ 在其定义域上是凸函数。(定义域为 $\mathbf{R}_{++}$ 或者 $\mathbf{R}_+$,当 $x=0$ 时定义函数值为 0。)
&emsp;&emsp;我们可以通过基本不等式 $\eqref{DefinitionOfConvexFunction}$ 或者二阶导数半正定或半负定来判断上述函数是凸的或是凹的。以函数 $f(x)=x\log x$ 为例,其导数和二阶导数为
$$
f'(x)=\log x+1,\quad f''(x)=1/x
$$
即对于 $x>0$,有 $f''(x)>0$。所以负熵函数是(严格)凸的。
## $\mathbf{R}^n$ 上的例子
&emsp;&emsp;下面给出 $\mathbf{R}^n$ 上的一些例子。
**范数**(*Norm*)。 $\mathbf{R}^n$ 上的任意范数均为凸函数。
**最大值函数**(*Max function*)。函数 $f(x)=\max\{x_1,\cdots,x_n\}$ 在 $\mathbf{R}^n$ 上是凸的。
**二次-线性分式函数**(*Quadratic-over-linear function*)。函数 $f(x,y)=x^2/y$,其定义域为
$$
\dom f= \mathbf{R} \times \mathbf{R} _{+ + }= \{ ( x, y) \in \mathbf{R} ^{2}\mid y> 0\}
$$
是凸函数(如[图 3](#图3)所示)。
<a id="图3"></a>
![图 3. 函数 $f(x, y) = x^2/y$ 的图像。](../images/post/2024-06-14-josh-cvx-2-1/2024-06-14-josh-cvx-2-1-030-QuadraticOverLinearFunction.png){width=400px}
**指数和的对数**(*Log-sum-exp*)。函数 $f(x)=\log\left(e^{x_1}+\cdots+e^{x_n}\right)$ 在 $\mathbf{R}^n$上是凸函数。这个函数可以看成最大值函数的可微(实际上是解析)近似,因为对任意 $x$,下面的不等式成立
$$
\max\{x_{1},\cdots,x_{n}\}\leqslant f(x)\leqslant\max\{x_{1},\cdots,x_{n}\}+\log n
$$
(第二个不等式当 $x$ 的所有分量都相等时是紧的。)[图 4](#图4) 描述了当 $n=2$ 时 $f$ 的图像。
<a id="图4"></a>
![图 4. 函数 $f(x, y) = log(e^x + e^y)$ 的图像。](../images/post/2024-06-14-josh-cvx-2-1/2024-06-14-josh-cvx-2-1-040-LogSumExo.png){width=400px}
**几何平均**(*Geometric mean*)。几何平均函数$f(x)=\left(\displaystyle\prod_{i=1}^n x_i\right)^{1/n}$在定义域 $\dom f=\mathbf{R}_{++}^n$ 上是凹函数。
**对数-行列式**(*Log-determinant*)。函数 $f(X)=\log\det X$ 在定义域 $\dom f=\mathbf{S}_{++}^n$ 上是凹函数。
&emsp;&emsp;判断上述函数的凸性(或者凹性)可以有多种途径,可以直接验证不等式 $\eqref{DefinitionOfConvexFunction}$ 是否成立,亦可以验证其 Hessian 矩阵是否半正定,或者可以将函数转换到与其定义域相交的任意直线上,通过得到的单变量函数判断原函数的凸性。
**范数**。若函数 $f:\mathbf{R}^n\to\mathbf{R}$ 是范数,任取 $0\leqslant\theta\leqslant1$,有
$$
f(\theta x+(1-\theta)y)\leqslant f(\theta x)+f((1-\theta)y)=\theta f(x)+(1-\theta)f(y)
$$
上述不等式可以由三角不等式得到,当范数满足齐次性时,上述不等式取等号。
**最大值函数**。对任意 $0\leqslant\theta\leqslant1$,函数 $f(x)=\displaystyle\max_i x_i$ 满足
$$\begin{aligned}
f(\theta x+(1-\theta)y)&=\max_{i}(\theta x_{i}+(1-\theta)y_{i})
\\
&\leqslant\theta\max_{i}x_{i}+(1-\theta)\max_{i}y_{i}
\\
&=\theta f(x)+(1-\theta)f(y)
\end{aligned}$$
**二次线性分式函数**。为了说明二次-线性分式函数 $f( x, y) = x^2/ y$ 是凸的,我们注意到,对于 $y>0$,有
$$
\nabla^2f(x,y)=\dfrac{2}{y^3}\left[\begin{array}{cc}
y^2&-xy\\-xy&x^2
\end{array}\right]=\dfrac{2}{y^3}\left[\begin{array}{c}
y\\-x
\end{array}\right]\left[\begin{array}{c}
y\\-x
\end{array}\right]^\TT \succeq0
$$
**指数和的对数**。指数和的对数函数的 Hessian 矩阵为
$$
\nabla^{2}f(x)=\frac{1}{(\mathbf{1}^\TT z)^{2}}\left((\mathbf{1}^\TT z)\diag(z)-zz^\TT\right)
$$
其中 $z=(e^{x_1},\cdots,e^{x_n})$。为了说明 $\nabla^2f(x)\succeq0$,我们证明对任意 $v$,有 $v^\TT \nabla^2f(x)v\geqslant0$,即
$$
v^\TT \nabla^{2}f(x)v=\frac{1}{(\mathbf{1}^\TT z)^{2}}\left(\left(\sum_{i=1}^{n}z_{i}\right)\left(\sum_{i=1}^{n}v_{i}^{2}z_{i}\right)-\left(\sum_{i=1}^{n}v_{i}z_{i}\right)^{2}\right)\geqslant0
$$
上述不等式可以应用 Cauchy-Schwarz 不等式 $(a^\TT a)(b^\TT b)\geqslant(a^\TT b)^2$ 得到,此时向量 $a$ 和 $b$ 的分量为 $a_i= v_i\sqrt {z_i}$,$b_i= \sqrt {z_i}$。
**几何平均**。类似地,我们说明,几何平均函数 $f(x)=\left(\displaystyle\prod_{i=1}^nx_i\right)^{1/n}$ 在定义域 $\dom f=\mathbf{R}_{++}^{n}$上是凹的。其 Hessian 矩阵 $\nabla^2f(x)$ 可以通过下面两个式子给出
$$
\frac{\partial^{2}f(x)}{\partial x_{k}^{2}}=-(n-1)\frac{\left(\displaystyle\prod_{i=1}^{n}x_{i}\right)^{1/n}}{n^{2}x_{k}^{2}},\quad\frac{\partial^{2}f(x)}{\partial x_{k}\partial x_{l}}=\frac{\left(\displaystyle\prod_{i=1}^{n}x_{i}\right)^{1/n}}{n^{2}x_{k}x_{l}}\quad\forall\:k\neq l
$$
因此 $\nabla^2f(x)$ 具有如下表达式
$$\nabla^{2}f(x)=-\frac{\displaystyle\prod_{i=1}^{n}x_{i}^{1/n}}{n^{2}}\left(n \diag(1/x_{1}^{2},\cdots,1/x_{n}^{2})-qq^\TT\right)
$$
其中,$q_i=1/x_i$。我们需要证明 $\nabla^2f(x)\preceq0$,即对于任意向量 $v$,有
$$
v^\TT \nabla^2f(x)v=-\frac{\displaystyle\prod_{i=1}^nx_i^{1/n}}{n^2}\left(n\sum_{i=1}^nv_i^2/x_i^2-\left(\sum_{i=1}^nv_i/x_i\right)^2\right)\leqslant0
$$
这同样可以应用 Cauchy-Schwarz 不等式 $(a^\TT a)(b^\TT b)\geqslant(a^\TT b)^2$ 得到,只需令向量 $a=\mathbf{1}$,向量 $b$ 的分量 $b_i=v_i/x_i$。
**对数-行列式**。对于函数 $f(X)=\log\det X$,我们可以将其转化为任意直线上的单变量函数来验证它是凹的。令 $X=Z+tV$,其中 $Z,V\in\mathbf{S}^n$,定义 $g(t)=f(Z+tV)$,自变量 $t$ 满足 $Z+tV\succ0$。不失一般性,假设 $t=0$ 满足条件,即 $Z\succ0$。我们有
$$\begin{aligned}
g(t)&=\log\det(Z+tV)
\\
&=\log\det(Z^{1/2}(I+tZ^{-1/2}VZ^{-1/2})Z^{1/2})
\\
&=\sum_{i=1}^{n}\log(1+t\lambda_{i})+\log\det Z
\end{aligned}$$
其中 $\lambda_1,\cdots,\lambda_n$ 是矩阵 $Z^{-1/2}VZ^{-1/2}$ 的特征值。因此下式成立
$$
g'(t)=\sum_{i=1}^{n}\frac{\lambda_{i}}{1+t\lambda_{i}},\qquad g''(t)=-\sum_{i=1}^{n}\frac{\lambda_{i}^{2}}{(1+t\lambda_{i})^{2}}
$$
因为 $g''(t)\leqslant0$,函数 $f$ 是凹的。
# 6. 下水平集
&emsp;&emsp;函数 $f: \mathbf{R} ^{n}\to \mathbf{R}$ 的 **$\alpha$-下水平集**(*$\alpha$-sublevel set*)定义为
$$
C_{\alpha}=\{x\in\dom f\mid f(x)\leqslant\alpha\}
$$
对于任意 $\alpha$ 值,凸函数的下水平集仍然是凸集。证明可以由凸集的定义直接得到:若 $x,y\in C_{\alpha }$,则有 $f( x) \leqslant \alpha$,$f( y) \leqslant \alpha$,因此对于任意$0\leqslant\theta\leqslant1$,$f(\theta x+(1-\theta)y)\leqslant\alpha$,即 $\theta x+(1-\theta)y\in C_{\alpha}$。
&emsp;&emsp;反过来不一定正确:某个函数的所有下水平集都是凸集,但这个函数可能不是凸函数。例如,函数 $f(x)=-e^x$ 在 $\mathbf{R}$ 上不是凸函数(实质上,它是严格凹函数),但是其所有下水平集均为凸集。
&emsp;&emsp;若 $f$ 是凹函数,则由 $\{x\in\dom f\mid f(x)\geqslant\alpha\}$ 定义的 **$\alpha$-上水平集**(*$\alpha$-superlevel set*)也是凸集。下水平集的性质可以用来判断集合的凸性,若某个集合可以描述为一个凸函数的下水平集,或者一个凹函数的上水平集,则其是凸集。
> **举例**&emsp;对于 $x\in\mathbf{R}_+^n$,其几何平均和算术平均分别为
>
> $$
> G(x)=\left(\prod_{i=1}^{n}x_{i}\right)^{1/n},\qquad A(x)=\frac{1}{n}\sum_{i=1}^{n}x_{i}
> $$
>
> (在 $G$ 中,定义 $0^{1/n}=0$)。算术几何平均不等式为 $G(x)\leqslant A(x)$。
>
> 设 $0\leqslant\alpha\leqslant1$,考虑集合
>
> $$
> \{x\in\mathbf{R}_{+}^{n}\mid G(x)\geqslant\alpha A(x)\}
> $$
>
> 即使得几何平均至少大于等于算术平均的 $\alpha$ 倍的集合。此集合是凸集,因为它是凹函数 $G(x)=\alpha A(x)$ 的 $0$-上水平集。事实上,这个每合是正齐次的,因此它是凸锥
# 7. 上境图
&emsp;&emsp;函数 $f:\mathbf{R}^{n}\to\mathbf{R}$ 的图像定义为
$$
\{(x,f(x))\mid x\in\dom f\}
$$
它是 $\mathbf{R}^{n+1}$ 空间的子集。函数 $f:\mathbf{R}^n\to\mathbf{R}$ 的**上境图**(*epigraph*)定义为
$$
\epi f=\{(x,t)\mid x\in\dom f,f(x)\leqslant t\}
$$
它也是 $\mathbf{R}^{n+1}$ 空间的子集。(“Epi”是之上的意思,所以上境图的英文 epigraph 是“在函数图像之上”的意思。)[图 5](#图5)说明了上境图的定义。
<a id="图5"></a>
![图 5. 函数 $f$ 的上境图,见阴影部分。深颜色的下边界是函数 $f$ 的图像。](../images/post/2024-06-14-josh-cvx-2-1/2024-06-14-josh-cvx-2-1-050-EpigraphOfF.png){width=400px}
&emsp;&emsp;凸集和凸函数的联系可以通过上境图来建立:一个函数是凸函数,当且仅当其上境图是凸集。一个函数是凹函数,当且仅当其**亚图**(*hypograph*)
$$
\hypo f=\{(x,t)\mid t\leqslant f(x)\},
$$
是凸集。
> **举例**&emsp;**矩阵分式函数**。矩阵分式函数 $f:\mathbf{R}^n\times\mathbf{S}^n\to\mathbf{R}$
>
> $$
> f(x,Y)=x^\TT Y^{-1}x
> $$
>
> 在定义域 $\dom f=\mathbf{R}^n\times\mathbf{S}_{++}^n$ 上是凸的。(这实质上是定义域为 $\dom f=\mathbf{R}\times\mathbf{R}_{++}$ 的二次-线性分式函数 $f(x,y)=x^2/y$ 的一个扩展。)
>
> 一个简单的方式来验证矩阵分式函数 $f$ 的凸性是通过其上境图
>
> $$\begin{aligned}
> \epi f &= \left\{(x,Y,t)\mid Y\succ0,\ x^\TT Y^{-1}x\leqslant t\right\}
> \\
> &=\left\{(x,Y,t)\:\middle|\left[\begin{array}{cc}
> Y&x
> \\
> x^\TT&t
> \end{array}\right]\succeq0,\:Y\succ0\right\}
> \end{aligned}$$
>
> 并应用 Schur 补条件判断分块矩阵的半正定性。最后一个条件是关于 $(x,Y,t)$ 的线性矩阵不等式,因此 $\epi f$ 是凸集。
>
> 对于 $n=1$ 的特殊情况,矩阵分式函数简化为二次-线性分式函数 $x^2/y$,相应的线性矩阵不等式表示为
> $$
> \left[\begin{array}{cc}y&x\\x&t\end{array}\right]\succeq0,\quad y>0
> $$
>
> (函数图像如[图 3](#图3) 所示)。
&emsp;&emsp;关于凸函数的很多结果可以从几何的角度利用上境图并结合凸集的一些结论来证明(或理解),例如,考虑凸函数的一阶条件
$$
f(y)\geqslant f(x)+\nabla f(x)^\TT (y-x)
$$
其中函数 $f$ 是凸的,$x,y\in\dom f$。我们可以利用 $\epi f$ 从几何角度理解上述基本不等式。若 $(y,t)\in\epi f$,有
$$
t\geqslant f(y)\geqslant f(x)+\nabla f(x)^\TT (y-x)
$$
上式可以描述为
$$
(y,t)\in\epi f\implies\left[\begin{array}{c}\nabla f(x)\\-1\end{array}\right]^\TT \left(\left[\begin{array}{c}y\\t\end{array}\right]-\left[\begin{array}{c}x\\f(x)\end{array}\right]\right)\leqslant0
$$
这意味着法向量为 $(\nabla f(x),-1)$ 的超平面在边界点 $(x,f(x))$ 支撑着 $\epi f$,如[图 6](#图6) 所示。
<a id="图6"></a>
![图 6. 对于可微凸函数 $f$,向量 $(\nabla f(x),-1)$ 定义了函数 $f$ 在点 $x$ 处的上境图的一个支撑超平面。](../images/post/2024-06-14-josh-cvx-2-1/2024-06-14-josh-cvx-2-1-060-EpigraphAndSupportingHyperplane.png){width=400px}
# 8. Jensen 不等式及其扩展
&emsp;&emsp;基本不等式
$$
f(\theta x+(1-\theta)y)\leqslant\theta f(x)+(1-\theta)f(y)
$$
有时也称作 **Jensen 不等式**(*Jensen’s inequality*)。此不等式可以很方便地扩展至更多点的凸组合:若函数 $f$ 是凸函数,$x_1,\cdots,x_k\in\dom f$,$\theta_1,\cdots,\theta_k\geqslant0$ 且 $\theta_1+\cdots+\theta_k=1$,则下式成立
$$
f(\theta_1x_1+\cdots+\theta_kx_k)\leqslant\theta_1f(x_1)+\cdots+\theta_kf(x_k)
$$
考虑凸集时,此不等式可以扩展至无穷项和、积分以及期望。例如,若在 $S\subseteq\dom f$ 上 $p(x)\geqslant0$ 且 $\displaystyle\int_Sp(x) \dd x = 1$,则当相应的积分存在时,下式成立
$$
f\left(\int_Sp(x)x\dd x\right)\leqslant\int_Sf(x)p(x)\dd x
$$
扩展到更一般的情况,我们可以采用其支撑属于 $\dom f$ 的任意概率测度。若 $x$ 是随机变量,事件 $x\in\dom f$ 发生的概率为 1,函数 $f$ 是凸函数,当相应的期望存在时,我们有
$$\begin{equation}\label{GeneralJensenInequality}
f(\mathbb{E}x)\leqslant\mathbb{E}f(x)
\end{equation}$$
设随机变量 $x$ 的可能取值为 $\{ x_1, x_2\}$ 相应地取值概率为 $\prob ( x= x_1) = \theta$,$\prob( x=x_2)=1-\theta$,则由一般形式 $\eqref{GeneralJensenInequality}$ 可以得到基本不等式 $\eqref{DefinitionOfConvexFunction}$。所以不等式 $\eqref{GeneralJensenInequality}$ 可以刻画凸性:若函数 $f$ 不是凸函数,则存在随机变量 $x$,$x\in\dom f$ 以概率 $1$ 发生,使得 $f(\mathbb{E}x)>\mathbb{E}f(x)$。
&emsp;&emsp;上述所有不等式均被称为 **Jensen 不等式**(*Jensen’s inequality*),而实际上最初由 Jensen 提出的不等式相当简单
$$
f\left(\frac{x+y}2\right)\leqslant\frac{f(x)+f(y)}2
$$
> **注释**&emsp;我们可以这样理解式 $\eqref{GeneralJensenInequality}$。假设 $x\in\dom f\subseteq\mathbf{R}^n$,$z$ 是 $\mathbf{R}^n$ 中的随机变量,其均值为零,则有
>
> $$
> \mathbb{E}f(x+z)\geqslant f(x)
> $$
>
> 因此,随机化或者扰动(即在自变量上增加一个零均值的随机变量)从平均效果上不会减小凸函数的值。
# 9. 不等式
&emsp;&emsp;很多著名的不等式都可以通过将 Jensen 不等式应用于合适的凸函数得到。(事实上,凸性和 Jensen 不等式可以构成不等式理论的基础。)
> **举例**&emsp;考虑算术-几何平均不等式
>
> $$\begin{equation}\label{ArithmeticGeometricMeanInequality}
> \sqrt{a b} \leqslant( a+b ) / 2
> \end{equation}$$
>
> 其中 $a, b \geqslant0$。我们可以利用凸性和 Jensen 不等式得到此不等式。函数 $-\log x$ 是凸函数:利用 Jensen 不等式,令 $\theta=1 / 2$ ,可得
>
> $$
> -\log \left( \frac{a+b} {2} \right) \leqslant\frac{-\log a-\log b} {2}
> $$
>
> 等式两边取指数即可得到式 $\eqref{ArithmeticGeometricMeanInequality}$。
> **举例**&emsp;证明 Hölder 不等式:对 $p > 1$,$1 / p+1 / q=1$,以及 $x,y \in\mathbf{R}^{n}$ 有
>
> $$
> \sum_{i=1}^{n} x_{i} y_{i} \leqslant\left( \sum_{i=1}^{n} | x_{i} |^{p} \right)^{1 / p} \left( \sum_{i=1}^{n} | y_{i} |^{q} \right)^{1 / q}
> $$
>
> 由 $-\log x$ 的凸性以及 Jensen 不等式,可以得到更为一般的算术-几何平均不等式
>
> $$
> a^{\theta} b^{1-\theta} \leqslant\theta a+( 1-\theta) b,
> $$
>
> 其中 $a,b \geqslant0$,$0 \leqslant\theta\leqslant1$。令
>
> $$
> a=\frac{| x_{i} |^{p}} {\displaystyle\sum_{j=1}^{n} | x_{j} |^{p}}, \qquad b=\frac{| y_{i} |^{q}} {\displaystyle\sum_{j=1}^{n} | y_{j} |^{q}}, \qquad\theta=1 / p,
> $$
>
> 可以得到如下不等式
>
> $$
> \left( \frac{| x_{i} |^{p}} {\displaystyle\sum_{j=1}^{n} | x_{j} |^{p}} \right)^{1 / p} \left( \frac{| y_{i} |^{q}} {\displaystyle\sum_{j=1}^{n} | y_{j} |^{q}} \right)^{1 / q} \leqslant\frac{| x_{i} |^{p}} {p \displaystyle\sum_{j=1}^{n} | x_{j} |^{p}}+\frac{| y_{i} |^{q}} {q \displaystyle\sum_{j=1}^{n} | y_{j} |^{q}}.
> $$
>
> 对 $i$ 进行求和可以得到 Hölder 不等式。
# 参考文献
1. Stephen P. Boyd and Lieven Vandenberghe, *Convex optimization*. Cambridge, UK: Cambridge University Press, 2004.
2. Stephen P. Boyd and Lieven Vandenberghe, *凸优化*. 北京: 清华大学出版社, 2013.
[仿射函数]: https://josh-gao.top/posts/a4a69a4f.html?#%E4%BB%BF%E5%B0%84%E5%87%BD%E6%95%B0
@@ -0,0 +1,479 @@
---
title: Zynq MPSoC / RFSoC 动态配置 DIMM DDR
mathjax: true
comments: true
copyright: true
toc:
enable: true
number: true
wrap: true
expand_all: true
max_depth: 4
tags:
- 调试记录
- DDR
- MPSoC
- RFSoC
- SPD
- Zynq
categories:
- 调试记录
abbrlink: 11cd1dc
date: 2024-06-27 20:06:13
---
对于 DIMM 拓扑的 DDR,通常可以使用 I2C 对搭载在 DIMM 上的 SPD EEPROM 进行读取后获得配置参数,然后对 DDR 控制器进行配置。
AMD Xilinx UG1085 的 [Dynamic DDR Configuration](https://docs.amd.com/r/en-US/ug1085-zynq-ultrascale-trm/Dynamic-DDR-Configuration) 一节指出,当 DDR 控制器处于复位状态时,可以在运行时通过 FSBL 获取 DDR 参数并对 DDR 控制器进行初始化。
本文基于 Zynq RFSoC,对 PS 端的 SO-DIMM DDR 进行动态配置。
<!-- more -->
# 名词释义
- [BSP](https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18842276/Standalone+Board+Support+Package+BSP):Board Support Package,板级支持包
- [EEPROM](https://en.wikipedia.org/wiki/EEPROM):Electrically-Erasable Programmable Read-Only Memory,电子擦除式可复写只读存储器
- [FSBL](https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18842019/Zynq+UltraScale+FSBL#ZynqUltraScale+FSBL-WhatisFSBL?):First Stage Bootloader,第一阶段引导加载程序
- [DDR DRAM](https://en.wikipedia.org/wiki/DDR_SDRAM):Double Data Rate Synchronous Dynamic Random-Access Memory,双倍数据率同步动态随机存取存储器
- [DIMM](https://en.wikipedia.org/wiki/DIMM):Dual In-line Memory Modules,双列直插式存储模块
- PCW:Processing System Configuration Wizard,处理系统配置向导
- [SO-DIMM](https://en.wikipedia.org/wiki/DIMM#SO-DIMM):Small Outline Dual In-line Memory Modules,小外形双列直插式内存模块
- [SPD](https://en.wikipedia.org/wiki/Serial_presence_detect):Serial Presence Detect,串行存在检测
# 硬软件版本
| 硬软件 | 型号/版本 |
| :--: | :-------: |
| FPGA | Zynq RFSoC XCZU48DR-2-FSVG1517-I |
| DDR4 | Micron MTA4ATF51264HZ-2G6E1 |
| I2C Mux | TI TCA9548APWR |
| Vivado | 2024.1 |
| Vitis Classic | 2024.1 |
# Zynq MPSoC / RFSoC 动态 DDR 配置简介
Zynq MPSoC / RFSoC 动态 DDR 配置具有如下特性:
- 无需在 Vivado 中进行改动即可更换 DIMM,并使用动态 DDR 配置初始化 DDR;
- 支持 DDR3 和 DDR4 DIMM;
- 单一的 PetaLinux BSP 即可支持任何可安装的 DIMM 器件。
{% note warning %}
动态 DDR 配置功能仅可用于 PS DIMM DDR,不支持颗粒 DDR。
{% endnote %}
# 具体操作方法
## PCW GUI 配置
在使用动态 DDR 配置之前,需要在如[图 1](#图1) 的 Vivado 的 PCW GUI 中启用 DDR 控制器,且将“DDR Controller Options”部分设置为:
- Memory Type:DDR4 或 DDR3
- Components:UDIMM 或 RDIMM
- ECC:Enabled 或 Disabled
- Effective DRAM Bus Width:64 Bit
<a id="图1"></a>
![图 1. Zynq UltraScale+ MPSoC 配置 GUI](../images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-010-ZynqGui.png)
动态 DDR 配置将自动读取 SPD 表,并设置“DDR Memory Option”部分的所有参数,如下表。
| Option | Value Example | Option | Value Example |
| -------------- | --------- | -------------- | --------- |
| Speed Bin (Use Tooltip) | DDR42133P | DRAM IC Bus Width (per die) | 8 Bits |
| Cas Latency | 15 | DRAM Device Capacity(per die) | 4096 MBits |
| RAS to CAS Delay (Cycles) | 15 | Bank Group Address Count (Bits) | 2 |
| Pre-charge Time (Cycles) | 15 | Bank Address Count (Bits) | 2 |
| Cas Write Latency (Cycles) | 14 | Row Address Count (Bits) | 15 |
| tRC (ns) | 46.5 | Column Address Count | 10 |
| tRASmin (ns) | 33 | Dual Rank | |
| tFAW (ns) | 21 | DDR Size (in hexa) | 0XFFFFFFFF (4GB) |
| Additive Latency (Cycles) | 0 | | |
而“Other Options”部分的所有值都需要用户根据需要设置,无法从 SPD 表中获得,如下表。
| Option | Value Example | Option | Value Example |
| -------------- | --------- | -------------- | --------- |
| Memory Address Map | ROW BANK COL | Power Mode Settings | Power Down Enable |
| Data Mask and DBI | DM NO DBI | Clock Stop |
| Address Mirroring | | **Refresh Mode Settings** |
| 2nd Clock | | Lower-Power Auto Self-Refresh | Manual Normal |
| Parity | | Temp Controlled Refresh | |
| 2Tck Command Timing (2T) | | Max. Operating Temperature | Normal (0-85) |
| | | Fine Granularity Refresh Mode | 1x |
| | | Self-Refresh Abort | |
## 启用动态 DDR 配置功能
要启用动态 DDR 配置功能,需要在 Vivado 中使用 TCL 命令将参数 `CONFIG.PSU_DYNAMIC_DDR_CONFIG_EN` 置为 1:
``` tcl
set_property CONFIG.PSU_DYNAMIC_DDR_CONFIG_EN 1 [get_bd_cells /zynq_ultra_ps_e]
```
这里的 `zynq_ultra_ps_e` 需要替换为实际 Block Design 中 Zynq UltraScale+ MPSoC IP 核的名称,如[图 2](#图2)。
<a id="图2"></a>
![图 2. Block Design 整体](../images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-020-BlockDesign.png)
然后重新生成 Output Products 即可(若除 PS 处理器外还有其他逻辑,则需要重新生成比特流)。FSBL 将会在启动过程中使用该参数,并执行动态 DDR 配置。
{% note info %}
如果设置了上述参数却出现了如下警告,是因为 GUI 中 DDR 类型必须为 UDIMM 或 RDIMM,不能为 Component。
``` plain
WARNING: [BD 41-721] Attempt to set value '1' on disabled parameter 'PSU_DYNAMIC_DDR_CONFIG_EN' of cell '/zynq_ultra_ps_e_0' is ignored
```
{% endnote %}
## I2C 硬件要求
由于动态 DDR 配置需要在 FSBL 中使用 I2C 读取 DDR SPD EEPROM 中的数据,而在 Xilinx 自动生成 FSBL 中,I2C 读取 DDR SPD EEPROM 的方式是固定的,因此**若不想对生成的 FSBL 进行修改,则需要在硬件上适配 FSBL**。
Xilinx FSBL 使用 I2C1(1 号 I2C 控制器),借助一个 I2C Mux 与 SPD EEPROM 进行通信,使用的地址为:
- I2C Mux 地址: 0x75
- I2C Slave 地址: 0b1010001 (0x51)
- SODIMM SA[2:0]: 0b001
{% note info %}
从 Vivado 2019.1 开始,动态 DDR 配置对于所有使用 DIMM DDR 的 Zynq MPSoC / RFSoC 评估板均启用,在使用预置硬件配置时无需额外用户操作。
{% endnote %}
## 根据硬件修改 FSBL
若 I2C 硬件连接不满足上述要求,还可以按照实际连接关系修改 FSBL。FSBL 中使用 I2C 读取 DDR SPD EEPROM 的函数为 `u32 XFsbl_IicReadSpdEeprom(u8 *SpdData)`。
``` c xfsbl_ddr_init.c
u32 XFsbl_DdrInit(void)
{
// ...
/* Get the Model Part Number from the SPD stored in EEPROM */
Status = XFsbl_IicReadSpdEeprom(SpdData);
if (Status != XFSBL_SUCCESS) {
Status = XFSBL_FAILURE;
goto END;
}
// ...
}
```
下面对函数进行拆解,结合注释可以更好理解操作的过程。
### 初始化 I2C 控制器
首先对 I2C 控制器 I2C1 进行初始化。值得一提的是,从 Vivado / Vitis 2023.2 版本开始,对设备进行寻址时,不再依赖于设备的 Device ID,而是直接使用基地址 Base Address,少了从 Device ID 到 Base Address 这一步操作,从开发的角度来看更为合理了。
{% note info %}
若设计使用了 I2C 控制器 I2C0,则可以改为使用基地址 `XPAR_I2C0_BASEADDR` 或 Device ID `XPAR_PSU_I2C_0_DEVICE_ID` 来寻找设备。
{% endnote %}
``` c xfsbl_ddr_init.c
static u32 XFsbl_IicReadSpdEeprom(u8 *SpdData)
{
// ...
/* Lookup for I2C-1U device */
#ifdef SDT
ConfigIic = XIicPs_LookupConfig(XPAR_I2C1_BASEADDR);
#else
ConfigIic = XIicPs_LookupConfig(XPAR_PSU_I2C_1_DEVICE_ID);
#endif
if (!ConfigIic) {
UStatus = XFSBL_FAILURE;
goto END;
}
/* Initialize the I2C device */
Status = XIicPs_CfgInitialize(&IicInstance, ConfigIic,
ConfigIic->BaseAddress);
if (Status != XST_SUCCESS) {
UStatus = XFSBL_FAILURE;
goto END;
}
/* Set the Serial Clock for I2C */
Status = XIicPs_SetSClk(&IicInstance, XFSBL_IIC_SCLK_RATE);
if (Status != XST_SUCCESS) {
UStatus = XFSBL_FAILURE;
goto END;
}
// ...
}
```
### 选择 I2C Mux 的 Slave
由于开发板搭载了较多 I2C 外设,而 Zynq MPSoC / RFSoC 的 I2C 控制器数量有限,因此需要通过 I2C Mux 来扩展所连 I2C Slave 的数量。
本板卡 I2C1 原理图如[图 3](#图3),所用 I2C Mux 的型号为 TCA9548A,其地址配置方式如[图 4](#图4),Slave 选择方式如[图 5](#图5),这里均和评估板保持一致,因此可以与自动生成的 FSBL 兼容。
结合[图 3](#图3) 和[图 4](#图4) 可知 I2C Mux 的地址为 `0x75`,从[图 3](#图3) 中可知 PS DDR4 SODIMM 的 I2C 连接在了第 3 号 Slave 的位置,因此按照[图 5](#图5) 需要将 B3 置 1,也即需要向地址为 `0x75` 的 I2C Mux TCA9548A 的控制寄存器中写入 `0x08`。
<a id="图3"></a>
![图 3. I2C Mux 原理图](../images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-030-I2C1Schematic.png)
<a id="图4"></a>
![图 4. TCA9548A 地址配置](../images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-040-tca9548aAddress.png){width=600px}
<a id="图5"></a>
![图 5. TCA9548A Slave选择](../images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-050-tca9548aConfig.png){width=1000px}
按照上述分析,下面的代码就不难理解了,首先向地址为 `XFSBL_MUX_ADDR`(默认为 `0x75`)的 I2C Mux 写入选通配置 `0x08`,然后从同样的地址回读,验证配置是否正确。
{% note info %}
- 若设计中没有使用到 I2C Mux,而是直接将 I2C 控制器连接到了 DIMM,则可以删去这部分代码;
- 若设计中 I2C Mux 地址不同,则可以修改 `XFSBL_MUX_ADDR` 的宏定义;
- 若设计中 I2C Mux 连接的 Slave 不同,可以修改 I2C 发送的 `TxArray`。
{% endnote %}
``` c xfsbl_ddr_init.c
static u32 XFsbl_IicReadSpdEeprom(u8 *SpdData)
{
// ...
/*
* Configure I2C Mux to select DDR4 SODIMM Slave
* 0x08U - Enable DDR4 SODIMM module
*/
TxArray = 0x08U;
XIicPs_MasterSendPolled(&IicInstance, &TxArray, 1U, XFSBL_MUX_ADDR);
/*
* Wait until bus is idle to start another transfer.
*/
Status = Xil_WaitForEvent(IicInstance.Config.BaseAddress +
XIICPS_SR_OFFSET, XIICPS_SR_BA_MASK, 0U, XFSBL_IIC_BUS_TIMEOUT);
if (Status != XST_SUCCESS) {
UStatus = XFSBL_FAILURE;
goto END;
}
/*
* Get Configuration to confirm the selection of the slave
* device.
*/
Status = XIicPs_MasterRecvPolled(&IicInstance, SpdData, 1U,
XFSBL_MUX_ADDR);
if (Status != XST_SUCCESS) {
UStatus = XFSBL_FAILURE;
goto END;
}
/*
* Wait until bus is idle to start another transfer.
*/
Status = Xil_WaitForEvent(IicInstance.Config.BaseAddress +
XIICPS_SR_OFFSET, XIICPS_SR_BA_MASK, 0U, XFSBL_IIC_BUS_TIMEOUT);
if (Status != XST_SUCCESS) {
UStatus = XFSBL_FAILURE;
goto END;
}
// ...
}
```
### 读取 EEPROM 的第一页
配置完 I2C Mux 后,即可开始读取 SPD EEPROM 中的内容了。[图 6](#图6) 给出了 EEPROM 支持的指令表,由于 EEPROM 一次读的最大长度为一页,也即一个 Page,因此需要分两次对其中的两个 Page 进行读取。
<a id="图6"></a>
![图 6. DDR4 SPD EEPROM 指令表](../images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-060-DDR4SPDAddress.png){width=800px}
首先设置 Page Address 为 0,也即向地址 `0x36` 中写入 `0x00`,表示从 Page 0 中进行读取,一次读取 256 Byte。
{% note info %}
通常 SPD EEPROM 的 Page 选择地址是固定的,如果 Page Address 0 的地址有变更,修改 `XFSBL_SODIMM_CONTROL_ADDR_LOW` 的宏定义即可。
{% endnote %}
``` c xfsbl_ddr_init.c
static u32 XFsbl_IicReadSpdEeprom(u8 *SpdData)
{
// ...
/*
* Set SODIMM control address to enable access to lower
* EEPROM page (0U to 255U Bytes).
* 0x00U - Enable Read of Lower Page from EEPROM
*/
TxArray = 0x00U;
XIicPs_MasterSendPolled(&IicInstance, &TxArray, 1U,
XFSBL_SODIMM_CONTROL_ADDR_LOW);
/*
* Wait until bus is idle to start another transfer.
*/
Status = Xil_WaitForEvent(IicInstance.Config.BaseAddress +
XIICPS_SR_OFFSET, XIICPS_SR_BA_MASK, 0U, XFSBL_IIC_BUS_TIMEOUT);
if (Status != XST_SUCCESS) {
UStatus = XFSBL_FAILURE;
goto END;
}
/*
* Configure SODIMM Slave address to select starting address of the
* read bytes.
* 0x00U - Set starting byte address of read Lowe Page from EEPROM
* This will result in to starting address of 0x149U (0x100U + 0x49U) in
* the EEPROM.
*/
TxArray = 0x00U;
XIicPs_MasterSendPolled(&IicInstance, &TxArray, 1U,
XFSBL_SODIMM_SLAVE_ADDR);
/*
* Wait until bus is idle to start another transfer.
*/
Status = Xil_WaitForEvent(IicInstance.Config.BaseAddress +
XIICPS_SR_OFFSET, XIICPS_SR_BA_MASK, 0U, XFSBL_IIC_BUS_TIMEOUT);
if (Status != XST_SUCCESS) {
UStatus = XFSBL_FAILURE;
goto END;
}
/*
* Receive the Data of 256U Bytes from SPD EEPROM via I2C.
*/
Status = XIicPs_MasterRecvPolled(&IicInstance, SpdData, 256U,
XFSBL_SODIMM_SLAVE_ADDR);
if (Status != XST_SUCCESS) {
UStatus = XFSBL_FAILURE;
goto END;
}
/*
* Wait until bus is idle.
*/
Status = Xil_WaitForEvent(IicInstance.Config.BaseAddress +
XIICPS_SR_OFFSET, XIICPS_SR_BA_MASK, 0U, XFSBL_IIC_BUS_TIMEOUT);
if (Status != XST_SUCCESS) {
UStatus = XFSBL_FAILURE;
goto END;
}
// ...
}
```
### 读取 EEPROM 的第二页
然后设置 Page Address 为 1,也即向地址 `0x37` 中写入 `0x00`,表示从 Page 0 中进行读取,一次读取 256 Byte。
{% note info %}
通常 SPD EEPROM 的 Page 选择地址是固定的,如果 Page Address 1 的地址有变更,修改 `XFSBL_SODIMM_CONTROL_ADDR_HIGH` 的宏定义即可。
{% endnote %}
``` c xfsbl_ddr_init.c
static u32 XFsbl_IicReadSpdEeprom(u8 *SpdData)
{
// ...
/*
* Set SODIMM control address to enable access to upper
* EEPROM page (256U to 511U Bytes).
* 0x01U - Enable Read of Upper Page from EEPROM
*/
TxArray = 0x01U;
XIicPs_MasterSendPolled(&IicInstance, &TxArray, 1U,
XFSBL_SODIMM_CONTROL_ADDR_HIGH);
/*
* Wait until bus is idle to start another transfer.
*/
Status = Xil_WaitForEvent(IicInstance.Config.BaseAddress +
XIICPS_SR_OFFSET, XIICPS_SR_BA_MASK, 0U, XFSBL_IIC_BUS_TIMEOUT);
if (Status != XST_SUCCESS) {
UStatus = XFSBL_FAILURE;
goto END;
}
/*
* Configure SODIMM Slave address to select starting address of the
* read bytes.
* 0x00U - Set starting byte address of read Upper Page from EEPROM
* This will result in to starting address of 0x149U (0x100U + 0x49U) in
* the EEPROM.
*/
TxArray = 0x00U;
XIicPs_MasterSendPolled(&IicInstance, &TxArray, 1U,
XFSBL_SODIMM_SLAVE_ADDR);
/*
* Wait until bus is idle to start another transfer.
*/
Status = Xil_WaitForEvent(IicInstance.Config.BaseAddress +
XIICPS_SR_OFFSET, XIICPS_SR_BA_MASK, 0U, XFSBL_IIC_BUS_TIMEOUT);
if (Status != XST_SUCCESS) {
UStatus = XFSBL_FAILURE;
goto END;
}
/*
* Receive the Data of 256U Bytes from SPD EEPROM via I2C.
*/
Status = XIicPs_MasterRecvPolled(&IicInstance, &SpdData[256U], 256U,
XFSBL_SODIMM_SLAVE_ADDR);
if (Status != XST_SUCCESS) {
UStatus = XFSBL_FAILURE;
goto END;
}
/*
* Wait until bus is idle.
*/
Status = Xil_WaitForEvent(IicInstance.Config.BaseAddress +
XIICPS_SR_OFFSET, XIICPS_SR_BA_MASK, 0U, XFSBL_IIC_BUS_TIMEOUT);
if (Status != XST_SUCCESS) {
UStatus = XFSBL_FAILURE;
goto END;
}
// ...
}
```
# 调试
配置完成后可以实测了,这里对 FSBL 进行 Debug,观察整个读写的过程。在单独调试 FSBL 的时候,可以不勾选“Program FPGA”和“Initialize using FSBL”,如[图 7](#图7)。
<a id="图7"></a>
![图 7. Debug 配置](../images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-070-DebugConfig.png)
将断点设置在函数 `XFsbl_IicReadSpdEeprom()` 被调用的地方。
<a id="图8"></a>
![图 8. `XFsbl_IicReadSpdEeprom()` 函数断点](../images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-080-Breakpoint.png)
观察 I2C Mux 回读的数据。回读的数据存储在 `SpdData` 数组中,可以观察到数组的第 0 个字节为 `0x08`,与写入的数据一致。
<a id="图9"></a>
![图 9. I2C Mux 回读](../images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-090-IICMuxRead.png)
然后观察 I2C EEPROM 回读的数据,并与 Micron 给出的 [MTA4ATF51264HZ-2G6E1 的 SPD 数据][]进行对比,可以观察到数据是一致的。
<a id="图10"></a>
![图 10. I2C EEPROM 回读](../images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-100-IICEEPROMRead.png)
最后,`XFsbl_DdrInit()` 函数的剩余部分会完成 DDR 参数的解析与 DDR 控制器的初始化。
# 参考文档
[75768 - Zynq MPSoC Dynamic DDR Configuration Support for DIMM Devices](https://support.xilinx.com/s/article/75768)
[SPD I2c Address for DDR4 SODIMM](https://electronics.stackexchange.com/questions/554703/spd-i2c-address-for-ddr4-sodimm)
[MTA4ATF51264HZ-2G6E1 的 SPD 数据]: https://www.micron.com/products/memory/dram-modules/sodimm/part-catalog/part-detail/spd-data/mta4atf51264hz-2g6e1
+653
View File
@@ -0,0 +1,653 @@
---
title: Josh's Note — 凸优化<br>Part 2.2 凸函数—保凸运算
mathjax: true
comments: true
copyright: true
toc:
enable: true
number: false
wrap: true
expand_all: true
max_depth: 4
categories:
- - Josh 的学习笔记
- 凸优化
- 凸函数
- - 数学
- 凸优化
tags:
- 凸优化
- 凸函数
- 保凸运算
abbrlink: c3476904
date: 2024-07-03 23:04:33
---
$
\newcommand{\dd}{\mathrm{d}}
\newcommand{\TT}{\mathrm{T}}
\def\diag{\mathop{\bf diag}}
\def\dist{\mathop{\bf dist}}
\def\dom{\mathop{\bf dom}}
\def\epi{\mathop{\bf epi}}
$&emsp;&emsp;本文讨论几种保持函数凸性或者凹性的运算,这样可以构造新的凸函数或者凹函数。首先从一些简单的运算开始,如求和、伸缩以及逐点上确界,之后再介绍一些更为复杂的运算(其中一些运算的特例即为简单运算)。
# 1. 非负加权求和
&emsp;&emsp;显然,若函数 $f$ 是凸函数且 $\alpha\geqslant0$,则函数 $\alpha f$ 也是凸函数。若函数 $f_1$ 和 $f_2$ 都是凸函数,则它们的和 $f_1+f_2$ 也是凸函数。将非负伸缩以及求和运算结合起来,可以看出,凸函数的集合本身是一个凸锥:凸函数的非负加权求和仍然是凸函数,即函数
$$
f=w_1f_1+\cdots+w_mf_m
$$
是凸函数。类似地,凹函数的非负加权求和仍然是凹函数。严格凸(凹)函数的非负,非零加权求和是严格凸(凹)函数。
&emsp;&emsp;这个性质可以扩展至无限项的求和以及积分的情形。例如,若对于每一个 $y\in\mathcal{A}$,函数 $f(x,y)$ 关于 $x$ 都是凸函数,且 $w(y)\geqslant 0$,则函数
$$
g(x)=\int_{\mathcal{A}}w(y)f(x,y)\dd y
$$
关于 $x$是凸函数(若此积分存在)。
<!-- more -->
&emsp;&emsp;容易验证非负伸缩以及求和运算是保凸运算,或者可以根据相关的上境图得到此结论。例如,若 $w\geqslant 0$ 且 $f$ 是凸函数,则有
$$
\epi (wf)=\left[\begin{array}{cc}
I&0\\
0&w
\end{array}\right]\epi f
$$
因为凸集通过线性变换得到的像仍然是凸集,所以 $\epi(wf)$ 是凸集。
{% note info 注解 %}
这里对上镜图的相关结论进行解释。函数 $f:\mathbf{R}^{n}\to\mathbf{R}$ 的上镜图定义为
$$
\epi f=\{(x,t)\mid f(x)\leqslant t\}
$$
则有
$$\begin{aligned}
\left[\begin{array}{cc}
I&0\\
0&w
\end{array}\right]\epi f&=\left\{\left[\begin{array}{cc}
I&0\\
0&w
\end{array}\right](x,t)\:\middle|\: f(x)\leqslant t\right\}
\\
&= \{(x,wt)\mid f(x)\leqslant t\}
\\
&= \{(x,t)\mid wf(x)\leqslant t\}
\\
&= \epi (wf)
\end{aligned}
$$
{% endnote %}
# 2. 复合仿射映射
&emsp;&emsp;假设函数 $f:\mathbf{R}^n\to\mathbf{R}$,$A\in\mathbf{R}^{n\times m}$,$b\in\mathbf{R}^n$,定义**复合仿射映射**(*composition with an affine mapping*)$ g:\mathbf{R}^m\to\mathbf{R}$ 为
$$
g(x)=f(Ax+b)
$$
其中 $\dom g=\{x\mid Ax+b\in\dom f\}$。若函数 $f$ 是凸函数,则函数 $g$ 是凸函数;若函数 $f$ 是凹函数,则函数 $g$ 是凹函数。
# 3. 逐点最大和逐点上确界
## 3.1 逐点最大
&emsp;&emsp;若函数 $f_{1}$ 和 $f_{2}$ 均为凸函数,则二者的**逐点最大**(*pointwise maximum*)函数
$$
f(x)=\max\{f_1(x),f_2(x)\}
$$
其定义域为 $\dom f=\dom f_1\cap\dom f_2$,仍然是凸函数。这个性质很容易验证:任取 $0\leqslant \theta \leqslant 1$ 以及 $x,y\in\dom f$,有
$$\begin{aligned}
f(\theta x+(1-\theta)y)&=\max\{f_1(\theta x+(1-\theta)y),f_2(\theta x+(1-\theta)y)\}
\\
&\leqslant\max\{\theta f_1(x)+(1-\theta)f_1(y),\theta f_2(x)+(1-\theta)f_2(y)\}
\\
&\leqslant\theta\max\{f_1(x),f_2(x)\}+(1-\theta)\max\{f_1(y),f_2(y)\}
\\
&=\theta f(x)+(1-\theta)f(y)
\end{aligned}$$
从而得到了函数 $f$ 的凸性。同样很容易证明,若函数 $f_1,\cdots,f_m$ 为凸函数,则它们的逐点最大函数
$$
f(x)=\max\{f_1(x),\cdots,f_m(x)\}
$$
仍然是凸函数。
> **举例**&emsp;**分段线性函数**(*Piecewise-linear functions*)。函数
>
> $$
> f(x)=\max\left\{a_1^\TT x+b_1,\cdots,a_L^\TT x+b_L\right\}
> $$
>
> 定义了一个(具有不大于 $L$ 个子区域的)分段线性函数(实际上是仿射函数)。因为它是一系列仿射函数的逐点最大函数,所以它是凸函数。反之亦成立:任意具有不大于 $L$ 个子区域的分段线性凸函数都可以表述成上述形式。
>
> {% note info 注解 %}
> 参考 Wikipedia,[分段线性函数词条](https://en.wikipedia.org/wiki/Piecewise_linear_function)即为我们通常理解的分段函数,但是这里的分段线性函数有所不同,定义为多个分段函数的逐点最大,因此数凸的。
>
> 关于子区域数量,可以这样理解:若 $L$ 个仿射函数相邻两段各不相同,则每一段仿射函数均对应着一个子区域,因此最多共有 $L$ 个子区域。
> {% endnote %}
> **举例**&emsp;**最大 $r$ 个分量之和**。对于任意 $x\in\mathbf{R}^n$,用 $x_{[i]}$ 表示 $x$ 中第 $i$ 大的分量,将 $x$ 的分量按照非升序进行排列
>
> $$
> x_{[1]}\geqslant x_{[2]}\geqslant\cdots\geqslant x_{[n]}
> $$
>
> 则对 $x$ 的最大 $r$ 个分量进行求和所得到的函数
>
> $$
> f(x)=\sum_{i=1}^rx_{[i]}
> $$
>
> 是凸函数。事实上,此函数可以表述为
>
> $$
> f(x)=\sum_{i=1}^rx_{[i]}=\max\{x_{i_1}+\cdots+x_{i_r}\mid1\leqslant i_1<i_2<\cdots<i_r\leqslant n\}
> $$
>
> 即从 $x$ 的分量中选取 $r$ 个不同分量进行求和的所有可能组合的最大值。因为函数 $f$ 是 $\displaystyle\frac{n!}{r!(n-r)!}$ 个线性函数的逐点最大,所以是凸函数。
>
> 进一步可以证明,当 $w_1\geqslant w_2\geqslant\cdots\geqslant w_r\geqslant 0$ 时,函数 $\displaystyle\sum_{i=1}^rw_ix_{[i]}$ 是凸函数。
## 3.2 逐点上确界
&emsp;&emsp;逐点最大的性质可以扩展至无限个凸函数的**逐点上确界**(*pointwise supremum*)。
{% note info 上确界和下确界 %}
&emsp;&emsp;假定 $C\subseteq\mathbf{R}$。若对每个 $x\in C$ 均有 $x\leqslant a$,则称 $a$ 是 $C$ 的**上界**(*upper bound*)。$C$ 的上界组成的集合或是空集(此时称 $C$ 无上界),或等于 $\mathbf{R}$(仅当 $C=\emptyset$ 时),或是闭的无限区间 $[b,\infty)$。称 $b$ 为 $C$ 的**最小上界**(*least upper bound*)或**上确界**(*supremum*),用 $\sup C$ 表示。规定 $\sup\emptyset=-\infty$,当 $C$ 无上界时取 $\sup C=\infty$。当 $\sup C\in C$ 时,称 $C$ 的上确界是可达的。
&emsp;&emsp;当 $C$ 是有限集时,$\sup C$ 是它所有元素的最大值。一些作者用符号 $\max C$ 表示可达的上确界,但我们采用标准的数学习惯,只在 $C$ 是有限集时用 $\max C$。
&emsp;&emsp;类似地,可以定义下界和下确界。若对每个 $x\in C$ 均有 $a\leqslant x$,则称 $a$ 是 $C\subseteq\mathbf{R}$ 的下界。$C\subseteq\mathbf{R}$ 的**下确界**(*infimum*)或**最大下界**(*greatest lower bound*)定义为 $\inf C=-\sup(-C)$。当 $C$ 是有限集时,下确界是它所有元素的最小值。规定 $\inf\emptyset=\infty$,并在 $C$ 无下界时,取 $\inf C=-\infty$。
{% endnote %}
&emsp;&emsp;若对于任意 $y\in\mathcal{A}$,函数 $f(x,y)$ 关于 $x$ 都是凸的,则函数
$$\begin{equation}\label{PointwiseMaximum}
g(x)=\sup_{y\in\mathcal{A}}f(x,y)
\end{equation}$$
关于 $x$ 亦是凸的。此时,函数 $g$ 的定义域为
$$
\dom g=\{x\mid(x,y)\in\dom f\:\forall y\in\mathcal{A},\sup_{y\in\mathcal{A}}f(x,y)<\infty\}
$$
类似地,一系列凹函数的逐点下确界仍然是凹函数。
&emsp;&emsp;从上境图的角度理解,一系列函数的逐点上确界函数对应着这些函数上境图的交集:对于函数 $f$,$g$ 以及式 $\eqref{PointwiseMaximum}$ 定义的 $\mathcal{A}$,有
$$
\epi g=\bigcap_{y\in\mathcal{A}}\epi f(\:\cdot\:,y)
$$
因此,函数 $g$ 的凸性可由一系列凸集的交集仍然是凸集得到。
> **举例**&emsp;**集合的支撑函数**。令集合 $C\subseteq\mathbf{R}^n$,且 $C\neq\emptyset$,定义集合 $C$ 的**支撑函数**(*support function*)$S_C$ 为
>
> $$
> S_C(x)=\sup\{x^\TT y\mid y\in C\}
> $$
>
> (自然地,函数 $S_C$ 的定义域为 $\dom S_{C}=\left\{x\mid\sup_{y\in C}x^\TT y<\infty\right\}$)。
>
> 对于任意 $y\in C$,$x^\TT y$ 是 $x$ 的线性函数,所以 $S_{C}$ 是一系列线性函数的逐点上确界函数,因此是凸函数。
> **举例**&emsp;**到集合中最远点的距离**。令集合 $C\subseteq\mathbf{R}^n$,定义点 $x$ 与集合中最远点的距离(范数)为
>
> $$
> f(x)=\sup_{y\in C}\|x-y\|
> $$
>
> 此函数是凸函数。为了说明这一点,我们注意到,对于任意 $y$,函数 $\|x-y\|$ 关于 $x$ 是凸函数。因为函数 $f$ 是一族凸函数(对应不同的 $y\in C$)的逐点上确界,所以是凸函数。
> **举例**&emsp;**以权为变量的最小二乘代价函数**。令 $a_1,\cdots,a_n\in\mathbf{R}^m$,在加权最小二乘问题中我们对所有的 $x\in\mathbf{R}^m$ 极小化目标函数 $\displaystyle\sum_{i=1}^nw_i(a_i^\TT x-b_i)^2$。我们称 $w_i$ 为**权**(*weight*),并允许 $w_i$ 为负(则目标函数有可能无下界)。
>
> 定义(最优)**加权最小二乘代价**(*weighted least-squares cost*)函数为
>
> $$
> g(w)=\inf_{x}\sum_{i=1}^{n}w_{i}(a_{i}^{\TT}x-b_{i})^{2}
> $$
>
> 其定义域为
>
> $$\dom g=\left\{w\,\middle|\,\inf_{x}\sum_{i=1}^{n}w_{i}(a_{i}^{\TT}x-b_{i})^{2}>-\infty\right\}$$
>
> 因为函数 $g$ 是一族关于 $w$ 的线性函数的下确界(对应于不同的 $x\in\mathbf{R}^m$),它是 $w$ 的凹函数。
>
> 至少在部分定义域上,我们可以得到函数 $g$ 的一个显式表达式。令 $W=\diag(w)$ 是一对角阵,其对角线元素为 $w_1,\cdots,w_n$,令 $A\in\mathbf{R}^{n\times m}$,其行向量为 $a_i^\TT$,有
>
> $$
> g(w)=\inf_{x}(Ax-b)^{\TT}W(Ax-b)=\inf_{x}(x^{\TT}A^{\TT}WAx-2b^{\TT}WAx+b^{\TT}Wb)
> $$
>
> 从上式可以看出,若 $A^{\TT}WA\not\succeq0$,括号里的二次函数关于 $x$ 无下界,故 $g(w)=-\infty$,即 $w\not\in\dom g$。当 $A^\TT WA\succ0$ 时(即定义了一个严格的线性矩阵不等式),通过解析求解二次函数的极小值,可以得到函数 $g$ 的一个简单的表达式
>
> $$\begin{aligned}
> g(w)&=b^{\TT}Wb-b^{\TT}WA(A^{\TT}WA)^{-1}A^{\TT}Wb
> \\
> &=\sum_{i=1}^{n}w_{i}b_{i}^{2}-\sum_{i=1}^{n}w_{i}^{2}b_{i}^{2}a_{i}^{\TT}\left(\sum_{j=1}^{n}w_{j}a_{j}a_{j}^{\TT}\right)^{-1}a_{i}
> \end{aligned}$$
>
> 从上述表达式并不能立即得到函数 $g$ 的凹性(不过可以从矩阵分式函数的凸性来推导函数 $g$ 的凹性)。
> **举例**&emsp;**对称矩阵的最大特征值**。 定义函数 $f(X)=\lambda_{\max}(X)$,其定义域为 $\dom f=\mathbf{S}^m$,它是凸函数。为了说明这一点,我们将 $f$ 表述为
>
> $$
> f(X)=\sup\{y^\TT Xy\mid\|y\|_2=1\}
> $$
>
> 即针对不同的 $y\in\mathbf{R}^m$ 关于 $X$ 的一族线性函数(即$y^\TT Xy$)的逐点上确界。
> **举例**&emsp;**矩阵范数**。考虑函数 $f(X)=\|X\|_2$,其定义域为 $\dom f=\mathbf{R}^{p\times q}$,其中 $\|\cdot\|_2$ 表示谱范数或者最大奇异值。函数 $f$ 可以表述为
>
> $$
> f(X)=\sup\{u^{\TT}Xv\mid\|u\|_{2}=1,\|v\|_{2}=1\}
> $$
>
> 由于它是 $X$ 的一族线性函数的逐点上确界,所以是凸函数。
>
> 作为一个推广,假设 $\|\cdot\|_a$和$\|\cdot\|_b$ 分别是 $\mathbf{R}^p$ 和 $\mathbf{R}^q$ 上的范数,定义矩阵 $X\in\mathbf{R}^{p\times q}$ 的诱导范数为
>
> $$
> \|X\|_{a,b}=\sup_{v\neq0}\frac{\|Xv\|_{a}}{\|v\|_{b}}
> $$
## 3.3 表示成一族仿射函数的逐点上确界
&emsp;&emsp;上述例子描述了一个建立函数凸性的好方法:将函数表示为一族仿射函数的逐点上确界。除了一个技术条件,反过来也是成立的:几乎所有的凸函数都可以表示成一族仿射函数的逐点上确界。例如,若函数 $f:\mathbf{R}^n\to\mathbf{R}$ 是凸函数,其定义域为 $\dom f=\mathbf{R}^n$,我们有
$$
f(x)=\sup\{g(x)\mid g\:\text{仿射},\:g(z)\leqslant f(z)\:\forall z\}
$$
换言之,函数 $f$ 是它所有的仿射全局下估计的逐点上确界。下面我们将证明这个结论。
&emsp;&emsp;设函数 $f$ 是凸函数,定义域为 $\dom f=\mathbf{R}^{n}$ ,显然下面的不等式成立
$$
f ( x ) \geqslant \sup \{g ( x ) \mid g\:\text{仿射}, \ g ( z ) \leqslant f ( z ) \ \forall z \},
$$
因为函数 $g$ 是函数 $f$ 的任意仿射下估计,我们有 $g ( x ) \leqslant f ( x )$。为了建立等式,我们说明,对于任意 $x \in\mathbf{R}^{n}$,存在仿射函数 $g$ 是函数 $f$ 的全局下估计,并且满足 $g ( x )=f ( x )$。
&emsp;&emsp;毫无疑问,函数 $f$ 的上境图是凸集,因此我们在点 $( x, f ( x ) )$ 处可以找到此凸集的支撑超平面,即存在 $a \in\mathbf{R}^{n}$,$\; b \in\mathbf{R}$ 且 $( a, b ) \neq0$,使得对任意 $( z, t ) \in\epi f$,有
$$
\left[ \begin{array} {c} a \\ b \\ \end{array} \right]^{\TT} \left[ \begin{array} {c} {x-z} \\ {f ( x )-t} \\ \end{array} \right] \leqslant0.
$$
即对任意 $z\in\dom f=\mathbf{R}^n$ 以及所有 $s\geqslant0$($(z,t)\in\epi f$ 等价于存在 $s\geqslant0$ 使得 $t=f(z)+s$),下式成立
$$\begin{equation}\label{ProofOfAffineFunctionRepresentation}
a^\TT(x-z)+b(f(x)-f(z)-s)\leqslant0
\end{equation}
$$
为了保证不等式 $\eqref{ProofOfAffineFunctionRepresentation}$ 对所有的 $s\geqslant0$ 均成立,必须有 $b\geqslant0$。若 $b=0$,对所有的$z\in\mathbf{R}^n$,不等式 $\eqref{ProofOfAffineFunctionRepresentation}$ 可以简化为 $a^\TT(x-z)\leqslant0$,这意味着 $a=0$,于是和假设 $(a,b)\neq0$ 矛盾。因此 $b>0$,即支撑超平面不是竖直的。
&emsp;&emsp;我们知道 $b>0$,因此,对任意 $z$,令 $s=0$,式 $\eqref{ProofOfAffineFunctionRepresentation}$ 可以重新表述为
$$
g(z)=f(x)+(a/b)^{\TT}(x-z)\leqslant f(z)
$$
由此说明函数 $g$ 是函数 $f$ 的一个仿射下估计,并且满足 $g(x)=f(x)$。
# 4. 复合
&emsp;&emsp;本节给定函数 $h:\mathbf{R}^k\to\mathbf{R}$ 以及 $g:\mathbf{R}^n\to\mathbf{R}^k$,定义复合函数 $f=h\circ g:\mathbf{R}^n\to\mathbf{R}$ 为
$$
f(x)=h(g(x)),\quad\dom f=\{x\in\dom g\mid g(x)\in\dom h\}
$$
我们考虑当函数 $f$ 保凸或者保凹时,函数 $h$ 和 $g$ 必须满足的条件。
## 4.1 标量复合
&emsp;&emsp;首先考虑 $k=1$ 的情况,即 $h:\mathbf{R}\to\mathbf{R}$,$g:\mathbf{R}^n\to\mathbf{R}$。仅考虑 $n=1$ 的情况(事实上,将函数限定在与其定义域相交的任意直线上得到的函数决定了原函数的凸性)。
&emsp;&emsp;为了找出复合规律,首先假设函数 $h$ 和 $g$ 是二次可微的,且 $\dom g= \dom h= \mathbf{R}$。在上述假设下,函数 $f$ 是凸的等价于 $f^{\prime\prime}\geqslant 0$(即对所有的 $x\in\mathbf{R}$,$f^{\prime\prime}(x)\geqslant 0$)。
&emsp;&emsp;复合函数 $f=h\circ g$ 的二阶导数为
$$\begin{equation}\label{SecondDerivativeOfScalarCompositionFunction}
f''(x)=h''(g(x))g'(x)^2+h'(g(x))g''(x)
\end{equation}$$
假设函数 $g$ 是凸函数($g^{\prime\prime}\geqslant 0$),函数 $h$ 是凸函数且非减(即$h^{\prime\prime}\geqslant0$ 且 $h^{\prime}\geqslant0$),从式 $\eqref{SecondDerivativeOfScalarCompositionFunction}$ 可以得出 $f^{\prime\prime}\geqslant 0$,即函数 $f$ 是凸函数。类似地,由式 $\eqref{SecondDerivativeOfScalarCompositionFunction}$ 可以得出如下结论
$$\begin{equation}\label{Conclusion1}\begin{aligned}
若\,h\,是凸函数且非减,g\,是凸函数,则\,f\,是凸函数,\\
若\,h\,是凸函数且非增,g\,是凹函数,则\,f\,是凸函数,\\
若\,h\,是凹函数且非减,g\,是凹函数,则\,f\,是凹函数,\\
若\,h\,是凹函数且非增,g\,是凸函数,则\,f\,是凹函数。
\end{aligned}\end{equation}$$
上述结论在函数 $g$ 和 $h$ 二次可微且定义域均为 $\mathbf{R}$ 时成立。事实上,对于更一般的情况,如 $n>1$,不再假设函数 $h$ 和 $g$ 可微或者 $\dom g=\mathbf{R}^n$,$\dom h=\mathbf{R}$,一些相似的复合规则仍然成立
$$\begin{equation}\label{Conclusion2}\begin{aligned}
若\,h\,是凸函数且\,\tilde{h}\,非减,\,g\,是凸函数,则\,f\,是凸函数,\\
若\,h\,是凸函数且\,\tilde{h}\,非增,\,g\,是凹函数,则\,f\,是凸函数,\\
若\,h\,是凹函数且\,\tilde{h}\,非减,\,g\,是凹函数,则\,f\,是凹函数,\\
若\,h\,是凹函数且\,\tilde{h}\,非增,\,g\,是凸函数,则\,f\,是凹函数。
\end{aligned}\end{equation}$$
其中,$\tilde{h}$ 表示函数 $h$ 的扩展值延伸,若点不在 $\dom h$ 内,对其赋值 $\infty$(若 $h$ 是凸函数)或者$-\infty$(若 $h$ 是凹函数)。这些结论和式 $\eqref{Conclusion1}$ 中的结论的唯一不同是我们要求**扩展值延伸**(*extended-value extension*)$\tilde{h}$ 在整个 $\mathbf{R}$ 上非增或者非减。
&emsp;&emsp;为了更好地理解式 $\eqref{Conclusion2}$ 中的结论,假设 $h$ 是凸函数,所以 $\tilde{h}$ 在定义域 $\dom h$ 外取值为 $\infty$。$\tilde{h}$ 非减意味着对于任意 $x,y\in\mathbf{R}$,$x<y$,有 $\tilde{h}(x)\leqslant\tilde{h}(y)$。特别地,若 $y\in\dom h$,则 $x\in\dom h$。换言之,我们可以认为 $h$ 的定义域在负方向上无限延伸。它或者是 $\mathbf{R}$ 或者是形如 $(-\infty,a)$ 或 $\left(-\infty,a\right]$ 的区间。类似地,若 $h$ 是凸函数且 $\tilde{h}$ 非增,我们可以理解为 $h$ 是非增的且 $\dom h$ 在正方向上趋于无穷。[图 7](#图7) 描述了不同的扩展值延伸的情况。
<a id="图7"></a>
![图 7. **左**:函数 $x^2$,其定义域为 $\mathbf{R}_+$,在其定义域内是凸且非减的,但是其扩展值延伸不是非减的。**右**:函数 $\max\{x,0\}^2$,其定义域为 $\mathbf{R}$,函数是凸函数,且其扩展值延伸是非减的。](../images/post/2024-07-03-josh-cvx-2-2/2024-07-03-josh-cvx-2-2-070-ExtendedValueExtension.png){width=700px}
> **举例**&emsp;通过一些简单例子,我们可以更好地理解复合定理中函数 $h$ 需要满足的条件。
>
> - 函数 $h(x)=\log x$:定义域为 $\dom h=\mathbf{R}_{++}$,为凹函数且 $\tilde{h}$ 非减。
> - 函数 $h(x)=x^1/2$:定义域为 $\dom h=\mathbf{R}_+$,为凹函数且 $\tilde{h}$ 非减。
> - 函数 $h(x)=x^{3/2}$:定义域为 $\dom h=\mathbf{R}_+$,为凸函数,但是**不**满足 $\tilde{h}$ 非减的条件。例如,$\tilde{h}(-1)=\infty$ 但 $\tilde{h}(1)=1$。
> - 当 $x\geqslant 0$ 时,$h(x)=x^3/2$,当 $x<0$ 时,$h(x)=0$:定义域为 $\dom h=\mathbf{R}$,$h$ 是凸函数且满足 $\tilde{h}$ 非减的条件。
&emsp;&emsp;即使不假设可微并运用表达式 $\eqref{SecondDerivativeOfScalarCompositionFunction}$,也可以直接证明复合函数结论式 $\eqref{Conclusion2}$。举例来说,我们证明如下结论:若 $g$ 是凸函数,$h$ 是凸函数且 $\tilde{h}$ 非减,则 $f=h\circ g$ 是凸函数。
> **证明**&emsp;假设 $x,y\in\dom f$,$0\leqslant\theta\leqslant1$。由 $x,y\in\dom f$,有 $x,y\in\dom g$ 且 $g( x)$, $g( y) \in \dom h$。因为 $\dom g$ 是凸集,有 $\theta x+(1-\theta)y\in\dom g$,由函数 $g$ 的凸性可得
>
> $$\begin{equation}\label{ConvexityOfFunctionG}
> g(\theta x+(1-\theta)y)\leqslant\theta g(x)+(1-\theta)g(y)
> \end{equation}
> $$
>
> 由 $g(x),g(y)\in\dom h$ 可得 $\theta g(x)+(1-\theta)g(y)\in\dom h$,即式 $\eqref{ConvexityOfFunctionG}$ 的右端在 $\dom h$ 内。根据假设 $\tilde{h}$ 是非减的,可以理解为其定义域在负方向上无限延伸。由式 $\eqref{ConvexityOfFunctionG}$ 的右端在 $\dom h$ 内,我们知道其左侧仍在定义域内,即 $g(\theta x+(1-\theta)y)\in\dom h$,因此 $\dom f$ 是凸集。
>
> 根据前提条件,$\tilde{h}$ 非减,利用不等式 $\eqref{ConvexityOfFunctionG}$,有
>
> $$\begin{equation}\label{NondecreasingOfFunctionH}
> h(g(\theta x+(1-\theta)y))\leqslant h(\theta g(x)+(1-\theta)g(y))
> \end{equation}
> $$
>
> 由函数 $h$ 的凸性可得
>
> $$\begin{equation}\label{ConvexityOfFunctionH}
> h(\theta g(x)+(1-\theta)g(y))\leqslant\theta h(g(x))+(1-\theta)h(g(y))
> \end{equation}
> $$
>
> 综合式 $\eqref{NondecreasingOfFunctionH}$ 和式 $\eqref{ConvexityOfFunctionH}$ 可得
>
> $$
> h(g(\theta x+(1-\theta)y))\leqslant\theta h(g(x))+(1-\theta)h(g(y))
> $$
>
> 复合定理得证。
> **举例**&emsp;**简单的复合结论**。
>
> - 若 $g$ 是凸函数,则 $\exp g(x)$ 是凸函数。
> - 若 $g$ 是凹函数且大于零,则 $\log g(x)$ 是凹函数。
> - 若 $g$ 是凹函数且大于零,则 $1/g(x)$是凸函数。
> - 若 $g$ 是凸函数且不小于零,$p\geqslant1$,则 $g(x)^p$ 是凸函数。
> - 若 $g$ 是凸函数,则 $-\log(-g(x))$ 在 $\{x\mid g(x)<0\}$ 上是凸函数。
> **注释**&emsp;扩展值延伸 $\tilde{h}$ 的单调性要求必须满足,注意到是 $\tilde{h}$,而不仅仅是 $h$。例如,考虑 $g( x) = x^2$,$\dom g = \mathbf{R}$,$h( x) = 0$,$\dom h= [ 1, 2]$ 复合的情形。此时 $g$ 是凸函数,$h$ 是凸函数且非减,但是函数 $f=h\circ g$
>
> $$
> f(x)=0,\quad\dom f=[-\sqrt{2},-1]\:\cup\:[1,\sqrt{2}]
> $$
>
> 不是凸函数,因为其定义域非凸。当然,此时函数 $\tilde{h}$ 不是非减的。
## 4.2 矢量复合
&emsp;&emsp;下面考虑 $k\geqslant1$ 的情况,此时更复杂一些。设
$$
f(x)=h(g(x))=h(g_1(x),\cdots,g_k(x))
$$
其中 $h: \mathbf{R} ^k\to \mathbf{R}$,$g_i: \mathbf{R} ^n\to \mathbf{R}$。和上一节一样,不失一般性,假设 $n=1$。和 $k=1$ 的情形类似,为了得到复合规则,假设函数二次可微,且 $\dom g=$ $\mathbf{R}$,$\dom h= \mathbf{R} ^{k}$。此时,对函数 $f$ 进行二次微分可得
$$\begin{equation}\label{SecondDerivativeOfVectorCompositionFunction}
f''(x)=g'(x)^{\TT}\nabla^2h(g(x))g'(x)+\nabla h(g(x))^{\TT}g''(x)
\end{equation}
$$
上式可以看成式 $\eqref{SecondDerivativeOfScalarCompositionFunction}$ 对应的向量形式。同样我们需要判断在什么条件下对所有 $x$ 有 $f(x)^{\prime\prime}\geqslant0$(或者对所有 $x$ 有 $f(x)^\prime\prime\leqslant 0$,此时 $f$ 是凹函数)。利用式 $\eqref{SecondDerivativeOfVectorCompositionFunction}$,我们可以得到很多规则,例如:
$$\begin{aligned}
若\:h\:是凸函数且在每维分量上\:h\:非减,g_i\:是凸函数,则\:f\:是凸函数;\\
若\:h\:是凸函数且在每维分量上\:h\:非增,g_i\:是凹函数,则\:f\:是凸函数;\\
若\:h\:是凹函数且在每维分量上\:h\:非减,g_i\:是凹函数,则\:f\:是凹函数。
\end{aligned}$$
和标量的情形类似,对于更一般的情况:$n>1$,不假设 $h$ 或 $g$ 可微以及一般的定义域类似的复合结论仍然成立。对于一般的结论,不仅 $h$ 需要满足单调性条件,其扩展值延伸 $\tilde{h}$ 同样必须满足。
&emsp;&emsp;为了更好地理解扩展值延伸 $\tilde{h}$ 必须满足单调性条件的含义,我们考虑凸函数 $h:\mathbf{R}^{k}\to\mathbf{R}$,且 $\tilde{h}$ 非减,即对任意 $u\preceq v$,有 $\tilde{h}(u)\leqslant\tilde{h}(v)$。这说明了若 $v\in\dom h$ 则 $u\in\dom h$,也即 $h$ 的定义域在方向 $-\mathbf{R}_+^k$ 上必须无限延伸。这个条件可以紧凑地描述为 $\dom h-\mathbf{R}_{+}^{k}=\dom h$。
> **举例**&emsp;矢量复合的例子。
>
> - 令 $h(z)=z_[1]+\cdots+z_{[r]}$,即对 $z\in\mathbf{R}^k$ 的前 $r$ 大分量进行求和。则 $h$ 是凸函数且在每一维分量上非减。假设 $g_1,\cdots,g_k$ 是 $\mathbf{R}^n$ 上的凸函数,则复合函数 $f=h\circ g$,即最大 $r\uparrow g_i$ 函数的逐点和,是凸函数。
>
> - 函数 $h(z)=\log\left(\displaystyle\sum_{i=1}^k\mathrm{e}^{z_i}\right)$ 是凸函数且在每一维分量上非减,因此只要 $g_i$ 是凸函数,$\log\left(\displaystyle\sum_{i=1}^{k}\mathrm{e}^{g_{i}}\right)$ 就是凸函数。
>
> - 对 $0<p\leqslant 1$,定义在 $\mathbf{R}_+^k$ 上的函数 $h(z)=\left(\displaystyle\sum_{i=1}^kz_i^p\right)^{1/p}$ 是凹的,且其扩展值延伸(当 $z\not\succeq0$ 时为 $-\infty$)在每维分量上非减,则若 $g_i$ 是凹函数且非负,$f(x)=\left(\displaystyle\sum_{i=1}^kg_i(x)^p\right)^{1/p}$ 是凸函数。
>
> - 设 $p\geqslant 1$, $g_{1}, \cdots , g_{k}$ 是凸函数且非负。则函数 $\left(\displaystyle\sum_{i=1}^ng_i(x)^p\right)^{1/p}$
>
> 为了说明这一点,考虑函数 $h:\mathbf{R}^k\to\mathbf{R}$
>
> $$
> h(z)=\left(\sum_{i=1}^{k}\max\{z_{i},0\}^{p}\right)^{1/p}
> $$
>
> 其中 $\dom h=\mathbf{R}^{k}$,因此 $h=\tilde{h}$。由函数 $h$ 是凸函数且非减可知 $h(g(x))$ 关于 $x$ 是凸函数。对 $z\succeq0$,我们有 $h(z)=\left(\displaystyle\sum_{i=1}^kz_i^p\right)^{1/p}$,所以 $\left(\displaystyle\sum_{i=1}^kg_i(x)^p\right)^{1/p}$ 是凸函数。
>
> - 几何平均函数 $h(z)=\left(\displaystyle\prod_{i=1}^kz_i\right)^{1/k}$,定义域为 $\mathbf{R}_+^k$,它是凹函数,且其扩展值延伸在每维分量上非减。因此若 $g_1,\cdots,g_k$ 是非负凹函数,它们的几何平均 $\left(\displaystyle\prod_{i=1}^kg_i\right)^{1/k}$ 也是非负凸函数。
# 5. 最小化
&emsp;&emsp;我们已经得到,任意个凸函数的逐点最大或者上确界仍然是凸函数。事实上,一些特殊形式的最小化同样可以得到凸函数。若函数 $f$ 关于 $(x,y)$ 是凸函数,集合 $C$ 是非空凸集,定义函数
$$\begin{equation}\label{DefinitionOfMinimization}
g(x)=\inf_{y\in C}f(x,y)
\end{equation}
$$
若存在某个 $x$ 使得 $g(x)>-\infty$(该条件隐含着对所有 $x,g(x)>-\infty$),则函数 $g$ 关于 $x$ 是凸函数。函数 $g$ 的定义域是 $\dom f$ 在 $x$ 方向上的投影,即
$$
\dom g=\{x\mid 对某些\:y\in C\:有\: (x,y)\in\dom f\}
$$
&emsp;&emsp;任取 $x_1$, $x_2\in \dom g$,利用 Jensen 不等式来证明上述结论。
> **证明**&emsp;令 $\epsilon>0$,则存在 $y_{1}$, $y_{2}\in C$,使 $f( x_{i}, y_{i}) \leqslant g( x_{i}) + \epsilon ( i= 1$, 2)。设 $\theta\in[0,1]$,有
>
> $$\begin{aligned}
> g(\theta x_{1}+(1-\theta)x_{2})&=\inf_{y\in C}f(\theta x_{1}+(1-\theta)x_{2},y)
> \\
> &\leqslant f(\theta x_1+(1-\theta)x_2,\theta y_1+(1-\theta)y_2)
> \\
> &\leqslant\theta f(x_1,y_1)+(1-\theta)f(x_2,y_2)
> \\
> &\leqslant\theta g(x_1)+(1-\theta)g(x_2)+\epsilon
> \end{aligned}$$
>
> 因为上式对任意$\epsilon>0$均成立,所以下式成立
> $$
> g(\theta x_1+(1-\theta)x_2)\leqslant\theta g(x_1)+(1-\theta)g(x_2)
> $$
&emsp;&emsp;此结论亦可通过上境图来说明。对式 $\eqref{DefinitionOfMinimization}$ 中定义的 $f$,$g$ 和 $C$,设对每个 $x$,在集合 $y\in C$ 上求下确界均可达到,则有
$$
\epi g=\{(x,t)\mid$对某个$y\in C$成立$(x,y,t)\in\epi f\}
$$
由于 $\epi g$是凸集在其中一些分量上的投影,所以它仍然是凸集。
> **举例**&emsp;**Schur 补**。设二次函数
>
> $$
> f(x,y)=x^{\TT}Ax+2x^{\TT}By+y^{\TT}Cy
> $$
>
> (其中$A$和$C$是对称矩阵)关于 $(x,y)$ 是凸函数,即
>
> $$
> \left[\begin{array}{cc}A&B\\B^{\TT}&C\end{array}\right]\succeq0
> $$
>
> 我们可以将$g(x)=\inf_yf(x,y)$表述为
>
> $$
> g(x)=x^{\TT}(A-BC^\dagger B^{\TT})x
> $$
>
> 其中 $C^\dagger$ 是矩阵 $C$ 的伪逆。根据极小化的性质,$g$ 是凸函数,因此 $A-BC^\dagger B^{\TT}\succeq 0$。
>
> 如果矩阵$C$可逆,即$C\succ0$,则矩阵$A-BC^{-1}B^{\TT}$称为$C$在矩阵
>
> $$
> \left[\begin{array}{cc}A&B\\B^{\TT}&C\end{array}\right]
> $$
>
> 中的 Schur 补。
> **举例**&emsp;**到某一集合的距离**。采用范数 $\|\cdot\|$,某点$x$到集合 $S\subseteq\mathbb{R}^n$ 的距离定义为
>
> $$
> \dist (x,S)=\inf_{y\in S}\|x-y\|
> $$
>
> 函数 $\|x-y\|$关于$(x,y)$ 是凸的,所以若集合 $S$ 是凸集,距离函数 $\dist (x,S)$ 是 $x$ 的凸函数。
> **举例**&emsp;设 $h$ 是凸函数。则函数 $g$
>
> $$
> g(x)=\inf\{h(y)\mid Ay=x\}
> $$
>
> 是凸函数。为了说明这一点,定义函数 $f$
>
> $$
> f(x,y)=\left\{\begin{array}{ll}h(y)&\text{如果}Ay=x\\\infty&\text{其他情况,}\end{array}\right.
> $$
>
> 此函数关于$(x,y)$是凸的。以$y$为自变量,极小化函数$f$即可得到函数$g$,因此函数$g$是凸函数。(直接证明$g$是凸函数亦不复杂。)
# 6. 透视函数
&emsp;&emsp;给定函数 $f:\mathbf{R}^n\to\mathbf{R}$,则 $f$ 的透视函数 $g:\mathbf{R}^n+1\to\mathbf{R}$ 定义为
$$
g(x,t)=tf(x/t)
$$
其定义域为
$$
\mathbf{dom}g=\{(x,t)\mid x/t\in\mathbf{dom}f,t>0\}
$$
透视运算是保凸运算:如果函数 $f$ 是凸函数,则其透视函数 $g$ 也是凸函数。类似地,若
$f$ 是凹函数,则 $g$ 亦是凹函数。
&emsp;&emsp;可以从多个角度来证明此结论,例如,我们可以直接验证定义凸性的不等式。这里应用上境图和[透视函数][]一节所描述的 $\mathbf{R}^{n+1}$ 上的透视映射给出一个简短的证明(同时也可以说明“透视”一词的由来)。当 $t>0$ 时,我们有
$$\begin{array}{lll}
(x,t,s)\in\epi g&\iff&tf(x/t)\leqslant s
\\
&\iff&f(x/t)\leqslant s/t
\\
&\iff&(x/t,s/t)\in\epi f
\end{array}$$
因此,$\epi g$是透视映射下 $\epi f$ 的原像,此透视映射将 $(u,v,w)$ 映射为 $(u,w)/v$。根据[透视函数][]一节中的结论,$\epi g$ 是凸集,所以函数 $g$ 是凸函数。
> **举例**&emsp;**Euclid 范数的平方**。$\mathbb{R}^n$ 上的凸函数 $f(x)=x^{\TT}x$ 的透视函数由下式给出
>
> $$
> g(x,t)=t(x/t)^{\TT}(x/t)=\frac{x^{\TT}x}{t}
> $$
>
> 当 $t>0$ 时它关于 $(x,t)$ 是凸函数。
>
> 我们可以利用其他方法导出$g$的凸性。首先,将 $g$ 表示为一系列二次-线性分式函数 $x_i^2/t$ 的和。在[凸函数举例][]部分,我们已经知道,每一项 $x_i^2/t$ 是凸函数,因此和亦为凸函数。另一方面。我们可以将 $g$ 表述为一种特殊的矩阵分式函数 $x^{\TT}(tI)^{-1}x$,由此导出凸性。
> **举例**&emsp;**负对数**。考虑 $\mathbf{R}_{++}$ 上的凸函数 $f(x)=-\log x$,其透视函数为
>
> $$
> g(x,t)=-t\log(x/t)=t\log(t/x)=t\log t-t\log x
> $$
>
> 在 $\mathbf{R}_{++}^{2}$ 上它是凸函数。函数 $g$ 称为关于 $t$ 和 $x$ 的**相对熵**(*relative entropy*)。当 $x=1$ 时,$g$ 即为负熵函数。
>
> 基于函数 $g$ 的凸性,我们可以得出一些有趣的相关函数的凸性或凹性。首先,定义两个向量 $u, v\in \mathbf{R} _{+ + }^{n}$ 的相对熵
>
> $$
> \sum_{i=1}^nu_i\log(u_i/v_i)
> $$
>
> 由于它是一系列 $u_i,v_i$ 的相对熵的和,因此关于 $(u,v)$ 是凸函数。
>
> 另一个密切相关的函数是向量 $u,v\in\mathbf{R}_{++}^{n}$ 之间的 **Kullback-Leibler 散度**(Kullback-Leibler divergence),其形式为
>
> $$\begin{equation}\label{KLDivergence}
> D_{\mathrm{kl}}(u,v)=\sum_{i=1}^{n}\left(u_{i}\log(u_{i}/v_{i})-u_{i}+v_{i}\right)
> \end{equation}
> $$
>
> 因为它是 $(u,v)$ 的相对熵和线性函数的和,所以它也是凸函数。Kullback-Leibler 散度总是满足 $D_{\mathrm{kl}}(u,v)\geqslant0$,当且仅当 $u=v$ 时,$D_\mathrm{kl}(u,v)=0$,因此 Kullback-Leibler 散度可以用来衡量两个正向量之间的偏差。(注意到当 $u$ 和 $v$ 都是概率向量,即 $\mathbf{1}^{\TT}u=\mathbf{1}^{\TT}v=1$ 时,相对熵和 Kullback-Leibler 散度是等价的。)
>
> 如果在相对熵函数中选择 $v_i=\mathbf{1}^{\TT}u$,我们可以得到定义在 $u\in\mathbb{R}_+^n$ 上的凹函数(也是齐次函数)
>
> $$
> \sum_{i=1}^{n}u_{i}\log(\mathbf{1}^{\TT}u/u_{i})=(\mathbf{1}^{\TT}u)\sum_{i=1}^{n}z_{i}\log(1/z_{i})
> $$
>
> 其中 $z=u/(\mathbf{1}^{\TT}u)$。此函数称为**归一化熵**(*normalized entropy*)函数。向量 $z=u/\mathbf{1}^{\TT}u$ 的分量和为 1,称为归一化向量或者概率分布;$u$ 的归一化熵是 $\mathbf{1}^{\TT}u$和归一化概率分布 $z$ 的熵的乘积。
> **举例**&emsp;设 $f:\mathbf{R}^m\to\mathbf{R}$ 是凸函数,$A\in\mathbf{R}^m\times n,b\in\mathbf{R}^m,c\in\mathbf{R}^n,d\in\mathbf{R}$。定义
>
> $$
> g(x)=(c^Tx+d)f\left((Ax+b)/(c^Tx+d)\right)
> $$
>
> 其定义域为
>
> $$
> \mathbf{dom}g=\{x\mid c^Tx+d>0,(Ax+b)/(c^Tx+d)\in\mathbf{dom}f\}
> $$
>
> 则$g$是凸函数。
# 参考文献
1. Stephen P. Boyd and Lieven Vandenberghe, *Convex optimization*. Cambridge, UK: Cambridge University Press, 2004.
2. Stephen P. Boyd and Lieven Vandenberghe, *凸优化*. 北京: 清华大学出版社, 2013.
[透视函数]: https://josh-gao.top/posts/a4a69a4f.html#%E9%80%8F%E8%A7%86%E5%87%BD%E6%95%B0
[凸函数举例]: https://josh-gao.top/posts/320f661c.html#%E4%BE%8B%E5%AD%90
@@ -0,0 +1,279 @@
---
title: 信息论角度推导高斯分布的概率密度函数
mathjax: true
comments: true
copyright: true
toc:
enable: true
number: true
wrap: true
expand_all: true
max_depth: 4
abbrlink: '741621e3'
date: 2025-07-02 09:20:07
tags:
- 高斯分布
- 信息论
categories:
- [数学, 概率论]
---
$\newcommand\diff{\mathop{}\!\mathrm{d}}$
# 背景与目标
在统计建模中,我们常常面临这样一个问题:**已知某个连续随机变量的期望和方差,如何合理地确定它的概率分布?** 最大熵原理(Maximum Entropy Principle)提供了一个具有信息论意义的答案:
> 在已知约束(如期望与方差)下,熵最大的概率密度函数是最“中立”或最“无偏”的选择。
熵在此表示不确定性或信息量。连续型随机变量的微分熵定义为:
$$
\begin{equation*}
H[p] = -\int_{-\infty}^{\infty} p(x) \ln p(x) \, \diff x
\end{equation*}
$$
我们的目标是:**在已知期望和方差的约束下,最大化熵 $H[p]$,求出最优概率密度函数 $p(x)$**。
<!-- more -->
# 约束条件
我们假设随机变量 $X$ 满足:
- 归一化约束:
$$
\begin{equation*}
\int_{-\infty}^{\infty} p(x) \, \diff x = 1
\end{equation*}
$$
- 期望约束:
$$
\begin{equation*}
\int_{-\infty}^{\infty} x \, p(x) \, \diff x = \mu
\end{equation*}
$$
- 方差约束:
$$
\begin{equation*}
\int_{-\infty}^{\infty} (x - \mu)^2 \, p(x) \, \diff x = \sigma^2
\end{equation*}
$$
# 构造拉格朗日泛函
引入拉格朗日乘子 $\lambda_0, \lambda_1, \lambda_2$,构造带约束的目标泛函:
$$
\begin{equation*}
\mathcal{L}[p] = -\int p(x) \ln p(x) \diff x
+ \lambda_0 \left( \int p(x) \diff x - 1 \right)
+ \lambda_1 \left( \int x p(x) \diff x - \mu \right)
+ \lambda_2 \left( \int (x - \mu)^2 p(x) \diff x - \sigma^2 \right)
\end{equation*}
$$
将所有积分项合并为:
$$
\begin{equation*}
\mathcal{L}[p] = \int \left[
- p(x) \ln p(x)
+ \lambda_0 p(x)
+ \lambda_1 x p(x)
+ \lambda_2 (x - \mu)^2 p(x)
\right] \diff x
\end{equation*}
$$
# 变分法求极值
我们考虑一个扰动:
$$
\begin{equation*}
p(x) \rightarrow p(x) + \epsilon \eta(x)
\end{equation*}
$$
其中 $\epsilon$ 是足够小的实数,$\eta(x)$ 是任意光滑、在积分区间内有界且满足边界条件的函数(可理解为“任意小的扰动”)。为了求出 $\dfrac{\delta \mathcal{L}}{\delta p(x)}$,我们代入扰动项进行展开:
$$
\begin{equation*}
\mathcal{L}[p + \epsilon \eta]
= -\int (p(x) + \epsilon \eta(x)) \ln (p(x) + \epsilon \eta(x)) \, \diff x + \text{其余约束项}
\end{equation*}
$$
> 注意:这里只展开了主熵项 $-\displaystyle\int p \ln p$,约束项形式类似,将在后面统一处理。
---
对主项使用泰勒展开(忽略高阶小量):
> **泰勒展开回顾:**
>
> 设 $f(p) = p \ln p$,我们对 $p(x) + \epsilon \eta(x)$ 展开,有:
> $$
> f(p + \epsilon \eta) = p \ln p + \epsilon \eta (1 + \ln p) + o(\epsilon)
> $$
> 其中:
> $$
> \frac{\diff }{\diff p}(p \ln p) = \ln p + 1
> $$
将其代入:
$$
\begin{align*}
\mathcal{L}[p + \epsilon \eta]
&= -\int \left[ p(x) \ln p(x) + \epsilon \eta(x)(1 + \ln p(x)) \right] \diff x + o(\epsilon) + \text{约束项} \\
&= \mathcal{L}[p] - \epsilon \int \eta(x) (1 + \ln p(x)) \diff x + o(\epsilon) + \text{约束项}
\end{align*}
$$
对约束项也类似展开:
- 对归一化项:
$$
\begin{equation*}
\lambda_0 \left( \int (p + \epsilon \eta) \diff x - 1 \right)
= \lambda_0 \left( \int p \, \diff x - 1 + \epsilon \int \eta \, \diff x \right)
\end{equation*}
$$
- 对期望项:
$$
\begin{equation*}
\lambda_1 \left( \int x (p + \epsilon \eta) \diff x - \mu \right)
= \lambda_1 \left( \int x p \, \diff x - \mu + \epsilon \int x \eta \, \diff x \right)
\end{equation*}
$$
- 对方差项:
$$
\begin{equation*}
\lambda_2 \left( \int (x - \mu)^2 (p + \epsilon \eta) \diff x - \sigma^2 \right)
= \lambda_2 \left( \int (x - \mu)^2 p \, \diff x - \sigma^2 + \epsilon \int (x - \mu)^2 \eta(x) \diff x \right)
\end{equation*}
$$
---
将所有一阶 $\epsilon$ 项收集起来:
$$
\begin{equation*}
\mathcal{L}[p + \epsilon \eta] = \mathcal{L}[p]
+ \epsilon \int \eta(x) \left[ - (1 + \ln p(x)) + \lambda_0 + \lambda_1 x + \lambda_2 (x - \mu)^2 \right] \diff x + o(\epsilon)
\end{equation*}
$$
对 $\epsilon$ 求导并令其在 $\epsilon = 0$ 处为零:
$$
\begin{equation*}
\left. \frac{\diff}{\diff \epsilon} \mathcal{L}[p + \epsilon \eta] \right|_{\epsilon=0}
= \int \eta(x) \left[ -\ln p(x) - 1 + \lambda_0 + \lambda_1 x + \lambda_2 (x - \mu)^2 \right] \diff x = 0
\end{equation*}
$$
根据变分法基本引理,这个积分当且仅当括号内为 $0$ 时对所有扰动函数 $\eta(x)$ 为零:
> 变分法基本引理:
>
> 若函数 $F(x)$ 满足
> $$
> \int_{a}^{b} F(x) \cdot \eta(x) dx = 0
> $$
> 对所有合适扰动 $\eta(x)$ 成立,则必有
> $$
> F(x) = 0 \quad \forall x \in (a, b)
> $$
>
> 这是因为若 $F(x_0) \ne 0$,则可构造在 $x_0$ 附近支持的 $\eta(x)$ 使得积分不为零,导致矛盾。
$$
\begin{equation*}
\frac{\delta \mathcal{L}}{\delta p(x)} = -\ln p(x) - 1 + \lambda_0 + \lambda_1 x + \lambda_2 (x - \mu)^2 = 0
\end{equation*}
$$
也即求得了变分导数。移项得:
$$
\begin{equation*}
\ln p(x) = \lambda_0' + \lambda_1 x + \lambda_2 (x - \mu)^2
\end{equation*}
$$
两边取指数:
$$
\begin{equation*}
p(x) = \exp\left( \lambda_0' + \lambda_1 x + \lambda_2 (x - \mu)^2 \right)
\end{equation*}
$$
要满足可积性,需 $\lambda_2 < 0$。设
$$
\begin{equation*}
p(x) = A \cdot \exp\left( -\alpha (x - \mu)^2 \right)
\end{equation*}
$$
# 归一化与确定参数
根据归一化条件:
$$
\begin{equation*}
A \cdot \int_{-\infty}^{\infty} \exp\left( -\alpha (x - \mu)^2 \right) \diff x = 1
\end{equation*}
$$
已知高斯积分结果:
$$
\begin{equation*}
\int_{-\infty}^{\infty} \exp\left( -\alpha (x - \mu)^2 \right) \diff x = \sqrt{\frac{\pi}{\alpha}}
\end{equation*}
$$
得到:
$$
\begin{equation*}
A = \sqrt{\frac{\alpha}{\pi}}
\end{equation*}
$$
若令 $\alpha = \dfrac{1}{2\sigma^2}$,则最终得:
$$
\begin{equation*}
p(x) = \frac{1}{\sqrt{2\pi\sigma^2}} \exp\left( -\frac{(x - \mu)^2}{2\sigma^2} \right)
\end{equation*}
$$
# 总结
从最大熵原理出发,在已知均值与方差的约束下,最“无偏”或熵最大的概率密度函数是:
$$
\begin{equation*}
p(x) = \frac{1}{\sqrt{2\pi\sigma^2}} \exp\left( -\frac{(x - \mu)^2}{2\sigma^2} \right)
\end{equation*}
$$
这正是**高斯分布**的标准形式,说明它不仅数学上方便,**信息论上也是最合理的选择**。

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Before

Width:  |  Height:  |  Size: 498 B

After

Width:  |  Height:  |  Size: 498 B

Before

Width:  |  Height:  |  Size: 937 B

After

Width:  |  Height:  |  Size: 937 B

Before

Width:  |  Height:  |  Size: 435 B

After

Width:  |  Height:  |  Size: 435 B

Before

Width:  |  Height:  |  Size: 827 B

After

Width:  |  Height:  |  Size: 827 B

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Before

Width:  |  Height:  |  Size: 640 B

After

Width:  |  Height:  |  Size: 640 B

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Before

Width:  |  Height:  |  Size: 1.4 MiB

After

Width:  |  Height:  |  Size: 1.4 MiB

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Before

Width:  |  Height:  |  Size: 534 B

After

Width:  |  Height:  |  Size: 534 B

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

@@ -0,0 +1,338 @@
<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.0//EN'
'http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd'>
<svg xmlns:xlink="http://www.w3.org/1999/xlink" style="fill-opacity:1; color-rendering:auto; color-interpolation:auto; text-rendering:auto; stroke:black; stroke-linecap:square; stroke-miterlimit:10; shape-rendering:auto; stroke-opacity:1; fill:black; stroke-dasharray:none; font-weight:normal; stroke-width:1; font-family:'Dialog'; font-style:normal; stroke-linejoin:miter; font-size:12px; stroke-dashoffset:0; image-rendering:auto;" width="560" height="420" xmlns="http://www.w3.org/2000/svg"
><!--Generated by the Batik Graphics2D SVG Generator--><defs id="genericDefs"
/><g
><defs id="defs1"
><clipPath clipPathUnits="userSpaceOnUse" id="clipPath1"
><path d="M0 0 L560 0 L560 420 L0 420 L0 0 Z"
/></clipPath
><font horiz-adv-x="75.0" id="font1"
><font-face ascent="100.53711" descent="21.972656" units-per-em="100" style="font-style:normal; font-family:Dialog; font-weight:normal;"
/><missing-glyph horiz-adv-x="75.0" d="M12.5 0 L12.5 62.5 L62.5 62.5 L62.5 0 L12.5 0 ZM14.0625 1.5625 L60.9375 1.5625 L60.9375 60.9375 L14.0625 60.9375 L14.0625 1.5625 Z"
/><glyph unicode="1" horiz-adv-x="55.615234" d="M37.25 0 L28.4688 0 L28.4688 56 Q25.2969 52.9844 20.1406 49.9531 Q14.9844 46.9219 10.8906 45.4062 L10.8906 53.9062 Q18.2656 57.375 23.7812 62.3047 Q29.2969 67.2344 31.5938 71.875 L37.25 71.875 L37.25 0 Z"
/><glyph unicode="." horiz-adv-x="27.783203" d="M9.0781 0 L9.0781 10.0156 L19.0938 10.0156 L19.0938 0 L9.0781 0 Z"
/><glyph unicode="0" horiz-adv-x="55.615234" d="M4.1562 35.2969 Q4.1562 48 6.7656 55.7422 Q9.375 63.4844 14.5234 67.6797 Q19.6719 71.875 27.4844 71.875 Q33.25 71.875 37.5938 69.5547 Q41.9375 67.2344 44.7734 62.8672 Q47.6094 58.5 49.2188 52.2266 Q50.8281 45.9531 50.8281 35.2969 Q50.8281 22.7031 48.2422 14.9688 Q45.6562 7.2344 40.5078 3.0078 Q35.3594 -1.2188 27.4844 -1.2188 Q17.1406 -1.2188 11.2344 6.2031 Q4.1562 15.1406 4.1562 35.2969 ZM13.1875 35.2969 Q13.1875 17.6719 17.3125 11.8359 Q21.4375 6 27.4844 6 Q33.5469 6 37.6719 11.8594 Q41.7969 17.7188 41.7969 35.2969 Q41.7969 52.9844 37.6719 58.7891 Q33.5469 64.5938 27.3906 64.5938 Q21.3438 64.5938 17.7188 59.4688 Q13.1875 52.9375 13.1875 35.2969 Z"
/><glyph unicode="-" horiz-adv-x="33.30078" d="M3.1719 21.4844 L3.1719 30.3281 L30.1719 30.3281 L30.1719 21.4844 L3.1719 21.4844 Z"
/><glyph unicode="2" horiz-adv-x="55.615234" d="M50.3438 8.4531 L50.3438 0 L3.0312 0 Q2.9375 3.1719 4.0469 6.1094 Q5.8594 10.9375 9.8359 15.625 Q13.8125 20.3125 21.3438 26.4688 Q33.0156 36.0312 37.1172 41.625 Q41.2188 47.2188 41.2188 52.2031 Q41.2188 57.4219 37.4766 61.0078 Q33.7344 64.5938 27.7344 64.5938 Q21.3906 64.5938 17.5781 60.7891 Q13.7656 56.9844 13.7188 50.25 L4.6875 51.1719 Q5.6094 61.2812 11.6641 66.5781 Q17.7188 71.875 27.9375 71.875 Q38.2344 71.875 44.2422 66.1641 Q50.25 60.4531 50.25 52 Q50.25 47.7031 48.4922 43.5547 Q46.7344 39.4062 42.6562 34.8125 Q38.5781 30.2188 29.1094 22.2188 Q21.1875 15.5781 18.9453 13.2109 Q16.7031 10.8438 15.2344 8.4531 L50.3438 8.4531 Z"
/><glyph unicode="3" horiz-adv-x="55.615234" d="M4.2031 18.8906 L12.9844 20.0625 Q14.5 12.5938 18.1406 9.2969 Q21.7812 6 27 6 Q33.2031 6 37.4766 10.2969 Q41.75 14.5938 41.75 20.9531 Q41.75 27 37.7969 30.9297 Q33.8438 34.8594 27.7344 34.8594 Q25.25 34.8594 21.5312 33.8906 L22.5156 41.6094 Q23.3906 41.5 23.9219 41.5 Q29.5469 41.5 34.0391 44.4297 Q38.5312 47.3594 38.5312 53.4688 Q38.5312 58.2969 35.2578 61.4766 Q31.9844 64.6562 26.8125 64.6562 Q21.6875 64.6562 18.2656 61.4297 Q14.8438 58.2031 13.875 51.7656 L5.0781 53.3281 Q6.6875 62.1562 12.3984 67.0156 Q18.1094 71.875 26.6094 71.875 Q32.4688 71.875 37.3984 69.3594 Q42.3281 66.8438 44.9453 62.5 Q47.5625 58.1562 47.5625 53.2656 Q47.5625 48.6406 45.0703 44.8281 Q42.5781 41.0156 37.7031 38.7656 Q44.0469 37.3125 47.5625 32.6953 Q51.0781 28.0781 51.0781 21.1406 Q51.0781 11.7656 44.2422 5.25 Q37.4062 -1.2656 26.9531 -1.2656 Q17.5312 -1.2656 11.3047 4.3516 Q5.0781 9.9688 4.2031 18.8906 Z"
/><glyph unicode="4" horiz-adv-x="55.615234" d="M32.3281 0 L32.3281 17.1406 L1.2656 17.1406 L1.2656 25.2031 L33.9375 71.5781 L41.1094 71.5781 L41.1094 25.2031 L50.7812 25.2031 L50.7812 17.1406 L41.1094 17.1406 L41.1094 0 L32.3281 0 ZM32.3281 25.2031 L32.3281 57.4688 L9.9062 25.2031 L32.3281 25.2031 Z"
/><glyph unicode="5" horiz-adv-x="55.615234" d="M4.1562 18.75 L13.375 19.5312 Q14.4062 12.7969 18.1406 9.3984 Q21.875 6 27.1562 6 Q33.5 6 37.8906 10.7891 Q42.2812 15.5781 42.2812 23.4844 Q42.2812 31 38.0625 35.3516 Q33.8438 39.7031 27 39.7031 Q22.75 39.7031 19.3359 37.7734 Q15.9219 35.8438 13.9688 32.7656 L5.7188 33.8438 L12.6406 70.6094 L48.25 70.6094 L48.25 62.2031 L19.6719 62.2031 L15.8281 42.9688 Q22.2656 47.4688 29.3438 47.4688 Q38.7188 47.4688 45.1641 40.9688 Q51.6094 34.4688 51.6094 24.2656 Q51.6094 14.5469 45.9531 7.4688 Q39.0625 -1.2188 27.1562 -1.2188 Q17.3906 -1.2188 11.2109 4.25 Q5.0312 9.7188 4.1562 18.75 Z"
/><glyph unicode="6" horiz-adv-x="55.615234" d="M49.75 54.0469 L41.0156 53.375 Q39.8438 58.5469 37.7031 60.8906 Q34.125 64.6562 28.9062 64.6562 Q24.7031 64.6562 21.5312 62.3125 Q17.3906 59.2812 14.9922 53.4688 Q12.5938 47.6562 12.5 36.9219 Q15.6719 41.75 20.2656 44.0938 Q24.8594 46.4375 29.8906 46.4375 Q38.6719 46.4375 44.8516 39.9688 Q51.0312 33.5 51.0312 23.25 Q51.0312 16.5 48.125 10.7188 Q45.2188 4.9375 40.1406 1.8594 Q35.0625 -1.2188 28.6094 -1.2188 Q17.625 -1.2188 10.6953 6.8594 Q3.7656 14.9375 3.7656 33.5 Q3.7656 54.25 11.4219 63.6719 Q18.1094 71.875 29.4375 71.875 Q37.8906 71.875 43.2891 67.1406 Q48.6875 62.4062 49.75 54.0469 ZM13.875 23.1875 Q13.875 18.6562 15.7969 14.5078 Q17.7188 10.3594 21.1875 8.1797 Q24.6562 6 28.4688 6 Q34.0312 6 38.0391 10.4922 Q42.0469 14.9844 42.0469 22.7031 Q42.0469 30.125 38.0859 34.3984 Q34.125 38.6719 28.125 38.6719 Q22.1719 38.6719 18.0234 34.3984 Q13.875 30.125 13.875 23.1875 Z"
/><glyph unicode="e" horiz-adv-x="55.615234" d="M42.0938 16.7031 L51.1719 15.5781 Q49.0312 7.625 43.2188 3.2266 Q37.4062 -1.1719 28.375 -1.1719 Q17 -1.1719 10.3281 5.8359 Q3.6562 12.8438 3.6562 25.4844 Q3.6562 38.5781 10.3984 45.8047 Q17.1406 53.0312 27.875 53.0312 Q38.2812 53.0312 44.875 45.9531 Q51.4688 38.875 51.4688 26.0312 Q51.4688 25.25 51.4219 23.6875 L12.75 23.6875 Q13.2344 15.1406 17.5781 10.6016 Q21.9219 6.0625 28.4219 6.0625 Q33.25 6.0625 36.6719 8.6016 Q40.0938 11.1406 42.0938 16.7031 ZM13.2344 30.9062 L42.1875 30.9062 Q41.6094 37.4531 38.875 40.7188 Q34.6719 45.7969 27.9844 45.7969 Q21.9219 45.7969 17.7969 41.75 Q13.6719 37.7031 13.2344 30.9062 Z"
/><glyph unicode="d" horiz-adv-x="55.615234" d="M40.2344 0 L40.2344 6.5469 Q35.2969 -1.1719 25.7344 -1.1719 Q19.5312 -1.1719 14.3281 2.25 Q9.125 5.6719 6.2734 11.7969 Q3.4219 17.9219 3.4219 25.875 Q3.4219 33.6406 6.0078 39.9688 Q8.5938 46.2969 13.7734 49.6641 Q18.9531 53.0312 25.3438 53.0312 Q30.0312 53.0312 33.6953 51.0547 Q37.3594 49.0781 39.6562 45.9062 L39.6562 71.5781 L48.3906 71.5781 L48.3906 0 L40.2344 0 ZM12.4531 25.875 Q12.4531 15.9219 16.6484 10.9922 Q20.8438 6.0625 26.5625 6.0625 Q32.3281 6.0625 36.3516 10.7734 Q40.375 15.4844 40.375 25.1406 Q40.375 35.7969 36.2734 40.7734 Q32.1719 45.75 26.1719 45.75 Q20.3125 45.75 16.3828 40.9688 Q12.4531 36.1875 12.4531 25.875 Z"
/><glyph unicode="u" horiz-adv-x="55.615234" d="M40.5781 0 L40.5781 7.625 Q34.5156 -1.1719 24.125 -1.1719 Q19.5312 -1.1719 15.5547 0.5859 Q11.5781 2.3438 9.6484 5.0078 Q7.7188 7.6719 6.9375 11.5312 Q6.3906 14.1094 6.3906 19.7344 L6.3906 51.8594 L15.1875 51.8594 L15.1875 23.0938 Q15.1875 16.2188 15.7188 13.8125 Q16.5469 10.3594 19.2344 8.375 Q21.9219 6.3906 25.875 6.3906 Q29.8281 6.3906 33.2969 8.4219 Q36.7656 10.4531 38.2109 13.9453 Q39.6562 17.4375 39.6562 24.0781 L39.6562 51.8594 L48.4375 51.8594 L48.4375 0 L40.5781 0 Z"
/><glyph unicode="t" horiz-adv-x="27.783203" d="M25.7812 7.8594 L27.0469 0.0938 Q23.3438 -0.6875 20.4062 -0.6875 Q15.625 -0.6875 12.9922 0.8281 Q10.3594 2.3438 9.2812 4.8125 Q8.2031 7.2812 8.2031 15.1875 L8.2031 45.0156 L1.7656 45.0156 L1.7656 51.8594 L8.2031 51.8594 L8.2031 64.7031 L16.9375 69.9688 L16.9375 51.8594 L25.7812 51.8594 L25.7812 45.0156 L16.9375 45.0156 L16.9375 14.7031 Q16.9375 10.9375 17.4062 9.8672 Q17.875 8.7969 18.9219 8.1562 Q19.9688 7.5156 21.9219 7.5156 Q23.3906 7.5156 25.7812 7.8594 Z"
/><glyph unicode="i" horiz-adv-x="22.216797" d="M6.6406 61.4688 L6.6406 71.5781 L15.4375 71.5781 L15.4375 61.4688 L6.6406 61.4688 ZM6.6406 0 L6.6406 51.8594 L15.4375 51.8594 L15.4375 0 L6.6406 0 Z"
/><glyph unicode="l" horiz-adv-x="22.216797" d="M6.3906 0 L6.3906 71.5781 L15.1875 71.5781 L15.1875 0 L6.3906 0 Z"
/><glyph unicode="p" horiz-adv-x="55.615234" d="M6.5938 -19.875 L6.5938 51.8594 L14.5938 51.8594 L14.5938 45.125 Q17.4375 49.0781 21 51.0547 Q24.5625 53.0312 29.6406 53.0312 Q36.2812 53.0312 41.3594 49.6094 Q46.4375 46.1875 49.0234 39.9609 Q51.6094 33.7344 51.6094 26.3125 Q51.6094 18.3594 48.7578 11.9844 Q45.9062 5.6094 40.4609 2.2188 Q35.0156 -1.1719 29 -1.1719 Q24.6094 -1.1719 21.1172 0.6875 Q17.625 2.5469 15.375 5.375 L15.375 -19.875 L6.5938 -19.875 ZM14.5469 25.6406 Q14.5469 15.625 18.6016 10.8438 Q22.6562 6.0625 28.4219 6.0625 Q34.2812 6.0625 38.4531 11.0156 Q42.625 15.9688 42.625 26.375 Q42.625 36.2812 38.5469 41.2109 Q34.4688 46.1406 28.8125 46.1406 Q23.1875 46.1406 18.8672 40.8906 Q14.5469 35.6406 14.5469 25.6406 Z"
/><glyph unicode="m" horiz-adv-x="83.30078" d="M6.5938 0 L6.5938 51.8594 L14.4531 51.8594 L14.4531 44.5781 Q16.8906 48.3906 20.9453 50.7109 Q25 53.0312 30.1719 53.0312 Q35.9375 53.0312 39.625 50.6406 Q43.3125 48.25 44.8281 43.9531 Q50.9844 53.0312 60.8438 53.0312 Q68.5625 53.0312 72.7109 48.7578 Q76.8594 44.4844 76.8594 35.5938 L76.8594 0 L68.1094 0 L68.1094 32.6719 Q68.1094 37.9375 67.2578 40.2578 Q66.4062 42.5781 64.1641 43.9922 Q61.9219 45.4062 58.8906 45.4062 Q53.4219 45.4062 49.8047 41.7734 Q46.1875 38.1406 46.1875 30.125 L46.1875 0 L37.4062 0 L37.4062 33.6875 Q37.4062 39.5469 35.2578 42.4766 Q33.1094 45.4062 28.2188 45.4062 Q24.5156 45.4062 21.3672 43.4531 Q18.2188 41.5 16.7969 37.7422 Q15.375 33.9844 15.375 26.9062 L15.375 0 L6.5938 0 Z"
/><glyph unicode="A" horiz-adv-x="66.69922" d="M-0.1406 0 L27.3438 71.5781 L37.5469 71.5781 L66.8438 0 L56.0625 0 L47.7031 21.6875 L17.7812 21.6875 L9.9062 0 L-0.1406 0 ZM20.5156 29.3906 L44.7812 29.3906 L37.3125 49.2188 Q33.8906 58.25 32.2344 64.0625 Q30.8594 57.1719 28.375 50.3906 L20.5156 29.3906 Z"
/><glyph unicode=")" horiz-adv-x="33.30078" d="M12.3594 -21.0469 L6.0625 -21.0469 Q20.6562 2.3906 20.6562 25.875 Q20.6562 35.0625 18.5625 44.0938 Q16.8906 51.4219 13.9219 58.1562 Q12.0156 62.5469 6.0625 72.7969 L12.3594 72.7969 Q21.5312 60.5469 25.9219 48.1875 Q29.6875 37.5469 29.6875 25.9219 Q29.6875 12.75 24.6328 0.4453 Q19.5781 -11.8594 12.3594 -21.0469 Z"
/><glyph unicode="a" horiz-adv-x="55.615234" d="M40.4375 6.3906 Q35.5469 2.25 31.0312 0.5391 Q26.5156 -1.1719 21.3438 -1.1719 Q12.7969 -1.1719 8.2031 3 Q3.6094 7.1719 3.6094 13.6719 Q3.6094 17.4844 5.3438 20.6328 Q7.0781 23.7812 9.8906 25.6875 Q12.7031 27.5938 16.2188 28.5625 Q18.7969 29.25 24.0312 29.8906 Q34.6719 31.1562 39.7031 32.9062 Q39.75 34.7188 39.75 35.2031 Q39.75 40.5781 37.25 42.7812 Q33.8906 45.75 27.25 45.75 Q21.0469 45.75 18.0938 43.5781 Q15.1406 41.4062 13.7188 35.8906 L5.125 37.0625 Q6.2969 42.5781 8.9844 45.9688 Q11.6719 49.3594 16.75 51.1953 Q21.8281 53.0312 28.5156 53.0312 Q35.1562 53.0312 39.3047 51.4688 Q43.4531 49.9062 45.4062 47.5391 Q47.3594 45.1719 48.1406 41.5469 Q48.5781 39.3125 48.5781 33.4531 L48.5781 21.7344 Q48.5781 9.4688 49.1406 6.2266 Q49.7031 2.9844 51.375 0 L42.1875 0 Q40.8281 2.7344 40.4375 6.3906 ZM39.7031 26.0312 Q34.9062 24.0781 25.3438 22.7031 Q19.9219 21.9219 17.6797 20.9453 Q15.4375 19.9688 14.2109 18.0938 Q12.9844 16.2188 12.9844 13.9219 Q12.9844 10.4062 15.6484 8.0625 Q18.3125 5.7188 23.4375 5.7188 Q28.5156 5.7188 32.4688 7.9375 Q36.4219 10.1562 38.2812 14.0156 Q39.7031 17 39.7031 22.7969 L39.7031 26.0312 Z"
/><glyph unicode="s" horiz-adv-x="50.0" d="M3.0781 15.4844 L11.7656 16.8438 Q12.5 11.625 15.8438 8.8438 Q19.1875 6.0625 25.2031 6.0625 Q31.25 6.0625 34.1797 8.5234 Q37.1094 10.9844 37.1094 14.3125 Q37.1094 17.2812 34.5156 19 Q32.7188 20.1719 25.5312 21.9688 Q15.875 24.4219 12.1406 26.2031 Q8.4062 27.9844 6.4766 31.1328 Q4.5469 34.2812 4.5469 38.0938 Q4.5469 41.5469 6.1328 44.5078 Q7.7188 47.4688 10.4531 49.4219 Q12.5 50.9219 16.0391 51.9766 Q19.5781 53.0312 23.6406 53.0312 Q29.7344 53.0312 34.3516 51.2734 Q38.9688 49.5156 41.1641 46.5078 Q43.3594 43.5 44.1875 38.4844 L35.5938 37.3125 Q35.0156 41.3125 32.2031 43.5547 Q29.3906 45.7969 24.2656 45.7969 Q18.2188 45.7969 15.625 43.7969 Q13.0312 41.7969 13.0312 39.1094 Q13.0312 37.4062 14.1094 36.0312 Q15.1875 34.625 17.4844 33.6875 Q18.7969 33.2031 25.25 31.4531 Q34.5781 28.9531 38.2578 27.3672 Q41.9375 25.7812 44.0391 22.7578 Q46.1406 19.7344 46.1406 15.2344 Q46.1406 10.8438 43.5781 6.9609 Q41.0156 3.0781 36.1797 0.9531 Q31.3438 -1.1719 25.25 -1.1719 Q15.1406 -1.1719 9.8438 3.0312 Q4.5469 7.2344 3.0781 15.4844 Z"
/><glyph unicode="(" horiz-adv-x="33.30078" d="M23.3906 -21.0469 Q16.1094 -11.8594 11.0859 0.4453 Q6.0625 12.75 6.0625 25.9219 Q6.0625 37.5469 9.8125 48.1875 Q14.2031 60.5469 23.3906 72.7969 L29.6875 72.7969 Q23.7812 62.6406 21.875 58.2969 Q18.8906 51.5625 17.1875 44.2344 Q15.0938 35.1094 15.0938 25.875 Q15.0938 2.3906 29.6875 -21.0469 L23.3906 -21.0469 Z"
/><glyph unicode=" " horiz-adv-x="27.783203" d=""
/><glyph unicode="n" horiz-adv-x="55.615234" d="M6.5938 0 L6.5938 51.8594 L14.5 51.8594 L14.5 44.4844 Q20.2188 53.0312 31 53.0312 Q35.6875 53.0312 39.625 51.3438 Q43.5625 49.6562 45.5156 46.9219 Q47.4688 44.1875 48.25 40.4375 Q48.7344 37.9844 48.7344 31.8906 L48.7344 0 L39.9375 0 L39.9375 31.5469 Q39.9375 36.9219 38.9141 39.5781 Q37.8906 42.2344 35.2812 43.8203 Q32.6719 45.4062 29.1562 45.4062 Q23.5312 45.4062 19.4531 41.8438 Q15.375 38.2812 15.375 28.3281 L15.375 0 L6.5938 0 Z"
/></font
><font horiz-adv-x="75.0" id="font2"
><font-face ascent="100.53711" descent="21.972656" units-per-em="100" style="font-style:normal; font-family:Dialog; font-weight:bold;"
/><missing-glyph horiz-adv-x="75.0" d="M12.5 0 L12.5 62.5 L62.5 62.5 L62.5 0 L12.5 0 ZM14.0625 1.5625 L60.9375 1.5625 L60.9375 60.9375 L14.0625 60.9375 L14.0625 1.5625 Z"
/><glyph unicode="n" horiz-adv-x="61.083984" d="M54.3438 0 L40.625 0 L40.625 26.4688 Q40.625 34.8594 39.75 37.3281 Q38.875 39.7969 36.8906 41.1641 Q34.9062 42.5312 32.125 42.5312 Q28.5625 42.5312 25.7344 40.5781 Q22.9062 38.625 21.8516 35.3984 Q20.7969 32.1719 20.7969 23.4844 L20.7969 0 L7.0781 0 L7.0781 51.8594 L19.8281 51.8594 L19.8281 44.2344 Q26.6094 53.0312 36.9219 53.0312 Q41.4531 53.0312 45.2109 51.3906 Q48.9688 49.75 50.8984 47.2109 Q52.8281 44.6719 53.5859 41.4531 Q54.3438 38.2344 54.3438 32.2344 L54.3438 0 Z"
/><glyph unicode="o" horiz-adv-x="61.083984" d="M4 26.6562 Q4 33.5 7.375 39.8984 Q10.75 46.2969 16.9219 49.6641 Q23.0938 53.0312 30.7188 53.0312 Q42.4844 53.0312 50 45.3906 Q57.5156 37.75 57.5156 26.0781 Q57.5156 14.3125 49.9219 6.5703 Q42.3281 -1.1719 30.8125 -1.1719 Q23.6875 -1.1719 17.2188 2.0547 Q10.75 5.2812 7.375 11.5 Q4 17.7188 4 26.6562 ZM18.0625 25.9219 Q18.0625 18.2188 21.7266 14.1172 Q25.3906 10.0156 30.7656 10.0156 Q36.1406 10.0156 39.7734 14.1172 Q43.4062 18.2188 43.4062 26.0312 Q43.4062 33.6406 39.7734 37.7422 Q36.1406 41.8438 30.7656 41.8438 Q25.3906 41.8438 21.7266 37.7422 Q18.0625 33.6406 18.0625 25.9219 Z"
/><glyph unicode="R" horiz-adv-x="72.2168" d="M7.3281 0 L7.3281 71.5781 L37.75 71.5781 Q49.2188 71.5781 54.4219 69.6484 Q59.625 67.7188 62.75 62.7891 Q65.875 57.8594 65.875 51.5156 Q65.875 43.4531 61.1328 38.2031 Q56.3906 32.9531 46.9688 31.5938 Q51.6562 28.8594 54.7109 25.5859 Q57.7656 22.3125 62.9375 13.9688 L71.6875 0 L54.3906 0 L43.9531 15.5781 Q38.375 23.9219 36.3281 26.0938 Q34.2812 28.2656 31.9844 29.0781 Q29.6875 29.8906 24.7031 29.8906 L21.7812 29.8906 L21.7812 0 L7.3281 0 ZM21.7812 41.3125 L32.4688 41.3125 Q42.875 41.3125 45.4609 42.1875 Q48.0469 43.0625 49.5156 45.2109 Q50.9844 47.3594 50.9844 50.5938 Q50.9844 54.2031 49.0547 56.4219 Q47.125 58.6406 43.6094 59.2344 Q41.8438 59.4688 33.0625 59.4688 L21.7812 59.4688 L21.7812 41.3125 Z"
/><glyph unicode=" " horiz-adv-x="27.783203" d=""
/><glyph unicode="e" horiz-adv-x="55.615234" d="M37.2031 16.5 L50.875 14.2031 Q48.25 6.6875 42.5547 2.7578 Q36.8594 -1.1719 28.3281 -1.1719 Q14.7969 -1.1719 8.2969 7.6719 Q3.1719 14.75 3.1719 25.5312 Q3.1719 38.4219 9.9141 45.7266 Q16.6562 53.0312 26.9531 53.0312 Q38.5312 53.0312 45.2188 45.3906 Q51.9062 37.75 51.6094 21.9688 L17.2344 21.9688 Q17.3906 15.875 20.5625 12.4766 Q23.7344 9.0781 28.4688 9.0781 Q31.6875 9.0781 33.8828 10.8359 Q36.0781 12.5938 37.2031 16.5 ZM37.9844 30.375 Q37.8438 36.3281 34.9141 39.4297 Q31.9844 42.5312 27.7812 42.5312 Q23.2969 42.5312 20.3594 39.2656 Q17.4375 35.9844 17.4844 30.375 L37.9844 30.375 Z"
/><glyph unicode="s" horiz-adv-x="55.615234" d="M2.3438 14.7969 L16.1094 16.8906 Q17 12.8906 19.6797 10.8125 Q22.3594 8.7344 27.2031 8.7344 Q32.5156 8.7344 35.2031 10.6875 Q37.0156 12.0625 37.0156 14.3594 Q37.0156 15.9219 36.0312 16.9375 Q35.0156 17.9219 31.4531 18.75 Q14.8438 22.4062 10.4062 25.4375 Q4.25 29.6406 4.25 37.1094 Q4.25 43.8438 9.5703 48.4375 Q14.8906 53.0312 26.0781 53.0312 Q36.7188 53.0312 41.8984 49.5625 Q47.0781 46.0938 49.0312 39.3125 L36.0781 36.9219 Q35.25 39.9375 32.9297 41.5547 Q30.6094 43.1719 26.3125 43.1719 Q20.9062 43.1719 18.5625 41.6562 Q17 40.5781 17 38.875 Q17 37.4062 18.3594 36.375 Q20.2188 35.0156 31.1797 32.5234 Q42.1406 30.0312 46.4844 26.4219 Q50.7812 22.75 50.7812 16.2188 Q50.7812 9.0781 44.8281 3.9531 Q38.875 -1.1719 27.2031 -1.1719 Q16.6094 -1.1719 10.4297 3.125 Q4.25 7.4219 2.3438 14.7969 Z"
/><glyph unicode="l" horiz-adv-x="27.783203" d="M7.1719 0 L7.1719 71.5781 L20.9062 71.5781 L20.9062 0 L7.1719 0 Z"
/><glyph unicode="u" horiz-adv-x="61.083984" d="M41.3125 0 L41.3125 7.7656 Q38.4844 3.6094 33.8672 1.2188 Q29.25 -1.1719 24.125 -1.1719 Q18.8906 -1.1719 14.7422 1.125 Q10.5938 3.4219 8.7422 7.5703 Q6.8906 11.7188 6.8906 19.0469 L6.8906 51.8594 L20.6094 51.8594 L20.6094 28.0312 Q20.6094 17.0938 21.3672 14.625 Q22.125 12.1562 24.125 10.7188 Q26.125 9.2812 29.2031 9.2812 Q32.7188 9.2812 35.5 11.2109 Q38.2812 13.1406 39.3047 15.9922 Q40.3281 18.8438 40.3281 29.9844 L40.3281 51.8594 L54.0469 51.8594 L54.0469 0 L41.3125 0 Z"
/><glyph unicode="p" horiz-adv-x="61.083984" d="M6.7812 51.8594 L19.5781 51.8594 L19.5781 44.2344 Q22.0781 48.1406 26.3203 50.5859 Q30.5625 53.0312 35.75 53.0312 Q44.7812 53.0312 51.0781 45.9531 Q57.375 38.875 57.375 26.2188 Q57.375 13.2344 51.0234 6.0312 Q44.6719 -1.1719 35.6406 -1.1719 Q31.3438 -1.1719 27.8516 0.5391 Q24.3594 2.25 20.5156 6.3906 L20.5156 -19.7344 L6.7812 -19.7344 L6.7812 51.8594 ZM20.3594 26.8125 Q20.3594 18.0625 23.8281 13.8906 Q27.2969 9.7188 32.2812 9.7188 Q37.0625 9.7188 40.2344 13.5547 Q43.4062 17.3906 43.4062 26.125 Q43.4062 34.2812 40.1328 38.2344 Q36.8594 42.1875 32.0312 42.1875 Q27 42.1875 23.6797 38.3047 Q20.3594 34.4219 20.3594 26.8125 Z"
/><glyph unicode="m" horiz-adv-x="88.916016" d="M6.1562 51.8594 L18.7969 51.8594 L18.7969 44.7812 Q25.5938 53.0312 34.9688 53.0312 Q39.9375 53.0312 43.6016 50.9766 Q47.2656 48.9219 49.6094 44.7812 Q53.0312 48.9219 56.9844 50.9766 Q60.9375 53.0312 65.4375 53.0312 Q71.1406 53.0312 75.0938 50.7109 Q79.0469 48.3906 81 43.8906 Q82.4219 40.5781 82.4219 33.1562 L82.4219 0 L68.7031 0 L68.7031 29.6406 Q68.7031 37.3594 67.2812 39.5938 Q65.375 42.5312 61.4219 42.5312 Q58.5469 42.5312 56.0078 40.7734 Q53.4688 39.0156 52.3438 35.625 Q51.2188 32.2344 51.2188 24.9062 L51.2188 0 L37.5 0 L37.5 28.4219 Q37.5 35.9844 36.7656 38.1797 Q36.0312 40.375 34.4922 41.4531 Q32.9531 42.5312 30.3281 42.5312 Q27.1562 42.5312 24.6172 40.8203 Q22.0781 39.1094 20.9766 35.8906 Q19.875 32.6719 19.875 25.2031 L19.875 0 L6.1562 0 L6.1562 51.8594 Z"
/><glyph unicode="I" horiz-adv-x="27.783203" d="M6.8438 0 L6.8438 71.5781 L21.2969 71.5781 L21.2969 0 L6.8438 0 Z"
/></font
></defs
><g style="fill:white; stroke:white;"
><rect x="0" y="0" width="560" style="clip-path:url(#clipPath1); stroke:none;" height="420"
/></g
><g style="fill:white; text-rendering:optimizeSpeed; color-rendering:optimizeSpeed; image-rendering:optimizeSpeed; shape-rendering:crispEdges; stroke:white; color-interpolation:sRGB;"
><rect x="0" width="560" height="420" y="0" style="stroke:none;"
/><path style="stroke:none;" d="M73 374 L507 374 L507 31 L73 31 Z"
/></g
><g style="fill:rgb(38,38,38); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(38,38,38); color-interpolation:linearRGB; stroke-width:0.6667;"
><line y2="31" style="fill:none;" x1="73" x2="73" y1="374"
/><line y2="31" style="fill:none;" x1="507" x2="507" y1="374"
/><line y2="374" style="fill:none;" x1="73" x2="77.34" y1="374"
/><line y2="325" style="fill:none;" x1="73" x2="77.34" y1="325"
/><line y2="276" style="fill:none;" x1="73" x2="77.34" y1="276"
/><line y2="227" style="fill:none;" x1="73" x2="77.34" y1="227"
/><line y2="178" style="fill:none;" x1="73" x2="77.34" y1="178"
/><line y2="129" style="fill:none;" x1="73" x2="77.34" y1="129"
/><line y2="80" style="fill:none;" x1="73" x2="77.34" y1="80"
/><line y2="31" style="fill:none;" x1="73" x2="77.34" y1="31"
/><line y2="374" style="fill:none;" x1="507" x2="502.66" y1="374"
/><line y2="325" style="fill:none;" x1="507" x2="502.66" y1="325"
/><line y2="276" style="fill:none;" x1="507" x2="502.66" y1="276"
/><line y2="227" style="fill:none;" x1="507" x2="502.66" y1="227"
/><line y2="178" style="fill:none;" x1="507" x2="502.66" y1="178"
/><line y2="129" style="fill:none;" x1="507" x2="502.66" y1="129"
/><line y2="80" style="fill:none;" x1="507" x2="502.66" y1="80"
/><line y2="31" style="fill:none;" x1="507" x2="502.66" y1="31"
/></g
><g transform="translate(67.6667,374)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-23" xml:space="preserve" y="5.5" style="stroke:none;"
>-0.1</text
></g
><g transform="translate(67.6667,325)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-8" xml:space="preserve" y="5.5" style="stroke:none;"
>0</text
></g
><g transform="translate(67.6667,276)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-19" xml:space="preserve" y="5.5" style="stroke:none;"
>0.1</text
></g
><g transform="translate(67.6667,227)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-19" xml:space="preserve" y="5.5" style="stroke:none;"
>0.2</text
></g
><g transform="translate(67.6667,178)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-19" xml:space="preserve" y="5.5" style="stroke:none;"
>0.3</text
></g
><g transform="translate(67.6667,129)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-19" xml:space="preserve" y="5.5" style="stroke:none;"
>0.4</text
></g
><g transform="translate(67.6667,80)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-19" xml:space="preserve" y="5.5" style="stroke:none;"
>0.5</text
></g
><g transform="translate(67.6667,31)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-19" xml:space="preserve" y="5.5" style="stroke:none;"
>0.6</text
></g
><g transform="translate(40.6667,202.4998) rotate(-90)" style="font-size:14.6667px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-33" xml:space="preserve" y="-4" style="stroke:none;"
>Amplitude</text
></g
><g transform="translate(290.0003,28.25)" style="font-size:14.6667px; text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; font-weight:bold;"
><text x="-65" xml:space="preserve" y="-4" style="stroke:none;"
>Impulse Response</text
></g
><g style="stroke-linecap:butt; fill:rgb(38,38,38); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(38,38,38); color-interpolation:linearRGB; stroke-width:0.6667;"
><line y2="325" style="fill:none;" x1="73" x2="507" y1="325"
/><line x1="73" x2="73" y1="325" style="fill:none; stroke:rgb(0,114,189);" y2="334.1989"
/><line x1="91.0833" x2="91.0833" y1="325" style="fill:none; stroke:rgb(0,114,189);" y2="323.5233"
/><line x1="109.1667" x2="109.1667" y1="325" style="fill:none; stroke:rgb(0,114,189);" y2="308.9882"
/><line x1="127.25" x2="127.25" y1="325" style="fill:none; stroke:rgb(0,114,189);" y2="301.9241"
/><line x1="145.3333" x2="145.3333" y1="325" style="fill:none; stroke:rgb(0,114,189);" y2="311.9907"
/><line x1="163.4167" x2="163.4167" y1="325" style="fill:none; stroke:rgb(0,114,189);" y2="338.4859"
/><line x1="181.5" x2="181.5" y1="325" style="fill:none; stroke:rgb(0,114,189);" y2="366.7602"
/><line x1="199.5833" x2="199.5833" y1="325" style="fill:none; stroke:rgb(0,114,189);" y2="373.7292"
/><line x1="217.6667" x2="217.6667" y1="325" style="fill:none; stroke:rgb(0,114,189);" y2="340.7522"
/><line x1="235.75" x2="235.75" y1="325" style="fill:none; stroke:rgb(0,114,189);" y2="266.6718"
/><line x1="253.8333" x2="253.8333" y1="325" style="fill:none; stroke:rgb(0,114,189);" y2="172.5236"
/><line x1="271.9167" x2="271.9167" y1="325" style="fill:none; stroke:rgb(0,114,189);" y2="93.7181"
/><line x1="290" x2="290" y1="325" style="fill:none; stroke:rgb(0,114,189);" y2="63.0303"
/><line x1="308.0833" x2="308.0833" y1="325" style="fill:none; stroke:rgb(0,114,189);" y2="93.7181"
/><line x1="326.1667" x2="326.1667" y1="325" style="fill:none; stroke:rgb(0,114,189);" y2="172.5236"
/><line x1="344.25" x2="344.25" y1="325" style="fill:none; stroke:rgb(0,114,189);" y2="266.6718"
/><line x1="362.3333" x2="362.3333" y1="325" style="fill:none; stroke:rgb(0,114,189);" y2="340.7522"
/><line x1="380.4167" x2="380.4167" y1="325" style="fill:none; stroke:rgb(0,114,189);" y2="373.7292"
/><line x1="398.5" x2="398.5" y1="325" style="fill:none; stroke:rgb(0,114,189);" y2="366.7602"
/><line x1="416.5833" x2="416.5833" y1="325" style="fill:none; stroke:rgb(0,114,189);" y2="338.4859"
/><line x1="434.6667" x2="434.6667" y1="325" style="fill:none; stroke:rgb(0,114,189);" y2="311.9907"
/><line x1="452.75" x2="452.75" y1="325" style="fill:none; stroke:rgb(0,114,189);" y2="301.9241"
/><line x1="470.8333" x2="470.8333" y1="325" style="fill:none; stroke:rgb(0,114,189);" y2="308.9882"
/><line x1="488.9167" x2="488.9167" y1="325" style="fill:none; stroke:rgb(0,114,189);" y2="323.5233"
/><line x1="507" x2="507" y1="325" style="fill:none; stroke:rgb(0,114,189);" y2="334.1989"
/></g
><g transform="translate(73,334.1989)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(73,334.1989)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(91.0833,323.5233)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(91.0833,323.5233)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(109.1667,308.9882)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(109.1667,308.9882)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(127.25,301.9241)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(127.25,301.9241)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(145.3333,311.9907)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(145.3333,311.9907)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(163.4167,338.4859)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(163.4167,338.4859)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(181.5,366.7602)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(181.5,366.7602)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(199.5833,373.7292)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(199.5833,373.7292)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(217.6667,340.7522)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(217.6667,340.7522)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(235.75,266.6718)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(235.75,266.6718)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(253.8333,172.5236)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(253.8333,172.5236)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(271.9167,93.7181)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(271.9167,93.7181)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(290,63.0303)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(290,63.0303)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(308.0833,93.7181)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(308.0833,93.7181)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(326.1667,172.5236)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(326.1667,172.5236)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(344.25,266.6718)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(344.25,266.6718)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(362.3333,340.7522)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(362.3333,340.7522)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(380.4167,373.7292)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(380.4167,373.7292)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(398.5,366.7602)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(398.5,366.7602)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(416.5833,338.4859)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(416.5833,338.4859)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(434.6667,311.9907)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(434.6667,311.9907)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(452.75,301.9241)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(452.75,301.9241)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(470.8333,308.9882)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(470.8333,308.9882)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(488.9167,323.5233)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(488.9167,323.5233)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(507,334.1989)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(507,334.1989)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/><line transform="translate(-507,-334.1989)" x1="73" x2="507" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="374"
/><line transform="translate(-507,-334.1989)" x1="73" x2="507" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="31"
/><line transform="translate(-507,-334.1989)" x1="73" x2="73" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="369.66"
/><line transform="translate(-507,-334.1989)" x1="163.4167" x2="163.4167" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="369.66"
/><line transform="translate(-507,-334.1989)" x1="253.8333" x2="253.8333" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="369.66"
/><line transform="translate(-507,-334.1989)" x1="344.25" x2="344.25" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="369.66"
/><line transform="translate(-507,-334.1989)" x1="434.6667" x2="434.6667" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="369.66"
/><line transform="translate(-507,-334.1989)" x1="73" x2="73" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="35.34"
/><line transform="translate(-507,-334.1989)" x1="163.4167" x2="163.4167" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="35.34"
/><line transform="translate(-507,-334.1989)" x1="253.8333" x2="253.8333" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="35.34"
/><line transform="translate(-507,-334.1989)" x1="344.25" x2="344.25" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="35.34"
/><line transform="translate(-507,-334.1989)" x1="434.6667" x2="434.6667" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="35.34"
/></g
><g transform="translate(73,379.3333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-4" xml:space="preserve" y="14" style="stroke:none;"
>0</text
></g
><g transform="translate(163.4167,379.3333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-4" xml:space="preserve" y="14" style="stroke:none;"
>5</text
></g
><g transform="translate(253.8333,379.3333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-7.5" xml:space="preserve" y="14" style="stroke:none;"
>10</text
></g
><g transform="translate(344.25,379.3333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-7.5" xml:space="preserve" y="14" style="stroke:none;"
>15</text
></g
><g transform="translate(434.6667,379.3333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-7.5" xml:space="preserve" y="14" style="stroke:none;"
>20</text
></g
><g transform="translate(290.0002,397.6667)" style="font-size:14.6667px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-38.5" xml:space="preserve" y="15" style="stroke:none;"
>n (samples)</text
></g
></g
></svg
>

After

Width:  |  Height:  |  Size: 56 KiB

@@ -0,0 +1,273 @@
<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.0//EN'
'http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd'>
<svg xmlns:xlink="http://www.w3.org/1999/xlink" style="fill-opacity:1; color-rendering:auto; color-interpolation:auto; text-rendering:auto; stroke:black; stroke-linecap:square; stroke-miterlimit:10; shape-rendering:auto; stroke-opacity:1; fill:black; stroke-dasharray:none; font-weight:normal; stroke-width:1; font-family:'Dialog'; font-style:normal; stroke-linejoin:miter; font-size:12px; stroke-dashoffset:0; image-rendering:auto;" width="560" height="420" xmlns="http://www.w3.org/2000/svg"
><!--Generated by the Batik Graphics2D SVG Generator--><defs id="genericDefs"
/><g
><defs id="defs1"
><clipPath clipPathUnits="userSpaceOnUse" id="clipPath1"
><path d="M0 0 L560 0 L560 420 L0 420 L0 0 Z"
/></clipPath
><font horiz-adv-x="75.0" id="font1"
><font-face ascent="100.53711" descent="21.972656" units-per-em="100" style="font-style:normal; font-family:Dialog; font-weight:normal;"
/><missing-glyph horiz-adv-x="75.0" d="M12.5 0 L12.5 62.5 L62.5 62.5 L62.5 0 L12.5 0 ZM14.0625 1.5625 L60.9375 1.5625 L60.9375 60.9375 L14.0625 60.9375 L14.0625 1.5625 Z"
/><glyph unicode="2" horiz-adv-x="55.615234" d="M50.3438 8.4531 L50.3438 0 L3.0312 0 Q2.9375 3.1719 4.0469 6.1094 Q5.8594 10.9375 9.8359 15.625 Q13.8125 20.3125 21.3438 26.4688 Q33.0156 36.0312 37.1172 41.625 Q41.2188 47.2188 41.2188 52.2031 Q41.2188 57.4219 37.4766 61.0078 Q33.7344 64.5938 27.7344 64.5938 Q21.3906 64.5938 17.5781 60.7891 Q13.7656 56.9844 13.7188 50.25 L4.6875 51.1719 Q5.6094 61.2812 11.6641 66.5781 Q17.7188 71.875 27.9375 71.875 Q38.2344 71.875 44.2422 66.1641 Q50.25 60.4531 50.25 52 Q50.25 47.7031 48.4922 43.5547 Q46.7344 39.4062 42.6562 34.8125 Q38.5781 30.2188 29.1094 22.2188 Q21.1875 15.5781 18.9453 13.2109 Q16.7031 10.8438 15.2344 8.4531 L50.3438 8.4531 Z"
/><glyph unicode="." horiz-adv-x="27.783203" d="M9.0781 0 L9.0781 10.0156 L19.0938 10.0156 L19.0938 0 L9.0781 0 Z"
/><glyph unicode="0" horiz-adv-x="55.615234" d="M4.1562 35.2969 Q4.1562 48 6.7656 55.7422 Q9.375 63.4844 14.5234 67.6797 Q19.6719 71.875 27.4844 71.875 Q33.25 71.875 37.5938 69.5547 Q41.9375 67.2344 44.7734 62.8672 Q47.6094 58.5 49.2188 52.2266 Q50.8281 45.9531 50.8281 35.2969 Q50.8281 22.7031 48.2422 14.9688 Q45.6562 7.2344 40.5078 3.0078 Q35.3594 -1.2188 27.4844 -1.2188 Q17.1406 -1.2188 11.2344 6.2031 Q4.1562 15.1406 4.1562 35.2969 ZM13.1875 35.2969 Q13.1875 17.6719 17.3125 11.8359 Q21.4375 6 27.4844 6 Q33.5469 6 37.6719 11.8594 Q41.7969 17.7188 41.7969 35.2969 Q41.7969 52.9844 37.6719 58.7891 Q33.5469 64.5938 27.3906 64.5938 Q21.3438 64.5938 17.7188 59.4688 Q13.1875 52.9375 13.1875 35.2969 Z"
/><glyph unicode="-" horiz-adv-x="33.30078" d="M3.1719 21.4844 L3.1719 30.3281 L30.1719 30.3281 L30.1719 21.4844 L3.1719 21.4844 Z"
/><glyph unicode="1" horiz-adv-x="55.615234" d="M37.25 0 L28.4688 0 L28.4688 56 Q25.2969 52.9844 20.1406 49.9531 Q14.9844 46.9219 10.8906 45.4062 L10.8906 53.9062 Q18.2656 57.375 23.7812 62.3047 Q29.2969 67.2344 31.5938 71.875 L37.25 71.875 L37.25 0 Z"
/><glyph unicode="3" horiz-adv-x="55.615234" d="M4.2031 18.8906 L12.9844 20.0625 Q14.5 12.5938 18.1406 9.2969 Q21.7812 6 27 6 Q33.2031 6 37.4766 10.2969 Q41.75 14.5938 41.75 20.9531 Q41.75 27 37.7969 30.9297 Q33.8438 34.8594 27.7344 34.8594 Q25.25 34.8594 21.5312 33.8906 L22.5156 41.6094 Q23.3906 41.5 23.9219 41.5 Q29.5469 41.5 34.0391 44.4297 Q38.5312 47.3594 38.5312 53.4688 Q38.5312 58.2969 35.2578 61.4766 Q31.9844 64.6562 26.8125 64.6562 Q21.6875 64.6562 18.2656 61.4297 Q14.8438 58.2031 13.875 51.7656 L5.0781 53.3281 Q6.6875 62.1562 12.3984 67.0156 Q18.1094 71.875 26.6094 71.875 Q32.4688 71.875 37.3984 69.3594 Q42.3281 66.8438 44.9453 62.5 Q47.5625 58.1562 47.5625 53.2656 Q47.5625 48.6406 45.0703 44.8281 Q42.5781 41.0156 37.7031 38.7656 Q44.0469 37.3125 47.5625 32.6953 Q51.0781 28.0781 51.0781 21.1406 Q51.0781 11.7656 44.2422 5.25 Q37.4062 -1.2656 26.9531 -1.2656 Q17.5312 -1.2656 11.3047 4.3516 Q5.0781 9.9688 4.2031 18.8906 Z"
/><glyph unicode="4" horiz-adv-x="55.615234" d="M32.3281 0 L32.3281 17.1406 L1.2656 17.1406 L1.2656 25.2031 L33.9375 71.5781 L41.1094 71.5781 L41.1094 25.2031 L50.7812 25.2031 L50.7812 17.1406 L41.1094 17.1406 L41.1094 0 L32.3281 0 ZM32.3281 25.2031 L32.3281 57.4688 L9.9062 25.2031 L32.3281 25.2031 Z"
/><glyph unicode="5" horiz-adv-x="55.615234" d="M4.1562 18.75 L13.375 19.5312 Q14.4062 12.7969 18.1406 9.3984 Q21.875 6 27.1562 6 Q33.5 6 37.8906 10.7891 Q42.2812 15.5781 42.2812 23.4844 Q42.2812 31 38.0625 35.3516 Q33.8438 39.7031 27 39.7031 Q22.75 39.7031 19.3359 37.7734 Q15.9219 35.8438 13.9688 32.7656 L5.7188 33.8438 L12.6406 70.6094 L48.25 70.6094 L48.25 62.2031 L19.6719 62.2031 L15.8281 42.9688 Q22.2656 47.4688 29.3438 47.4688 Q38.7188 47.4688 45.1641 40.9688 Q51.6094 34.4688 51.6094 24.2656 Q51.6094 14.5469 45.9531 7.4688 Q39.0625 -1.2188 27.1562 -1.2188 Q17.3906 -1.2188 11.2109 4.25 Q5.0312 9.7188 4.1562 18.75 Z"
/><glyph unicode="6" horiz-adv-x="55.615234" d="M49.75 54.0469 L41.0156 53.375 Q39.8438 58.5469 37.7031 60.8906 Q34.125 64.6562 28.9062 64.6562 Q24.7031 64.6562 21.5312 62.3125 Q17.3906 59.2812 14.9922 53.4688 Q12.5938 47.6562 12.5 36.9219 Q15.6719 41.75 20.2656 44.0938 Q24.8594 46.4375 29.8906 46.4375 Q38.6719 46.4375 44.8516 39.9688 Q51.0312 33.5 51.0312 23.25 Q51.0312 16.5 48.125 10.7188 Q45.2188 4.9375 40.1406 1.8594 Q35.0625 -1.2188 28.6094 -1.2188 Q17.625 -1.2188 10.6953 6.8594 Q3.7656 14.9375 3.7656 33.5 Q3.7656 54.25 11.4219 63.6719 Q18.1094 71.875 29.4375 71.875 Q37.8906 71.875 43.2891 67.1406 Q48.6875 62.4062 49.75 54.0469 ZM13.875 23.1875 Q13.875 18.6562 15.7969 14.5078 Q17.7188 10.3594 21.1875 8.1797 Q24.6562 6 28.4688 6 Q34.0312 6 38.0391 10.4922 Q42.0469 14.9844 42.0469 22.7031 Q42.0469 30.125 38.0859 34.3984 Q34.125 38.6719 28.125 38.6719 Q22.1719 38.6719 18.0234 34.3984 Q13.875 30.125 13.875 23.1875 Z"
/><glyph unicode="e" horiz-adv-x="55.615234" d="M42.0938 16.7031 L51.1719 15.5781 Q49.0312 7.625 43.2188 3.2266 Q37.4062 -1.1719 28.375 -1.1719 Q17 -1.1719 10.3281 5.8359 Q3.6562 12.8438 3.6562 25.4844 Q3.6562 38.5781 10.3984 45.8047 Q17.1406 53.0312 27.875 53.0312 Q38.2812 53.0312 44.875 45.9531 Q51.4688 38.875 51.4688 26.0312 Q51.4688 25.25 51.4219 23.6875 L12.75 23.6875 Q13.2344 15.1406 17.5781 10.6016 Q21.9219 6.0625 28.4219 6.0625 Q33.25 6.0625 36.6719 8.6016 Q40.0938 11.1406 42.0938 16.7031 ZM13.2344 30.9062 L42.1875 30.9062 Q41.6094 37.4531 38.875 40.7188 Q34.6719 45.7969 27.9844 45.7969 Q21.9219 45.7969 17.7969 41.75 Q13.6719 37.7031 13.2344 30.9062 Z"
/><glyph unicode="d" horiz-adv-x="55.615234" d="M40.2344 0 L40.2344 6.5469 Q35.2969 -1.1719 25.7344 -1.1719 Q19.5312 -1.1719 14.3281 2.25 Q9.125 5.6719 6.2734 11.7969 Q3.4219 17.9219 3.4219 25.875 Q3.4219 33.6406 6.0078 39.9688 Q8.5938 46.2969 13.7734 49.6641 Q18.9531 53.0312 25.3438 53.0312 Q30.0312 53.0312 33.6953 51.0547 Q37.3594 49.0781 39.6562 45.9062 L39.6562 71.5781 L48.3906 71.5781 L48.3906 0 L40.2344 0 ZM12.4531 25.875 Q12.4531 15.9219 16.6484 10.9922 Q20.8438 6.0625 26.5625 6.0625 Q32.3281 6.0625 36.3516 10.7734 Q40.375 15.4844 40.375 25.1406 Q40.375 35.7969 36.2734 40.7734 Q32.1719 45.75 26.1719 45.75 Q20.3125 45.75 16.3828 40.9688 Q12.4531 36.1875 12.4531 25.875 Z"
/><glyph unicode="u" horiz-adv-x="55.615234" d="M40.5781 0 L40.5781 7.625 Q34.5156 -1.1719 24.125 -1.1719 Q19.5312 -1.1719 15.5547 0.5859 Q11.5781 2.3438 9.6484 5.0078 Q7.7188 7.6719 6.9375 11.5312 Q6.3906 14.1094 6.3906 19.7344 L6.3906 51.8594 L15.1875 51.8594 L15.1875 23.0938 Q15.1875 16.2188 15.7188 13.8125 Q16.5469 10.3594 19.2344 8.375 Q21.9219 6.3906 25.875 6.3906 Q29.8281 6.3906 33.2969 8.4219 Q36.7656 10.4531 38.2109 13.9453 Q39.6562 17.4375 39.6562 24.0781 L39.6562 51.8594 L48.4375 51.8594 L48.4375 0 L40.5781 0 Z"
/><glyph unicode="t" horiz-adv-x="27.783203" d="M25.7812 7.8594 L27.0469 0.0938 Q23.3438 -0.6875 20.4062 -0.6875 Q15.625 -0.6875 12.9922 0.8281 Q10.3594 2.3438 9.2812 4.8125 Q8.2031 7.2812 8.2031 15.1875 L8.2031 45.0156 L1.7656 45.0156 L1.7656 51.8594 L8.2031 51.8594 L8.2031 64.7031 L16.9375 69.9688 L16.9375 51.8594 L25.7812 51.8594 L25.7812 45.0156 L16.9375 45.0156 L16.9375 14.7031 Q16.9375 10.9375 17.4062 9.8672 Q17.875 8.7969 18.9219 8.1562 Q19.9688 7.5156 21.9219 7.5156 Q23.3906 7.5156 25.7812 7.8594 Z"
/><glyph unicode="i" horiz-adv-x="22.216797" d="M6.6406 61.4688 L6.6406 71.5781 L15.4375 71.5781 L15.4375 61.4688 L6.6406 61.4688 ZM6.6406 0 L6.6406 51.8594 L15.4375 51.8594 L15.4375 0 L6.6406 0 Z"
/><glyph unicode="l" horiz-adv-x="22.216797" d="M6.3906 0 L6.3906 71.5781 L15.1875 71.5781 L15.1875 0 L6.3906 0 Z"
/><glyph unicode="p" horiz-adv-x="55.615234" d="M6.5938 -19.875 L6.5938 51.8594 L14.5938 51.8594 L14.5938 45.125 Q17.4375 49.0781 21 51.0547 Q24.5625 53.0312 29.6406 53.0312 Q36.2812 53.0312 41.3594 49.6094 Q46.4375 46.1875 49.0234 39.9609 Q51.6094 33.7344 51.6094 26.3125 Q51.6094 18.3594 48.7578 11.9844 Q45.9062 5.6094 40.4609 2.2188 Q35.0156 -1.1719 29 -1.1719 Q24.6094 -1.1719 21.1172 0.6875 Q17.625 2.5469 15.375 5.375 L15.375 -19.875 L6.5938 -19.875 ZM14.5469 25.6406 Q14.5469 15.625 18.6016 10.8438 Q22.6562 6.0625 28.4219 6.0625 Q34.2812 6.0625 38.4531 11.0156 Q42.625 15.9688 42.625 26.375 Q42.625 36.2812 38.5469 41.2109 Q34.4688 46.1406 28.8125 46.1406 Q23.1875 46.1406 18.8672 40.8906 Q14.5469 35.6406 14.5469 25.6406 Z"
/><glyph unicode="m" horiz-adv-x="83.30078" d="M6.5938 0 L6.5938 51.8594 L14.4531 51.8594 L14.4531 44.5781 Q16.8906 48.3906 20.9453 50.7109 Q25 53.0312 30.1719 53.0312 Q35.9375 53.0312 39.625 50.6406 Q43.3125 48.25 44.8281 43.9531 Q50.9844 53.0312 60.8438 53.0312 Q68.5625 53.0312 72.7109 48.7578 Q76.8594 44.4844 76.8594 35.5938 L76.8594 0 L68.1094 0 L68.1094 32.6719 Q68.1094 37.9375 67.2578 40.2578 Q66.4062 42.5781 64.1641 43.9922 Q61.9219 45.4062 58.8906 45.4062 Q53.4219 45.4062 49.8047 41.7734 Q46.1875 38.1406 46.1875 30.125 L46.1875 0 L37.4062 0 L37.4062 33.6875 Q37.4062 39.5469 35.2578 42.4766 Q33.1094 45.4062 28.2188 45.4062 Q24.5156 45.4062 21.3672 43.4531 Q18.2188 41.5 16.7969 37.7422 Q15.375 33.9844 15.375 26.9062 L15.375 0 L6.5938 0 Z"
/><glyph unicode="A" horiz-adv-x="66.69922" d="M-0.1406 0 L27.3438 71.5781 L37.5469 71.5781 L66.8438 0 L56.0625 0 L47.7031 21.6875 L17.7812 21.6875 L9.9062 0 L-0.1406 0 ZM20.5156 29.3906 L44.7812 29.3906 L37.3125 49.2188 Q33.8906 58.25 32.2344 64.0625 Q30.8594 57.1719 28.375 50.3906 L20.5156 29.3906 Z"
/><glyph unicode="8" horiz-adv-x="55.615234" d="M17.6719 38.8125 Q12.2031 40.8281 9.5703 44.5391 Q6.9375 48.25 6.9375 53.4219 Q6.9375 61.2344 12.5547 66.5547 Q18.1719 71.875 27.4844 71.875 Q36.8594 71.875 42.5781 66.4297 Q48.2969 60.9844 48.2969 53.1719 Q48.2969 48.1875 45.6797 44.5078 Q43.0625 40.8281 37.75 38.8125 Q44.3438 36.6719 47.7812 31.8828 Q51.2188 27.0938 51.2188 20.4531 Q51.2188 11.2812 44.7266 5.0312 Q38.2344 -1.2188 27.6406 -1.2188 Q17.0469 -1.2188 10.5469 5.0547 Q4.0469 11.3281 4.0469 20.7031 Q4.0469 27.6875 7.5938 32.3984 Q11.1406 37.1094 17.6719 38.8125 ZM15.9219 53.7188 Q15.9219 48.6406 19.1953 45.4141 Q22.4688 42.1875 27.6875 42.1875 Q32.7656 42.1875 36.0156 45.3828 Q39.2656 48.5781 39.2656 53.2188 Q39.2656 58.0625 35.9141 61.3594 Q32.5625 64.6562 27.5938 64.6562 Q22.5625 64.6562 19.2422 61.4297 Q15.9219 58.2031 15.9219 53.7188 ZM13.0938 20.6562 Q13.0938 16.8906 14.875 13.375 Q16.6562 9.8594 20.1719 7.9297 Q23.6875 6 27.7344 6 Q34.0312 6 38.1328 10.0547 Q42.2344 14.1094 42.2344 20.3594 Q42.2344 26.7031 38.0156 30.8594 Q33.7969 35.0156 27.4375 35.0156 Q21.2344 35.0156 17.1641 30.9141 Q13.0938 26.8125 13.0938 20.6562 Z"
/><glyph unicode=")" horiz-adv-x="33.30078" d="M12.3594 -21.0469 L6.0625 -21.0469 Q20.6562 2.3906 20.6562 25.875 Q20.6562 35.0625 18.5625 44.0938 Q16.8906 51.4219 13.9219 58.1562 Q12.0156 62.5469 6.0625 72.7969 L12.3594 72.7969 Q21.5312 60.5469 25.9219 48.1875 Q29.6875 37.5469 29.6875 25.9219 Q29.6875 12.75 24.6328 0.4453 Q19.5781 -11.8594 12.3594 -21.0469 Z"
/><glyph unicode="a" horiz-adv-x="55.615234" d="M40.4375 6.3906 Q35.5469 2.25 31.0312 0.5391 Q26.5156 -1.1719 21.3438 -1.1719 Q12.7969 -1.1719 8.2031 3 Q3.6094 7.1719 3.6094 13.6719 Q3.6094 17.4844 5.3438 20.6328 Q7.0781 23.7812 9.8906 25.6875 Q12.7031 27.5938 16.2188 28.5625 Q18.7969 29.25 24.0312 29.8906 Q34.6719 31.1562 39.7031 32.9062 Q39.75 34.7188 39.75 35.2031 Q39.75 40.5781 37.25 42.7812 Q33.8906 45.75 27.25 45.75 Q21.0469 45.75 18.0938 43.5781 Q15.1406 41.4062 13.7188 35.8906 L5.125 37.0625 Q6.2969 42.5781 8.9844 45.9688 Q11.6719 49.3594 16.75 51.1953 Q21.8281 53.0312 28.5156 53.0312 Q35.1562 53.0312 39.3047 51.4688 Q43.4531 49.9062 45.4062 47.5391 Q47.3594 45.1719 48.1406 41.5469 Q48.5781 39.3125 48.5781 33.4531 L48.5781 21.7344 Q48.5781 9.4688 49.1406 6.2266 Q49.7031 2.9844 51.375 0 L42.1875 0 Q40.8281 2.7344 40.4375 6.3906 ZM39.7031 26.0312 Q34.9062 24.0781 25.3438 22.7031 Q19.9219 21.9219 17.6797 20.9453 Q15.4375 19.9688 14.2109 18.0938 Q12.9844 16.2188 12.9844 13.9219 Q12.9844 10.4062 15.6484 8.0625 Q18.3125 5.7188 23.4375 5.7188 Q28.5156 5.7188 32.4688 7.9375 Q36.4219 10.1562 38.2812 14.0156 Q39.7031 17 39.7031 22.7969 L39.7031 26.0312 Z"
/><glyph unicode="s" horiz-adv-x="50.0" d="M3.0781 15.4844 L11.7656 16.8438 Q12.5 11.625 15.8438 8.8438 Q19.1875 6.0625 25.2031 6.0625 Q31.25 6.0625 34.1797 8.5234 Q37.1094 10.9844 37.1094 14.3125 Q37.1094 17.2812 34.5156 19 Q32.7188 20.1719 25.5312 21.9688 Q15.875 24.4219 12.1406 26.2031 Q8.4062 27.9844 6.4766 31.1328 Q4.5469 34.2812 4.5469 38.0938 Q4.5469 41.5469 6.1328 44.5078 Q7.7188 47.4688 10.4531 49.4219 Q12.5 50.9219 16.0391 51.9766 Q19.5781 53.0312 23.6406 53.0312 Q29.7344 53.0312 34.3516 51.2734 Q38.9688 49.5156 41.1641 46.5078 Q43.3594 43.5 44.1875 38.4844 L35.5938 37.3125 Q35.0156 41.3125 32.2031 43.5547 Q29.3906 45.7969 24.2656 45.7969 Q18.2188 45.7969 15.625 43.7969 Q13.0312 41.7969 13.0312 39.1094 Q13.0312 37.4062 14.1094 36.0312 Q15.1875 34.625 17.4844 33.6875 Q18.7969 33.2031 25.25 31.4531 Q34.5781 28.9531 38.2578 27.3672 Q41.9375 25.7812 44.0391 22.7578 Q46.1406 19.7344 46.1406 15.2344 Q46.1406 10.8438 43.5781 6.9609 Q41.0156 3.0781 36.1797 0.9531 Q31.3438 -1.1719 25.25 -1.1719 Q15.1406 -1.1719 9.8438 3.0312 Q4.5469 7.2344 3.0781 15.4844 Z"
/><glyph unicode="(" horiz-adv-x="33.30078" d="M23.3906 -21.0469 Q16.1094 -11.8594 11.0859 0.4453 Q6.0625 12.75 6.0625 25.9219 Q6.0625 37.5469 9.8125 48.1875 Q14.2031 60.5469 23.3906 72.7969 L29.6875 72.7969 Q23.7812 62.6406 21.875 58.2969 Q18.8906 51.5625 17.1875 44.2344 Q15.0938 35.1094 15.0938 25.875 Q15.0938 2.3906 29.6875 -21.0469 L23.3906 -21.0469 Z"
/><glyph unicode=" " horiz-adv-x="27.783203" d=""
/><glyph unicode="n" horiz-adv-x="55.615234" d="M6.5938 0 L6.5938 51.8594 L14.5 51.8594 L14.5 44.4844 Q20.2188 53.0312 31 53.0312 Q35.6875 53.0312 39.625 51.3438 Q43.5625 49.6562 45.5156 46.9219 Q47.4688 44.1875 48.25 40.4375 Q48.7344 37.9844 48.7344 31.8906 L48.7344 0 L39.9375 0 L39.9375 31.5469 Q39.9375 36.9219 38.9141 39.5781 Q37.8906 42.2344 35.2812 43.8203 Q32.6719 45.4062 29.1562 45.4062 Q23.5312 45.4062 19.4531 41.8438 Q15.375 38.2812 15.375 28.3281 L15.375 0 L6.5938 0 Z"
/></font
><font horiz-adv-x="75.0" id="font2"
><font-face ascent="100.53711" descent="21.972656" units-per-em="100" style="font-style:normal; font-family:Dialog; font-weight:bold;"
/><missing-glyph horiz-adv-x="75.0" d="M12.5 0 L12.5 62.5 L62.5 62.5 L62.5 0 L12.5 0 ZM14.0625 1.5625 L60.9375 1.5625 L60.9375 60.9375 L14.0625 60.9375 L14.0625 1.5625 Z"
/><glyph unicode="n" horiz-adv-x="61.083984" d="M54.3438 0 L40.625 0 L40.625 26.4688 Q40.625 34.8594 39.75 37.3281 Q38.875 39.7969 36.8906 41.1641 Q34.9062 42.5312 32.125 42.5312 Q28.5625 42.5312 25.7344 40.5781 Q22.9062 38.625 21.8516 35.3984 Q20.7969 32.1719 20.7969 23.4844 L20.7969 0 L7.0781 0 L7.0781 51.8594 L19.8281 51.8594 L19.8281 44.2344 Q26.6094 53.0312 36.9219 53.0312 Q41.4531 53.0312 45.2109 51.3906 Q48.9688 49.75 50.8984 47.2109 Q52.8281 44.6719 53.5859 41.4531 Q54.3438 38.2344 54.3438 32.2344 L54.3438 0 Z"
/><glyph unicode="o" horiz-adv-x="61.083984" d="M4 26.6562 Q4 33.5 7.375 39.8984 Q10.75 46.2969 16.9219 49.6641 Q23.0938 53.0312 30.7188 53.0312 Q42.4844 53.0312 50 45.3906 Q57.5156 37.75 57.5156 26.0781 Q57.5156 14.3125 49.9219 6.5703 Q42.3281 -1.1719 30.8125 -1.1719 Q23.6875 -1.1719 17.2188 2.0547 Q10.75 5.2812 7.375 11.5 Q4 17.7188 4 26.6562 ZM18.0625 25.9219 Q18.0625 18.2188 21.7266 14.1172 Q25.3906 10.0156 30.7656 10.0156 Q36.1406 10.0156 39.7734 14.1172 Q43.4062 18.2188 43.4062 26.0312 Q43.4062 33.6406 39.7734 37.7422 Q36.1406 41.8438 30.7656 41.8438 Q25.3906 41.8438 21.7266 37.7422 Q18.0625 33.6406 18.0625 25.9219 Z"
/><glyph unicode="R" horiz-adv-x="72.2168" d="M7.3281 0 L7.3281 71.5781 L37.75 71.5781 Q49.2188 71.5781 54.4219 69.6484 Q59.625 67.7188 62.75 62.7891 Q65.875 57.8594 65.875 51.5156 Q65.875 43.4531 61.1328 38.2031 Q56.3906 32.9531 46.9688 31.5938 Q51.6562 28.8594 54.7109 25.5859 Q57.7656 22.3125 62.9375 13.9688 L71.6875 0 L54.3906 0 L43.9531 15.5781 Q38.375 23.9219 36.3281 26.0938 Q34.2812 28.2656 31.9844 29.0781 Q29.6875 29.8906 24.7031 29.8906 L21.7812 29.8906 L21.7812 0 L7.3281 0 ZM21.7812 41.3125 L32.4688 41.3125 Q42.875 41.3125 45.4609 42.1875 Q48.0469 43.0625 49.5156 45.2109 Q50.9844 47.3594 50.9844 50.5938 Q50.9844 54.2031 49.0547 56.4219 Q47.125 58.6406 43.6094 59.2344 Q41.8438 59.4688 33.0625 59.4688 L21.7812 59.4688 L21.7812 41.3125 Z"
/><glyph unicode=" " horiz-adv-x="27.783203" d=""
/><glyph unicode="e" horiz-adv-x="55.615234" d="M37.2031 16.5 L50.875 14.2031 Q48.25 6.6875 42.5547 2.7578 Q36.8594 -1.1719 28.3281 -1.1719 Q14.7969 -1.1719 8.2969 7.6719 Q3.1719 14.75 3.1719 25.5312 Q3.1719 38.4219 9.9141 45.7266 Q16.6562 53.0312 26.9531 53.0312 Q38.5312 53.0312 45.2188 45.3906 Q51.9062 37.75 51.6094 21.9688 L17.2344 21.9688 Q17.3906 15.875 20.5625 12.4766 Q23.7344 9.0781 28.4688 9.0781 Q31.6875 9.0781 33.8828 10.8359 Q36.0781 12.5938 37.2031 16.5 ZM37.9844 30.375 Q37.8438 36.3281 34.9141 39.4297 Q31.9844 42.5312 27.7812 42.5312 Q23.2969 42.5312 20.3594 39.2656 Q17.4375 35.9844 17.4844 30.375 L37.9844 30.375 Z"
/><glyph unicode="s" horiz-adv-x="55.615234" d="M2.3438 14.7969 L16.1094 16.8906 Q17 12.8906 19.6797 10.8125 Q22.3594 8.7344 27.2031 8.7344 Q32.5156 8.7344 35.2031 10.6875 Q37.0156 12.0625 37.0156 14.3594 Q37.0156 15.9219 36.0312 16.9375 Q35.0156 17.9219 31.4531 18.75 Q14.8438 22.4062 10.4062 25.4375 Q4.25 29.6406 4.25 37.1094 Q4.25 43.8438 9.5703 48.4375 Q14.8906 53.0312 26.0781 53.0312 Q36.7188 53.0312 41.8984 49.5625 Q47.0781 46.0938 49.0312 39.3125 L36.0781 36.9219 Q35.25 39.9375 32.9297 41.5547 Q30.6094 43.1719 26.3125 43.1719 Q20.9062 43.1719 18.5625 41.6562 Q17 40.5781 17 38.875 Q17 37.4062 18.3594 36.375 Q20.2188 35.0156 31.1797 32.5234 Q42.1406 30.0312 46.4844 26.4219 Q50.7812 22.75 50.7812 16.2188 Q50.7812 9.0781 44.8281 3.9531 Q38.875 -1.1719 27.2031 -1.1719 Q16.6094 -1.1719 10.4297 3.125 Q4.25 7.4219 2.3438 14.7969 Z"
/><glyph unicode="l" horiz-adv-x="27.783203" d="M7.1719 0 L7.1719 71.5781 L20.9062 71.5781 L20.9062 0 L7.1719 0 Z"
/><glyph unicode="u" horiz-adv-x="61.083984" d="M41.3125 0 L41.3125 7.7656 Q38.4844 3.6094 33.8672 1.2188 Q29.25 -1.1719 24.125 -1.1719 Q18.8906 -1.1719 14.7422 1.125 Q10.5938 3.4219 8.7422 7.5703 Q6.8906 11.7188 6.8906 19.0469 L6.8906 51.8594 L20.6094 51.8594 L20.6094 28.0312 Q20.6094 17.0938 21.3672 14.625 Q22.125 12.1562 24.125 10.7188 Q26.125 9.2812 29.2031 9.2812 Q32.7188 9.2812 35.5 11.2109 Q38.2812 13.1406 39.3047 15.9922 Q40.3281 18.8438 40.3281 29.9844 L40.3281 51.8594 L54.0469 51.8594 L54.0469 0 L41.3125 0 Z"
/><glyph unicode="p" horiz-adv-x="61.083984" d="M6.7812 51.8594 L19.5781 51.8594 L19.5781 44.2344 Q22.0781 48.1406 26.3203 50.5859 Q30.5625 53.0312 35.75 53.0312 Q44.7812 53.0312 51.0781 45.9531 Q57.375 38.875 57.375 26.2188 Q57.375 13.2344 51.0234 6.0312 Q44.6719 -1.1719 35.6406 -1.1719 Q31.3438 -1.1719 27.8516 0.5391 Q24.3594 2.25 20.5156 6.3906 L20.5156 -19.7344 L6.7812 -19.7344 L6.7812 51.8594 ZM20.3594 26.8125 Q20.3594 18.0625 23.8281 13.8906 Q27.2969 9.7188 32.2812 9.7188 Q37.0625 9.7188 40.2344 13.5547 Q43.4062 17.3906 43.4062 26.125 Q43.4062 34.2812 40.1328 38.2344 Q36.8594 42.1875 32.0312 42.1875 Q27 42.1875 23.6797 38.3047 Q20.3594 34.4219 20.3594 26.8125 Z"
/><glyph unicode="m" horiz-adv-x="88.916016" d="M6.1562 51.8594 L18.7969 51.8594 L18.7969 44.7812 Q25.5938 53.0312 34.9688 53.0312 Q39.9375 53.0312 43.6016 50.9766 Q47.2656 48.9219 49.6094 44.7812 Q53.0312 48.9219 56.9844 50.9766 Q60.9375 53.0312 65.4375 53.0312 Q71.1406 53.0312 75.0938 50.7109 Q79.0469 48.3906 81 43.8906 Q82.4219 40.5781 82.4219 33.1562 L82.4219 0 L68.7031 0 L68.7031 29.6406 Q68.7031 37.3594 67.2812 39.5938 Q65.375 42.5312 61.4219 42.5312 Q58.5469 42.5312 56.0078 40.7734 Q53.4688 39.0156 52.3438 35.625 Q51.2188 32.2344 51.2188 24.9062 L51.2188 0 L37.5 0 L37.5 28.4219 Q37.5 35.9844 36.7656 38.1797 Q36.0312 40.375 34.4922 41.4531 Q32.9531 42.5312 30.3281 42.5312 Q27.1562 42.5312 24.6172 40.8203 Q22.0781 39.1094 20.9766 35.8906 Q19.875 32.6719 19.875 25.2031 L19.875 0 L6.1562 0 L6.1562 51.8594 Z"
/><glyph unicode="I" horiz-adv-x="27.783203" d="M6.8438 0 L6.8438 71.5781 L21.2969 71.5781 L21.2969 0 L6.8438 0 Z"
/></font
></defs
><g style="fill:white; stroke:white;"
><rect x="0" y="0" width="560" style="clip-path:url(#clipPath1); stroke:none;" height="420"
/></g
><g style="fill:white; text-rendering:optimizeSpeed; color-rendering:optimizeSpeed; image-rendering:optimizeSpeed; shape-rendering:crispEdges; stroke:white; color-interpolation:sRGB;"
><rect x="0" width="560" height="420" y="0" style="stroke:none;"
/><path style="stroke:none;" d="M73 374 L507 374 L507 31 L73 31 Z"
/></g
><g style="fill:rgb(38,38,38); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(38,38,38); color-interpolation:linearRGB; stroke-width:0.6667;"
><line y2="31" style="fill:none;" x1="73" x2="73" y1="374"
/><line y2="31" style="fill:none;" x1="507" x2="507" y1="374"
/><line y2="374" style="fill:none;" x1="73" x2="77.34" y1="374"
/><line y2="331.125" style="fill:none;" x1="73" x2="77.34" y1="331.125"
/><line y2="288.25" style="fill:none;" x1="73" x2="77.34" y1="288.25"
/><line y2="245.375" style="fill:none;" x1="73" x2="77.34" y1="245.375"
/><line y2="202.5" style="fill:none;" x1="73" x2="77.34" y1="202.5"
/><line y2="159.625" style="fill:none;" x1="73" x2="77.34" y1="159.625"
/><line y2="116.75" style="fill:none;" x1="73" x2="77.34" y1="116.75"
/><line y2="73.875" style="fill:none;" x1="73" x2="77.34" y1="73.875"
/><line y2="31" style="fill:none;" x1="73" x2="77.34" y1="31"
/><line y2="374" style="fill:none;" x1="507" x2="502.66" y1="374"
/><line y2="331.125" style="fill:none;" x1="507" x2="502.66" y1="331.125"
/><line y2="288.25" style="fill:none;" x1="507" x2="502.66" y1="288.25"
/><line y2="245.375" style="fill:none;" x1="507" x2="502.66" y1="245.375"
/><line y2="202.5" style="fill:none;" x1="507" x2="502.66" y1="202.5"
/><line y2="159.625" style="fill:none;" x1="507" x2="502.66" y1="159.625"
/><line y2="116.75" style="fill:none;" x1="507" x2="502.66" y1="116.75"
/><line y2="73.875" style="fill:none;" x1="507" x2="502.66" y1="73.875"
/><line y2="31" style="fill:none;" x1="507" x2="502.66" y1="31"
/></g
><g transform="translate(67.6667,374)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-23" xml:space="preserve" y="5.5" style="stroke:none;"
>-0.2</text
></g
><g transform="translate(67.6667,331.125)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-23" xml:space="preserve" y="5.5" style="stroke:none;"
>-0.1</text
></g
><g transform="translate(67.6667,288.25)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-8" xml:space="preserve" y="5.5" style="stroke:none;"
>0</text
></g
><g transform="translate(67.6667,245.375)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-19" xml:space="preserve" y="5.5" style="stroke:none;"
>0.1</text
></g
><g transform="translate(67.6667,202.5)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-19" xml:space="preserve" y="5.5" style="stroke:none;"
>0.2</text
></g
><g transform="translate(67.6667,159.625)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-19" xml:space="preserve" y="5.5" style="stroke:none;"
>0.3</text
></g
><g transform="translate(67.6667,116.75)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-19" xml:space="preserve" y="5.5" style="stroke:none;"
>0.4</text
></g
><g transform="translate(67.6667,73.875)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-19" xml:space="preserve" y="5.5" style="stroke:none;"
>0.5</text
></g
><g transform="translate(67.6667,31)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-19" xml:space="preserve" y="5.5" style="stroke:none;"
>0.6</text
></g
><g transform="translate(40.6667,202.4998) rotate(-90)" style="font-size:14.6667px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-33" xml:space="preserve" y="-4" style="stroke:none;"
>Amplitude</text
></g
><g transform="translate(290.0003,28.25)" style="font-size:14.6667px; text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; font-weight:bold;"
><text x="-65" xml:space="preserve" y="-4" style="stroke:none;"
>Impulse Response</text
></g
><g style="stroke-linecap:butt; fill:rgb(38,38,38); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(38,38,38); color-interpolation:linearRGB; stroke-width:0.6667;"
><line y2="288.25" style="fill:none;" x1="73" x2="507" y1="288.25"
/><line x1="73" x2="73" y1="288.25" style="fill:none; stroke:rgb(0,114,189);" y2="288.25"
/><line x1="109.1667" x2="109.1667" y1="288.25" style="fill:none; stroke:rgb(0,114,189);" y2="324.2551"
/><line x1="145.3333" x2="145.3333" y1="288.25" style="fill:none; stroke:rgb(0,114,189);" y2="336.0701"
/><line x1="181.5" x2="181.5" y1="288.25" style="fill:none; stroke:rgb(0,114,189);" y2="288.25"
/><line x1="217.6667" x2="217.6667" y1="288.25" style="fill:none; stroke:rgb(0,114,189);" y2="184.7164"
/><line x1="253.8333" x2="253.8333" y1="288.25" style="fill:none; stroke:rgb(0,114,189);" y2="77.0925"
/><line x1="290" x2="290" y1="288.25" style="fill:none; stroke:rgb(0,114,189);" y2="31.2541"
/><line x1="326.1667" x2="326.1667" y1="288.25" style="fill:none; stroke:rgb(0,114,189);" y2="77.0925"
/><line x1="362.3333" x2="362.3333" y1="288.25" style="fill:none; stroke:rgb(0,114,189);" y2="184.7164"
/><line x1="398.5" x2="398.5" y1="288.25" style="fill:none; stroke:rgb(0,114,189);" y2="288.25"
/><line x1="434.6667" x2="434.6667" y1="288.25" style="fill:none; stroke:rgb(0,114,189);" y2="336.0701"
/><line x1="470.8333" x2="470.8333" y1="288.25" style="fill:none; stroke:rgb(0,114,189);" y2="324.2551"
/><line x1="507" x2="507" y1="288.25" style="fill:none; stroke:rgb(0,114,189);" y2="288.25"
/></g
><g transform="translate(73,288.25)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(73,288.25)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(109.1667,324.2551)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(109.1667,324.2551)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(145.3333,336.0701)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(145.3333,336.0701)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(181.5,288.25)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(181.5,288.25)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(217.6667,184.7164)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(217.6667,184.7164)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(253.8333,77.0925)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(253.8333,77.0925)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(290,31.2541)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(290,31.2541)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(326.1667,77.0925)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(326.1667,77.0925)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(362.3333,184.7164)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(362.3333,184.7164)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(398.5,288.25)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(398.5,288.25)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(434.6667,336.0701)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(434.6667,336.0701)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(470.8333,324.2551)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(470.8333,324.2551)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(507,288.25)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(507,288.25)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/><line transform="translate(-507,-288.25)" x1="73" x2="507" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="374"
/><line transform="translate(-507,-288.25)" x1="73" x2="507" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="31"
/><line transform="translate(-507,-288.25)" x1="73" x2="73" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="369.66"
/><line transform="translate(-507,-288.25)" x1="145.3333" x2="145.3333" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="369.66"
/><line transform="translate(-507,-288.25)" x1="217.6667" x2="217.6667" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="369.66"
/><line transform="translate(-507,-288.25)" x1="290" x2="290" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="369.66"
/><line transform="translate(-507,-288.25)" x1="362.3333" x2="362.3333" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="369.66"
/><line transform="translate(-507,-288.25)" x1="434.6667" x2="434.6667" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="369.66"
/><line transform="translate(-507,-288.25)" x1="507" x2="507" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="369.66"
/><line transform="translate(-507,-288.25)" x1="73" x2="73" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="35.34"
/><line transform="translate(-507,-288.25)" x1="145.3333" x2="145.3333" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="35.34"
/><line transform="translate(-507,-288.25)" x1="217.6667" x2="217.6667" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="35.34"
/><line transform="translate(-507,-288.25)" x1="290" x2="290" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="35.34"
/><line transform="translate(-507,-288.25)" x1="362.3333" x2="362.3333" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="35.34"
/><line transform="translate(-507,-288.25)" x1="434.6667" x2="434.6667" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="35.34"
/><line transform="translate(-507,-288.25)" x1="507" x2="507" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="35.34"
/></g
><g transform="translate(73,379.3333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-4" xml:space="preserve" y="14" style="stroke:none;"
>0</text
></g
><g transform="translate(145.3333,379.3333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-4" xml:space="preserve" y="14" style="stroke:none;"
>2</text
></g
><g transform="translate(217.6667,379.3333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-4" xml:space="preserve" y="14" style="stroke:none;"
>4</text
></g
><g transform="translate(290,379.3333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-4" xml:space="preserve" y="14" style="stroke:none;"
>6</text
></g
><g transform="translate(362.3333,379.3333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-4" xml:space="preserve" y="14" style="stroke:none;"
>8</text
></g
><g transform="translate(434.6667,379.3333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-7.5" xml:space="preserve" y="14" style="stroke:none;"
>10</text
></g
><g transform="translate(507,379.3333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-7.5" xml:space="preserve" y="14" style="stroke:none;"
>12</text
></g
><g transform="translate(290.0002,397.6667)" style="font-size:14.6667px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-38.5" xml:space="preserve" y="15" style="stroke:none;"
>n (samples)</text
></g
></g
></svg
>

After

Width:  |  Height:  |  Size: 46 KiB

@@ -0,0 +1,280 @@
<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.0//EN'
'http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd'>
<svg xmlns:xlink="http://www.w3.org/1999/xlink" style="fill-opacity:1; color-rendering:auto; color-interpolation:auto; text-rendering:auto; stroke:black; stroke-linecap:square; stroke-miterlimit:10; shape-rendering:auto; stroke-opacity:1; fill:black; stroke-dasharray:none; font-weight:normal; stroke-width:1; font-family:'Dialog'; font-style:normal; stroke-linejoin:miter; font-size:12px; stroke-dashoffset:0; image-rendering:auto;" width="560" height="420" xmlns="http://www.w3.org/2000/svg"
><!--Generated by the Batik Graphics2D SVG Generator--><defs id="genericDefs"
/><g
><defs id="defs1"
><clipPath clipPathUnits="userSpaceOnUse" id="clipPath1"
><path d="M0 0 L560 0 L560 420 L0 420 L0 0 Z"
/></clipPath
><font horiz-adv-x="75.0" id="font1"
><font-face ascent="100.53711" descent="21.972656" units-per-em="100" style="font-style:normal; font-family:Dialog; font-weight:normal;"
/><missing-glyph horiz-adv-x="75.0" d="M12.5 0 L12.5 62.5 L62.5 62.5 L62.5 0 L12.5 0 ZM14.0625 1.5625 L60.9375 1.5625 L60.9375 60.9375 L14.0625 60.9375 L14.0625 1.5625 Z"
/><glyph unicode="2" horiz-adv-x="55.615234" d="M50.3438 8.4531 L50.3438 0 L3.0312 0 Q2.9375 3.1719 4.0469 6.1094 Q5.8594 10.9375 9.8359 15.625 Q13.8125 20.3125 21.3438 26.4688 Q33.0156 36.0312 37.1172 41.625 Q41.2188 47.2188 41.2188 52.2031 Q41.2188 57.4219 37.4766 61.0078 Q33.7344 64.5938 27.7344 64.5938 Q21.3906 64.5938 17.5781 60.7891 Q13.7656 56.9844 13.7188 50.25 L4.6875 51.1719 Q5.6094 61.2812 11.6641 66.5781 Q17.7188 71.875 27.9375 71.875 Q38.2344 71.875 44.2422 66.1641 Q50.25 60.4531 50.25 52 Q50.25 47.7031 48.4922 43.5547 Q46.7344 39.4062 42.6562 34.8125 Q38.5781 30.2188 29.1094 22.2188 Q21.1875 15.5781 18.9453 13.2109 Q16.7031 10.8438 15.2344 8.4531 L50.3438 8.4531 Z"
/><glyph unicode="." horiz-adv-x="27.783203" d="M9.0781 0 L9.0781 10.0156 L19.0938 10.0156 L19.0938 0 L9.0781 0 Z"
/><glyph unicode="0" horiz-adv-x="55.615234" d="M4.1562 35.2969 Q4.1562 48 6.7656 55.7422 Q9.375 63.4844 14.5234 67.6797 Q19.6719 71.875 27.4844 71.875 Q33.25 71.875 37.5938 69.5547 Q41.9375 67.2344 44.7734 62.8672 Q47.6094 58.5 49.2188 52.2266 Q50.8281 45.9531 50.8281 35.2969 Q50.8281 22.7031 48.2422 14.9688 Q45.6562 7.2344 40.5078 3.0078 Q35.3594 -1.2188 27.4844 -1.2188 Q17.1406 -1.2188 11.2344 6.2031 Q4.1562 15.1406 4.1562 35.2969 ZM13.1875 35.2969 Q13.1875 17.6719 17.3125 11.8359 Q21.4375 6 27.4844 6 Q33.5469 6 37.6719 11.8594 Q41.7969 17.7188 41.7969 35.2969 Q41.7969 52.9844 37.6719 58.7891 Q33.5469 64.5938 27.3906 64.5938 Q21.3438 64.5938 17.7188 59.4688 Q13.1875 52.9375 13.1875 35.2969 Z"
/><glyph unicode="-" horiz-adv-x="33.30078" d="M3.1719 21.4844 L3.1719 30.3281 L30.1719 30.3281 L30.1719 21.4844 L3.1719 21.4844 Z"
/><glyph unicode="1" horiz-adv-x="55.615234" d="M37.25 0 L28.4688 0 L28.4688 56 Q25.2969 52.9844 20.1406 49.9531 Q14.9844 46.9219 10.8906 45.4062 L10.8906 53.9062 Q18.2656 57.375 23.7812 62.3047 Q29.2969 67.2344 31.5938 71.875 L37.25 71.875 L37.25 0 Z"
/><glyph unicode="3" horiz-adv-x="55.615234" d="M4.2031 18.8906 L12.9844 20.0625 Q14.5 12.5938 18.1406 9.2969 Q21.7812 6 27 6 Q33.2031 6 37.4766 10.2969 Q41.75 14.5938 41.75 20.9531 Q41.75 27 37.7969 30.9297 Q33.8438 34.8594 27.7344 34.8594 Q25.25 34.8594 21.5312 33.8906 L22.5156 41.6094 Q23.3906 41.5 23.9219 41.5 Q29.5469 41.5 34.0391 44.4297 Q38.5312 47.3594 38.5312 53.4688 Q38.5312 58.2969 35.2578 61.4766 Q31.9844 64.6562 26.8125 64.6562 Q21.6875 64.6562 18.2656 61.4297 Q14.8438 58.2031 13.875 51.7656 L5.0781 53.3281 Q6.6875 62.1562 12.3984 67.0156 Q18.1094 71.875 26.6094 71.875 Q32.4688 71.875 37.3984 69.3594 Q42.3281 66.8438 44.9453 62.5 Q47.5625 58.1562 47.5625 53.2656 Q47.5625 48.6406 45.0703 44.8281 Q42.5781 41.0156 37.7031 38.7656 Q44.0469 37.3125 47.5625 32.6953 Q51.0781 28.0781 51.0781 21.1406 Q51.0781 11.7656 44.2422 5.25 Q37.4062 -1.2656 26.9531 -1.2656 Q17.5312 -1.2656 11.3047 4.3516 Q5.0781 9.9688 4.2031 18.8906 Z"
/><glyph unicode="4" horiz-adv-x="55.615234" d="M32.3281 0 L32.3281 17.1406 L1.2656 17.1406 L1.2656 25.2031 L33.9375 71.5781 L41.1094 71.5781 L41.1094 25.2031 L50.7812 25.2031 L50.7812 17.1406 L41.1094 17.1406 L41.1094 0 L32.3281 0 ZM32.3281 25.2031 L32.3281 57.4688 L9.9062 25.2031 L32.3281 25.2031 Z"
/><glyph unicode="5" horiz-adv-x="55.615234" d="M4.1562 18.75 L13.375 19.5312 Q14.4062 12.7969 18.1406 9.3984 Q21.875 6 27.1562 6 Q33.5 6 37.8906 10.7891 Q42.2812 15.5781 42.2812 23.4844 Q42.2812 31 38.0625 35.3516 Q33.8438 39.7031 27 39.7031 Q22.75 39.7031 19.3359 37.7734 Q15.9219 35.8438 13.9688 32.7656 L5.7188 33.8438 L12.6406 70.6094 L48.25 70.6094 L48.25 62.2031 L19.6719 62.2031 L15.8281 42.9688 Q22.2656 47.4688 29.3438 47.4688 Q38.7188 47.4688 45.1641 40.9688 Q51.6094 34.4688 51.6094 24.2656 Q51.6094 14.5469 45.9531 7.4688 Q39.0625 -1.2188 27.1562 -1.2188 Q17.3906 -1.2188 11.2109 4.25 Q5.0312 9.7188 4.1562 18.75 Z"
/><glyph unicode="6" horiz-adv-x="55.615234" d="M49.75 54.0469 L41.0156 53.375 Q39.8438 58.5469 37.7031 60.8906 Q34.125 64.6562 28.9062 64.6562 Q24.7031 64.6562 21.5312 62.3125 Q17.3906 59.2812 14.9922 53.4688 Q12.5938 47.6562 12.5 36.9219 Q15.6719 41.75 20.2656 44.0938 Q24.8594 46.4375 29.8906 46.4375 Q38.6719 46.4375 44.8516 39.9688 Q51.0312 33.5 51.0312 23.25 Q51.0312 16.5 48.125 10.7188 Q45.2188 4.9375 40.1406 1.8594 Q35.0625 -1.2188 28.6094 -1.2188 Q17.625 -1.2188 10.6953 6.8594 Q3.7656 14.9375 3.7656 33.5 Q3.7656 54.25 11.4219 63.6719 Q18.1094 71.875 29.4375 71.875 Q37.8906 71.875 43.2891 67.1406 Q48.6875 62.4062 49.75 54.0469 ZM13.875 23.1875 Q13.875 18.6562 15.7969 14.5078 Q17.7188 10.3594 21.1875 8.1797 Q24.6562 6 28.4688 6 Q34.0312 6 38.0391 10.4922 Q42.0469 14.9844 42.0469 22.7031 Q42.0469 30.125 38.0859 34.3984 Q34.125 38.6719 28.125 38.6719 Q22.1719 38.6719 18.0234 34.3984 Q13.875 30.125 13.875 23.1875 Z"
/><glyph unicode="7" horiz-adv-x="55.615234" d="M4.7344 62.2031 L4.7344 70.6562 L51.0781 70.6562 L51.0781 63.8125 Q44.2344 56.5469 37.5234 44.4844 Q30.8125 32.4219 27.1562 19.6719 Q24.5156 10.6875 23.7812 0 L14.75 0 Q14.8906 8.4531 18.0625 20.4141 Q21.2344 32.375 27.1719 43.4844 Q33.1094 54.5938 39.7969 62.2031 L4.7344 62.2031 Z"
/><glyph unicode="e" horiz-adv-x="55.615234" d="M42.0938 16.7031 L51.1719 15.5781 Q49.0312 7.625 43.2188 3.2266 Q37.4062 -1.1719 28.375 -1.1719 Q17 -1.1719 10.3281 5.8359 Q3.6562 12.8438 3.6562 25.4844 Q3.6562 38.5781 10.3984 45.8047 Q17.1406 53.0312 27.875 53.0312 Q38.2812 53.0312 44.875 45.9531 Q51.4688 38.875 51.4688 26.0312 Q51.4688 25.25 51.4219 23.6875 L12.75 23.6875 Q13.2344 15.1406 17.5781 10.6016 Q21.9219 6.0625 28.4219 6.0625 Q33.25 6.0625 36.6719 8.6016 Q40.0938 11.1406 42.0938 16.7031 ZM13.2344 30.9062 L42.1875 30.9062 Q41.6094 37.4531 38.875 40.7188 Q34.6719 45.7969 27.9844 45.7969 Q21.9219 45.7969 17.7969 41.75 Q13.6719 37.7031 13.2344 30.9062 Z"
/><glyph unicode="d" horiz-adv-x="55.615234" d="M40.2344 0 L40.2344 6.5469 Q35.2969 -1.1719 25.7344 -1.1719 Q19.5312 -1.1719 14.3281 2.25 Q9.125 5.6719 6.2734 11.7969 Q3.4219 17.9219 3.4219 25.875 Q3.4219 33.6406 6.0078 39.9688 Q8.5938 46.2969 13.7734 49.6641 Q18.9531 53.0312 25.3438 53.0312 Q30.0312 53.0312 33.6953 51.0547 Q37.3594 49.0781 39.6562 45.9062 L39.6562 71.5781 L48.3906 71.5781 L48.3906 0 L40.2344 0 ZM12.4531 25.875 Q12.4531 15.9219 16.6484 10.9922 Q20.8438 6.0625 26.5625 6.0625 Q32.3281 6.0625 36.3516 10.7734 Q40.375 15.4844 40.375 25.1406 Q40.375 35.7969 36.2734 40.7734 Q32.1719 45.75 26.1719 45.75 Q20.3125 45.75 16.3828 40.9688 Q12.4531 36.1875 12.4531 25.875 Z"
/><glyph unicode="u" horiz-adv-x="55.615234" d="M40.5781 0 L40.5781 7.625 Q34.5156 -1.1719 24.125 -1.1719 Q19.5312 -1.1719 15.5547 0.5859 Q11.5781 2.3438 9.6484 5.0078 Q7.7188 7.6719 6.9375 11.5312 Q6.3906 14.1094 6.3906 19.7344 L6.3906 51.8594 L15.1875 51.8594 L15.1875 23.0938 Q15.1875 16.2188 15.7188 13.8125 Q16.5469 10.3594 19.2344 8.375 Q21.9219 6.3906 25.875 6.3906 Q29.8281 6.3906 33.2969 8.4219 Q36.7656 10.4531 38.2109 13.9453 Q39.6562 17.4375 39.6562 24.0781 L39.6562 51.8594 L48.4375 51.8594 L48.4375 0 L40.5781 0 Z"
/><glyph unicode="t" horiz-adv-x="27.783203" d="M25.7812 7.8594 L27.0469 0.0938 Q23.3438 -0.6875 20.4062 -0.6875 Q15.625 -0.6875 12.9922 0.8281 Q10.3594 2.3438 9.2812 4.8125 Q8.2031 7.2812 8.2031 15.1875 L8.2031 45.0156 L1.7656 45.0156 L1.7656 51.8594 L8.2031 51.8594 L8.2031 64.7031 L16.9375 69.9688 L16.9375 51.8594 L25.7812 51.8594 L25.7812 45.0156 L16.9375 45.0156 L16.9375 14.7031 Q16.9375 10.9375 17.4062 9.8672 Q17.875 8.7969 18.9219 8.1562 Q19.9688 7.5156 21.9219 7.5156 Q23.3906 7.5156 25.7812 7.8594 Z"
/><glyph unicode="i" horiz-adv-x="22.216797" d="M6.6406 61.4688 L6.6406 71.5781 L15.4375 71.5781 L15.4375 61.4688 L6.6406 61.4688 ZM6.6406 0 L6.6406 51.8594 L15.4375 51.8594 L15.4375 0 L6.6406 0 Z"
/><glyph unicode="l" horiz-adv-x="22.216797" d="M6.3906 0 L6.3906 71.5781 L15.1875 71.5781 L15.1875 0 L6.3906 0 Z"
/><glyph unicode="p" horiz-adv-x="55.615234" d="M6.5938 -19.875 L6.5938 51.8594 L14.5938 51.8594 L14.5938 45.125 Q17.4375 49.0781 21 51.0547 Q24.5625 53.0312 29.6406 53.0312 Q36.2812 53.0312 41.3594 49.6094 Q46.4375 46.1875 49.0234 39.9609 Q51.6094 33.7344 51.6094 26.3125 Q51.6094 18.3594 48.7578 11.9844 Q45.9062 5.6094 40.4609 2.2188 Q35.0156 -1.1719 29 -1.1719 Q24.6094 -1.1719 21.1172 0.6875 Q17.625 2.5469 15.375 5.375 L15.375 -19.875 L6.5938 -19.875 ZM14.5469 25.6406 Q14.5469 15.625 18.6016 10.8438 Q22.6562 6.0625 28.4219 6.0625 Q34.2812 6.0625 38.4531 11.0156 Q42.625 15.9688 42.625 26.375 Q42.625 36.2812 38.5469 41.2109 Q34.4688 46.1406 28.8125 46.1406 Q23.1875 46.1406 18.8672 40.8906 Q14.5469 35.6406 14.5469 25.6406 Z"
/><glyph unicode="m" horiz-adv-x="83.30078" d="M6.5938 0 L6.5938 51.8594 L14.4531 51.8594 L14.4531 44.5781 Q16.8906 48.3906 20.9453 50.7109 Q25 53.0312 30.1719 53.0312 Q35.9375 53.0312 39.625 50.6406 Q43.3125 48.25 44.8281 43.9531 Q50.9844 53.0312 60.8438 53.0312 Q68.5625 53.0312 72.7109 48.7578 Q76.8594 44.4844 76.8594 35.5938 L76.8594 0 L68.1094 0 L68.1094 32.6719 Q68.1094 37.9375 67.2578 40.2578 Q66.4062 42.5781 64.1641 43.9922 Q61.9219 45.4062 58.8906 45.4062 Q53.4219 45.4062 49.8047 41.7734 Q46.1875 38.1406 46.1875 30.125 L46.1875 0 L37.4062 0 L37.4062 33.6875 Q37.4062 39.5469 35.2578 42.4766 Q33.1094 45.4062 28.2188 45.4062 Q24.5156 45.4062 21.3672 43.4531 Q18.2188 41.5 16.7969 37.7422 Q15.375 33.9844 15.375 26.9062 L15.375 0 L6.5938 0 Z"
/><glyph unicode="A" horiz-adv-x="66.69922" d="M-0.1406 0 L27.3438 71.5781 L37.5469 71.5781 L66.8438 0 L56.0625 0 L47.7031 21.6875 L17.7812 21.6875 L9.9062 0 L-0.1406 0 ZM20.5156 29.3906 L44.7812 29.3906 L37.3125 49.2188 Q33.8906 58.25 32.2344 64.0625 Q30.8594 57.1719 28.375 50.3906 L20.5156 29.3906 Z"
/><glyph unicode="8" horiz-adv-x="55.615234" d="M17.6719 38.8125 Q12.2031 40.8281 9.5703 44.5391 Q6.9375 48.25 6.9375 53.4219 Q6.9375 61.2344 12.5547 66.5547 Q18.1719 71.875 27.4844 71.875 Q36.8594 71.875 42.5781 66.4297 Q48.2969 60.9844 48.2969 53.1719 Q48.2969 48.1875 45.6797 44.5078 Q43.0625 40.8281 37.75 38.8125 Q44.3438 36.6719 47.7812 31.8828 Q51.2188 27.0938 51.2188 20.4531 Q51.2188 11.2812 44.7266 5.0312 Q38.2344 -1.2188 27.6406 -1.2188 Q17.0469 -1.2188 10.5469 5.0547 Q4.0469 11.3281 4.0469 20.7031 Q4.0469 27.6875 7.5938 32.3984 Q11.1406 37.1094 17.6719 38.8125 ZM15.9219 53.7188 Q15.9219 48.6406 19.1953 45.4141 Q22.4688 42.1875 27.6875 42.1875 Q32.7656 42.1875 36.0156 45.3828 Q39.2656 48.5781 39.2656 53.2188 Q39.2656 58.0625 35.9141 61.3594 Q32.5625 64.6562 27.5938 64.6562 Q22.5625 64.6562 19.2422 61.4297 Q15.9219 58.2031 15.9219 53.7188 ZM13.0938 20.6562 Q13.0938 16.8906 14.875 13.375 Q16.6562 9.8594 20.1719 7.9297 Q23.6875 6 27.7344 6 Q34.0312 6 38.1328 10.0547 Q42.2344 14.1094 42.2344 20.3594 Q42.2344 26.7031 38.0156 30.8594 Q33.7969 35.0156 27.4375 35.0156 Q21.2344 35.0156 17.1641 30.9141 Q13.0938 26.8125 13.0938 20.6562 Z"
/><glyph unicode=")" horiz-adv-x="33.30078" d="M12.3594 -21.0469 L6.0625 -21.0469 Q20.6562 2.3906 20.6562 25.875 Q20.6562 35.0625 18.5625 44.0938 Q16.8906 51.4219 13.9219 58.1562 Q12.0156 62.5469 6.0625 72.7969 L12.3594 72.7969 Q21.5312 60.5469 25.9219 48.1875 Q29.6875 37.5469 29.6875 25.9219 Q29.6875 12.75 24.6328 0.4453 Q19.5781 -11.8594 12.3594 -21.0469 Z"
/><glyph unicode="a" horiz-adv-x="55.615234" d="M40.4375 6.3906 Q35.5469 2.25 31.0312 0.5391 Q26.5156 -1.1719 21.3438 -1.1719 Q12.7969 -1.1719 8.2031 3 Q3.6094 7.1719 3.6094 13.6719 Q3.6094 17.4844 5.3438 20.6328 Q7.0781 23.7812 9.8906 25.6875 Q12.7031 27.5938 16.2188 28.5625 Q18.7969 29.25 24.0312 29.8906 Q34.6719 31.1562 39.7031 32.9062 Q39.75 34.7188 39.75 35.2031 Q39.75 40.5781 37.25 42.7812 Q33.8906 45.75 27.25 45.75 Q21.0469 45.75 18.0938 43.5781 Q15.1406 41.4062 13.7188 35.8906 L5.125 37.0625 Q6.2969 42.5781 8.9844 45.9688 Q11.6719 49.3594 16.75 51.1953 Q21.8281 53.0312 28.5156 53.0312 Q35.1562 53.0312 39.3047 51.4688 Q43.4531 49.9062 45.4062 47.5391 Q47.3594 45.1719 48.1406 41.5469 Q48.5781 39.3125 48.5781 33.4531 L48.5781 21.7344 Q48.5781 9.4688 49.1406 6.2266 Q49.7031 2.9844 51.375 0 L42.1875 0 Q40.8281 2.7344 40.4375 6.3906 ZM39.7031 26.0312 Q34.9062 24.0781 25.3438 22.7031 Q19.9219 21.9219 17.6797 20.9453 Q15.4375 19.9688 14.2109 18.0938 Q12.9844 16.2188 12.9844 13.9219 Q12.9844 10.4062 15.6484 8.0625 Q18.3125 5.7188 23.4375 5.7188 Q28.5156 5.7188 32.4688 7.9375 Q36.4219 10.1562 38.2812 14.0156 Q39.7031 17 39.7031 22.7969 L39.7031 26.0312 Z"
/><glyph unicode="s" horiz-adv-x="50.0" d="M3.0781 15.4844 L11.7656 16.8438 Q12.5 11.625 15.8438 8.8438 Q19.1875 6.0625 25.2031 6.0625 Q31.25 6.0625 34.1797 8.5234 Q37.1094 10.9844 37.1094 14.3125 Q37.1094 17.2812 34.5156 19 Q32.7188 20.1719 25.5312 21.9688 Q15.875 24.4219 12.1406 26.2031 Q8.4062 27.9844 6.4766 31.1328 Q4.5469 34.2812 4.5469 38.0938 Q4.5469 41.5469 6.1328 44.5078 Q7.7188 47.4688 10.4531 49.4219 Q12.5 50.9219 16.0391 51.9766 Q19.5781 53.0312 23.6406 53.0312 Q29.7344 53.0312 34.3516 51.2734 Q38.9688 49.5156 41.1641 46.5078 Q43.3594 43.5 44.1875 38.4844 L35.5938 37.3125 Q35.0156 41.3125 32.2031 43.5547 Q29.3906 45.7969 24.2656 45.7969 Q18.2188 45.7969 15.625 43.7969 Q13.0312 41.7969 13.0312 39.1094 Q13.0312 37.4062 14.1094 36.0312 Q15.1875 34.625 17.4844 33.6875 Q18.7969 33.2031 25.25 31.4531 Q34.5781 28.9531 38.2578 27.3672 Q41.9375 25.7812 44.0391 22.7578 Q46.1406 19.7344 46.1406 15.2344 Q46.1406 10.8438 43.5781 6.9609 Q41.0156 3.0781 36.1797 0.9531 Q31.3438 -1.1719 25.25 -1.1719 Q15.1406 -1.1719 9.8438 3.0312 Q4.5469 7.2344 3.0781 15.4844 Z"
/><glyph unicode="(" horiz-adv-x="33.30078" d="M23.3906 -21.0469 Q16.1094 -11.8594 11.0859 0.4453 Q6.0625 12.75 6.0625 25.9219 Q6.0625 37.5469 9.8125 48.1875 Q14.2031 60.5469 23.3906 72.7969 L29.6875 72.7969 Q23.7812 62.6406 21.875 58.2969 Q18.8906 51.5625 17.1875 44.2344 Q15.0938 35.1094 15.0938 25.875 Q15.0938 2.3906 29.6875 -21.0469 L23.3906 -21.0469 Z"
/><glyph unicode=" " horiz-adv-x="27.783203" d=""
/><glyph unicode="n" horiz-adv-x="55.615234" d="M6.5938 0 L6.5938 51.8594 L14.5 51.8594 L14.5 44.4844 Q20.2188 53.0312 31 53.0312 Q35.6875 53.0312 39.625 51.3438 Q43.5625 49.6562 45.5156 46.9219 Q47.4688 44.1875 48.25 40.4375 Q48.7344 37.9844 48.7344 31.8906 L48.7344 0 L39.9375 0 L39.9375 31.5469 Q39.9375 36.9219 38.9141 39.5781 Q37.8906 42.2344 35.2812 43.8203 Q32.6719 45.4062 29.1562 45.4062 Q23.5312 45.4062 19.4531 41.8438 Q15.375 38.2812 15.375 28.3281 L15.375 0 L6.5938 0 Z"
/></font
><font horiz-adv-x="75.0" id="font2"
><font-face ascent="100.53711" descent="21.972656" units-per-em="100" style="font-style:normal; font-family:Dialog; font-weight:bold;"
/><missing-glyph horiz-adv-x="75.0" d="M12.5 0 L12.5 62.5 L62.5 62.5 L62.5 0 L12.5 0 ZM14.0625 1.5625 L60.9375 1.5625 L60.9375 60.9375 L14.0625 60.9375 L14.0625 1.5625 Z"
/><glyph unicode="n" horiz-adv-x="61.083984" d="M54.3438 0 L40.625 0 L40.625 26.4688 Q40.625 34.8594 39.75 37.3281 Q38.875 39.7969 36.8906 41.1641 Q34.9062 42.5312 32.125 42.5312 Q28.5625 42.5312 25.7344 40.5781 Q22.9062 38.625 21.8516 35.3984 Q20.7969 32.1719 20.7969 23.4844 L20.7969 0 L7.0781 0 L7.0781 51.8594 L19.8281 51.8594 L19.8281 44.2344 Q26.6094 53.0312 36.9219 53.0312 Q41.4531 53.0312 45.2109 51.3906 Q48.9688 49.75 50.8984 47.2109 Q52.8281 44.6719 53.5859 41.4531 Q54.3438 38.2344 54.3438 32.2344 L54.3438 0 Z"
/><glyph unicode="o" horiz-adv-x="61.083984" d="M4 26.6562 Q4 33.5 7.375 39.8984 Q10.75 46.2969 16.9219 49.6641 Q23.0938 53.0312 30.7188 53.0312 Q42.4844 53.0312 50 45.3906 Q57.5156 37.75 57.5156 26.0781 Q57.5156 14.3125 49.9219 6.5703 Q42.3281 -1.1719 30.8125 -1.1719 Q23.6875 -1.1719 17.2188 2.0547 Q10.75 5.2812 7.375 11.5 Q4 17.7188 4 26.6562 ZM18.0625 25.9219 Q18.0625 18.2188 21.7266 14.1172 Q25.3906 10.0156 30.7656 10.0156 Q36.1406 10.0156 39.7734 14.1172 Q43.4062 18.2188 43.4062 26.0312 Q43.4062 33.6406 39.7734 37.7422 Q36.1406 41.8438 30.7656 41.8438 Q25.3906 41.8438 21.7266 37.7422 Q18.0625 33.6406 18.0625 25.9219 Z"
/><glyph unicode="R" horiz-adv-x="72.2168" d="M7.3281 0 L7.3281 71.5781 L37.75 71.5781 Q49.2188 71.5781 54.4219 69.6484 Q59.625 67.7188 62.75 62.7891 Q65.875 57.8594 65.875 51.5156 Q65.875 43.4531 61.1328 38.2031 Q56.3906 32.9531 46.9688 31.5938 Q51.6562 28.8594 54.7109 25.5859 Q57.7656 22.3125 62.9375 13.9688 L71.6875 0 L54.3906 0 L43.9531 15.5781 Q38.375 23.9219 36.3281 26.0938 Q34.2812 28.2656 31.9844 29.0781 Q29.6875 29.8906 24.7031 29.8906 L21.7812 29.8906 L21.7812 0 L7.3281 0 ZM21.7812 41.3125 L32.4688 41.3125 Q42.875 41.3125 45.4609 42.1875 Q48.0469 43.0625 49.5156 45.2109 Q50.9844 47.3594 50.9844 50.5938 Q50.9844 54.2031 49.0547 56.4219 Q47.125 58.6406 43.6094 59.2344 Q41.8438 59.4688 33.0625 59.4688 L21.7812 59.4688 L21.7812 41.3125 Z"
/><glyph unicode=" " horiz-adv-x="27.783203" d=""
/><glyph unicode="e" horiz-adv-x="55.615234" d="M37.2031 16.5 L50.875 14.2031 Q48.25 6.6875 42.5547 2.7578 Q36.8594 -1.1719 28.3281 -1.1719 Q14.7969 -1.1719 8.2969 7.6719 Q3.1719 14.75 3.1719 25.5312 Q3.1719 38.4219 9.9141 45.7266 Q16.6562 53.0312 26.9531 53.0312 Q38.5312 53.0312 45.2188 45.3906 Q51.9062 37.75 51.6094 21.9688 L17.2344 21.9688 Q17.3906 15.875 20.5625 12.4766 Q23.7344 9.0781 28.4688 9.0781 Q31.6875 9.0781 33.8828 10.8359 Q36.0781 12.5938 37.2031 16.5 ZM37.9844 30.375 Q37.8438 36.3281 34.9141 39.4297 Q31.9844 42.5312 27.7812 42.5312 Q23.2969 42.5312 20.3594 39.2656 Q17.4375 35.9844 17.4844 30.375 L37.9844 30.375 Z"
/><glyph unicode="s" horiz-adv-x="55.615234" d="M2.3438 14.7969 L16.1094 16.8906 Q17 12.8906 19.6797 10.8125 Q22.3594 8.7344 27.2031 8.7344 Q32.5156 8.7344 35.2031 10.6875 Q37.0156 12.0625 37.0156 14.3594 Q37.0156 15.9219 36.0312 16.9375 Q35.0156 17.9219 31.4531 18.75 Q14.8438 22.4062 10.4062 25.4375 Q4.25 29.6406 4.25 37.1094 Q4.25 43.8438 9.5703 48.4375 Q14.8906 53.0312 26.0781 53.0312 Q36.7188 53.0312 41.8984 49.5625 Q47.0781 46.0938 49.0312 39.3125 L36.0781 36.9219 Q35.25 39.9375 32.9297 41.5547 Q30.6094 43.1719 26.3125 43.1719 Q20.9062 43.1719 18.5625 41.6562 Q17 40.5781 17 38.875 Q17 37.4062 18.3594 36.375 Q20.2188 35.0156 31.1797 32.5234 Q42.1406 30.0312 46.4844 26.4219 Q50.7812 22.75 50.7812 16.2188 Q50.7812 9.0781 44.8281 3.9531 Q38.875 -1.1719 27.2031 -1.1719 Q16.6094 -1.1719 10.4297 3.125 Q4.25 7.4219 2.3438 14.7969 Z"
/><glyph unicode="l" horiz-adv-x="27.783203" d="M7.1719 0 L7.1719 71.5781 L20.9062 71.5781 L20.9062 0 L7.1719 0 Z"
/><glyph unicode="u" horiz-adv-x="61.083984" d="M41.3125 0 L41.3125 7.7656 Q38.4844 3.6094 33.8672 1.2188 Q29.25 -1.1719 24.125 -1.1719 Q18.8906 -1.1719 14.7422 1.125 Q10.5938 3.4219 8.7422 7.5703 Q6.8906 11.7188 6.8906 19.0469 L6.8906 51.8594 L20.6094 51.8594 L20.6094 28.0312 Q20.6094 17.0938 21.3672 14.625 Q22.125 12.1562 24.125 10.7188 Q26.125 9.2812 29.2031 9.2812 Q32.7188 9.2812 35.5 11.2109 Q38.2812 13.1406 39.3047 15.9922 Q40.3281 18.8438 40.3281 29.9844 L40.3281 51.8594 L54.0469 51.8594 L54.0469 0 L41.3125 0 Z"
/><glyph unicode="p" horiz-adv-x="61.083984" d="M6.7812 51.8594 L19.5781 51.8594 L19.5781 44.2344 Q22.0781 48.1406 26.3203 50.5859 Q30.5625 53.0312 35.75 53.0312 Q44.7812 53.0312 51.0781 45.9531 Q57.375 38.875 57.375 26.2188 Q57.375 13.2344 51.0234 6.0312 Q44.6719 -1.1719 35.6406 -1.1719 Q31.3438 -1.1719 27.8516 0.5391 Q24.3594 2.25 20.5156 6.3906 L20.5156 -19.7344 L6.7812 -19.7344 L6.7812 51.8594 ZM20.3594 26.8125 Q20.3594 18.0625 23.8281 13.8906 Q27.2969 9.7188 32.2812 9.7188 Q37.0625 9.7188 40.2344 13.5547 Q43.4062 17.3906 43.4062 26.125 Q43.4062 34.2812 40.1328 38.2344 Q36.8594 42.1875 32.0312 42.1875 Q27 42.1875 23.6797 38.3047 Q20.3594 34.4219 20.3594 26.8125 Z"
/><glyph unicode="m" horiz-adv-x="88.916016" d="M6.1562 51.8594 L18.7969 51.8594 L18.7969 44.7812 Q25.5938 53.0312 34.9688 53.0312 Q39.9375 53.0312 43.6016 50.9766 Q47.2656 48.9219 49.6094 44.7812 Q53.0312 48.9219 56.9844 50.9766 Q60.9375 53.0312 65.4375 53.0312 Q71.1406 53.0312 75.0938 50.7109 Q79.0469 48.3906 81 43.8906 Q82.4219 40.5781 82.4219 33.1562 L82.4219 0 L68.7031 0 L68.7031 29.6406 Q68.7031 37.3594 67.2812 39.5938 Q65.375 42.5312 61.4219 42.5312 Q58.5469 42.5312 56.0078 40.7734 Q53.4688 39.0156 52.3438 35.625 Q51.2188 32.2344 51.2188 24.9062 L51.2188 0 L37.5 0 L37.5 28.4219 Q37.5 35.9844 36.7656 38.1797 Q36.0312 40.375 34.4922 41.4531 Q32.9531 42.5312 30.3281 42.5312 Q27.1562 42.5312 24.6172 40.8203 Q22.0781 39.1094 20.9766 35.8906 Q19.875 32.6719 19.875 25.2031 L19.875 0 L6.1562 0 L6.1562 51.8594 Z"
/><glyph unicode="I" horiz-adv-x="27.783203" d="M6.8438 0 L6.8438 71.5781 L21.2969 71.5781 L21.2969 0 L6.8438 0 Z"
/></font
></defs
><g style="fill:white; stroke:white;"
><rect x="0" y="0" width="560" style="clip-path:url(#clipPath1); stroke:none;" height="420"
/></g
><g style="fill:white; text-rendering:optimizeSpeed; color-rendering:optimizeSpeed; image-rendering:optimizeSpeed; shape-rendering:crispEdges; stroke:white; color-interpolation:sRGB;"
><rect x="0" width="560" height="420" y="0" style="stroke:none;"
/><path style="stroke:none;" d="M73 374 L507 374 L507 31 L73 31 Z"
/></g
><g style="fill:rgb(38,38,38); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(38,38,38); color-interpolation:linearRGB; stroke-width:0.6667;"
><line y2="31" style="fill:none;" x1="73" x2="73" y1="374"
/><line y2="31" style="fill:none;" x1="507" x2="507" y1="374"
/><line y2="374" style="fill:none;" x1="73" x2="77.34" y1="374"
/><line y2="335.8889" style="fill:none;" x1="73" x2="77.34" y1="335.8889"
/><line y2="297.7778" style="fill:none;" x1="73" x2="77.34" y1="297.7778"
/><line y2="259.6667" style="fill:none;" x1="73" x2="77.34" y1="259.6667"
/><line y2="221.5556" style="fill:none;" x1="73" x2="77.34" y1="221.5556"
/><line y2="183.4444" style="fill:none;" x1="73" x2="77.34" y1="183.4444"
/><line y2="145.3333" style="fill:none;" x1="73" x2="77.34" y1="145.3333"
/><line y2="107.2222" style="fill:none;" x1="73" x2="77.34" y1="107.2222"
/><line y2="69.1111" style="fill:none;" x1="73" x2="77.34" y1="69.1111"
/><line y2="31" style="fill:none;" x1="73" x2="77.34" y1="31"
/><line y2="374" style="fill:none;" x1="507" x2="502.66" y1="374"
/><line y2="335.8889" style="fill:none;" x1="507" x2="502.66" y1="335.8889"
/><line y2="297.7778" style="fill:none;" x1="507" x2="502.66" y1="297.7778"
/><line y2="259.6667" style="fill:none;" x1="507" x2="502.66" y1="259.6667"
/><line y2="221.5556" style="fill:none;" x1="507" x2="502.66" y1="221.5556"
/><line y2="183.4444" style="fill:none;" x1="507" x2="502.66" y1="183.4444"
/><line y2="145.3333" style="fill:none;" x1="507" x2="502.66" y1="145.3333"
/><line y2="107.2222" style="fill:none;" x1="507" x2="502.66" y1="107.2222"
/><line y2="69.1111" style="fill:none;" x1="507" x2="502.66" y1="69.1111"
/><line y2="31" style="fill:none;" x1="507" x2="502.66" y1="31"
/></g
><g transform="translate(67.6667,374)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-23" xml:space="preserve" y="5.5" style="stroke:none;"
>-0.2</text
></g
><g transform="translate(67.6667,335.8889)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-23" xml:space="preserve" y="5.5" style="stroke:none;"
>-0.1</text
></g
><g transform="translate(67.6667,297.7778)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-8" xml:space="preserve" y="5.5" style="stroke:none;"
>0</text
></g
><g transform="translate(67.6667,259.6667)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-19" xml:space="preserve" y="5.5" style="stroke:none;"
>0.1</text
></g
><g transform="translate(67.6667,221.5556)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-19" xml:space="preserve" y="5.5" style="stroke:none;"
>0.2</text
></g
><g transform="translate(67.6667,183.4444)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-19" xml:space="preserve" y="5.5" style="stroke:none;"
>0.3</text
></g
><g transform="translate(67.6667,145.3333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-19" xml:space="preserve" y="5.5" style="stroke:none;"
>0.4</text
></g
><g transform="translate(67.6667,107.2222)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-19" xml:space="preserve" y="5.5" style="stroke:none;"
>0.5</text
></g
><g transform="translate(67.6667,69.1111)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-19" xml:space="preserve" y="5.5" style="stroke:none;"
>0.6</text
></g
><g transform="translate(67.6667,31)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-19" xml:space="preserve" y="5.5" style="stroke:none;"
>0.7</text
></g
><g transform="translate(40.6667,202.4998) rotate(-90)" style="font-size:14.6667px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-33" xml:space="preserve" y="-4" style="stroke:none;"
>Amplitude</text
></g
><g transform="translate(290.0003,28.25)" style="font-size:14.6667px; text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; font-weight:bold;"
><text x="-65" xml:space="preserve" y="-4" style="stroke:none;"
>Impulse Response</text
></g
><g style="stroke-linecap:butt; fill:rgb(38,38,38); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(38,38,38); color-interpolation:linearRGB; stroke-width:0.6667;"
><line y2="297.7778" style="fill:none;" x1="73" x2="507" y1="297.7778"
/><line x1="73" x2="73" y1="297.7778" style="fill:none; stroke:rgb(0,114,189);" y2="286.0547"
/><line x1="109.1667" x2="109.1667" y1="297.7778" style="fill:none; stroke:rgb(0,114,189);" y2="319.2088"
/><line x1="145.3333" x2="145.3333" y1="297.7778" style="fill:none; stroke:rgb(0,114,189);" y2="342.9954"
/><line x1="181.5" x2="181.5" y1="297.7778" style="fill:none; stroke:rgb(0,114,189);" y2="311.9726"
/><line x1="217.6667" x2="217.6667" y1="297.7778" style="fill:none; stroke:rgb(0,114,189);" y2="217.5108"
/><line x1="253.8333" x2="253.8333" y1="297.7778" style="fill:none; stroke:rgb(0,114,189);" y2="109.4356"
/><line x1="290" x2="290" y1="297.7778" style="fill:none; stroke:rgb(0,114,189);" y2="61.7083"
/><line x1="326.1667" x2="326.1667" y1="297.7778" style="fill:none; stroke:rgb(0,114,189);" y2="109.4356"
/><line x1="362.3333" x2="362.3333" y1="297.7778" style="fill:none; stroke:rgb(0,114,189);" y2="217.5108"
/><line x1="398.5" x2="398.5" y1="297.7778" style="fill:none; stroke:rgb(0,114,189);" y2="311.9726"
/><line x1="434.6667" x2="434.6667" y1="297.7778" style="fill:none; stroke:rgb(0,114,189);" y2="342.9954"
/><line x1="470.8333" x2="470.8333" y1="297.7778" style="fill:none; stroke:rgb(0,114,189);" y2="319.2088"
/><line x1="507" x2="507" y1="297.7778" style="fill:none; stroke:rgb(0,114,189);" y2="286.0547"
/></g
><g transform="translate(73,286.0547)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(73,286.0547)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(109.1667,319.2088)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(109.1667,319.2088)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(145.3333,342.9954)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(145.3333,342.9954)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(181.5,311.9726)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(181.5,311.9726)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(217.6667,217.5108)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(217.6667,217.5108)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(253.8333,109.4356)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(253.8333,109.4356)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(290,61.7083)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(290,61.7083)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(326.1667,109.4356)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(326.1667,109.4356)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(362.3333,217.5108)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(362.3333,217.5108)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(398.5,311.9726)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(398.5,311.9726)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(434.6667,342.9954)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(434.6667,342.9954)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(470.8333,319.2088)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(470.8333,319.2088)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(507,286.0547)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(507,286.0547)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/><line transform="translate(-507,-286.0547)" x1="73" x2="507" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="374"
/><line transform="translate(-507,-286.0547)" x1="73" x2="507" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="31"
/><line transform="translate(-507,-286.0547)" x1="73" x2="73" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="369.66"
/><line transform="translate(-507,-286.0547)" x1="145.3333" x2="145.3333" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="369.66"
/><line transform="translate(-507,-286.0547)" x1="217.6667" x2="217.6667" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="369.66"
/><line transform="translate(-507,-286.0547)" x1="290" x2="290" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="369.66"
/><line transform="translate(-507,-286.0547)" x1="362.3333" x2="362.3333" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="369.66"
/><line transform="translate(-507,-286.0547)" x1="434.6667" x2="434.6667" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="369.66"
/><line transform="translate(-507,-286.0547)" x1="507" x2="507" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="369.66"
/><line transform="translate(-507,-286.0547)" x1="73" x2="73" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="35.34"
/><line transform="translate(-507,-286.0547)" x1="145.3333" x2="145.3333" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="35.34"
/><line transform="translate(-507,-286.0547)" x1="217.6667" x2="217.6667" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="35.34"
/><line transform="translate(-507,-286.0547)" x1="290" x2="290" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="35.34"
/><line transform="translate(-507,-286.0547)" x1="362.3333" x2="362.3333" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="35.34"
/><line transform="translate(-507,-286.0547)" x1="434.6667" x2="434.6667" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="35.34"
/><line transform="translate(-507,-286.0547)" x1="507" x2="507" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="35.34"
/></g
><g transform="translate(73,379.3333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-4" xml:space="preserve" y="14" style="stroke:none;"
>0</text
></g
><g transform="translate(145.3333,379.3333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-4" xml:space="preserve" y="14" style="stroke:none;"
>2</text
></g
><g transform="translate(217.6667,379.3333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-4" xml:space="preserve" y="14" style="stroke:none;"
>4</text
></g
><g transform="translate(290,379.3333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-4" xml:space="preserve" y="14" style="stroke:none;"
>6</text
></g
><g transform="translate(362.3333,379.3333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-4" xml:space="preserve" y="14" style="stroke:none;"
>8</text
></g
><g transform="translate(434.6667,379.3333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-7.5" xml:space="preserve" y="14" style="stroke:none;"
>10</text
></g
><g transform="translate(507,379.3333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-7.5" xml:space="preserve" y="14" style="stroke:none;"
>12</text
></g
><g transform="translate(290.0002,397.6667)" style="font-size:14.6667px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-38.5" xml:space="preserve" y="15" style="stroke:none;"
>n (samples)</text
></g
></g
></svg
>

After

Width:  |  Height:  |  Size: 47 KiB

@@ -0,0 +1,365 @@
<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.0//EN'
'http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd'>
<svg xmlns:xlink="http://www.w3.org/1999/xlink" style="fill-opacity:1; color-rendering:auto; color-interpolation:auto; text-rendering:auto; stroke:black; stroke-linecap:square; stroke-miterlimit:10; shape-rendering:auto; stroke-opacity:1; fill:black; stroke-dasharray:none; font-weight:normal; stroke-width:1; font-family:'Dialog'; font-style:normal; stroke-linejoin:miter; font-size:12px; stroke-dashoffset:0; image-rendering:auto;" width="560" height="420" xmlns="http://www.w3.org/2000/svg"
><!--Generated by the Batik Graphics2D SVG Generator--><defs id="genericDefs"
/><g
><defs id="defs1"
><clipPath clipPathUnits="userSpaceOnUse" id="clipPath1"
><path d="M0 0 L560 0 L560 420 L0 420 L0 0 Z"
/></clipPath
><font horiz-adv-x="75.0" id="font1"
><font-face ascent="100.53711" descent="21.972656" units-per-em="100" style="font-style:normal; font-family:Dialog; font-weight:normal;"
/><missing-glyph horiz-adv-x="75.0" d="M12.5 0 L12.5 62.5 L62.5 62.5 L62.5 0 L12.5 0 ZM14.0625 1.5625 L60.9375 1.5625 L60.9375 60.9375 L14.0625 60.9375 L14.0625 1.5625 Z"
/><glyph unicode="2" horiz-adv-x="55.615234" d="M50.3438 8.4531 L50.3438 0 L3.0312 0 Q2.9375 3.1719 4.0469 6.1094 Q5.8594 10.9375 9.8359 15.625 Q13.8125 20.3125 21.3438 26.4688 Q33.0156 36.0312 37.1172 41.625 Q41.2188 47.2188 41.2188 52.2031 Q41.2188 57.4219 37.4766 61.0078 Q33.7344 64.5938 27.7344 64.5938 Q21.3906 64.5938 17.5781 60.7891 Q13.7656 56.9844 13.7188 50.25 L4.6875 51.1719 Q5.6094 61.2812 11.6641 66.5781 Q17.7188 71.875 27.9375 71.875 Q38.2344 71.875 44.2422 66.1641 Q50.25 60.4531 50.25 52 Q50.25 47.7031 48.4922 43.5547 Q46.7344 39.4062 42.6562 34.8125 Q38.5781 30.2188 29.1094 22.2188 Q21.1875 15.5781 18.9453 13.2109 Q16.7031 10.8438 15.2344 8.4531 L50.3438 8.4531 Z"
/><glyph unicode="." horiz-adv-x="27.783203" d="M9.0781 0 L9.0781 10.0156 L19.0938 10.0156 L19.0938 0 L9.0781 0 Z"
/><glyph unicode="0" horiz-adv-x="55.615234" d="M4.1562 35.2969 Q4.1562 48 6.7656 55.7422 Q9.375 63.4844 14.5234 67.6797 Q19.6719 71.875 27.4844 71.875 Q33.25 71.875 37.5938 69.5547 Q41.9375 67.2344 44.7734 62.8672 Q47.6094 58.5 49.2188 52.2266 Q50.8281 45.9531 50.8281 35.2969 Q50.8281 22.7031 48.2422 14.9688 Q45.6562 7.2344 40.5078 3.0078 Q35.3594 -1.2188 27.4844 -1.2188 Q17.1406 -1.2188 11.2344 6.2031 Q4.1562 15.1406 4.1562 35.2969 ZM13.1875 35.2969 Q13.1875 17.6719 17.3125 11.8359 Q21.4375 6 27.4844 6 Q33.5469 6 37.6719 11.8594 Q41.7969 17.7188 41.7969 35.2969 Q41.7969 52.9844 37.6719 58.7891 Q33.5469 64.5938 27.3906 64.5938 Q21.3438 64.5938 17.7188 59.4688 Q13.1875 52.9375 13.1875 35.2969 Z"
/><glyph unicode="-" horiz-adv-x="33.30078" d="M3.1719 21.4844 L3.1719 30.3281 L30.1719 30.3281 L30.1719 21.4844 L3.1719 21.4844 Z"
/><glyph unicode="4" horiz-adv-x="55.615234" d="M32.3281 0 L32.3281 17.1406 L1.2656 17.1406 L1.2656 25.2031 L33.9375 71.5781 L41.1094 71.5781 L41.1094 25.2031 L50.7812 25.2031 L50.7812 17.1406 L41.1094 17.1406 L41.1094 0 L32.3281 0 ZM32.3281 25.2031 L32.3281 57.4688 L9.9062 25.2031 L32.3281 25.2031 Z"
/><glyph unicode="6" horiz-adv-x="55.615234" d="M49.75 54.0469 L41.0156 53.375 Q39.8438 58.5469 37.7031 60.8906 Q34.125 64.6562 28.9062 64.6562 Q24.7031 64.6562 21.5312 62.3125 Q17.3906 59.2812 14.9922 53.4688 Q12.5938 47.6562 12.5 36.9219 Q15.6719 41.75 20.2656 44.0938 Q24.8594 46.4375 29.8906 46.4375 Q38.6719 46.4375 44.8516 39.9688 Q51.0312 33.5 51.0312 23.25 Q51.0312 16.5 48.125 10.7188 Q45.2188 4.9375 40.1406 1.8594 Q35.0625 -1.2188 28.6094 -1.2188 Q17.625 -1.2188 10.6953 6.8594 Q3.7656 14.9375 3.7656 33.5 Q3.7656 54.25 11.4219 63.6719 Q18.1094 71.875 29.4375 71.875 Q37.8906 71.875 43.2891 67.1406 Q48.6875 62.4062 49.75 54.0469 ZM13.875 23.1875 Q13.875 18.6562 15.7969 14.5078 Q17.7188 10.3594 21.1875 8.1797 Q24.6562 6 28.4688 6 Q34.0312 6 38.0391 10.4922 Q42.0469 14.9844 42.0469 22.7031 Q42.0469 30.125 38.0859 34.3984 Q34.125 38.6719 28.125 38.6719 Q22.1719 38.6719 18.0234 34.3984 Q13.875 30.125 13.875 23.1875 Z"
/><glyph unicode="8" horiz-adv-x="55.615234" d="M17.6719 38.8125 Q12.2031 40.8281 9.5703 44.5391 Q6.9375 48.25 6.9375 53.4219 Q6.9375 61.2344 12.5547 66.5547 Q18.1719 71.875 27.4844 71.875 Q36.8594 71.875 42.5781 66.4297 Q48.2969 60.9844 48.2969 53.1719 Q48.2969 48.1875 45.6797 44.5078 Q43.0625 40.8281 37.75 38.8125 Q44.3438 36.6719 47.7812 31.8828 Q51.2188 27.0938 51.2188 20.4531 Q51.2188 11.2812 44.7266 5.0312 Q38.2344 -1.2188 27.6406 -1.2188 Q17.0469 -1.2188 10.5469 5.0547 Q4.0469 11.3281 4.0469 20.7031 Q4.0469 27.6875 7.5938 32.3984 Q11.1406 37.1094 17.6719 38.8125 ZM15.9219 53.7188 Q15.9219 48.6406 19.1953 45.4141 Q22.4688 42.1875 27.6875 42.1875 Q32.7656 42.1875 36.0156 45.3828 Q39.2656 48.5781 39.2656 53.2188 Q39.2656 58.0625 35.9141 61.3594 Q32.5625 64.6562 27.5938 64.6562 Q22.5625 64.6562 19.2422 61.4297 Q15.9219 58.2031 15.9219 53.7188 ZM13.0938 20.6562 Q13.0938 16.8906 14.875 13.375 Q16.6562 9.8594 20.1719 7.9297 Q23.6875 6 27.7344 6 Q34.0312 6 38.1328 10.0547 Q42.2344 14.1094 42.2344 20.3594 Q42.2344 26.7031 38.0156 30.8594 Q33.7969 35.0156 27.4375 35.0156 Q21.2344 35.0156 17.1641 30.9141 Q13.0938 26.8125 13.0938 20.6562 Z"
/><glyph unicode="1" horiz-adv-x="55.615234" d="M37.25 0 L28.4688 0 L28.4688 56 Q25.2969 52.9844 20.1406 49.9531 Q14.9844 46.9219 10.8906 45.4062 L10.8906 53.9062 Q18.2656 57.375 23.7812 62.3047 Q29.2969 67.2344 31.5938 71.875 L37.25 71.875 L37.25 0 Z"
/><glyph unicode="u" horiz-adv-x="55.615234" d="M40.5781 0 L40.5781 7.625 Q34.5156 -1.1719 24.125 -1.1719 Q19.5312 -1.1719 15.5547 0.5859 Q11.5781 2.3438 9.6484 5.0078 Q7.7188 7.6719 6.9375 11.5312 Q6.3906 14.1094 6.3906 19.7344 L6.3906 51.8594 L15.1875 51.8594 L15.1875 23.0938 Q15.1875 16.2188 15.7188 13.8125 Q16.5469 10.3594 19.2344 8.375 Q21.9219 6.3906 25.875 6.3906 Q29.8281 6.3906 33.2969 8.4219 Q36.7656 10.4531 38.2109 13.9453 Q39.6562 17.4375 39.6562 24.0781 L39.6562 51.8594 L48.4375 51.8594 L48.4375 0 L40.5781 0 Z"
/><glyph unicode="t" horiz-adv-x="27.783203" d="M25.7812 7.8594 L27.0469 0.0938 Q23.3438 -0.6875 20.4062 -0.6875 Q15.625 -0.6875 12.9922 0.8281 Q10.3594 2.3438 9.2812 4.8125 Q8.2031 7.2812 8.2031 15.1875 L8.2031 45.0156 L1.7656 45.0156 L1.7656 51.8594 L8.2031 51.8594 L8.2031 64.7031 L16.9375 69.9688 L16.9375 51.8594 L25.7812 51.8594 L25.7812 45.0156 L16.9375 45.0156 L16.9375 14.7031 Q16.9375 10.9375 17.4062 9.8672 Q17.875 8.7969 18.9219 8.1562 Q19.9688 7.5156 21.9219 7.5156 Q23.3906 7.5156 25.7812 7.8594 Z"
/><glyph unicode="p" horiz-adv-x="55.615234" d="M6.5938 -19.875 L6.5938 51.8594 L14.5938 51.8594 L14.5938 45.125 Q17.4375 49.0781 21 51.0547 Q24.5625 53.0312 29.6406 53.0312 Q36.2812 53.0312 41.3594 49.6094 Q46.4375 46.1875 49.0234 39.9609 Q51.6094 33.7344 51.6094 26.3125 Q51.6094 18.3594 48.7578 11.9844 Q45.9062 5.6094 40.4609 2.2188 Q35.0156 -1.1719 29 -1.1719 Q24.6094 -1.1719 21.1172 0.6875 Q17.625 2.5469 15.375 5.375 L15.375 -19.875 L6.5938 -19.875 ZM14.5469 25.6406 Q14.5469 15.625 18.6016 10.8438 Q22.6562 6.0625 28.4219 6.0625 Q34.2812 6.0625 38.4531 11.0156 Q42.625 15.9688 42.625 26.375 Q42.625 36.2812 38.5469 41.2109 Q34.4688 46.1406 28.8125 46.1406 Q23.1875 46.1406 18.8672 40.8906 Q14.5469 35.6406 14.5469 25.6406 Z"
/><glyph unicode="A" horiz-adv-x="66.69922" d="M-0.1406 0 L27.3438 71.5781 L37.5469 71.5781 L66.8438 0 L56.0625 0 L47.7031 21.6875 L17.7812 21.6875 L9.9062 0 L-0.1406 0 ZM20.5156 29.3906 L44.7812 29.3906 L37.3125 49.2188 Q33.8906 58.25 32.2344 64.0625 Q30.8594 57.1719 28.375 50.3906 L20.5156 29.3906 Z"
/><glyph unicode=" " horiz-adv-x="27.783203" d=""
/><glyph unicode="d" horiz-adv-x="55.615234" d="M40.2344 0 L40.2344 6.5469 Q35.2969 -1.1719 25.7344 -1.1719 Q19.5312 -1.1719 14.3281 2.25 Q9.125 5.6719 6.2734 11.7969 Q3.4219 17.9219 3.4219 25.875 Q3.4219 33.6406 6.0078 39.9688 Q8.5938 46.2969 13.7734 49.6641 Q18.9531 53.0312 25.3438 53.0312 Q30.0312 53.0312 33.6953 51.0547 Q37.3594 49.0781 39.6562 45.9062 L39.6562 71.5781 L48.3906 71.5781 L48.3906 0 L40.2344 0 ZM12.4531 25.875 Q12.4531 15.9219 16.6484 10.9922 Q20.8438 6.0625 26.5625 6.0625 Q32.3281 6.0625 36.3516 10.7734 Q40.375 15.4844 40.375 25.1406 Q40.375 35.7969 36.2734 40.7734 Q32.1719 45.75 26.1719 45.75 Q20.3125 45.75 16.3828 40.9688 Q12.4531 36.1875 12.4531 25.875 Z"
/><glyph unicode="e" horiz-adv-x="55.615234" d="M42.0938 16.7031 L51.1719 15.5781 Q49.0312 7.625 43.2188 3.2266 Q37.4062 -1.1719 28.375 -1.1719 Q17 -1.1719 10.3281 5.8359 Q3.6562 12.8438 3.6562 25.4844 Q3.6562 38.5781 10.3984 45.8047 Q17.1406 53.0312 27.875 53.0312 Q38.2812 53.0312 44.875 45.9531 Q51.4688 38.875 51.4688 26.0312 Q51.4688 25.25 51.4219 23.6875 L12.75 23.6875 Q13.2344 15.1406 17.5781 10.6016 Q21.9219 6.0625 28.4219 6.0625 Q33.25 6.0625 36.6719 8.6016 Q40.0938 11.1406 42.0938 16.7031 ZM13.2344 30.9062 L42.1875 30.9062 Q41.6094 37.4531 38.875 40.7188 Q34.6719 45.7969 27.9844 45.7969 Q21.9219 45.7969 17.7969 41.75 Q13.6719 37.7031 13.2344 30.9062 Z"
/><glyph unicode="z" horiz-adv-x="50.0" d="M1.9531 0 L1.9531 7.125 L34.9688 45.0156 Q29.3438 44.7344 25.0469 44.7344 L3.9062 44.7344 L3.9062 51.8594 L46.2969 51.8594 L46.2969 46.0469 L18.2188 13.1406 L12.7969 7.125 Q18.7031 7.5625 23.875 7.5625 L47.8594 7.5625 L47.8594 0 L1.9531 0 Z"
/><glyph unicode="i" horiz-adv-x="22.216797" d="M6.6406 61.4688 L6.6406 71.5781 L15.4375 71.5781 L15.4375 61.4688 L6.6406 61.4688 ZM6.6406 0 L6.6406 51.8594 L15.4375 51.8594 L15.4375 0 L6.6406 0 Z"
/><glyph unicode="l" horiz-adv-x="22.216797" d="M6.3906 0 L6.3906 71.5781 L15.1875 71.5781 L15.1875 0 L6.3906 0 Z"
/><glyph unicode="a" horiz-adv-x="55.615234" d="M40.4375 6.3906 Q35.5469 2.25 31.0312 0.5391 Q26.5156 -1.1719 21.3438 -1.1719 Q12.7969 -1.1719 8.2031 3 Q3.6094 7.1719 3.6094 13.6719 Q3.6094 17.4844 5.3438 20.6328 Q7.0781 23.7812 9.8906 25.6875 Q12.7031 27.5938 16.2188 28.5625 Q18.7969 29.25 24.0312 29.8906 Q34.6719 31.1562 39.7031 32.9062 Q39.75 34.7188 39.75 35.2031 Q39.75 40.5781 37.25 42.7812 Q33.8906 45.75 27.25 45.75 Q21.0469 45.75 18.0938 43.5781 Q15.1406 41.4062 13.7188 35.8906 L5.125 37.0625 Q6.2969 42.5781 8.9844 45.9688 Q11.6719 49.3594 16.75 51.1953 Q21.8281 53.0312 28.5156 53.0312 Q35.1562 53.0312 39.3047 51.4688 Q43.4531 49.9062 45.4062 47.5391 Q47.3594 45.1719 48.1406 41.5469 Q48.5781 39.3125 48.5781 33.4531 L48.5781 21.7344 Q48.5781 9.4688 49.1406 6.2266 Q49.7031 2.9844 51.375 0 L42.1875 0 Q40.8281 2.7344 40.4375 6.3906 ZM39.7031 26.0312 Q34.9062 24.0781 25.3438 22.7031 Q19.9219 21.9219 17.6797 20.9453 Q15.4375 19.9688 14.2109 18.0938 Q12.9844 16.2188 12.9844 13.9219 Q12.9844 10.4062 15.6484 8.0625 Q18.3125 5.7188 23.4375 5.7188 Q28.5156 5.7188 32.4688 7.9375 Q36.4219 10.1562 38.2812 14.0156 Q39.7031 17 39.7031 22.7969 L39.7031 26.0312 Z"
/><glyph unicode="m" horiz-adv-x="83.30078" d="M6.5938 0 L6.5938 51.8594 L14.4531 51.8594 L14.4531 44.5781 Q16.8906 48.3906 20.9453 50.7109 Q25 53.0312 30.1719 53.0312 Q35.9375 53.0312 39.625 50.6406 Q43.3125 48.25 44.8281 43.9531 Q50.9844 53.0312 60.8438 53.0312 Q68.5625 53.0312 72.7109 48.7578 Q76.8594 44.4844 76.8594 35.5938 L76.8594 0 L68.1094 0 L68.1094 32.6719 Q68.1094 37.9375 67.2578 40.2578 Q66.4062 42.5781 64.1641 43.9922 Q61.9219 45.4062 58.8906 45.4062 Q53.4219 45.4062 49.8047 41.7734 Q46.1875 38.1406 46.1875 30.125 L46.1875 0 L37.4062 0 L37.4062 33.6875 Q37.4062 39.5469 35.2578 42.4766 Q33.1094 45.4062 28.2188 45.4062 Q24.5156 45.4062 21.3672 43.4531 Q18.2188 41.5 16.7969 37.7422 Q15.375 33.9844 15.375 26.9062 L15.375 0 L6.5938 0 Z"
/><glyph unicode="r" horiz-adv-x="33.30078" d="M6.5 0 L6.5 51.8594 L14.4062 51.8594 L14.4062 44 Q17.4375 49.5156 20 51.2734 Q22.5625 53.0312 25.6406 53.0312 Q30.0781 53.0312 34.6719 50.2031 L31.6406 42.0469 Q28.4219 43.9531 25.2031 43.9531 Q22.3125 43.9531 20.0156 42.2188 Q17.7188 40.4844 16.75 37.4062 Q15.2812 32.7188 15.2812 27.1562 L15.2812 0 L6.5 0 Z"
/><glyph unicode="o" horiz-adv-x="55.615234" d="M3.3281 25.9219 Q3.3281 40.3281 11.3281 47.2656 Q18.0156 53.0312 27.6406 53.0312 Q38.3281 53.0312 45.1172 46.0234 Q51.9062 39.0156 51.9062 26.6562 Q51.9062 16.6562 48.9062 10.9141 Q45.9062 5.1719 40.1641 2 Q34.4219 -1.1719 27.6406 -1.1719 Q16.75 -1.1719 10.0391 5.8125 Q3.3281 12.7969 3.3281 25.9219 ZM12.3594 25.9219 Q12.3594 15.9688 16.7031 11.0156 Q21.0469 6.0625 27.6406 6.0625 Q34.1875 6.0625 38.5312 11.0391 Q42.875 16.0156 42.875 26.2188 Q42.875 35.8438 38.5 40.7969 Q34.125 45.75 27.6406 45.75 Q21.0469 45.75 16.7031 40.8203 Q12.3594 35.8906 12.3594 25.9219 Z"
/><glyph unicode="N" horiz-adv-x="72.2168" d="M7.625 0 L7.625 71.5781 L17.3281 71.5781 L54.9375 15.375 L54.9375 71.5781 L64.0156 71.5781 L64.0156 0 L54.2969 0 L16.7031 56.25 L16.7031 0 L7.625 0 Z"
/><glyph unicode="s" horiz-adv-x="50.0" d="M3.0781 15.4844 L11.7656 16.8438 Q12.5 11.625 15.8438 8.8438 Q19.1875 6.0625 25.2031 6.0625 Q31.25 6.0625 34.1797 8.5234 Q37.1094 10.9844 37.1094 14.3125 Q37.1094 17.2812 34.5156 19 Q32.7188 20.1719 25.5312 21.9688 Q15.875 24.4219 12.1406 26.2031 Q8.4062 27.9844 6.4766 31.1328 Q4.5469 34.2812 4.5469 38.0938 Q4.5469 41.5469 6.1328 44.5078 Q7.7188 47.4688 10.4531 49.4219 Q12.5 50.9219 16.0391 51.9766 Q19.5781 53.0312 23.6406 53.0312 Q29.7344 53.0312 34.3516 51.2734 Q38.9688 49.5156 41.1641 46.5078 Q43.3594 43.5 44.1875 38.4844 L35.5938 37.3125 Q35.0156 41.3125 32.2031 43.5547 Q29.3906 45.7969 24.2656 45.7969 Q18.2188 45.7969 15.625 43.7969 Q13.0312 41.7969 13.0312 39.1094 Q13.0312 37.4062 14.1094 36.0312 Q15.1875 34.625 17.4844 33.6875 Q18.7969 33.2031 25.25 31.4531 Q34.5781 28.9531 38.2578 27.3672 Q41.9375 25.7812 44.0391 22.7578 Q46.1406 19.7344 46.1406 15.2344 Q46.1406 10.8438 43.5781 6.9609 Q41.0156 3.0781 36.1797 0.9531 Q31.3438 -1.1719 25.25 -1.1719 Q15.1406 -1.1719 9.8438 3.0312 Q4.5469 7.2344 3.0781 15.4844 Z"
/><glyph unicode="S" horiz-adv-x="66.69922" d="M4.5 23 L13.4219 23.7812 Q14.0625 18.4062 16.3828 14.9688 Q18.7031 11.5312 23.5859 9.4062 Q28.4688 7.2812 34.5781 7.2812 Q39.9844 7.2812 44.1406 8.8906 Q48.2969 10.5 50.3203 13.3047 Q52.3438 16.1094 52.3438 19.4375 Q52.3438 22.7969 50.3906 25.3125 Q48.4375 27.8281 43.9531 29.5469 Q41.0625 30.6719 31.2031 33.0391 Q21.3438 35.4062 17.3906 37.5 Q12.25 40.1875 9.7422 44.1641 Q7.2344 48.1406 7.2344 53.0781 Q7.2344 58.5 10.3047 63.2109 Q13.375 67.9219 19.2891 70.3594 Q25.2031 72.7969 32.4219 72.7969 Q40.375 72.7969 46.4609 70.2344 Q52.5469 67.6719 55.8125 62.6953 Q59.0781 57.7188 59.3281 51.4219 L50.25 50.7344 Q49.5156 57.5156 45.2891 60.9844 Q41.0625 64.4531 32.8125 64.4531 Q24.2188 64.4531 20.2891 61.3047 Q16.3594 58.1562 16.3594 53.7188 Q16.3594 49.8594 19.1406 47.3594 Q21.875 44.875 33.4219 42.2656 Q44.9688 39.6562 49.2656 37.7031 Q55.5156 34.8125 58.4922 30.3984 Q61.4688 25.9844 61.4688 20.2188 Q61.4688 14.5 58.2031 9.4453 Q54.9375 4.3906 48.8047 1.5859 Q42.6719 -1.2188 35.0156 -1.2188 Q25.2969 -1.2188 18.7266 1.6094 Q12.1562 4.4375 8.4219 10.1328 Q4.6875 15.8281 4.5 23 Z"
/><glyph unicode="h" horiz-adv-x="55.615234" d="M6.5938 0 L6.5938 71.5781 L15.375 71.5781 L15.375 45.9062 Q21.5312 53.0312 30.9062 53.0312 Q36.6719 53.0312 40.9219 50.7578 Q45.1719 48.4844 47 44.4844 Q48.8281 40.4844 48.8281 32.8594 L48.8281 0 L40.0469 0 L40.0469 32.8594 Q40.0469 39.4531 37.1875 42.4531 Q34.3281 45.4531 29.1094 45.4531 Q25.2031 45.4531 21.7578 43.4297 Q18.3125 41.4062 16.8438 37.9375 Q15.375 34.4688 15.375 28.375 L15.375 0 L6.5938 0 Z"
/><glyph unicode="*" horiz-adv-x="38.916016" d="M3.125 58.4531 L5.375 65.375 Q13.1406 62.6406 16.6562 60.6406 Q15.7188 69.4844 15.6719 72.7969 L22.75 72.7969 Q22.6094 67.9688 21.625 60.6875 Q26.6562 63.2344 33.1562 65.375 L35.4062 58.4531 Q29.2031 56.3906 23.25 55.7188 Q26.2188 53.125 31.6406 46.4844 L25.7812 42.3281 Q22.9531 46.1875 19.0938 52.8281 Q15.4844 45.9531 12.75 42.3281 L6.9844 46.4844 Q12.6406 53.4688 15.0938 55.7188 Q8.7969 56.9375 3.125 58.4531 Z"
/></font
></defs
><g style="fill:white; stroke:white;"
><rect x="0" y="0" width="560" style="clip-path:url(#clipPath1); stroke:none;" height="420"
/></g
><g style="fill:white; text-rendering:optimizeSpeed; color-rendering:optimizeSpeed; image-rendering:optimizeSpeed; shape-rendering:crispEdges; stroke:white; color-interpolation:sRGB;"
><rect x="0" width="560" height="420" y="0" style="stroke:none;"
/><path style="stroke:none;" d="M73 374 L507 374 L507 31 L73 31 Z"
/></g
><g style="fill:rgb(38,38,38); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(38,38,38); color-interpolation:linearRGB; stroke-width:0.6667;"
><line y2="31" style="fill:none;" x1="73" x2="73" y1="374"
/><line y2="31" style="fill:none;" x1="507" x2="507" y1="374"
/><line y2="374" style="fill:none;" x1="73" x2="77.34" y1="374"
/><line y2="316.8333" style="fill:none;" x1="73" x2="77.34" y1="316.8333"
/><line y2="259.6667" style="fill:none;" x1="73" x2="77.34" y1="259.6667"
/><line y2="202.5" style="fill:none;" x1="73" x2="77.34" y1="202.5"
/><line y2="145.3333" style="fill:none;" x1="73" x2="77.34" y1="145.3333"
/><line y2="88.1667" style="fill:none;" x1="73" x2="77.34" y1="88.1667"
/><line y2="31" style="fill:none;" x1="73" x2="77.34" y1="31"
/><line y2="374" style="fill:none;" x1="507" x2="502.66" y1="374"
/><line y2="316.8333" style="fill:none;" x1="507" x2="502.66" y1="316.8333"
/><line y2="259.6667" style="fill:none;" x1="507" x2="502.66" y1="259.6667"
/><line y2="202.5" style="fill:none;" x1="507" x2="502.66" y1="202.5"
/><line y2="145.3333" style="fill:none;" x1="507" x2="502.66" y1="145.3333"
/><line y2="88.1667" style="fill:none;" x1="507" x2="502.66" y1="88.1667"
/><line y2="31" style="fill:none;" x1="507" x2="502.66" y1="31"
/></g
><g transform="translate(67.6667,374)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-23" xml:space="preserve" y="5.5" style="stroke:none;"
>-0.2</text
></g
><g transform="translate(67.6667,316.8333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-8" xml:space="preserve" y="5.5" style="stroke:none;"
>0</text
></g
><g transform="translate(67.6667,259.6667)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-19" xml:space="preserve" y="5.5" style="stroke:none;"
>0.2</text
></g
><g transform="translate(67.6667,202.5)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-19" xml:space="preserve" y="5.5" style="stroke:none;"
>0.4</text
></g
><g transform="translate(67.6667,145.3333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-19" xml:space="preserve" y="5.5" style="stroke:none;"
>0.6</text
></g
><g transform="translate(67.6667,88.1667)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-19" xml:space="preserve" y="5.5" style="stroke:none;"
>0.8</text
></g
><g transform="translate(67.6667,31)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-8" xml:space="preserve" y="5.5" style="stroke:none;"
>1</text
></g
><g transform="translate(40.6667,202.4998) rotate(-90)" style="font-size:14.6667px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-72" xml:space="preserve" y="-4" style="stroke:none;"
>Normalized Amplitude</text
></g
><g style="stroke-linecap:butt; fill:rgb(38,38,38); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(38,38,38); color-interpolation:linearRGB; stroke-width:0.6667;"
><line y2="316.8333" style="fill:none;" x1="73" x2="507" y1="316.8333"
/><line x1="73" x2="73" y1="316.8333" style="fill:none; stroke:rgb(0,114,189);" y2="316.8333"
/><line x1="109.1667" x2="109.1667" y1="316.8333" style="fill:none; stroke:rgb(0,114,189);" y2="356.8786"
/><line x1="145.3333" x2="145.3333" y1="316.8333" style="fill:none; stroke:rgb(0,114,189);" y2="370.0193"
/><line x1="181.5" x2="181.5" y1="316.8333" style="fill:none; stroke:rgb(0,114,189);" y2="316.8333"
/><line x1="217.6667" x2="217.6667" y1="316.8333" style="fill:none; stroke:rgb(0,114,189);" y2="201.6823"
/><line x1="253.8333" x2="253.8333" y1="316.8333" style="fill:none; stroke:rgb(0,114,189);" y2="81.9819"
/><line x1="290" x2="290" y1="316.8333" style="fill:none; stroke:rgb(0,114,189);" y2="31"
/><line x1="326.1667" x2="326.1667" y1="316.8333" style="fill:none; stroke:rgb(0,114,189);" y2="81.9819"
/><line x1="362.3333" x2="362.3333" y1="316.8333" style="fill:none; stroke:rgb(0,114,189);" y2="201.6823"
/><line x1="398.5" x2="398.5" y1="316.8333" style="fill:none; stroke:rgb(0,114,189);" y2="316.8333"
/><line x1="434.6667" x2="434.6667" y1="316.8333" style="fill:none; stroke:rgb(0,114,189);" y2="370.0193"
/><line x1="470.8333" x2="470.8333" y1="316.8333" style="fill:none; stroke:rgb(0,114,189);" y2="356.8786"
/><line x1="507" x2="507" y1="316.8333" style="fill:none; stroke:rgb(0,114,189);" y2="316.8333"
/></g
><g transform="translate(73,316.8333)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(73,316.8333)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(109.1667,356.8786)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(109.1667,356.8786)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(145.3333,370.0193)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(145.3333,370.0193)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(181.5,316.8333)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(181.5,316.8333)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(217.6667,201.6823)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(217.6667,201.6823)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(253.8333,81.9819)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(253.8333,81.9819)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(290,31)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(290,31)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(326.1667,81.9819)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(326.1667,81.9819)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(362.3333,201.6823)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(362.3333,201.6823)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(398.5,316.8333)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(398.5,316.8333)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(434.6667,370.0193)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(434.6667,370.0193)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(470.8333,356.8786)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(470.8333,356.8786)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(507,316.8333)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(507,316.8333)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/><line transform="translate(-507,-316.8333)" x1="73" x2="73" y1="316.8333" style="fill:none; stroke:rgb(217,83,25);" y2="335.7162"
/><line transform="translate(-507,-316.8333)" x1="109.1667" x2="109.1667" y1="316.8333" style="fill:none; stroke:rgb(217,83,25);" y2="366.0592"
/><line transform="translate(-507,-316.8333)" x1="145.3333" x2="145.3333" y1="316.8333" style="fill:none; stroke:rgb(217,83,25);" y2="368.8731"
/><line transform="translate(-507,-316.8333)" x1="181.5" x2="181.5" y1="316.8333" style="fill:none; stroke:rgb(217,83,25);" y2="311.4659"
/><line transform="translate(-507,-316.8333)" x1="217.6667" x2="217.6667" y1="316.8333" style="fill:none; stroke:rgb(217,83,25);" y2="198.1429"
/><line transform="translate(-507,-316.8333)" x1="253.8333" x2="253.8333" y1="316.8333" style="fill:none; stroke:rgb(217,83,25);" y2="81.4696"
/><line transform="translate(-507,-316.8333)" x1="290" x2="290" y1="316.8333" style="fill:none; stroke:rgb(217,83,25);" y2="31"
/><line transform="translate(-507,-316.8333)" x1="326.1667" x2="326.1667" y1="316.8333" style="fill:none; stroke:rgb(217,83,25);" y2="81.4696"
/><line transform="translate(-507,-316.8333)" x1="362.3333" x2="362.3333" y1="316.8333" style="fill:none; stroke:rgb(217,83,25);" y2="198.1429"
/><line transform="translate(-507,-316.8333)" x1="398.5" x2="398.5" y1="316.8333" style="fill:none; stroke:rgb(217,83,25);" y2="311.4659"
/><line transform="translate(-507,-316.8333)" x1="434.6667" x2="434.6667" y1="316.8333" style="fill:none; stroke:rgb(217,83,25);" y2="368.8731"
/><line transform="translate(-507,-316.8333)" x1="470.8333" x2="470.8333" y1="316.8333" style="fill:none; stroke:rgb(217,83,25);" y2="366.0592"
/><line transform="translate(-507,-316.8333)" x1="507" x2="507" y1="316.8333" style="fill:none; stroke:rgb(217,83,25);" y2="335.7162"
/></g
><g transform="translate(73,335.7162)" style="fill:rgb(217,83,25); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(217,83,25);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(73,335.7162)" style="stroke-linecap:butt; fill:rgb(217,83,25); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(217,83,25); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(109.1667,366.0592)" style="fill:rgb(217,83,25); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(217,83,25);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(109.1667,366.0592)" style="stroke-linecap:butt; fill:rgb(217,83,25); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(217,83,25); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(145.3333,368.8731)" style="fill:rgb(217,83,25); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(217,83,25);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(145.3333,368.8731)" style="stroke-linecap:butt; fill:rgb(217,83,25); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(217,83,25); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(181.5,311.4659)" style="fill:rgb(217,83,25); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(217,83,25);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(181.5,311.4659)" style="stroke-linecap:butt; fill:rgb(217,83,25); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(217,83,25); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(217.6667,198.1429)" style="fill:rgb(217,83,25); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(217,83,25);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(217.6667,198.1429)" style="stroke-linecap:butt; fill:rgb(217,83,25); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(217,83,25); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(253.8333,81.4696)" style="fill:rgb(217,83,25); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(217,83,25);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(253.8333,81.4696)" style="stroke-linecap:butt; fill:rgb(217,83,25); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(217,83,25); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(290,31)" style="fill:rgb(217,83,25); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(217,83,25);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(290,31)" style="stroke-linecap:butt; fill:rgb(217,83,25); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(217,83,25); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(326.1667,81.4696)" style="fill:rgb(217,83,25); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(217,83,25);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(326.1667,81.4696)" style="stroke-linecap:butt; fill:rgb(217,83,25); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(217,83,25); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(362.3333,198.1429)" style="fill:rgb(217,83,25); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(217,83,25);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(362.3333,198.1429)" style="stroke-linecap:butt; fill:rgb(217,83,25); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(217,83,25); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(398.5,311.4659)" style="fill:rgb(217,83,25); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(217,83,25);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(398.5,311.4659)" style="stroke-linecap:butt; fill:rgb(217,83,25); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(217,83,25); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(434.6667,368.8731)" style="fill:rgb(217,83,25); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(217,83,25);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(434.6667,368.8731)" style="stroke-linecap:butt; fill:rgb(217,83,25); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(217,83,25); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(470.8333,366.0592)" style="fill:rgb(217,83,25); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(217,83,25);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(470.8333,366.0592)" style="stroke-linecap:butt; fill:rgb(217,83,25); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(217,83,25); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g transform="translate(507,335.7162)" style="fill:rgb(217,83,25); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(217,83,25);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(507,335.7162)" style="stroke-linecap:butt; fill:rgb(217,83,25); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(217,83,25); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/><line transform="translate(-507,-335.7162)" x1="73" x2="507" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="374"
/><line transform="translate(-507,-335.7162)" x1="73" x2="507" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="31"
/><line transform="translate(-507,-335.7162)" x1="73" x2="73" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="369.66"
/><line transform="translate(-507,-335.7162)" x1="145.3333" x2="145.3333" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="369.66"
/><line transform="translate(-507,-335.7162)" x1="217.6667" x2="217.6667" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="369.66"
/><line transform="translate(-507,-335.7162)" x1="290" x2="290" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="369.66"
/><line transform="translate(-507,-335.7162)" x1="362.3333" x2="362.3333" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="369.66"
/><line transform="translate(-507,-335.7162)" x1="434.6667" x2="434.6667" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="369.66"
/><line transform="translate(-507,-335.7162)" x1="507" x2="507" y1="374" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="369.66"
/><line transform="translate(-507,-335.7162)" x1="73" x2="73" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="35.34"
/><line transform="translate(-507,-335.7162)" x1="145.3333" x2="145.3333" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="35.34"
/><line transform="translate(-507,-335.7162)" x1="217.6667" x2="217.6667" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="35.34"
/><line transform="translate(-507,-335.7162)" x1="290" x2="290" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="35.34"
/><line transform="translate(-507,-335.7162)" x1="362.3333" x2="362.3333" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="35.34"
/><line transform="translate(-507,-335.7162)" x1="434.6667" x2="434.6667" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="35.34"
/><line transform="translate(-507,-335.7162)" x1="507" x2="507" y1="31" style="stroke-linecap:square; fill:none; stroke:rgb(38,38,38);" y2="35.34"
/></g
><g transform="translate(73,379.3333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-4" xml:space="preserve" y="14" style="stroke:none;"
>0</text
></g
><g transform="translate(145.3333,379.3333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-4" xml:space="preserve" y="14" style="stroke:none;"
>2</text
></g
><g transform="translate(217.6667,379.3333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-4" xml:space="preserve" y="14" style="stroke:none;"
>4</text
></g
><g transform="translate(290,379.3333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-4" xml:space="preserve" y="14" style="stroke:none;"
>6</text
></g
><g transform="translate(362.3333,379.3333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-4" xml:space="preserve" y="14" style="stroke:none;"
>8</text
></g
><g transform="translate(434.6667,379.3333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-7.5" xml:space="preserve" y="14" style="stroke:none;"
>10</text
></g
><g transform="translate(507,379.3333)" style="font-size:13.3333px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-7.5" xml:space="preserve" y="14" style="stroke:none;"
>12</text
></g
><g transform="translate(290.0002,397.6667)" style="font-size:14.6667px; fill:rgb(38,38,38); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; stroke:rgb(38,38,38); color-interpolation:linearRGB;"
><text x="-29" xml:space="preserve" y="15" style="stroke:none;"
>Samples</text
></g
><g style="fill:white; text-rendering:optimizeSpeed; color-rendering:optimizeSpeed; image-rendering:optimizeSpeed; shape-rendering:crispEdges; stroke:white; color-interpolation:sRGB;"
><path style="stroke:none;" d="M496 78 L496 42 L406 42 L406 78 Z"
/></g
><g style="text-rendering:geometricPrecision; color-rendering:optimizeQuality; color-interpolation:linearRGB; image-rendering:optimizeQuality;" transform="translate(453,51.863)"
><text x="0" xml:space="preserve" y="5" style="stroke:none;"
>h1</text
></g
><g style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><line y2="51.863" style="fill:none;" x1="410" x2="438" y1="51.863"
/></g
><g transform="translate(438,51.863)" style="fill:rgb(0,114,189); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(0,114,189);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(438,51.863)" style="stroke-linecap:butt; fill:rgb(0,114,189); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(0,114,189); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/></g
><g style="text-rendering:geometricPrecision; color-rendering:optimizeQuality; color-interpolation:linearRGB; image-rendering:optimizeQuality;" transform="translate(453,68.137)"
><text x="0" xml:space="preserve" y="5" style="stroke:none;"
>h2 * h2</text
></g
><g style="stroke-linecap:butt; fill:rgb(217,83,25); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(217,83,25); color-interpolation:linearRGB; stroke-width:0.6667;"
><line y2="68.137" style="fill:none;" x1="410" x2="438" y1="68.137"
/></g
><g transform="translate(438,68.137)" style="fill:rgb(217,83,25); text-rendering:geometricPrecision; color-rendering:optimizeQuality; image-rendering:optimizeQuality; color-interpolation:linearRGB; stroke:rgb(217,83,25);"
><circle r="4" style="stroke:none;" cx="0" cy="0"
/></g
><g transform="translate(438,68.137)" style="stroke-linecap:butt; fill:rgb(217,83,25); text-rendering:geometricPrecision; image-rendering:optimizeQuality; color-rendering:optimizeQuality; stroke-linejoin:round; stroke:rgb(217,83,25); color-interpolation:linearRGB; stroke-width:0.6667;"
><path style="stroke:none;" d="M0 -3.6667 C2.025 -3.6667 3.6667 -2.025 3.6667 0 L3.6667 0 C3.6667 2.025 2.025 3.6667 -0 3.6667 C-2.025 3.6667 -3.6667 2.025 -3.6667 -0 C-3.6667 -2.025 -2.025 -3.6667 0 -3.6667 ZM0 -4.3333 C-2.3932 -4.3333 -4.3333 -2.3932 -4.3333 -0 C-4.3333 2.3932 -2.3932 4.3333 -0 4.3333 C2.3932 4.3333 4.3333 2.3932 4.3333 0 L4.3333 0 C4.3333 -2.3932 2.3932 -4.3333 0 -4.3333 Z"
/><path transform="translate(-438,-68.137)" style="fill:none; fill-rule:evenodd; stroke:rgb(38,38,38); stroke-linejoin:miter;" d="M406 78 L406 42 L496 42 L496 78 Z"
/></g
></g
></svg
>

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Some files were not shown because too many files have changed in this diff Show More