Language/Verilog & SV
[Verilog] APB의 State FSM, 간단한 Master Code
VIR&US
2023. 7. 21. 02:06
반응형
목차
APB란?
2023.07.20 - [Knowledge] - APB란? AMBA APB에 대해 알아보자
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 해보기
728x90
반응형