본문 바로가기
Language/Verilog & SV

[Verilog] APB의 State FSM, 간단한 Master Code

by VIR&US 2023. 7. 21.
반응형

목차

APB란?

2023.07.20 - [Knowledge] - APB란? AMBA APB에 대해 알아보자

 

APB란? AMBA APB에 대해 알아보자

*All photos and content in this article are copyrighted by Arm Ltd. This is a personal compilation for students and practitioners entering digital design. Content may be removed or modified at any time at the request of the copyright holder, Arm Ltd. Copyr

vir-us.tistory.com

APB에 대한 내용은 이전글을 참고바랍니다.

APB States

반응형

APB의 상태 FSM를 기반으로 구성한 간단한 Master

Slave가 없기때문에, PREADY는 1로 Tie하고 Simulation했습니다. 예시 코드입니다.

Code

module APB_master 
  	#(parameter 	PACKET_WIDTH = 64, 
			ADDR_WIDTH = 16, 
			DATA_WIDTH = 32) (
	 input CLK
    	,input RSTn
	//////////PACKET Dev///////////////////////////////
	//[PACKET_WIDTH - 1] = RW			///
	//[PACKET_WIDTH - 2] = Transfer enable		///
	//[ADDR_WHITH - 1:0] = ADDR			///
	//[DATA_WHITH + ADDR_WIDTH - 1:ADDR_WIDTH] = DATA//
	///////////////////////////////////////////////////
      	,input [PACKET_WIDTH - 1:0] PACKET
  	,input PREADY
  	,output PCLK
  	,output PRESETn
  	,output PSEL
    	,output PENABLE
  	,output PWRITE
      	,output [ADDR_WIDTH - 1:0] PADDR
      	,output [DATA_WIDTH - 1:0] PWDATA
      	,input [DATA_WIDTH - 1:0] PRDATA); 

	localparam IDLE = 2'b00;
	localparam SETUP = 2'b01;
	localparam ACCESS = 2'b10;

	reg [1:0] cur_state;
	reg [1:0] next_state;
	
	always@ (posedge PCLK, negedge PRESETn) begin
		if(PRESETn == 1'b0) begin
			cur_state <= IDLE;
		end
		else begin
			cur_state <= next_state;
		end
	end

	always@ (*) begin
		case(cur_state)
			IDLE:
			begin
			if(PACKET[PACKET_WIDTH - 2] == 1'b1)begin
				next_state <= SETUP;
			end
			else begin
				next_state <= IDLE;
			end
            		end
			SETUP:
			begin
				next_state <= ACCESS;
			end
			ACCESS:
			begin
			if(PREADY == 1'b0) begin
				next_state <= ACCESS;
			end
			else if(PACKET[PACKET_WIDTH - 2] == 1'b1) begin
				next_state <= SETUP;
			end
			else begin
				next_state <= IDLE;
			end
            		end
            		default:
              		begin
              			next_state <= IDLE;
              		end
		endcase
	end
	
	assign PCLK = CLK;
	assign PRESETn = RSTn;
	assign PSEL = (cur_state == IDLE) ? 1'b0 : 1'b1;
	assign PENABLE = (cur_state == ACCESS) ? 1'b1 : 1'b0;
  	assign PWRITE = (cur_state == IDLE) ? 1'b0 : PACKET[PACKET_WIDTH - 1];
  	assign PADDR = (cur_state == IDLE) ? 0 : PACKET[ADDR_WIDTH - 1:0];
  	assign PWDATA = (cur_state == IDLE) ? 0 : PACKET[DATA_WIDTH + ADDR_WIDTH - 1:ADDR_WIDTH];

endmodule

 

TB

`timescale 1ns/1ns
`define start_dly 5
`define clk_dly 10

module tb
  	#(parameter 	PACKET_WIDTH = 64, 
			ADDR_WIDTH = 16, 
			DATA_WIDTH = 32);
	reg CLK_t;
	reg RSTn_t;
	//////////PACKET Dev///////////////////////////////
	//[PACKET_WIDTH - 1] = RW			///
	//[PACKET_WIDTH - 2] = Transfer enable		///
	//[ADDR_WHITH - 1:0] = ADDR			///
	//[DATA_WHITH + ADDR_WIDTH - 1:ADDR_WIDTH] = DATA//
	///////////////////////////////////////////////////
	reg [PACKET_WIDTH - 1:0] PACKET_t;
	reg PREADY_t;
	wire PCLK_t;
	wire PRESETn_t;
	wire PSEL_t;
	wire PENABLE_t;
	wire PWRITE_t;
	wire [ADDR_WIDTH - 1:0] PADDR_t;
	wire [DATA_WIDTH - 1:0] PWDATA_t;
	reg [DATA_WIDTH - 1:0] PRDATA_t;
        

	APB_master master (
	 .CLK		(CLK_t)
	,.RSTn	        (RSTn_t)	
	,.PACKET        (PACKET_t)
	,.PREADY        (PREADY_t)
	,.PCLK          (PCLK_t)
	,.PRESETn       (PRESETn_t)
	,.PSEL          (PSEL_t)
	,.PENABLE       (PENABLE_t)
	,.PWRITE        (PWRITE_t)
	,.PADDR         (PADDR_t)
	,.PWDATA        (PWDATA_t)
	,.PRDATA        (PRDATA_t));
        

	initial begin
	CLK_t <= 1'b0;
	#`start_dly;
	forever #(`clk_dly/2) CLK_t = ~CLK_t;
	end

	initial begin
		PREADY_t = 1'b1;
		RSTn_t = 1'b0;
		#`start_dly;
		RSTn_t = 1'b1;
		#(`clk_dly*2);
		PACKET_t = 64'b1100_0000_0000_0000_1010_1010_0101_0101_1010_1010_0101_0101_0000_0000_0000_0100;
		#(`clk_dly*2);
		PACKET_t = 64'b1100_0000_0000_0000_1111_1111_1111_1111_1111_1111_1111_1111_0000_0000_0000_1000;
		#(`clk_dly*2);
		PACKET_t = 64'b0000_0000_0000_0000_1111_1111_1111_1111_1111_1111_1111_1111_0000_0000_0000_1000;
		#(`clk_dly*2);
		PACKET_t = 64'b0100_0000_0000_0000_1111_1111_1111_1111_1111_1111_1111_1111_0000_0000_0000_1000;
		#(`clk_dly*2);
		PACKET_t = 64'b0000_0000_0000_0000_1111_1111_1111_1111_1111_1111_1111_1111_0000_0000_0000_1000;	
		#(`clk_dly*2);
		$finish;
	end

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars;
	end
endmodule

 

DUMP

EDA Playground에서 Simulation 해보기

 

EDA Playground

Edit, save, simulate, synthesize SystemVerilog, Verilog, VHDL and other HDLs from your web browser.

www.edaplayground.com

 

728x90
반응형

'Language > Verilog & SV' 카테고리의 다른 글

[Verilog] Frequency(Clock) Divider  (0) 2023.07.21
[Verilog] Counter  (0) 2023.07.21
[Verilog] Full-adder, Ripple-carry adder  (0) 2023.07.20
[Verilog] Clock generator  (0) 2023.07.20
[Verilog] Blocking(=) vs Nonblocking(<=)  (0) 2023.07.19
VIR&USTechBlog