Basys 3는 Xilinx의 ARTIX-7시리즈의 파트넘버 XC7A35T1CPG236C의 FPGA칩을 사용하고있다.
Xilinx의 Vivado로 FPGA개발을 진행할 것이다.
logic gate(and, nand, or, nor, xor, xnor, not)를 하나의 칩(module)으로 만들것이다.
input : 2개 switch (X0 ~ X1)
output : 7개 LED (Y0 ~ Y6)
설계하려는 하드웨어를 코드로 작성
module Logic_Gate(
input x0,
input x1,
output y0,
output y1,
output y2,
output y3,
output y4,
output y5,
output y6
);
// verilog에서 '='은 대입이 아닌 연결한다는 의미
assign y0 = x0 & x1;
assign y1 = ~(x0 & x1);
assign y2 = x0 | x1;
assign y3 = ~(x0 | x1);
assign y4 = x0 ^ x1;
assign y5 = ~(x0 ^ x1);
assign y6 = ~x0;
endmodule
Elaboration을 통해 코드를 하드웨어로 표현
Constraint (XDC): 포트설정한 내용이 있는 파일
같은 보드를 사용해 개발할 때 매번 Constraint로 포트를 지정하기보다 basys3에 대해 정의된 마스터파일을 가져와 사용하는 것이 편리하다. constraint파일을 가져올때 copy로 가져와야 원본이 변경되지 않는다.
verilog code(논리) -> synthesis(물리)를 통해 H/W(Netlist)회로 -> implementation을 통해 fpga에 배치 -> 배치된 회로를 소프트웨어로 다운로드하기위해 bitstream fpga회로파일 생성 -> fpga에 다운로드하면 끝
`timescale 1ns / 1ps // delay단위 / 분해능
// 테스트벤치는 포트가 없다
module tb_Logic_Gate();
reg x0; // reg는 메모리공간을 차지하는 변수
reg x1;
wire y0; // wire는 전선, 저장기능 X
wire y1;
wire y2;
wire y3;
wire y4;
wire y5;
wire y6;
// 모듈이름 인스턴스이름(보통 DUT라 함)
Logic_Gate u_lg(
.x0(x0), // .x0포트를 reg x0와 연결
.x1(x1),
.y0(y0),
.y1(y1),
.y2(y2),
.y3(y3),
.y4(y4),
.y5(y5),
.y6(y6)
);
// 전원 인가 시 시작
initial begin // begin end는 중괄호
#0 x0 = 0; x1 = 0; // '#숫자'는 delay를 표현
#10 x0 = 1; x1 = 0; // reg변수에 0저장하면 연결된 포트로 바로 입력
#10 x0 = 0; x1 = 1;
#10 x0 = 1; x1 = 1;
#10 $finish; // simulation 끝
end
endmodule
그림을 코드로 그대로 옮기면 된다.
module halfAdder (
input a,
input b,
output sum,
output carry
);
assign sum = a ^ b;
assign carry = a & b;
endmodule
추상화(Abstract)는 구체화된 모듈을 간략하게 입출력만 표현한 것을 말한다.
module fullAdder (
input a,
input b,
input cin,
output sum,
output co
);
// 배선부분은 wire로 연결
wire w_sum1, w_carry1, w_carry2;
halfAdder U_HA1 (
.a(a),
.b(b),
.sum(w_sum1),
.carry(w_carry1)
);
halfAdder U_HA2 (
.a(w_sum1),
.b(cin),
.sum(sum),
.carry(w_carry2)
);
assign co = w_carry1 | w_carry2;
endmodule
그림을 그대로 코드로 표현한다.
module Adder (
input [3:0] a, // 4bit포트 a
input [3:0] b,
input cin,
output [3:0] sum,
output co
);
// carry wire는 1bit씩 3개 필요
wire [2:0] w_carry;
// 각각의 FA에 포트를 연결
fullAdder U_FA0 (
.a (a[0]),
.b (b[0]),
.cin(cin),
.sum(sum[0]),
.co (w_carry[0])
);
fullAdder U_FA1 (
.a (a[1]),
.b (b[1]),
.cin(w_carry[0]),
.sum(sum[1]),
.co (w_carry[1])
);
fullAdder U_FA2 (
.a (a[2]),
.b (b[2]),
.cin(w_carry[1]),
.sum(sum[2]),
.co (w_carry[2])
);
fullAdder U_FA3 (
.a (a[3]),
.b (b[3]),
.cin(w_carry[2]),
.sum(sum[3]),
.co (co)
);
endmodule
`timescale 1ns / 1ps
module tb_adder ();
reg [3:0] a;
reg [3:0] b;
reg cin;
wire [3:0] sum;
wire co;
Adder dut ( // design under test
.a (a),
.b (b),
.cin(cin),
.sum(sum),
.co (co)
);
initial begin
#00 a = 0;
b = 0;
cin = 1'b0;
#10 a = 1;
b = 2;
#10 a = 2;
b = 3;
#10 a = 10;
b = 4;
#10 a = 8;
b = 7;
#10 a = 8;
b = 8;
#10 a = 11;
b = 12;
#10 $finish;
end
endmodule