伪双端口ram:写端口:clk_w,en_A,we_A,addr_A,din_A;读端口:clk_r,en_B,addr_B;dout_B.
设计读写模块,写入256个数据,再读出256个数据。
输入时钟100Mhz,输出时钟50Mhz。
多bit数据,高速时钟域到低速时钟域处理。
模块框图:
代码:
module ram_real_wr(input wire clk_w ,input wire clk_r ,input wire sys_rst_n ,output reg en_A ,output reg we_A ,output wire [7:0] addr_A ,output wire [7:0] din_A ,output reg en_B ,output wire [7:0] addr_B
);// parameterparameter WR_NUM = 256 ,RD_NUM = 256 ;reg [7:0] cnt_w ; // 用来产生写地�?与写数据�?reg flag_wr ;reg done ;reg [7:0] cnt_r ;always @(posedge clk_w or negedge sys_rst_n) beginif(~sys_rst_n) cnt_w <= 8'd0 ;else if(en_A && we_A && (cnt_w == WR_NUM - 1))cnt_w <= 8'd0 ;else if(en_A && we_A)cnt_w <= cnt_w + 1'b1 ;else cnt_w <= cnt_w;endalways @(posedge clk_w or negedge sys_rst_n) beginif(~sys_rst_n) flag_wr <= 1'b1 ;else if(cnt_w == WR_NUM - 2)flag_wr <= 1'b0 ;else flag_wr <= flag_wr ;endalways @(posedge clk_w or negedge sys_rst_n) beginif(~sys_rst_n) en_A <= 1'b0 ; else en_A <= 1'b1 ;endalways @(posedge clk_w or negedge sys_rst_n) beginif(~sys_rst_n) we_A <= 1'b0 ; else we_A <= flag_wr ;endassign addr_A = (we_A) ? cnt_w : 8'd0 ;assign din_A = (we_A) ? cnt_w : 8'd0 ;always @(posedge clk_r or negedge sys_rst_n) beginif(~sys_rst_n)done <= 1'b0 ;else if(en_B && (cnt_r == RD_NUM - 2))done <= 1'b1 ;else done <= done ; endalways @(posedge clk_r or negedge sys_rst_n) beginif(~sys_rst_n) en_B <= 1'b0 ;else if(~done) beginif(~flag_wr)en_B <= 1'b1 ;else en_B <= 1'b0 ;endelseen_B <= 1'b0 ;endalways @(posedge clk_r or negedge sys_rst_n) beginif(~sys_rst_n)cnt_r <= 8'd0 ;else if(en_B && (cnt_r == RD_NUM - 1))cnt_r <= 8'd0 ;else if(en_B)cnt_r <= cnt_r + 1'b1 ;elsecnt_r <= 8'd0 ;endassign addr_B = (en_B) ? cnt_r : 8'd0 ;endmodule
module top(input wire sys_clk ,input wire sys_rst_n ,output wire [7:0] data_out
);// 例化间连�?wire clk_100Mhz ;wire clk_50Mhz ;wire locked ;wire rst_n ;wire en_A ;wire we_A ;wire [7:0] addr_A ;wire [7:0] din_A ;wire en_B ;wire [7:0] addr_B ;
pll_clk pll_clk_inst(.resetn ( sys_rst_n ) ,.clk_in1 ( sys_clk ) ,.clk_out1 ( clk_100Mhz ) ,.clk_out2 ( clk_50Mhz ) ,.locked ( locked ) );assign rst_n = sys_rst_n && locked ;ram_real_wr ram_real_wr_inst(.clk_w ( clk_100Mhz ) ,.clk_r ( clk_50Mhz ) ,.sys_rst_n ( rst_n ) ,.en_A ( en_A ) ,.we_A ( we_A ) ,.addr_A ( addr_A ) ,.din_A ( din_A ) ,.en_B ( en_B ) ,.addr_B ( addr_B )
); blk_mem_gen_0 blk_mem_gen_0_inst(.clka ( clk_100Mhz ) , .ena ( en_A ) , .wea ( we_A ) , .addra ( addr_A ) , .dina ( din_A ) , .clkb ( clk_50Mhz ) , .enb ( en_B ) , .addrb ( addr_B ) , .doutb ( data_out )
);endmodule
改进一下,使得只读出偶数地址内的数据:
module ram_real_wr(input wire clk_w ,input wire clk_r ,input wire sys_rst_n ,output reg en_A ,output reg we_A ,output wire [7:0] addr_A ,output wire [7:0] din_A ,output reg en_B ,output wire [7:0] addr_B
);// parameterparameter WR_NUM = 256 ,RD_NUM = 256 ;reg [7:0] cnt_w ; // 用来产生写地�?与写数据�?reg flag_wr ;
// reg done ;reg [7:0] cnt_r ;always @(posedge clk_w or negedge sys_rst_n) beginif(~sys_rst_n) cnt_w <= 8'd0 ;else if(en_A && we_A && (cnt_w == WR_NUM - 1))cnt_w <= 8'd0 ;else if(en_A && we_A)cnt_w <= cnt_w + 1'b1 ;else cnt_w <= cnt_w;endalways @(posedge clk_w or negedge sys_rst_n) beginif(~sys_rst_n) flag_wr <= 1'b1 ;else if(cnt_w == WR_NUM - 2)flag_wr <= 1'b0 ;else flag_wr <= flag_wr ;endalways @(posedge clk_w or negedge sys_rst_n) beginif(~sys_rst_n) en_A <= 1'b0 ; else en_A <= 1'b1 ;endalways @(posedge clk_w or negedge sys_rst_n) beginif(~sys_rst_n) we_A <= 1'b0 ; else if(cnt_w == WR_NUM - 2)we_A <= 1'b0 ;else we_A <= flag_wr ;endassign addr_A = (we_A) ? cnt_w : 8'd0 ;assign din_A = (we_A) ? cnt_w : 8'd0 ;// always @(posedge clk_r or negedge sys_rst_n) begin// if(~sys_rst_n)// done <= 1'b0 ;// else if(en_B && (cnt_r == RD_NUM - 2))// done <= 1'b1 ;// else // done <= done ; // end// always @(posedge clk_r or negedge sys_rst_n) begin// if(~sys_rst_n) // en_B <= 1'b0 ;// else if(~done) begin// if(~flag_wr)// en_B <= 1'b1 ;// else // en_B <= 1'b0 ;// end// else// en_B <= 1'b0 ;// end// always @(posedge clk_r or negedge sys_rst_n) begin//只读出偶数地址的数据。// if(~sys_rst_n) // en_B <= 1'b0 ;// else if(~flag_wr) begin// if(cnt_r[0]) // 奇数赋值1,读使能有效,偶数读使能无效。// en_B <= 1'b1 ;// else // en_B <= 1'b0 ;// end// else // en_B <= 1'b0 ;// endalways @(posedge clk_r or negedge sys_rst_n) begin//只读出偶数地址的数据。if(~sys_rst_n) en_B <= 1'b0 ;else if(~flag_wr && (cnt_r[0])) en_B <= 1'b1 ;else en_B <= 1'b0 ;endalways @(posedge clk_r or negedge sys_rst_n) beginif(~sys_rst_n)cnt_r <= 8'd0 ;else if(~flag_wr && (cnt_r == RD_NUM - 1))cnt_r <= 8'd0 ;else if(~flag_wr)cnt_r <= cnt_r + 1'b1 ;elsecnt_r <= 8'd0 ;endassign addr_B = (en_B) ? cnt_r : 8'd0 ;endmodule
仿真图: