2014年6月2日星期一

研究生期间做项目所学到的一些经验 - clover_toeic

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
研究生期间做项目所学到的一些经验 - clover_toeic  阅读原文»

本文主要分享研究生期间所学到的一些科研和项目经验,实践部分偏重于硬件电路。点滴琐碎,还请见谅。

一 项目所得

1.1 心得体会

  • 任何事物都要从最简单、最基本的构架入手,理解复杂的。——接触学习新东西时的指导思路。
  • 做理论要做做想想,边停边走;做工程则要不断推进,因为不做不出来。工程就是靠时间堆出来的,不在于谁比谁聪明多少,而在于谁比谁用功了多少。
  • 做工程思路:不要挑刺钻牛角尖,能用就行。要实用主义而不是理想主义,忌追求完美(比如正确解调需要信噪比至少10dB,则前端的同步就无须追求在5dB下性能最佳)!该细则细,该粗则粗。不要死抠理论,太专注细节往往看不到整体(又如同步性能设计再好,解调不出正确数据也是白搭,还不如多分配些时间精力给解调模块)。
  • 不是做大项目就能学到东西的。恰恰相反,因为难以吃透大项目,所以只能按照别人的现有思路走,导致思维固化。而做小东西更具灵活性,可以充分发挥自己的想象力,寻求多种解决途径。外面做了几年大项目的人拿到新项目时,仍会感到无从下手;而老师接到新项目后,能立刻在脑海里构建出各个功能模块(“庖丁解牛”),原因即在此。
  • 不要着急,一步一步来,别指望一口吃成胖子。很多时候工程做到一定程度了才能发现问题。你要做的就是通过项目学到能力,没必要尽善尽美,说实话项目本身对你今后的工作帮助不大。
  • 自己的核心设计往往只占工程的很小一部分,大部分工作在于工程的集成。
  • 把项目当成学习的好机会,而不是负担,才能有激情。
  • 保留自己的想法,接受并尝试老师的想法而不是固守自己的方案——记住你是在“学习”,不是在“打工”!多向老师学习系统观和做事方法。老师的工程经验很丰富,整体化的系统思维值得认真学习借鉴。不要怕和老师讨论。伸手向老师要,老师才会给你。
  • 请教老师前先说说自己的尝试方案,因为老师有经验一看便知如何入手;请教师兄们时则保留自己的方案,因为容易限制师兄们的思路。
  • 不讨论、不提问、不向老师同学请教学习,即使做出东西又有何用?你只是发挥了自己的水平而已,能力并未得到提高!按自己的思维而不是借鉴别人的好想法做工程,只是交差,能力得不到提高!
  • 工作后技术可以是二流的,但做人应该是一流的。
  • 工程有忙有闲。忙的时候能忙得上,闲的时候能闲下来。一味地忙或闲都不好。
  • 不要屡教不改,总犯同样的问题!
  • 不要太专注所做东西本身,而更要体会做事的过程。

1.2 设计实践

  • 数电思路 + 参考相关芯片设计
  • 不要想着先做出来再说——应该先讨论确定方案。随时向老师汇报,排除系统原理结构上的设计失误!策略性问题及时与老师讨论,公式推导、器件操作等可自己验证的则自行搞定。
  • 必须跳出自己的思维约束,把握整体构架,确定整体思路后再着手实现。最好先画出波形图,至少要有关键信号的时序关系。着手写程序时可以先写出大体框架,然后完成和完善子模块。
  • 设计时问一问自己:是否从工程的思维入手?体会老师设计的控制模块的优点(先定整体时序,便于调试)。
  • 对照Matlab理论波形与示波器实际波形。不要满足于软件仿真“正确”,要放到实践中测试!类似地,电源等电器件不要直接拿来用,要实测一下电压值。
  • 设计要具有一定的通用性和灵活性,如便于扩充或调试。

