# verilog => 설계를 지원하는 언어

=>추상화 -> 문자로 표현

 

1. 구조적 모델링

 

2. 연속할당 모델링

  • 조합회로 (verilog 연산자)
  • ==, &, !, ? 등등
  • wire 만 가능

 

3. 동작적 모델링 (추상적)

always @ (posedge clk or negedge rst) // 밑에 안쓴 변수가 clk이 된다.
begin
    if(!rst) begin
    end

    else begin
    end
end
 

posedge clk 를 사용하면 순차회로(F/F 존재)이다. 따라서 "<=" 를 사용해야한다.

 

ex) latch

always @ (d, en, ck)
begin
    if(en&ck)
      q<=d;
end
 

# assign 조합회로 "="

# always 조합회로 "="


# Flip-Flop

  • SIPO

한 clk이 들어올때 마다 data를 하나씩 받는다. clk 지연 기능도 존재하지만 병렬로 값이 나온다.

 

  • SISO : 주로 clk 지연 기능을 수행하기 위해 사용한다.

 

  • PISO

# MUX


# Counter


 

'Verilog' 카테고리의 다른 글

20230330 APB  (0) 2023.03.31
20230329 AXI  (0) 2023.03.31
20230328 Bus란 무엇인가  (0) 2023.03.31
20230327 두번째 발표 (CPU설계)  (0) 2023.03.31
20230325 주말 CPU  (0) 2023.03.31

 

 

 

apb_bridge와 apb_slave, ila의 port bit를 맞추어준다.

 

'Verilog' 카테고리의 다른 글

20230331 Verilog 총정리  (0) 2023.03.31
20230329 AXI  (0) 2023.03.31
20230328 Bus란 무엇인가  (0) 2023.03.31
20230327 두번째 발표 (CPU설계)  (0) 2023.03.31
20230325 주말 CPU  (0) 2023.03.31

 

 

 

debug 후에 밑에 for문을 계속 돌려서 연속적으로 trigger를 해주었다.

slot1의 Rdata는 버튼과 Led 슬라이드 스위치의 입력에 따라 출력이 달라지는 것을 볼 수 있었다.

 

Rvalid 가 1인 경우에만 데이터 값이 유효하기 때문에 중간에 0이 나올 수도 있다.

RREADY 신호는 master가 신호 받을 준비가 되어있다는 의미의 신호미여, RVALID는 slave가 '이 부분이 유효한 data야' 라는 의미로 보내는 신호이다.


# AXI

M : manager / S : subordinate

AWADDR(ADDR_WIDTH)-Manager : Transaction address

AWPROT(3)-Manager : Access attributes

AWVALID(1)-Manager : Valid indicator

AWREADY(1)-Subordinate : Ready indicator

 

WDATA(DATA_WIDTH)-Manager : Write data

WSTRB(DATA_WIDTH / 8)-Manager : Write data strobes

WVALID(1)-Manager : Valid indicator

WREADY(1)-Subordinate : Ready indicator

 

BRESP (BRESP_WIDTH)-Subordinate : Write response

BVALID (1)-Subordinate : Valid indicator

BREADY (1)-Manager : Ready indicator

////////////////////////////////////////////////////////////////////////////////////////

ARADDR (ADDR_WIDTH)-Manager : Transaction address

ARPROT (3)-Manager : Access attributes

ARVALID (1)-Manager : Valid indicator => 1일때 addr을 가져온다.

ARREADY (1)-Subordinate : Ready indicator

 

RDATA (DATA_WIDTH)-Subordinate : Read data

RRESP (RRESP_WIDTH)-Subordinate : Read response

RVALID (1)-Subordinate : Valid indicator

RREADY (1)-Manager : Ready indicator


# Write Mode

 

'Verilog' 카테고리의 다른 글

20230331 Verilog 총정리  (0) 2023.03.31
20230330 APB  (0) 2023.03.31
20230328 Bus란 무엇인가  (0) 2023.03.31
20230327 두번째 발표 (CPU설계)  (0) 2023.03.31
20230325 주말 CPU  (0) 2023.03.31

 

# Bus transfer

- AHB, ASB (rising edge to rising edge) : 하나 이상의 버스 사이클을 요구하는 Data read/write. 지정된 slave로부터 completion 응답을 이루어 질때까지.

• Bus masters

• On-chip memory blocks

• External memory blocks

• High-bandwidth peripherals with FIFO interfaces

• DMA slave peripherals

 

- APB (falling edge to falling edge) : 항상 two-bus-cycle을 요구한다.

• Simple register-mapped slave devices

• Very low power interface

• Grouping Narrow-bus peripherals to avoid loading the system bus


