이번에는 베릴로그로 간단한 RAM을 설계해보도록 하겠습니다.
FPGA 등에서 사용할 수 있는 Single Port RAM의 가장 기본적인 형태를 구현해보려고 합니다.
우선 기본적인 입력은 posedge에서 동작하는 clk 신호, addr(주소값), 쓰기 데이터인 8bit wdata 마지막으로 쓰기 제어 신호인 wr이 있습니다. 출력은 현재 addr 위치에 있는 데이터인 읽기 데이터 rdata 입니다.
// ram
`timescale 1ns / 1ps
module ram (
input clk,
input [7:0] addr,
input [7:0] wdata,
input wr,
output [7:0] rdata
);
reg [7:0] mem[0:255];
assign rdata = mem[addr];
always @(posedge clk) begin
if (wr) begin
mem[addr] <= wdata;
end
end
endmodule
메모리는 8bit의 메모리 셀이 256개 선언되어 있습니다. 다시 말해서 주소는 0~255까지 지정이 가능하고, 각 주소에 8bit 데이터를 저장할 수 있습니다.
reg [7:0] mem[0:255];
위 코드는 현재 주소 addr에 해당하는 메모리 값을 실시간으로 rdata에 출력합니다. 별도의 클럭 동기화 없이 주소 입력이 바뀌면 즉시 출력이 반영되므로 조합 논리 방식입니다.
always @(posedge clk) begin
if (wr) begin
mem[addr] <= wdata;
end
end
클럭의 상승 엣지에서 쓰기 동작이 이루어집니다. wr 신호가 1일 때, 현재 주소 addr에 wdata 값을 저장합니다.
Schematic를 확인하면 위와 같이 나오게 됩니다.
다음은 읽기와 쓰기 모두 동기식 방식으로 동작하는 RAM을 Verilog로 구현하려고 합니다. 이전에 봤던 조합 논리 기반 읽기 방식과는 다른 순차 논리 기반의 읽기 방식으로 설계하였습니다. 코드를 확인하면 아래와 같습니다.
`timescale 1ns / 1ps
module ram (
input clk,
input [7:0] addr,
input [7:0] wdata,
input wr,
output reg [7:0] rdata
);
reg [7:0] mem[0:255];
always @(posedge clk) begin
if (wr) begin
mem[addr] <= wdata;
end else begin
rdata <= mem[addr];
end
end
endmodule
클럭의 상승 엣지에서 메모리 동작을 수행합니다. wr
이 1이면 쓰기 모드로 현재 주소에 데이터를 저장합니다. wr
이 0이면 읽기 모드로 주소의 데이터를 rdata
로 출력합니다.
회로의 Schematic을 확인해보면 아래와 같이 나오게됩니다.