关于垛积术的疑惑

这是由于在做一道求极限的运算题引发的,原题要用到求我记得以前学过这个,但那时没有认真对待数学。因此上网查了一下发现要用到这个公式在网上看了用数学归纳法的证明,知道这个结果的前提下,再用数学归纳法证明是很简单的事情。可是问题是,在看到这个结果之前,他怎么想到这个规律呢?带着这个疑问,我在网上搜了一下。原来我国古代很早就研究过这一类问题,还包括:, 并总结出了这样的公式。真是厉害啊。他们都用到了叫“垛积术”的方法。目前我没有找到详细的资料,还没有想明白。希望有知道的朋友能介绍点资料。

我看到其中一个思路如下:

[tex] \begin{bmatrix} &n &n& n& n&n\\ & n-1& n-1&n-1 &n-1 \\ &...&...&...&...&... \\ &2& 2& & & \\ &1& && \end{bmatrix}+ \begin{bmatrix} n& n-1& ...& 2&1\\ n& n-1&... &2& \\ ...&...&...&\\ n& n-1& & \\ n& & & \end{bmatrix} + \begin{bmatrix} 1& 2& ...&n-1&n\\ 2& 3&... &n& \\ ...&...&...&\\ n-1& n& & \\ n& & & \end{bmatrix} [/tex]

这样,就形成一个等差数列了。

[tex] \begin{bmatrix}
&2n+1 &2n+1&  2n+1& 2n+1&2n+1\\
&2n+1&2n+1&2n+1  & \\
&...&...& & &  \\
&2n+1& 2n+1&  & & \\
&2n+1&  &&
\end{bmatrix} [/tex]

用等差数列求和公式可得:

[tex]3\sum\limits_{k=1}^n K^2 = (2n+1)\frac{n(n+1)}{2}=\frac{1}{2}n(n+1)(2n+1)[/tex]

从而有:

[tex]\sum\limits_{k=1}^n K^2 = (2n+1)\frac{n(n+1)}{2}=\frac{1}{6}n(n+1)(2n+1)[/tex]

结合垛积术,相当于这里有3堆,先求3堆的总和,然后再除以3,得到结果。我画出了当n=4时,第一堆和第而堆。第三堆,应该是变形才能画出来,图形如下:

可能我的理解有误吧,写出来的目的是希望能有高手指点,或者能有人告诉我,哪里能找到垛积术的详细资料。谢谢!

Posted by 独孤求真 2010年10月02日 06:57


Asymptote的3D作图一例

size(300);
import three;

currentprojection=orthographic(1,1,1);
picture SumOfSquaresN(int n)
{
  int x, y, z;
  picture p;
  for (z = 0; z < n; ++z)
    for (y = 0; y < (n-z); ++y)
      for (x = 0; x < (n-z); ++x)
        draw(p, shift(x,y,z)*unitcube, white, meshpen=black+2, nolight);	

  return p;
}

picture pic = SumOfSquaresN(4);
add(pic);

 这是求的图,调用SumOfSquaresN,就可以了,当n=4时,图片如下:

感谢www.ctex.org以及www.ctex.orgTeX 图形技术 版主cvgmt 。详情见  长方体堆叠要如何画

Posted by 独孤求真 2010年10月02日 06:44


柯西(Cauchy)收敛准则

当一个数列的极限不是很容易求出来时,那么首要任务就是判断其极限是否存在,只有肯定了极限的存在后,再设法计算其极限。因此柯西收敛准则的重要性不言而喻。

对于这个定理的推导,课本上用到致密性定理,又是看了能看懂,但是自己看之前想不到的感觉,因此记录一下自己的思路。

致密性定理:任一有界数列必有收敛的子序列。

要看数列是否收敛,首先想到有界,这是很自然的,因为如果没有界,则肯定不是收敛的了。但是他怎么就和有界数列的子序列联系起来了呢?致密性定理是柯西收敛准则总结出来就有的吗?柯西也用这个定理来完成他的推理了?

