题解主体

       要实现RAM,首先要声明数据的存储空间,例如:[3:0] rom [7:0];变量名称ram之前的[3:0]表示每个数据具有多少位,指位宽;变量名称ram之后的[7:0]表示需要多少个数据,指深度,注意这里深度为8,应该是使用[7:0],而不是[2:0];

       声明存储变量之后,需要对ram进行初始化,写入数据,当write_en有效,向write_addr写入write_data,当read_en有效,根据输入的read_addr输出read_data。需要注意的是,题目要求实现真双端口RAM,即可以同时写入和读出,所以需要使用两个always语句块实现写入和读出逻辑,不可以在同一个always块中使用if-else if-else if结果。以下为错误代码。

       reg [3:0] ram_data [7:0];

       always @(posedge clk or negedge rst_n)

              if (!rst_n)                                          //对RAM中的数据进行初始化

                     begin

                            ram_data[0] <= 4'd0;

                            ram_data[1] <= 4'd0;

                            ram_data[2] <= 4'd0;

                            ram_data[3] <= 4'd0;         

                            ram_data[4] <= 4'd0;

                            ram_data[5] <= 4'd0;

                            ram_data[6] <= 4'd0;

                            ram_data[7] <= 4'd0;

                     end

              else if(write_en)           //当write_en有效,向write_addr写入write_data

                     begin           

                            ram_data[write_addr] <= write_data;

                     end

              else if(read_en)            //当read_en有效,根据输入的read_addr输出read_data

                     begin           

                            read_data <= ram_data[read_addr];

                     end

按照以上代码,如果write_en和read_en同时有效,只有写操作会执行,而读操作被屏蔽。最好将读写其中一个分离到单独的always语句块。

       always @(posedge clk or negedge rst_n)

              if (!rst_n)

                     read_data <= 4’d0;

              else if (read_en)

                     begin           

                            read_data <= ram_data[read_addr];

                     end

              else

                     begin           

                            read_data <= 4’d0;

                     end

有一点值得注意:读写操作可以同时进行,当同一个时刻且读写地址相同时,读数据就会是写操作之前的数值,之后该地址的数值才改变为写数据。映射之后的电路图大致如下:(只展示RAM中的某一位)

在write_en和read_en同时有效时,read_data被赋予D除法的输出。而D触发器接收到来着write_data的输入,输出的数值尚未改变。

参考答案

`timescale 1ns/1ns
module ram_mod(
	input clk,
	input rst_n,
	
	input write_en,
	input [7:0]write_addr,
	input [3:0]write_data,
	
	input read_en,
	input [7:0]read_addr,
	output reg [3:0]read_data
);
	reg [3:0] ram_data [7:0];
	

	always @(posedge clk or negedge rst_n)
		if (!rst_n) 						//对RAM中的数据进行初始化
			begin
				ram_data[0] <= 4'd0;
				ram_data[1] <= 4'd0;
				ram_data[2] <= 4'd0;
				ram_data[3] <= 4'd0;
				ram_data[4] <= 4'd0;
				ram_data[5] <= 4'd0;
				ram_data[6] <= 4'd0;
				ram_data[7] <= 4'd0;
			end
		else if(write_en)		//当write_en有效,向write_addr写入write_data
			begin		
				ram_data[write_addr] <= write_data;
			end
		else 	
			begin		
				ram_data[0] <= ram_data[0];
				ram_data[1] <= ram_data[1];
				ram_data[2] <= ram_data[2];
				ram_data[3] <= ram_data[3];
				ram_data[4] <= ram_data[4];
				ram_data[5] <= ram_data[5];
				ram_data[6] <= ram_data[6];
				ram_data[7] <= ram_data[7];
			end
			
	always @(posedge clk or negedge rst_n)
		if (!rst_n)
			read_data <= 4'd0;
		else if (read_en)
			read_data <= ram_data[read_addr];
		else 
			read_data <= 4'd0;
endmodule