Files
ciciec2026_loongson/rtl/ip/DVI/axi_dvi.v

254 lines
8.4 KiB
Verilog

module axi_dvi #
(
parameter WIDTH = 12, // hdata and vdata width (in bits)
parameter HSIZE = 800, // Horizontal size of visible area
parameter HFP = 856, // Horizontal front porch
parameter HSP = 976, // Horizontal sync pulse
parameter HMAX = 1040, // Horizontal total size
parameter VSIZE = 600, // Vertical size of visible area
parameter VFP = 637, // Vertical front porch
parameter VSP = 643, // Vertical sync pulse
parameter VMAX = 666, // Vertical total size
parameter HSPP = 1, // Horizontal sync pulse polarity (1 for positive)
parameter VSPP = 1 // Vertical sync pulse polarity (1 for positive)
)
(
input s_awvalid,
output s_awready,
input [31:0] s_awaddr,
input [4:0] s_awid,
input [7:0] s_awlen,
input [2:0] s_awsize,
input [1:0] s_awburst,
input [0:0] s_awlock,
input [3:0] s_awcache,
input [2:0] s_awprot,
input s_wvalid,
output reg s_wready,
input [31:0] s_wdata,
input [3:0] s_wstrb,
input s_wlast,
output reg s_bvalid,
input s_bready,
output [4:0] s_bid,
output [1:0] s_bresp,
input s_arvalid,
output s_arready,
input [31:0] s_araddr,
input [4:0] s_arid,
input [7:0] s_arlen,
input [2:0] s_arsize,
input [1:0] s_arburst,
input [0:0] s_arlock,
input [3:0] s_arcache,
input [2:0] s_arprot,
output reg s_rvalid,
input s_rready,
output reg [31:0] s_rdata,
output [4:0] s_rid,
output [1:0] s_rresp,
output reg s_rlast,
output video_clk, // Video clock signal
output hsync, // Horizontal sync signal
output vsync, // Vertical sync signal
output data_enable, // Data enable signal
output [2:0] video_red, // Red color signal (3 bits)
output [2:0] video_green, // Green color signal (3 bits)
output [1:0] video_blue, // Blue color signal (2 bits)
input aclk,
input aresetn
);
reg [31:0] DVI_RECT_DIR,DVI_RECT_L_W,DVI_SQU_DIR,DVI_SQU_R;
reg busy,write,R_or_W;
wire ar_enter = s_arvalid & s_arready;
wire r_retire = s_rvalid & s_rready & s_rlast;
wire aw_enter = s_awvalid & s_awready;
wire w_enter = s_wvalid & s_wready & s_wlast;
wire b_retire = s_bvalid & s_bready;
assign s_arready = ~busy & (!R_or_W| !s_awvalid);
assign s_awready = ~busy & ( R_or_W| !s_arvalid);
always@(posedge aclk)
if(~aresetn) busy <= 1'b0;
else if(ar_enter|aw_enter) busy <= 1'b1;
else if(r_retire|b_retire) busy <= 1'b0;
reg [3 :0] buf_id;
reg [31:0] buf_addr;
reg [7 :0] buf_len;
reg [2 :0] buf_size;
reg [1 :0] buf_burst;
reg buf_lock;
reg [3 :0] buf_cache;
reg [2 :0] buf_prot;
always@(posedge aclk) begin
if(~aresetn) begin
R_or_W <= 1'b0;
buf_id <= 'b0;
buf_addr <= 'b0;
buf_len <= 'b0;
buf_size <= 'b0;
buf_burst <= 'b0;
buf_lock <= 'b0;
buf_cache <= 'b0;
buf_prot <= 'b0;
end
else
if(ar_enter | aw_enter) begin
R_or_W <= ar_enter;
buf_id <= ar_enter ? s_arid : s_awid ;
buf_addr <= ar_enter ? s_araddr : s_awaddr ;
buf_len <= ar_enter ? s_arlen : s_awlen ;
buf_size <= ar_enter ? s_arsize : s_awsize ;
buf_burst <= ar_enter ? s_arburst: s_awburst;
buf_lock <= ar_enter ? s_arlock : s_awlock ;
buf_cache <= ar_enter ? s_arcache: s_awcache;
buf_prot <= ar_enter ? s_arprot : s_awprot ;
end
end
always@(posedge aclk)
if(~aresetn) write <= 1'b0;
else if(aw_enter) write <= 1'b1;
else if(ar_enter) write <= 1'b0;
always@(posedge aclk)
if(~aresetn) s_wready <= 1'b0;
else if(aw_enter) s_wready <= 1'b1;
else if(w_enter & s_wlast) s_wready <= 1'b0;
wire [31:0] rdata_d = buf_addr[15:0] == 16'h0 ? DVI_RECT_DIR :
buf_addr[15:0] == 16'h4 ? DVI_RECT_L_W :
buf_addr[15:0] == 16'h8 ? DVI_SQU_DIR :
buf_addr[15:0] == 16'hc ? DVI_SQU_R :
32'd0;
always@(posedge aclk)begin
if(~aresetn) begin
s_rdata <= 'b0;
s_rvalid <= 1'b0;
s_rlast <= 1'b0;
end
else if(busy & !write & !r_retire)
begin
s_rdata <= rdata_d;
s_rvalid <= 1'b1;
s_rlast <= 1'b1;
end
else if(r_retire)
begin
s_rvalid <= 1'b0;
end
end
always@(posedge aclk) begin
if(~aresetn) s_bvalid <= 1'b0;
else if(w_enter) s_bvalid <= 1'b1;
else if(b_retire) s_bvalid <= 1'b0;
end
assign s_rid = buf_id;
assign s_bid = buf_id;
assign s_bresp = 2'b0;
assign s_rresp = 2'b0;
//-------------------------------{dvi controller}begin----------------------------//
wire write_reg_en[3:0];
assign write_reg_en[0] = w_enter & (buf_addr[15:0]==16'h0);
assign write_reg_en[1] = w_enter & (buf_addr[15:0]==16'h4);
assign write_reg_en[2] = w_enter & (buf_addr[15:0]==16'h8);
assign write_reg_en[3] = w_enter & (buf_addr[15:0]==16'hc);
always @(posedge aclk) begin
if(!aresetn) begin
DVI_RECT_DIR <= 32'h0;
end
else if (write_reg_en[0]) begin
DVI_RECT_DIR <= s_wdata;
end
end
always @(posedge aclk) begin
if(!aresetn) begin
DVI_RECT_L_W <= 32'h0;
end
else if (write_reg_en[1]) begin
DVI_RECT_L_W <= s_wdata;
end
end
always @(posedge aclk) begin
if(!aresetn) begin
DVI_SQU_DIR <= 32'h0;
end
else if (write_reg_en[2]) begin
DVI_SQU_DIR <= s_wdata;
end
end
always @(posedge aclk) begin
if(!aresetn) begin
DVI_SQU_R <= 32'h0;
end
else if (write_reg_en[3]) begin
DVI_SQU_R <= s_wdata;
end
end
reg [WIDTH-1:0] hdata = 0; // Horizontal position counter
reg [WIDTH-1:0] vdata = 0; // Vertical position counter
wire hdata_in_range;
wire vdata_in_range;
wire hdata1_in_range;
wire vdata1_in_range;
always @(posedge aclk) begin
if (hdata == (HMAX - 1)) // If horizontal counter reaches max
hdata <= 0; // Reset horizontal counter
else
hdata <= hdata + 1; // Increment horizontal counter
end
// Vertical counter (vdata) logic
always @(posedge aclk) begin
if (hdata == (HMAX - 1)) begin
if (vdata == (VMAX - 1)) // If vertical counter reaches max
vdata <= 0; // Reset vertical counter
else
vdata <= vdata + 1; // Increment vertical counter
end
end
// Horizontal sync signal generation (hsync)
assign video_clk = aclk; // Example: using input clock as video clock
assign hsync = ((hdata >= HFP) && (hdata < HSP)) ? HSPP : !HSPP;
assign vsync = ((vdata >= VFP) && (vdata < VSP)) ? VSPP : !VSPP;
assign data_enable = ((hdata < HSIZE) & (vdata < VSIZE));
assign hdata_in_range = (hdata > (DVI_RECT_DIR[31:16]-DVI_RECT_L_W[31:16])) && (hdata < (DVI_RECT_DIR[31:16]+DVI_RECT_L_W[31:16]));
// Check if vdata is in the range specified by DVI_RECT_L_W
assign vdata_in_range = (vdata > DVI_RECT_DIR[15:0]) && (vdata <(DVI_RECT_DIR[15:0]+DVI_RECT_L_W[15:0]));
assign hdata1_in_range = (hdata > (DVI_SQU_DIR[31:16]-DVI_SQU_R[31:16])) && (hdata < (DVI_SQU_DIR[31:16]+DVI_SQU_R[31:16]));
// Check if vdata is in the range specified by DVI_RECT_L_W
assign vdata1_in_range = (vdata > (DVI_SQU_DIR[15:0]-DVI_SQU_R[15:0])) && (vdata <(DVI_SQU_DIR[15:0]+DVI_SQU_R[15:0]));
// Set video output colors based on conditions
assign video_red = ((hdata_in_range && vdata_in_range)||(hdata1_in_range && vdata1_in_range)) ? 3'b111 : 3'b0;
assign video_green = 3'b0;
assign video_blue = 2'b0;
//--------------------------------{dvi controller}end-----------------------------//
endmodule