虽然致密性定理相对来说比较简单,而且我的课本上,致密性定理也是在柯西收敛准则之前的。换句话说,当我学完致密性定理后,开始看课本上的柯西收敛准则,然后我在琢磨怎么推导柯西收敛准则时,压根就没有把他和致密性定理想到一块。

我推导过程没有用致密性定理,用了极限的定义和确界定义,似乎也没有漏洞。废话少说,学习笔记如下:

柯西(Cauchy)收敛准则:

数列[tex]\{a_n\}[/tex]有极限 [tex]\Leftrightarrow \forall \varepsilon>0, \exists N \in \mathbf{N}, \forall m,n>N[/tex], 有[tex] \vert x_n - x_m \vert < \varepsilon [/tex]

必要性[tex] \Rightarrow [/tex]: 设[tex] \lim_{x_n \rightarrow \infty} = a [/tex], 则[tex] \forall \varepsilon > 0, \exists N \in \mathbf{N}, \forall k>N [/tex]时,有:

[tex] \vert x_k - a \vert < \frac{\varepsilon}{2} [/tex]

从而可以得到,[tex] \forall m,n>N [/tex],有:

[tex] \vert x_n - x_m \vert = \vert x_n-a+a-x_m \vert \leq \vert x_n-a \vert + \vert a-x_m \vert < \varepsilon [/tex]

有了前面 极限唯一性 和 极限的保序性 的学习,必要性的证明过程再简单不过了。

充分性,既:由[tex] \forall \varepsilon > 0, \exists N \in \mathbf{N}, m,n>N, \vert x_n - x_m \vert < \varepsilon [/tex]得出数列收敛的结论。要看极限是否存在,首先想到判别是否有界,这是很容易想到的了。

当给定一个[tex] \varepsilon [/tex]后,N的值也就确定了,而m,n都是大于N的。由于[tex] \vert x_n-x_m \vert = \vert x_m - x_n \vert [/tex], 因此接下来只讨论[tex]n>m[/tex]的情况就可以了。既然N确定了,不管它有多大,始终都是一个有限值,从有限项[tex] \{\vert x_0 \vert, \vert x_1 \vert, \cdots \vert x_N \vert\} [/tex]取一个最大值都是可以的。于是:记[tex] X=max{ \{\vert x_0 \vert, \vert x_1 \vert, \cdots \vert x_N \vert\}\}[/tex], 而对于这个数列后面可能有无限项,于是是否有界的问题就转化成考察位于N之后的无限项是否有界。由于:

[tex] \vert x_n - x_m \vert < \varepsilon, \forall n>N[/tex], 恒成立,因此取m=N+1,n>m这样做的目的是把每一项都考虑进来,然后考虑那一项最大或最小。由于前面已经考虑了前N项,所以现在从N+1项开始考察。由代数的不等式规则有:

[tex] |x_n| \leq |x_n - x_{N+1}| + |x_{N+1}| < \varepsilon + |x_{N+1}|[/tex]

这就意味着,后面所有的项目都比[tex]|x_{N+1}| + \varepsilon[/tex]要小。于是,界线问题就只需要考虑:[tex] \{X, |x_{N+1}| + \varepsilon\}[/tex]了,对于任意给定的[tex]\varepsilon[/tex],只要[tex]\varepsilon[/tex],那么N以及[tex]|x_{N+1}| + \varepsilon}[/tex]都是可以计算出来的。因此数列有界。

这里课本上假设[tex] \varepsilon = 1 [/tex],然后3,5行就证明出来了,我根据自己的思路在这扯了一通。其实设为任何值都是可以的。

确定有界了,但是有界不一定有极限啊,例如[tex] \{ (-1)^n\}[/tex]有界,但不收敛。然后课本用致密性定理证明了它是有极限的。在看答案之前,我的确想不到。经过了痛苦的挣扎后,我首先想到的是,单调有界数列必有极限。又挣扎之后,我发现根据[tex] \forall \varepsilon>0, \exists N \in \mathbf{N}, \forall m,n>N  \vert x_n - x_m \vert < \varepsilon [/tex]

来证明它是单调的,这对我来说似乎很难啊。于是之后,我很自然的想到了有界的定义。主要是第二点:

