작성
·
605
1
안녕하세요
simple_bram_ctrl.v 의 148 째줄 밑에 아래와 같이
true_dpbram.v를 instantiation을 해서 시뮬레이션을 돌리면 test bench에서 콘트롤러 모듈만 instantiation해 주면 되겠다 싶어서 나름 응용해 보고자 아래 처럼 instantiation 해줘서 vivado에서 implantation을 해 줬는데요 자꾸 error가 나오네요.
제생각에는 콘트롤러의 q0 포트가 input 인데 true_dpbram 모듈의 q0는 out put이라서 그런거 같은데 포트를 어떻게 매치 시켜줄야 instantiation이 될까요?
아래는 에러 메세지 입니다.
답변 2
1
제공해 주신 simple_bram_ctrl.v 마지막에 true_dpbram.v 를 instantiation 한 코드만 아래와 같이추가한 단순한 코드입니다.
전체 코드도 첨부 하였습니다.
true_dpbram
#( .DWIDTH (DWIDTH),
.AWIDTH (AWIDTH),
.MEM_SIZE (MEM_SIZE))
u_TDPBRAM(
.clk (clk),
.addr0 (addr0),
.ce0 (ce0),
.we0 (we0),
.q0 (q0),
.d0 (d0),
// no use port B.
.addr1 (0),
.ce1 (0),
.we1 (0),
.q1 (),
.d1 (0)
);
//////////////////////////////////////////////////////////////////////////////////
// Company: Personal
// Engineer: Matbi / Austin
//
// Create Date: 2021.01.31
// Design Name:
// Module Name: simple_bram_ctrl
// Project Name:
// Target Devices:
// Tool Versions:
// Description: To study ctrl sram. (WRITE / READ)
// FSM + mem I/F
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
`timescale 1ns / 1ps
module simple_bram_ctrl
// Param
#(
parameter DWIDTH = 16,
parameter AWIDTH = 7,
parameter MEM_SIZE = 128
)
(
input clk,
input reset_n,
input i_run,
input [AWIDTH-1:0] i_num_cnt,
output o_idle,
output o_write,
output o_read,
output o_done,
// Memory I/F
output[AWIDTH-1:0] addr0,
output ce0,
output we0,
input [DWIDTH-1:0] q0,
output[DWIDTH-1:0] d0,
// output read value from BRAM
output o_valid,
output[DWIDTH-1:0] o_mem_data
);
/////// Local Param. to define state ////////
localparam S_IDLE = 2'b00;
localparam S_WRITE = 2'b01;
localparam S_READ = 2'b10;
localparam S_DONE = 2'b11;
/////// Type ////////
reg [1:0] c_state; // Current state (F/F)
reg [1:0] n_state; // Next state (Variable in Combinational Logic)
wire is_write_done;
wire is_read_done;
/////// Main ////////
// Step 1. always block to update state
always @(posedge clk or negedge reset_n) begin
if(!reset_n) begin
c_state <= S_IDLE;
end else begin
c_state <= n_state;
end
end
// Step 2. always block to compute n_state
//always @(c_state or i_run or is_done)
always @(*)
begin
n_state = c_state; // To prevent Latch.
case(c_state)
S_IDLE : if(i_run)
n_state = S_WRITE;
S_WRITE : if(is_write_done)
n_state = S_READ;
S_READ : if(is_read_done)
n_state = S_DONE;
S_DONE : n_state = S_IDLE;
endcase
end
// Step 3. always block to compute output
// Added to communicate with control signals.
assign o_idle = (c_state == S_IDLE);
assign o_write = (c_state == S_WRITE);
assign o_read = (c_state == S_READ);
assign o_done = (c_state == S_DONE);
// Step 4. Registering (Capture) number of Count
reg [AWIDTH-1:0] num_cnt;
always @(posedge clk or negedge reset_n) begin
if(!reset_n) begin
num_cnt <= 0;
end else if (i_run) begin
num_cnt <= i_num_cnt;
end else if (o_done) begin
num_cnt <= 0;
end
end
// Step 5. increased addr_cnt
reg [AWIDTH-1:0] addr_cnt;
assign is_write_done = o_write && (addr_cnt == num_cnt-1);
assign is_read_done = o_read && (addr_cnt == num_cnt-1);
always @(posedge clk or negedge reset_n) begin
if(!reset_n) begin
addr_cnt <= 0;
end else if (is_write_done || is_read_done) begin
addr_cnt <= 0;
end else if (o_write || o_read) begin
addr_cnt <= addr_cnt + 1;
end
end
// Assign Memory I/F
assign addr0 = addr_cnt;
assign ce0 = o_write || o_read;
assign we0 = o_write;
assign d0 = addr_cnt; // same value;
// output data from memory
reg r_valid;
reg [DWIDTH-1:0] r_mem_data;
// 1 cycle latency to sync mem output
always @(posedge clk or negedge reset_n) begin
if(!reset_n) begin
r_valid <= 0;
end else begin
r_valid <= o_read; // read data
end
end
assign o_valid = r_valid;
assign o_mem_data = q0; // direct assign, bus Matbi recommends you to add a register for timing.
true_dpbram
#( .DWIDTH (DWIDTH),
.AWIDTH (AWIDTH),
.MEM_SIZE (MEM_SIZE))
u_TDPBRAM(
.clk (clk),
.addr0 (addr0),
.ce0 (ce0),
.we0 (we0),
.q0 (q0),
.d0 (d0),
// no use port B.
.addr1 (0),
.ce1 (0),
.we1 (0),
.q1 (),
.d1 (0)
);
endmodule
true_dpbram 모듈의 q0를 o_mem_data에 연결해 주니 instantiation 이 되네요. 너무 쉽게 해결 되네요. input qO를 어떻게든 이용해야 한다고 생각이 고정 되어있던 것 같습니다. 조언 해 주신 대로ㅐoutput q0를 버리고 바로 o_mem_data에 연결해 주면 되는 되는데요^^
아래는 instatntiation을 위한 변형해본 코드 입니다.
저는 개인적으로는 두개의 모듈을 instantiation 해서 하나의 모듈로 만들어서 비바도에서 implantation도 해 볼수 있어서 더 좋았던 것 같습니다. 같지만 다른 두 디자인인데 각자 어떤 잇점이 있을 까요? 강의에서 보여주신 것 처럼 두개 의 dotv 파일을 tb로 묵어서 시뮬레이션을 보여주신 숨은 의도? 가 있을 까요?^^
assign o_valid = r_valid;
//assign o_mem_data = q0; // direct assign, bus Matbi recommends you to add a register for timing.
true_dpbram
#( .DWIDTH (DWIDTH),
.AWIDTH (AWIDTH),
.MEM_SIZE (MEM_SIZE))
u_TDPBRAM(
.clk (clk),
.addr0 (addr0),
.ce0 (ce0),
.we0 (we0),
.q0 (o_mem_data),
.d0 (d0),
// no use port B.
.addr1 (0),
.ce1 (0),
.we1 (0),
.q1 (),
.d1 (0)
);
안녕하세요 :)
먼저, 코드 수정 부분은.
지금 처럼 모듈 내부에 Memory 가 들어가는 상황에서 "memory port 를 in / output 으로 사용할 필요가 없다" 였구요. 그렇게 해결 하셨으리라 믿습니다.
강의에서 보여주신 것 처럼 두개 의 dotv 파일을 tb로 묵어서 시뮬레이션을 보여주신 숨은 의도? 가 있을 까요?^^
"Memory Controller 를 설계해보자" 여서, Memory 를 바깥으로 빼서 설계해 봤어요. 만약에 질문자님이 설계자이다. 그런데 넣는게 좋아보인다. 그러면 넣으시면 됩니다. (설계자 마음대로!)
하지만, 현업가시면, Memory 는 모아서 관리합니다.
즉, 제 강의 코드처럼 Memory 는 바깥에 있다 라는 가정하에 설계하실 가능성이 높아요.
그런데, 지금은 공부하는 입장이니까, 이런 부분에 연연? 하시지 마시고, 마음껏 많이 설계해 보세요.
그럼 즐공하세요~~ :)
0
안녕하세요 :)
Multiple Driver Nets 는 input, output port 를 중복 사용을 해서 그런 것 같구요.
현재 캡쳐해주신 내용만으로는 잘 모르겠습니다.
q0 에 관한 내용 전부를 확인해보고 싶어요.
추가적으로 코드를 남겨주시겠어요?
많은 정보를 주시면 해결에 도움이 될 것 같아요 :)
(코드를 전부 올려주시는 것도 방법)
아하.....
바로 파악했구요.
그래서 이렇게 적어주셨군요.
제생각에는 콘트롤러의 q0 포트가 input 인데 true_dpbram 모듈의 q0는 out put이라서 그런거 같은데 포트를 어떻게 매치 시켜줄야 instantiation이 될까요?
제가 답을 알려드리기 전에 이 그림에 대해서 생각해 보시겠어요? (먼저 20장 그림을 가져왔습니다.)
제가 몰라서... 일 수도 있는데!!! (실력이 부족한 맛비... ㅠ.ㅠ)
질문자님께서 스스로 찾으시기를 바라는 마음에서 적습니다.
후배님께 설계 Tip 을 드리자면, Verilog HDL 을 코딩하기 전에 Architecture 를 먼저 고민하시기를 바랍니다.
지금 이 상황을 다음처럼 바꾸고 싶어하시는 것 같아요.
Hint 를 드리자면,
.
.
.
.
.
.
DUT 에서 Port A 에 대한 in /out port 가 필요할까요?
Wire 로 변경하여서, port 를 연결한다면? 어떻게 될까요?
고민해보시고, 코드를 수정해서 다시 남겨주세요.
아 참고로! 못맞추셔도 됩니다. (괴롭히는거 아니에요. 오해하지 말아주세요.)
시도한 내용을 정리해서 남겨주세요.
우리는 공부하는 입장이니까요!!
즐공입니다. :)