ENV ( INTERFACE , TRANSACTION ==> GEN -> DRV -> MON -> SCB )
Transaction : rand변수, constraint class
Interface : 전선다발. interface
Driver : `include "transaction , interface" : DATA 생성.
drv.reset, drv.run : 초기값 설정.
Generatior : `include "transaction" : DATA -> HW 신호로 생성.
randomize() 실행.
SCB에서 EVENT 받는곳.
Monitor : `include " interface" : DUT 출력신호를 DATA로 변경. HW데이터 -> SW데이터
Scoreboard : `include " transaction " 생성 SW와 DATA를 판단.
GEN으로 EVENT 보낸다.
Envieronment : gen,drv,mon,scb 묶어두는곳.
tb_fifo
ENV에서 실행할 FIFO
`timescale 1ns / 1ps
module fifo #
(parameter ADDR_WIDTH = 3,
DATA_WIDTH = 8)(
input clk ,
input reset ,
input wr_en ,
output full ,
input [DATA_WIDTH - 1:0] wdata ,
input rd_en ,
output empty ,
output[DATA_WIDTH - 1:0] rdata
);
wire w_full;
wire [ADDR_WIDTH - 1:0] w_waddr, w_raddr;
register_file #
(.ADDR_WIDTH(ADDR_WIDTH), .DATA_WIDTH(DATA_WIDTH)
)U_register_file(
.clk(clk) ,
.reset(reset) ,
.wr_en(wr_en & ~full) ,
.waddr(w_waddr) ,
.wdata(wdata) ,
.rd_en(rd_en & ~empty) ,
.raddr (w_raddr),
.rdata(rdata)
);
fifo_control_unit #
(.ADDR_WIDTH(ADDR_WIDTH
))U_fifo_control_unit(
.clk(clk) ,
.reset(reset) ,
.wr_en(wr_en) ,
.full(full) ,
.waddr(w_waddr) ,
.rd_en(rd_en) ,
.empty(empty) ,
.raddr(w_raddr)
);
endmodule
module register_file #
(parameter ADDR_WIDTH = 3, DATA_WIDTH = 8
)(
input clk ,
input reset ,
input wr_en ,
input rd_en ,
input [ADDR_WIDTH - 1:0] waddr ,
input [DATA_WIDTH - 1:0] wdata ,
input [ADDR_WIDTH - 1:0] raddr ,
output[DATA_WIDTH - 1:0] rdata
);
reg [DATA_WIDTH-1:0] mem[0:2**ADDR_WIDTH-1];
always @(posedge clk) begin
if (wr_en) mem[waddr] <= wdata;
end
assign rdata = mem[raddr];
endmodule
module fifo_control_unit #
(parameter ADDR_WIDTH = 3
)(
input clk ,
input reset ,
input wr_en ,
output full ,
output [ADDR_WIDTH-1:0] waddr ,
input rd_en ,
output empty ,
output [ADDR_WIDTH-1:0] raddr
);
reg[ADDR_WIDTH-1:0] wr_ptr_reg, wr_ptr_next;
reg[ADDR_WIDTH-1:0] rd_ptr_reg, rd_ptr_next;
reg full_reg, full_next, empty_reg, empty_next;
assign full = full_reg;
assign empty = empty_reg;
assign waddr = wr_ptr_reg;
assign raddr = rd_ptr_reg;
always @(posedge clk, posedge reset) begin
if (reset) begin
wr_ptr_reg <= 0;
rd_ptr_reg <= 0;
full_reg <= 1'b0;
empty_reg <= 1'b0;
end else begin
wr_ptr_reg <= wr_ptr_next;
rd_ptr_reg <= rd_ptr_next;
full_reg <= full_next;
empty_reg <= empty_next;
end
end
always @(*) begin
wr_ptr_next = wr_ptr_reg;
rd_ptr_next = rd_ptr_reg;
full_next = full_reg;
empty_next = empty_reg;
case({wr_en, rd_en})
2'b01 : begin //read
if(!empty) begin
full_next = 1'b0;
rd_ptr_next = rd_ptr_reg +1;
if(rd_ptr_next == wr_ptr_reg) begin
empty_next = 1'b1;
end
end
end
2'b10 : begin //write
if(!full)begin
empty_next = 1'b0;
wr_ptr_next = wr_ptr_reg +1;
if(wr_ptr_next == rd_ptr_reg)begin
full_next = 1'b1;
end
end
end
2'b11: begin //write, read
if(empty_reg)begin
wr_ptr_next = wr_ptr_reg;
rd_ptr_next = rd_ptr_reg;
end
else begin
wr_ptr_next = wr_ptr_reg +1;
rd_ptr_next = rd_ptr_reg +1;
end
end
endcase
end
endmodule
wr_en = 1 일 떈 write를 하고 rd_en = 1 일 땐 data를 queue로 부터 pop 시킨다.
if (trans.wr_en & ~trans.full)
else if (trans.rd_en & ~trans.empty)
두가지 상황에 대해서 Fail이 나오게 설정했다.
FULL 인데 wr_en이 되어 쓰기를 하거나 EMPTY 인데 rd_en 이 되어 값을 읽으려는 두가지 상황에서 오류가 발생했다.
'공부방 > Verilog_vivado' 카테고리의 다른 글
AXI4-Lite Read Address _ Read Data (0) | 2024.06.15 |
---|---|
CPU 세번째 발자국 + I, S, B, U, J, JA (0) | 2024.06.01 |
CPU 설계 두 번째 발자국 RV32I_ISA : R, IL (0) | 2024.06.01 |
CPU_설계 첫걸음.SV Register File & ALU (0) | 2024.05.30 |
코드를 짜는 방식 (0) | 2024.05.08 |