[tex]\forall \varepsilon > 0, \exists |x_{n0}| \in \{ |x_n| \},  a-\varepsilon < |x_{n0}| [/tex]

这里还是都加个绝对值符号,考虑是上界的情况吧,下界的道理是一样的,不妨设上确界为|a|。

显然,设[tex]|x_k|[/tex]是[tex]\{|x_n|\}[/tex]中最大的,则有:

[tex] \forall \varepsilon > 0, |a|-\frac{\varepsilon}{2}< |x_k| \Rightarrow |x_k|-|a| < \frac{\varepsilon}{2}[/tex] 

[tex] \forall m \in \mathbf{N}, |x_m| \leq |x_k| [/tex]

由此有:

1. [tex] |x_m| - |a| < \frac{\varepsilon}{2} \because |x_m| \leq |x_k|  [/tex]

由已知:

2. [tex] |x_n| - |x_m| \leq |x_n-x_m| < \frac{\varepsilon}{2} [/tex]

把1和2相加,有:

[tex] |x_n|-|x_m|+|x_m|-|a| < \varepsilon} => |x_n|-|a| < \varepsilon[/tex]

有代数不等式规则有:

[tex] |x_n|-|a| \leq |x_n-a| < \varepsilon[/tex]

从而得到,此数列收敛于[tex]|a|[/tex]。

注意:先睡觉吧!改天再扯!

Posted by 独孤求真 2010年9月28日 06:08


Asymptote作图两例

 用Asymptote作图还是很方便的,前提是要改变用那种可视化工具作图的习惯,不是一来就打开软件,一边画一边改。Asymptote在画之前,需要先在草稿上画个大概,有个构思,要哪些点,或辅助点,这些规划好了,然后再用Asymptote,还是挺快的。

unitsize(2cm);

pair O=(0, 0);
pair X=(5, 0);
pair a=(4, 0);
pair ah=(4, 0.5);
pair ahl=(4, 0.3);
pair d=(3, 0);
pair dh=(3, 0.3);
pair c=(2.5, 0);
pair ch=(2.5, 0.3);
pair b=(1.5, 0);
pair bh=(1.5, 0.5);
pair bhl=(1.5, 0.3);

draw(O -- X, Arrow);
label(Label("$x$"), X, SW);
label(Label("$+$"), X, NW);
dot(a);
label(Label("$a$"), a, S);
draw(a -- ah, dashed+red);
dot(d);
draw(d -- dh, dashed);
dot(c);
draw(c -- ch, dashed);
dot(d);
draw(b -- bh, dashed+red);
dot(b);
label(Label("$b$"), b, S);

draw(ch -- bhl, Arrow);
label(Label("$y_n$"), ch -- bhl, N);
draw(dh -- ahl, Arrow);
label(Label("$x_n$"), dh -- ahl, N);

效果图如下:

再来一个:

import math;

unitsize(2cm);

pair O=(0, 0);
pair X=(5, 0);
pair a=(4, 0);
pair ah=(4, 0.6);
pair ahl=(4, 0.3);
pair c=(3, 0);
pair ch=(3, 0.5);
pair d=(2.5, 0);
pair dh=(2.5, 0.3);
pair b=(1.5, 0);
pair bh=(1.5, 0.6);
pair bhl=(1.5, 0.5);

draw(O -- X, Arrow);
label(Label("$x$"), X, SW);
label(Label("$+$"), X, NW);
dot(a);
label(Label("$a$"), a, S);
draw(a -- ah, dashed+red);
dot(d);
draw(d -- dh, dashed);
dot(c);
draw(c -- ch, dashed);
dot(d);
draw(b -- bh, dashed+red);
dot(b);
label(Label("$b$"), b, S);

draw(ch -- bhl, Arrow);
label(Label("$y_n$"), ch -- bhl, N);
draw(dh -- ahl, Arrow);
label(Label("$x_n$"), dh -- ahl, N);
pair cc=extension(dh, ahl, c, ch);
filldraw(d--dh--cc--c--cycle, fillpen=opacity(0.1), drawpen=gray);

效果如下:

Posted by 独孤求真 2010年9月27日 19:01


极限的保序性

