关于利用verilog 编写ssram的读写时序时遇到的问题
2014-09-16 21:30
281 查看
此次使用的 ssram型号为 CY7C1462AV33
ssram的读和写都在两个时钟周期内完成,即写时钟周期内,第一个clk上升沿时采集 addr ,w_n等有效信号,第三个clk上升沿时将要写的数据采样进去。
ssram主要用在存储ccd的图像,40MHz的速度。
一开始采用的想法是状态机来实现一个读和写的周期,及完成一个读和写需要两个时钟周期。按照这个想法写了一下verilog代码。
后来发现这个速度跟不上,而其对于官方给的ssram的读写时序就是一个流水线的操作。这样可以利用每个时钟周期。给出verilog代码:
这里将数据延迟两个时钟周期来完成对ssram对读写时序的要求,这里为了提高效率,我采用了时钟下降沿完成外部数据以及控制信号的采样,上升沿为ssram的数据采样。
下图为modelsim的功能仿真:
为检测实际的读写功能我写了一个测试模块:
采用一个循环计数,完成两次写,一次读。
下图为用signaltap的逻辑分析的实测结果。为了有对比性,第一张图将ssram的clk断了,第二张图为正常。可以观察在ssram_we_n分别为高电平和低电平时ssram_data的读数情况。
1.
2.
ssram的读和写都在两个时钟周期内完成,即写时钟周期内,第一个clk上升沿时采集 addr ,w_n等有效信号,第三个clk上升沿时将要写的数据采样进去。
ssram主要用在存储ccd的图像,40MHz的速度。
一开始采用的想法是状态机来实现一个读和写的周期,及完成一个读和写需要两个时钟周期。按照这个想法写了一下verilog代码。
后来发现这个速度跟不上,而其对于官方给的ssram的读写时序就是一个流水线的操作。这样可以利用每个时钟周期。给出verilog代码:
module line_ssram( clk, addr, w_data, r_data, cs_n, w_n, r_n, ssram_clk, ssram_data, ssram_addr, ssram_be_n, ssram_ce1_n, ssram_ce2, ssram_ce3_n, ssram_we_n, ssram_oe_n, ssram_cen_n, ssram_adv_ld_n, ssram_mode, ssram_zz ); input clk; input [20:0] addr; input [15:0] w_data; output [15:0] r_data; input cs_n; input w_n; input r_n; output ssram_clk; inout [15:0] ssram_data; output [20:0] ssram_addr; output [1:0] ssram_be_n; output ssram_ce1_n; output ssram_ce2; output ssram_ce3_n; output ssram_we_n; output ssram_oe_n; output ssram_cen_n; output ssram_adv_ld_n; output ssram_mode; output ssram_zz; reg ce3_n_temp; reg we_n_temp; reg oe_n_temp; reg [1:0] be_n_temp; reg read_bus_d1; reg read_bus_d2; reg read_bus; reg write_bus_d1; reg write_bus_d2; reg write_bus; reg [15:0] write_data_d1; reg [15:0] write_data_d2; reg [15:0] write_data; assign ssram_cen_n = 1'b0; assign ssram_adv_ld_n = 1'b0; assign ssram_mode = 1'b0; assign ssram_ce1_n = 1'b0; assign ssram_ce2 = 1'b1; assign ssram_zz = 1'b0; assign ssram_clk = clk; assign ssram_addr =(!cs_n) ? addr : 21'bz; assign ssram_data =(write_bus_d2) ? write_data_d2 : 16'bz; assign r_data =(read_bus_d2) ? ssram_data : 16'bz; assign ssram_ce3_n = ce3_n_temp; assign ssram_we_n = we_n_temp; assign ssram_oe_n = oe_n_temp; assign ssram_be_n = be_n_temp; always@(negedge clk) begin if(cs_n) begin ce3_n_temp <= 1'b1; we_n_temp <= 1'bz; oe_n_temp <= 1'bz; be_n_temp <= 2'b11; read_bus<=1'b0; write_bus<=1'b0; end else if((w_n)&&(!r_n)) //read begin ce3_n_temp <= 1'b0; we_n_temp <= 1'b1; oe_n_temp <= 1'b0; read_bus <= 1'b1; write_bus <= 1'b0; end else if((!w_n)&&(r_n)) //write begin ce3_n_temp <= 1'b0; we_n_temp <= 1'b0; oe_n_temp <= 1'b1; be_n_temp <= 2'd0; write_bus <= 1'b1; read_bus <= 1'b0; write_data <= w_data; end end always@(negedge clk) begin if(cs_n) begin read_bus_d1<=1'b0; read_bus_d2<=1'b0; end else begin read_bus_d1<=read_bus; read_bus_d2<=read_bus_d1; end end always@(negedge clk) begin if(cs_n) begin write_bus_d1<=1'b0; write_bus_d2<=1'b0; end else begin write_bus_d1<=write_bus; write_bus_d2<=write_bus_d1; end end always@(negedge clk) begin write_data_d1<=write_data; write_data_d2<=write_data_d1; end endmodule
这里将数据延迟两个时钟周期来完成对ssram对读写时序的要求,这里为了提高效率,我采用了时钟下降沿完成外部数据以及控制信号的采样,上升沿为ssram的数据采样。
下图为modelsim的功能仿真:
为检测实际的读写功能我写了一个测试模块:
module rw_test( rest_n, clkin, clk, addr, cs_n, w_n, r_n, w_data, r_data, seg, cnt_out ); input clkin; input rest_n; output [20:0] addr; output [15:0] w_data; input [15:0] r_data; output [13:0] seg; output cs_n; output w_n; output r_n; output clk; output [7:0] cnt_out; reg [20:0] addr_temp; reg [13:0] seg_temp; reg cs_n_temp; reg w_n_temp; reg r_n_temp; reg [15:0] w_data_temp; reg [20:0] cnt; initial cnt = 0; reg r_data_en; initial r_data_en=0; assign addr = addr_temp; assign w_data = w_data_temp; assign cs_n = cs_n_temp; assign w_n = w_n_temp; assign r_n = r_n_temp; assign clk = clkin; assign cnt_out =cnt; always@(posedge clkin) begin if(cnt == 21'd40) cnt <= 21'd0; else cnt <= cnt + 1'b1; end always@(posedge clkin) begin if(cnt==21'd20) //read begin cs_n_temp <= 1'b0; w_n_temp <= 1'b1; r_n_temp <= 1'b0; addr_temp <= 21'd1; end else if(cnt == 21'd 30) begin cs_n_temp <= 1'b1; w_n_temp <= 1'b1; r_n_temp <= 1'b1; end else if(cnt==21'd1) //w begin cs_n_temp <= 1'b0; w_n_temp <= 1'b0; r_n_temp <= 1'b1; addr_temp <= 21'd1; w_data_temp <= 16'd1; end else if(cnt==21'd3) //w begin cs_n_temp <= 1'b0; w_n_temp <= 1'b0; r_n_temp <= 1'b1; addr_temp <= 21'd2; w_data_temp <= 16'd2; end else if(cnt == 21'd8) begin cs_n_temp <= 1'b1; w_n_temp <= 1'b1; r_n_temp <= 1'b1; end end always@(clkin) begin if(r_data == 16'd2) r_data_en <= 1'b1; else r_data_en <= 1'b0; end assign seg =(r_data_en==1'b1) ? 14'd2 :14'd1; //assign seg = 14'd6; endmodule
采用一个循环计数,完成两次写,一次读。
下图为用signaltap的逻辑分析的实测结果。为了有对比性,第一张图将ssram的clk断了,第二张图为正常。可以观察在ssram_we_n分别为高电平和低电平时ssram_data的读数情况。
1.
2.
相关文章推荐
- 关于Xcode提高读写速度遇到的问题和一些想法
- 关于编写android程序遇到的问题
- iOS实战演练之关于数据交互的问题(利用XAMPP搭建本地服务器, 编写PHP代码实现iOS端注册登录功能)
- 关于用eclipse通过绑定外部安装的tomcat和myeclipse自带tomcat编写servlet遇到的问题
- 关于直接编写应用程序读写/dev/mtd0 或者 /dev/mtdblock0的问题。
- 关于利用libsvm分类时遇到的问题
- 关于Resin在Eclipse或者Myeclipse上利用Debug模式部署的方法以及遇到的一些问题
- 关于利用juqery eq()和remove()动态删除表格中的行时遇到的问题
- 关于程序编写中遇到的细节问题
- Tip:编写jFrame时关于控件实例化遇到的问题
- 关于Win2K3中利用ASP上传文件的问题!
- 关于工作流项目移植到Oracle9i布署时遇到的问题!
- 关于msflexgrid控件的开发时所遇到的问题
- 用hibernate编写程序遇到的问题及解决方法
- 关于在VS2005中建立Login.aspx页面所遇到的问题
- 关于安全的ActiveX控件的编写,纠正大家一点错误,包括MSDN上也有问题
- 关于ASP.NET2.0编写扩展存储过程的问题
- 最近要做个项目,遇到一些关于ansys问题,看看兄弟们能否帮我解决?
- 请问关于在开发BS系统中,遇到了上传服务器数据的问题
- 由一个朋友遇到的问题想到的关于程序的架构