복습
조합회로+플립플롭=카운터
조합회로와 플립플롭의 조합은 일반적으로 순차 회로의 기본 구조를 형성하며, 카운터는 이러한 순차 회로의 대표적인 예이다

module up_downcounter_p(
input clk, reset_p,
input up_down,
output reg [3:0] count);
always @(posedge clk or posedge reset_p)begin
if(reset_p)count = 0;
else begin
if(up_down)begin
count = count + 1;
end
else begin
count = count -1;
end
end
end
endmodule
(alway문 안에있는것이 복합적이지만 약간의 조합회로 역할, reg로 선언된 count가 플립플롭 역할)

덧셈기, pdt의 영향으로(캐리가 반영되기전) 결과전에 잠시 잘못된 값이 나옴

pdt시간보다 크게 클럭을 설정하면 클럭안에 동작이 완료되고 다음 클럭때 반영
RTL:register transfer level


상승엣지 사용 : cur, old (1,0)
하강엣지 사용 : cur, old (0,1)
상승 엣지 감지: (cur, old) = (1, 0)
cur = 1: 현재 클럭 상태가 높음
old = 0: 이전 클럭 상태가 낮았음
이 조합은 클럭이 낮은 상태에서 높은 상태로 변화했음을 나타낸다. 즉, 상승 엣지이다.
하강 엣지 감지: (cur, old) = (0, 1)
cur = 0: 현재 클럭 상태가 낮음
old = 1: 이전 클럭 상태가 높았음
이 조합은 클럭이 높은 상태에서 낮은 상태로 변화했음을 나타낸다. 즉, 하강 엣지이다.
edge_detector_p
module edge_detector_p(
input clk, reset_p,
input cp,
output p_edge, n_edge);
reg ff_cur, ff_old;
always @(posedge clk or posedge reset_p)begin
if(reset_p)begin
ff_cur<=0;
ff_old<=0;
end
else begin
ff_cur <= cp;
ff_old <= ff_cur;
end
end
assign p_edge = ({ff_cur, ff_old} == 2'b10) ? 1 : 0;
assign n_edge = ({ff_cur, ff_old} == 2'b01) ? 1 : 0;
endmodule
edge_detector_n
module edge_detector_n(
input clk, reset_p,
input cp,
output p_edge, n_edge);
reg ff_cur, ff_old;
always @(negedge clk or posedge reset_p)begin
if(reset_p)begin
ff_cur<=0;
ff_old<=0;
end
else begin
ff_cur <= cp;
ff_old <= ff_cur;
end
end
assign p_edge = ({ff_cur, ff_old} == 2'b10) ? 1 : 0;
assign n_edge = ({ff_cur, ff_old} == 2'b01) ? 1 : 0;
endmodule
edge_detector_n 결과

D플립플롭으로 레지스터 메모리 만들기
병렬입력 병렬출력
module register_8bit_n(
input [7:0] d,
input clk, reset_p, enable,
output reg [7:0] q);
always @(negedge clk or posedge reset_p)begin
if(reset_p) q = 0;
else if(enable) q = d;
end
endmodule

D플립플롭 겹쳐놓음

직입직출 : 입출력선이 1개씩, 비트를 쉬프트해서 1비트씩 보낼 수 있다

블럭킹, 넌블럭킹 주의
always문 안에는 블럭킹, 넌블럭킹 통일하는것이 좋다
module shift_register_SISO_n(
input clk, reset_p,
input d,
output q);
reg [3:0] siso_reg;
always @(negedge clk or posedge reset_p)begin
if(reset_p)siso_reg<=0;
else begin
siso_reg[3]<=d;
siso_reg[2]<=siso_reg[3];
siso_reg[1]<=siso_reg[2];
siso_reg[0]<=siso_reg[1];
end
end
assign q=siso_reg[0];
endmodule
쉬프트하는걸 결합연산자 사용으로 구현
module shift_register_SISO_n(
input clk, reset_p,
input d,
output q);
reg [3:0] siso_reg;
always @(negedge clk or posedge reset_p)begin
if(reset_p)siso_reg<=0;
else begin
siso_reg<={d, siso_reg[3:1]};
// siso_reg[3]<=d;
// siso_reg[2]<=siso_reg[3];
// siso_reg[1]<=siso_reg[2];
// siso_reg[0]<=siso_reg[1];
end
end
assign q=siso_reg[0];
endmodule
파라미터를 이용한 N비트 쉬프트 레지스터
우쉬프트 레지스터 (최하위비트부터 출력)
module shift_register_SISO_Nbit_n #(parameter N=8)(
input clk, reset_p,
input d,
output q);
reg [N-1:0] siso_reg;
always @(negedge clk or posedge reset_p)begin
if(reset_p)siso_reg<=0;
else begin
siso_reg<={d, siso_reg[N-1:1]};
// siso_reg[3]<=d;
// siso_reg[2]<=siso_reg[3];
// siso_reg[1]<=siso_reg[2];
// siso_reg[0]<=siso_reg[1];
end
end
assign q=siso_reg[0];
endmodule
시뮬레이션에서 d값에 1010을 준다면 1주고 10ns 실행 0주고 10ns실행 1주고 10ns실행 0주고 10ns
테스트벤치 사용해서 코드로 실행
이니셜값 시뮬레이션 최초값 설정
(대략적인 순서:테스트 벤치-인스턴스-입출력-이니셜 초기값-클락설정-이니셜 설정)
테스트벤치의 모듈 선언후 괄호안에 변수를 선언 하지 않는것은 외부와의 연결이 필요없는, 내부에서만 사용되는 변수들이기 때문이다(괄호안에 선언되는 변수들은 외부와의 통신을 위한 포트)
우쉬프트 테스트 벤치
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2024/07/15 11:24:03
// Design Name:
// Module Name: tb_shift_register_SISO_Nbit_n
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module tb_shift_register_SISO_Nbit_n();
reg clk, reset_p; //input값 reg로 선언
reg d;
wire q;
parameter data = 4'b1010; //입력해줄 값
shift_register_SISO_Nbit_n #(.N(4)) DUT( //DUT=design under test
.clk(clk), .reset_p(reset_p),
.d(d),
.q(q));
initial begin //초기 설정
clk=0;
reset_p=1;
d=data[0];
end
always #5 clk = ~clk; //#=time delay, 5ns, edit 1th code, 5ns=0 -> 5ns=1 =>10ns clk
//#은 시간지연, #뒤에 지연할 시간, 코드첫번째줄 설정된 시간 단위, 5ns마다 클락 변경 전체 10ns 주기
integer i; //for문에 쓸 i선언
initial begin
#10;
reset_p = 0;
for(i=0;i<4;i=i+1)begin
d=data[i]; #10;
end
// d = data[0]; #10;
// d = data[1]; #10;
// d = data[2]; #10;
// d = data[3]; #10;
// #40;
$finish; //시뮬레이션 종료
end
endmodule
직입직출 N비트 우쉬프트 테스트벤치
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2024/07/15 11:24:03
// Design Name:
// Module Name: tb_shift_register_SISO_Nbit_n
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module tb_shift_register_SISO_Nbit_n();
reg clk, reset_p;
reg d;
wire q;
parameter data = 8'b11010011;
shift_register_SISO_Nbit_n #(.N(8)) DUT( //DUT=design under test
.clk(clk), .reset_p(reset_p),
.d(d),
.q(q));
initial begin
clk=0;
reset_p=1;
d=data[0];
end
always #5 clk = ~clk; //#=time delay, 5ns, edit 1th code, 5ns=0 -> 5ns=1 =>10ns clk
integer i;
initial begin
#10;
reset_p = 0;
for(i=0;i<8;i=i+1)begin
d=data[i]; #10;
end
// d = data[0]; #10;
// d = data[1]; #10;
// d = data[2]; #10;
// d = data[3]; #10;
#70;
$finish;
end
endmodule
직입직출 N비트 우쉬프트 레지스터 결과


좌쉬프트 (최상위 비트부터 출력)
module shift_register_SISO_Nbit_msb_n #(parameter N=8)(
input clk, reset_p,
input d,
output q);
reg [N-1:0] siso_reg;
always @(negedge clk or posedge reset_p)begin
if(reset_p)siso_reg<=0;
else begin
siso_reg<={siso_reg[N-2:0], d}; //좌쉬프트 오버플로우로 최상위비트 버림
// siso_reg[3]<=d;
// siso_reg[2]<=siso_reg[3];
// siso_reg[1]<=siso_reg[2];
// siso_reg[0]<=siso_reg[1];
end
end
assign q=siso_reg[N-1];
endmodule
좌쉬프트 테스트벤치
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2024/07/15 14:08:46
// Design Name:
// Module Name: tb_shift_register_siso_nbit_msb_n
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module tb_shift_register_SISO_Nbit_msb_n();
reg clk, reset_p;
reg d;
wire q;
parameter data = 8'b11010011;
shift_register_SISO_Nbit_msb_n #(.N(8)) DUT( //DUT=design under test
.clk(clk), .reset_p(reset_p),
.d(d),
.q(q));
initial begin
clk=0;
reset_p=1;
d=data[7];
end
always #5 clk = ~clk; //#=time delay, 5ns, edit 1th code, 5ns=0 -> 5ns=1 =>10ns clk
integer i;
initial begin
#10;
reset_p = 0;
for(i=7;i>0;i=i-1)begin
d=data[i]; #10;
end
// d = data[0]; #10;
// d = data[1]; #10;
// d = data[2]; #10;
// d = data[3]; #10;
#80;
$finish;
end
endmodule