已知[tex]\lim_{n \rightarrow \infty} x_n = a, \lim_{n \rightarrow \infty} y_n = b[/tex], 且 [tex]a>b[/tex], 则[tex]\exists N \in \mathbf{N}[/tex],[tex] \forall n>N[/tex],有[tex]x_n > y_n[/tex] 。

课本的证明又一次用选用了[tex]\varepsilon = \frac{a-b}{2}[/tex] !虽然证明过程简单明了,还是老问题,他怎么想到选这个呢?这里就不列出课本的证明了。我的推理如下:

根据极限定义有:

[tex] \left \vert x_n - a \right \vert < \varepsilon [/tex]

[tex] \left \vert y_n - b \right \vert < \varepsilon [/tex]

注意,这里同一个[tex]\varepsilon[/tex]对[tex]a_n[/tex]对应一个[tex]N_1[/tex],对[tex]b_n[/tex]对应一个[tex]N_2[/tex],[tex]N_1[/tex]不一定等于[tex]N_2[/tex]。既:

[tex]{\color{red}{a - \varepsilon}} < x_n < {\color{blue}{a + \varepsilon}}[/tex]

[tex]{\color{blue}{b - \varepsilon}} < y_n < {\color{red}{b + \varepsilon}} [/tex]

由已知条件,[tex]a>b[/tex],因此,一定可以找到一个[tex]\varepsilon > 0[/tex]使得[tex] a-\varepsilon = b+\varepsilon[/tex]成立。既:[tex] \exists \varepsilon > 0 [/tex],有[tex] a-\varepsilon = b+\varepsilon[/tex],可进一步推算出,在此条件下,[tex] a-b = 2\varepsilon[/tex]。

由不等式的递推关系式可进一步得到

[tex] y_n < ({\color{red}{b + \varepsilon}} = {\color{red}{a - \varepsilon}}) < x_n [/tex]

从而得到:

[tex] \exists \varepsilon[/tex],使得 [tex] x_n > y_n [/tex]。

这就可以了吗?实则不然,命题是说[tex]\exists N \in \mathbf{N}[/tex],[tex] \forall n>N[/tex],有[tex]x_n > y_n[/tex] 。而到目前,我们只是证明了以下结论:

[tex] \exists \varepsilon = \frac{a-b}{2} > 0 [/tex],[tex] \exists N_1 \in \mathbf{N},  \exists N_2 \in \mathbf{N} [/tex],有[tex] x_n > y_n [/tex]。

但是对于[tex] n>N_1[/tex]或[tex] n>N_2[/tex]时,[tex]x_n > y_n[/tex]是不是恒成立的,则需要另作讨论。

这时我不禁想到,当[tex] n > N_n[/tex]之后,[tex] y_n [/tex]有没有可能“追上”[tex] x_n [/tex]呢? 不妨再回到前面的那个不等式:

[tex] y_n < ({\color{red}{b + \varepsilon}} = {\color{red}{a - \varepsilon}}) < x_n [/tex]

取[tex]N=Max\{N_1, N_2\}, \varepsilon = \frac{a-b}{2} [/tex],则有:

[tex] \forall n>N, y_n < \frac{a-b}{2} < x_n[/tex]

这就意味着,从[tex]n>N[/tex]以后,所有的[tex]x_n[/tex]都大于[tex]\frac{a-b}{2}[/tex], 所有的[tex]y_n[/tex]都要小于[tex]\frac{a-b}{2}[/tex],因此从这以后[tex] y_n [/tex]就不可能再“追上”[tex] x_n [/tex]了!

最后还是回到了课本上的设 [tex] \varepsilon = \frac{a-b}{2}[/tex],但似乎也知道他为啥要这么设置了!

反过来,若已知数列[tex]\{x_n\}, \{y_n\}[/tex]极限存在,且[tex]\forall n \in \texbf{N}[/tex]有 [tex] x_n \geq y_n [/tex],则有[tex] \lim_{n \rightarrow \infty} x_n \geq \lim_{n \rightarrow \infty} y_n [/tex], 证明方法是一样的。考虑下面这个说明了啥?

