인프런 커뮤니티 질문&답변
과제3 시뮬레이션 관련 질문
해결된 질문
작성
·
78
0
안녕하세요 삼코치님!
과제 3 하다가 계속 시뮬레이션 부분에서 tpsram 과 dpsram의 read data부분에서 오류가 생겨서 질문 드립니다.
두 소자 모두 Netlist viewer는 정상적으로 나오는 것을 확인하였고, 삼코치님이 올려주신 tb_tpsram.sv 파일을 이용하여 시뮬레이션을 진행하였는데 계속 문제가 생겨서 어디서 잘못된건지 감이 잡히지 않아 질문드립니다!
module tpsram #(
parameter DEPTH= 8,
parameter WIDTH =32,
parameter DEPTH_LOG = $clog2(DEPTH)
) (
input clk,
input [WIDTH-1:0] wd,
input [DEPTH_LOG -1:0] ra,
input [DEPTH_LOG -1:0] wa,
input we,
input re,
output reg [WIDTH-1:0] rd
);
reg [WIDTH-1:0] mem[DEPTH-1:0];
initial begin
for (int i=0;i<DEPTH;i++)
mem[i] = 0;
end
always @(posedge clk)
if (we)
mem[wa] <= wd;
always @(posedge clk)
if (re)
rd <= mem[ra];
endmodule
module dpsram #(
parameter DEPTH = 8,
parameter WIDTH = 32,
parameter DEPTH_LOG =$clog2(DEPTH)
)(
input clk,
input we_a,
input we_b,
input [WIDTH-1:0] wd_a,
input [WIDTH-1:0] wd_b,
input cs_a,
input cs_b,
input [DEPTH_LOG-1:0] ad_a,
input [DEPTH_LOG-1:0] ad_b,
output reg [WIDTH-1:0] rd_a,
output reg [WIDTH-1:0] rd_b
);
reg [WIDTH-1:0] mem[DEPTH-1:0];
initial begin
for (int i=0; i<DEPTH; i++)
mem[i] =0;
end
always @(posedge clk)
if(cs_a & we_a)
mem[ad_a] <= wd_a;
else if (cs_a)
rd_a <= mem[ad_a];
always @(posedge clk)
if(cs_b & we_b)
mem[ad_b] <= wd_b;
else if (cs_b)
rd_b <= mem[ad_b];
endmodule

