AXI4 Master Interfaceモジュールの作製1(仕様の検討)
AXI4 Master Interfaceモジュールの作製2(シミュレーション)
AXI4 Master Interfaceモジュールの作製3(シミュレーション2)
AXI4 Master Interfaceモジュールの作製4(axi4_master_inf.v のHDLソース)
AXI4 Master Interfaceモジュールの作製5(Write用FIFOのXCO)
AXI4 Master Interfaceモジュールの作製6(Read用FIFOのXCO)
/* * drawn_disp.c * * Created on: 2012/08/23 * Author: Masaaki */
// char_draw: アドレスとキャラクタコードを受け取ってそのキャラクタを描画する
// addr : 描画するキャラクタのスタートアドレス
// char_code : 描画するキャラクタのコード
// char_color : 描画するキャラクタのカラー、32ビットで表される、0RGBと8ビットずつで表す
// 戻り値:次のキャラクタの描画先頭アドレスを示す。
unsigned int *char_draw(unsigned int *addr, unsigned char char_code, unsigned int char_color){
int i,j;
unsigned int char_pattern;
unsigned int char_code_int;
unsigned int *cal_char_addr;
unsigned int *return_addr;
char_code_int = (unsigned int)(char_code);
return_addr = addr + 8;
cal_char_addr = 0x7f800000+((char_code_int<<3)<<2); // キャラジェネROMのデータは32ビット幅で下の8ビットだけ有効
for(i=0; i<8; i++){
char_pattern = *(volatile unsigned int *)(cal_char_addr); // キャラクタのパターンを読み出し
for(j=0; j<8; j++){
if(char_pattern & 0x1) // 7ビット目が1の時はドットを描画
*(volatile unsigned int *)((unsigned int)addr ^ 4) = char_color;
else
*(volatile unsigned int *)((unsigned int)addr ^ 4) = 0; // 黒を描画
addr++;
char_pattern >>= 1; // キャラクタのパターンを1ビット右シフト
}
addr -= 8; // 行の最初のアドレスに戻す
addr += 640; // アドレスを1行下にする
cal_char_addr++;
}
return return_addr;
}
int main()
{
unsigned char char_code;
unsigned int * ddr2_addr;
unsigned int coler_code;
unsigned int char_cnt;
int i, j;
for (ddr2_addr=0x20000000; ddr2_addr<0x2012C000; ddr2_addr++){
*(volatile unsigned int *)((unsigned int)ddr2_addr ^ 4) = 0;
}
ddr2_addr = 0x20000000;
char_cnt = 0;
for(j=0; j<8; j++){
for(i=1; i<8; i++){
switch(i){
case 1 :
coler_code = 0xff;
break;
case 2 :
coler_code = 0xff00;
break;
case 3 :
coler_code = 0xffff;
break;
case 4 :
coler_code = 0xff0000;
break;
case 5 :
coler_code = 0xff00ff;
break;
case 6 :
coler_code = 0xffff00;
break;
case 7 :
coler_code = 0xffffff;
}
for(char_code=0x21; char_code<0x80; char_code++){
if(char_code >= 0x80) // キャラクタコードが上限に達したら、一番下に戻す
char_code = 0x21;
if (char_cnt!=0 && char_cnt%80==0)
ddr2_addr = (unsigned int)ddr2_addr + 640*4*7; // 1行書き終わったので、下の行に、アドレスは640ドットx1ピクセル4バイトx7行
ddr2_addr = char_draw(ddr2_addr, char_code, coler_code); // キャラクタを描画
char_cnt++;
}
}
}
return 0;
}
/* * drawn_disp.c * * Created on: 2012/08/23 * Author: Masaaki */
int main()
{
unsigned int * ddr2_addr;
unsigned int pixel_data;
pixel_data=0x0;
for (ddr2_addr=0x20000000; ddr2_addr<0x20010000; ddr2_addr++){
*(volatile unsigned int *)(ddr2_addr) = pixel_data++;
}
return 0;
}
// 表示タイミングの定義
// VGA 解像度 pixel clock = 25MHz
parameter H_ACTIVE_VIDEO= 640;
parameter H_FRONT_PORCH = 16;
parameter H_SYNC_PULSE = 96;
parameter H_BACK_PORCH = 48;
parameter H_SUM = H_ACTIVE_VIDEO + H_FRONT_PORCH + H_SYNC_PULSE + H_BACK_PORCH;
parameter V_ACTIVE_VIDEO = 480;
parameter V_FRONT_PORCH = 11;
parameter V_SYNC_PULSE = 2;
parameter V_BACK_PORCH = 31;
parameter V_SUM = V_ACTIVE_VIDEO + V_FRONT_PORCH + V_SYNC_PULSE + V_BACK_PORCH;
// SVGA 解像度 pixel clock = 40MHz
// parameter H_ACTIVE_VIDEO= 800;
// parameter H_FRONT_PORCH = 40;
// parameter H_SYNC_PULSE = 128;
// parameter H_BACK_PORCH = 88;
// parameter H_SUM = H_ACTIVE_VIDEO + H_FRONT_PORCH + H_SYNC_PULSE + H_BACK_PORCH;
// parameter V_ACTIVE_VIDEO = 600;
// parameter V_FRONT_PORCH = 1;
// parameter V_SYNC_PULSE = 4;
// parameter V_BACK_PORCH = 23;
// parameter V_SUM = V_ACTIVE_VIDEO + V_FRONT_PORCH + V_SYNC_PULSE + V_BACK_PORCH;
// XGA 解像度 pixel clock = 65MHz
// parameter H_ACTIVE_VIDEO= 1024;
// parameter H_FRONT_PORCH = 24;
// parameter H_SYNC_PULSE = 136;
// parameter H_BACK_PORCH = 160;
// parameter H_SUM = H_ACTIVE_VIDEO + H_FRONT_PORCH + H_SYNC_PULSE + H_BACK_PORCH;
// parameter V_ACTIVE_VIDEO = 768;
// parameter V_FRONT_PORCH = 2;
// parameter V_SYNC_PULSE = 6;
// parameter V_BACK_PORCH = 29;
// parameter V_SUM = V_ACTIVE_VIDEO + V_FRONT_PORCH + V_SYNC_PULSE + V_BACK_PORCH;
// SXGA 解像度 pixel clock = 108MHz
// parameter H_ACTIVE_VIDEO= 1280;
// parameter H_FRONT_PORCH = 48;
// parameter H_SYNC_PULSE = 112;
// parameter H_BACK_PORCH = 248;
// parameter H_SUM = H_ACTIVE_VIDEO + H_FRONT_PORCH + H_SYNC_PULSE + H_BACK_PORCH;
// parameter V_ACTIVE_VIDEO = 1024;
// parameter V_FRONT_PORCH = 1;
// parameter V_SYNC_PULSE = 3;
// parameter V_BACK_PORCH = 38;
// parameter V_SUM = V_ACTIVE_VIDEO + V_FRONT_PORCH + V_SYNC_PULSE + V_BACK_PORCH;
parameter H_DISPLAY_SIZE = H_ACTIVE_VIDEO/8; // 横80桁
parameter V_DISPLAY_SIZE = V_ACTIVE_VIDEO/8; // 縦60行
parameter RED_DOT_POS = 15; // 15~13ビット目がRED
parameter GREEN_DOT_POS = 12; // 12~10ビット目がGREEN
parameter BLUE_DOT_POS = 9; // 9~7ビット目がBLUE
parameter COLOR_ATTRIB_WIDHT = 3; // 色情報のビット幅
// bitmap_disp_cntrler_axi_master.v
//
// Read Only IP, 64 bit bus
//
// 2012/06/28
`default_nettype none
module bitmap_disp_cntrler_axi_master #
(
parameter integer C_INTERCONNECT_M_AXI_WRITE_ISSUING = 8,
parameter integer C_M_AXI_THREAD_ID_WIDTH = 1,
parameter integer C_M_AXI_ADDR_WIDTH = 32,
parameter integer C_M_AXI_DATA_WIDTH = 64,
parameter integer C_M_AXI_AWUSER_WIDTH = 1,
parameter integer C_M_AXI_ARUSER_WIDTH = 1,
parameter integer C_M_AXI_WUSER_WIDTH = 1,
parameter integer C_M_AXI_RUSER_WIDTH = 1,
parameter integer C_M_AXI_BUSER_WIDTH = 1,
parameter [31:0] C_M_AXI_TARGET = 32'h00000000,
parameter integer C_M_AXI_BURST_LEN = 256,
parameter integer C_OFFSET_WIDTH = 32,
/* Disabling these parameters will remove any throttling.
The resulting ERROR flag will not be useful */
parameter integer C_M_AXI_SUPPORTS_WRITE = 0,
parameter integer C_M_AXI_SUPPORTS_READ = 1
)
(
// System Signals
input wire ACLK,
input wire ARESETN,
// Master Interface Write Address
output wire [C_M_AXI_THREAD_ID_WIDTH-1:0] M_AXI_AWID,
output wire [C_M_AXI_ADDR_WIDTH-1:0] M_AXI_AWADDR,
output wire [8-1:0] M_AXI_AWLEN,
output wire [3-1:0] M_AXI_AWSIZE,
output wire [2-1:0] M_AXI_AWBURST,
output wire M_AXI_AWLOCK,
output wire [4-1:0] M_AXI_AWCACHE,
output wire [3-1:0] M_AXI_AWPROT,
// AXI3 output wire [4-1:0] M_AXI_AWREGION,
output wire [4-1:0] M_AXI_AWQOS,
output wire [C_M_AXI_AWUSER_WIDTH-1:0] M_AXI_AWUSER,
output wire M_AXI_AWVALID,
input wire M_AXI_AWREADY,
// Master Interface Write Data
// AXI3 output wire [C_M_AXI_THREAD_ID_WIDTH-1:0] M_AXI_WID,
output wire [C_M_AXI_DATA_WIDTH-1:0] M_AXI_WDATA,
output wire [C_M_AXI_DATA_WIDTH/8-1:0] M_AXI_WSTRB,
output wire M_AXI_WLAST,
output wire [C_M_AXI_WUSER_WIDTH-1:0] M_AXI_WUSER,
output wire M_AXI_WVALID,
input wire M_AXI_WREADY,
// Master Interface Write Response
input wire [C_M_AXI_THREAD_ID_WIDTH-1:0] M_AXI_BID,
input wire [2-1:0] M_AXI_BRESP,
input wire [C_M_AXI_BUSER_WIDTH-1:0] M_AXI_BUSER,
input wire M_AXI_BVALID,
output wire M_AXI_BREADY,
// Master Interface Read Address
output wire [C_M_AXI_THREAD_ID_WIDTH-1:0] M_AXI_ARID,
output wire [C_M_AXI_ADDR_WIDTH-1:0] M_AXI_ARADDR,
output wire [8-1:0] M_AXI_ARLEN,
output wire [3-1:0] M_AXI_ARSIZE,
output wire [2-1:0] M_AXI_ARBURST,
output wire [2-1:0] M_AXI_ARLOCK,
output wire [4-1:0] M_AXI_ARCACHE,
output wire [3-1:0] M_AXI_ARPROT,
// AXI3 output wire [4-1:0] M_AXI_ARREGION,
output wire [4-1:0] M_AXI_ARQOS,
output wire [C_M_AXI_ARUSER_WIDTH-1:0] M_AXI_ARUSER,
output wire M_AXI_ARVALID,
input wire M_AXI_ARREADY,
// Master Interface Read Data
input wire [C_M_AXI_THREAD_ID_WIDTH-1:0] M_AXI_RID,
input wire [C_M_AXI_DATA_WIDTH-1:0] M_AXI_RDATA,
input wire [2-1:0] M_AXI_RRESP,
input wire M_AXI_RLAST,
input wire [C_M_AXI_RUSER_WIDTH-1:0] M_AXI_RUSER,
input wire M_AXI_RVALID,
output wire M_AXI_RREADY,
// User Ports
input wire pixclk,
output wire TMDS_tx_clk_p,
output wire TMDS_tx_clk_n,
output wire TMDS_tx_2_G_p,
output wire TMDS_tx_2_G_n,
output wire TMDS_tx_1_R_p,
output wire TMDS_tx_1_R_n,
output wire TMDS_tx_0_B_p,
output wire TMDS_tx_0_B_n,
input wire ddr_cont_init_done
);
wire [7:0] red, green, blue;
wire hsyncx, vsyncx;
wire display_enable;
wire bde_req, bde_ack;
wire [7:0] bde_arlen;
wire [31:0] bde_address;
wire [63:0] bde_data;
wire bde_data_valid;
reg reset_disp_2b, reset_disp_1b;
wire reset_disp;
wire afifo_overflow, afifo_underflow;
wire addr_is_zero, h_v_is_zero;
axi_master_interface #(
.C_M_AXI_THREAD_ID_WIDTH(C_M_AXI_THREAD_ID_WIDTH),
.C_M_AXI_ADDR_WIDTH(C_M_AXI_ADDR_WIDTH),
.C_M_AXI_DATA_WIDTH(C_M_AXI_DATA_WIDTH),
.C_M_AXI_AWUSER_WIDTH(C_M_AXI_AWUSER_WIDTH),
.C_M_AXI_ARUSER_WIDTH(C_M_AXI_ARUSER_WIDTH),
.C_M_AXI_WUSER_WIDTH(C_M_AXI_WUSER_WIDTH),
.C_M_AXI_RUSER_WIDTH(C_M_AXI_RUSER_WIDTH),
.C_M_AXI_BUSER_WIDTH(C_M_AXI_BUSER_WIDTH),
.C_M_AXI_SUPPORTS_WRITE(C_M_AXI_SUPPORTS_WRITE),
.C_M_AXI_SUPPORTS_READ(C_M_AXI_SUPPORTS_READ)
) axi_master_inf_inst
(
.ACLK(ACLK),
.ARESETN(ARESETN),
.M_AXI_AWID(M_AXI_AWID),
.M_AXI_AWADDR(M_AXI_AWADDR),
.M_AXI_AWLEN(M_AXI_AWLEN),
.M_AXI_AWSIZE(M_AXI_AWSIZE),
.M_AXI_AWBURST(M_AXI_AWBURST),
.M_AXI_AWLOCK(M_AXI_AWLOCK),
.M_AXI_AWCACHE(M_AXI_AWCACHE),
.M_AXI_AWPROT(M_AXI_AWPROT),
.M_AXI_AWQOS(M_AXI_AWQOS),
.M_AXI_AWUSER(M_AXI_AWUSER),
.M_AXI_AWVALID(M_AXI_AWVALID),
.M_AXI_AWREADY(M_AXI_AWREADY),
.M_AXI_WDATA(M_AXI_WDATA),
.M_AXI_WSTRB(M_AXI_WSTRB),
.M_AXI_WLAST(M_AXI_WLAST),
.M_AXI_WUSER(M_AXI_WUSER),
.M_AXI_WVALID(M_AXI_WVALID),
.M_AXI_WREADY(M_AXI_WREADY),
.M_AXI_BID(M_AXI_BID),
.M_AXI_BRESP(M_AXI_BRESP),
.M_AXI_BUSER(M_AXI_BUSER),
.M_AXI_BVALID(M_AXI_BVALID),
.M_AXI_BREADY(M_AXI_BREADY),
.M_AXI_ARID(M_AXI_ARID),
.M_AXI_ARADDR(M_AXI_ARADDR),
.M_AXI_ARLEN(M_AXI_ARLEN),
.M_AXI_ARSIZE(M_AXI_ARSIZE),
.M_AXI_ARBURST(M_AXI_ARBURST),
.M_AXI_ARLOCK(M_AXI_ARLOCK),
.M_AXI_ARCACHE(M_AXI_ARCACHE),
.M_AXI_ARPROT(M_AXI_ARPROT),
.M_AXI_ARQOS(M_AXI_ARQOS),
.M_AXI_ARUSER(M_AXI_ARUSER),
.M_AXI_ARVALID(M_AXI_ARVALID),
.M_AXI_ARREADY(M_AXI_ARREADY),
.M_AXI_RID(M_AXI_RID),
.M_AXI_RDATA(M_AXI_RDATA),
.M_AXI_RRESP(M_AXI_RRESP),
.M_AXI_RLAST(M_AXI_RLAST),
.M_AXI_RUSER(M_AXI_RUSER),
.M_AXI_RVALID(M_AXI_RVALID),
.M_AXI_RREADY(M_AXI_RREADY),
.bde_req(bde_req),
.bde_ack(bde_ack),
.bde_arlen(bde_arlen),
.bde_address(bde_address),
.bde_data_out(bde_data),
.bde_data_valid(bde_data_valid)
);
bitmap_disp_engine bitmap_disp_eng_inst (
.clk_disp(pixclk),
.clk_axi(ACLK),
.reset_disp(reset_disp),
.reset_axi(~ARESETN),
.req(bde_req),
.ack(bde_ack),
.ARLEN(bde_arlen),
.address(bde_address),
.data_in(bde_data),
.data_valid(bde_data_valid),
.red_out(red),
.green_out(green),
.blue_out(blue),
.hsyncx(hsyncx),
.vsyncx(vsyncx),
.display_enable(display_enable),
.ddr_cont_init_done(ddr_cont_init_done),
.afifo_overflow(afifo_overflow),
.afifo_underflow(afifo_underflow),
.addr_is_zero(addr_is_zero),
.h_v_is_zero(h_v_is_zero)
);
dvi_disp #(
.PLL_CLKFBOUT_MULT(20), // クロック倍率 PLL VCO Freq 400MHz ~ 1000MHz
.PLL_CLKIN_PERIOD(40.0), // 40 ns, VGA, 640x480
.PLL_CLKOUT0_DIVIDE(2), // ピクセルクロックX10
.PLL_CLKOUT1_DIVIDE(20), // ピクセルクロック
.PLL_CLKOUT2_DIVIDE(10) // ピクセルクロックX2
) dvi_disp_inst
(
.pixclk(pixclk),
.reset_in(reset_disp),
.red_in(red),
.green_in(green),
.blue_in(blue),
.hsync(hsyncx),
.vsync(vsyncx),
.display_enable(display_enable),
.TMDS_tx_clk_p(TMDS_tx_clk_p),
.TMDS_tx_clk_n(TMDS_tx_clk_n),
.TMDS_tx_2_G_p(TMDS_tx_2_G_p),
.TMDS_tx_2_G_n(TMDS_tx_2_G_n),
.TMDS_tx_1_R_p(TMDS_tx_1_R_p),
.TMDS_tx_1_R_n(TMDS_tx_1_R_n),
.TMDS_tx_0_B_p(TMDS_tx_0_B_p),
.TMDS_tx_0_B_n(TMDS_tx_0_B_n)
);
always @(posedge pixclk) begin
reset_disp_2b <= ~ARESETN;
reset_disp_1b <= reset_disp_2b;
end
assign reset_disp = reset_disp_1b;
endmodule
`default_nettype wire
// axi_master_interface.v
//
// Read Only IP, 64 bit bus
//
// 2012/06/28
`default_nettype none
module axi_master_interface #
(
parameter integer C_M_AXI_THREAD_ID_WIDTH = 1,
parameter integer C_M_AXI_ADDR_WIDTH = 32,
parameter integer C_M_AXI_DATA_WIDTH = 64,
parameter integer C_M_AXI_AWUSER_WIDTH = 1,
parameter integer C_M_AXI_ARUSER_WIDTH = 1,
parameter integer C_M_AXI_WUSER_WIDTH = 1,
parameter integer C_M_AXI_RUSER_WIDTH = 1,
parameter integer C_M_AXI_BUSER_WIDTH = 1,
/* Disabling these parameters will remove any throttling.
The resulting ERROR flag will not be useful */
parameter integer C_M_AXI_SUPPORTS_WRITE = 0,
parameter integer C_M_AXI_SUPPORTS_READ = 1
)
(
// System Signals
input wire ACLK,
input wire ARESETN,
// Master Interface Write Address
output wire [C_M_AXI_THREAD_ID_WIDTH-1:0] M_AXI_AWID,
output wire [C_M_AXI_ADDR_WIDTH-1:0] M_AXI_AWADDR,
output wire [8-1:0] M_AXI_AWLEN,
output wire [3-1:0] M_AXI_AWSIZE,
output wire [2-1:0] M_AXI_AWBURST,
output wire M_AXI_AWLOCK,
output wire [4-1:0] M_AXI_AWCACHE,
output wire [3-1:0] M_AXI_AWPROT,
// AXI3 output wire [4-1:0] M_AXI_AWREGION,
output wire [4-1:0] M_AXI_AWQOS,
output wire [C_M_AXI_AWUSER_WIDTH-1:0] M_AXI_AWUSER,
output wire M_AXI_AWVALID,
input wire M_AXI_AWREADY,
// Master Interface Write Data
// AXI3 output wire [C_M_AXI_THREAD_ID_WIDTH-1:0] M_AXI_WID,
output wire [C_M_AXI_DATA_WIDTH-1:0] M_AXI_WDATA,
output wire [C_M_AXI_DATA_WIDTH/8-1:0] M_AXI_WSTRB,
output wire M_AXI_WLAST,
output wire [C_M_AXI_WUSER_WIDTH-1:0] M_AXI_WUSER,
output wire M_AXI_WVALID,
input wire M_AXI_WREADY,
// Master Interface Write Response
input wire [C_M_AXI_THREAD_ID_WIDTH-1:0] M_AXI_BID,
input wire [2-1:0] M_AXI_BRESP,
input wire [C_M_AXI_BUSER_WIDTH-1:0] M_AXI_BUSER,
input wire M_AXI_BVALID,
output wire M_AXI_BREADY,
// Master Interface Read Address
output wire [C_M_AXI_THREAD_ID_WIDTH-1:0] M_AXI_ARID,
output reg [C_M_AXI_ADDR_WIDTH-1:0] M_AXI_ARADDR,
output reg [8-1:0] M_AXI_ARLEN,
output wire [3-1:0] M_AXI_ARSIZE,
output wire [2-1:0] M_AXI_ARBURST,
output wire [2-1:0] M_AXI_ARLOCK,
output wire [4-1:0] M_AXI_ARCACHE,
output wire [3-1:0] M_AXI_ARPROT,
// AXI3 output wire [4-1:0] M_AXI_ARREGION,
output wire [4-1:0] M_AXI_ARQOS,
output wire [C_M_AXI_ARUSER_WIDTH-1:0] M_AXI_ARUSER,
output wire M_AXI_ARVALID,
input wire M_AXI_ARREADY,
// Master Interface Read Data
input wire [C_M_AXI_THREAD_ID_WIDTH-1:0] M_AXI_RID,
input wire [C_M_AXI_DATA_WIDTH-1:0] M_AXI_RDATA,
input wire [2-1:0] M_AXI_RRESP,
input wire M_AXI_RLAST,
input wire [C_M_AXI_RUSER_WIDTH-1:0] M_AXI_RUSER,
input wire M_AXI_RVALID,
output wire M_AXI_RREADY,
// bitmap_disp_engine Interface
input wire bde_req,
output reg bde_ack,
input wire [7:0] bde_arlen,
input wire [31:0] bde_address,
output reg [63:0] bde_data_out,
output reg bde_data_valid
);
parameter RESP_OKAY = 2'b00,
RESP_EXOKAY = 2'b01,
RESP_SLVERR = 2'b10,
RESP_DECERR = 2'b11;
reg reset_1d, reset;
parameter idle_rd = 4'b0001,
arvalid_assert = 4'b0010,
data_read = 4'b0100,
rd_tran_end = 4'b1000;
reg [3:0] rdt_cs;
reg arvalid;
reg [63:0] read_data;
reg rready;
// ARESETN をACLK で同期化
always @(posedge ACLK) begin
reset_1d <= ~ARESETN;
reset <= reset_1d;
end
// Write は無し
assign M_AXI_AWID = 0;
assign M_AXI_AWADDR = 0;
assign M_AXI_AWLEN = 0;
assign M_AXI_AWSIZE = 0;
assign M_AXI_AWBURST = 0;
assign M_AXI_AWLOCK = 0;
assign M_AXI_AWCACHE = 0;
assign M_AXI_AWPROT = 0;
assign M_AXI_AWQOS = 0;
assign M_AXI_AWUSER = 0;
assign M_AXI_AWVALID = 0;
assign M_AXI_WDATA = 0;
assign M_AXI_WSTRB = 0;
assign M_AXI_WLAST = 0;
assign M_AXI_WUSER = 0;
assign M_AXI_WVALID = 0;
assign M_AXI_BREADY = 0;
// Read
// AXI4バス Read Transaction State Machine
always @(posedge ACLK) begin
if (reset) begin
rdt_cs <= idle_rd;
arvalid <= 1'b0;
rready <= 1'b0;
end else begin
case (rdt_cs)
idle_rd :
if (bde_req) begin
rdt_cs <= arvalid_assert;
arvalid <= 1'b1;
end
arvalid_assert :
if (M_AXI_ARREADY) begin
rdt_cs <= data_read;
arvalid <= 1'b0;
rready <= 1'b1;
end
data_read :
if (M_AXI_RLAST && M_AXI_RVALID) begin // 終了
rdt_cs <= rd_tran_end;
rready <= 1'b0;
end
rd_tran_end :
rdt_cs <= idle_rd;
endcase
end
end
assign M_AXI_ARVALID = arvalid;
assign M_AXI_RREADY = rready;
assign M_AXI_ARID = 0;
// M_AXI_ARADDR の処理
always @(posedge ACLK) begin
if (reset)
M_AXI_ARADDR <= 0;
else begin
if (bde_req)
M_AXI_ARADDR <= bde_address;
end
end
// M_AXI_ARLEN の処理
always @(posedge ACLK) begin
M_AXI_ARLEN <= bde_arlen;
end
assign M_AXI_ARSIZE = 3'b011; // 8 Bytes in Transfer
assign M_AXI_ARBURST = 2'b01; // INCR
assign M_AXI_ARLOCK = 2'b00; // Normal Access
assign M_AXI_ARCACHE = 4'b0010; // Normal Non-cacheable Non-bufferable
assign M_AXI_ARPROT = 3'b000; // Data access, Secure access, Unprivileged access
assign M_AXI_ARQOS = 4'b0000; // default
assign M_AXI_ARUSER = 1'b0;
// bde_ack の処理
always @(posedge ACLK) begin
if (arvalid && M_AXI_ARREADY)
bde_ack <= 1'b1;
else
bde_ack <= 1'b0;
end
// bde_data_out の処理
always @(posedge ACLK) begin
bde_data_out <= M_AXI_RDATA;
end
// bde_data_valid の処理
always @(posedge ACLK) begin
if (rready && M_AXI_RVALID)
bde_data_valid <= 1'b1;
else
bde_data_valid <= 1'b0;
end
endmodule
// BitMap Display Controller
// bitmap_disp_engine.v
// AXI4バス用
`default_nettype none
// synthesis translate_off
// `include "std_ovl_defines.h"
// synthesis translate_on
module bitmap_disp_engine (
input wire clk_disp, // ディスプレイ表示用クロック
input wire clk_axi, // AXI4バスクロック
input wire reset_disp, // clk_disp 用リセット
input wire reset_axi, // clk_axi 用リセット
output reg req, // Read Address転送のrequest
input wire ack, // Read Address転送のacknowlege
output reg [7:0] ARLEN, // Read Address転送のバースト長-1
output wire [31:0] address, // AXI4 Busのアドレス
input wire [63:0] data_in, // DDR2 SDRAMの画像データ(2つのRGB)
input wire data_valid,
output reg [7:0] red_out,
output reg [7:0] green_out,
output reg [7:0] blue_out,
output reg hsyncx,
output reg vsyncx,
output reg display_enable,
input wire ddr_cont_init_done, // DDR2 SDRAMコントローラの初期化終了
output wire afifo_overflow, // 非同期FIFO のオーバーフロー・エラー
output wire afifo_underflow, // 非同期FIFO のアンダーフロー・エラー
output reg addr_is_zero, // for test
output reg h_v_is_zero // for test
);
`include "./disp_timing_parameters.vh"
parameter DDR2_SDRAM_START_ADDRESS = 32'h2000_0000; // DDR2 SDRAMのスタートアドレス
parameter AFIFO_FULL_VAL = 8'b1000_0000; // Write側の値。Write側は32ビットなので、128でRead側は256となる
parameter AFIFO_HALF_FULL_VAL = 8'b0100_0000; // Write側の値。Write側は32ビットなので、64でRead側は128となる
parameter [5:0] idle_rdg= 6'b000001,
init_full_mode= 6'b000010,
wait_half_full= 6'b000100,
req_burst= 6'b001000,
frame_wait_state= 6'b010000,
frame_start_full= 6'b100000;
reg [5:0] cs_rdg;
parameter [2:0] IDLE_REQ = 3'b001,
REQ_ASSERT = 3'b010,
REQ_HOLD = 3'b100;
reg [2:0] cs_req;
reg afifo_rd_en;
wire [31:0] afifo_dout;
wire afifo_full;
wire afifo_empty;
wire [7:0] wr_data_count;
reg [31:0] addr_count;
(* KEEP="TURE" *) wire hv_count_enable;
reg [7:0] read_count;
(* KEEP="TURE" *) reg hv_cnt_ena_d1;
(* KEEP="TURE" *) reg hv_cnt_ena_d2;
reg [11:0] h_count;
reg [11:0] v_count;
reg [7:0] red_node, green_node, blue_node;
reg hsyncx_node, vsyncx_node;
reg addr_is_zero_node, h_v_is_zero_node;
reg vsync_axi, vsync_axi_b1;
reg vsync_axi_1d;
reg vsyncx_rise_pulse;
// synthesis translate_off
// wire [`OVL_FIRE_WIDTH-1:0] fire_overflow, fire_underflow;
// synthesis translate_on
// RGB保存用非同期FIFO, FWFT Wirte側64ビット幅128深度、Read側32ビット256深度とする
bitmap_afifo bitmap_afifo_inst (
.wr_rst(reset_axi | vsync_axi),
.wr_clk(clk_axi),
.rd_clk(clk_disp),
.rd_rst(reset_disp | ~vsyncx_node),
.din(data_in), // Bus [63 : 0]
.wr_en(data_valid),
.rd_en(afifo_rd_en),
.dout(afifo_dout), // Bus [31 : 0]
.full(afifo_full),
.overflow(afifo_overflow),
.empty(afifo_empty),
.underflow(afifo_underflow),
.wr_data_count(wr_data_count) // Bus [7 : 0]
);
// AXI4 Busのアドレスカウンタ(AXI4クロックドメイン)カウンタの単位は1バイト
always @(posedge clk_axi) begin
if (reset_axi)
addr_count <= DDR2_SDRAM_START_ADDRESS;
else begin
// if (addr_count>=(DDR2_SDRAM_START_ADDRESS + (H_ACTIVE_VIDEO * V_ACTIVE_VIDEO *4))) // 1フレーム分描画終了したのでクリアする(1ピクセルに3バイト使用する。つまり32ビット(4bytes)使用するので*4する)
if (vsync_axi)
addr_count <= DDR2_SDRAM_START_ADDRESS;
else if (data_valid) // データが来たらカウントアップ
addr_count <= addr_count + 32'd8; // 1回のデータは64ビット長(8バイト)
end
end
assign address = addr_count;
// Readデータ処理モジュール用ステートマシン
always @(posedge clk_axi) begin
if (reset_axi)
cs_rdg <= idle_rdg;
else begin
case (cs_rdg)
idle_rdg :
if (ddr_cont_init_done)
cs_rdg <= init_full_mode;
init_full_mode : // 最初にcam_data_afifo をFULLにするステート、このステートではVGA信号は出力しないで、ひたすらcam_data_afifo がFULLになるのを待つ。
if (read_count==0)
cs_rdg <= wait_half_full;
wait_half_full : // cam_data_afifo がHALF_FULLになるまでこのステートで待機
if (vsync_axi)
cs_rdg <= frame_wait_state;
else if (wr_data_count<=AFIFO_HALF_FULL_VAL)
cs_rdg <= req_burst;
req_burst :
if (vsync_axi)
cs_rdg <= frame_wait_state;
else if (read_count==0) // データが全部来たら
cs_rdg <= wait_half_full;
frame_wait_state : // 1フレーム終了後vsync の時にWaitする
if (vsyncx_rise_pulse) // vsyncx の立ち上がり
cs_rdg <= frame_start_full;
frame_start_full : // 1フレームのスタートの時にFIFOをフルにする
if (read_count==0)
cs_rdg <= wait_half_full;
endcase
end
end
assign hv_count_enable = (cs_rdg==wait_half_full || cs_rdg==req_burst || cs_rdg==frame_wait_state || cs_rdg==frame_start_full) ? 1'b1 : 1'b0;
// req の実装。VRAMのデータをReadしたいときにアクティベート。ackが帰ってきたら落とす
always @(posedge clk_axi) begin
if (reset_axi) begin
cs_req <= IDLE_REQ;
req <= 1'b0;
end else begin
case (cs_req)
IDLE_REQ :
if (cs_rdg==req_burst || cs_rdg==init_full_mode || cs_rdg==frame_start_full) begin
cs_req <= REQ_ASSERT;
req <= 1'b1;
end
REQ_ASSERT :
if (ack) begin
cs_req <= REQ_HOLD;
req <= 1'b0;
end
REQ_HOLD :
if (~(cs_rdg==req_burst || cs_rdg==init_full_mode || cs_rdg==frame_start_full))
cs_req <= IDLE_REQ;
endcase
end
end
// ARLEN, read_count の決定。 init_full_mode,frame_start_full の時はAFIFO_FULL_VAL-1、それ以外はAFIFO_HALF_FULL_VAL-1
always @(posedge clk_axi) begin
if (reset_axi) begin
ARLEN <= AFIFO_FULL_VAL-1;
read_count <= AFIFO_FULL_VAL;
end else begin
if (cs_rdg==idle_rdg || cs_rdg==frame_wait_state) begin
ARLEN <= AFIFO_FULL_VAL-1;
read_count <= AFIFO_FULL_VAL;
end else if (cs_rdg==wait_half_full) begin
ARLEN <= AFIFO_HALF_FULL_VAL-1;
read_count <= AFIFO_HALF_FULL_VAL;
end else if (cs_rdg==req_burst || cs_rdg==init_full_mode || cs_rdg==frame_start_full) begin
if (read_count!=0 && data_valid) // 0になるまで、データが来たらデクリメント
read_count <= read_count - 1;
end
end
end
// read_count の実装、AXI4 Bus Interface へのRead要求のカウントをする。
// always @(posedge clk_axi) begin
// if (reset_axi)
// read_count <= ARLEN+1;
// else begin
// if (cs_rdg==wait_half_full || cs_rdg==idle_rdg)
// read_count <= ARLEN+1;
// else if (cs_rdg==req_burst || cs_rdg==init_full_mode) begin
// if (read_count!=0 && data_valid) // 0になるまで、データが来たらデクリメント
// read_count <= read_count - 1;
// end
// end
// end
// ビットマップVGAコントローラのclk_disp 動作部
// h_count、v_count用にclk_axi 動作のcs_rdg の値を使用するので2回clk_disp 動作のFFでラッチする
always @(posedge clk_disp) begin
if (reset_disp) begin
hv_cnt_ena_d1 <= 1'b0;
hv_cnt_ena_d2 <= 1'b0;
end else begin
hv_cnt_ena_d1 <= hv_count_enable;
hv_cnt_ena_d2 <= hv_cnt_ena_d1;
end
end
// h_countの実装(水平カウンタ)
always @(posedge clk_disp) begin
if (reset_disp)
h_count <= 0;
else if (h_count>=(H_SUM-1)) // h_count がH_SUM-1よりも大きければ0に戻す(mod H_SUM)
h_count <= 0;
else if (hv_cnt_ena_d2) // 最初に非同期FIFOをフルにするまではカウントしない
h_count <= h_count + 11'd1;
end
// v_countの実装(垂直カウンタ)
always @(posedge clk_disp) begin
if (reset_disp)
v_count <= 0;
else if (h_count>=(H_SUM-1)) begin // 水平カウンタがクリアされるとき
if (v_count>=(V_SUM-1)) // v_count がV_SUM-1よりも大きければ0に戻す(mode V_SUM)
v_count <= 0;
else if (hv_cnt_ena_d2) // 最初に非同期FIFOをフルにするまではカウントしない
v_count <= v_count + 10'd1;
end
end
// Red, Green, Blue出力
always @(posedge clk_disp) begin
if (reset_disp) begin
red_node <= 0;
green_node <= 0;
blue_node <= 0;
end else begin
if (~hv_cnt_ena_d2) begin // 最初にpixel_async_fifo がフルになるまで画像データを出力しない。
red_node <= 0;
green_node <= 0;
blue_node <= 0;
end else if (h_count<H_ACTIVE_VIDEO && v_count<V_ACTIVE_VIDEO) begin
red_node <= afifo_dout[23:16];
green_node <= afifo_dout[15:8];
blue_node <= afifo_dout[7:0];
end else begin
red_node <= 0;
green_node <= 0;
blue_node <= 0;
end
end
end
always @(posedge clk_disp) begin
if (reset_disp) begin
red_out <= 0;
green_out <= 0;
blue_out <= 0;
end else begin
red_out <= red_node;
green_out <= green_node;
blue_out <= blue_node;
end
end
// hsyncx 出力(水平同期信号)
always @(posedge clk_disp) begin
if (reset_disp)
hsyncx_node <= 1'b1;
else
if (h_count>(H_ACTIVE_VIDEO + H_FRONT_PORCH-1) && h_count<=(H_ACTIVE_VIDEO + H_FRONT_PORCH + H_SYNC_PULSE-1)) // 水平同期期間
hsyncx_node <= 1'b0;
else
hsyncx_node <= 1'b1;
end
always @(posedge clk_disp) begin
if (reset_disp)
hsyncx <= 1'b1;
else
hsyncx <= hsyncx_node;
end
// vsyncx 出力(水平同期信号)
always @(posedge clk_disp) begin
if (reset_disp)
vsyncx_node <= 1'b1;
else
if (v_count>(V_ACTIVE_VIDEO + V_FRONT_PORCH-1) && v_count<=(V_ACTIVE_VIDEO + V_FRONT_PORCH + V_SYNC_PULSE-1)) // 垂直同期期間
vsyncx_node <= 1'b0;
else
vsyncx_node <= 1'b1;
end
always @(posedge clk_disp) begin
if (reset_disp)
vsyncx <= 1'b1;
else
vsyncx <= vsyncx_node;
end
// vsync をclk_axi で同期化
always @(posedge clk_axi) begin
if (reset_axi) begin
vsync_axi <= 1'b0;
vsync_axi_b1 <= 1'b0;
vsync_axi_1d <= 1'b0;
end else begin
vsync_axi_b1 <= ~vsyncx_node;
vsync_axi <= vsync_axi_b1;
vsync_axi_1d <= vsync_axi;
end
end
// vsyncx_rise_pulse の処理。vsyncx の立ち上がり時に1パルス出力する
always @(posedge clk_axi) begin
if (reset_axi)
vsyncx_rise_pulse <= 1'b0;
else begin
if (vsync_axi==1'b0 && vsync_axi_1d==1'b1)
vsyncx_rise_pulse <= 1'b1;
else
vsyncx_rise_pulse <= 1'b0;
end
end
// display_enable 出力
always @(posedge clk_disp) begin
if (reset_disp)
display_enable <= 1'b1;
else begin
if (h_count<H_ACTIVE_VIDEO && v_count<V_ACTIVE_VIDEO)
display_enable <= 1'b1;
else
display_enable <= 1'b0;
end
end
// afifo_rd_en の処理
always @(posedge clk_disp) begin
if (reset_disp)
afifo_rd_en <= 1'b0;
else begin
if (~hv_cnt_ena_d2) // 初期化中
afifo_rd_en <= 1'b0;
else if (h_count<H_ACTIVE_VIDEO && v_count<V_ACTIVE_VIDEO) // 表示期間
afifo_rd_en <= 1'b1;
else
afifo_rd_en <= 1'b0;
end
end
// アサーション
// synthesis translate_off
always @ (posedge clk_axi) begin
if (reset_axi)
;
else begin
if (afifo_overflow) begin
$display("%m: at time %t ERROR : FIFOがフルなのにライトした",$time);
$stop;
end
end
end
always @(posedge clk_disp) begin
if (reset_disp)
;
else begin
if (afifo_underflow) begin
$display("%m: at time %t ERROR : FIFOが空なのにリードした",$time);
$stop;
end
end
end
// ovl_never #(
// `OVL_ERROR, // severity_level
// `OVL_ASSERT, // property_type
// "ERROR : FIFOがフルなのにライトした", // msg
// `OVL_COVER_DEFAULT, // coverage_level
// `OVL_POSEDGE, // clock_edge
// `OVL_ACTIVE_HIGH, // reset_polarity
// `OVL_GATE_CLOCK // gating_type
// ) afifo_overflow_assertion (
// clk_axi,
// reset_axi,
// 1'b1,
// afifo_overflow,
// fire_overflow
// );
// ovl_never #(
// `OVL_ERROR, // severity_level
// `OVL_ASSERT, // property_type
// "ERROR : FIFOが空なのにリードした", // msg
// `OVL_COVER_DEFAULT, // coverage_level
// `OVL_POSEDGE, // clock_edge
// `OVL_ACTIVE_HIGH, // reset_polarity
// `OVL_GATE_CLOCK // gating_type
// ) afifo_underflow_assertion (
// clk_disp,
// reset_disp,
// 1'b1,
// afifo_underflow,
// fire_underflow
// );
// synthesis translate_on
// for test
always @(posedge clk_axi) begin
if (reset_axi) begin
addr_is_zero_node <= 1'b0;
addr_is_zero <= 1'b0;
end else begin
if (addr_count == 0)
addr_is_zero_node <= 1'b1;
else
addr_is_zero_node <= 1'b0;
addr_is_zero <= addr_is_zero_node;
end
end
always @(posedge clk_disp) begin
if (reset_disp) begin
h_v_is_zero_node <= 1'b0;
h_v_is_zero <= 1'b0;
end else begin
if (h_count==0 && v_count==0)
h_v_is_zero_node <= 1'b1;
else
h_v_is_zero_node <= 1'b0;
h_v_is_zero <= h_v_is_zero_node;
end
end
endmodule
`default_nettype wire
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
- | - | - | - | - | 1 | 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 | - | - | - | - | - | - |