[tex] x_n = \frac{n+1}{n}, y_n = \frac{n}{n+1} [/tex] 有:[tex] x_n \geq y_n [/tex] 但:[tex] \lim_{n \rightarrow \infty} x_n = 1 = \lim_{n \rightarrow \infty} y_n[/tex]

[tex] x_n = \frac{1}{n}, y_n = \frac{1}{n+1} [/tex] 有:[tex] x_n \geq y_n [/tex] 但:[tex] \lim_{n \rightarrow \infty} x_n = 0 = \lim_{n \rightarrow \infty} y_n[/tex]

说明了啥?

感谢views63http://www.mathchina.com

Posted by 独孤求真 2010年9月26日 07:08


极限唯一性

若数列[tex]\left \{ x_n \right \}[/tex]的极限存在,则极限值是唯一的。

看了很多数学教材,证明过程都选取了一个[tex] \left \vert a-b \right \vert = \frac{d}{2}[/tex],证明过程虽然简洁明了,而取[tex] \left \vert a-b \right \vert [/tex]也是很容易想到的,但他是怎么想到了个[tex]\frac{d}{2}[/tex]呢?这先给出课本的证明过程,后面是我的推理过程!

设数列[tex]\left \{ x_n \right \}[/tex] 有两个不相等的极限值[tex]a[/tex]、[tex]b[/tex],[tex]a \neq b[/tex],则有[tex] d = \left \vert a-b \right \vert > 0[/tex],总可以找到一个正整数[tex]\mathbf{N}[/tex],当[tex]n>\mathbf{N}[/tex]时,总满足下列不等式:

[tex]\left \vert x_n - a \right \vert < \frac{d}{2}[/tex]

[tex]\left \vert x_n - b \right \vert < \frac{d}{2}[/tex]

另一方面有:

[tex] \left \vert a - b \right \vert = \left \vert a - x_n + x_n - b \right \vert = \left \vert (x_n - a)  - (x_n - b) \right \vert [/tex]

由代数的不等式公式可得:

[tex] \left \vert (x_n - a)  - (x_n - b) \right \vert \leq \left \vert (x_n - a) \right \vert +  \left \vert (x_n - b) \right \vert = d[/tex]

即有

[tex] \left \vert a - b \right \vert  < d [/tex]

这于假设[tex] d = \left \vert a-b \right \vert > 0[/tex]矛盾,因此极限唯一。

证明过程很简洁明了,可问题是,他怎么就想到在这里,选[tex]\varepsilon = \frac{d}{2}[/tex]呢?这对我来说,总有一种感觉,就是看了别人的能看懂,但是换做自己,则想不到。因此我按我的理解,证明了一下,过程如下:

对于同一个[tex]\varepsilon[/tex],分别有[tex]n1, n2[/tex]根据极限定义有:

[tex]\left \vert x_{n1} - a \right \vert <\varepsilon [/tex]

[tex]\left \vert x_{n1} - b \right \vert < \varepsilon [/tex]

这里n1不一定等于n2,但是根据极限定义,我们取n=Max(n1, n2),从而有:

[tex]{\color{red}{a - \varepsilon}} < x_n < {\color{blue}{a + \varepsilon}}[/tex]

[tex]{\color{blue}{b - \varepsilon}} < x_n < {\color{red}{b + \varepsilon}} [/tex]

由于[tex] a \neq b[/tex],无非有两种情况,[tex] a>b[/tex] 或者 [tex]a<b[/tex],对于[tex] a>b[/tex],由于在极限定义中,[tex]\varepsilon[/tex]是可以任意选取的大于0的数,因此总可以找到一个[tex]\varepsilon[/tex]满足以下条件:

[tex]{\color{red}{a - \varepsilon}} =  {\color{red}{b + \varepsilon}}[/tex]

由不等式递推,可得:

[tex]{x_n < (\color{red}{b + \varepsilon}} = {\color{red}{a - \varepsilon}}) < {\color{blue}{x_n}}  [/tex]

既得到,[tex] x_n < x_n [/tex],这显然是不可能的,因为对任意自然数[tex]\mathbf{N}[/tex],都有[tex] x_n = x_n [/tex]。