demux 이용, demux의 선택값이 주소값
8비트 레지스터 여러개를 8비트 데이터 버스에 연결(선이 너무 많아져서 데이터 버스에 연결), 3상 버퍼(3상 버퍼의 제어비트)를 이용하여 데이터 버스에 연결 또는 차단
module shift_register_SIPO_n(
input clk, reset_p,
input d,
input rd_en, //read enable
output [3:0] q);
reg [3:0] sipo_reg;
always @(negedge clk or posedge reset_p)begin
if(reset_p)sipo_reg<=0;
else begin
sipo_reg<={d, sipo_reg[3:1]};
end
end
assign q=rd_en ? 4'bz : sipo_reg; //re_en이 1이면 차단(임피던스)
//bufif0 {q[0], sipi_reg[0], rd_en);//3phase buffer
endmodule
N비트짜리 직입병출
module shift_register_SIPO_Nbit_n #(parameter N=8)(
input clk, reset_p,
input d,
input rd_en, //read enable
output [N-1:0] q);
reg [N-1:0] sipo_reg;
always @(negedge clk or posedge reset_p)begin
if(reset_p)sipo_reg<=0;
else begin
sipo_reg<={d, sipo_reg[N-1:1]};
end
end
assign q=rd_en ? 'bz : sipo_reg; //임피던스는 몇비트든지간에 모두 임피던스로 채워짐 때문에 따로 써줄필요없음 (문법적으로도 N으로 두지 못함)
//bufif0 {q[0], sipi_reg[0], rd_en);//3phase buffer
endmodule
N비트 직입병출 테스트벤치
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2024/07/15 15:26:39
// Design Name:
// Module Name: tb_shift_register_SIPO_Nbit_n
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module tb_shift_register_SIPO_Nbit_n();
reg clk, reset_p;
reg d;
reg rd_en;
wire [7:0] q;
parameter data = 8'b10100011;
shift_register_SIPO_Nbit_n #(.N(8)) DUT(clk, reset_p, d, rd_en, q);
initial begin
clk = 0;
reset_p = 1;
d = 0;
rd_en = 0;
end
always #5 clk = ~clk;
integer i;
initial begin
#10;
reset_p = 0; #10;
for(i=0; i<8; i=i+1)begin
d = data[i]; #10;
end
//#30;
$finish;
end
endmodule
결과

