• 论文答辩已经顺利完成了,四优一良,中上水平吧。所做的工作也已经交接给室里的人了,一天到晚没什么事做,就是不时的研究生部让补充一些表格、资料等。后天授位典礼,下个礼拜到公司报道。学生生活马上就要结束了!不知是好事还是坏事?
  • CY7C68013A是支持USB2.0高速传输的芯片,网上资料很丰富。
    我做的nandflash板上就是通过这个芯片与PC通讯的。采用slave fifo的方式,
    四重缓冲,EP2和EP4一个做IN,另一个做OUT,连接到板上的FPGA。测了一下,FPGA->USB->PC最高速度可以达到38MB/s,PC->USB->FPGA最高速度可以达到29MB/s,两者速度有差距,估计是在后者的传输过程中,CY7C68013A需要做一些辅助的识别操作。
  • 今天才发现AD6.3的PCB向导产生的PCB没有在机械层里画出板子的边沿,只是标出了keepout的大小,默认的是板子的四边往里缩1.3mm,标出的尺寸是keepout的尺寸.结果PCB厂家可能是误解了意思,直接将板子做成keepout大小的尺寸.费了半天才向厂家说清楚.以后做板子的时候,如果是用PCB向导产生的PCB,最好手动在机械层画出板子的边沿,同时把keepout的尺寸标注去掉,以免PCB厂家误解成板子的尺寸.如果需要的时候可以标示出板子的尺寸,千万不要标示keepout的尺寸,以我免画蛇添足.

  •         其实早在十一月初的时候这个公司就来电子科大招人.由于地处福建,搞的跟我现在做的也很接近,所以还是想去.经过笔试,第二天就通知面试.面试分两次,一次是技术人员的面试,一次是人力资源经理的面试.技术面试很顺利,那个技术人员一开场就是"你是所有人中就合适我们公司的"把我乐坏了.在面试过程中主要是对着我的简历你写的工作经历来问的,感觉很顺利,还出现什么问题.面试完之后就直接叫人带我去见人力资源经理.跟那经理聊的是一些与技术无关的事,主要是公司,个人和家庭的情况.聊了个把钟头,最后完了的时候说了"我们基本上要你了",大概这就是口头offer吧.果然当天晚上五六点钟就打来电话,确定录用了我,让我明天带三方协议就签约.真的好快.第三天签约的现场除了我之外还有两个研究生.那个经理主要是跟我们谈一些工作待遇的情况,包括基本工资,资金,补助,住宿,福州的情况,说的很详细,还让我们拿笔来记.最后说可以给我们二十天的时间.但是末了又说,在这二十天里他们可以选你也可以选其它人,如此回复得晚了可能就没戏了.当时可能是前头找了好几个工作都被BS了,信心指数下降,还有就是看到这个公司也蛮有前景的,而且又在福建,直接就人拿出三方协议,填完就直接交给他们了.后来电子科大又来了好些公司,由于三方协议都上交了,也就没再去应聘了.现在想想当初可能是签得太急了,因为瑞芯微给了二十天的时间,完全可以再试几家,最后再决定去向.不过后来的这些公司跟瑞芯微的待遇差不多,所以感觉当初的决定还是正确的.

  • 由于所定的芯片还没回来,挺清闲的。导师那边在做一个东东,需要一个多串口板,让有帮忙画。这个多串口板中心也是一个FPGA,能过FPGA的引脚引出20个串口。其中的一个串口用于与PC机通讯,剩下的串口用于与分布在不同位置的器件通讯。FPGA负责将分布在不同位置器件传回来的信息进行适当的处理,传给PC机。由于器件所处的位置可能比较远,所以用RS422进行差分的收发。但FPGA不能直接接受RS422信号,所以用到了DS26C31和DS26C32芯片,用于单端信号与双端信号的转换。后来发现spartan-3 FPGA支持LVDS,而这种正是
    RS-644,是串口的另一新版本,也是差分收发,比RS-422可以达到更快的速度。如果直接使用LVDS,就可以省下DS26C31和DS26C32两种芯片共10块,但由于室里也没人用过这个,导师不放心,还是让我用RS422。看到FPGA的引脚还剩好多,就专门拿一个bank来做LVDS的实验,VCCO接2.5V,同时VRN、VRP各接50Ω的上接和下拉电阻,引出三对LVDS作测试用,如果测试成功,下回就可以直接用LVDS了。板子上又引出了两个PS/2接口,用来接键盘和鼠标,还有一个15针VGA口,用于接显示器。由于引出了20个串口,如果还直接用普通的9针的串口插座的话,肯定很占板面。考虑到RS422只用了四根线,两根用来发送两根用来接收,而USB插座也是正好是四芯的,可以通过USB插座引出。后来找到USB插座有那种两个USB口封装在一起的,又节省了好多地方。布这个板子相对容易多了,需要考虑的就是差分布线。又是先用specctra自动布线,布完之后引到altium designer6.3里,再进行手工修改。现在的altium designer6.3已经支持差分布线了,比以前的protel dxp2004方便多了。还有那个引脚替换的功能也不错。总共布了四层,两层信号,两层电源和地。用了不到一个礼拜就基本搞定了。
  •  电路板上的固定孔不能与地相连,否则容易造成电路板工作的不稳定。因为固定孔是用来上螺丝的,而螺丝一般是导体。如果固定孔接地,造成螺丝与电路板的地相接,而螺丝很容易接受外面的干扰,从而造成电路板的地的不稳定。整个电路板工作于一个不稳定的地,工作肯定也不稳定。
  • 终于把那块nandflash读写的PCB做完了,面积为13.2mm*9.7mm,,一共布了8层,三层电源和地,五层信号层,信号线宽5mil,电源线宽12mil,最小过孔的内径为12mil,外径20mil,整个看起来密得吓人,真怀疑能否正常工作。由于是第一次做板子,本来已经做好了,就是担心拿出去做后又发现了问题,所以一直拖着没拿去做,最后还是导师催促才赶忙又检查修正了一遍。又发现了问题,原来画芯片的焊盘的时候是看pdf上的标准数据画的,但是我们作出来的试验板只能是手工焊,所以那些焊盘应该适当加长加宽,才好上焊。原来画的flash的芯片管脚只考虑了单片封装(SLC)的,后来一看FPGA的管脚还有剩余,所以把双片封装(MLC)的管脚也考虑进去,希望如果单封装的做通之后可以接着做双片封装的。又从FPGA引出几根管脚作为测试引脚,方便调试。在电源芯片的地方加了大面积的焊盘,用于帮助电源芯片散热。最后又加了用于安装的固定孔。联系了上海的一家PCB厂家,制板费2400块,每片板子100块,做了两块,一共是2600块。问了在其它PCB厂家做过板子的同学,觉得这个PCB厂价格还是很合理的。而且,速度也很快,一个星期就拿到板子了。现在就等着所定的芯片了。芯片的焊接室里有专门的师傅做,不用我烦心。那么密的管脚,让一人新手去焊,谁放心。
  • 在场同步脉冲前后的窄脉冲分别称为前均衡脉冲与后均衡脉冲。按我国电视标准,前后均衡脉冲均为5个,各占两行两行半时间。行同步脉冲宽度为4.7us,均衡脉冲的宽度为2.35us。场同步脉冲也占两行半时间,因开了五个槽而形成五个齿脉冲,场同步中齿脉冲宽度为27.3us,开槽脉冲宽度为4.7us。

  • 今天导师拿了我的优盘去用,回来时说我的优盘上有个病毒,叫sxs。我机子上装了卡巴斯基,应该不会中毒才是。拿过优盘插到自己的电脑上一分析,也就是一种普通的病毒—双击盘符自动运行的病毒。一般这种病毒的特征就是在那个盘符的根目录下放置一个autorun.inf的文件,是个文本文件。打开该文件可以看到一句话
    open=xxx,其中的xxx一般就是一可执行文件。如果是中了上述的病毒,xxx一般就是病毒体了。清除的办法也简单,只须将autorun.inf和病毒体删除即可。这二者如果是隐藏文件的话,还必须通过单击菜单工具-文件夹选项-查看,选中“显示所有文件和文件夹”选项,去除“隐藏受保护的操作系统文件”选项的勾号来查看隐藏文件。因为病毒是通过双击盘符激活运行的,所以想删除的话,须用右击菜单打开该盘符,或是直接在地址栏里键入盘符加“:”也可以打开该盘符。如果双击该盘符,则病毒体被激活运行,删除的时候就会提示文件正在运行,写保护,删除失败。

  • 昨天导师让我读取一14位灰度的bmp图像。因为我原来是在matlab下整过14位灰度bmp图像的。我用原来写的matlab程序来读取这种图像。但是与正确的数据总是偏差一点。究竟是哪里出了问题。费了好大的劲还是没找到原因。是不是我的原理有问题?对了,可以看一下matlab是如何读取16位的bmp图像的。因为matlab在读取完16位bmp图像之后还得将其转化为RGB三分量。如果知道了matlab是如何将16位数据转化为RGB三分量的话,将RGB三分量复原为16位的数据也就不复杂了。经过长时间的仔细查找,终于在readbmpdata.m这个文件中找到了matlab将16位数据转化为RGB三分量的那段代码。代码如下:
    RGB(1:abs(height), 1:width, 1) = uint8(bitslice(X,11,15));
    RGB(:,:,2) = uint8(bitslice(X,6,10));
    RGB(:,:,3) = uint8(bitslice(X,1,5));

    %Scale data for display
    RGB = bitor(bitshift(RGB,3),bitshift(RGB,-2));

    原来RGB三分量是各自从16位的数据X中取其中的5位。将这5位的数据左移3位与这5位数据右移2位相或,最终得到了8位的数据。如此的话,将RGB三分量复原成16位的数据就不困难了。

    原来的程序是这样的:
     function b=read16graybmp(filename)
    if(nargin~=1)
        error('Need 1 parameters!');
    end;0
      i=0:2^5-1;index5=floor(i*255.99/(2^5-1));%for 5bits
     value5(index5 1)=0:2^5-1;
     a=imread(filename);
      b1=value5(a(:,:,1) 1);
      b2=value5(a(:,:,2) 1);
      b3=value5(a(:,:,3) 1);
     b=bitshift(uint16(b1),10) bitshift(uint16(b2),5) uint16(b3);
    如果按照matlab将16位数据转化成RGB三分量的原理的话,程序可以是这样:
     function b=read16graybmp(filename)
    if(nargin~=1)
        error('Need 1 parameters!');
    end;0
      i=0:2^5-1;index5=floor(i*255.99/(2^5-1));%for 5bits
     value5(index5 1)=0:2^5-1;
      a=imread(filename);
      b1=bitshift(a(:,:,1),-3);
      b2=bitshift(a(:,:,2),-3);
      b3=bitshift(a(:,:,3),-3); 
      b=bitshift(uint16(b1),10) bitshift(uint16(b2),5) uint16(b3);
    但是仔细想想,两者的原理是相类似的。如果在运行
    i=0:2^5-1;index5=floor(i*255.99/(2^5-1));
    i8=uint8(i);index55=bitor(bitshift(i8,3),bitshift(i8,-2));
    a=index5==index55;find(a==0)
    结果显示index5与index55是一样的。但原来写的程序读出来的数据有的就是有偏差,究竟是怎么回事呢。费了好大的劲才找到问题。原来a=imread(filename);执行后,a的类型是uint8,如果a是255的话,那么加1等于0而不是256,问题就出在这里。于是,我们可以将原来的程序稍微改动一下就可以了。
     function b=read16graybmp(filename)
    if(nargin~=1)
        error('Need 1 parameters!');
    end;0
      i=0:2^5-1;index5=floor(i*255.99/(2^5-1));%for 5bits
     value5(index5 1)=0:2^5-1;
     a=double(imread(filename));
      b1=value5(a(:,:,1) 1);
      b2=value5(a(:,:,2) 1);
      b3=value5(a(:,:,3) 1);
     b=bitshift(uint16(b1),10) bitshift(uint16(b2),5) uint16(b3);

    参考:用matlab读取16位、14位、12位灰度bmp图像(*.bmp)

  • 由于FPGA工艺的不断改进,功能的不断增强,价格的不断下降,现在的电子系统设计更多的考虑FPGA的使用。现在的PCB设计更多的是以FPGA为中心。由于FPGA引脚的可配置性,在设计以FPGA为中心的PCB时,我们应该更好的利用这一特性,以更好的完成PCB的布线。通过引脚的交换,可以使原本交叉的布线不交叉,这可使布线更容易,减少布线长度和层数。protel dxp为我们提供了这个功能。在PCB完成布局后,就可以利用引脚交换功能交换FPGA的引脚配置。打开PCB,单击菜单Tools-FPGA Pin Swapping-FPGA Pin Swap Manager,弹出一对话框,提示连接到一FPGA工程,可以是已有的,也可以是新建的。完成后弹出一对话框,FPGA Pin Swap Manager for Componet,通过这个对话,我们可以设置交换组ID(Swap group ID),以更好地让dxp完成引脚交换。交换组ID可以是任意一数,引脚交换在具有相同的交换组ID的引脚间进行。可以设置几个不同的组ID,使不同组各自进行引脚交换。不设置交换组ID的引脚则不进行引脚交换。有些FPGA的引脚,比如时钟引脚,配置引脚等不能进行引脚交换,则不设组ID。完成后回到PCB,单击菜单Tools-FPGA Pin Swapping-Auto,则dxp开始进行自动引脚交换。完成后,原来交叉成一团的虚拉线现在已经总体不交叉了,这样进行布线可以容易完成。
  •     Protel dxp自带的布线器situs的自动布线功能不敢恭维,速度慢,效率也不高。先前试过几次,自己画的一个PCB如果用situs自动布线,要一个多小时,而且只布到96%,还有好多connection。后来用specctra自动布线,只要六、七分钟,可以布到99%以上,对PCB稍加改动一下,最终可以布到100%。通过对比,可以看到specctra自动布线功能的强大。难怪protel dxp也为specctra留下了接口。通过这个接口,我们可以用specctra代替situs,提高自动布线的效率。
      在用protel DXP的画完原理图,映射到PCB中,完成布局,设定好布线规则后,我们就可以开始自动布线了。首先将PCB文件另存为.dsn文件,然后启动specctra,Design/Session File一栏选择刚才保存的.dsn文件,其它可以不选择,单击start specctra,PCB就载入完成。单击菜单Autoroute-Route,选择smart,然后按OK,specctra就开始自动布线。速度之快,是用situs所不能体会得到的。在specctra自动布线之前也可以设定布线规则,可以在载入PCB后通过菜单或命令行完成,也可以在选择.dsn文件的同时选择.do文件完成,其中的.do包含设定规则的命令和其它的命令。如下是一个.do文件的内容:
    define (class flashv)
    define (class flashv (add_net  FLASHVCC3V3))
    define (class flashv (add_net  FLASHVCC3V3-2))
    define (class flashv (add_net  GND))
    rule class flashv (pin_width_taper up (max_length -1))
    define (pair (nets RXD+ RXD-))
    define (pair (nets TXD+ TXD-))
    rule pcb (edge_primary_gap 10)
    smart_route (min_via_grid 11.811) (min_wire_grid 5) (auto_fanout on) (auto_fanout_via_share on) (auto_fanout_pin_share on) (auto_testpoint off) (auto_miter off)
    通过.do文件,原来重复繁琐的菜单操作就只需要一步就可以完成。如果不能布到100%,可以通过查看分析specctra布线结果,在protel dxp中的PCB中作适当改动,存为.dsn文件,继续让specctra自动布线。在布完线后,可以运行菜单Autoroute-postroute中的选项,比如将90度角改为45度等。最后,单击菜单File-Write-Routes,保存布线文件为.rte文件。在protel dxp的PCB图中,单击菜单File-Import,选择所保存的.rte文件。在将.rte文件导入PCB图后,可能会出现一些虚拉线,只要稍微移动与虚拉线连接的器件,虚拉线就会变成实布线。由于是自动布线,最后还要手动修改一些走线,使PCB减少过孔,减少走线长度等,使PCB更美观。
  • 今天早上上班刚一开机,显示器又出现昨天同样的问题。真的好生奇怪,昨天不是已经修好了吗?!昨天晚上我就用了整个一个晚上也没问题。于是又打开机体,查了一下按键,没问题,电阻也没问题,电容也用新的替换,再开机,问题依旧。最后干脆好一招绝的,把按键板与底板的连线拔,再一开机,问题解决了,只是现在按键就使不上了。幸好一般是不用按键的。就整到这吧,又浪费了一个上午,好花时间!
  • 今天早上上班刚一开机,显示器就出了问题,OSD菜单不间断地出现又消失,而且显示器上的按键的功能也发生了紊乱。这可怎么办?这样的话谁受得了,那个OSD菜单不断地自动跳出尔后又自动消失,很是惊人。
      自己解决不了,只好将情况向导师说明。导师过来看了一下,就让我将显示器机体打开。这个我可从没想过,因为显示器机壳上写有“内有高压,非专业人员切勿打开”,一般人一看到这,马上就会打住,谁还敢轻易打开机体。既然导师都这样说了,相信他以前整过这个东西,我也就无后顾之忧了。在导师的指导下,小心翼翼地将打开机壳,里面的东西一目了然:中间是个显像管,显像管后头是一高压包,显像管侧面有一块驱动电路板,靠近机体按键部位的是一小块电路板,接受用户的按键。既然问题出在OSD上,那就应该查看一下跟OSD相连的一些器件。看了一下,有个器件是24C16,是个EEPROM,应该不会是这个的问题,还有个WELTREND 6148,估计是个MCU。赶快上网查它的pdf。在网上顺便查了一下显示器OSD菜单自动跳出这个问题。我的显示器是PHILIPS 107P5。还真的有好些人碰到跟我类似的情况。其中有个说法是说出现这个问题是因为连接到按键板的信号线上的那个电容因为受潮出现了问题,可以换个等值电容或干脆不接电容。后来又下到PHILIPS 107P2的电路图,估计跟107P5的差不多。回来后跟导师一说,然后找了一个等值的电容替换掉原来的电容,用螺丝上好机体,再开机一试,问题依旧。仔细看看107P2的电路图,其按键部分是五个按键,而107P5的按键是四个按键。不过原理是一样的,不同的按键接不过的电阻,所有的电阻的一端接同一个点(这个点还接了个上拉电阻),另一端与按键相连,按键的另一端接地。只要按下不同的按键,就会将对应的电阻接到电路上去,改变电路的电流,进而改变电压,而这个电压送到MCU的一个管脚上进行采样,通过采样值,MCU可以判断用户按下了哪个键,进而响应用户的动作。问题很可能出在按键板上,将按键板卸下,用万用表各个电阻的阻值,各个电阻并未有短路的情况(我以为电阻出了问题就只有短路的情况,后来发现电阻阻值不符也会出问题)。看到我找不出问题,导师将按键板拿过去,自己亲自测量。电阻上标有不同的阻值,虽说以前学过,不过早就忘了。会不会是电阻的阻值跟所标示的阻值不一样呢?赶忙向导师提出这个问题。导师还是挺强的,一眼就能电阻的标示值。果然有两个电阻的阻值跟所标示的阻值相差较大。原来是27K和47K的电阻,测量下来只有十多K。导师找来27K和47K的两个电阻,替换掉的电阻,然后将按键板放到原来的位置,上好机壳。上电一试,没问题了。原来竟然是两个电阻出了问题。想想如果直接将显示器拿到成都去修,不但费时,还费力费钱,到头来只为这两个电阻。电阻虽小,出了问题也会让整个系统出问题。每个东西都有每个东西的价值,哪怕它再小再不起眼。
  • 由于在设计中需要用到除法器,开始的时候使用是如下的形式
     g<=8192 when S>=0 and S<2 else
    8191 when S=2 else
    5460 when S=3 else
    4095 when S=4 else
    3276 when S=5 else
    2730 when S=6 else
    2340 when S=7 else
    2047 when S=8 else
    1820 when S=9 else
    ...
    4 when S>=3277 and S<4096 else
    3 when S>=4096 and S<5461 else
    2 when S>=5461 and S<8192 else
    1;
    来实现g=16383/s这个除法计算,上述那么长的一大串数据用人工来写是很累的,也容易出错。编个matlab程序就可以轻松实现。以前不是说工业革命让我们可以用机器来制造机器,那么现在我们可以用程序来帮助我们写程序,一个道理。这样做是可以实现的,并且没用延迟,就是所用的资源比较多。
      后来看到ISE中有除法器的IP核,被除数最多可以32位,并且是可以定制的。于是就试着使用。根据需要,我们在程序中设定被除数为28位,商只需整数部分,这样一来,从输入数据到得到商会用28个基本时钟的延迟(我们在定制中已经设定了一个基本时钟计算一位)。我们需要将计算出来的结果写入到一个显示ram中,以供给显示模块使用。在将数据写入ram中是用像素时钟、行时钟、场时钟来控制,如果不作任何的处理,直接写入ram中,显示出来的图像将会整体向右偏移28个像素,而最右边的28个像素跑到了图像的左边来了。最后导师告诉我一个方法,重新产生行时钟,新的时钟比原来的行时钟延迟28个像素,这样一来就没问题了。一试,果然可以,这个方法确实不错。
  • 图像的直方图统计的原理是用图像的灰度值来作为地址,统计各个灰度值出现的次数。开始的时候打算用数组的形式来实现,做出来一综合才发现用尽了所有的SLICES资源,并且还不够。所以用这种方法来实现是行不通的。想到了ram资源,可以做一个双口ram来存储直方图的数据。双口ram有两个输入口,一个基本时钟内可以进行读或是写两次。我们可以用一个口用来读出ram中原来的数据,另一个负责将读出的数据加一后写回ram中。由于双口ram的两个口是并行进行的,不会互相影响。这样一来,更新一个计数由两个步骤组成,一个是读出ram中的计数,另一个是将读出的计数加一后写回中ram中,两个步骤组成一个流水,平均下来,更新一个计数只须一个基本时钟,跟得上外面进来的数据流的速度。最终的实现证明了这个方法的可行性。
  • 红外图像采集设备送出来的图像信号的灰度直大部分集中在一个小范围的区域内,给图像的显示带来了一定的困难。必须通过一定的方法将灰度拉伸到整个范围,才能显示出清晰的图像。由于是用FPGA来进行灰度拉伸的,所以拉伸的方法往往比较简单。以前的做法是选取整帧图像的最大值最小值来作为灰度拉伸的两个参考值,由于图像中往往有噪声点,而这些噪声点很大可能就是极值点,这样一来,所选取的最大值最小值就会经常跳动,造成显示的时候图像也在跳动,闪烁不定,不利于工作人员对图像的查看。补救的办法就是在选取整帧图像的最大值最小值时先进行适当的滤波,滤除噪声点,但效果也不是十分理想。
      现在我们采用了直方图的方法来选取整帧图像的最大值最小值。具体的方法是这样的,先对整帧图像作直方图计,然后从最低灰度值往上进行点数累加,直到累加的点数达到预先设定的一个值,比方说整帧图像点数的%2,将此时的灰度值作为所要选取的最小值;同理,从最高灰度值往下进行点数累加,选取出最大值。最大值最小值选出来之后就可以根据灰度拉伸的公式进行两点线性拉伸。这种方法比前一种方法好,显示效果也好得多,就是利用FPGA进行直方图统计比较麻烦。
  • 2006-08-10

    nandFlash简介 - [参考资料]

    nandFlash存储芯片
    现在市面上的常见的优盘、MP3和MP4等数码设备的存储系统都是采用nandFlash存储芯片来实现的。nandFlash价格便宜量又足,性价比很高,并且十分轻便,抗震性也很不错,很适合用来做数码产品。生产nandFlash芯片的厂商主要有Samsung、Hynix、Micron、STMicroelectronics 、Toshiba等。现在单片的nandFlash芯片的存储容量已经可以做到4GB。很难想像,在一个大小只有12*20*1.2mm的芯片里可以做到如此的容量。想想以后如果现在计算机的主要存储设备——硬盘被nandFlash芯片代替,那计算机将是另一番景象,更轻便,更稳定。很多厂商都在打这方面的主意,包括intel、samsung。相信这一天很快就会到来。Apple公司的iPod原先采用微型硬盘做为存储系统,后来改成了nandFlash就是明证。
  • 因为原来的题目实用价值不是很高,做出来也没什么份量(其实我已经做得差不多了,在这个东西上还整了篇文章,《利用matlab与modelsim联合仿真VHDL图像算法》,发表在《光电工程》2005年12月份的增刊,挣了80块大洋,版面费室里给出的),所以决定换题。之所以六月份早早地回所,是希望尽早把新的题目定下来,因为所剩的时间已经不多了。六月底终于如愿地开了新的题目,主要是做高速海量存储系统的设计,做出来的东西就跟优盘差不多,只是用FPGA直接控制nandFlash存储芯片的读写,并且同时对多片nandFlash进行读写,所以速度可以达到很高,然后通过USB2.0接口将数据传给PC,从版图设计到FPGA设计都要做,工作量还是有的,只是时间太紧,有点担心做不完,那可就毕不了业了……,不敢再往下想了,既然做了,就要做好。多加几天班应该没问题的。
  • 在用ISE编写代码并下载到FPGA上运行的过程中,由于源程序经常需要更改,程序的下载也是经常的操作。程序下载就是重复的几个对话框选择操作,但每次源程序修改完,程序下载的操作也必须相应的重复一次。对此很是不爽,因为这些操作都是千篇一律。于是决定整个批处理文件来执行这些操作。
      一般源程序编译完之后产生的是.bit文件,可以直接下载到FPGA上,但是断电之后将丢失,因为.bit文件是直接写入到FPGA芯片的。如果想断电之后所编程的内容不丢失,可以利用.bit文件来产生.mcs文件,再将.mcs文件下载到FPGA相配套的rom或是flash芯片上。经常重复的操作便是从.bit文件产生.mcs文件,然后进行下载,其间必须多次的进行对话框选择操作。由于ISE中附带有impact编程工具,该工具也支持命令行方式,实现批处理就是将那些默认的操作放置在批处理文件中,减少鼠标操作,减轻工作量。impact命令支持批处理文件,我们可以先编写批处理文件,再调用impact来执行该批处理文件。在此我主要写两个批处理文件,一个是从.bit文件产生.mcs文件,另一个就是将.mcs文件下载。第一个批处理文件取名为batch1.txt,内容如下:
    setMode -pff
    setSubmode -pffserial
    setAttribute -configdevice -attr name -value "PFFConfigDevice"
    setAttribute -configdevice -attr size -value "0"
    addCollection -name "Untitled"
    setAttribute -collection -attr dir -value "UP"
    addDesign -version 0 -name "0000"
    addDeviceChain -index 0
    addDevice -position 1 -file ".\ccdtop.bit"
    generate -format mcs -fillvalue FF -output Untitled
    quit
    第二个批处理文件取名为batch2.txt,内容如下:
    setMode -bs
    setCable -port lpt1
    Identify
    setAttribute -position 1 -attr devicePartName -value "xcf02s"
    setAttribute -position 1 -attr configFileName -value ".\Untitled.mcs"
    Program -p 1 -e -v
    quit
    具体的参数意思可以参见有关的帮助文件。
    最后编写一个总的批处理文件test.cmd,内容如下
    cd E:\work\fpga\ccd512_15M
    e:
    impact -batch batch1.txt
    pause
    impact -batch batch2.txt
    pause
    现在只要双击test.cmd文件就可以执行从.bit文件产生.mcs文件,并将.mcs文件下载的操作,其中的pause是用来让程序暂停以察看执行情况,如果不需要可以去掉。
  •   一同学机子上有些chm文件可以打开,但是就是无法显示内容。而其它chm文件可以正常显示。确实挺怪的。chm文件中显示内容就相当于网页的显示,靠的是链接。打开无法正常显示的chm文件,在无法正常显示内容的地方右击属性,可以看到当前显示的内容的路径。仔细一看,发现整条路径名中含有非法的字符",",也就是chm文件所在的目录的目录名含有非法的字符",",于是修改一下目录名,再打开无法正常显示的chm文件,现在可以正常显示了。

  • 在今年四月份的《工业控制计算机》发了篇文章,,文章是去年投的。可以左等右等就是没收到样刊。昨天打电话过去问一下,说是四月份一出版就寄过来了,让我再找一下,如果弄丢了今天说一下,可以再给我寄一份。今天下午本来要打电话过去,问了一下室里的李师傅,竟然已经寄过来了一段时间,只是我在上学位课,所以一直放在那里。喔,原来如此,好高兴,三本样刊,让我等得好苦啊。
  • 记得以前在初中的时候看过一个英文字谜,就是问最长的单词是哪个。答案是smiles,因为从单词的头(字母's')到尾(字母's')有一英里(mile),确实够长的了。这个字谜是靠会意来猜中的。而英文中实际长度最长的单词是哪个,今天不小心让我碰上了。pneumonoultramicroscopicsilicovolcanoconiosisn.[医]硅酸盐沉着病,矽肺病),共45个字母,这么长的单词谁记得了!用百度搜一下最长的单词,竟然还有一个更长的单字:MethionylglutaminylarginyltyrosylglutamylserylleucylphenylalanylalanylglutaminylleucyllysylglutamylarginyllysylglutamylglycylalanylphenylalanylvalylprolyphenylalanYlvalythreonylleucylglycylaspartylprolylglycylisoleucylglutamylglutaminylsErylleucyllysylisoleucylaspartylthreonylleucylIsoleucylglutamylalanylglycylalanylasparthlalanylleucylglutamylleucylglycylisoleucylprolylphenylalanylseRylaspartylprolylleucylalanylaspartylglycylpRolylthreOnylisoleucylglutaminylasPfraginylalanylthreonylleucylarfinylalanylphenylalanylalanylalanylglycylvalythreonylprolylalanylglutaminylcysteinylphenylalanylglutamylmethionylleucylalanylleuOylisoleucylarginylglutaminyllysyhistidylprolylthreonylisoleucylprolylisoleucylglycylleucylmethionyltyrosylalanylasparaginylleucylvalylphenylalanylasparaginyllysyglycylisoleucylaspartylglutamylphenylalanylthrosylalanylglutaminylcysteinylglutamyllysylvalylglycylvalylaspartylserylvalylleucylvalylalnylaspartylvalylprolylvalylglUtaminylglutamylserylalanylprolylphenylalanylarginylglutaminylalanylalanylleucylarginylhistidylasparaginyvalylalanylprolylisoleucylprolylisoleucylphenylalanylisoleucylphenylalanylisoleucylcysteinylprolylprolylaspartylalanylaspartylaspartylaspartylleucylleucylarginylglutaminylisoleucylalanylseryltyrosylglycylarginylglycyltyrosylthreonyltyrOsylleucylleucylserylarginylalanylglycylvalylthreonylglycylalanylglutamYlasparainylarginylalanylalanylleucylprolylleucylasparaginylhistidylleucylValylalanyllysylleucyllysylglutamyltyrosylasparaginylalanylalanylprolylprolylleucylglutaminylglgycylphenylalanylglycylisoleucylserylalanylprolylaspartylglutaminylvalyllysylalanylalanylisoleucylaspartylalanylglycylalanylalanylglycylalanylisoleucylserylglycylserylalanylisoleucylvalyllysylisoIeucylisoleucylglutamylglutaminylHistidylasparaginyliSoleucylglutamylprolylglutamyllysylmethionylleucylalanylalanylleucyllysylvalylphenylalanylcalylglutaminylprolylmethionlysylalanylalanylthreonylarginylserine

    总共1913个字母。是“色氨酸合成酶A蛋白质”(一种含有267种氨基酸酶)的全称,普通的字典上能查到的最长的单词是前者,而后者需用医学专用字词才能查得到。这么长的单词并不实用,估计是很少人会用到它们,充其量不过是多了一项吉尼斯世界记录罢了。可能人们当初造出它们来本身就是为了创造新的吉尼斯世界记录!

  •   这几天一直在写控制台程序,每次调试的时候总要重新输入数据,很是麻烦,尤其在输入数据比较多的时候更是如此。把时间浪费在这样纯粹机械活动中太不值得。能不能让机子帮我完成这些机械动作?于是想到了重定向:写个数据文件,里面放入测试数据,调试控制台程序的时候将该数据文件重定向到控制台程序上。一试,果然可以,这样就省事多了。但是每次调试控制台程序的时候还是得运行cmd,进入到控制台程序所在的目录,再运行,次数多了也觉得麻烦了!想想有没有办法解决这个问题。于是想到了批处理文件:可以建个批处理文件,里面放入所需运行的各条命令,只要运行这个批处理文件就可以了。经过几次的修改,终于试验成功了。将批处理文件建在桌面上(图个方便),文件内容如下:

    cd D:\dotNet\myproj\AaddB\Debug
    D:
    AaddB <dat.txt
    pause

    其中,“D:\dotNet\myproj\AaddB\Debug”为控制台程序所在的目录,“AaddB”为控制台程序,“dat.txt”为测试数据,也放在控制台程序所在的目录,“pause”为暂停语句,如果不加该语句cmd一运行完就自动关闭,没法看清运行结果。你可以修改上述的参数以适合你的需求。

     

     

  •   前些时候去上《软件无线电》时,听老师讲信号插值的原理:在相邻两个信号间插入N-1个零,然后信号通过低通滤波器,原先插入的零的位置自动替换为适当的插值,觉得甚是奇妙。如果将其应用于图像的插值,就不用再一个个地来计算所在位置的插值了。经过几天的试验,终于成功了。大体是设要将原图像放大N倍,则在原图像数据的相邻两个像素插入N-1个零,将插值后的图像进行FFT2变换,在频域对数据进行截取,将高频部分置为1(或是0),再进行IFFT2变换,如此图像就已经插值放大的,图像质量跟还不错。

      参考程序如下:

    %a function to magnify the image using the lowpass filter.
    %       function cout=magnif(filestr,x,y)
    %       filestr: the image filename string
    %       x:the times magnify in the row direction,integer>=1
    %       y:the times magnify in the column direction,integer>=1;
    %designed by darnshong,chenzushang@sina.com
    %March 31,2006
    function cout=magnif(filestr,x,y)
    a=imread(filestr);
    timesx=round(x);%x;
    timesy=round(y);%y;
    b=a(:,:,1);
    xy=size(b);
    sy=xy(1);
    sx=xy(2);
    c2=zeros(sy*timesy,sx*timesx);
    n=1:sy;
    m=1:sx;
    c2(n*timesy,m*timesx)=b(n,m);
    if(timesx>1)
        for i=timesy:timesy:(sy*timesy),
            fc=fft(c2(i,:));
            fc((ceil((sx+1)/2)):(timesx*sx-ceil((sx+1)/2)+1))=0;
            c2(i,:)=abs(ifft(fc));
        end,
    end,
    if(timesy>1)
        for j=1:(sx*timesx),
            fc=fft(c2(:,j));
            fc((ceil((sy+1)/2)):(timesy*sy-ceil((sy+1)/2)+1))=0;
            c2(:,j)=abs(ifft(fc));
        end
    end,
    c2=c2*timesx*timesy;
    % minc=min(min(c2));
    % maxc=max(max(c2));
    % cout=uint8(256/(maxc-minc).*(c2-minc));
    cout=uint8(c2);
    %imshow(c2);

  • 2006-03-23

    如此期刊 - [生活流水帐]

      今天晚上去阅览室看书,竟然发现一个奇迹,《*计算机**》一期上竟然有厚厚的一大本,数了一下,有六七十篇之多。记得以前厚度也就跟一般的期刊差不多,篇数撑死不过二十篇。在一期的期刊上发如此多的文章,不知为何。细细一想,可能多少跟“版面费”有点牵连。这其中的内容,你可以自由联想,不说也罢。
  • 今天不小心发现可以直接上国外网了,再也不会出国代理了!以后再也不用为找不到出国代理发愁了。
  • //matlab mex file to convert font characters to image
    //author:darnshong http://darnshong.52blog.net
    //date:2006,2
    //compile to use >> mex font2pic.c user32.lib gdi32.lib
    //declaration: a=font2pic(iBits,iHeight,iAngle,iBold,bItalic,pstrFontName,chartemp);
    // iBits:double the font chararter's resolution 1,2,3,4
    // iHeight:double  the font character's height
    // iAngle:double  the font character's angle
    // iBold: double  the font character's weight
    // bItalic: boolean  be italic or not
    // pstrFontName:char array  the fontname.
    //You can use "a=enumfont;" to get all the right fontnames;
    // chartemp: char  the font character
    //e.g.:a=font2pic(2,695,0,300,0,'华文行楷','尚');
    //usage: >>a=font2pic(2,695,0,300,0,'华文行楷','尚');
    //       >>imshow(a)

    #include <windows.h>
    #include <string.h>
    #include <tchar.h>
    #include "mex.h"
    int BITSTABLE[]={2,5,17,65};
    void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
    {
        int iBits,iHeight,iAngle,iBold,charLineW,nDims[2],i,j,k,recchar;
        UINT uchar;
        bool bItalic,*pbool;
        BYTE chartemp[3];
        char *pBuf=NULL,*pchar,pstrFontName[100];
        mxChar *cShowChar;
        MAT2 mmat2={0,1,0,0,0,0,0,1};
        GLYPHMETRICS glpm;
        HFONT hfont,hold;
        HDC hdc;
        DWORD nLen,nLentemp;
        if(nrhs!=7)
            mexErrMsgTxt("The number of input arguments must be 7");
        iBits=(int)*(double*)mxGetData(prhs[0]);
        iHeight=(int)*(double*)mxGetData(prhs[1]);
        iAngle=(int)*(double*)mxGetData(prhs[2]);
        iBold=(int)*(double*)mxGetData(prhs[3]);
        bItalic=(bool)*(double*)mxGetData(prhs[4]);
        mxGetString(prhs[5],pstrFontName,100);
        mxGetString(prhs[6],chartemp,3);
        if(iBits<1 || iBits>4)
            mexErrMsgTxt("The iBits must be an integer between 1 and 4.\n");
        if(chartemp[0]<128)
        {
            uchar=chartemp[0];
         }
        else
        {
            //mexPrintf("the char num is %d\n",chartemp[0]);
            uchar=chartemp[0];
            uchar=uchar<<8;
            //mexPrintf("the char num is %d\n",uchar);
            uchar+=chartemp[1];
            //mexPrintf("the char num is %d\n",uchar);
           
        }
        //mexPrintf("iBits:%d;iHeight:%d;iAngle:%d;iBold:%d;iItalic:%d;FontName:%s;Char:%d\n",iBits,iHeight,iAngle,iBold,bItalic,pstrFontName,uchar);
        //printf("The font name is %s\n",pstrFontName);
        hfont=CreateFont(iHeight,0,iAngle,0,iBold,bItalic,0,0,DEFAULT_CHARSET,OUT_CHARACTER_PRECIS,CLIP_CHARACTER_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH|FF_DONTCARE,pstrFontName);
        if(hfont==NULL)
        {
            mexErrMsgTxt("Fail to create the font!\n");
        }
        hdc=GetWindowDC(NULL);
        hold=SelectObject(hdc,hfont);
        if(iBits==1)
            nLen=GetGlyphOutline(hdc,uchar,iBits,&glpm,0,NULL,&mmat2);
        else
           nLen=GetGlyphOutline(hdc,uchar,iBits+2,&glpm,0,NULL,&mmat2);
                     //GGO_BITMAP 1
              // GGO_GRAY2_BITMAP   4
                    // GGO_GRAY4_BITMAP   5
                    //GGO_GRAY8_BITMAP   6
        if(nLen!=GDI_ERROR)
        {
            if(pBuf!=NULL)
                free(pBuf);
            if(nLen<0)
                mexErrMsgTxt("the malloc memory'size can't be negative!\n");
           
            pBuf=(char*)mxMalloc(nLen);
            if(pBuf==NULL)
            {
                mexErrMsgTxt("Fail to malloc the memory!\n");
            }
            if(iBits==1)
            {
                nLentemp=GetGlyphOutline(hdc,uchar,iBits,&glpm,nLen,pBuf,&mmat2);
               
                if(nLentemp!=nLen)
                {
                    mexPrintf("The font size is too big!\n");
                    exit(-1);
                }
                charLineW=(glpm.gmBlackBoxX/32+(glpm.gmBlackBoxX%32==0?0:1))*4;
                //mexPrintf("charLine:%d,X:%d; Y:%d\n",charLineW,glpm.gmBlackBoxX,glpm.gmBlackBoxY);
                nDims[0]=glpm.gmBlackBoxY;
                nDims[1]=glpm.gmBlackBoxX;
                if(nDims[0]<=0 || nDims[1]<=0)
                {
                    mexErrMsgTxt("return error matrix!\n ");
                }
                plhs[0]=mxCreateNumericArray(2,nDims,mxLOGICAL_CLASS,mxREAL);
                pbool=(bool*)mxGetData(plhs[0]);
                for(j=0;j<glpm.gmBlackBoxY;j++)
                    for(i=0;i<glpm.gmBlackBoxX/8;i++)
                      for(k=0;k<8;k++)
                     {  
                        pbool[(8-k+i*8)*glpm.gmBlackBoxY+j]=!((pBuf[j*charLineW+i]&1<<k)>>k);
                      
                       }
               }
            else
            {
                nLentemp=GetGlyphOutline(hdc,uchar,iBits+2,&glpm,nLen,pBuf,&mmat2);
               
                if(nLentemp!=nLen)
                {
                    //mexPrintf("The font size is too big!\n");
                    exit(-1);
                }
                charLineW=(glpm.gmBlackBoxX/4+(glpm.gmBlackBoxX%4==0?0:1))*4;
               // mexPrintf("charLine:%d,X:%d; Y:%d\n",charLineW,glpm.gmBlackBoxX,glpm.gmBlackBoxY);
                nDims[0]=glpm.gmBlackBoxY;
                nDims[1]=glpm.gmBlackBoxX;
                if(nDims[0]<=0 || nDims[1]<=0)
                {
                    mexErrMsgTxt("return error matrix!\n ");
                }
                plhs[0]=mxCreateNumericArray(2,nDims,mxUINT8_CLASS,mxREAL);
                pchar=(BYTE *)mxGetData(plhs[0]);
                for(j=0;j<glpm.gmBlackBoxY;j++)
                    for(i=0;i<glpm.gmBlackBoxX;i++)
                        pchar[i*glpm.gmBlackBoxY+j]=(BYTE)(255.0-pBuf[j*charLineW+i]*255.0f/(BITSTABLE[iBits-1]-1));
              
            }
             mxFree(pBuf);
           
        }
        else
        {
            plhs[0]=NULL;
            //mexPrintf("nLen is %d,The font size is too big!\n",nLen);
            mexErrMsgTxt("Fail to select the font!\n");
        }
        
            SelectObject(hdc,hold);
            DeleteObject(hfont);
            ReleaseDC(GetDesktopWindow(),hdc);
       
    }

  •   原本是打算坐17号的火车的,可是17号到福州火车站买票时,17、18号只有无座票,有座的票要19号的。火车上没座位实在难受,所以买了19号的票。17、18两天在姑妈那里住。还好我们第一、二个星期是在选课,不大要紧。

  •   今天起了个大早,八点多,以往都是睡到十点左右。到学校附近的售票点去,并没有想像的那么多人,柜台前只有一人,记得以前买票的时候都是一长长的队伍。不会是我回去得太早了吧?!上前问了一下十三号的票,回答说没有票了,心一下子凉了半截。再问有没有十二号的票,这回还好,终于有了肯定的答复。掏钱的时候突然想到应该要个靠窗户的比较好点,跟那售票员一说。她竟然说再不买可能就没了!以前这种售票点是很乐于帮你挑个靠窗户的硬座的!这次竟然如此,可以上面下了什么通知了吧!算了,将就吧,于是付了钱,也拿到了票。33号的座位,还算挨着窗户。终于可以回家了。