同理对于[tex] a<b[/tex]的情况,总可以找到一个[tex]\varepsilon>0[/tex]满足以下条件:

[tex]{\color{blue}{b - \varepsilon}} =  {\color{blue}{a + \varepsilon}}[/tex]

也得到,[tex] x_n < x_n [/tex]的结论。因此无论[tex]a<b[/tex]还是[tex]a>[/tex]的情况,都可以找到一个反例子。所以假设不成立。推理到这里,我终于理解课本要选取[tex]\varepsilon = \frac{d}{2}[/tex]了。

我的推理过程应该也没有漏洞吧,:)

Posted by 独孤求真 2010年9月26日 04:36


Latex写数学表达式

用Latex做数学表达式真是又方便又好看,准备以后把用过的表达式极其代码都保存到这里,用于备忘。随时更新。还有,对Latex爱好者来说,http://www.codecogs.com 这个网站真的很方便。

1. 分数,极限及上标(n次方)

\lim_{n \rightarrow \infty}
\frac{1+a+a^2+\cdots +a^n}{1+b+b^2+\cdots+b^n}, 
(\left\vert a \right\vert < 1, \left\vert b \right\vert < 1)

[tex]\lim_{n \rightarrow \infty}\frac{1+a+a^2+\cdots +a^n}{1+b+b^2+\cdots+b^n},(\left\vert a \right\vert < 1, \left\vert b \right\vert < 1)[/tex]

2. 大括号推倒符号

a_n \leq b_n \Rightarrow sup \begin{Bmatrix} a_n \end{Bmatrix} 
\leq sup \begin{Bmatrix} b_n \end{Bmatrix}

[tex]a_n \leq b_n \Rightarrow sup \begin{Bmatrix} a_n \end{Bmatrix} \leq sup \begin{Bmatrix} b_n \end{Bmatrix}[/tex]

a_n \leq b_n \Rightarrow \sup \big\{ a_n \big\}\leq \sup \big\{ b_n \big\}

[tex] a_n \leq b_n \Rightarrow \sup \big\{ a_n \big\}\leq \sup \big\{ b_n \big\} [/tex]

3. 求和符号:

\sum\limits_{k=1}^n K^2

[tex]\sum\limits_{k=1}^n K^2[/tex]

Posted by 独孤求真 2010年9月23日 07:20


RS232串口通信实验Verilog

RS232串口通信实验几乎是入门必做实验,这是本人学习过程中做的练习。首先是分频模块,分频模块是学习了OpenCore上的uart2bus项目的。http://opencores.org/project,uart2bus
该模块接收任意频率的输入频率(clk_i),输出频率(记为clk_o)由baud_freq_i和baud_limit_i根据以下公式计算,使用时首先需要根据输入频率和输出频率计算出baud_freq_i和baud_limit_i这两个参数。

[tex] baud\_freq = \frac{clk\_o}{GCD(clk\_i, clk\_o)}[/tex]

[tex] baud\_limit = \frac{clk\_i}{GCD(clk\_i, clk\_o)} - baud\_freq [/tex]

公式里的GCD(Greatest Common Divisor)表示取2个数的最大公约数。

这里系统时钟频率为50MHz,串口频率为9600,通常我们是在中间进行采样。因此分频模块分出来的频率为16*9600。模块如下:

/* 
 * this module has been changed to receive the baud rate 
 * dividing counter from registers.
 * the two registers should be calculated as follows:
 * first register:
 * 	baud_freq = 16*baud_rate / gcd(global_clock_freq, 16*baud_rate)
 * second register:
 * 	baud_limit = (global_clock_freq / 
 *                   gcd(global_clock_freq, 16*baud_rate)) - baud_freq
 */
module baud_gen(clk_i, rst_i, ce16_o, baud_freq_i, baud_limit_i);
input		clk_i;
input		rst_i;
output		ce16_o;
input [11:0]	baud_freq_i;
input [15:0]	baud_limit_i;

reg ce16_o;
reg [15:0] count;

