我决议把我写ARM处理器的经历共享给咱们。不是自我吹嘘,我这个核是十分好的核。一个证明办法是下载入FPGA,看她是不是能作业。这种证明办法,我现已做到了。咱们假如能够下载整个工程文件,略微改造一下,即能验证是否成功。可是这还不是推行她的办法。由于关于大多数人来说,仅仅知其然不知其所以然。人们关于不熟悉、不了解的作业,总是觉得奥秘,那么关于她的使用,就会大打折扣。推行她的最好的办法,便是让她成为人人能够轻松写的核。我期望以此推进咱们关于SOC规划的热心。能够幻想,假如最奥秘,最杂乱的CPU核,都能够轻松的写出来的话,那么还有什么能够难得到咱们的呢?
在写之前,我要声明两点精力。这两点精力当然不是我发明的,我仅仅引证起来,让咱们更能读下去,能信任我是能发明这个奇观的,当然你也能发明这个奇观的。榜首点便是毛主席在军事上常常用的“分而歼之”,在政治上的意思便是“拉一派,打一派”。这一招在毛主席的奋斗生计中屡试不爽,成果了他成了巨人。这一点国外叫做“divide and conqur(没拼写对,懒得查了)”,也是很重要的一个办法。所以在面临庞然大物的时分,千万别惧怕,必定要祭起这个”法宝“。榜首步,先试着“divide”,必定让这个庞然大物小起来,然后再小下去,先条分缕析了,现已算成功了一大半了;第二步,从最小的开端,一点点的做,做对了,做好了。好到什么程度?好到这一小点绝不会打扰咱们持续降服下一小点为至。那么降服这个庞然大物就仅仅时刻问题了。包含我现在写这个文章,就得用这个精力,否则的话,千丝万缕,从哪里说呢?从哪里说的清呢?不必怕,我已然用这个办法降服了ARM core,那么把它讲出来,讲理解,绝比照写arm core要简略,我信任我也能够完结的。
可是我缺一点东西:那便是视角问题。由于我是站在我的立场上,我了解全部,我讲的时分,仅仅想当然的从我的视点以为咱们该了解什么。但实际上,这中心的距离,就像愿望和实际的距离相同远。所以我需求咱们有反应,那一点疏忽了,及时提示我,让我一直站在咱们的立场上,讲东西,而不是让我自说自话。假如我自说自话,作用十分差。所以请咱们满足我,满足我便是满足自己。假如或许,请及时提出不理解的当地。让我把这今日的这一末节降服到不会打扰我降服下一末节,这是契合我上面的精力。
有网友,或许会问,我操心吃力的图什么?为什么要满足我?我图啥呢?横竖我从小也算一个狡猾的孩子,越是大人不让我干的作业,我仍是乐意冒险试一下。当然整体来说,我小时分也算听话,归于只做”建设性“损坏的人,掏马蜂窝、堵烟筒这事不干。现在有一件特别有含义的作业,比方ARM公司的这些达人们,卖ARM7核卖的不亦乐乎。忽然,我闯进来,说这东西底子不值钱,你得卖真货,不是特别有意思么?ARM公司越不爽,其实关于咱们来说越是爽。由于咱们整体的水平提高了,那么ARM公司就必须努力提高自己的水平,这样才干凸显他自己的价值。所以这件作业想起来就特别有意思,所以我就决议做这么一件”建设性“损坏的作业。所以请咱们满足我,满足他人其实也是成果自己,请咱们和我一同实践吧。所以,我假如是个软件工程师,我必定会写些病毒啥的,有意思呀!但定心我只会做“建设性”的,我做的病毒绝不会给咱们带来太多费事,由于这不契合我的风格。但我现在已然是一个硬件工程师,就得想办法在硬件上做一些大事。做一些让让某些“大人”不爽的事。人在世上,也就图一乐嘛。呵呵,说多了。
说了半响,还没有说第二点精力。其实第二点也就包含在榜首点上了。不过仍是有别离的。这第二点精力便是古人的”格物致知“的功夫。古代这些儒学咱们们常常对着一花一叶格个半响啥的,便是这种精力的极致。”divide and conqur”仅仅奋斗准则,可是怎样conqur呢?我觉得要用古人的”格物致知“,也便是耐得烦,从最细微的东西”格“起。我在后面临每一个net,每一个wire都描绘出来,便是这样”格“的成果。cpu是一套杂乱的体系,要做的好,就得用net, wire, register搭起来,传闻intel便是这么干的。不过我是和它有别离的。由于我的这一套,仍是把许多功夫交给归纳器完结,我仅仅描绘出来,让归纳器理解罢了。
闲话休提,我期望咱们看了我这一系列的文章后,能够把我的arm核写出来。当然你能发挥,我期望的是咱们发挥,把这个核写的更好。由于我在做离经叛道的作业,哪能期望他人”故步自封“把我的核当成标杆?我仅仅期望抛砖引玉。我要抛出一块砖,对arm这个皇帝的新衣说出:你底子没穿衣服!莫非我知道这个了,不应该告知咱们么?所以纵情的浪费我的arm核吧,由于这样,它存在的含义更大。
开端写了:榜首句是: module arm ( 。这恐怕是verilog规划的经典开篇了。然后是什么?是界说接口。接口其实规则了大部分的功用,关于IP核的重用,告知清楚接口,跟下家阐明清楚,他人才好用核。
module arm (
clk,
rst,
cpu_en,
clk是时钟,rst是异步复位信号。这个就不需求我多解说了。cpu_en是什么?cpu_en是同步使能信号。也便是说只需在cpu_en==1b1时,整个核才作业。假如cpu_en==1b0时,那么这个arm 核就不作业了。简略的说,便是在这个verilog文件里边的一切register都不做什么改动。这就如同有些神话里边说的“时刻中止”,城堡里边的人都静住了,全部都中止了。那么寄存器就归于住在城堡里边的人,由于只需他们安静了,没有活物了,那些依托人而存在的东西就不会动了。这个cpu_en关于整个模块也是重要的,比方你不想让它作业了,就可让cpu_en==1b0,那么他就不作业。再让他作业,只需让”cpu_en==1b1″就可。我在这个FPGA的项目中,就使用这个输入连到一个“开关”上。假如扳到”1b1″,那体系开端作业;假如扳到”1b0″,那它就停住,我就经过串口,把新的code下到它的rom中。
cpu_restart,
irq,
fiq,
rom_abort,
ram_abort,
这是ARM的五个中止源,详细的能够参阅ARM的文档,我在这里仅仅简略带一遍。cpu_restart相当于一个同步复位,它只需是高电平,那么体系又重头开端了。irq,fiq是两个中止,只需它等于“1b1”假如cpsr没关掉它,就得履行相应的中止。rom_abort, ram_abort是对应于rom,ram读过错,则发动一个中止来处理这些作业。
rom_en,
rom_addr,
rom_data,
这三个信号连接到ROM中,是指令的来历。取指令的办法是:rom_en==1b1时,鄙人一个时钟,存放在rom_addr方位的code就呈现在rom_data了。当然假如rom_en==1b0,则rom_data坚持本来的值不变。这是一个十分一般的ROM。取指令的主动权把握在ARM核中。假如它要处理十分杂乱的指令,一个周期底子处理不过来,那怎样办?那就不发动rom_en,只需当处理完了,有闲暇了再发动rom_en,更新rom_data。
ram_cen,
ram_wen,
ram_addr,
ram_wdata,
ram_rdata,
ram_flag
);
前五个“ram_cen,ram_wen,ram_addr,ram_wdata,ram_rdata”是典型的单端口RAM的接口。功用是:在ram_cen==1b1时,开端履行对RAM的操作,一起ram_wen==1b1,履行写操作,把ram_wdata写入ram_addr对应的方位;假如ram_wen==1b0,表明是读操作,就得鄙人一个时钟,把放在ram_addr的数据呈现在ram_rdata。
ram_flag是我新添加的。由于RAM里边呈现了LDRB, STRH这样对字节、字的操作。为了操作简略,我给每一个字节对应了一个标志位:假如ram_flag[0]==1b1表明榜首个字节的操作有用;假如ram_flag[0]==1b1,则读写操刁难榜首个字节无效。比方我履行STRB 0x4000_0000,则ram_flag==4b0001, 表明只对地址0x4000_0000的低8bit进行写入。假如STRH 0x4000_0002,则ram_flag==4b1100, 表明写入0x4000_0000的高 2 byte。
所以我主张连上4块RAM,每块RAM的位宽都是8 bit。让ARM核对每byte的操作是独立的。那每一块的cen便是:ram_cen&ram_flag[3]; ram_cen&ram_flag[2]; ram_cen&ram_flag[1]; ram_cen&ram_flag[0]。
好了,接下来,便是他们位宽的界说:
input clk;
input rst;
input cpu_en;
input cpu_restart;
input irq;
input fiq;
input rom_abort;
input ram_abort;
output rom_en;
output [31:0] rom_addr;
input [31:0] rom_data;
output ram_cen;
output ram_wen;
output [31:0] ram_addr;
output [31:0] ram_wdata;
input [31:0] ram_rdata;
output [31:0] ram_flag;
好了,本篇到此结束,下一节再会!