# AHB

AHB master : 한번에 하나의 master만이 bus를 사용할 수 있다.

 

AHB slave : 슬레이브는 주어진 어드레스 범위내에서 read/write동작을 수행한다. Slave는 데이터 전송에 대한 success, failure, waiting 상태에 대한 정보를 master에게 돌려 주어야 한다. (APB bridge는 가장 일반적인 형태의 AHB slave. 또한 다른 peripheral들도 AHB slave가 될 수 있다. 그러나 low Bandwidth peripheral들은 대체적으로 APB에 연결된다.)

 

AHB arbiter : arbiter는 한번에 하나의 master만이 bus를 사용하도록 권한을 부여 한다. 하나의 AHB는 하나의 arbiter를 갖는다.

 

AHB decoder : decoder는 전송하고자 하는 slave의 어드레스를 디코딩한다. 하나의 decoder가 모든 AHB상의 slave들을 디코딩 한다


# ASB

ASB는 APB보다는 상위 버스구조에 속하면서 high-performance system에서 요구하는 특징들을 지닌 bus이다.

 

ASB master, ASB slave, ASB decoder, ASB arbiter는 AHB의 특징과 동일

cf) 그러나 signal list와 bus동작방법은 차이를 보인다.


# APB

APB slave의 특징

- Unpipelined

- APB가 동작하지 않는 동안 전력 소비가 없다.

- Strobe 타이밍에 의한 디코딩 동작(Unclocked interface)


# AHB

 HSEL = HADDR의 상위 번지 [31:n]

 

Host(Master) / Slave

 


# APB

 


 

 

'Verilog' 카테고리의 다른 글

20230330 APB  (0) 2023.03.31
20230329 AXI  (0) 2023.03.31
20230327 두번째 발표 (CPU설계)  (0) 2023.03.31
20230325 주말 CPU  (0) 2023.03.31
20230324 CPU 설계  (0) 2023.03.24

 

 

'Verilog' 카테고리의 다른 글

20230329 AXI  (0) 2023.03.31
20230328 Bus란 무엇인가  (0) 2023.03.31
20230325 주말 CPU  (0) 2023.03.31
20230324 CPU 설계  (0) 2023.03.24
20230322 명령어 구조  (0) 2023.03.24

 

 
module cpu_top (clk100M, push_sw, seg_drv, an_sel);
parameter	BW = 16;
input				clk100M, push_sw;
output	[7:0]		seg_drv;	// muxed signal
output	[3:0]		an_sel;

reg [6:0]			seg_k;
reg [6:0]			seg_h;
reg [6:0]			seg_t;
reg [6:0]			seg_o;

//wire				ta, tb, td;
wire				clk;
wire				start;
wire	[7:0]		pc;
wire	[8:0]		addr_out;
wire	[BW-1:0]	data_out;
wire	[BW-1:0]	data_in;
wire	[2:0]		dr, sa, sb;
wire	[4:0]		fs;
wire				rw, mb, mw, mm, md;
wire				vflg, cflg, nflg, zflg;
wire	[BW-1:0]	r0_out;


//
ila_0 ILA (
.clk(clk),
.probe0(start),
.probe1(pc),
.probe2(addr_out),
.probe3(data_out),
.probe4(data_in),
.probe5(dr),
.probe6(sa),
.probe7(sb),
.probe8(fs),
.probe9(rw),
.probe10(mb),
.probe11(mw),
.probe12(mm),
.probe13(md),
.probe14(vflg),
.probe15(cflg),
.probe16(nflg),
.probe17(zflg),
.probe18(r0_out)
);


//up_control inst_up_control (.clk(clk), .start(s_start), .ta(ta), .sa(sa), .tb(tb), .sb(sb), .td(td), .dr(dr), 
up_control inst_up_control (.clk(clk), .start(start), .sa(sa), .sb(sb), .dr(dr), 
							.fs(fs), .pc(pc), .rw(rw), .mw(mw), .mb(mb), .md(md), .mm(mm), .data_in(data_in), 
							.vflg(vflg), .cflg(cflg), .nflg(nflg), .zflg(zflg));

//datapath_unit inst_datapath_unit (.clk(clk), .start(s_start), .ta(ta), .sa(sa), .tb(tb), .sb(sb), .td(td), .dr(dr), 
datapath_unit inst_datapath_unit (.clk(clk), .start(start), .sa(sa), .sb(sb), .dr(dr), 
								  .fs(fs), .pc(pc), .rw(rw), .mb(mb), .md(md), .mm(mm), .data_in(data_in), 
								  .vflg(vflg), .cflg(cflg), .nflg(nflg), .zflg(zflg), 
								  .data_out(data_out), .addr_out(addr_out), .r0_reg(r0_out));

