Kraklog
Day.82 Advanced Verilog #5 본문
728x90
클럭 도메인이 안맞을때도 사용가능하지만
이 기능을 사용하지 않고는 뒤에 로직이 하나 더 붙는다.
(동작을 하지 않는 것은 아님)
read enable 신호때 생성을 하게 만들거나
aclr에 asynchornous 를 해주는 세팅을 할 수 있게 하거나
이것에 대한 순서를 정할 수 있다.
module sp_ram_sync_rdwo(
input clk ,
input we ,
input [7:0] d ,
input [6:0] addr ,
output reg [7:0] q
);
reg [7:0] mem [0:127];
always @ (posedge clk) begin
if(we)
mem[addr] <= d;
q <= mem[addr];
end
endmodule
`define CLK_50Mhz 10
module tb_sp_ram_sync_rdwo();
reg clk ;
reg we ;
reg [7:0] d ;
reg [6:0] addr ;
wire [7:0] q ;
sp_ram_sync_rdwo uSp_ram_sync_rdwo (
.clk (clk ) ,
.we (we ) ,
.d (d ) ,
.addr(addr) ,
.q (q )
);
initial fork
clk_gen();
reset_gen();
data_gen();
ctrl_gen();
join
task clk_gen;
begin
clk = 1'b0;
forever #(`CLK_50Mhz/2) clk=~clk;
end
endtask
task reset_gen();
begin
addr=6'b0;
forever #(`CLK_50Mhz*2) addr=addr+1'b1;
end
endtask
task data_gen;
begin
d = 8'hA17;
forever #(`CLK_50Mhz*5) d = d+1;
end
endtask
task ctrl_gen;
begin
we = 1'b0;
forever #(`CLK_50Mhz*3) we = ~we;
end
endtask
endmodule
module sp_ram_sync_rdwo2(
input clk ,
input we ,
input [7:0] d ,
input [6:0] addr ,
output reg [7:0] q
);
reg [7:0] mem [0:2**8-1];
always @ (posedge clk) begin
if(we)
mem[addr] <= d;
q <= mem[addr];
end
//실제로 동작이
/*
always @(posedge clk) begin
if (we)
mem [addr] <= d;
end
always @(posedge clk) begin
q <= mem [addr];
end
//처럼 동작한다.
*/
//else가 있다면
/* always @(posedge clk)
begin
if (we)
mem[addr] <= d;
else
q <= mem[addr];
end
이렇게 있으면 we가 1일때 else 전까지만 동작하고 동작하지 않기 때문에
else가 없는구문이 맞다.
*/
endmodule
`timescale 1ns/ 1ns
`define CLK_50Mhz 20
`define DBUS_SIZE 8
`define SBUS_SIZE 7
module tb_sp_ram_sync_rdwo2();
reg clk ;
reg we ;
reg [`DBUS_SIZE-1:0] d ;
reg [`SBUS_SIZE-1:0] addr ;
wire [`DBUS_SIZE-1:0] q ;
sp_ram_sync_rdwo2 uSp_ram_sync_rdwo (
.clk (clk ) ,
.we (we ) ,
.d (d ) ,
.addr(addr) ,
.q (q )
);
initial fork
clk_gen();
reset_gen();
data_gen();
ctrl_gen();
join
task clk_gen;
begin
clk = 1'b0;
forever #(`CLK_50Mhz/2) clk=~clk;
end
endtask
task reset_gen();
begin
addr = 7'h00;
repeat(3) @(negedge clk);
addr = 7'h05;
@(negedge clk);
addr = 7'h06;
@(negedge clk);
addr = 7'h05;
@(negedge clk);
addr = 7'h6;
@(negedge clk);
end
endtask
task data_gen;
begin
d=8'hAA;
repeat(5) @(negedge clk);
d=8'h55;
repeat(2) @(negedge clk);
d=8'hf7;
end
endtask
task ctrl_gen;
begin
we = 1'b0;
repeat(5) @(negedge clk);
we = 1'b1;
end
endtask
endmodule
else를 적어주면 q에 데이터가 wirte 되질 않는다.
-Old Data가 나오는 셋팅
module sp_ram_sync_rdwo2(
input clk ,
input we ,
input [7:0] d ,
input [6:0] addr ,
output reg [7:0] q
);
reg [7:0] mem [0:2**8-1];
always @ (posedge clk) begin
if(we)
mem[addr] = d; //blocking
q = mem[addr]; //blocking
end
endmodule
`timescale 1ns/ 1ns
`define CLK_50Mhz 20
`define DBUS_SIZE 8
`define SBUS_SIZE 7
module tb_sp_ram_sync_rdwo2();
reg clk ;
reg we ;
reg [`DBUS_SIZE-1:0] d ;
reg [`SBUS_SIZE-1:0] addr ;
wire [`DBUS_SIZE-1:0] q ;
sp_ram_sync_rdwo2 uSp_ram_sync_rdwo (
.clk (clk ) ,
.we (we ) ,
.d (d ) ,
.addr(addr) ,
.q (q )
);
initial fork
clk_gen();
reset_gen();
data_gen();
ctrl_gen();
join
task clk_gen;
begin
clk = 1'b0;
forever #(`CLK_50Mhz/2) clk=~clk;
end
endtask
task reset_gen();
begin
addr = 7'h00;
repeat(3) @(negedge clk);
addr = 7'h05;
@(negedge clk);
addr = 7'h06;
@(negedge clk);
addr = 7'h05;
@(negedge clk);
addr = 7'h6;
@(negedge clk);
end
endtask
task data_gen;
begin
d=8'hAA;
repeat(5) @(negedge clk);
d=8'h55;
repeat(2) @(negedge clk);
d=8'hf7;
end
endtask
task ctrl_gen;
begin
we = 1'b0;
repeat(5) @(negedge clk);
we = 1'b1;
end
endtask
endmodule
blocking - > Immediately
unblocking -> scheduled
f7이 업데이트 되는 속도의 차이가 보인다.
module dp_dc_ram (
input [7:0] data_a ,
input [7:0] data_b ,
input [6:0] addr_a ,
input [6:0] addr_b ,
input clk_a ,
input clk_b ,
input we_a ,
input we_b ,
output reg [7:0] q_a ,
output reg [7:0] q_b
);
reg [7:0] mem [0:(2**8)-1];
always @(posedge clk_a) begin
if (we_a)
mem[addr_a] <= data_a;
q_a <= mem[addr_a];
end
always @(posedge clk_b) begin
if (we_b)
mem[addr_b] <= data_b;
q_b <= mem[addr_b];
end
endmodule
`timescale 1ns/ 1ns
`define CLK_50Mhz 20
`define DBUS_SIZE 8
`define SBUS_SIZE 7
module tb_dp_dc_ram ();
reg [7:0] data_a ;
reg [7:0] data_b ;
reg [6:0] addr_a ;
reg [6:0] addr_b ;
reg clk_a ;
reg clk_b ;
reg we_a ;
reg we_b ;
wire [7:0] q_a ;
wire [7:0] q_b ;
dp_dc_ram uDp_dc_ram(
.data_a(data_a) ,
.data_b(data_b) ,
.addr_a(addr_a) ,
.addr_b(addr_b) ,
.clk_a (clk_a ) ,
.clk_b (clk_b ) ,
.we_a (we_a ) ,
.we_b (we_b ) ,
.q_a (q_a ) ,
.q_b (q_b )
);
initial fork
clk_gen_a();
clk_gen_b();
add_a();
add_b();
data_gen_a();
data_gen_b();
ctrl_gen_a();
ctrl_gen_b();
join
task clk_gen_a;
begin
clk_a = 1'b0;
forever #(`CLK_50Mhz/2) clk_a=~clk_a;
end
endtask
task add_a;
begin
addr_a = 7'h00;
repeat(3) @(negedge clk_a);
addr_a = 7'h05;
@(negedge clk_a);
addr_a = 7'h06;
@(negedge clk_a);
addr_a = 7'h05;
@(negedge clk_a);
addr_a = 7'h6;
end
endtask
task data_gen_a;
begin
data_a=8'hAA;
repeat(5) @(negedge clk_a);
data_a=8'hBB;
repeat(2) @(negedge clk_a);
data_a=8'hf7;
end
endtask
task ctrl_gen_a;
begin
we_a= 1'b0;
repeat(5) @(negedge clk_a);
we_a= 1'b1;
end
endtask
task clk_gen_b;
begin
clk_b = 1'b0;
#5
forever #(`CLK_50Mhz/2) clk_b=~clk_b;
end
endtask
task add_b;
begin
addr_b = 7'h00;
repeat(3) @(negedge clk_b);
addr_b = 7'h01;
@(negedge clk_b);
addr_b = 7'h02;
@(negedge clk_b);
addr_b = 7'h03;
@(negedge clk_b);
addr_b = 7'h04;
end
endtask
task data_gen_b;
begin
data_b=8'hBB;
repeat(5) @(negedge clk_b);
data_b=8'hBC;
repeat(2) @(negedge clk_b);
data_b=8'hf8;
end
endtask
task ctrl_gen_b;
begin
we_b= 1'b0;
repeat(5) @(negedge clk_b);
we_b= 1'b1;
end
endtask
endmodule
a와 b의 클락 위상을 다르게 대입 할 수 있다.
vlib work
vlog dp_dc_ram.v tb_dp_dc_ram.v
vsim -t ns tb_dp_dc_ram
view wave
add wave -expand -group a -radix binary /tb_dp_dc_ram/clk_a
add wave -expand -group a -radix binary /tb_dp_dc_ram/we_a
add wave -expand -group a -radix hexadecimal /tb_dp_dc_ram/data_a
add wave -expand -group a -radix hexadecimal /tb_dp_dc_ram/addr_a
add wave -expand -group a /tb_dp_dc_ram/uDp_dc_ram/mem
add wave -expand -group a -radix hexadecimal /tb_dp_dc_ram/q_a
add wave -expand -group b -radix binary /tb_dp_dc_ram/clk_b
add wave -expand -group b -radix binary /tb_dp_dc_ram/we_b
add wave -expand -group b -radix hexadecimal /tb_dp_dc_ram/data_b
add wave -expand -group b -radix hexadecimal /tb_dp_dc_ram/addr_b
add wave -expand -group b /tb_dp_dc_ram/uDp_dc_ram/mem
add wave -expand -group b -radix hexadecimal /tb_dp_dc_ram/q_b
run 500ns
그룹 + 확장까지 되는 tcl.
module dp_dc_ram (
input [7:0] data_a ,
input [7:0] data_b ,
input [6:0] addr_a ,
input [6:0] addr_b ,
input clk_a ,
input clk_b ,
input we_a ,
input we_b ,
output reg [7:0] q_a ,
output reg [7:0] q_b
);
reg [7:0] mem [0:(2**8)-1];
always @(posedge clk_a) begin
if (we_a)
mem[addr_a] <= data_a;
q_a <= mem[addr_a];
end
always @(posedge clk_b) begin
if (we_b)
mem[addr_b] <= data_b;
q_b <= mem[addr_b];
end
endmodule
`timescale 1ns/ 1ns
`define CLK_50Mhz 20
module tb_dp_dc_ram ();
reg [7:0] data_a ;
reg [7:0] data_b ;
reg [6:0] addr_a ;
reg [6:0] addr_b ;
reg clk_a ;
reg clk_b ;
reg we_a ;
reg we_b ;
wire [7:0] q_a ;
wire [7:0] q_b ;
dp_dc_ram uDp_dc_ram(
.data_a(data_a) ,
.data_b(data_b) ,
.addr_a(addr_a) ,
.addr_b(addr_b) ,
.clk_a (clk_a ) ,
.clk_b (clk_b ) ,
.we_a (we_a ) ,
.we_b (we_b ) ,
.q_a (q_a ) ,
.q_b (q_b )
);
initial fork
clk_gen_a();
clk_gen_b();
data_gen_a();
data_gen_b();
ctrl_gen_a();
ctrl_gen_b();
join
task clk_gen_a;
begin
clk_a = 1'b0;
forever #(`CLK_50Mhz/2) clk_a=~clk_a;
end
endtask
task data_gen_a;
begin
data_a=8'hAA;
repeat(5) @(negedge clk_a);
data_a=8'hBB;
repeat(2) @(negedge clk_a);
data_a=8'hf7;
end
endtask
task ctrl_gen_a;
begin
we_a = 1'b0;
addr_a = 7'h00;
repeat(5) @(negedge clk_a);
we_a = 1'b1;
addr_a = 7'h05;
@(negedge clk_a);
addr_a = 7'h06;
@(negedge clk_a);
addr_a = 7'h05;
@(negedge clk_a);
addr_a = 7'h6;
end
endtask
task clk_gen_b;
begin
clk_b = 1'b0;
#5
forever #(`CLK_50Mhz/2) clk_b=~clk_b;
end
endtask
task data_gen_b;
begin
data_b=8'hBB;
repeat(5) @(negedge clk_b);
data_b=8'hBC;
repeat(2) @(negedge clk_b);
data_b=8'hf8;
end
endtask
task ctrl_gen_b;
begin
we_b= 1'b0;
addr_b = 7'h00;
repeat(5) @(negedge clk_b);
we_b= 1'b1;
addr_b = 7'h01;
@(negedge clk_b);
addr_b = 7'h02;
@(negedge clk_b);
addr_b = 7'h03;
@(negedge clk_b);
addr_b = 7'h04;
end
endtask
endmodule
module ram_init(
input clk ,
input we ,
input [7:0] d ,
input [6:0] wr_addr ,
input [6:0] rd_addr ,
output reg [7:0] q
);
reg [7:0] mem [0:2**7-1];
initial
$readmemb ("ram.dat",mem);
always @(posedge clk) begin
if (we)
mem[wr_addr] <= d;
q<=mem[rd_addr];
end
endmodule
`timescale 1ns/ 1ns
`define CLK_50Mhz 20
module tb_ram_init();
reg clk ;
reg we ;
reg [7:0] d ;
reg [6:0] wr_addr ;
reg [6:0] rd_addr ;
wire [7:0] q ;
ram_init uRam_init(
.clk (clk ) ,
.we (we ) ,
.d (d ) ,
.wr_addr(wr_addr) ,
.rd_addr(rd_addr) ,
.q (q )
);
initial fork
clk_gen();
data_gen();
ctrl_gen();
join
task clk_gen;
begin
clk = 1'b0;
forever #(`CLK_50Mhz/2) clk =~clk ;
end
endtask
task data_gen;
begin
d = "ram.dat";
end
endtask
task ctrl_gen;
begin
we = 1'b0;
wr_addr = 7'h00;
rd_addr = 7'h00;
repeat(3) @(negedge clk);
we = 1'b1;
wr_addr = 7'h01;
rd_addr = 7'h01;
repeat(2) @(negedge clk);
wr_addr = 7'h02;
rd_addr = 7'h02;
repeat(2) @(negedge clk);
wr_addr = 7'h03;
rd_addr = 7'h03;
end
endtask
endmodule
//create ram.dat
00000000
00000101
00001010
00001111
00010100
00011001
00011110
00100011
00101000
//Repeat segment at
//address 20 hex
@20
00000000
00000101
00001010
00001111
00010100
00011001
00011110
00100011
00101000
728x90
'[Harman] 하만 반도체 설계 > VerilogHDL' 카테고리의 다른 글
Day.84 Advanced Verilog #7 (0) | 2023.11.20 |
---|---|
Day.83 Advanced Verilog #6 (0) | 2023.11.17 |
Day.81 Advanced Verilog #4 (0) | 2023.11.14 |
Day.80 Advavnced Verilog #3 (0) | 2023.11.13 |
Day.79 Advanced Verilog #2 (0) | 2023.11.10 |