PIN "dcm_DDR2_VGA_clk_i/dcm_VGA_clk_dcm.CLKFX" TNM = VGA_CLK_OUTPUT;
PIN "ddr2_sdram_cont_i/dcm_module_inst/DCM_INST1.CLK0" TNM = DDR2_CLK_OUTPUT;
TIMESPEC TS_VGA2DDR2_CLK_TIG = FROM "VGA_CLK_OUTPUT" TO "DDR2_CLK_OUTPUT" TIG;
TIMESPEC TS_DDR22VGA_CLK_TIG = FROM "DDR2_CLK_OUTPUT" TO "VGA_CLK_OUTPUT" TIG;
関連する資料
Spartan3A Starter KitのビットマップVGAコントローラの仕様1
Spartan3A Starter KitのビットマップVGAコントローラの仕様2
キャラクタ生成コントローラの仕様
キャラクタ生成コントローラの仕様2
parameter DECODE_ADDRESS_LENGTH = 4; // デーコードするアドレス長、上のビットから何ビットデーコードするか。
parameter CHAR_GEN_CONTROLLER_ADDR = DECODE_ADDRESS_LENGTH'hF; // キャラクタ生成コントローラのアドレスマップ
parameter DDR2_SDRAM_ADDR = DECODE_ADDRESS_LENGTH'h0;cpu_address <= {CHAR_GEN_CONTROLLER_ADDR, (DECODE_ADDRESS_LENGTH-8)'d4, 4'd0};
cpu_address <= {CHAR_GEN_CONTROLLER_ADDR, (32-(DECODE_ADDRESS_LENGTH+4))'d4, 4'd0};
`define DCODE_ADDRESS_LENGTH 4 // デーコードするアドレス長、上のビットから何ビットデーコードするか。
parameter CHAR_GEN_CONTROLLER_ADDR = `DECODE_ADDRESS_LENGTH'hF; // キャラクタ生成コントローラのアドレスマップ
parameter DDR2_SDRAM_ADDR = `DECODE_ADDRESS_LENGTH'h0;cpu_address <= {CHAR_GEN_CONTROLLER_ADDR, (32-(`DECODE_ADDRESS_LENGTH+4))'d4, 4'd0};
parameter DECODE_ADDRESS_LENGTH = 4; // デーコードするアドレス長、上のビットから何ビットデーコードするか。
parameter CHAR_GEN_CONTROLLER_ADDR = 4'hF; // キャラクタ生成コントローラのアドレスマップ
parameter DDR2_SDRAM_ADDR = 4'h0;
cpu_address[31:31-(DECODE_ADDRESS_LENGTH-1)] <= CHAR_GEN_CONTROLLER_ADDR;
cpu_address[31-(DECODE_ADDRESS_LENGTH):4] <= 4;
cpu_address[3:0] <= 4'd0;
// Address_Map_Define.vh
// アドレスマップを定義する
parameter DECODE_ADDRESS_LENGTH = 4; // デーコードするアドレス長、上のビットから何ビットデーコードするか。
parameter CHAR_GEN_CONTROLLER_ADDR = 4'hF; // キャラクタ生成コントローラのアドレスマップ
parameter DDR2_SDRAM_ADDR = 4'h0;
// Command_Status_Define.vh
// Command Registers
// 0番地の割り当て
parameter CHAR_CODE_UPPER_HIGH = 31; // キャラクタ・コードの上位バイト
parameter CHAR_CODE_UPPER_LOW = 24;
parameter CHAR_CODE_LOWER_HIGH = 23; // キャラクタ・コードの下位バイト
parameter CHAR_CODE_LOWER_LOW = 16;
parameter NOT_PAINTED_BACKGROUND = 15; // 0 - 文字の背景を塗りつぶす, 1 - 文字の背景を塗りつぶさない
parameter DRAW_IMMEDIATELY = 14; // 0 - 8番地の書き込みを待つ, 1 - 0番地の書き込みだけで描画
parameter RED_FEILD_HIGH = 11;
parameter RED_FEILD_LOW = 8;
parameter GREEN_FEILD_HIGH = 7;
parameter GREEN_FEILD_LOW = 4;
parameter BLUE_FEILD_HIGH = 3;
parameter BLUE_FEILD_LOW = 0;
// 4番地の割り当て
parameter MAGNIFICATION_HIGH = 15; // 拡大倍率
parameter MAGNIFICATION_LOW = 11;
// Red, Green, Blue の割り当ては0番地と同じ
// 8番地の割り当て
parameter VRAM_START_ADDRESS_HIGH = 31;
parameter VRAM_START_ADDRESS_LOW = 0;
// Status Register
parameter FIFO_COUNT_HIGH = 4;
parameter FIFO_COUNT_LOW = 0;
// 各領域のビット幅
`define CHAR_CODE_UPPER_WIDTH 8
`define CHAR_CODE_LOWER_WIDTH 8
`define RED_FEILD_WIDTH 4
parameter RED_FEILD_WIDTH = 4;
`define GREEN_FEILD_WIDTH 4
parameter GREEN_FEILD_WIDTH = 4;
`define BLUE_FEILD_WIDTH 4
parameter BLUE_FEILD_WIDTH = 4;
`define MAGNIFICATION_WIDTH 5
`define VRAM_START_ADDRESS_WIDTH 32
`define FIFO_COUNT_WIDTH 5
// テスト用キャラクタ描画モジュール
// Char_Draw_for_Test.v
//
// グラフィックメモリの先頭からキャラクタを描画する。0~9まで、A~Zまで描画したら元に戻る。背景色は黒とする
// Char_Gen_Controller.v のCPUのインターフェースを操作する。
// DDR2 SDRAMは64Mbytes, よって先頭を0x0とすると0x3FF_FFFFまで。
// グラフィックメモリは1024X768X2bytes = 1,572,864 bytes = 0x18_0000
// グラフィックメモリは0x300_0000からとする
// キャラクタは128X96文字 = 12,288文字を1画面に描画できる
`default_nettype none
module Char_Draw_for_Test (clk_vga, reset_vga, cpu_address, cpu_write_data, cpu_read_data, cpu_data_we);
input wire clk_vga; // VGAのクロック、65MHzの予定
input wire reset_vga; // clk_vga用リセット
output reg [31:0] cpu_address; // CPUのアドレス
output wire [31:0] cpu_write_data; // CPUのWrite データ
input wire [31:0] cpu_read_data; // CPUのRead データ
output reg cpu_data_we; // CPUのデータ入力のWrite Enable
`include "Address_Map_Define.vh"
`include "Command_Status_Define.vh"
parameter idle_char = 6'b000001;
parameter CGC_first_cmd0_set = 6'b000010;
parameter CGC_cmd4_set = 6'b000100;
parameter CGC_cmd8_set = 6'b001000;
parameter Wait_CGC_cmd0 = 6'b010000;
parameter CGC_cmd0_loop = 6'b100000;
reg [5:0] cs_char;
reg [7:0] char_code_count; // キャラクタのカウンタ
reg [RED_FEILD_HIGH:RED_FEILD_LOW] red_count;
reg [GREEN_FEILD_HIGH:GREEN_FEILD_LOW] green_count;
reg [BLUE_FEILD_HIGH:BLUE_FEILD_LOW] blue_count;
wire op_ena;
reg [13:0] vram_disp_count;
reg [31:0] cmd_data;
// 周波数分周
freqdiv #(.DIVISOR(3250000)) // 65MHzを20Hzにする
freqdiv_inst (
.clk(clk_vga),
.reset(reset_vga),
.op_ena(op_ena)
);
// キャラクタを書きまくるステートマシン
always @(posedge clk_vga) begin
if (reset_vga)
cs_char <= idle_char;
else begin
case (cs_char)
idle_char :
cs_char <= CGC_first_cmd0_set;
CGC_first_cmd0_set : // キャラクタ生成コントローラの0番地に最初のキャラクタと色をセット
cs_char <= CGC_cmd4_set;
CGC_cmd4_set : // キャラクタ生成コントローラの4番地背景色、倍率をセット
cs_char <= CGC_cmd8_set;
CGC_cmd8_set : // キャラクタ生成コントローラの8番地アドレスをセットして1キャラクタ描画
cs_char <= Wait_CGC_cmd0;
Wait_CGC_cmd0 : // 次のキャラクタを書くまでのWait
if ((cpu_read_data[FIFO_COUNT_HIGH:FIFO_COUNT_LOW]<5'h01110) && op_ena)
cs_char <= CGC_cmd0_loop;
CGC_cmd0_loop : // ループしながらキャラクタと色を+1しながら
if (vram_disp_count>14'd12287) // 1画面描画済み
cs_char <= CGC_first_cmd0_set;
else
cs_char <= Wait_CGC_cmd0;
endcase
end
end
// キャラクタ生成コントローラのコマンドデータの用意
always @(posedge clk_vga) begin
if (reset_vga) begin
cpu_address <= 32'd0;
cmd_data <= 32'd0;
cpu_data_we <= 1'b0;
end else begin
case (cs_char)
idle_char :begin
cpu_address <= 32'd0;
cmd_data <= 32'd0;
cpu_data_we <= 1'b0;
end
CGC_first_cmd0_set : begin
cpu_address[31:31-(DECODE_ADDRESS_LENGTH-1)] <= CHAR_GEN_CONTROLLER_ADDR;
cpu_address[31-(DECODE_ADDRESS_LENGTH):4] <= 0;
cpu_address[3:0] <= 4'd0;
cmd_data[CHAR_CODE_UPPER_HIGH:CHAR_CODE_UPPER_LOW] <= 0;
cmd_data[CHAR_CODE_LOWER_HIGH:CHAR_CODE_LOWER_LOW] <= `CHAR_CODE_LOWER_WIDTH'h30; // 0x30
cmd_data[NOT_PAINTED_BACKGROUND] <= 1'b0; // 背景を塗りつぶす
cmd_data[DRAW_IMMEDIATELY] <= 1'b0; // アドレスの書き込みを待つ
cmd_data[DRAW_IMMEDIATELY-1 : RED_FEILD_HIGH+1] <= 0;
cmd_data[RED_FEILD_HIGH:RED_FEILD_LOW] <= red_count;
cmd_data[GREEN_FEILD_HIGH:GREEN_FEILD_LOW] <= green_count;
cmd_data[BLUE_FEILD_HIGH:BLUE_FEILD_LOW] <= blue_count;
cpu_data_we <= 1'b1;
end
CGC_cmd4_set : begin
cpu_address[31:31-(DECODE_ADDRESS_LENGTH-1)] <= CHAR_GEN_CONTROLLER_ADDR;
cpu_address[31-(DECODE_ADDRESS_LENGTH):4] <= 0;
cpu_address[3:0] <= 4'd4;
cmd_data[31:MAGNIFICATION_HIGH+1] <= 0;
cmd_data[MAGNIFICATION_HIGH:MAGNIFICATION_LOW] <= 0; // 倍率1倍
cmd_data[RED_FEILD_HIGH:RED_FEILD_LOW] <= `RED_FEILD_WIDTH'd0;
cmd_data[GREEN_FEILD_HIGH:GREEN_FEILD_LOW] <= `GREEN_FEILD_WIDTH'd0;
cmd_data[BLUE_FEILD_HIGH:BLUE_FEILD_LOW] <= `BLUE_FEILD_WIDTH'd0;
cpu_data_we <= 1'b1;
end
CGC_cmd8_set : begin
cpu_address[31:31-(DECODE_ADDRESS_LENGTH-1)] <= CHAR_GEN_CONTROLLER_ADDR;
cpu_address[31-(DECODE_ADDRESS_LENGTH):4] <= 0;
cpu_address[3:0] <= 4'd8;
cmd_data <= VRAM_START_ADDRESS;
cpu_data_we <= 1'b1;
end
Wait_CGC_cmd0 : begin
cpu_address[31:31-(DECODE_ADDRESS_LENGTH-1)] <= CHAR_GEN_CONTROLLER_ADDR;
cpu_address[31-(DECODE_ADDRESS_LENGTH):4] <= 0;
cpu_address[3:0] <= 4'd0;
cmd_data[CHAR_CODE_UPPER_HIGH:CHAR_CODE_UPPER_LOW] <= 0;
cmd_data[CHAR_CODE_LOWER_HIGH:CHAR_CODE_LOWER_LOW] <= char_code_count;
cmd_data[NOT_PAINTED_BACKGROUND] <= 1'b0; // 背景を塗りつぶす
cmd_data[DRAW_IMMEDIATELY] <= 1'b1; // アドレスの書き込みを待つ
cmd_data[DRAW_IMMEDIATELY-1 : RED_FEILD_HIGH+1] <= 0;
cmd_data[RED_FEILD_HIGH:RED_FEILD_LOW] <= red_count;
cmd_data[GREEN_FEILD_HIGH:GREEN_FEILD_LOW] <= green_count;
cmd_data[BLUE_FEILD_HIGH:BLUE_FEILD_LOW] <= blue_count;
cpu_data_we <= 1'b0;
end
CGC_cmd0_loop : begin
cpu_address[31:31-(DECODE_ADDRESS_LENGTH-1)] <= CHAR_GEN_CONTROLLER_ADDR;
cpu_address[31-(DECODE_ADDRESS_LENGTH):4] <= 0;
cpu_address[3:0] <= 4'd0;
cmd_data[CHAR_CODE_UPPER_HIGH:CHAR_CODE_UPPER_LOW] <= 0;
cmd_data[CHAR_CODE_LOWER_HIGH:CHAR_CODE_LOWER_LOW] <= char_code_count;
cmd_data[NOT_PAINTED_BACKGROUND] <= 1'b0; // 背景を塗りつぶす
cmd_data[DRAW_IMMEDIATELY] <= 1'b1; // アドレスの書き込みを待つ
cmd_data[DRAW_IMMEDIATELY-1 : RED_FEILD_HIGH+1] <= 0;
cmd_data[RED_FEILD_HIGH:RED_FEILD_LOW] <= red_count;
cmd_data[GREEN_FEILD_HIGH:GREEN_FEILD_LOW] <= green_count;
cmd_data[BLUE_FEILD_HIGH:BLUE_FEILD_LOW] <= blue_count;
cpu_data_we <= 1'b1;
end
endcase
end
end
assign cpu_write_data = cmd_data;
// vram_disp_count の処理
always @(posedge clk_vga) begin
if (reset_vga)
vram_disp_count <= 14'd0;
else
if (cs_char==CGC_cmd8_set || cs_char==CGC_cmd0_loop) begin
if (vram_disp_count>14'd12287)
vram_disp_count <= 14'd0;
else
vram_disp_count <= vram_disp_count + 14'd0;
end
end
// キャラクタのカウンタ
always @(posedge clk_vga) begin
if (reset_vga)
char_code_count <= 8'h30;
else begin
if (cs_char==CGC_cmd8_set || cs_char==CGC_cmd0_loop) begin
if (char_code_count==8'h39) // 9
char_code_count <= 8'h41; // A
else if (char_code_count==8'h5A) // Z
char_code_count <= 8'h61; // a
else if (char_code_count==8'h7A) // z
char_code_count <= 8'h30; // 0
else
char_code_count <= char_code_count + 8'd1;
end
end
end
// Red のカウント
always @(posedge clk_vga) begin
if (reset_vga)
red_count <= {RED_FEILD_WIDTH{1'b1}};
else
if (cs_char==CGC_cmd8_set || cs_char==CGC_cmd0_loop)
red_count <= red_count - `RED_FEILD_WIDTH'd1;
end
// Green のカウント
always @(posedge clk_vga) begin
if (reset_vga)
green_count <= {GREEN_FEILD_WIDTH{1'b1}};
else
if ((cs_char==CGC_cmd8_set || cs_char==CGC_cmd0_loop) && red_count==`RED_FEILD_WIDTH'd0) // Redが0の時に-1
green_count <= green_count - `GREEN_FEILD_WIDTH'd1;
end
// Blue のカウント
always @(posedge clk_vga) begin
if (reset_vga)
blue_count <= {BLUE_FEILD_WIDTH{1'b1}};
else
if ((cs_char==CGC_cmd8_set || cs_char==CGC_cmd0_loop) && green_count==`GREEN_FEILD_WIDTH'd0) // Greenが0の時に-1
blue_count <= blue_count - `BLUE_FEILD_WIDTH'd1;
end
endmodule
// 各領域のビット幅
`define CHAR_CODE_UPPER_WIDTH 8
`define CHAR_CODE_LOWER_WIDTH 8
`define RED_FEILD_WIDTH 4
`define GREEN_FEILD_WIDTH 4
`define BLUE_FEILD_WIDTH 4
`define MAGNIFICATION_WIDTH 5
`define VRAM_START_ADDRESS_WIDTH 32
`define FIFO_COUNT_WIDTH 5
parameter RED_FEILD_WIDTH = `RED_FEILD_WIDTH;
parameter GREEN_FEILD_WIDTH = `GREEN_FEILD_WIDTH;
parameter BLUE_FEILD_WIDTH = `BLUE_FEILD_WIDTH;
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
- | - | - | - | - | 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 |