정해진 출력이 끝나고 30ns를 더 줬을때 마지막 입력인 1이 계속 쉬프트

rd_en 꺼놨다가 입력이 모두 들어오면 rd_en을 켜서 마지막에 출력
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2024/07/15 15:26:39
// Design Name:
// Module Name: tb_shift_register_SIPO_Nbit_n
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module tb_shift_register_SIPO_Nbit_n();
reg clk, reset_p;
reg d;
reg rd_en;
wire [7:0] q;
parameter data = 8'b10100011;
shift_register_SIPO_Nbit_n #(.N(8)) DUT(clk, reset_p, d, rd_en, q);
initial begin
clk = 0;
reset_p = 1;
d = data[0];
rd_en = 1;
end
always #5 clk = ~clk;
integer i;
initial begin
#10;
reset_p = 0; #10;
for(i=1; i<8; i=i+1)begin
#10; d = data[i];
end
rd_en=0; #1;
$finish;
end
endmodule

z:임피던스(연결이 끊어진 상태), x:unkown(출력이 2개연결되서 어떤게 출력될지 모르는 상태);레이싱상태

mux를 통해 병렬입력을 받을지 쉬프트할지 결정
shift_load`(1,0)이면 쉬프트, shift_load`(0,1)이면 병렬입력
module shift_register_PISO_n(
input clk, reset_p,
input [3:0] d,
input shift_load,
output q);
reg [3:0] piso_reg;
always @(negedge clk or posedge reset_p)begin
if(reset_p)piso_reg<=0;
else begin
if(shift_load)begin
piso_reg<={1'b0, piso_reg[3:1]};
end
else begin
piso_reg = d;
end
end
end
assign q=piso_reg[0];
endmodule
module shift_register_PISO_Nbit_n #(parameter N=8)(
input clk, reset_p,
input [N-1:0] d,
input shift_load,
output q);
reg [N-1:0] piso_reg;
always @(negedge clk or posedge reset_p)begin
if(reset_p)piso_reg<=0;
else begin
if(shift_load)begin
piso_reg<={1'b0, piso_reg[N-1:1]};
end
else begin
piso_reg = d;
end
end
end
assign q=piso_reg[0];
endmodule
module tb_shift_register_PISO_Nbit_n();
reg clk, reset_p;
reg [7:0] d;
reg shift_load;
wire q;
parameter data = 8'b10100011;
shift_register_PISO_Nbit_n #(.N(8)) DUT(clk, reset_p, d, shift_load, q);
initial begin
clk = 0;
reset_p = 1;
d = 0;
shift_load = 0;
end
always #5 clk = ~clk;
initial begin
#10;
reset_p = 0;
d=data;
#10;
shift_load = 1;
#70;
$finish;
end
endmodule