模块通用性:基本思想是做通用可扩展、特定功能的小“模块”,而不要在后续阶段为加入功能而添加代码。

模块就是你给我输入,我给你想要的输出,仅此而已,尽可能不要让我进行控制。

模块化,减少耦合度,便于移植和调试。尽量模块化,可避免大的改动。

  • 在阅读别人的程序时,遇到不确定有无的地方,不要冒然删减,应深入思考其存在的理由,深入画图分析(也利于别人理解和答辩申明)。
  • 在不了解系统全局的情况下,先摸索后看手册(前提是避免危险的操作)。在摸索尝试中理解,切莫一开始就拿起手册从头看。先尝试各种可能来解决问题,不要轻易下结论!做完后再回过来理解,不要“轻信”资料。比如调时AD开发板时,与其研究透彻每个寄存器怎么设置后再着手调,不如边调边试。同样地,对于别人的东西既要吸收,又要质疑。不要因为那是别人做好的就认为OK了,实际上可能有很严重的设计缺陷。
  • 利用别人的力量做出来才是水平。当你看到别人的东西并很快领悟为自己的东西才是水平。先模仿后发展。多向别人请教想法!尽量不要问具体问题,问思路才最重要。
  • “反驳激将法”获取别人的想法,集思广益。多征求想法,记在纸上。即使现在想法不成熟,以后也可能有用。外行也能提出新想法新思路。因为我们的设计都是面向实际生活的,外行可能更清楚实际需要怎么做——当局者迷,旁观者清。比如我在用4点采样做同步,而数据却是8点采样,还煞有介事地试图找到精确的同步位置。假如说给搞图像处理的人听,人家的第一反应就是“这不可能”,因为同步“分辨率”不够。后来才在老师的启发下改用两个同步模块解决了问题。
  • 思路灵活。做时定式,想时无定式。不要一根筋走到底,要考虑变通的方法。比如同步相关模块之前用定制的元件altshift_tags,tap distance>=3,不得不进行时钟三分频。原先的想法是用时钟来换取LE的减少(假设定制元件比自己编写的节省资源——其实未必,考虑“通用性”),后来发现时钟远比LE重要。所以自己编写了移存器模块,可以实现清零复位,tap distance等效为1,免去了时钟三分频。

【注】自己编写的三分频模块在Modelsim里会仿真出什么结果呢?比如clk_sn由75M时钟clk_sf三分频产生,那么仿真出来的clk_sn为42ns的时钟,而不是40ns(25M)——因为你所加的75M时钟仿真激励不可能很精确(13.333...ns)!

1.3 论文

  • 每节开门见山,不要�嗦。每章前面有摘要,后面有小结,承上启下,既有条理又凑够字数。
  • 仿真要多,尽量多参数,反复仿多个,得出结论!仿真分析等尽量用1、2、3....条理化。
  • 图表要多,摘要绪论及结束语一定要写好,评审老师哪有工夫看理论。
  • 论文侧重理论。理论上下功夫的论文容易通过(“新名词”多)。许多评委都是理论出身,容易接受理论文章,故起评分高。偏工程类的论文除工程实现还必须要做理论部分,否则答辩时评委要问你除了“实现”还有什么创新点呢?你的工作量(工程)人家不一定认可啊。
  • 将数据导出来在Matlab中观察(如画图)往往能发现新问题甚至新思路。

- 把FPGA仿真结果数据导入Matlab中,画出Matlab理论曲线与FPGA仿真曲线比较(大数据量)

- 提出一种想法后务必画出理论比较曲线(有比较才有说服力),过多的解释说明倒不如图表直观。

- 设计验证机制

  • 不要写得太细,给评委提问的余地(大的方面让评委觉得你水平挺高,思路清晰,有创新性;从细处一想又有不清楚处)——否则评委可能会问预料之外的问题!

1.4 其他

勤写报告:1. 保持进度; 2. 用于提问讨论; 3.论文素材。

三种报告:

