-
替换chiplab里的axi-sram-bridge
前两天自己搞了个最简单的axi-sram-bridge,只支持单次的读写,准备替换chiplab里的IP/AXI_SRAM_BRIDGE/soc_axi_sram_bridge.v chiplab代码里默认定义的是AXI64,也就是数据是64位宽,地址宽都是还是32。 试了下把数据宽改为32,出错了,这个错也可能是因为之前把TLB拿掉,改了不少地方,现在不好确定了。 所以还是用64的。 把自己的axi_sram_bridge替换上去,结果取指没取到。 结果发现是数据在下降沿到了,比rvalid晚了半个cycle。 可能是verilator里testbench模拟的时候搞错了?先试试把chiplab里的模拟delay的AXI_DELAY_RAND去掉。 这个模拟读内存delay的模块之前也没搞清楚怎么用,每次delay没变化。 奇怪的事。 soc_axi_sram_bridge.v文件如果在IP/AXI_SRAM_BRIDGE/目录下,虽然在makefile里看,是会被编译,但并没有用到。 可这个文件在的话,不但编译了,还加到工程里了。比如随便一搜,有好多。 ../run_func/obj_dir/Vsimu_top___024root__39.cpp: vlSelf->soc_axi_sram_bridge__DOT__ram_r_a_data_push ../run_func/obj_dir/Vsimu_top___024root__39.cpp: = ((IData)(vlSelf->soc_axi_sram_bridge__DOT__ram_r_a_push) ../run_func/obj_dir/Vsimu_top___024root__39.cpp: & ((IData)(vlSelf->soc_axi_sram_bridge__DOT__ram_r_a_pop) ../run_func/obj_dir/Vsimu_top___024root__39.cpp: | (~ (IData)(vlSelf->soc_axi_sram_bridge__DOT__ram_r_a_valid)))); ../run_func/obj_dir/Vsimu_top___024root__39.cpp: vlSelf->soc_axi_sram_bridge__DOT__ram_r_a_queue_push ../run_func/obj_dir/Vsimu_top___024root__39.cpp: = ((((IData)(vlSelf->soc_axi_sram_bridge__DOT__ram_r_a_push) ../run_func/obj_dir/Vsimu_top___024root__39.cpp: & (IData)(vlSelf->soc_axi_sram_bridge__DOT__ram_r_a_valid)) ../run_func/obj_dir/Vsimu_top___024root__39.cpp: & (~ (IData)(vlSelf->soc_axi_sram_bridge__DOT__ram_r_a_pop))) ../run_func/obj_dir/Vsimu_top___024root__39.cpp: & (~ (IData)(vlSelf->soc_axi_sram_bridge__DOT__ram_r_a_queue_valid))); ../run_func/obj_dir/Vsimu_top___024root__39.cpp: vlSelf->soc_axi_sram_bridge__DOT__ram_w_a_queue_pop ../run_func/obj_dir/Vsimu_top___024root__39.cpp: = ((IData)(vlSelf->soc_axi_sram_bridge__DOT__ram_w_a_pop) ../run_func/obj_dir/Vsimu_top___024root__39.cpp: & (IData)(vlSelf->soc_axi_sram_bridge__DOT__ram_w_a_queue_valid)); ../run_func/obj_dir/Vsimu_top___024root__39.cpp: vlSelf->soc_axi_sram_bridge__DOT__ram_w_a_data_push ../run_func/obj_dir/Vsimu_top___024root__39.cpp:...
-
经常用的信号开关的两个问题,1.dff得加上reset 2.结束信号来得太早,比开始信号还早
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), 107 .q (rdata_valid), 108 .se(), .si(), .so()); 这里有个问题,如果ar_enter如果不为1,或者m_rready没有为1过,这时候rdata_valid是x。 所以这段代码在刚reset以后,rdata_valid可能会有一段x的时候。 所以这个dff得用带reset的。 100 wire rdata_valid_next; 101 102 assign rdata_valid_next = (rdata_valid | ar_enter) & (~m_rready); 103 104...
-
试下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),...