혹시 어디서 제가 실수를 한 걸 까요??
답변 2
1
안녕하세요, 답변 남겨드립니다 :)
✅ 문제 1. tpsram의 rd 출력이 zzzzzzz
원인:
rd가 reg 타입임에도 불구하고 초기 상태에서 드라이브되지 않아서 high impedance(z) 상태가 유지되고 있습니다.
다만 시뮬레이션 상에서 포트가 연결되지 않았거나, 모듈의 인스턴스 연결이 누락되었을 가능성이 높습니다.
확인할 사항:
tb_tpsram.sv파일에서rd를 확실하게 포트로 받고 있는지, 출력이 wire로 연결되어 있는지 확인테스트벤치 상에서
re신호가posedge clk시점에 정확하게 HIGH가 되었는지 확인
✅ 문제 2. dpsram의 rd_a는 zzzzzzzz, rd_b는 0
rd_a가 Z인 이유:
cs_a가 LOW 상태에서rd_a에 아무런 값을 할당하지 않아reg타입인데도 드라이버가 없음또는
cs_a가 HIGH라도we_a도 HIGH이어서 write로만 동작 중
rd_b가 0인 이유:
실제 메모리에 값이 write되지 않았거나, 해당 주소의 값이 0으로 초기화된 상태를 read하고 있음
🛠 해결 방법 요약
1. tpsram 테스트벤치에서 re와 ra의 타이밍 확인
@(posedge clk);
we = 1; wa = 7; wd = 32'h17;
@(posedge clk);
we = 0; re = 1; ra = 7;
@(posedge clk); // 이 클럭에서 read 발생
$display("Read value = %h", rd);
2. dpsram의 read 조건 개선
현재 코드:
always @(posedge clk)
if(cs_a & we_a)
mem[ad_a] <= wd_a;
else if (cs_a)
rd_a <= mem[ad_a];
이 구조는 cs_a & we_a일 때만 write하고, cs_a일 때만 read합니다.
⚠ 문제점:
cs_a가 LOW이면 아무 동작도 하지 않음 ⇒rd_a는 마지막 값 유지 (초기에는Z)cs_a가 HIGH이고we_a도 HIGH이면 write만 발생 ⇒ read 안됨
💡 수정 예시:
always @(posedge clk) begin
if (cs_a) begin
if (we_a)
mem[ad_a] <= wd_a;
else
rd_a <= mem[ad_a];
end
end
혹은 더 깔끔하게 default 값을 넣어 초기화 방지:
always @(posedge clk) begin
rd_a <= 0;
if (cs_a && !we_a)
rd_a <= mem[ad_a];
end
🔎 권장 디버깅 팁
각
posedge clk시점마다 다음 로그 찍기:
$display("[%t] clk=%b, we=%b, re=%b, wa=%0d, ra=%0d, wd=%h, rd=%h", $time, clk, we, re, wa, ra, wd, rd);
초기화 이후 첫
write/read가 몇 번째 clk에서 일어나는지 추적의심되는 부분 시그널에 breakpoint 설정하여 강제로 입력값 고정 후 변화 추적
위 내용 한 번 따라가면서 testbench도 따져보시면 좋을 것 같습니다.
0
안녕하세요, 인프런 AI 인턴입니다. ghdrnek111님.
시뮬레이션 과정에서 발생한 TPSRAM과 DPSRAM의 read 데이터 오류와 관련된 문제로 고민 중이시군요. 사용하신 Waveform을 통해 문제를 진단하는 데 도움이 될 수 있는 몇 가지 주요 원인을 아래에 설명드립니다.
TPSRAM 및 DPSRAM 모듈 검토:
초기값 및 초기화 문제:
- 메모리(
mem[i])는 초기화로 모든 값을 0으로 설정하셨습니다. 그러나 시뮬레이션 초반에 read(addr)하는 것을 시도하면 초기에는 유효하지 않은 데이터(zzzzzzzZ와 같은 high-impedance 상태)가 관찰될 수 있습니다. 초기화 이후 메모리 읽기가 제대로 이루어지는지 확인하세요.
- 메모리(
신호 타이밍 및 깔끔한 제어:
always블록은posedge clk조건에 정의되어 있지만,re(TPSRAM의 경우) 및cs_a,cs_b(DPSRAM의 경우)가 확실히 의도한 시점에 활성화되고 있는지 확인이 필요합니다.
테스트 벤치(tb_tpsram.sv) 확인:
- 시뮬레이션 파형 이미지를 제공하셨는데, 제공된 테스터 벤치에
혹시 이상이 없는지도 확인해 보세요. 특히 읽기 클럭 주기에ra,ad_a,ad_b의 값이 적절히 할당되고 있는지 체크해야 합니다.
- 읽음과 기록 사이의 시간 간격을 충분히 유지해야 합니다.
- 시뮬레이션 파형 이미지를 제공하셨는데, 제공된 테스터 벤치에
네트리스 및 구성 확인:
- Netlist viewer에서는 정상적으로 보인다고 하셨으니, 그럼에도 불구하고 비정상적인 상태가 발생한다면 트리거 및 논리적 흐름에 문제 있는지 의심해야 합니다.
- 시뮬레이션에서는
ra또는ad_a/ad_b의 값 변경 직후에 즉시 읽으려고 하면 문제가 발생할 수 있습니다. 이는 클럭 사이클의 지연 때문에 문제가 될 수 있습니다.
관련 질문 URL을 확인해보시면 코드 구조와 시그널 핸들링에 대한 다른 유용한 설명들을 발견하실 수 있습니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.






피드백 감사합니다!