我这个程序是51(89c51)单片机通过fpga读写sram中fpga的接口模块的程序(verilog语言),问题是读写会出现错误,sram的时序我已注意检查了一次,仿真时序也是合理的,但是读写500个还是有70个左右的错误,所以希望大家帮忙看看。 硬件方面:共两块板子,系统板,fpga板(有sram_is61lc12816)之间的数据总线是直接相连的,读写,片选是分别通过一个电阻连接的(阻值记不清了,不知到会有影响么)。 软件思路:单片机给fpga四个数据,前两个是地址,后面的为要存储的数据或是读出的数据。这算一个过程。 //读写fpga内部ram模块,将51数据转换成对应的地址与存储数据模块,并将从sram来的数据送回51 //输入 en_sram_ns,使能信号mcu_wr_ns,mcu_rd_ns 51的读写信号,mcu_data 51的数据线
//输出 en_consram2_ns ,sram_addr,sram_data,sram_wr_ns,sram_rd_ns
//注意sram的读时序!!!!!!
module com_sram2(sys_clk,en_sram_ns,mcu_wr_ns,mcu_rd_ns,mcu_data, en_consram2_ns,sram_addr,sram_data,sram_wr_ns,sram_rd_ns,sram_ub_ns,sram_lb_ns,wr_rd_nums); input sys_clk,en_sram_ns,mcu_wr_ns,mcu_rd_ns; inout[7:0] mcu_data;
output en_consram2_ns,sram_wr_ns,sram_rd_ns,sram_ub_ns,sram_lb_ns;//sram的读写信号,和片选信号 output[3:0] wr_rd_nums; //状态机方便调试 output[16:0] sram_addr; //sram 的地址线
inout[15:0] sram_data;
reg[15:0] sram_data_out; reg en_consram2_ns,sram_wr_ns,sram_rd_ns,sram_ub_ns,sram_lb_ns; reg[16:0] sram_addr;
//中间变量 reg wr_rd,wr_rd_over; reg[3:0] wr_rd_nums; reg[7:0] mcu_data_temp,mcu_data_temp_m,mcu_data_temp_l; reg[7:0] sram_addr_temp_m,sram_data_temp_m; reg[15:0] sram_data_temp;
parameter one=4'b0001,two=4'b0010,three=4'b0100,four=4'b1000;
assign mcu_data=(!en_sram_ns&!mcu_rd_ns)?mcu_data_temp:8'bz; assign sram_data=(!sram_wr_ns)?sram_data_temp:16'bz;
always @(negedge en_sram_ns) begin case(wr_rd_nums) one:begin wr_rd_nums<=two; end two:begin wr_rd_nums<=three; end three:begin wr_rd_nums<=four; end default:begin wr_rd_nums<=one; end endcase end
always @(posedge sys_clk) begin if(en_sram_ns) begin wr_rd<=1; //允许读写数据 en_consram2_ns<=0; //使能sram sram_ub_ns<=0; sram_lb_ns<=0; //sram以字操作 sram_wr_ns<=1; //关闭写 sram_rd_ns<=1; //关闭读 if(wr_rd_over) begin //读写过程结束 sram_addr<=11'bz; wr_rd_over<=0; end end else begin sram_rd_ns<=0; //使能sram的读 sram_wr_ns<=1; mcu_data_temp_m<=sram_data[15:8]; mcu_data_temp_l<=sram_data[7:0]; if((mcu_wr_ns^mcu_rd_ns)&wr_rd) begin case(wr_rd_nums) default:begin sram_addr_temp_m<=mcu_data; wr_rd<=0; //每次只读写一次,wr_rd作为标志记录是否读写过 end two:begin sram_addr<={1'b0,sram_addr_temp_m,mcu_data}; wr_rd<=0; end three:begin if(!mcu_rd_ns) mcu_data_temp<=mcu_data_temp_m; else sram_data_temp_m<=mcu_data; //记录高位数据 wr_rd<=0; end four:begin if(!mcu_rd_ns) mcu_data_temp<=mcu_data_temp_l; else begin sram_data_temp<={sram_data_temp_m,mcu_data}; sram_wr_ns<=0; //使能sram的写 end wr_rd<=0; wr_rd_over<=1; end endcase end end end
endmodule |