Inflearn brand logo image

인프런 커뮤니티 질문&답변

ghdrnek111님의 프로필 이미지
ghdrnek111

작성한 질문수

디지털 회로설계 실무 : Computer Architecture 와 SoC 프로토콜 Digital IP 설계하기

[과제2] Port를 확장하여 High-speed를 위한 Dual-port + Two-port RAM 설계하기

과제3 시뮬레이션 관련 질문

해결된 질문

작성

·

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


	
111111111.png.webp

혹시 어디서 제가 실수를 한 걸 까요??

답변 2

1

안녕하세요, 답변 남겨드립니다 :)


문제 1. tpsramrd 출력이 zzzzzzz

원인:

rdreg 타입임에도 불구하고 초기 상태에서 드라이브되지 않아서 high impedance(z) 상태가 유지되고 있습니다.
다만 시뮬레이션 상에서 포트가 연결되지 않았거나, 모듈의 인스턴스 연결이 누락되었을 가능성이 높습니다.

확인할 사항:

  • tb_tpsram.sv 파일에서 rd확실하게 포트로 받고 있는지, 출력이 wire로 연결되어 있는지 확인

  • 테스트벤치 상에서 re 신호가 posedge clk 시점에 정확하게 HIGH가 되었는지 확인


문제 2. dpsramrd_azzzzzzzz, 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

🔎 권장 디버깅 팁

  1. 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);
  1. 초기화 이후 첫 write/read몇 번째 clk에서 일어나는지 추적

  2. 의심되는 부분 시그널에 breakpoint 설정하여 강제로 입력값 고정 후 변화 추적


위 내용 한 번 따라가면서 testbench도 따져보시면 좋을 것 같습니다.

ghdrnek111님의 프로필 이미지
ghdrnek111
질문자

피드백 감사합니다!

0

안녕하세요, 인프런 AI 인턴입니다. ghdrnek111님.

시뮬레이션 과정에서 발생한 TPSRAM과 DPSRAM의 read 데이터 오류와 관련된 문제로 고민 중이시군요. 사용하신 Waveform을 통해 문제를 진단하는 데 도움이 될 수 있는 몇 가지 주요 원인을 아래에 설명드립니다.

TPSRAM 및 DPSRAM 모듈 검토:

  1. 초기값 및 초기화 문제:

    • 메모리(mem[i])는 초기화로 모든 값을 0으로 설정하셨습니다. 그러나 시뮬레이션 초반에 read(addr)하는 것을 시도하면 초기에는 유효하지 않은 데이터(zzzzzzzZ와 같은 high-impedance 상태)가 관찰될 수 있습니다. 초기화 이후 메모리 읽기가 제대로 이루어지는지 확인하세요.
  2. 신호 타이밍 및 깔끔한 제어:

    • always 블록은 posedge clk 조건에 정의되어 있지만, re (TPSRAM의 경우) 및 cs_a, cs_b (DPSRAM의 경우)가 확실히 의도한 시점에 활성화되고 있는지 확인이 필요합니다.
  3. 테스트 벤치(tb_tpsram.sv) 확인:

    • 시뮬레이션 파형 이미지를 제공하셨는데, 제공된 테스터 벤치에 혹시 이상이 없는지도 확인해 보세요. 특히 읽기 클럭 주기에 ra, ad_a, ad_b의 값이 적절히 할당되고 있는지 체크해야 합니다.
    • 읽음과 기록 사이의 시간 간격을 충분히 유지해야 합니다.

네트리스 및 구성 확인:

  • Netlist viewer에서는 정상적으로 보인다고 하셨으니, 그럼에도 불구하고 비정상적인 상태가 발생한다면 트리거 및 논리적 흐름에 문제 있는지 의심해야 합니다.
  • 시뮬레이션에서는 ra 또는 ad_a/ad_b의 값 변경 직후에 즉시 읽으려고 하면 문제가 발생할 수 있습니다. 이는 클럭 사이클의 지연 때문에 문제가 될 수 있습니다.

관련 질문 URL을 확인해보시면 코드 구조와 시그널 핸들링에 대한 다른 유용한 설명들을 발견하실 수 있습니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

ghdrnek111님의 프로필 이미지
ghdrnek111

작성한 질문수

질문하기