If-else 및 case 사용법
// 2to1 mux if 문 구현방법
//always@(*) 문에 포함한다
module mux2to1 (s, d0, d1, z);
input s, d0, d1;
output z;
reg z; //always 문에서 배정되는 값은 wire가 아니라 reg type을 사용할 것 !
always @(*) begin // sensitivity list @(s,d0,d1) 과 동일하지만 @(*)를 쓰자
if( s==0) begin // begin-end는 c의 중괄호와 비슷하며, c와 마찬가리고 한 개 명령이면 생략가능
z=d0;
end
else begin
z=d1;
end
end
endmodule
// 4to1 mux case 문
// c와 쓰임은 비슷하다 문법이 상이함
modulemux4to1(s,d0,d1,d2,d3,z);
input[1:0]s;
inputd0,d1,d2,d3;
output z; reg z; //output reg z; 도 ok!!!!!!
always@(*)begin
case(s) // case는 보통 mux로 합성된다!!!
0:z=d0; //2b'00
1:z=d1; //2b'01
2:z=d2; //2b'10
default:z=d3; //3대신 default 가 있는 것이 좋음
endcase
end
endmodule
//case 문은 특정 조건에 따라 여러 값을 선택하는 구조를 하드웨어적으로 효율적으로 구현할 수 있다.
언제 wire assign을 사용하고 언제 reg always를 사용하는 것이 좋을까? ( 조사 )
- 조합 회로의 경우:
wire와 assign을 사용해야 합니다. 예를 들어, AND, OR, XOR 연산과 같은 조합 논리를 구현할 때, wire로 선언된 신호에 assign 문을 사용하여 값을 할당합니다. -
verilog코드 복사assign z = a & b; // 조합 논리
- 순차 회로의 경우:
reg와 always를 사용해야 합니다. 클록에 동기화되어 값을 저장하거나 순차적인 동작을 구현할 때 reg와 always를 사용합니다. -
verilog코드 복사always @(posedge clk) begin q <= a; // 순차 회로 end
- 상태 머신, 레지스터 등의 순차적 동작:
순차적으로 동작하는 설계를 할 때, 예를 들어 상태 머신, 카운터, 레지스터 배열 등을 구현할 때는 reg와 always를 사용합니다. 클록 또는 리셋 신호에 따라 상태를 업데이트하고 값을 저장합니다.
결론
- wire assign: 조합 회로에서 신호의 계산 및 할당이 지속적으로 이루어져야 할 때 사용합니다.
- reg always: 클록에 동기화된 값의 저장이 필요하거나 순차적인 동작이 필요한 경우 사용합니다.
8.2 structural modeling
다른 모듈을 서브모듈삼아 더 복잡한 모듈을 설계할 수 있다.
어떤 모듈을 다른 모듈 안에 인스턴스화 하는 방법
< module 종류> <인스턴스 이름>(포트이름);
module top(input a,b,c, output d);
wire e;
siple mysimplemodule(a,b,c,e);
assign d = ~e; //~ 대신 not mynot (d, e) ; 도 가능 but 흔히 쓰이지는 않는다.
endmodule
// not .. (z,a) = assign z = ~a;
// and .. (z,a,b) = assign z = a&b;
//submodule port와의 연결을 명시적으로 언급하는 방법
module top(input a,b,c, output d);
wire e;
simple mysimplemodule( .x(a), .y(b), .z(c), .f(e));
assign d = ~e;
endmodule
// half adder 로 full adder 구현하기
module full_adder(output sum, cout, input x, y, z);
wire s1, c1, c2;
half_adder ha0(s1, c1, x, y); // 첫 번째 half adder
half_adder ha1(sum, c2, s1, z); // 두 번째 half adder
assign cout = c1 | c2; // 캐리 아웃 계산
endmodule
// 4b 감가산기를 verilog로 설계하기
module tb_addsub4b;
reg [3:0] x;
reg [3:0] y;
reg op;
wire [3:0] s;
wire ovf;
integer i;
wire [3:0] z_ans;
wire [3:0] s_ans;
wire ovf_ans;
integer cnt = 0;
initial begin
x = 0; y = 0;
for(i = 0; i < 16; i = i + 1, x = x - 1, y = y + 2) begin
op = (i%2==0) ? 0 : 1;
#10;
if( s != s_ans || ovf != ovf_ans ) begin
$display("x=%04b, y=%04b, op=%01b, expecting sum:%04b, overflow:%01b, but observed %04b and %01b", x, y, op, s_ans, ovf_ans, s, ovf);
cnt = cnt + 1;
end
end
$display("////Simulation finished with %d errors////", cnt);
$finish;
end
assign z_ans = (op) ? ~y : y;
assign s_ans = x + z_ans + op;
assign ovf_ans = (~x[3]&~y[3]&~op&s[3])|(x[3]&y[3]&~op&~s[3])|(x[3]&~y[3]&op&~s[3])|(~x[3]&y[3]&op&s[3]);
addsub4b dut(x, y, op, s, ovf);
wire [3:0] yn = dut.yn;
wire [3:0] z = dut.z;
wire [3:0] c = dut.c;
endmodule
C vs Verilog
c는 순차언어인 반면 벨로그는 병렬 언어
- c의 명령어는 cpu 명령어로 변환되어 수행 후 명령어로 넘어가만, 벨로그의 statement들은 디지털회로로 변환되어 항상 연산을 하고 있음 (입출력 신호만 바뀜)
- 벨로그에서 모든 모듈 인스턴스, assignment 등은 동시에 지속 수행됨
'Major S-T-U-D-Y > Digital System' 카테고리의 다른 글
[논리회로] 7 (2) 동기식 J/K , D FF 카운터의 설계과정 (1) | 2024.12.01 |
---|---|
[논리회로] 7 (1) 비동기적(ripple) 카운터와 동기적 카운터(mod/up-down/presettable) (1) | 2024.11.29 |
[논리회로] 5 (2) S-R Flip-Flop 과 J-K Flip-Flop (0) | 2024.11.17 |
[논리회로] 5 (1) NAND/NOR Gate Lanch (set/reset) (0) | 2024.11.17 |
[논리회로] 8 (1) 벨로그 기초 문법과 테스트벤치 (1) | 2024.11.17 |
If-else 및 case 사용법
// 2to1 mux if 문 구현방법
//always@(*) 문에 포함한다
module mux2to1 (s, d0, d1, z);
input s, d0, d1;
output z;
reg z; //always 문에서 배정되는 값은 wire가 아니라 reg type을 사용할 것 !
always @(*) begin // sensitivity list @(s,d0,d1) 과 동일하지만 @(*)를 쓰자
if( s==0) begin // begin-end는 c의 중괄호와 비슷하며, c와 마찬가리고 한 개 명령이면 생략가능
z=d0;
end
else begin
z=d1;
end
end
endmodule
// 4to1 mux case 문
// c와 쓰임은 비슷하다 문법이 상이함
modulemux4to1(s,d0,d1,d2,d3,z);
input[1:0]s;
inputd0,d1,d2,d3;
output z; reg z; //output reg z; 도 ok!!!!!!
always@(*)begin
case(s) // case는 보통 mux로 합성된다!!!
0:z=d0; //2b'00
1:z=d1; //2b'01
2:z=d2; //2b'10
default:z=d3; //3대신 default 가 있는 것이 좋음
endcase
end
endmodule
//case 문은 특정 조건에 따라 여러 값을 선택하는 구조를 하드웨어적으로 효율적으로 구현할 수 있다.
언제 wire assign을 사용하고 언제 reg always를 사용하는 것이 좋을까? ( 조사 )
- 조합 회로의 경우:
wire와 assign을 사용해야 합니다. 예를 들어, AND, OR, XOR 연산과 같은 조합 논리를 구현할 때, wire로 선언된 신호에 assign 문을 사용하여 값을 할당합니다. -
verilog코드 복사assign z = a & b; // 조합 논리
- 순차 회로의 경우:
reg와 always를 사용해야 합니다. 클록에 동기화되어 값을 저장하거나 순차적인 동작을 구현할 때 reg와 always를 사용합니다. -
verilog코드 복사always @(posedge clk) begin q <= a; // 순차 회로 end
- 상태 머신, 레지스터 등의 순차적 동작:
순차적으로 동작하는 설계를 할 때, 예를 들어 상태 머신, 카운터, 레지스터 배열 등을 구현할 때는 reg와 always를 사용합니다. 클록 또는 리셋 신호에 따라 상태를 업데이트하고 값을 저장합니다.
결론
- wire assign: 조합 회로에서 신호의 계산 및 할당이 지속적으로 이루어져야 할 때 사용합니다.
- reg always: 클록에 동기화된 값의 저장이 필요하거나 순차적인 동작이 필요한 경우 사용합니다.
8.2 structural modeling
다른 모듈을 서브모듈삼아 더 복잡한 모듈을 설계할 수 있다.
어떤 모듈을 다른 모듈 안에 인스턴스화 하는 방법
< module 종류> <인스턴스 이름>(포트이름);
module top(input a,b,c, output d);
wire e;
siple mysimplemodule(a,b,c,e);
assign d = ~e; //~ 대신 not mynot (d, e) ; 도 가능 but 흔히 쓰이지는 않는다.
endmodule
// not .. (z,a) = assign z = ~a;
// and .. (z,a,b) = assign z = a&b;
//submodule port와의 연결을 명시적으로 언급하는 방법
module top(input a,b,c, output d);
wire e;
simple mysimplemodule( .x(a), .y(b), .z(c), .f(e));
assign d = ~e;
endmodule
// half adder 로 full adder 구현하기
module full_adder(output sum, cout, input x, y, z);
wire s1, c1, c2;
half_adder ha0(s1, c1, x, y); // 첫 번째 half adder
half_adder ha1(sum, c2, s1, z); // 두 번째 half adder
assign cout = c1 | c2; // 캐리 아웃 계산
endmodule
// 4b 감가산기를 verilog로 설계하기
module tb_addsub4b;
reg [3:0] x;
reg [3:0] y;
reg op;
wire [3:0] s;
wire ovf;
integer i;
wire [3:0] z_ans;
wire [3:0] s_ans;
wire ovf_ans;
integer cnt = 0;
initial begin
x = 0; y = 0;
for(i = 0; i < 16; i = i + 1, x = x - 1, y = y + 2) begin
op = (i%2==0) ? 0 : 1;
#10;
if( s != s_ans || ovf != ovf_ans ) begin
$display("x=%04b, y=%04b, op=%01b, expecting sum:%04b, overflow:%01b, but observed %04b and %01b", x, y, op, s_ans, ovf_ans, s, ovf);
cnt = cnt + 1;
end
end
$display("////Simulation finished with %d errors////", cnt);
$finish;
end
assign z_ans = (op) ? ~y : y;
assign s_ans = x + z_ans + op;
assign ovf_ans = (~x[3]&~y[3]&~op&s[3])|(x[3]&y[3]&~op&~s[3])|(x[3]&~y[3]&op&~s[3])|(~x[3]&y[3]&op&s[3]);
addsub4b dut(x, y, op, s, ovf);
wire [3:0] yn = dut.yn;
wire [3:0] z = dut.z;
wire [3:0] c = dut.c;
endmodule
C vs Verilog
c는 순차언어인 반면 벨로그는 병렬 언어
- c의 명령어는 cpu 명령어로 변환되어 수행 후 명령어로 넘어가만, 벨로그의 statement들은 디지털회로로 변환되어 항상 연산을 하고 있음 (입출력 신호만 바뀜)
- 벨로그에서 모든 모듈 인스턴스, assignment 등은 동시에 지속 수행됨
'Major S-T-U-D-Y > Digital System' 카테고리의 다른 글
[논리회로] 7 (2) 동기식 J/K , D FF 카운터의 설계과정 (1) | 2024.12.01 |
---|---|
[논리회로] 7 (1) 비동기적(ripple) 카운터와 동기적 카운터(mod/up-down/presettable) (1) | 2024.11.29 |
[논리회로] 5 (2) S-R Flip-Flop 과 J-K Flip-Flop (0) | 2024.11.17 |
[논리회로] 5 (1) NAND/NOR Gate Lanch (set/reset) (0) | 2024.11.17 |
[논리회로] 8 (1) 벨로그 기초 문법과 테스트벤치 (1) | 2024.11.17 |