2023. 6. 23. 16:28ㆍ[Harman] 세미콘(semiconductor) 아카데미-반도체설계/Verilog를 이용한 RTL 시스템 반도체 설계
- 레지스터
베릴로그에 의한 레지스터의 구현 방법
클럭이 있는 순차회로 = 플립플롭과 조합게이트로 구성
플립플롭이 없으면 조합회로만 구현 가능
플립플롭만 구성된 회로의 경우 조합논리게이트 없더라도 순차회로로 간주
플립플롭을 포함하고 있는 회로는 순차 회로라는 명칭 뿐만 아니라 수행하는 기능에 의해 레지스터와 카운터로 분류
레지스터 = 플립플롭들로 구성되며 각 플립플롭은 클럭을 공유하고 한 비트의 정보를 저장 가능
n비트 렞니스터는 n개의 플립플롭으로 구성되고 n개의 비트를 가지는 2진 정보를 wjwkd
카운터
입력이 가해짐에 따라 상태를 미리 정해진 순서대로 진행시키는 레지스터
카운터의 게이트는 레지스터에서 2진상태를 정해진 순서대로 만들어둔 것
래치
임시저장장소의 한 종류로서 두 개의 안정 상태를 가지고 있으며 플립플롭과 별개의 분류로 분류되는 쌍안정소자
레지스터는 클럭에 의해 값이 변하므로 레지스터 자체를 순차논리회로의 하나로 간주
베릴로그의 레지스터는 클리어, 프리셋, 클럭과 비동기 로드 신호에 의해 제어가 가능
저장요소로서의 래치는 신호레벨로 동작
레지스터의 회로 표현
q1 = 비동기 로드를 갖는 레지스터
q2 = 비동기 프리셋, 클리어를 갖는 레지스터
레지스터는 클럭에 의해 값이 변하므로 순차논리회로의 하나
모든 순차논리회로는 하나 이상의 레지스터를 포함
비동기 로드 레지스터 = load신호가 클럭에 영향을 받지 않음
`timescale 1ns / 1ps
module regitser(
input clk, clr, pre, load, data, d,
output reg q1, q2
);
always @(posedge clk or posedge load) begin
if(load)
q1<=data;
else
q1<=d;
end
always @(posedge clk or negedge clr or negedge pre) begin
if(!clr)
q2 <= 1'b0;
else if(!pre)
q2 <= 1'b1;
else
q2 <= d;
end
endmodule
module register_tb;
reg clk, clr, pre, load, data, d;
wire q1, q2;
regitser uut (
.clk(clk),
.clr(clr),
.pre(pre),
.load(load),
.data(data),
.d(d),
.q1(q1),
.q2(q2)
);
initial begin
// Initialize inputs
clk = 0;
clr = 1;
pre = 0;
load = 0;
data = 0;
d = 0;
// Test case 1: Load data into q1
load = 1;
data = 1;
#10; // Wait for 10 time units
// Test case 2: Use d as input to q1
load = 0;
d = 0;
#10;
// Test case 3: Clear q2
clr = 0;
pre = 1;
d = 0;
#10;
// Test case 4: Set q2 with d
clr = 1;
pre = 0;
d = 1;
#10;
// Add more test cases if needed
$finish; // End simulation
end
always begin
#5; // Toggle clock every 5 time units
clk = ~clk;
end
endmodule

- 병렬 - 직렬 변환회로 설계
병렬입력 - 직렬출력
시프트 레지스터 = 저장되어 있는 이진 정보를 단방향 또는 양방향으로 이동시킬 수 있는 레지스터의 종류
시프트 레지스터는 직렬입렬 병렬출력과 병렬입력 직렬출력형태를 포함하여 직렬과 병렬의 입출력 조합이 가능. 여기에는 직병렬 입력을 가지고 직병렬 출력을 지닌 형태도 존재.
시프트레지스터와 각 플립플롭들은 각각 입력과 출력이 연쇄적으로 연결되어 공통으로 입력되는 클럭이 데이터를 한 비트씩 다음 레지스터로 이동
입력이 parallell하게 들어간다.
시프트 레지스터를 응용한 병렬-직렬 변환기 블록도
변환기가 필요한 경우는 asic칩에서 모든 데이터 비트를 출력시키는데 사용할 핀들이 충분히 없을 때 유용
신호 load = 1이면, 입력p_in이 시프트 레지스터에 저장
`timescale 1ns / 1ps
module shift_regitser(
input clk,reset_n,load,
input [7:0] p_in,
output [7:0] s_out
);
reg [7:0] reg1 = 8'h00, s_reg = 8'h00;
reg [25:0] cnt = 26'h0;
reg clk100Hz;
always @(posedge clk100Hz) begin
if(load)
reg1 <= p_in;
else begin
s_reg <= {s_reg[6:0], reg1[7]};
reg1 <= {reg1[6:0], 1'b0};
end
end
always @(posedge clk or negedge reset_n) begin
if(!reset_n) begin
cnt <= 26'b0;
clk100Hz <= 1'b0;
end
else if(cnt == (26'd50000000 - 1)) begin
cnt <= 26'd0;
clk100Hz <= ~clk100Hz;
end else
cnt <= cnt +1'b1;
end
assign s_out = s_reg;
endmodule
## Clock signal
set_property -dict { PACKAGE_PIN W5 IOSTANDARD LVCMOS33 } [get_ports clk]
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk]
## Switches
set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports {p_in[0]}]
set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports {p_in[1]}]
set_property -dict { PACKAGE_PIN W16 IOSTANDARD LVCMOS33 } [get_ports {p_in[2]}]
set_property -dict { PACKAGE_PIN W17 IOSTANDARD LVCMOS33 } [get_ports {p_in[3]}]
set_property -dict { PACKAGE_PIN W15 IOSTANDARD LVCMOS33 } [get_ports {p_in[4]}]
set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports {p_in[5]}]
set_property -dict { PACKAGE_PIN W14 IOSTANDARD LVCMOS33 } [get_ports {p_in[6]}]
set_property -dict { PACKAGE_PIN W13 IOSTANDARD LVCMOS33 } [get_ports {p_in[7]}]
set_property -dict { PACKAGE_PIN T1 IOSTANDARD LVCMOS33 } [get_ports {reset_n}]
set_property -dict { PACKAGE_PIN R2 IOSTANDARD LVCMOS33 } [get_ports {load}]
## LEDs
set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports {s_out[0]}]
set_property -dict { PACKAGE_PIN E19 IOSTANDARD LVCMOS33 } [get_ports {s_out[1]}]
set_property -dict { PACKAGE_PIN U19 IOSTANDARD LVCMOS33 } [get_ports {s_out[2]}]
set_property -dict { PACKAGE_PIN V19 IOSTANDARD LVCMOS33 } [get_ports {s_out[3]}]
set_property -dict { PACKAGE_PIN W18 IOSTANDARD LVCMOS33 } [get_ports {s_out[4]}]
set_property -dict { PACKAGE_PIN U15 IOSTANDARD LVCMOS33 } [get_ports {s_out[5]}]
set_property -dict { PACKAGE_PIN U14 IOSTANDARD LVCMOS33 } [get_ports {s_out[6]}]
set_property -dict { PACKAGE_PIN V14 IOSTANDARD LVCMOS33 } [get_ports {s_out[7]}]
- up-down 카운터
`timescale 1ns / 1ps
module updowncnt( clk, reset, updown, cnt_out, updown_out);
input reset, clk, updown;
output [1:0] cnt_out;
output updown_out;
parameter S0 = 2'b00, S1 = 2'b01, S2 = 2'b10, S3 = 2'b11;
reg [1:0] state = S0;
assign updown_out = updown;
assign cnt_out = state;
always @ (posedge clk or negedge reset) begin
if (~reset)
state <= S0;
else begin
case(state)
S0 : if(~updown) state <= S1;
else state <= S3;
S1 : if(~updown) state <= S2;
else state <= S0;
S2 : if(~updown) state <= S3;
else state <= S1;
S3 : if(~updown) state <= S0;
else state <= S2;
endcase
end
end
endmodule
`timescale 1ns / 1ps
module counter (
input clkin,
input reset,
output reg [1:0] out_counter // 4x1 Data MUX의 en 역할
);
// reg [1:0] r_counter = 0; // 선언할 때 초기화
// assign o_counter = r_counter;
always @(posedge clkin, negedge reset)
begin
if (~reset) begin
out_counter <= 0;
end
else begin
out_counter <= out_counter + 1;
end
end
endmodule
`timescale 1ns / 1ps
module clock_divider_paramN #(parameter N = 50_000_000)(
input clk, //보드 내부 클럭 100MHz,이고 분주하면 50MHz-> 50,000,000 (100MHz는 1초당 1억번 -> 분주 시 5000만번)
input reset,
output reg clk1000Hz // 클럭 주기를 1000Hz로 설정
);
reg [25:0] cnt = 0; // 2^26승 이상일 때부터 50000만 이상 이므로 count는 26 bit 할당, 초기값 0 선언
always @(posedge clk, negedge reset) begin // 반복문을 positive edge와 negative edge의 값이 변화할 때 항상 반복을 시작
if (~reset) begin // if reset(활성화 상태)가 아니라면
cnt <= 0; // count는 0이다.
end else begin // ~reset인 상태가 아닌 이외의 상태일 때,
if (cnt == (N - 1)) begin // count가 4999번째 클럭이라면 그 다음 클럭에서
cnt <= 0; // count는 0으로 간다.
clk1000Hz <= ~clk1000Hz; // clk 주기를 다시 1000Hz로
end else begin
cnt <= cnt + 1; // 현재 count에서 1을 더한 값을 cnt에
end
end
end
endmodule
`timescale 1ns / 1ps
module data_mux4x1(
input [3:0] ina, inb, inc, ind, // 4x1 Data mux 입력 4bit 입력 4개
input [1:0] dmuxsel, // counter 구조의 output이 data mux의 select로 입력
output reg [3:0] dmux_out // data mux의 output이 FND Decoder의 input으로 들어가므로 register로 데이터 저장
);
always @ (dmuxsel) // select의 값이 변할 때 항상 다음을 반복
begin : datamux4x1
case(dmuxsel) // dmuxsel이 입력될 경우
2'b00 : dmux_out = ina; //2'b00이 출력일 때 ina이다.
2'b01 : dmux_out = inb; //2'b01이 출력일 때 inb이다.
2'b10 : dmux_out = inc; //2'b10이 출력일 때 inc이다.
2'b11 : dmux_out = ind; //2'b11이 출력일 때 ind이다.
endcase
end
endmodule
`timescale 1ns / 1ps
module mux_4x1(
input [1:0] s, // select
output reg [3:0] y // 사용중인 보드(basys3)의 FND가 cathode 방식이므로 0일 때, 활성화
);
always @(s)
begin : MUX_4x1
case (s)
2'b00: y = 4'b1110; // 1번째 FND 결정
2'b01: y = 4'b1101; // 2번째 FND 결정
2'b10: y = 4'b1011; // 3번째 FND 결정
2'b11: y = 4'b0111; // 4번째 FND 결정
default: y = 4'b1111; // Default 값 FND 결정
endcase
end
endmodule
`timescale 1ns / 1ps
module fnddecoder(
input [3:0] a, // input 4 bit
output reg [7:0] fnd // output -> dot 까지 표현을 위해 8 bit 출력
);
always @ (a) begin // a의 값이 변할 때만 다음 구문을 항상 반복한다
case (a) // input a가 입력된 경우
4'h0 : fnd = 8'h40; // 16진수 0을 출력에 8 bit 16진수 40에 할당
4'h1 : fnd = 8'h79;
4'h2 : fnd = 8'h24;
4'h3 : fnd = 8'h30;
4'h4 : fnd = 8'h19;
4'h5 : fnd = 8'h12;
4'h6 : fnd = 8'h02;
4'h7 : fnd = 8'h58;
4'h8 : fnd = 8'h00;
4'h9 : fnd = 8'h10;
4'ha : fnd = 8'h20;
4'hb : fnd = 8'h03;
4'hc : fnd = 8'h27;
4'hd : fnd = 8'h21;
4'he : fnd = 8'h04;
4'hf : fnd = 8'h0e;
default: fnd = 8'hff; // 이외의 조건은 default 값을 따른다
endcase
end
endmodule
`timescale 1ns / 1ps
module clock_divider_paramN #(parameter N = 50_000_000)(
input clk, //보드 내부 클럭 100MHz,이고 분주하면 50MHz-> 50,000,000 (100MHz는 1초당 1억번 -> 분주 시 5000만번)
input reset,
output reg clk1000Hz // 클럭 주기를 1000Hz로 설정
);
reg [25:0] cnt = 0; // 2^26승 이상일 때부터 50000만 이상 이므로 count는 26 bit 할당, 초기값 0 선언
always @(posedge clk, negedge reset) begin // 반복문을 positive edge와 negative edge의 값이 변화할 때 항상 반복을 시작
if (~reset) begin // if reset(활성화 상태)가 아니라면
cnt <= 0; // count는 0이다.
end else begin // ~reset인 상태가 아닌 이외의 상태일 때,
if (cnt == (N - 1)) begin // count가 4999번째 클럭이라면 그 다음 클럭에서
cnt <= 0; // count는 0으로 간다.
clk1000Hz <= ~clk1000Hz; // clk 주기를 다시 1000Hz로
end else begin
cnt <= cnt + 1; // 현재 count에서 1을 더한 값을 cnt에
end
end
end
endmodule
`timescale 1ns / 1ps
module top_controller2(
input clk, // counter clk
input reset, // counter input reset
input updown,
output [1:0] cnt_out,
output updown_out,
output [3:0] fndsel, // select에 따라 output FND 결정 (mux_4x1 output) // nbitAddSub 회로의 출력 hexout1과 hexout2가 inc와 ind의 입력으로 연결
output [7:0] fnd // FND output (FND Decoder output)
);
wire [3:0] w_outy4;
wire w_clkout;
wire [1:0] w_counter;
wire [3:0] w_datafnd;
wire [3:0] w_clk_out;
updowncnt U0(
.clk(w_clk_out),
.reset(reset),
.updown(updown),
.updown_out(updown_out),
.cnt_out(cnt_out)
);
counter U1(
.clkin(w_clkout),
.reset(reset),
.out_counter(w_counter)
);
clock_divider_paramN#(.N(50_000)) U2(
.clk(clk),
.reset(reset),
.clk1000Hz(w_clkout)
);
data_mux4x1 U3(
.ina(cnt_out),
.dmuxsel(w_counter),
.dmux_out(w_datafnd)
);
mux_4x1 U4(
.s(w_counter),
.y(fndsel)
);
fnddecoder U5(
.a(w_datafnd),
.fnd(fnd)
);
clock_divider_paramN#(.N(50_000_000)) U6(
.clk(clk),
.reset(reset),
.clk1000Hz(w_clk_out)
);
endmodule
## Clock signal
set_property -dict { PACKAGE_PIN W5 IOSTANDARD LVCMOS33 } [get_ports clk]
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk]
## Switches
set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports {reset}]
set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports {updown}]
## LEDs
set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports {updown_out}]
set_property -dict { PACKAGE_PIN E19 IOSTANDARD LVCMOS33 } [get_ports {cnt_out[0]}]
set_property -dict { PACKAGE_PIN U19 IOSTANDARD LVCMOS33 } [get_ports {cnt_out[1]}]
##7 Segment Display
set_property -dict { PACKAGE_PIN W7 IOSTANDARD LVCMOS33 } [get_ports {fnd[0]}]
set_property -dict { PACKAGE_PIN W6 IOSTANDARD LVCMOS33 } [get_ports {fnd[1]}]
set_property -dict { PACKAGE_PIN U8 IOSTANDARD LVCMOS33 } [get_ports {fnd[2]}]
set_property -dict { PACKAGE_PIN V8 IOSTANDARD LVCMOS33 } [get_ports {fnd[3]}]
set_property -dict { PACKAGE_PIN U5 IOSTANDARD LVCMOS33 } [get_ports {fnd[4]}]
set_property -dict { PACKAGE_PIN V5 IOSTANDARD LVCMOS33 } [get_ports {fnd[5]}]
set_property -dict { PACKAGE_PIN U7 IOSTANDARD LVCMOS33 } [get_ports {fnd[6]}]
set_property -dict { PACKAGE_PIN V7 IOSTANDARD LVCMOS33 } [get_ports fnd[7]]
set_property -dict { PACKAGE_PIN U2 IOSTANDARD LVCMOS33 } [get_ports {fndsel[0]}]
set_property -dict { PACKAGE_PIN U4 IOSTANDARD LVCMOS33 } [get_ports {fndsel[1]}]
set_property -dict { PACKAGE_PIN V4 IOSTANDARD LVCMOS33 } [get_ports {fndsel[2]}]
set_property -dict { PACKAGE_PIN W4 IOSTANDARD LVCMOS33 } [get_ports {fndsel[3]}]
'[Harman] 세미콘(semiconductor) 아카데미-반도체설계 > Verilog를 이용한 RTL 시스템 반도체 설계' 카테고리의 다른 글
교통신호등 제어기 설계 (0) | 2023.06.30 |
---|---|
리플 가산기 (0) | 2023.06.22 |
FND, 가산기, 감산기 (0) | 2023.06.16 |
FND&디코더 (0) | 2023.06.15 |
7-세그먼트 디코더, 크기 비교기 (0) | 2023.06.09 |