1) 给老师的报告:综合、轮廓、整体思路——图表化

2) 给自己的报告:设计算法、心得经验、调试细节

3) 给接收人的报告:系统、思路、如何实现及该做哪些工作,便于迅速上手。

以后发挥自己的能动性,每天向老师汇报进度——不是做了多少(太“虚”),而是具体完成了什么!

计划、讨论、汇报,讲给老师听。

有问题一定写文档问老师,不要想着口头说——这其实减少了仔细思考的过程。

二 测试调试

2.1 调试信念

不合理的现象背后,一定有合理的原因。只有抱定这一信念,才能解决调试中遇到的各种问题。与此相反的是:遇到不合理的现象,不是去寻求合理的解释,而是猜想有一些不可控、不可证明的原因。比如猜想综合工具有bug,电路的信号完整性有问题,芯片过热等。这样一想,问题往往不了了之,调试也就半途而废了。

遇到问题首先思考什么情况下会产生此类问题,寻求可能原因,而不是怀疑软/硬件工具有问题。

2.2 调试原则

  • “遇到拦路虎一定要把它解决掉,否则日后碰到它你会更发怵”。不要回避问题,躲得过初一躲不过十五,迟早是要面对的——与其推倒重来,不如在初期就多加讨论解决!
  • 从最简单的开始调试,先确定哪些模块正确,哪些有问题,而不是整个工程拿来跑,期望某次会“碰巧”正确(寻找问题所在,而不是回避问题)。
  • 按规程走,不要寄托于修改“好”的工程以求毕其功于一役。
  • 看起来最简单最不会出错的地方才最容易出错,反而复杂程序却很少出致命问题!
  • 最基本的“常识”——不工作时各个寄存器(尤其是使能信号和计数器)都要复位!

