银杏科技有限公司旗下技术文档发布平台 | |||
技术支持电话 | 0379-69926675-801 | ||
技术支持邮件 | Gingko@vip.163.com | ||
版本 | 日期 | 作者 | 修改内容 |
---|---|---|---|
V1.0 | 2020-07-01 | gingko | 初次建立 |
1、 新建一个工程名为twodual_ram的工程。 2、 在工程目录栏选中工程,右键单击,点击New Source…。 3、 弹出界面的左侧栏选中IP(CORE Generator & Architecture Wizard)选项,并在右侧File name栏输入新建IP核的文件名,然后点击Next。 4、 弹出Select IP界面如下图所示,在Memories & Storage Elements 栏下找到RAM & ROM,点击前面的“+”展开,单击选中Block Memory Generator,然后点击Next 进入下一步。 5、 直接点击Finished。 6、 然后弹出RAM IP 核相关信息设置的界面,这里的Interface Type选项保持默认设置Native即可,然后点击Next,如下图所示: 7、 在Memory Type 栏选择RAM类型,本实验是双口RAM实验,所以这里选择True Dual Port RAM,然后点击Next。 8、 设置RAM的位宽为8,存储深度为1024,Port A Options和Port B Options参数勾选如下图红框中所示,然后点击Next。 9、 此界面保持默认选项,直接点击Next。 10、 此界面也是默认选项,点击Next。 11、 保持默认,点击Generate。可以在工程目录栏中看到spi_ram IP核文件已经添加完成。
//------------------------------------------------// //spi_ram //负责存储SPI通信的数据(具体的存储位置可通过spi命令寄存器设置) //双口RAM的缺点是与单口RAM相比,相同容量的RAM占用逻辑资源比较多。 //优点在于具有2个输入2个输出端口,两个端口都可用于输入输出,可实现同时读写 //数据从A端口写入,从B端口读出 spi_ram u0( .clka(wr_clk), .wea(wr_en), .ena(1'd1), .addra(address_a), .dina(receive_byte), .douta(a_dataout), .clkb(rd_clk), .web(1'd0), .enb(rd_en), .addrb(address_b), .dinb(8'd0), .doutb(data_out) );
case(rx_state) rx_idle_state:begin//空闲状态,匹配伪命令时钟 rx_state <= rx_judge_state; end rx_judge_state:begin//接收指令字节,判断指令含义分配跳转状态机状态 case(receive_byte) 8'h01:begin//存储指令编码(获取设备状态) order <= receive_byte; end 8'h02:begin//存储指令编码,跳转状态(写数据的长度信息) rx_state <= rx_wr_length_state; order <= receive_byte; end 8'h04:begin//存储指令编码,跳转状态(写数据的地址信息) rx_state <= rx_wr_add_state; order <= receive_byte; end 8'h05:begin//存储指令编码,跳转状态(读数据的长度信息) rx_state <= rx_rd_ledgth_state; order <= receive_byte; end 8'h07:begin//存储指令编码,跳转状态(读数据的地址信息) rx_state <= rx_rd_add_state; order <= receive_byte; end default:; endcase end rx_wr_length_state:begin//获取写数据长度信息,高字节在前,低字节在后 case(rx_cnt) 8'd0:begin wr_length_r[15:8] <= receive_byte; rx_cnt <= rx_cnt + 1'd1; end 8'd1:begin wr_length_r <= {wr_length_r[15:8],receive_byte}; end default:begin end endcase end rx_wr_add_state:begin//获取写数据地址,并产生RAM的写地址,高字节在前 case(rx_cnt) 8'd0:begin wr_address_r[15:8] <= receive_byte; rx_cnt <= rx_cnt + 1'd1; end 8'd1:begin wr_address_r <= {wr_address_r[15:8],receive_byte}; rx_cnt <= rx_cnt + 1'd1; wr_en_r <= 1'd1; end 8'd2:begin wr_address_r <= wr_address_r + 1'd1; if(wr_cnt==wr_length_r-1'd1) begin wr_cnt <= 12'h00; rx_cnt <= rx_cnt + 1'd1; end else begin wr_cnt <= wr_cnt + 1'd1; end end default:begin end endcase end rx_rd_ledgth_state:begin//获取读数据长度信息,高字节在前,低字节在后 case(rx_cnt) 8'd0:begin rd_length_r[15:8] <= receive_byte; rx_cnt <= rx_cnt + 1'd1; end 8'd1:begin rd_length_r <= {rd_length_r[15:8],receive_byte}; end default:begin end endcase end rx_rd_add_state:begin//获取读数据地址信息,并产生读地址信息,高字节在前 case(rx_cnt) 8'd0:begin rd_address_r[15:8] <= receive_byte; rx_cnt <= rx_cnt + 1'd1; end 8'd1:begin rd_address_r <= {rd_address_r[15:8],receive_byte}; rx_cnt <= rx_cnt + 1'd1; rd_en_r <= 1'd1; end 8'd2:begin rd_address_r <= rd_address_r + 1'd1; if(rd_cnt==rd_length_r-1'd1) begin rd_cnt <= 12'h00; rx_cnt <= rx_cnt + 1'd1; else begin rd_cnt <= rd_cnt + 1'd1; end end default:; endcase end endcase
1.通过逻辑分析仪观察RAM读写时序是否和参考时序一致。