-
试下AXI read channel
刚开始试着写axi的master和slave。看了下arm最近的手册,改叫manager和subordinate了。 先试了下read channel,ar和r,也就是address read和read。 arid,rid都没处理,也没有多条管道,每次只能一个读请求。 size,length也都没有,每次只能读bus width,也就是32bit。 所以主要是处理握手过程,valid和ready。 m_arvalid和m_rready都是testbench里force的,所以并不是对齐上升沿的,不过这样正好可以和手册里给出的例子一样。 前面的黄框,m_arready是在m_arvalid前面就已经high了,这个是允许的,表示slave随时可以接收地址,本身没有任何待处理的请求。 一但正在处理请求,m_arready就不能上来就high了,要看进来的m_arid和m_arvalid。如果m_arid不同,并且m_arvalid是high,那可以接收新的请求,这时才能给出m_arready。 如果m_arid和正在处理的请求一样,那就要需要等当前同id的请求处理完才能给出m_arready。 我这里是提前给出的m_arready,这时候m_arvalid也来了,在下一个上升沿信号采集到以后,m_arvalid就可以撤了,这里是testbench做的。 而slave这边一但成功的接收到一个读请求的地址,就把内部寄存器busy置high,同时拉低m_arready,表示不接收新请求。这时就算有新地址和m_arvalid,那也得一直valid等着。 一个cycle后,sram得数据就读出来了,同时给出m_rvalid,表示让master过来拿数据。 这里我特意让testbench过了很久才给出m_rready来拿数据。右边红框里,m_rvalid直到遇到m_rready,才拉低回0。 同时busy也变0,表示可以处理下一个读请求,这样上面的m_arready也马上拉到1了。 这里逻辑上又遇到以前的逻辑开关了。 m_rvalid要在ar_enter来到后的下一个cycle置high(因为sram读写需要1个cycle),直到看到m_rready后落回low。 ar_enter __--______________ m_rready ______________--__ rdata_valid ____------------__ 100 wire rdata_valid_next; 101 102 assign rdata_valid_next = (rdata_valid | ar_enter) & (~m_rready); 103 104 dff_s #(1) rdata_valid_reg ( 105 .din (rdata_valid_next), 106 .clk (aclk),...
-
reset的一个有意思的地方
没找到是什么的原因,先看下这个简单的代码。 77 dffr_s #(1) busy_reg ( 78 .din (ar_enter & (~r_retire)), 79 .clk (aclk), 80 .rst (~resetn), 81 .q (busy), 82 .se(), .si(), .so()); ar_enter为1,r_retire为0时,输入为1,busy也就此为1。 图上黄框也是这样显示的,这个时候的reset复位结束变1的时候clk正好在上升沿。(感觉这种时候在实际电路上会让事情更复杂,因为reset和clk应该不会同步的很准。) 接下来是reset为1的时候正是clk的下降沿。 黄框中这个时候在上升沿ar_enter为1,r_retire为0,而busy得到的是x。虽然busy在下一个cycle有值了,但这时候ar_enter和r_retire全为0了,所以busy为0。 这样busy就错过了开始这个本该为1的cycle。 不知道是什么原因。 如果不用dffr_s,用不带reset的dff_s。 结果则是没问题的。 再试下reset到clk上升沿后面一点。 还是不对,这时候怎么也不应该是x啊,首先reset的时候应该把dffr_s初始化成0,应该前面就不是x了。 原因找到了。 rst一直是x,结果发现resetn敲错了,应该是aresetn。 白废了这么久,还特意写个blog。 不过问题又来了,rst一直是x,为啥后面q又成0了?
-
gs132 ifcbus
这两天看gs132的代码,看到CPU_gs132/ls132r_interface.v 里面的ifc还没搞明白是什么,应该不是instruction fetch control。 因为从代码里可以看出来,有inst到ifc,也有data到ifc。 output idle_in_ifc_o; input [`Ltoifcbus-1:0] inst_ifc_i; output [`Lfromifcbus-1:0] ifc_inst_o; input [`Ltoifcbus-1:0] data_ifc_i; output [`Lfromifcbus-1:0] ifc_data_o; wire inst_ifc_valid = inst_ifc_i[ 0: 0]; wire [ 3:0] inst_ifc_width = inst_ifc_i[ 4: 1]; wire [ 3:0] inst_ifc_ben = inst_ifc_i[ 8: 5]; wire inst_ifc_wr = inst_ifc_i[ 9: 9]; wire [31:0] inst_ifc_addr...