always @(posedge clk_i or negedge rst_i)
begin
	if (!rst_i)
		count <= 16'h0;
	else if (count >= baud_limit_i)
		count <= count - baud_limit_i;
	else
		count <= count + baud_freq_i;
end

always @(posedge clk_i or negedge rst_i)
begin
	if (!rst_i)
		ce16_o <= 1'b0;
	else if (count >= baud_limit_i)
		ce16_o <= 1'b1;
	else
		ce16_o <= 1'b0;
end

endmodule

分频模块的仿真波形如下,上面是50M的输入时钟,下面是分频后的,需要注意的是,分频后的时钟的占空比不是1:1的,每一个9600Hz的周期中产生16个高电平,高电平维持一个20ns(50MHz的一个周期)

计算baud_freq和baud_limitC程序如下,程序中的输入频率clk_i为50MHZ,输出频率为9600*16。

#include <stdio.h>

int GCD(int a, int b)
{
        if (b == 0)
                return a;
        else
                return GCD(b, a%b);
}

int main()
{
        int clk_i = 50*1000*1000;
        int clk_o = 9600*16;

        int gcd = GCD(clk_i, clk_o);
        int baud_freq = clk_o/gcd;
        int baud_limit = (clk_i/gcd) - baud_freq;
        printf("baud_freq: 0x%x, baud_limit: 0x%x\n", baud_freq, baud_limit);
        return 0;
}

 

然后是发送模块:

module uart_tx(clk_i, 
		rst_i, 
		ce16_i, 
		ser_o, 
		tx_data_i, 
		new_tx_i, 
		tx_int_o, 
		tx_busy_o);
input		clk_i;
input		rst_i;
input		ce16_i;
output		ser_o;
input [7:0]	tx_data_i;
input		new_tx_i;
output		tx_int_o;
output		tx_busy_o;

reg		ser_o;
reg		tx_int_o;
reg		tx_busy_o;
reg [3:0]	count;
reg [3:0]	bit_count;
reg [8:0]	tx_data;