2.3 调试技巧

  • “隔离”(回路之间加入不同的延迟单元,测试时序是否满足)、“直通”(模块直连,如调制数据直接送往解调模块——bypass同步)。
  • 设计时就应该写好测试比较模块。一是软件比较,如Quartus II仿真结果与Matlab理论结果比较,或Modelsim结果(testbench)输出至Matlab中与理论结果画图比较。二是硬件比较,如可把待调制数据写入FIFO,当解调数据输出时同时读该FIFO并进行比较,如果对应位不同则输出ERROR高电平(此法也可用来判断两个模块是否实现完全相同的功能)。后者在上板子后可用逻辑分析仪捕捉ERROR信号(触发),注意“Trigger”|“Trigger position”项选择“Post trigger position”,这样可以捕捉到出错前的信号。
  • 高效率:多建工程备份(面积换速度),这样可以立刻调试正确版本。
  • 将已经基本调试成功的工程备份至另外的目录,并且每个工程属性改为“只读”,防止无意中误操作修改了正确版本。——保留备份!
  • 当前正确工程备份后,在此基础上逐步添加新模块。
  • 及时给程序加注释,便于理解;及时写调试文档,重点记录错误点,避免重犯(还有一种情况就是后面想到某个曾被部分否定的方法,却不知道哪里需要注意)。
  • 将中间结果尤其是关键信号的波形截图保存在word中,可以方便对照!
  • 逐个模块调试,Modelsim大数据量仿真(尤其注意两段数据之间的使能信号及计数器的状态),示波器观察波形(周期,相位...尤其注意不要出现长时间的直流或跳变)。找到出错的地方,看其与哪些变量直接相关,然后由出错位置出发,观察这些变量甚至它们的相关变量,逆向一步步寻找出错原因。
  • 用已知在别人机器上正确的工程去检验自己的软件环境,而不是从头新建工程trial and error!
  • 先从最简单的功能,最简单的数据(如方波)做起。先测试最基本的信号(如时钟)。输入特殊值观察规律。
  • 若某个reg信号在仿真时波形不正常,可试着将其设为输出output(改变布线)重新仿真。
  • 合理地使用拼接符可以提高程序的可读性和可维护性。使用拼接可以把多个信号的某?div style="border-bottom:1px solid #aaa;margin-bottom:25px">DOM系列---基础篇 - 努力就有机会  阅读原文»

    DOM (Document Object Model) 即文档对象模型, 针对 HTML 和 XML 文档的 API (应用程序接口) 。DOM 描绘了一个层次化的节点树,运行开发人员添加、移除和修改页面的某一部分。DOM 产生于 网景公司及微软公司创始的 DHTML(动态 HTML) ,但现在它已经成为表现和操作页面标记的真正跨平台、语言中立的方式。

    DOM 中的三个字母:

    D(文档)可以理解为整个 Web 加载的网页文档;

    O(对象)可以理解为类似 window 对象之类的东西,可以调用属性和方法,这里我们说的是 document对象;

    M(模型)可以理解为网页文档的树型结构。

    DOM 有三个等级,分别是 DOM1、DOM2、DOM3。

    PS:IE 中的所有 DOM 对象都是以 COM 对象的形式实现的,这意味着 IE 中的 DOM

    可能会和其他浏览器有一定的差异。

    一.DOM介绍

    1.节点

    加载 HTML 页面时, Web 浏览器生成一个树型结构, 用来表示页面内部结构。 DOM 将这种树型结构理解为由节点组成。

    图1

    从上图的树型结构,我们理解几个概念,html 标签没有父辈,没有兄弟,所以 html 标签为根标签。head 标签是 html 子标签,meta 和 title 标签之间是兄弟关系。如果把每个标签当作一个节点的话,那么这些节点组合成了一棵节点树。

    PS:后面我们经常把标签称作为元素,是一个意思。

    2.节点种类:元素节点,属性节点,文本节点

    例如:<div title="标签属性">测试 Div</div>

    图2

    二.查找元素

    W3C 提供了比较方便简单的定位节点的方法和属性, 以便我们快速的对节点进行操作。

    分别为:

    图3

    1.getElementById()方法

    getElementById()方法,接受一个参数:获取元素的 ID。如果找到相应的元素则返回该元素的 HTMLDivElement 对象,如果不存在,则返回 null。

    document.getElementById('box'); //获取 id 为 box 的元素节点

    注意:某些低版本的浏览器会无法识别 getElementById()方法,比如 IE5.0-,这时需要做一些判断,可以结合上章的浏览器检测来操作。

    if (document.getElementById) { //判断是否支持 getElementById

    alert('当前浏览器支持 getElementById');

    }

    PS:一个程序要想写的健壮,需要很多的判断语句,方方面面考虑周到!

    当我们通过 getElementById()获取到特定元素节点时, 这个节点对象就被我们获取到了,而通过这个节点对象,我们可以访问它的一系列属性。

    图4

    例如:<div id=”box” title="标签属性">测试 Div</div>

    document.getElementById('box').tagName; //输出:DIV

    document.getElementById('box').innerHTML; //输出:测试 Div

    PS:innerHTML获取这个元素节点里的文本(包含HTML标签),纯文本不能包含标签,innerHTML获取的是这个元素的文本内容,而不是文本节点。

    还可以赋值:

    var box = document.getElementById('box');

    box.innerHTML = '玩转<strong>JS</strong>'; //赋值

    注意:上述赋值语句中,HTML标签会被页面解析,所以在页面显示的时候“JS”会加粗显示。

    图5

    例如:<div id="box" title="标题" class="pox" style="color:red;" bbb="aaa">测试Div</div>

    var box = document.getElementById('box');

    alert(box.id); //获取这个元素节点id属性的值,注意不是属性节点alert(box.title); //获取title属性的值

    alert(box.style); //获取style属性对象

    alert(box.style.color); //获取style属性对象中color属性的值

    alert(box.class); //貌似是保留字

    alert(box.className); //获取class属性的值

    以上都是HTML属性的直接调用,当然后面还有几种方式可以调用。

    alert(box.bbb); //自定义属性,直接获取,非IE不支持

    PS:如果有浏览器不支持,那么必须做兼容操作,或者尽可能不去使用。

    同样:

    也可以通过上述属性赋值:

    document.getElementById('box').style.color = 'red'; //设置 style 对象中 color 的值

    document.getElementById('box').className = 'box'; //设置 class

    2.getElementsByTagName()方法

    getElementsByTagName()方法将返回一个对象数组 HTMLCollection(NodeList),这个数组保存着所有相同元素名的节点列表。

    document.getElementsByTagName('*'); //获取所有元素

    PS:IE 浏览器在使用通配符的时候,会把文档最开始的 html 的规范声明当作第一个元素节点,所以在求length的时候,IE会比谷歌火狐多一个。代码示例:

    window.onload = function () {

    var all = document.getElementsByTagName("*");

    alert(all.length);

    alert(all[0].tagName); //谷歌火狐返回HTML,IE返回!

    };

    HTML部分代码:

    <ul>

    <li>1</li>

    <li>2</li>

    <li>3</li>

    </ul>

    JS部分代码:

    document.getElementsByTagName('li'); //获取所有 li 元素,返回数组

    document.getElementsByTagName('li')[0]; //获取第一个 li 元素,HTMLLIElement

    document.getElementsByTagName('li').item(0) //获取第一个 li 元素,HTMLLIElement

    document.getElementsByTagName('li').length; //获取所有 li 元素的数目

    获取body节点对象:

    var body = document.getElementsByTagName('body')[0];

    alert(body); //返回 HTMLBodyElement对象,body节点

    3.getElementsByName()方法

    getElementsByName()方法可以获取相同名称(name)的元素,返回一个对象数组HTMLCollection(NodeList)

    document.getElementsByName('add') //获取 input 元素

    document.getElementsByName('add')[0].value //获取 input 元素的 value 值

    document.getElementsByName('add')[0].checked //获取 input 元素的 checked 值

    PS:对于并不是 HTML 合法的属性,那么在 JS 获取的兼容性上也会存在差异,IE 浏览器支持本身合法的 name 属性,而不合法的就会出现不兼容的问题,例如,name 属性本身不是div里的属性,所以IE就忽略掉。

    4.getAttribute()方法

    getAttribute()方法将获取元素中某个属性的值。 它和直接使用.属性获取属性值的方法有一定区别。

    document.getElementById('box').getAttribute('id'); //获取元素的 id 值

    document.getElementById('box').id; //获取元素的 id 值

    document.getElementById('box').getAttribute('mydiv'); //获取元素的自定义属性值

    上述获取自定义属性值的方法各浏览器都支持,区别于.属性的方法,代码如下:

    document.getElementById('box').mydiv //获取元素的自定义属性值, 非IE不支持

    document.getElementById('box').getAttribute('class'); //获取元素的 class 值,IE 不支持

    document.getElementById('box').getAttribute('className'); //非 IE 不支持

    //跨浏览器获取className(注:不过貌似高版本的都修复了这个问题了!!!)

    1 if (box.getAttribute('className') == null) {
    2
    3 alert(box.getAttribute('class'));
    4
    5 } else {
    6
    7 alert(box.getAttribute('className'));
    8
    9 }

    PS: HTML 通用属性 style 和 onclick, IE7 更低的版本 style 返回一个对象, onclick 返回一个函数式。虽然 IE8 已经修复这个 bug,但为了更好的兼容,开发人员只有尽可能避免使用 getAttribute()访问 HTML 属性了,或者碰到特殊的属性获取做特殊的兼容处理。

    5.setAttribute()方法

    setAttribute()方法将设置元素中某个属性和值。它需要接受两个参数:属性名和值。如果属性本身已存在,那么就会被覆盖。

    document.getElementById('box').

    阅读更多内容

没有评论:

发表评论