//ram_512x16b inst_ram_512x16b (.address(addr_out), .clock(clk), .data(data_out), .wren(mw), .q(data_in));
ram_512x16b inst_ram_512x16b (.addra(addr_out), .clka(clk), .ena(1'b1), .dina(data_out), .wea(mw), .douta(data_in));
/*
cpu_debug u0 (
    .acq_data_in    ({mw, addr_out, data_out, data_in}),    //     tap.acq_data_in
    .acq_trigger_in (start), 		//        .acq_trigger_in
    .acq_clk        (clk)         	// acq_clk.clk
);
*/

misc_blk inst_misc_blk (push_sw, clk100M, r0_out, start, clk, seg_drv, an_sel);

endmodule
module misc_blk (push_sw, clk, din_h16, start, clk_50M, seg_drv, an_sel);
input				push_sw, clk;
input	[15:0]		din_h16;	
output				start, clk_50M;
output	[7:0]		seg_drv;	
output reg [3:0]	an_sel;		

wire				clk200;
reg		[23:0]		tm_cnt, por_cnt;
reg					t_start, start;
reg					pwr_on;

reg		[6:0]		seg_o;
reg		[6:0]		seg_t;
reg		[6:0]		seg_h;
reg		[6:0]		seg_k;

reg		[1:0]		cnt_fnd;


//clk_50MHz
//freq_div #(27'd0) freq_50MHz (push_sw, clk, clk_50M);
clk_50m_gen u1 (.clk_out1(clk_50M), .clk_in1(clk));

//clk_200Hz
freq_div #(27'd124_999) freq_200Hz (push_sw, clk_50M, clk200);

always @(posedge clk_50M)
begin
	if (por_cnt!=24'hFF_FFFF) begin
		por_cnt <= por_cnt+1'b1;
		pwr_on <= 1'b0;
	end
	else
		pwr_on <= 1'b1;
end

always @(posedge clk_50M, posedge push_sw)
begin
	if (push_sw)
		tm_cnt <= 24'b0;
	else if (tm_cnt!=24'h7F_FFFF)
		tm_cnt <= tm_cnt+1'b1;
end

always @(posedge clk_50M, negedge pwr_on)
begin
	if (!pwr_on) 
		start <= 1'b0;
	else if (tm_cnt==24'b0)
		start <= 1'b0;
	else if (tm_cnt==24'h4C_4B3F)	//0.1s
			start <= 1'b1;
end

always @(posedge clk200)
	cnt_fnd <= cnt_fnd+1'b1;

mux4x1 #(7) seg_mux (cnt_fnd, seg_o, seg_t, seg_h, seg_k, seg_drv[6:0]);

assign seg_drv[7] = 1'b1;

always @(start, cnt_fnd)
begin
	an_sel = 4'b1111;
	if (start)
		case(cnt_fnd)
			2'h0 	: an_sel = 4'b1110;
			2'h1 	: an_sel = 4'b1101;
			2'h2 	: an_sel = 4'b1011;
			//2'h3 	: an_sel = 4'b0111;
			default	: an_sel = 4'b0111;
		endcase
end

always @(din_h16)
begin
	seg_o = h2disp(din_h16[3:0]);
	seg_t = h2disp(din_h16[7:4]);
	seg_h = h2disp(din_h16[11:8]);
	seg_k = h2disp(din_h16[15:12]);
end

//hex-to-7segment
function [6:0] h2disp;
input	[3:0]	din;
begin
	case (din)
		4'h0 : h2disp = 7'h01;
		4'h1 : h2disp = 7'h4F;
		4'h2 : h2disp = 7'h12;
		4'h3 : h2disp = 7'h06;
		4'h4 : h2disp = 7'h4C;
		4'h5 : h2disp = 7'h24;
		4'h6 : h2disp = 7'h20;
		4'h7 : h2disp = 7'h0D;
		4'h8 : h2disp = 7'h00;
		4'h9 : h2disp = 7'h04;
		4'hA : h2disp = 7'h08;
		4'hB : h2disp = 7'h60;
		4'hC : h2disp = 7'h31;
		4'hD : h2disp = 7'h42;
		4'hE : h2disp = 7'h30;
		default : h2disp = 7'h38;
	endcase
end
endfunction

endmodule

// freq_div
module freq_div (rst, clk, clk_o);
parameter		DIV_CNT = 49_999_999;
input			rst, clk;
output	reg 	clk_o;
reg     [26:0]  clk_div;			// 

always @ (posedge clk, posedge rst)
begin
	if (rst) begin
		clk_div <= 26'b0;
		clk_o <= 1'b1;			// to correct 1'st period
	end
	else if (clk_div==DIV_CNT) 
	begin
	   clk_div <= 28'h0;
	   clk_o <= ~clk_o;
	end
	else begin
		clk_div <= clk_div+1'b1;
	end
end
endmodule

// mux4x1 
module mux4x1 (sel, d0, d1, d2, d3, m_out);
parameter	BW = 8;
input	[1:0]		sel;
input	[BW-1:0]	d0, d1, d2, d3;
output	[BW-1:0]	m_out;

assign m_out = (sel[1]) ? ((sel[0] ? d3: d2)) : ((sel[0] ?d1 : d0));

endmodule

'Verilog' 카테고리의 다른 글

20230328 Bus란 무엇인가  (0) 2023.03.31
20230327 두번째 발표 (CPU설계)  (0) 2023.03.31
20230324 CPU 설계  (0) 2023.03.24
20230322 명령어 구조  (0) 2023.03.24
20230321 CPU 설계 (control)  (0) 2023.03.24

■ Datapath 설계

module datapath_unit (clk, start, rw,  sa, sb, dr, fs, pc, mb, md, mm, data_in, vflg, cflg, nflg, zflg, data_out, addr_out);
parameter BW = 16;
input               clk, start, rw;
input   [2:0]       sa, sb, dr;
input   [4:0]       fs;
input   [7:0]       pc; // 9비트여야 하니깐 나중에 결합연산자로 0을 넣어
input               mb, md, mm;
input   [BW-1:0]    data_in;

output  reg         vflg, cflg, nflg, zflg;
output  wire [BW-1:0]    data_out;
output  wire [9:0]       addr_out;

wire    [BW-1:0]	opra, oprb, r_oprb;
wire 	[BW-1:0]	r_din;
wire	[BW-1:0]	din;
wire				s_vflg, s_cflg, s_nflg, s_zflg;

register_file R1 (.clk(clk), .st(start), .rw(rw), .sel_sa(sa), .sel_sb(sb), .sel_d(dr), .din(din), .opra(opra), .oprb(r_oprb));

func_unit F1 (.opra(opra), .oprb(oprb), .sa(sa), .fs(fs), .f_out(r_din), .v_flag(s_vflg), .c_flag(s_cflg), .n_flag(s_nflg), .z_flag(s_zflg));

always @(posedge clk)
begin
	if (start==1'b0) begin
		vflg <= 1'b0;
		cflg <= 1'b0;
		nflg <= 1'b0;
		zflg <= 1'b0;
	end
	else if (rw) begin
		vflg <= s_vflg;
		cflg <= s_cflg;
		nflg <= s_nflg;
		zflg <= s_zflg;
	end
end

assign  oprb = (mb) ? {13'b0, sb} : r_oprb;
assign  data_out = oprb;
assign  addr_out = (mm) ? {1'b0, pc} : opra[8:0];
assign  din = (md) ? data_in : r_din;

endmodule

 

 

 

module tb_datapath;

reg clk=1'b1, start, rw;
reg [2:0] sa, sb, dr;
reg mb, md, mm;
reg [15:0] data_in;
reg [4:0] fs;
reg [7:0] pc;

wire vflg, cflg, nflg, zflg;
wire [15:0] data_out;
wire [8:0] addr_out;

always #100 clk = ~clk;

datapath_unit D1 (clk, start, rw,  sa, sb, dr, fs, pc, mb, md, mm, data_in, vflg, cflg, nflg, zflg, data_out, addr_out);


initial
begin
           start = 1'b0; 
    #40    start = 1'b1;
    #40    sa = 3'b101; sb = 3'b111; data_in = 16'b1100_0011_1100_0011; fs = 5'b00000; mb =1'b0;  rw = 1'b1; md = 1'b1; dr = 3'b111;
    #230                                                                                                                dr = 3'b101;
    #230   md = 1'b0;
    #230   dr = 3'b011;
    #230   dr = 3'b100;
    #230   dr = 3'b101;
    #230   dr = 3'b110;
    #230   dr = 3'b111;
    #230   fs = 5'b00000;
    #230   fs = 5'b00001;
    #230   fs = 5'b00010;
    #230   fs = 5'b00011;
    #230   fs = 5'b00100;
    #230   fs = 5'b00101;
    #230   fs = 5'b00111;
    #230   fs = 5'b01000;
    #230   fs = 5'b01010;
    #230   fs = 5'b01100;
    #230   fs = 5'b01110;
    #230   fs = 5'b10000;
    #230   fs = 5'b10010;
    #230   fs = 5'b10100;
    #230   fs = 5'b10110;
    #230   fs = 5'b11000;
    #230   fs = 5'b11010;
    #230   fs = 5'b11100;
    #230   fs = 5'b11100;
    #230   fs = 5'b11111;
    #230   fs = 5'b11111;
    #200;
    $stop;
//           start = 1'b0; 
//    #40    start = 1'b1;
//    #40  sa = 3'b101; sb = 3'b111; data_in = 16'b1100_0011_1100_0011; fs = 5'b00000; mb =1'b0;  rw = 1'b1; md = 1'b1; dr = 3'b111;
//    #80;
//    $stop;
end
endmodule

 

 

 

 


■up control 설계

 

module up_control (clk, start, sa, sb, dr, fs, pc, rw, mw, mb, md, mm, data_in, vflg, cflg, nflg, zflg);
parameter	BW = 16;
parameter	S_ADDR = 8'h0;
parameter	IF_ADDR = 8'hFE;

input						clk, start;
//output						ta, tb, td;
output	reg	[2:0]			sa, sb, dr;
output	reg		[4:0]		fs;
output	wire	[7:0]		pc;				//512-words LPM_RAM_DQ 

output	reg				rw, mw, mb, md, mm;
input			[BW-1:0]	data_in;
input						vflg, cflg, nflg, zflg;

wire						ta, tb, td;

reg				[6:0]		ir_ca_opr;

wire			[27:0]		cm_out;

reg							pc_ctrl;

reg						    pl;
reg						    pi;
reg							il;
reg							mc;
reg				[2:0]		ms;
reg				[7:0]		na;

reg				[7:0]		t_pc;
reg				[7:0]		s_pc;

reg				[7:0]		t_ca_reg;
reg				[7:0]		s_ca_reg;
wire			[7:0]		ca_reg;

always @(start, pc_ctrl, pl, pi, s_pc, dr[1:0], sa, sb, t_pc)
begin
	if (!start) 
		t_pc = S_ADDR;
	else if (pl) begin
		if (pc_ctrl) begin
			if (pi)
				t_pc = s_pc+{dr[1:0],sa,sb};
			else
				t_pc = {dr[1:0],sa,sb};
		end
		else
			t_pc = s_pc;
	end
	else
		t_pc = s_pc + pi;
end

always @(posedge clk, negedge start)
begin
	if (!start) 
		s_pc <= 8'b0;
	else if (pl | pi)
		s_pc <= t_pc;
end

assign pc = t_pc;//s_pc;//

always @(posedge clk, negedge start)
begin
	if (!start) begin
		sb <= 3'b0;
		sa <= 3'b0;
		dr <= 3'b0;
	end
	else if (il) begin
		sb <= data_in[2:0];
		sa <= data_in[5:3];
		dr <= data_in[8:6];
	end
end

always @(data_in[15:9])
begin
	ir_ca_opr = data_in[15:9];
end

always @(posedge clk, negedge start)
begin
	if (!start)
		pc_ctrl <= 1'b0;
	else begin
		case (ms)
			3'h0 : pc_ctrl <= 1'b0;
			3'h1 : pc_ctrl <= 1'b1;
			3'h2 : pc_ctrl <= cflg;
			3'h3 : pc_ctrl <= vflg;
			3'h4 : pc_ctrl <= zflg;
			3'h5 : pc_ctrl <= nflg;
			3'h6 : pc_ctrl <= ~cflg;
			default : pc_ctrl = ~zflg;	//3'h7
		endcase
	end
end

always @(start ,mc, ir_ca_opr, na)
begin
	if (!start) 
		t_ca_reg = IF_ADDR;
	else begin
		if (mc==1'b1)
			t_ca_reg = {1'b0,ir_ca_opr};
		else
			t_ca_reg = na;
	end
end

assign ca_reg = t_ca_reg;

//ram_256x28b inst_ram_256x28b (.address(ca_reg), .clock(clk), .data(28'b0), .wren(1'b0), .q(cm_out)); 
rom_28x256b inst_rom_28x256b (.clka(clk), .ena(1'b1), .addra(ca_reg), .douta(cm_out)); 

/*
rw, mw, mb, md, mm;
assign mw = start & cm_out[0];
assign mm = start & cm_out[1];
assign rw = start & cm_out[2];
assign md = start & cm_out[3];
assign mb = start & cm_out[9];
assign fs = {5{start}} & cm_out[8:4];
*/
	
assign tb = start & cm_out[10];
assign ta = start & cm_out[11];
assign td = start & cm_out[12];

always @(posedge clk, negedge start)
begin
	if (!start) begin
		il <= 1'b0;
		pl <= 1'b0;
		pi <= 1'b0;
		fs <= 5'b0;
//		mw <= 1'b0;
	    rw <= 1'b0;
//	    mm <= 1'b0;
	    md <= 1'b0;
	    mb <= 1'b0;		
		//ms <= 3'b0;
	end
	else begin
		il <= cm_out[15];
		pl <= cm_out[13];
		pi <= cm_out[14];		
		fs <= cm_out[8:4];		
		
//		mw <= cm_out[0];
	    rw <= cm_out[2];
//	    mm <= cm_out[1];
		md <= cm_out[3];
		mb <= cm_out[9];	
		//ms <= cm_out[19:17];		
	end
end


always @(start, cm_out[27:16])
begin
	if (!start) begin
		mc = 1'b0;
		ms = 3'b0;
		na = 8'b0;
		mw = 1'b0;
	    //rw = 1'b0;		
	    mm = 1'b0;
	    //md = 1'b0;
	    //mb = 1'b0;			
	end
	else begin
		mc = cm_out[16];
		ms = cm_out[19:17];
		na = cm_out[27:20];
		mw = cm_out[0];
	    //rw = cm_out[2];		
	    mm = cm_out[1];
		//md = cm_out[3];
		//mb = cm_out[9];		
	end
end


endmodule

 


■CPU 설계

 

`timescale 1ns / 1ps

module cpu(clk, start);
input   clk;
input   start;

wire    [2:0]   sa, sb, dr;
wire    [4:0]   fs;
wire    [7:0]   pc;
wire            rw, mw, mb, md, mm;
wire            vflg, cflg, nflg, zflg;
wire    [15:0]  data_in, data_out;
wire    [8:0]   addr_out;
wire            r0_reg;


up_control up1 (clk, start, sa, sb, dr, fs, pc, rw, mw, mb, md, mm, data_in, vflg, cflg, nflg, zflg);
datapath_unit dp1 (clk, start, rw,  sa, sb, dr, fs, pc, mb, md, mm, data_in, vflg, cflg, nflg, zflg, data_out, addr_out, r0_reg);

ram_512x16b inst_ram_512x16b (.clka(clk), .ena(1'b1), .wea(mw), .addra(addr_out), .dina(data_out), .douta(data_in));

endmodule

 

 

 

'Verilog' 카테고리의 다른 글

20230327 두번째 발표 (CPU설계)  (0) 2023.03.31
20230325 주말 CPU  (0) 2023.03.31
20230322 명령어 구조  (0) 2023.03.24
20230321 CPU 설계 (control)  (0) 2023.03.24
20230320 CPU 설계 (Data Path)  (0) 2023.03.20

 

■ shifter 설계

module	mux_16	(sel, d_in, d_out);
parameter	BW = 16;
input	[3:0]		sel;
input	[BW-1:0]	d_in;
output				d_out;

assign	d_out = d_in[sel];

endmodule

////////////////////////////////////////////////////////////////////////////////////


module shifter (oprb, sel, br_num, s_out);
parameter	BW = 16;
parameter	MVB = 3'b000, LSL = 3'b001, LSR = 3'b010, ASR = 3'b011;
parameter	RL = 3'b100, RR = 3'b101, BRR = 3'b110, BRL = 3'b111;
input			[3:0]			br_num;
input			[2:0]			sel;
input			[BW-1:0]		oprb;
output  wire	[BW-1:0]		s_out;

wire			[3:0]			t_br_num;

reg		   		[2*BW-2:0]  	temp;   // s_oprb
reg				[3:0]			s_br_num;
reg								u2s;	

genvar i;


	for(i=0; i < BW; i=i+1)
		always @ (*)
		begin
			case(sel)
			
			LSL: begin temp	={oprb[14:0],    16'b0}		; s_br_num=4'h1;	u2s=1'b1; end
			LSR: begin temp	={15'b0,   		 oprb[15:0]}; s_br_num=4'h1;	u2s=1'b0; end
			ASR: begin temp	={{15{oprb[15]}},oprb[15:0]}; s_br_num=4'h1;	u2s=1'b0; end
			RL : begin temp	={oprb[14:0],    oprb[15:0]}; s_br_num=4'h1;	u2s=1'b1; end
			RR : begin temp	={oprb[14:0],    oprb[15:0]}; s_br_num=4'h1;	u2s=1'b0; end
			BRR: begin temp	={oprb[14:0],    oprb[15:0]}; s_br_num=br_num;  u2s=1'b0; end
			BRL: begin temp	={oprb[14:0],    oprb[15:0]}; s_br_num=br_num;  u2s=1'b1; end
			default : begin temp	={oprb[14:0],    oprb[15:0]}; s_br_num=4'h0;	u2s=1'b0; end
	
			endcase
		end
		
u2s_comp #(BW) inst_u2s_comp (u2s, s_br_num, t_br_num);

generate
	for(i=0; i < BW; i=i+1) begin : br_gen
		mux_16 mux1 (t_br_num, temp[i+BW-1:i], s_out[i]);
	end
endgenerate

endmodule


////////////////////////////////////////////////////////////////////////////////////////////////////////

module u2s_comp (u2s, din, dout);
parameter		BW = 4;
input							u2s;
input			[BW-1:0]		din;
output	wire	[BW-1:0]		dout;

wire	[BW-1:0]	inv_flag;

genvar i;

assign inv_flag[0] = 1'b0;
generate 
	for (i=1;i<BW;i=i+1) begin : or_gen
		assign inv_flag[i] = (din[i-1]|inv_flag[i-1]) & u2s;
	end
endgenerate

assign dout = inv_flag ^ din;

endmodule

 

 
 
.

 

■ ALU 설계

module ALU (opra, oprb, sel, v_flag, c_flag, n_flag, z_flag, g_out, c_in);
parameter	BW = 16;
input	[BW-1:0]	opra, oprb;
input	[2:0]		sel;
output	          	v_flag, c_flag, n_flag, z_flag;
input              c_in;
output 	[BW-1:0]	g_out;	
wire	[BW-1:0]	sum;
wire	[BW-1:0]	dout;
wire 	[1:0]		t_cout;

assign	g_out = (sel[2]) ? dout : sum;

func_logic L1 (opra, oprb, sel[1:0], dout);
func_arith A1 (opra, oprb, sel[1:0], c_in, sum, t_cout);

assign v_flag = ^(t_cout);
assign c_flag = t_cout[1];
assign  n_flag = g_out[BW-1];     
assign  z_flag = ~(|g_out);


endmodule

 

 

 

 


 

■ function_unit 설계

 

module func_unit (
input	    [BW-1:0]	opra, oprb,
input       [2:0]       sa,
input       [4:0]       fs,
output reg	[BW-1:0] 	f_out,
output 				    v_flag, c_flag, n_flag, z_flag);

parameter	BW = 16;

wire	[3:0]	     sel;
wire	[3:0]	     sel;
wire    [BW-1:0]    s_out, g_out;

shifter S1 (oprb, fs[3:1], {fs[0],sa[2:0]}, s_out);
ALU A1 (opra, oprb, fs[3:1], v_flag, c_flag, n_flag, z_flag, g_out, fs[0]);

always @ (*)
begin
	if (fs[4]==0)
		 f_out = g_out;
	else
		 f_out = s_out;
end

endmodule

///////////////////////////////////////////////////////////////////////////////////
module TB_func_unit;

reg [4:0] fs;
reg [15:0] a, b;
reg ir, il;
reg [2:0] sa;
wire [15:0] d;
wire v_flag, c_flag, n_flag, z_flag;

func_unit FU1 (.opra(a), .oprb(b), .fs(fs), .sa(sa), .f_out(d), .v_flag(v_flag), .c_flag(c_flag), .n_flag(n_flag), .z_flag(z_flag));

initial begin
            fs=5'b00000;    a=16'b0100001000100101; b=16'b1011110111011010; ir=1'b0;    il=1'b0;    sa=3'b011; 
    #100    fs=5'b00001;
    #100    fs=5'b00010;
    #100    fs=5'b00011;
    #100    fs=5'b00100;
    #100    fs=5'b00101;
    #100    fs=5'b00110;
    #100    fs=5'b00111;
    #100    fs=5'b01000;
    #100    fs=5'b01010;
    #100    fs=5'b01100;
    #100    fs=5'b01110;
    #100    fs=5'b10000;
    #100    fs=5'b10010;
    #100    fs=5'b10100;
    #100    fs=5'b10110;
    #100    fs=5'b11000;
    #100    fs=5'b11010;
    #100    fs=5'b11100;
    #100    fs=5'b11110;
    #100;
    $stop;
end
endmodule

 


■ register file 설계

module dec_3to8(
input                   en,
input       [2:0]       sel,
output reg  [7:0]       dec_out
);

always  @ (en, sel)
begin
    if (en)
        case(sel)
            3'h1 : dec_out = 8'h02;
            3'h2 : dec_out = 8'h04;
            3'h3 : dec_out = 8'h08;
            3'h4 : dec_out = 8'h10;
            3'h5 : dec_out = 8'h20;
            3'h6 : dec_out = 8'h40;
            3'h7 : dec_out = 8'h80;
            default  : dec_out = 8'h00;
            
        endcase 
    else
        dec_out = 8'h0;

end

endmodule 

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

module univ_sr
# (parameter N=16)(   
input   wire             clk, rst,
input   wire             sel,
input   wire    [N-1:0]  d,
output  wire    [N-1:0]  q
);
reg [N-1:0] r_reg, r_next;

assign  q = r_reg;
always @   (posedge rst or posedge clk)
    if(rst) r_reg <= 0;
    else r_reg <= r_next;
    
always @ (*)
    case(sel)
        1'b0 : r_next = r_reg; //hold
        default : r_next = d;
    endcase
endmodule  
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

module mux_8 (sel, d0, d1, d2, d3, d4, d5, d6, d7, d_out);
parameter BW = 16;
input [2:0] sel;
input [BW-1:0]  d0, d1, d2, d3, d4, d5, d6, d7;
output reg [BW-1:0] d_out;

always  @ (*)
    case(sel)
        3'b000 : d_out = d0;
        3'b001 : d_out = d1;
        3'b010 : d_out = d2;
        3'b011 : d_out = d3;
        3'b100 : d_out = d4;
        3'b101 : d_out = d5;
        3'b110 : d_out = d6;
        default  : d_out = d7;
     endcase 
endmodule 
        
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

module register_file (clk, st, rw, sel_sa, sel_sb, sel_d, din, opra, oprb);
parameter BW = 16;
input               clk, st, rw;
input   [2:0]       sel_sa, sel_sb, sel_d;
input   [BW-1:0]    din;
output  [BW-1:0]    opra, oprb;

wire    [BW-1:0]    d_out;
wire    [BW-1:0]    r0, r1, r2, r3, r4, r5, r6, r7;

dec_3to8  D1 (.en(rw), .sel(sel_d), .dec_out(d_out));

univ_sr  R0 (.clk(clk), .rst(st), .sel(d_out[0]), .d(din), .q(r0));
univ_sr  R1 (.clk(clk), .rst(st), .sel(d_out[1]), .d(din), .q(r1)); 
univ_sr  R2 (.clk(clk), .rst(st), .sel(d_out[2]), .d(din), .q(r2)); 
univ_sr  R3 (.clk(clk), .rst(st), .sel(d_out[3]), .d(din), .q(r3)); 
univ_sr  R4 (.clk(clk), .rst(st), .sel(d_out[4]), .d(din), .q(r4)); 
univ_sr  R5 (.clk(clk), .rst(st), .sel(d_out[5]), .d(din), .q(r5)); 
univ_sr  R6 (.clk(clk), .rst(st), .sel(d_out[6]), .d(din), .q(r6)); 
univ_sr  R7 (.clk(clk), .rst(st), .sel(d_out[7]), .d(din), .q(r7));

mux_8 ma (.sel(sel_sa), .d0(r0), .d1(r1), .d2(r2), .d3(r3), .d4(r4), .d5(r5), .d6(r6), .d7(r7), .d_out(opra));
mux_8 mb (.sel(sel_sb), .d0(r0), .d1(r1), .d2(r2), .d3(r3), .d4(r4), .d5(r5), .d6(r6), .d7(r7), .d_out(oprb));

endmodule 

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
module TB_reg_file;

reg clk=1'b0, st, rw;
reg [2:0] sel_sa, sel_sb, sel_d;
reg [15:0] din;
wire [15:0]opra, oprb;

always #50 clk = ~clk;

register_file  R1 (clk, st, rw, sel_sa, sel_sb, sel_d, din, opra, oprb);

initial begin

         sel_sa = 3'b000;   sel_sb = 3'b000;   sel_d = 3'b011;
         st = 1'b1;
            din=16'b0100001000100101;
         rw =1'b0;   st = 1'b0;
   #100   rw =1'b1; //Write Mode on
    #100    rw = 1'b0; // Write Mode off
    #100    sel_sa = 3'b101; //choose oprA Reg5
   #100   sel_sb = 3'b011; //choose oprB Reg3
   #100   din=16'hffff; // change Data
   #500;
   #100   rw =1'b1; //Write Mode on
    #100    rw = 1'b0; // Write Mode off
   #100   din=16'hcdea; // change Data
    #100    sel_d = 3'b010; //change D Add Reg2
   #100   rw =1'b1; //Write Mode on
    #300    rw = 1'b0; // Write Mode off
   #100   sel_sb = 3'b010; //choose oprB Reg2
    #100    sel_sa = 3'b011; //choose oprA Reg3
    #100    st = 1'b1;
    #100    st = 1'b0;
    #500;
    $stop;
end   
endmodule

 

 

 

 

 

+ Recent posts