wire		ce1_end;
assign ce1_end = (count == 4'b1111) & ce16_i;

always @(posedge clk_i or negedge rst_i)
begin
	if (!rst_i)
		count <= 4'h0;
	else if (tx_busy_o & ce16_i)
		count <= count + 1'b1;
	else if (!tx_busy_o & ce16_i)
		count <= 1'b0;
end

always @(posedge clk_i or negedge rst_i)
begin
	if (!rst_i)
		tx_busy_o <= 1'b0;
	else if (!tx_busy_o & new_tx_i)
		tx_busy_o <= 1'b1;
	else if (tx_busy_o & ce1_end & (bit_count == 4'd9))
		tx_busy_o <= 1'b0;
end

always @(posedge clk_i or negedge rst_i)
begin
	if (!rst_i)
		bit_count <= 4'h0;
	else if (tx_busy_o & ce1_end)
		bit_count <= bit_count + 1'b1;
	else if (!tx_busy_o)
		bit_count <= 4'h0;
end

always @(posedge clk_i or negedge rst_i)
begin
	if (!rst_i)
		tx_data <= 9'h0;
	else if (!tx_busy_o)
		tx_data <= {tx_data_i, 1'b0};
	else if (tx_busy_o & ce1_end)
		tx_data <= {1'b1, tx_data[8:1]};
end

always @(posedge clk_i or negedge rst_i)
begin
	if (!rst_i)
		ser_o <= 1'b1;
	else if (tx_busy_o)
		ser_o <= tx_data[0];
	else
		ser_o <= 1'b1;
end


always @(posedge clk_i or negedge rst_i)
begin
	if (!rst_i)
		tx_int_o <= 1'b0;		
	else if (tx_busy_o & ce1_end & (bit_count == 4'd9))
		tx_int_o <= 1'b1;
	else
		tx_int_o <= 1'b0;
end

endmodule

接收模块:

module uart_rx(clk_i,
		rst_i,
		ce16_i,
		ser_i,
		rx_data_o,
		rx_int_o);
input		clk_i;
input		rst_i;
input		ce16_i;
input		ser_i;
output [7:0] 	rx_data_o;
output		rx_int_o;

reg [7:0] 	rx_data_o;
reg		rx_int_o;

reg [7:0] 	rx_data;
reg [1:0]	ser_in;
reg [3:0]	count;
reg [3:0]	bit_count;
reg		rx_busy;

wire		ce1_mid;
wire		ce1_end;

always @(posedge clk_i or negedge rst_i)
begin
	if (!rst_i)
		ser_in <= 2'b11;
	else
		ser_in <= {ser_in[0], ser_i};
end

always @(posedge clk_i or negedge rst_i)
begin
	if (!rst_i)
		count <= 4'h0;
	else if ((rx_busy | (ser_in[1] == 1'b0)) & ce16_i)
		count <= count + 1'b1;
	else if (!rx_busy & ce16_i)
		count <= 4'h0;
end

assign ce1_mid = ((count == 4'b0111) & ce16_i);
assign ce1_end = ((count == 4'b1111) & ce16_i);

always @(posedge clk_i or negedge rst_i)
begin
	if (!rst_i)
		rx_busy <= 1'b0;
	else if (!rx_busy & ce1_mid)
		rx_busy <= 1'b1;
	else if (rx_busy & ce1_end & (bit_count == 4'd9))
		rx_busy <= 1'b0;
end

always @(posedge clk_i or negedge rst_i)
begin
	if (!rst_i)
		bit_count <= 4'h0;
	else if (rx_busy & ce1_mid)
		bit_count <= bit_count + 1'b1;
	else if (!rx_busy)
		bit_count <= 4'h0;
end

always @(posedge clk_i or negedge rst_i)
begin
	if (!rst_i)
		rx_data <= 8'h0;
	else if (ce1_mid)
		rx_data <= {ser_in[1], rx_data[7:1]};
end

always @(posedge clk_i or negedge rst_i)
begin
	if (!rst_i) begin
		rx_data_o <= 8'h0;
		rx_int_o <= 1'b0;
	end else if (ce1_end & (bit_count == 4'd8)) begin
		rx_data_o <= rx_data;
		rx_int_o <= 1'b1;
	end else
		rx_int_o <= 1'b0;
end

endmodule

顶层模块:

module uart_loop_top(clk_i, rst_i, ser_i, ser_o);
input		clk_i;
input		rst_i;
input		ser_i;
output		ser_o;

// baud rate generator parameters for 9600 baud on 50MHz clock
`define D_BAUD_FREQ		12'h30
`define D_BAUD_LIMIT		16'h3CD9

wire		ce16;
wire [11:0]	baud_freq;
wire [15:0]	baud_limit; 

wire [7:0]	rx_data;
reg [7:0] 	rx_reg;
reg		start_tx;
wire		tx_int;
wire		tx_busy;

assign baud_freq = `D_BAUD_FREQ;
assign baud_limit = `D_BAUD_LIMIT;


baud_gen baud_gen1(.clk_i(clk_i), 
		.rst_i(rst_i), 
		.ce16_o(ce16),
		.baud_freq_i(baud_freq),
		.baud_limit_i(baud_limit));

uart_rx uart_rx1(.clk_i(clk_i), 
		.rst_i(rst_i),
		.ce16_i(ce16),
		.ser_i(ser_i),
		.rx_data_o(rx_data),
		.rx_int_o(rx_int));

uart_tx uart_tx1(.clk_i(clk_i),
		.rst_i(rst_i),
		.ce16_i(ce16),
		.ser_o(ser_o), 
		.tx_data_i(rx_reg),
		.new_tx_i(start_tx),
		.tx_int_o(tx_int),
		.tx_busy_o(tx_busy));

always @(posedge clk_i or negedge rst_i)
begin
	if (!rst_i)
		rx_reg <= 8'h0;
	else if (rx_int & ~tx_busy)
		rx_reg <= rx_data;
end


always @(posedge clk_i or negedge rst_i)
begin
	if (!rst_i)
		start_tx <= 1'b0;
	else if (rx_int & ~tx_busy)
		start_tx <= 1'b1;
	else
		start_tx <= 1'b0;
end

endmodule

Posted by 独孤求真 2010年9月21日 20:24