본문 바로가기
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