해결된 질문
작성
·
57
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
안녕하세요, 답변 남겨드립니다 :)
tpsram
의 rd
출력이 zzzzzzz
rd
가 reg
타입임에도 불구하고 초기 상태에서 드라이브되지 않아서 high impedance(z) 상태가 유지되고 있습니다.
다만 시뮬레이션 상에서 포트가 연결되지 않았거나, 모듈의 인스턴스 연결이 누락되었을 가능성이 높습니다.
tb_tpsram.sv
파일에서 rd
를 확실하게 포트로 받고 있는지, 출력이 wire로 연결되어 있는지 확인
테스트벤치 상에서 re
신호가 posedge clk
시점에 정확하게 HIGH가 되었는지 확인
dpsram
의 rd_a
는 zzzzzzzz
, rd_b
는 0Z
인 이유:cs_a
가 LOW 상태에서 rd_a
에 아무런 값을 할당하지 않아 reg
타입인데도 드라이버가 없음
또는 cs_a
가 HIGH라도 we_a
도 HIGH이어서 write로만 동작 중
실제 메모리에 값이 write되지 않았거나, 해당 주소의 값이 0으로 초기화된 상태를 read하고 있음
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);
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 설정하여 강제로 입력값 고정 후 변화 추적
0
안녕하세요, 인프런 AI 인턴입니다. ghdrnek111님.
시뮬레이션 과정에서 발생한 TPSRAM과 DPSRAM의 read 데이터 오류와 관련된 문제로 고민 중이시군요. 사용하신 Waveform을 통해 문제를 진단하는 데 도움이 될 수 있는 몇 가지 주요 원인을 아래에 설명드립니다.
초기값 및 초기화 문제:
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
의 값이 적절히 할당되고 있는지 체크해야 합니다.ra
또는 ad_a/ad_b
의 값 변경 직후에 즉시 읽으려고 하면 문제가 발생할 수 있습니다. 이는 클럭 사이클의 지연 때문에 문제가 될 수 있습니다.관련 질문 URL을 확인해보시면 코드 구조와 시그널 핸들링에 대한 다른 유용한 설명들을 발견하실 수 있습니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.
피드백 감사합니다!