// 水平同期(h_sync)、垂直同期(v_sync)、表示期間(display_on)
`default_nettype none
`timescale 1ns / 1ps
module disp_timing # (
parameter integer RESOLUTION = 1 // SVGA
)
(clk, reset, page_start, display_on, h_addr, v_addr, h_sync, h_sync_pulse, v_sync);
`include "video_timing_param.vh"
`include "convenient_functions.vh"
input clk; // 25MHz
input reset;
output page_start; // 1ページのスタート信号、ページの最初の表示ビットのときにだけ1(同期用信号)
output display_on; // 表示期間を示す(Active High)
output [log2(H_SUM)-1:0] h_addr; // 水平のドットアドレス
output [log2(V_SUM)-1:0] v_addr; // 垂直のドットアドレス
output h_sync; // 水平同期、Active High
output h_sync_pulse; // 水平同期パルス
output v_sync; // 垂直同期、Active High
wire clk;
wire reset;
wire page_start;
wire display_on;
wire [log2(H_SUM)-1:0] h_addr; // 水平のドットアドレス
wire [log2(V_SUM)-1:0] v_addr; // 垂直のドットアドレス
wire h_sync;
wire h_sync_pulse;
wire v_sync;
reg [log2(H_SUM)-1:0] h_point, h_addr_node;
reg [log2(V_SUM)-1:0] v_point, v_addr_node;
reg page_start_node;
reg display_on_node;
reg h_sync_node;
reg v_sync_node;
reg h_sync_pulse_node;
always @(posedge reset, posedge clk) begin // 水平信号
if (reset) begin
h_point <= 0;
h_addr_node <= 0;
end else begin
h_addr_node <= h_point;
if (h_point == H_SUM-1) // H_SUM-1だったらクリア
h_point <= 0;
else // H_SUM-1になるまでインクリメント
h_point <= h_point + 1;
end
end
assign h_addr = h_addr_node[9:0];
always @(posedge reset, posedge clk) begin // 垂直信号
if (reset) begin
v_point <= 0;
v_addr_node <= 0;
end else begin
v_addr_node <= v_point;
if (v_point == V_SUM-1) // H_SUM-1だったらクリア
v_point <= 0;
else if (h_point == H_SUM-1) // 水平信号のエンドでインクリメント
v_point <= v_point + 1;
end
end
assign v_addr = v_addr_node[9:0];
always @(posedge reset, posedge clk) begin // 表示期間
if (reset)
display_on_node <= 0;
else begin
if (h_point<H_ACTIVE_VIDEO && v_point<V_ACTIVE_VIDEO) // 表示期間
display_on_node <= 1'b1;
else
display_on_node <= 1'b0; // 非表示期間
end
end
assign display_on = display_on_node;
always @(posedge reset, posedge clk) begin // 表示スタート
if (reset)
page_start_node <= 1'b0;
else begin
if (h_point==0) // 表示スタート
page_start_node <= 1'b1;
else
page_start_node <= 1'b0;
end
end
assign page_start = page_start_node;
always @(posedge reset, posedge clk) begin // 水平同期
if (reset)
h_sync_node <= 1'b0;
else begin
if ((h_point>=(H_ACTIVE_VIDEO + H_FRONT_PORCH)) && (h_point < (H_SUM-H_BACK_PORCH))) // 水平同期期間
h_sync_node <= 1'b1;
else
h_sync_node <= 1'b0;
end
end
assign h_sync = h_sync_node;
always @(posedge reset, posedge clk) begin // 水平同期位置のパルス
if (reset)
h_sync_pulse_node <= 1'b0;
else begin
if (h_point==(H_ACTIVE_VIDEO+H_FRONT_PORCH))
h_sync_pulse_node <= 1'b1;
else
h_sync_pulse_node <= 1'b0;
end
end
assign h_sync_pulse = h_sync_pulse_node;
always @(posedge reset, posedge clk) begin // 垂直同期
if (reset)
v_sync_node <= 1'b0;
else begin
if ((v_point>=(V_ACTIVE_VIDEO + V_FRONT_PORCH)) && (v_point<(V_SUM-V_BACK_PORCH))) // 垂直同期期間
v_sync_node <= 1'b1;
else
v_sync_node <= 1'b0;
end
end
assign v_sync = v_sync_node;
endmodule
// フレームバッファ用メモリ
// AポートはプロセッサからのRead/Write用ポート、BポートはVGA用データ出力ポート
// display_on信号を受け取って、フレームバッファ用のアドレスを生成。このアドレスは8クロックごとにカウントアップ。
// データはキャラクタコード7ビットにR,G,Bの3ビットを追加
//
// 2012/02/24 : R 3bit, G 3bit, B 3bit, キャラクタ 7bitの16ビットに変更した。
// 2012/02/25 : Write側とRead側のクロックを分離して、非同期RAMに変更した。
// 2013/03/05 : reset を reset_a, reset_b に変更
// 2014/03/16 : 全面変更
`default_nettype none
module frame_buffer # (
parameter integer RESOLUTION = 1 // SVGA
)
(clka, clkb, reset_a, reset_b, processor_addr, processor_din, processor_dout, processor_we, display_addr, display_dout);
`include "video_timing_param.vh"
`include "convenient_functions.vh"
input clka;
input clkb;
input reset_a;
input reset_b;
input [log2(ALL_CHAR_SIZE)-1:0] processor_addr;
input [15:0] processor_din;
output [15:0] processor_dout;
input processor_we;
input [log2(ALL_CHAR_SIZE)-1:0] display_addr;
output [15:0] display_dout;
parameter integer FB_MEM_SIZE = near_power2(ALL_CHAR_SIZE);
reg [15:0] mem [0:near_power2(ALL_CHAR_SIZE)-1];
wire clka;
wire clkb;
wire reset_a;
wire reset_b;
wire [log2(ALL_CHAR_SIZE)-1:0] processor_addr;
wire [15:0] processor_din;
reg [15:0] processor_dout;
wire processor_we;
wire [log2(ALL_CHAR_SIZE)-1:0] display_addr;
reg [15:0] display_dout;
integer i;
// initialization
// Simulation では通るが、Synthesize だと、どうしてもエラーになるので Simulation のみとした
// pragma translate off
initial begin
for (i=0; i<FB_MEM_SIZE; i=i+1) begin
mem[i] = 16'd0;
end
end
// pragma translate on
// Write
always @(posedge clka) begin
if (processor_we)
mem[processor_addr] <= processor_din;
processor_dout <= mem[processor_addr];
end
// Read
always @(posedge clkb) begin
display_dout <= mem[display_addr];
end
endmodule
`default_nettype none
// CharDispCtrler.v
// キャラクタ ディスレイ コントローラ
// processor_dout, display_doutのビット構成 bit9 - RED, bit8 - GREEN, bit7 - BLUE, bit6〜0 : キャラクタデータ
//
// 2010/06/21 : Ver.1.1 : display_enableを追加
// 2012/02/24 : R 3bit, G 3bit, B 3bit, キャラクタ 7bitの16ビットに変更した。
// 2012/02/25 : プロセッサ側のクロックと画像表示用クロックを分けた。
`default_nettype none
`timescale 1ns / 1ps
module CharDispCtrler # (
parameter integer RESOLUTION = 1 // SVGA
)
(axi4clk, pixclk, reset_axi, reset_pix, processor_addr, processor_din, processor_dout, processor_we, VGA_RED, VGA_GREEN, VGA_BLUE, VGA_HSYNC, VGA_VSYNC, display_enable);
`include "video_timing_param.vh"
`include "convenient_functions.vh"
input wire axi4clk;
input wire pixclk;
input wire reset_axi;
input wire reset_pix;
input wire [log2(ALL_CHAR_SIZE)-1:0] processor_addr;
input wire [15:0] processor_din;
output wire [15:0] processor_dout;
input wire processor_we;
output [COLOR_ATTRIB_WIDHT-1 : 0] VGA_RED;
output [COLOR_ATTRIB_WIDHT-1 : 0] VGA_GREEN;
output [COLOR_ATTRIB_WIDHT-1 : 0] VGA_BLUE;
output VGA_HSYNC;
output VGA_VSYNC;
output wire display_enable;
wire [COLOR_ATTRIB_WIDHT-1 : 0] VGA_RED;
wire [COLOR_ATTRIB_WIDHT-1 : 0] VGA_GREEN;
wire [COLOR_ATTRIB_WIDHT-1 : 0] VGA_BLUE;
wire VGA_HSYNC;
wire VGA_VSYNC;
wire [log2(H_SUM)-1:0] h_addr; // 水平のドットアドレス
wire [log2(V_SUM)-1:0] v_addr; // 垂直のドットアドレス
wire h_sync_pulse;
reg [COLOR_ATTRIB_WIDHT-1 : 0] red_node, green_node, blue_node;
reg [6:0] char_data_node;
reg [log2(ALL_CHAR_SIZE)-1:0] temp_pointer;
wire page_start, display_on;
wire h_sync_0, v_sync_0;
reg h_sync_1, v_sync_1;
reg h_sync_2, v_sync_2;
reg h_sync_3, v_sync_3;
reg [log2(ALL_CHAR_SIZE)-1:0] display_addr;
wire [15:0] display_dout;
wire [7:0] char_data;
reg [RED_DOT_POS:BLUE_DOT_POS-COLOR_ATTRIB_WIDHT+1] temp_color;
reg display_on_d1, display_on_d2;
frame_buffer #(
.RESOLUTION(RESOLUTION)
) frame_buffer_inst (
.clka(axi4clk),
.clkb(pixclk),
.reset_a(reset_axi),
.reset_b(reset_pix),
.processor_addr(processor_addr),
.processor_din(processor_din),
.processor_dout(processor_dout),
.processor_we(processor_we),
.display_addr(display_addr),
.display_dout(display_dout)
);
char_gen_rom char_gen_rom_inst (
.clk(pixclk),
.reset(reset_pix),
.char_addr(display_dout[6:0]),
.row_addr(v_addr[2:0]),
.dout(char_data)
);
disp_timing #(
.RESOLUTION(RESOLUTION)
) disp_timing_inst (
.clk(pixclk),
.reset(reset_pix),
.page_start(page_start),
.display_on(display_on),
.h_addr(h_addr),
.v_addr(v_addr),
.h_sync(h_sync_0),
.h_sync_pulse(h_sync_pulse),
.v_sync(v_sync_0)
);
always @(posedge pixclk) begin // display_onを2クロック遅延する。下の表示部分はframe_buffer, キャラジェネROMで2クロックデータが遅延している。それを吸収するためにdisplay_onを2クロック遅延した信号を作る
if (reset_pix) begin
display_on_d1 <= 1'b0;
display_on_d2 <= 1'b0;
end else begin
display_on_d1 <= display_on;
display_on_d2 <= display_on_d1;
end
end
assign display_enable = display_on_d2;
always @(posedge pixclk) begin // キャラジェネROM、赤、緑、青のビット
if (reset_pix) begin
red_node <= 3'b111;
green_node <= 3'b111;
blue_node <= 3'b111;
char_data_node <= 0;
temp_color <= 0;
end else begin
if (h_addr[2:0] == 3'd2) begin // 最初の時、なぜ2かと言うと0でframe_bufferのアドレスが変化して、データが出るのが1クロック後、さらにそのデータからキャラクタROMのデータが出るのが更に1クロック後だから
char_data_node <= char_data[7:1];
temp_color <= display_dout[RED_DOT_POS : BLUE_DOT_POS-COLOR_ATTRIB_WIDHT+1]; // 最後に色データがなくなってしまうのでとりあえず保存しておく
if (char_data[0]==1'b1 && display_on_d2==1'b1) begin // 最初はシフトレジスタにロードするのと同時なので直接0ビット目を判定する。表示領域のときだけ映像信号を出力
red_node <= display_dout[RED_DOT_POS : RED_DOT_POS-COLOR_ATTRIB_WIDHT+1];
green_node <= display_dout[GREEN_DOT_POS : GREEN_DOT_POS-COLOR_ATTRIB_WIDHT+1];
blue_node <= display_dout[BLUE_DOT_POS : BLUE_DOT_POS-COLOR_ATTRIB_WIDHT+1];
end else begin
red_node <= 3'b000;
green_node <= 3'b000;
blue_node <= 3'b000;
end
end else begin
char_data_node <= {1'b0, char_data_node[6:1]}; // 1ビット右シフト
if (char_data_node[0]==1'b1 && display_on_d2==1'b1) begin // シフトデータを判定
red_node <= temp_color[RED_DOT_POS : RED_DOT_POS-COLOR_ATTRIB_WIDHT+1]; // 以降は保存した色データから判断
green_node <= temp_color[GREEN_DOT_POS : GREEN_DOT_POS-COLOR_ATTRIB_WIDHT+1];
blue_node <= temp_color[BLUE_DOT_POS : BLUE_DOT_POS-COLOR_ATTRIB_WIDHT+1];
end else begin
red_node <= 3'b000;
green_node <= 3'b000;
blue_node <= 3'b000;
end
end
end
end
assign VGA_RED = red_node;
assign VGA_GREEN = green_node;
assign VGA_BLUE = blue_node;
always @(posedge pixclk) begin // 表示するフレームバッファのアドレスを生成
if (reset_pix) begin
display_addr <= 0;
temp_pointer <= 0;
end else begin
if (display_on == 1'b1) begin // 1キャラクタのラスタが終了のときにアドレスを+1
if (h_addr[2:0] == 3'd7) // 1キャラクタのラスタが終了のときにアドレスを+1
display_addr <= display_addr + 1;
end else begin // 非表示領域
if (v_sync_0 == 1'b1) begin // 垂直同期のときはdisplay_addrを0クリア
display_addr <= 0;
temp_pointer <= 0;
end else if (h_sync_pulse == 1'b1) begin // 水平同期のとき
if (v_addr[2:0] == 3'd7) // 最後のラスタ
temp_pointer <= display_addr; // 現在のアドレス値+1になっているので、そのままtemp_pointerに入れる
else // それ以外のラスタのとき
display_addr <= temp_pointer;
end
end
end
end
always @(posedge pixclk) begin // 同期信号の位相を合わせる
if (reset_pix) begin
h_sync_1 <= 1'b0;
v_sync_1 <= 1'b0;
h_sync_2 <= 1'b0;
v_sync_2 <= 1'b0;
h_sync_3 <= 1'b0;
v_sync_3 <= 1'b0;
end else begin
h_sync_1 <= h_sync_0;
v_sync_1 <= v_sync_0;
h_sync_2 <= h_sync_1;
v_sync_2 <= v_sync_1;
h_sync_3 <= h_sync_2;
v_sync_3 <= v_sync_2;
end
end
assign VGA_HSYNC = !h_sync_3;
assign VGA_VSYNC = !v_sync_3;
endmodule
`default_nettype wire
// キャラクタジェネレータ用ROM
`default_nettype none
`timescale 1ns / 1ps
module char_gen_rom(clk, reset, char_addr, row_addr, dout);
input clk;
input reset;
input [6:0] char_addr;
input [2:0] row_addr;
output [7:0] dout;
wire clk;
wire reset;
wire [6:0] char_addr;
wire [2:0] row_addr;
wire [7:0] dout;
wire [10:0] addr;
assign addr = {1'b0, char_addr, row_addr};
RAMB16_S9 #(
.INIT_00(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_01(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_02(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_03(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_04(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_05(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_06(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_07(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_08(256'h0014147F147F1414000000000012243600080008080808080000000000000000), // #,",!,
.INIT_09(256'h0000000000081018004C322254081408002152240812254200083E483E093E08), // ',&,%,$
.INIT_0A(256'h000808087F08080800492A1C7F1C2A4900040810101008040020100808081020), // +,*,),(
.INIT_0B(256'h00010204081020400006060000000000000000007F0000000002040600000000), // /,.,-,,
.INIT_0C(256'h001C22201820221C003E02041820221C001C080808080C080018244242422418), // 3,2,1,0
.INIT_0D(256'h001010202040407E003C42423E02423C001E20201E02023E0020207E22242830), // 7,6,5,4
.INIT_0E(256'h0004080C00000C000000000C00000C00003C42407C42423C003C42423C42423C), // ;,:,9,8
.INIT_0F(256'h000800081020221C00040810201008040000003E003E00000020100804081020), // ?,>,=,<
.INIT_10(256'h001C22010101221C003F41413F41413F0041417F2236141C005C2A155549221E), // C,B,A,@
.INIT_11(256'h001C22710101221C000101013F01017F007F01013F01017F001F21414141211F), // G,F,E,D
.INIT_12(256'h0022120A060A1222000E11101010103E001C08080808081C004141417F414141), // K,J,I,H
.INIT_13(256'h001C22414141221C00416151494543410041414149556341003E020202020202),// O,N,M,L
.INIT_14(256'h003C42403C02423C002111093F41413F005C26594141221C000101013F41413F), // S,R,Q,P
.INIT_15(256'h00225555554949490008141422224141001C224141414141000808080808087F), // W,V,U,T
.INIT_16(256'h0038080808080838003F02040810203F00080808081422410041221408142241), // [,Z,Y,X
.INIT_17(256'h007F0000000000000000000000221408001C10101010101C0008083E083E1422), // _,^,],\
.INIT_18(256'h0038040438000000001E22221E020200003C223C201C00000000000000180810), // c,b,a,`
.INIT_19(256'h001C221C0C122C00000808081C081000001C021E221C0000003C22223C202000), // g,f,e,d
.INIT_1A(256'h0024140C14240400000C1210100010000008080800080000002424241C040400), // k,j,i,h
.INIT_1B(256'h0018242424180000002828282814000000545454542A00000018080808080800), // o,n,m,l
.INIT_1C(256'h0018201804180000000404040C34000000202038243800000004041C241C0000), // s,r,q,p
.INIT_1D(256'h00142A2A2A2200000008141422220000001824242424000000180808081C0800), // w,v,u,t
.INIT_1E(256'h001008080C080810003E0408103E000000020408142200000022140814220000), // {,z,y,x
.INIT_1F(256'h0000000000000000000000000000142800040808180808040008080808080808), // ,~,},|
.INIT_20(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_21(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_22(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_23(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_24(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_25(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_26(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_27(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_28(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_29(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_2A(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_2B(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_2C(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_2D(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_2E(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_2F(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_31(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_32(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_33(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_34(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_35(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_36(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_37(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_38(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_39(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_3A(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_3B(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_3C(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_3D(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_3E(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_3F(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INITP_00(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INITP_01(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INITP_02(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INITP_03(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INITP_04(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INITP_05(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INITP_06(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INITP_07(256'h0000000000000000000000000000000000000000000000000000000000000000)
) CHAR_GEN_ROM_INST (
.DO(dout),
.DOP(),
.ADDR(addr),
.CLK(clk),
.DI(8'd0),
.DIP(1'b0),
.EN(1'b1),
.SSR(reset),
.WE(1'b0)
);
endmodule
// video_timing_param.vh
//
parameter integer H_ACTIVE_VIDEO = (RESOLUTION==0) ? 640 : // VGA 25MHz
(RESOLUTION==1) ? 800 : // SVGA 40MHz
(RESOLUTION==2) ? 1024 : // XGA 65MHz
(RESOLUTION==3) ? 1280 : // SXGA 108MHz
(RESOLUTION==4) ? 1920 : 1920; // HD 148.5MHz
parameter integer H_FRONT_PORCH = (RESOLUTION==0) ? 16 : // VGA
(RESOLUTION==1) ? 40 : // SVGA
(RESOLUTION==2) ? 24 : // XGA
(RESOLUTION==3) ? 48 : // SXGA
(RESOLUTION==4) ? 88 : 88; // HD
parameter integer H_SYNC_PULSE = (RESOLUTION==0) ? 96 : // VGA
(RESOLUTION==1) ? 128 : // SVGA
(RESOLUTION==2) ? 136 : // XGA
(RESOLUTION==3) ? 112 : // SXGA
(RESOLUTION==4) ? 44 : 44; // HD
parameter integer H_BACK_PORCH = (RESOLUTION==0) ? 48 : // VGA
(RESOLUTION==1) ? 88 : // SVGA
(RESOLUTION==2) ? 160 : // XGA
(RESOLUTION==3) ? 248 : // SXGA
(RESOLUTION==4) ? 148 : 148; // HD
parameter integer V_ACTIVE_VIDEO = (RESOLUTION==0) ? 480 : // VGA
(RESOLUTION==1) ? 600 : // SVGA
(RESOLUTION==2) ? 768 : // XGA
(RESOLUTION==3) ? 1024 : // SXGA
(RESOLUTION==4) ? 1080 : 1080; // HD
parameter integer V_FRONT_PORCH = (RESOLUTION==0) ? 11 : // VGA
(RESOLUTION==1) ? 1 : // SVGA
(RESOLUTION==2) ? 2 : // XGA
(RESOLUTION==3) ? 1 : // SXGA
(RESOLUTION==4) ? 4 : 4; // HD
parameter integer V_SYNC_PULSE = (RESOLUTION==0) ? 2 : // VGA
(RESOLUTION==1) ? 4 : // SVGA
(RESOLUTION==2) ? 6 : // XGA
(RESOLUTION==3) ? 3 : // SXGA
(RESOLUTION==4) ? 5 : 5; // HD
parameter integer V_BACK_PORCH = (RESOLUTION==0) ? 31 : // VGA
(RESOLUTION==1) ? 23 : // SVGA
(RESOLUTION==2) ? 29 : // XGA
(RESOLUTION==3) ? 38 : // SXGA
(RESOLUTION==4) ? 36 : 36; // HD
parameter H_SUM = H_ACTIVE_VIDEO + H_FRONT_PORCH + H_SYNC_PULSE + H_BACK_PORCH;
parameter V_SUM = V_ACTIVE_VIDEO + V_FRONT_PORCH + V_SYNC_PULSE + V_BACK_PORCH;
parameter H_DISPLAY_SIZE = H_ACTIVE_VIDEO/8; // 横?桁
parameter V_DISPLAY_SIZE = V_ACTIVE_VIDEO/8; // 縦?行
parameter ALL_CHAR_SIZE = H_DISPLAY_SIZE*V_DISPLAY_SIZE;
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; // 色情報のビット幅
// function (log2, near_power2)
// convenient_functions.vh
//
// Beyond Circuts, Constant Function in Verilog 2001を参照しました
// http://www.beyond-circuits.com/wordpress/2008/11/constant-functions/
function integer log2;
input integer addr;
begin
addr = addr - 1;
for (log2=0; addr>0; log2=log2+1)
addr = addr >> 1;
end
endfunction
// 一番近く、より大きい2のn乗の値を返す
function integer near_power2;
input integer num;
begin
for (near_power2=2; near_power2<=num; )
near_power2=near_power2*2;
end
endfunction
package video_timing_pkg is
subtype RESLUTION_TYPE is integer range 0 to 4;
type VIDEO_RECORD is record
H_ACTIVE_VIDEO : integer range 640 to 1920;
H_FRONT_PORCH : integer;
H_SYNC_PULSE : integer;
H_BACK_PORCH : integer;
V_ACTIVE_VIDEO : integer range 480 to 1080;
V_FRONT_PORCH : integer;
V_SYNC_PULSE : integer;
V_BACK_PORCH : integer;
end record VIDEO_RECORD;
type VIDEO_RECORD_A is array (RESLUTION_TYPE) of VIDEO_RECORD;
constant CONST_VIDEO_R : VIDEO_RECORD_A := (
0 => ( H_ACTIVE_VIDEO => 640,
H_FRONT_PORCH => 16,
H_SYNC_PULSE => 96,
H_BACK_PORCH => 48,
V_ACTIVE_VIDEO => 480,
V_FRONT_PORCH => 11,
V_SYNC_PULSE => 2,
V_BACK_PORCH => 31
), -- VGA, 25MHz
1 => ( H_ACTIVE_VIDEO => 800,
H_FRONT_PORCH => 40,
H_SYNC_PULSE => 128,
H_BACK_PORCH => 88,
V_ACTIVE_VIDEO => 600,
V_FRONT_PORCH => 1,
V_SYNC_PULSE => 4,
V_BACK_PORCH => 23
), -- SVGA, 40MHz
2 => ( H_ACTIVE_VIDEO => 1024,
H_FRONT_PORCH => 24,
H_SYNC_PULSE => 136,
H_BACK_PORCH => 160,
V_ACTIVE_VIDEO => 768,
V_FRONT_PORCH => 2,
V_SYNC_PULSE => 6,
V_BACK_PORCH => 29
), -- XGA, 65MHz
3 => ( H_ACTIVE_VIDEO => 1280,
H_FRONT_PORCH => 48,
H_SYNC_PULSE => 112,
H_BACK_PORCH => 248,
V_ACTIVE_VIDEO => 1024,
V_FRONT_PORCH => 1,
V_SYNC_PULSE => 3,
V_BACK_PORCH => 38
), -- SXGA, 108MHz
4 => ( H_ACTIVE_VIDEO => 1920,
H_FRONT_PORCH => 88,
H_SYNC_PULSE => 44,
H_BACK_PORCH => 148,
V_ACTIVE_VIDEO => 1080,
V_FRONT_PORCH => 4,
V_SYNC_PULSE => 5,
V_BACK_PORCH => 36
) -- HD, 148.5MHz
);
end package video_timing_pkg;
-----------------------------------------------------------------------------
--
-- AXI Slave
--
-----------------------------------------------------------------------------
-- 2012/02/25 : S_AXI_AWBURST=1 (INCR) にのみ対応、AWSIZE, ARSIZE = 000 (1byte), 001 (2bytes), 010 (4bytes) のみ対応。
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use IEEE.math_real.all;
--library unisim;
--use unisim.vcomponents.all;
use work.video_timing_pkg.all;
entity cdc_vga_axi_slave is
generic (
C_S_AXI_ID_WIDTH : integer := 1;
C_S_AXI_ADDR_WIDTH : integer := 32;
C_S_AXI_DATA_WIDTH : integer := 32;
C_S_AXI_AWUSER_WIDTH : integer := 1;
C_S_AXI_ARUSER_WIDTH : integer := 1;
C_S_AXI_WUSER_WIDTH : integer := 1;
C_S_AXI_RUSER_WIDTH : integer := 1;
C_S_AXI_BUSER_WIDTH : integer := 1;
RESOLUTION : integer := 1 -- SVGA
);
port(
-- System Signals
ACLK : in std_logic;
ARESETN : in std_logic;
-- Slave Interface Write Address Ports
S_AXI_AWID : in std_logic_vector(C_S_AXI_ID_WIDTH-1 downto 0);
S_AXI_AWADDR : in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
S_AXI_AWLEN : in std_logic_vector(8-1 downto 0);
S_AXI_AWSIZE : in std_logic_vector(3-1 downto 0);
S_AXI_AWBURST : in std_logic_vector(2-1 downto 0);
S_AXI_AWLOCK : in std_logic_vector(2-1 downto 0);
S_AXI_AWCACHE : in std_logic_vector(4-1 downto 0);
S_AXI_AWPROT : in std_logic_vector(3-1 downto 0);
S_AXI_AWREGION : in std_logic_vector(4-1 downto 0);
S_AXI_AWQOS : in std_logic_vector(4-1 downto 0);
S_AXI_AWUSER : in std_logic_vector(C_S_AXI_AWUSER_WIDTH-1 downto 0);
S_AXI_AWVALID : in std_logic;
S_AXI_AWREADY : out std_logic;
-- Slave Interface Write Data Ports
S_AXI_WID : in std_logic_vector(C_S_AXI_ID_WIDTH-1 downto 0);
S_AXI_WDATA : in std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
S_AXI_WSTRB : in std_logic_vector(C_S_AXI_DATA_WIDTH/8-1 downto 0);
S_AXI_WLAST : in std_logic;
S_AXI_WUSER : in std_logic_vector(C_S_AXI_WUSER_WIDTH-1 downto 0);
S_AXI_WVALID : in std_logic;
S_AXI_WREADY : out std_logic;
-- Slave Interface Write Response Ports
S_AXI_BID : out std_logic_vector(C_S_AXI_ID_WIDTH-1 downto 0);
S_AXI_BRESP : out std_logic_vector(2-1 downto 0);
S_AXI_BUSER : out std_logic_vector(C_S_AXI_BUSER_WIDTH-1 downto 0);
S_AXI_BVALID : out std_logic;
S_AXI_BREADY : in std_logic;
-- Slave Interface Read Address Ports
S_AXI_ARID : in std_logic_vector(C_S_AXI_ID_WIDTH-1 downto 0);
S_AXI_ARADDR : in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
S_AXI_ARLEN : in std_logic_vector(8-1 downto 0);
S_AXI_ARSIZE : in std_logic_vector(3-1 downto 0);
S_AXI_ARBURST : in std_logic_vector(2-1 downto 0);
S_AXI_ARLOCK : in std_logic_vector(2-1 downto 0);
S_AXI_ARCACHE : in std_logic_vector(4-1 downto 0);
S_AXI_ARPROT : in std_logic_vector(3-1 downto 0);
S_AXI_ARREGION : in std_logic_vector(4-1 downto 0);
S_AXI_ARQOS : in std_logic_vector(4-1 downto 0);
S_AXI_ARUSER : in std_logic_vector(C_S_AXI_ARUSER_WIDTH-1 downto 0);
S_AXI_ARVALID : in std_logic;
S_AXI_ARREADY : out std_logic;
-- Slave Interface Read Data Ports
S_AXI_RID : out std_logic_vector(C_S_AXI_ID_WIDTH-1 downto 0);
S_AXI_RDATA : out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
S_AXI_RRESP : out std_logic_vector(2-1 downto 0);
S_AXI_RLAST : out std_logic;
S_AXI_RUSER : out std_logic_vector(C_S_AXI_RUSER_WIDTH-1 downto 0);
S_AXI_RVALID : out std_logic;
S_AXI_RREADY : in std_logic;
-- VGA Signals
pixclk : in std_logic;
reset_pixclk : in std_logic;
red_out : out std_logic_vector(4 downto 0);
green_out : out std_logic_vector(5 downto 0);
blue_out : out std_logic_vector(4 downto 0);
hsync_n : out std_logic;
vsync_n : out std_logic
);
end cdc_vga_axi_slave;
architecture implementation of cdc_vga_axi_slave is
constant VIDEO_PARAM : VIDEO_RECORD := CONST_VIDEO_R(RESOLUTION);
constant H_ACTIVE_VIDEO : integer := VIDEO_PARAM.H_ACTIVE_VIDEO;
constant V_ACTIVE_VIDEO : integer := VIDEO_PARAM.V_ACTIVE_VIDEO;
constant ALL_CHAR_SIZE : integer := (H_ACTIVE_VIDEO/8)*(V_ACTIVE_VIDEO/8);
constant CDC_ADDR_WIDTH : integer := natural(ceil(log(real(ALL_CHAR_SIZE), 2.0)));
component CharDispCtrler
generic(
RESOLUTION : integer := 4 -- HD
);
port(
axi4clk : in std_logic;
pixclk : in std_logic;
reset_axi : in std_logic;
reset_pix : in std_logic;
processor_addr : in std_logic_vector(CDC_ADDR_WIDTH-1 downto 0);
processor_din : in std_logic_vector(15 downto 0);
processor_dout : out std_logic_vector(15 downto 0);
processor_we : in std_logic;
VGA_RED : out std_logic_vector(2 downto 0);
VGA_GREEN : out std_logic_vector(2 downto 0);
VGA_BLUE : out std_logic_vector(2 downto 0);
VGA_HSYNC : out std_logic;
VGA_VSYNC : out std_logic;
display_enable : out std_logic
);
end component;
COMPONENT afifo_sm
PORT (
clk : IN STD_LOGIC;
rst : IN STD_LOGIC;
din : IN STD_LOGIC_VECTOR(15 DOWNTO 0);
wr_en : IN STD_LOGIC;
rd_en : IN STD_LOGIC;
dout : OUT STD_LOGIC_VECTOR(15 DOWNTO 0);
full : OUT STD_LOGIC;
almost_full : OUT STD_LOGIC;
overflow : OUT STD_LOGIC;
empty : OUT STD_LOGIC;
almost_empty : OUT STD_LOGIC;
underflow : OUT STD_LOGIC
);
END COMPONENT;
constant AxBURST_FIXED : std_logic_vector := "00";
constant AxBURST_INCR : std_logic_vector := "01";
constant AxBURST_WRAP : std_logic_vector := "10";
constant RESP_OKAY : std_logic_vector := "00";
constant RESP_EXOKAY : std_logic_vector := "01";
constant RESP_SLVERR : std_logic_vector := "10";
constant RESP_DECERR : std_logic_vector := "11";
-- for write transaction
type write_transaction_state is (idle_wr, awr_wait, awr_accept, wr_burst);
type write_response_state is (idle_wres, bvalid_assert);
type write_wready_state is (idle_wrdy, wready_assert);
signal wrt_cs : write_transaction_state;
signal wrres : write_response_state;
signal wrwr : write_wready_state;
-- for read transaction
type read_transaction_state is (idle_rd, arr_wait, arr_accept, rd_burst);
type read_last_state is (idle_rlast, rlast_assert);
signal rdt_cs : read_transaction_state;
signal rdlast : read_last_state;
signal reset_1d, reset_2d, reset_axi : std_logic := '1';
signal awready : std_logic;
signal wr_addr : std_logic_vector(CDC_ADDR_WIDTH-1 downto 0);
signal wr_bid : std_logic_vector(C_S_AXI_ID_WIDTH-1 downto 0);
signal wr_bresp : std_logic_vector(1 downto 0);
signal wr_bvalid : std_logic;
signal arready : std_logic;
signal rd_addr : std_logic_vector(CDC_ADDR_WIDTH-1 downto 0);
signal rd_axi_count : std_logic_vector(7 downto 0);
signal rd_cdc_count : std_logic_vector(8 downto 0);
signal rdfifo_din : std_logic_vector(15 downto 0);
signal rdfifo_wr_en : std_logic;
signal rdfifo_rd_en : std_logic;
signal rdfifo_full, rdfifo_empty : std_logic;
signal rdfifo_almost_full, rdfifo_almost_empty : std_logic;
signal rdfifo_overflow, rdfifo_underflow : std_logic;
signal rvalid : std_logic;
signal rlast : std_logic;
signal cdc_addr : std_logic_vector(CDC_ADDR_WIDTH-1 downto 0);
signal vga_red, vga_green, vga_blue : std_logic_vector(2 downto 0);
signal vga_red8, vga_green8, vga_blue8 : std_logic_vector(7 downto 0);
signal vga_hsync, vga_vsync : std_logic;
signal display_enable : std_logic;
signal cdc_we : std_logic;
signal rdfifo_wr_en_node : std_logic;
signal reset_p1d, reset_p2d, reset_pix : std_logic;
begin
-- ARESETN をACLK で同期化
process (ACLK) begin
if ACLK'event and ACLK='1' then
reset_1d <= not ARESETN;
reset_2d <= reset_1d;
end if;
end process;
reset_axi <= reset_2d;
-- reset_pix を pixclk で同期化
process (pixclk) begin
if pixclk'event and pixclk='1' then
reset_p1d <= reset_pixclk;
reset_p2d <= reset_p1d;
end if;
end process;
reset_pix <= reset_p2d;
-- AXI4バス Write Transaction State Machine
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset_axi='1' then
wrt_cs <= idle_wr;
awready <= '0';
else
case (wrt_cs) is
when idle_wr =>
if S_AXI_AWVALID='1' then -- S_AXI_AWVALID が1にアサートされた
if rdt_cs=idle_rd then -- Read Transaction が終了している(Writeの方が優先順位が高い)
wrt_cs <= awr_accept;
awready <= '1';
else -- Read Transaction が終了していないのでWait
wrt_cs <= awr_wait;
end if;
end if;
when awr_wait => -- Read Transaction の終了待ち
if rdt_cs=idle_rd or rdt_cs=arr_wait then -- Read Transaction が終了
wrt_cs <= awr_accept;
awready <= '1';
end if;
when awr_accept => -- S_AXI_AWREADY をアサート
wrt_cs <= wr_burst;
awready <= '0';
when wr_burst => -- Writeデータの転送
if S_AXI_WLAST='1' and S_AXI_WVALID='1' then -- Write Transaction 終了
wrt_cs <= idle_wr;
end if;
end case;
end if;
end if;
end process;
S_AXI_AWREADY <= awready;
S_AXI_WREADY <= '1' when wrt_cs=wr_burst else '0';
cdc_we <= '1' when wrt_cs=wr_burst and S_AXI_WVALID='1' else '0';
-- wr_addr の処理
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset_axi='1' then
wr_addr <= (others => '0');
else
if wrt_cs=awr_accept then
wr_addr <= S_AXI_AWADDR(CDC_ADDR_WIDTH+1 downto 2); -- 32ビット幅データのため
elsif wrt_cs=wr_burst and S_AXI_WVALID='1' then -- アドレスを1つ進める
wr_addr <= wr_addr + 1;
end if;
end if;
end if;
end process;
-- wr_bid の処理
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset_axi='1' then
wr_bid <= (others => '0');
else
if wrt_cs=awr_accept then
wr_bid <= S_AXI_AWID;
end if;
end if;
end if;
end process;
S_AXI_BID <= wr_bid;
-- wr_bresp の処理
-- S_AXI_AWBURSTがINCRの時はOKAYを返す。それ以外はSLVERRを返す。
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset_axi='1' then
wr_bresp <= (others => '0');
else
if wrt_cs=awr_accept then
if S_AXI_AWBURST=AxBURST_INCR then -- バーストタイプがアドレス・インクリメントタイプ
wr_bresp <= RESP_OKAY; -- Write Transaction は成功
else
wr_bresp <= RESP_SLVERR; -- エラー
end if;
end if;
end if;
end if;
end process;
S_AXI_BRESP <= wr_bresp;
-- wr_bvalid の処理
-- Write Transaction State Machineには含まない。axi_master のシミュレーションを見ると1クロックで終了しているので、長い間、Master側の都合でWaitしていることは考えない。
-- 次のWrite転送まで遅延しているようであれば、Write Transaction State Machine に入れてブロックすることも考える必要がある。
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset_axi='1' then
wr_bvalid <= '0';
else
if S_AXI_WLAST='1' and S_AXI_WVALID='1' then -- Write Transaction 終了
wr_bvalid <= '1';
elsif wr_bvalid='1' and S_AXI_BREADY='1' then -- wr_bvalid が1でMaster側のReadyも1ならばWrite resonse channel の転送も終了
wr_bvalid <= '0';
end if;
end if;
end if;
end process;
S_AXI_BVALID <= wr_bvalid;
S_AXI_BUSER <= (others => '0');
-- AXI4バス Read Transaction State Machine
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset_axi='1' then
rdt_cs <= idle_rd;
arready <= '0';
else
case (rdt_cs) is
when idle_rd =>
if S_AXI_ARVALID='1' then -- Read Transaction 要求
if wrt_cs=idle_wr and S_AXI_AWVALID='0' then -- Write Transaction State Machine がidle でWrite要求もない
rdt_cs <= arr_accept;
arready <= '1';
else -- Write Transaction が終了していないのでWait
rdt_cs <= arr_wait;
end if;
end if;
when arr_wait => -- Write Transaction の終了待ち
if wrt_cs=idle_wr and S_AXI_AWVALID='0' then -- Write Transaction State Machine がidle でWrite要求もない
rdt_cs <= arr_accept;
arready <= '1';
end if;
when arr_accept => -- S_AXI_ARREADY をアサート
rdt_cs <= rd_burst;
arready <= '0';
when rd_burst => -- Readデータの転送
if rd_axi_count=0 and rvalid='1' and S_AXI_RREADY='1' then -- Read Transaction 終了
rdt_cs <= idle_rd;
end if;
end case;
end if;
end if;
end process;
S_AXI_ARREADY <= arready;
-- rd_addr の処理
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset_axi='1' then
rd_addr <= (others => '0');
else
if rdt_cs=arr_accept then
rd_addr <= S_AXI_ARADDR(CDC_ADDR_WIDTH+1 downto 2); -- 32ビット幅データのため
elsif rdt_cs=rd_burst and rdfifo_almost_full='0' and rd_cdc_count/=0 then -- rdfifoに余裕があるときにはアドレスを1つ進める
rd_addr <= rd_addr + 1;
end if;
end if;
end if;
end process;
-- Read用FIFOのインスタンス
rdfifo : afifo_sm PORT MAP (
clk => ACLK,
rst => reset_axi,
din => rdfifo_din,
wr_en => rdfifo_wr_en,
rd_en => rdfifo_rd_en,
dout => S_AXI_RDATA(15 downto 0),
full => rdfifo_full,
almost_full => rdfifo_almost_full,
overflow => rdfifo_overflow,
empty => rdfifo_empty,
almost_empty => rdfifo_almost_empty,
underflow => rdfifo_underflow
);
S_AXI_RDATA(31 downto 16) <= (others => '0');
rvalid <= not rdfifo_empty;
S_AXI_RVALID <= rvalid;
rdfifo_wr_en_node <= '1' when rdt_cs=rd_burst and rdfifo_almost_full='0' and rd_cdc_count/=0 else '0';
-- BlockRAMのReadは1クロック遅延するため、1クロック遅延させる。
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset_axi='1' then
rdfifo_wr_en <= '0';
else
rdfifo_wr_en <= rdfifo_wr_en_node;
end if;
end if;
end process;
rdfifo_rd_en <= '1' when rdt_cs=rd_burst and rvalid='1' and S_AXI_RREADY='1' else '0';
-- rd_cdc_count の処理(CDC側のデータカウント)
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset_axi='1' then
rd_cdc_count <= (others => '0');
else
if rdt_cs=arr_accept then -- ロード
rd_cdc_count <= ('0'& S_AXI_ARLEN) + 1;
elsif rdt_cs=rd_burst and rdfifo_almost_full='0' and rd_cdc_count/=0 then -- FIFOに余裕がある
rd_cdc_count <= rd_cdc_count - 1;
end if;
end if;
end if;
end process;
-- rd_axi_count の処理(AXIバス側のデータカウント)
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset_axi='1' then
rd_axi_count <= (others => '0');
else
if rdt_cs=arr_accept then -- rd_axi_count のロード
rd_axi_count <= S_AXI_ARLEN;
elsif rdt_cs=rd_burst and rvalid='1' and S_AXI_RREADY='1' then -- Read Transaction が1つ終了
rd_axi_count <= rd_axi_count - 1;
end if;
end if;
end if;
end process;
-- rdlast State Machine
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset_axi='1' then
rdlast <= idle_rlast;
rlast <= '0';
else
case (rdlast) is
when idle_rlast =>
if rd_axi_count=1 and rvalid='1' and S_AXI_RREADY='1' then -- バーストする場合
rdlast <= rlast_assert;
rlast <= '1';
elsif rdt_cs=arr_accept and S_AXI_ARLEN=0 then -- 転送数が1の場合
rdlast <= rlast_assert;
rlast <= '1';
end if;
when rlast_assert =>
if rvalid='1' and S_AXI_RREADY='1' then -- Read Transaction 終了(rd_axi_count=0は決定)
rdlast <= idle_rlast;
rlast <= '0';
end if;
end case;
end if;
end if;
end process;
S_AXI_RLAST <= rlast;
-- S_AXI_RID, S_AXI_RUSER の処理
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset_axi='1' then
S_AXI_RID <= (others => '0');
else
if rdt_cs=arr_accept then
S_AXI_RID <= S_AXI_ARID;
end if;
end if;
end if;
end process;
S_AXI_RUSER <= (others => '0');
-- S_AXI_RRESP は、S_AXI_ARBURST がINCR の場合はOKAYを返す。それ以外はSLVERRを返す。
process (ACLK) begin
if ACLK'event and ACLK='1' then
if reset_axi='1' then
S_AXI_RRESP <= (others => '0');
else
if rdt_cs=arr_accept then
if S_AXI_ARBURST=AxBURST_INCR then
S_AXI_RRESP <= RESP_OKAY;
else
S_AXI_RRESP <= RESP_SLVERR;
end if;
end if;
end if;
end if;
end process;
-- CharDispCtrler
cdc_addr <= wr_addr when rdt_cs=idle_rd or rdt_cs=arr_wait else rd_addr;
CDC_inst : CharDispCtrler generic map(
RESOLUTION => RESOLUTION
) port map (
axi4clk => ACLK,
pixclk => pixclk,
reset_axi => reset_axi,
reset_pix => reset_pix,
processor_addr => cdc_addr,
processor_din => S_AXI_WDATA(15 downto 0),
processor_dout => rdfifo_din,
processor_we => cdc_we,
VGA_RED => vga_red,
VGA_GREEN => vga_green,
VGA_BLUE => vga_blue,
VGA_HSYNC => vga_hsync,
VGA_VSYNC => vga_vsync,
display_enable => display_enable
);
vga_red8 <= vga_red & "00000";
vga_green8 <= vga_green & "00000";
vga_blue8 <= vga_blue & "00000";
-- VGA Signals
process( pixclk ) begin
if pixclk'event and pixclk='1' then
if reset_pix = '1' then
red_out <= (others => '0');
green_out <= (others => '0');
blue_out <= (others => '0');
hsync_n <= '1';
vsync_n <= '1';
else
red_out <= vga_red8(7 downto 3);
green_out <= vga_green8(7 downto 2);
blue_out <= vga_blue8(7 downto 3);
hsync_n <= vga_hsync;
vsync_n <= vga_vsync;
end if;
end if;
end process ;
end implementation;
から、
LED_Display_Counter <= LED_Display_Counter + 4'd1;
に変更した。
LED_Display_Counter <= LED_Display_Counter - 4'd1;
を
LED_Display_Counter <= 4'd0;
に変更したが、LEDの表示は3 にはならなかった。ARESETNが 0 になることはないのか?ハードウェアをコンフィギュレーションしたあとで。。。
LED_Display_Counter <= 4'd3;
set_property IOSTANDARD LVCMOS33 [get_ports {blue_out[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {blue_out[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {blue_out[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {blue_out[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {blue_out[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {green_out[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {green_out[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {green_out[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {green_out[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {green_out[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {green_out[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {red_out[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {red_out[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {red_out[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {red_out[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {red_out[0]}]
set_property PACKAGE_PIN G19 [get_ports {blue_out[4]}]
set_property PACKAGE_PIN J18 [get_ports {blue_out[3]}]
set_property PACKAGE_PIN K19 [get_ports {blue_out[2]}]
set_property PACKAGE_PIN M20 [get_ports {blue_out[1]}]
set_property PACKAGE_PIN P20 [get_ports {blue_out[0]}]
set_property PACKAGE_PIN F20 [get_ports {green_out[5]}]
set_property PACKAGE_PIN H20 [get_ports {green_out[4]}]
set_property PACKAGE_PIN J19 [get_ports {green_out[3]}]
set_property PACKAGE_PIN L19 [get_ports {green_out[2]}]
set_property PACKAGE_PIN N20 [get_ports {green_out[1]}]
set_property PACKAGE_PIN H18 [get_ports {green_out[0]}]
set_property PACKAGE_PIN F19 [get_ports {red_out[4]}]
set_property PACKAGE_PIN G20 [get_ports {red_out[3]}]
set_property PACKAGE_PIN J20 [get_ports {red_out[2]}]
set_property PACKAGE_PIN L20 [get_ports {red_out[1]}]
set_property PACKAGE_PIN M19 [get_ports {red_out[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports hsync_n]
set_property IOSTANDARD LVCMOS33 [get_ports vsync_n]
set_property PACKAGE_PIN P19 [get_ports hsync_n]
set_property PACKAGE_PIN R19 [get_ports vsync_n]
library ieee;
use ieee.std_logic_1164.all;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use IEEE.math_real.all;
--library unisim;
--use unisim.vcomponents.all;
use work.video_timing_pkg.all;
entity cdc_vga_axi_slave is
generic (
C_S_AXI_ID_WIDTH : integer := 1;
C_S_AXI_ADDR_WIDTH : integer := 32;
C_S_AXI_DATA_WIDTH : integer := 32;
C_S_AXI_AWUSER_WIDTH : integer := 1;
C_S_AXI_ARUSER_WIDTH : integer := 1;
C_S_AXI_WUSER_WIDTH : integer := 1;
C_S_AXI_RUSER_WIDTH : integer := 1;
C_S_AXI_BUSER_WIDTH : integer := 1;
RESOLUTION : RESLUTION_TYPE := 1 -- SVGA
);
port(
-- System Signals
ACLK : in std_logic;
ARESETN : in std_logic;
-- Slave Interface Write Address Ports
S_AXI_AWID : in std_logic_vector(C_S_AXI_ID_WIDTH-1 downto 0);
S_AXI_AWADDR : in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
subtype RESLUTION_TYPE is integer range 0 to 4;
<spirit:modelParameter spirit:dataType="RESLUTION_TYPE">
<spirit:name>RESOLUTION</spirit:name>
<spirit:displayName>Resolution</spirit:displayName>
<spirit:value spirit:format="long" spirit:resolve="generated" spirit:id="MODELPARAM_VALUE.RESOLUTION">1</spirit:value>
</spirit:modelParameter>
これでOK。<spirit:modelParameter spirit:dataType="integer">
<spirit:name>RESOLUTION</spirit:name>
<spirit:displayName>Resolution</spirit:displayName>
<spirit:value spirit:format="long" spirit:resolve="generated" spirit:id="MODELPARAM_VALUE.RESOLUTION">1</spirit:value>
</spirit:modelParameter>
masaaki@masaaki-VirtualBox:~/Parallella$ sudo fdisk -l | grep Disk
Disk /dev/sda: 214.7 GB, 214748364800 bytes
Disk /dev/sdc: 15.9 GB, 15931539456 bytes
”VivadoでZYBOのAXI4 Slave キャラクタ・ディスプレイ・コントローラ IP1(新規プロジェクトの生成)”
”VivadoでZYBOのAXI4 Slave キャラクタ・ディスプレイ・コントローラ IP2(FIFOの生成)”
”VivadoでZYBOのAXI4 Slave キャラクタ・ディスプレイ・コントローラ IP3(単体シミュレーション)”
ERROR: [VRFC 10-1540] value for parameter FB_MEM_SIZE is not constant [C:/Users/Masaaki/Documents/Vivado/Zynq/ZYBO/IP_test/cdc_vga_axi_slave/cdc_vga_axi_slave.srcs/sources_1/imports/hdl/verilog/frame_buffer.v:31]
ERROR: [XSIM 43-3322] Static elaboration of top level Verilog design unit(s) in library work failed.K/pre>
module frame_buffer # (
parameter integer RESOLUTION = 1 // SVGA
)
(clka, clkb, reset_a, reset_b, processor_addr, processor_din, processor_dout, processor_we, display_addr, display_dout);
`include "video_timing_param.vh"
`include "convenient_functions.vh"
input clka;
input clkb;
input reset_a;
input reset_b;
input [log2(ALL_CHAR_SIZE)-1:0] processor_addr;
input [15:0] processor_din;
output [15:0] processor_dout;
input processor_we;
input [log2(ALL_CHAR_SIZE)-1:0] display_addr;
output [15:0] display_dout;
parameter integer FB_MEM_SIZE = near_power2(ALL_CHAR_SIZE);
// 一番近く、より大きい2のn乗の値を返す
function integer near_power2;
input integer num;
begin
for (near_power2=2; near_power2<=num; near_power2=near_power2*2);
end
endfunction
parameter ALL_CHAR_SIZE = H_DISPLAY_SIZE*V_DISPLAY_SIZE;
function integer near_power2;
input integer num;
begin
for (near_power2=2; near_power2<=num; )
near_power2=near_power2*2;
end
endfunction
================================================================================
Timing constraint: TS_clk_fpga_0 = PERIOD TIMEGRP "clk_fpga_0" 100 MHz HIGH 50%;
For more information, see Period Analysis in the Timing Closure User Guide (UG612).
3814414 paths analyzed, 74771 endpoints analyzed, 43 failing endpoints
43 timing errors detected. (43 setup errors, 0 hold errors, 0 component switching limit errors)
Minimum period is 10.631ns.
--------------------------------------------------------------------------------
Paths for end point system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/tmp_i_37_reg_859_9 (SLICE_X82Y21.CIN), 244131 paths
--------------------------------------------------------------------------------
Slack (setup path): -0.631ns (requirement - (data path - clock path skew + uncertainty))
Source: system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ap_reg_ppstg_exitcond_reg_804_pp0_it3_0 (FF)
Destination: system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/tmp_i_37_reg_859_9 (FF)
Requirement: 10.000ns
Data Path Delay: 10.564ns (Levels of Logic = 13)
Clock Path Skew: -0.032ns (0.158 - 0.190)
Source Clock: system_i/processing_system7_0_FCLK_CLK0 rising at 0.000ns
Destination Clock: system_i/processing_system7_0_FCLK_CLK0 rising at 10.000ns
Clock Uncertainty: 0.035ns
Clock Uncertainty: 0.035ns ((TSJ^2 + TIJ^2)^1/2 + DJ) / 2 + PE
Total System Jitter (TSJ): 0.070ns
Total Input Jitter (TIJ): 0.000ns
Discrete Jitter (DJ): 0.000ns
Phase Error (PE): 0.000ns
Maximum Data Path at Slow Process Corner: system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ap_reg_ppstg_exitcond_reg_804_pp0_it3_0 to system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/tmp_i_37_reg_859_9
Location Delay type Delay(ns) Physical Resource
Logical Resource(s)
------------------------------------------------- -------------------
SLICE_X83Y14.CQ Tcko 0.456 system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ap_reg_ppstg_exitcond_reg_804_pp0_it3_0
system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ap_reg_ppstg_exitcond_reg_804_pp0_it3_0
SLICE_X81Y14.C3 net (fanout=4) 0.673 system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ap_reg_ppstg_exitcond_reg_804_pp0_it3_0
SLICE_X81Y14.C Tilo 0.124 system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/current_2_V_1_fu_84<7>
system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/Mmux_current_2_V_phi_fu_247_p41101_1
SLICE_X81Y14.D4 net (fanout=6) 0.458 system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/Mmux_current_2_V_phi_fu_247_p41101
SLICE_X81Y14.D Tilo 0.124 system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/current_2_V_1_fu_84<7>
system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd1_lut<0>
SLICE_X80Y15.A5 net (fanout=1) 0.465 system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd1_lut<0>
SLICE_X80Y15.COUT Topcya 0.656 system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd1_cy<3>
system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd1_lut<0>_rt
system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd1_cy<3>
SLICE_X80Y16.CIN net (fanout=1) 0.000 system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd1_cy<3>
SLICE_X80Y16.CMUX Tcinc 0.417 system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd_71
system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd1_cy<7>
SLICE_X81Y18.C4 net (fanout=1) 0.900 system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd_61
SLICE_X81Y18.CMUX Tilo 0.356 system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/y_reg_869<7>
system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd26
SLICE_X81Y18.D5 net (fanout=2) 0.422 system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd26
SLICE_X81Y18.COUT Topcyd 0.525 system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/y_reg_869<7>
system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd2_lut<0>7
system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd2_cy<0>_6
SLICE_X81Y19.CIN net (fanout=1) 0.000 system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd2_cy<0>7
SLICE_X81Y19.DMUX Tcind 0.495 system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd_102
system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd2_xor<0>_10
SLICE_X83Y18.C6 net (fanout=33) 0.446 system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd_112
SLICE_X83Y18.C Tilo 0.124 system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/current_0_V_1_fu_76<3>
system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/Mmux_current_0_V_phi_fu_238_p431
SLICE_X83Y19.C4 net (fanout=1) 0.571 system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/current_0_V_phi_fu_238_p4<2>
SLICE_X83Y19.CMUX Tilo 0.356 system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd_36
system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd62
SLICE_X83Y19.DX net (fanout=2) 0.617 system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd62
SLICE_X83Y19.COUT Tdxcy 0.385 system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd_36
system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd6_cy<0>_2
SLICE_X83Y20.CIN net (fanout=1) 0.000 system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd6_cy<0>3
SLICE_X83Y20.BQ Tito_logic 0.674 system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd_76
system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd6_cy<0>_6
system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd_56_rt
SLICE_X82Y20.B4 net (fanout=1) 0.449 system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd_56
SLICE_X82Y20.COUT Topcyb 0.657 system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/tmp_i_37_reg_859<7>
system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd7_lut<5>
system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd7_cy<7>
SLICE_X82Y21.CIN net (fanout=1) 0.000 system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd7_cy<7>
SLICE_X82Y21.CLK Tcinck 0.214 system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/tmp_i_37_reg_859<11>
system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/ADDERTREE_INTERNAL_Madd7_xor<11>
system_i/lap_filter_axim_top_0/lap_filter_axim_top_0/lap_filter_axim_U/grp_filter_line_fu_397/tmp_i_37_reg_859_9
------------------------------------------------- ---------------------------
Total 10.564ns (5.563ns logic, 5.001ns route)
(52.7% logic, 47.3% route)
// laplacian_filter.cpp
// lap_filter_axim()
#include <stdio.h>
#include <string.h>
#include <ap_int.h>
#define HORIZONTAL_PIXEL_WIDTH 800
#define VERTICAL_PIXEL_WIDTH 600
#define ALL_PIXEL_VALUE (HORIZONTAL_PIXEL_WIDTH*VERTICAL_PIXEL_WIDTH)
int laplacian_fil(int x0y0, int x1y0, int x2y0, int x0y1, int x1y1, int x2y1, int x0y2, int x1y2, int x2y2);
int conv_rgb2y(int rgb);
void conv_line(unsigned int* buf){
for (int b=0; b<HORIZONTAL_PIXEL_WIDTH; b++){
#pragma HLS pipeline
buf[b] = conv_rgb2y(buf[b]); // カラーから白黒へ
}
}
void filter_line(unsigned int* lap_buf, unsigned int* fl, unsigned int* sl, unsigned int* tl){
int lap_fil_val;
ap_uint<8> prev[3],current[3],next[3]; // 0->1ライン目, 1->2ライン目, 2->3ライン目, prev->1pixel前, current->現在, next->次pixel
#pragma HLS array_partition variable=prev complete dim=0
#pragma HLS array_partition variable=current complete dim=0
#pragma HLS array_partition variable=next complete dim=0
next[0] = fl[0] & 0xFF;
next[1] = sl[0] & 0xFF;
next[2] = sl[0] & 0xFF;
for (int x = 0; x < HORIZONTAL_PIXEL_WIDTH; x++){
#pragma HLS pipeline
if (x == 0 || x == HORIZONTAL_PIXEL_WIDTH-1){
lap_fil_val = 0;
current[0] = next[0];
next[0] = fl[1];
current[1] = next[1];
next[1] = sl[1];
current[2] = next[2];
next[2] = tl[1];
}else{
prev[0] = current[0];
current[0] = next[0];
next[0] = fl[x+1];
prev[1] = current[1];
current[1] = next[1];
next[1] = sl[x+1];
prev[2] = current[2];
current[2] = next[2];
next[2] = tl[x+1];
lap_fil_val = laplacian_fil(prev[0], current[0], next[0],
prev[1], current[1], next[1],
prev[2], current[2], next[2]);
}
lap_buf[x] = (lap_fil_val<<16)+(lap_fil_val<<8)+lap_fil_val; // RGB同じ値を入れる
}
}
int lap_filter_axim(int cam_addr, int lap_addr, volatile int *cam_fb, volatile int *lap_fb)
{
#pragma HLS RESOURCE variable=cam_addr core=AXI4LiteS metadata="-bus_bundle LiteS"
#pragma HLS RESOURCE variable=lap_addr core=AXI4LiteS metadata="-bus_bundle LiteS"
#pragma HLS RESOURCE variable=return core=AXI4LiteS metadata="-bus_bundle LiteS"
#pragma HLS INTERFACE ap_bus port=cam_fb depth=480000
#pragma HLS INTERFACE ap_bus port=lap_fb depth=480000
#pragma HLS RESOURCE variable=cam_fb core=AXI4M
#pragma HLS RESOURCE variable=lap_fb core=AXI4M
unsigned int line_buf[3][HORIZONTAL_PIXEL_WIDTH];
#pragma HLS array_partition variable line_buf block factor=3 dim=1
#pragma HLS resource variable=line_buf core=RAM_2P
unsigned int lap_buf[HORIZONTAL_PIXEL_WIDTH];
int x, y;
int lap_fil_val;
int a, b;
int fl, sl, tl;
unsigned int offset_cam_addr, offset_lap_addr;
int *cam_fb_addr, *lap_fb_addr;
offset_cam_addr = cam_addr/sizeof(int);
offset_lap_addr = lap_addr/sizeof(int);
// RGB値をY(輝度成分)のみに変換し、ラプラシアンフィルタを掛けた。
for (y=1; y<VERTICAL_PIXEL_WIDTH-1; y++){
fl = (y-1)%3; // 最初のライン, y=1 012, y=2 120, y=3 201, y=4 012
sl = y%3; // 2番めのライン
tl = (y+1)%3; // 3番目のライン
if (y == 1){
#ifndef __SYNTHESIS__
printf("copy 3 lines\n");
#endif
for (a=0; a<3; a++){ // 3ライン分
cam_fb_addr = (int*)(cam_fb+offset_cam_addr+(a*(HORIZONTAL_PIXEL_WIDTH)));
memcpy(line_buf[a], (unsigned int*)cam_fb_addr, HORIZONTAL_PIXEL_WIDTH*sizeof(int));
conv_line(line_buf[a]);
}
}else{ // 最初のラインではないので、1ラインだけ読み込む。すでに他の2ラインは読み込まれている
cam_fb_addr = (int*)(cam_fb+offset_cam_addr+((y+1)*(HORIZONTAL_PIXEL_WIDTH)));
memcpy(line_buf[tl], (unsigned int*)cam_fb_addr, HORIZONTAL_PIXEL_WIDTH*sizeof(int));
conv_line(line_buf[tl]);
}
filter_line(lap_buf, line_buf[fl], line_buf[sl], line_buf[tl]);
lap_fb_addr = (int *)(lap_fb+offset_lap_addr+(y*(HORIZONTAL_PIXEL_WIDTH)));
#ifndef __SYNTHESIS__
printf("write back:%d\n", y);
#endif
memcpy((unsigned int*)lap_fb_addr, (unsigned int*)lap_buf, HORIZONTAL_PIXEL_WIDTH*sizeof(int));
}
// 最初と最後のラインは0にする
for (x = 0; x < HORIZONTAL_PIXEL_WIDTH; x++)
lap_buf[x] = 0;
lap_fb_addr = (int *)(lap_fb+offset_lap_addr+(0*(HORIZONTAL_PIXEL_WIDTH)));
memcpy((unsigned int*)lap_fb_addr, (unsigned int*)lap_buf, HORIZONTAL_PIXEL_WIDTH*sizeof(int));
lap_fb_addr = (int *)(lap_fb+offset_lap_addr+(VERTICAL_PIXEL_WIDTH-1)*HORIZONTAL_PIXEL_WIDTH);
memcpy((unsigned int*)lap_fb_addr, (unsigned int*)lap_buf, HORIZONTAL_PIXEL_WIDTH*sizeof(int));
#if 0
for (x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
if (y==0 || y==VERTICAL_PIXEL_WIDTH-1){ // 縦の境界の時の値は0とする
lap_fil_val = 0;
}else if (x==0 || x==HORIZONTAL_PIXEL_WIDTH-1){ // 横の境界の時も値は0とする
lap_fil_val = 0;
}else{
if (x == 1){ // ラインの最初でラインの画素を読み出す
if (y == 1){ // 最初のラインでは3ライン分の画素を読み出す
for (a=0; a<3; a++){ // 3ライン分
cam_fb_addr = (int*)(cam_fb+offset_cam_addr+(a*(HORIZONTAL_PIXEL_WIDTH)));
memcpy(&line_buf[a][0], (const int*)cam_fb_addr, HORIZONTAL_PIXEL_WIDTH*sizeof(int));
for (b=0; b<HORIZONTAL_PIXEL_WIDTH; b++){ // ライン
#pragma HLS pipeline
line_buf[a][b] = conv_rgb2y(line_buf[a][b]); // カラーから白黒へ
}
}
} else {
cam_fb_addr = (int*)(cam_fb+offset_cam_addr+((y+1)*(HORIZONTAL_PIXEL_WIDTH)));
memcpy(line_buf[(y+1)%3], (const int*)cam_fb_addr, HORIZONTAL_PIXEL_WIDTH*sizeof(int));
for (b=0; b<HORIZONTAL_PIXEL_WIDTH; b++){ // ライン
#pragma HLS pipeline
line_buf[(y+1)%3][b] = conv_rgb2y(line_buf[(y+1)%3][b]); // カラーから白黒へ
}
}
}
lap_fil_val = laplacian_fil(line_buf[fl][x-1], line_buf[fl][x], line_buf[fl][x+1], line_buf[sl][x-1], line_buf[sl][x], line_buf[sl][x+1], line_buf[tl][x-1], line_buf[tl][x], line_buf[tl][x+1]);
}
lap_buf[x] = (lap_fil_val<<16)+(lap_fil_val<<8)+lap_fil_val; // RGB同じ値を入れる
}
lap_fb_addr = (int *)(lap_fb+offset_lap_addr+(y*(HORIZONTAL_PIXEL_WIDTH)));
memcpy(lap_fb_addr, (const int*)lap_buf, HORIZONTAL_PIXEL_WIDTH*sizeof(int));
}
#endif
return(7);
}
// RGBからYへの変換
// RGBのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 輝度信号Yのみに変換する。変換式は、Y = 0.299R + 0.587G + 0.114B
// "YUVフォーマット及び YUV<->RGB変換"を参考にした。http://vision.kuee.kyoto-u.ac.jp/~hiroaki/firewire/yuv.html
// 2013/09/27 : float を止めて、すべてint にした
int conv_rgb2y(int rgb){
int r, g, b, y_f;
int y;
b = rgb & 0xff;
g = (rgb>>8) & 0xff;
r = (rgb>>16) & 0xff;
y_f = 77*r + 150*g + 29*b; //y_f = 0.299*r + 0.587*g + 0.114*b;の係数に256倍した
y = y_f >> 8; // 256で割る
return(y);
}
// ラプラシアンフィルタ
// x0y0 x1y0 x2y0 -1 -1 -1
// x0y1 x1y1 x2y1 -1 8 -1
// x0y2 x1y2 x2y2 -1 -1 -1
int laplacian_fil(int x0y0, int x1y0, int x2y0, int x0y1, int x1y1, int x2y1, int x0y2, int x1y2, int x2y2)
{
int y;
y = -x0y0 -x1y0 -x2y0 -x0y1 +8*x1y1 -x2y1 -x0y2 -x1y2 -x2y2;
if (y<0)
y = 0;
else if (y>255)
y = 255;
return(y);
}
というものです。”How to fix “X: user not authorized to run the X server, aborting.”? ”にそのバグ・フィックスの方法が書いてありました。X: user not authorized to run the X server, aborting.
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
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 | - | - | - | - | - |