mirror of
git://projects.qi-hardware.com/nn-usb-fpga.git
synced 2025-04-21 12:27:27 +03:00
Updating examples to Board changes, adding irq driver demo
This commit is contained in:
229
lm32/logic/sakc/cores/vgafb/rtl/vgafb.v
Normal file
229
lm32/logic/sakc/cores/vgafb/rtl/vgafb.v
Normal file
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Milkymist VJ SoC
|
||||
* Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
module vgafb #(
|
||||
parameter csr_addr = 4'h0,
|
||||
parameter fml_depth = 26
|
||||
) (
|
||||
input sys_clk,
|
||||
input sys_rst,
|
||||
|
||||
/* Configuration interface */
|
||||
input [13:0] csr_a,
|
||||
input csr_we,
|
||||
input [31:0] csr_di,
|
||||
output [31:0] csr_do,
|
||||
|
||||
/* Framebuffer FML 4x64 interface */
|
||||
output [fml_depth-1:0] fml_adr,
|
||||
output fml_stb,
|
||||
input fml_ack,
|
||||
input [63:0] fml_di,
|
||||
|
||||
/* VGA pixel clock */
|
||||
input vga_clk,
|
||||
|
||||
/* VGA signal pads */
|
||||
output vga_psave_n,
|
||||
output reg vga_hsync_n,
|
||||
output reg vga_vsync_n,
|
||||
output vga_sync_n,
|
||||
output vga_blank_n,
|
||||
output reg [7:0] vga_r,
|
||||
output reg [7:0] vga_g,
|
||||
output reg [7:0] vga_b,
|
||||
output [1:0] vga_clk_sel
|
||||
);
|
||||
|
||||
/*
|
||||
* Control interface
|
||||
*/
|
||||
wire vga_rst;
|
||||
|
||||
wire [10:0] hres;
|
||||
wire [10:0] hsync_start;
|
||||
wire [10:0] hsync_end;
|
||||
wire [10:0] hscan;
|
||||
|
||||
wire [10:0] vres;
|
||||
wire [10:0] vsync_start;
|
||||
wire [10:0] vsync_end;
|
||||
wire [10:0] vscan;
|
||||
|
||||
wire [fml_depth-1:0] baseaddress;
|
||||
wire baseaddress_ack;
|
||||
|
||||
wire [17:0] nbursts;
|
||||
|
||||
vgafb_ctlif #(
|
||||
.csr_addr(csr_addr),
|
||||
.fml_depth(fml_depth)
|
||||
) ctlif (
|
||||
.sys_clk(sys_clk),
|
||||
.sys_rst(sys_rst),
|
||||
|
||||
.csr_a(csr_a),
|
||||
.csr_we(csr_we),
|
||||
.csr_di(csr_di),
|
||||
.csr_do(csr_do),
|
||||
|
||||
.vga_rst(vga_rst),
|
||||
|
||||
.hres(hres),
|
||||
.hsync_start(hsync_start),
|
||||
.hsync_end(hsync_end),
|
||||
.hscan(hscan),
|
||||
|
||||
.vres(vres),
|
||||
.vsync_start(vsync_start),
|
||||
.vsync_end(vsync_end),
|
||||
.vscan(vscan),
|
||||
|
||||
.baseaddress(baseaddress),
|
||||
.baseaddress_ack(baseaddress_ack),
|
||||
|
||||
.nbursts(nbursts),
|
||||
|
||||
.vga_clk_sel(vga_clk_sel)
|
||||
);
|
||||
|
||||
/*
|
||||
* Generate signal data
|
||||
*/
|
||||
reg hsync_n;
|
||||
reg vsync_n;
|
||||
wire pixel_valid;
|
||||
wire [15:0] pixel_fb;
|
||||
wire pixel_ack;
|
||||
wire [15:0] pixel;
|
||||
|
||||
wire fifo_full;
|
||||
|
||||
reg hactive;
|
||||
reg vactive;
|
||||
wire active = hactive & vactive;
|
||||
assign pixel = active ? pixel_fb : 16'h0000;
|
||||
|
||||
wire generate_en;
|
||||
|
||||
reg [10:0] hcounter;
|
||||
reg [10:0] vcounter;
|
||||
|
||||
always @(posedge sys_clk) begin
|
||||
if(vga_rst) begin
|
||||
hcounter <= 10'd0;
|
||||
vcounter <= 10'd0;
|
||||
hactive <= 1'b0;
|
||||
hsync_n <= 1'b1;
|
||||
vactive <= 1'b0;
|
||||
vsync_n <= 1'b1;
|
||||
end else begin
|
||||
if(generate_en) begin
|
||||
hcounter <= hcounter + 10'd1;
|
||||
|
||||
if(hcounter == 10'd0) hactive <= 1'b1;
|
||||
if(hcounter == hres) hactive <= 1'b0;
|
||||
if(hcounter == hsync_start) hsync_n <= 1'b0;
|
||||
if(hcounter == hsync_end) hsync_n <= 1'b1;
|
||||
if(hcounter == hscan) begin
|
||||
hcounter <= 10'd0;
|
||||
if(vcounter == vscan)
|
||||
vcounter <= 10'd0;
|
||||
else
|
||||
vcounter <= vcounter + 10'd1;
|
||||
end
|
||||
|
||||
if(vcounter == 10'd0) vactive <= 1'b1;
|
||||
if(vcounter == vres) vactive <= 1'b0;
|
||||
if(vcounter == vsync_start) vsync_n <= 1'b0;
|
||||
if(vcounter == vsync_end) vsync_n <= 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign generate_en = ~fifo_full & (~active | pixel_valid);
|
||||
assign pixel_ack = ~fifo_full & active & pixel_valid;
|
||||
|
||||
vgafb_pixelfeed #(
|
||||
.fml_depth(fml_depth)
|
||||
) pixelfeed (
|
||||
.sys_clk(sys_clk),
|
||||
.sys_rst(sys_rst),
|
||||
.vga_rst(vga_rst),
|
||||
|
||||
.nbursts(nbursts),
|
||||
.baseaddress(baseaddress),
|
||||
.baseaddress_ack(baseaddress_ack),
|
||||
|
||||
.fml_adr(fml_adr),
|
||||
.fml_stb(fml_stb),
|
||||
.fml_ack(fml_ack),
|
||||
.fml_di(fml_di),
|
||||
|
||||
.pixel_valid(pixel_valid),
|
||||
.pixel(pixel_fb),
|
||||
.pixel_ack(pixel_ack)
|
||||
);
|
||||
|
||||
/*
|
||||
* System clock to VGA clock domain crossing is
|
||||
* acheived by an asynchronous FIFO.
|
||||
*
|
||||
* Bits 0-15 are RGB565 pixel data
|
||||
* Bit 16 is negated Horizontal Sync
|
||||
* Bit 17 is negated Verical Sync
|
||||
*/
|
||||
wire [17:0] fifo_do;
|
||||
|
||||
vgafb_asfifo #(
|
||||
.DATA_WIDTH(18),
|
||||
.ADDRESS_WIDTH(6)
|
||||
) fifo (
|
||||
.Data_out(fifo_do),
|
||||
.Empty_out(),
|
||||
.ReadEn_in(1'b1),
|
||||
.RClk(vga_clk),
|
||||
|
||||
.Data_in({vsync_n, hsync_n, pixel}),
|
||||
.Full_out(fifo_full),
|
||||
.WriteEn_in(generate_en),
|
||||
.WClk(sys_clk),
|
||||
|
||||
.Clear_in(vga_rst)
|
||||
);
|
||||
|
||||
/*
|
||||
* Drive the VGA pads.
|
||||
* RGB565 -> RGB888 color space conversion is also performed here
|
||||
* by bit shifting and replicating the most significant bits of
|
||||
* the input into the least significant bits of the output left
|
||||
* undefined by the shifting.
|
||||
*/
|
||||
|
||||
assign vga_sync_n = 1'b0; /* Sync-on-Green is not implemented */
|
||||
assign vga_psave_n = 1'b1;
|
||||
assign vga_blank_n = 1'b1;
|
||||
|
||||
always @(posedge vga_clk) begin
|
||||
vga_vsync_n <= fifo_do[17];
|
||||
vga_hsync_n <= fifo_do[16];
|
||||
vga_r <= {fifo_do[15:11], fifo_do[15:13]};
|
||||
vga_g <= {fifo_do[10:5], fifo_do[10:9]};
|
||||
vga_b <= {fifo_do[4:0], fifo_do[4:2]};
|
||||
end
|
||||
|
||||
endmodule
|
||||
116
lm32/logic/sakc/cores/vgafb/rtl/vgafb_asfifo.v
Normal file
116
lm32/logic/sakc/cores/vgafb/rtl/vgafb_asfifo.v
Normal file
@@ -0,0 +1,116 @@
|
||||
//==========================================
|
||||
// Function : Asynchronous FIFO (w/ 2 asynchronous clocks).
|
||||
// Coder : Alex Claros F.
|
||||
// Date : 15/May/2005.
|
||||
// Notes : This implementation is based on the article
|
||||
// 'Asynchronous FIFO in Virtex-II FPGAs'
|
||||
// writen by Peter Alfke. This TechXclusive
|
||||
// article can be downloaded from the
|
||||
// Xilinx website. It has some minor modifications.
|
||||
//=========================================
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module vgafb_asfifo
|
||||
#(parameter DATA_WIDTH = 8,
|
||||
ADDRESS_WIDTH = 4,
|
||||
FIFO_DEPTH = (1 << ADDRESS_WIDTH))
|
||||
//Reading port
|
||||
(output wire [DATA_WIDTH-1:0] Data_out,
|
||||
output reg Empty_out,
|
||||
input wire ReadEn_in,
|
||||
input wire RClk,
|
||||
//Writing port.
|
||||
input wire [DATA_WIDTH-1:0] Data_in,
|
||||
output reg Full_out,
|
||||
input wire WriteEn_in,
|
||||
input wire WClk,
|
||||
|
||||
input wire Clear_in);
|
||||
|
||||
/////Internal connections & variables//////
|
||||
reg [DATA_WIDTH-1:0] Mem [FIFO_DEPTH-1:0];
|
||||
wire [ADDRESS_WIDTH-1:0] pNextWordToWrite, pNextWordToRead;
|
||||
wire EqualAddresses;
|
||||
wire NextWriteAddressEn, NextReadAddressEn;
|
||||
wire Set_Status, Rst_Status;
|
||||
reg Status;
|
||||
wire PresetFull, PresetEmpty;
|
||||
|
||||
//////////////Code///////////////
|
||||
//Data ports logic:
|
||||
//(Uses a dual-port RAM).
|
||||
//'Data_out' logic:
|
||||
assign Data_out = Mem[pNextWordToRead];
|
||||
// always @ (posedge RClk)
|
||||
// if (!PresetEmpty)
|
||||
// Data_out <= Mem[pNextWordToRead];
|
||||
// if (ReadEn_in & !Empty_out)
|
||||
|
||||
//'Data_in' logic:
|
||||
always @ (posedge WClk)
|
||||
if (WriteEn_in & !Full_out)
|
||||
Mem[pNextWordToWrite] <= Data_in;
|
||||
|
||||
//Fifo addresses support logic:
|
||||
//'Next Addresses' enable logic:
|
||||
assign NextWriteAddressEn = WriteEn_in & ~Full_out;
|
||||
assign NextReadAddressEn = ReadEn_in & ~Empty_out;
|
||||
|
||||
//Addreses (Gray counters) logic:
|
||||
vgafb_graycounter #(
|
||||
.COUNTER_WIDTH( ADDRESS_WIDTH )
|
||||
) GrayCounter_pWr (
|
||||
.GrayCount_out(pNextWordToWrite),
|
||||
.Enable_in(NextWriteAddressEn),
|
||||
.Clear_in(Clear_in),
|
||||
|
||||
.Clk(WClk)
|
||||
);
|
||||
|
||||
vgafb_graycounter #(
|
||||
.COUNTER_WIDTH( ADDRESS_WIDTH )
|
||||
) GrayCounter_pRd (
|
||||
.GrayCount_out(pNextWordToRead),
|
||||
.Enable_in(NextReadAddressEn),
|
||||
.Clear_in(Clear_in),
|
||||
.Clk(RClk)
|
||||
);
|
||||
|
||||
|
||||
//'EqualAddresses' logic:
|
||||
assign EqualAddresses = (pNextWordToWrite == pNextWordToRead);
|
||||
|
||||
//'Quadrant selectors' logic:
|
||||
assign Set_Status = (pNextWordToWrite[ADDRESS_WIDTH-2] ~^ pNextWordToRead[ADDRESS_WIDTH-1]) &
|
||||
(pNextWordToWrite[ADDRESS_WIDTH-1] ^ pNextWordToRead[ADDRESS_WIDTH-2]);
|
||||
|
||||
assign Rst_Status = (pNextWordToWrite[ADDRESS_WIDTH-2] ^ pNextWordToRead[ADDRESS_WIDTH-1]) &
|
||||
(pNextWordToWrite[ADDRESS_WIDTH-1] ~^ pNextWordToRead[ADDRESS_WIDTH-2]);
|
||||
|
||||
//'Status' latch logic:
|
||||
always @ (Set_Status, Rst_Status, Clear_in) //D Latch w/ Asynchronous Clear & Preset.
|
||||
if (Rst_Status | Clear_in)
|
||||
Status = 0; //Going 'Empty'.
|
||||
else if (Set_Status)
|
||||
Status = 1; //Going 'Full'.
|
||||
|
||||
//'Full_out' logic for the writing port:
|
||||
assign PresetFull = Status & EqualAddresses; //'Full' Fifo.
|
||||
|
||||
always @ (posedge WClk, posedge PresetFull) //D Flip-Flop w/ Asynchronous Preset.
|
||||
if (PresetFull)
|
||||
Full_out <= 1;
|
||||
else
|
||||
Full_out <= 0;
|
||||
|
||||
//'Empty_out' logic for the reading port:
|
||||
assign PresetEmpty = ~Status & EqualAddresses; //'Empty' Fifo.
|
||||
|
||||
always @ (posedge RClk, posedge PresetEmpty) //D Flip-Flop w/ Asynchronous Preset.
|
||||
if (PresetEmpty)
|
||||
Empty_out <= 1;
|
||||
else
|
||||
Empty_out <= 0;
|
||||
|
||||
endmodule
|
||||
93
lm32/logic/sakc/cores/vgafb/rtl/vgafb_asfifo_xilinx.v
Normal file
93
lm32/logic/sakc/cores/vgafb/rtl/vgafb_asfifo_xilinx.v
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Milkymist VJ SoC
|
||||
* Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* FIXME: this module does not work. Find out why. */
|
||||
|
||||
module vgafb_asfifo #(
|
||||
/* NB: those are fixed in this implementation */
|
||||
parameter DATA_WIDTH = 18,
|
||||
parameter ADDRESS_WIDTH = 11
|
||||
) (
|
||||
/* Reading port */
|
||||
output [17:0] Data_out,
|
||||
output Empty_out,
|
||||
input ReadEn_in,
|
||||
input RClk,
|
||||
|
||||
/* Writing port */
|
||||
input [17:0] Data_in,
|
||||
output Full_out,
|
||||
input WriteEn_in,
|
||||
input WClk,
|
||||
|
||||
input Clear_in
|
||||
);
|
||||
|
||||
wire full;
|
||||
wire empty;
|
||||
|
||||
FIFO16 #(
|
||||
.DATA_WIDTH(9),
|
||||
.FIRST_WORD_FALL_THROUGH("TRUE")
|
||||
) fifo_lo (
|
||||
.ALMOSTEMPTY(),
|
||||
.ALMOSTFULL(),
|
||||
.DO(Data_out[7:0]),
|
||||
.DOP(Data_out[8]),
|
||||
.EMPTY(empty),
|
||||
.FULL(full),
|
||||
.RDCOUNT(),
|
||||
.RDERR(),
|
||||
.WRCOUNT(),
|
||||
.WRERR(),
|
||||
.DI(Data_in[7:0]),
|
||||
.DIP(Data_in[8]),
|
||||
.RDCLK(RClk),
|
||||
.RDEN(ReadEn_in & ~empty & ~Clear_in),
|
||||
.RST(Clear_in),
|
||||
.WRCLK(WClk),
|
||||
.WREN(WriteEn_in & ~full & ~Clear_in)
|
||||
);
|
||||
|
||||
assign Empty_out = empty;
|
||||
assign Full_out = full;
|
||||
|
||||
FIFO16 #(
|
||||
.DATA_WIDTH(9),
|
||||
.FIRST_WORD_FALL_THROUGH("TRUE")
|
||||
) fifo_hi (
|
||||
.ALMOSTEMPTY(),
|
||||
.ALMOSTFULL(),
|
||||
.DO(Data_out[16:9]),
|
||||
.DOP(Data_out[17]),
|
||||
.EMPTY(),
|
||||
.FULL(),
|
||||
.RDCOUNT(),
|
||||
.RDERR(),
|
||||
.WRCOUNT(),
|
||||
.WRERR(),
|
||||
.DI(Data_in[16:9]),
|
||||
.DIP(Data_in[17]),
|
||||
.RDCLK(RClk),
|
||||
.RDEN(ReadEn_in & ~empty & ~Clear_in),
|
||||
.RST(Clear_in),
|
||||
.WRCLK(WClk),
|
||||
.WREN(WriteEn_in & ~full & ~Clear_in)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
121
lm32/logic/sakc/cores/vgafb/rtl/vgafb_ctlif.v
Normal file
121
lm32/logic/sakc/cores/vgafb/rtl/vgafb_ctlif.v
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Milkymist VJ SoC
|
||||
* Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
module vgafb_ctlif #(
|
||||
parameter csr_addr = 4'h0,
|
||||
parameter fml_depth = 26
|
||||
) (
|
||||
input sys_clk,
|
||||
input sys_rst,
|
||||
|
||||
input [13:0] csr_a,
|
||||
input csr_we,
|
||||
input [31:0] csr_di,
|
||||
output reg [31:0] csr_do,
|
||||
|
||||
output reg vga_rst,
|
||||
|
||||
output reg [10:0] hres,
|
||||
output reg [10:0] hsync_start,
|
||||
output reg [10:0] hsync_end,
|
||||
output reg [10:0] hscan,
|
||||
|
||||
output reg [10:0] vres,
|
||||
output reg [10:0] vsync_start,
|
||||
output reg [10:0] vsync_end,
|
||||
output reg [10:0] vscan,
|
||||
|
||||
output reg [fml_depth-1:0] baseaddress,
|
||||
input baseaddress_ack,
|
||||
|
||||
output reg [17:0] nbursts,
|
||||
|
||||
output reg [1:0] vga_clk_sel
|
||||
);
|
||||
|
||||
reg [fml_depth-1:0] baseaddress_act;
|
||||
|
||||
always @(posedge sys_clk) begin
|
||||
if(sys_rst)
|
||||
baseaddress_act <= {fml_depth{1'b0}};
|
||||
else if(baseaddress_ack)
|
||||
baseaddress_act <= baseaddress;
|
||||
end
|
||||
|
||||
wire csr_selected = csr_a[13:10] == csr_addr;
|
||||
|
||||
always @(posedge sys_clk) begin
|
||||
if(sys_rst) begin
|
||||
csr_do <= 32'd0;
|
||||
|
||||
vga_rst <= 1'b1;
|
||||
|
||||
hres <= 10'd640;
|
||||
hsync_start <= 10'd656;
|
||||
hsync_end <= 10'd752;
|
||||
hscan <= 10'd799;
|
||||
|
||||
vres <= 10'd480;
|
||||
vsync_start <= 10'd491;
|
||||
vsync_end <= 10'd493;
|
||||
vscan <= 10'd523;
|
||||
|
||||
baseaddress <= {fml_depth{1'b0}};
|
||||
|
||||
nbursts <= 18'd19200;
|
||||
vga_clk_sel <= 2'd00;
|
||||
end else begin
|
||||
csr_do <= 32'd0;
|
||||
if(csr_selected) begin
|
||||
if(csr_we) begin
|
||||
case(csr_a[3:0])
|
||||
4'd0: vga_rst <= csr_di[0];
|
||||
4'd1: hres <= csr_di[10:0];
|
||||
4'd2: hsync_start <= csr_di[10:0];
|
||||
4'd3: hsync_end <= csr_di[10:0];
|
||||
4'd4: hscan <= csr_di[10:0];
|
||||
4'd5: vres <= csr_di[10:0];
|
||||
4'd6: vsync_start <= csr_di[10:0];
|
||||
4'd7: vsync_end <= csr_di[10:0];
|
||||
4'd8: vscan <= csr_di[10:0];
|
||||
4'd9: baseaddress <= csr_di[fml_depth-1:0];
|
||||
// 10: baseaddress_act is read-only for Wishbone
|
||||
4'd11: nbursts <= csr_di[17:0];
|
||||
4'd12: vga_clk_sel <= csr_di[1:0];
|
||||
endcase
|
||||
end
|
||||
|
||||
case(csr_a[3:0])
|
||||
4'd0: csr_do <= vga_rst;
|
||||
4'd1: csr_do <= hres;
|
||||
4'd2: csr_do <= hsync_start;
|
||||
4'd3: csr_do <= hsync_end;
|
||||
4'd4: csr_do <= hscan;
|
||||
4'd5: csr_do <= vres;
|
||||
4'd6: csr_do <= vsync_start;
|
||||
4'd7: csr_do <= vsync_end;
|
||||
4'd8: csr_do <= vscan;
|
||||
4'd9: csr_do <= baseaddress;
|
||||
4'd10: csr_do <= baseaddress_act;
|
||||
4'd11: csr_do <= nbursts;
|
||||
4'd12: csr_do <= vga_clk_sel;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
75
lm32/logic/sakc/cores/vgafb/rtl/vgafb_fifo64to16.v
Normal file
75
lm32/logic/sakc/cores/vgafb/rtl/vgafb_fifo64to16.v
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Milkymist VJ SoC
|
||||
* Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
module vgafb_fifo64to16(
|
||||
input sys_clk,
|
||||
input vga_rst,
|
||||
|
||||
input stb,
|
||||
input [63:0] di,
|
||||
|
||||
output do_valid,
|
||||
output reg [15:0] do,
|
||||
input next /* should only be asserted when do_valid = 1 */
|
||||
);
|
||||
|
||||
/*
|
||||
* FIFO can hold 4 64-bit words
|
||||
* that is 16 16-bit words.
|
||||
*/
|
||||
|
||||
reg [63:0] storage[0:3];
|
||||
reg [1:0] produce; /* in 64-bit words */
|
||||
reg [3:0] consume; /* in 16-bit words */
|
||||
/*
|
||||
* 16-bit words stored in the FIFO, 0-16 (17 possible values)
|
||||
*/
|
||||
reg [4:0] level;
|
||||
|
||||
wire [63:0] do64;
|
||||
assign do64 = storage[consume[3:2]];
|
||||
|
||||
always @(*) begin
|
||||
case(consume[1:0])
|
||||
2'd0: do <= do64[63:48];
|
||||
2'd1: do <= do64[47:32];
|
||||
2'd2: do <= do64[31:16];
|
||||
2'd3: do <= do64[15:0];
|
||||
endcase
|
||||
end
|
||||
|
||||
always @(posedge sys_clk) begin
|
||||
if(vga_rst) begin
|
||||
produce = 2'd0;
|
||||
consume = 4'd0;
|
||||
level = 5'd0;
|
||||
end else begin
|
||||
if(stb) begin
|
||||
storage[produce] = di;
|
||||
produce = produce + 2'd1;
|
||||
level = level + 5'd4;
|
||||
end
|
||||
if(next) begin /* next should only be asserted when do_valid = 1 */
|
||||
consume = consume + 4'd1;
|
||||
level = level - 5'd1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign do_valid = ~(level == 5'd0);
|
||||
|
||||
endmodule
|
||||
35
lm32/logic/sakc/cores/vgafb/rtl/vgafb_graycounter.v
Normal file
35
lm32/logic/sakc/cores/vgafb/rtl/vgafb_graycounter.v
Normal file
@@ -0,0 +1,35 @@
|
||||
//==========================================
|
||||
// Function : Code Gray counter.
|
||||
// Coder : Alex Claros F.
|
||||
// Date : 15/May/2005.
|
||||
//=======================================
|
||||
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module vgafb_graycounter
|
||||
#(parameter COUNTER_WIDTH = 2)
|
||||
|
||||
(output reg [COUNTER_WIDTH-1:0] GrayCount_out, //'Gray' code count output.
|
||||
|
||||
input wire Enable_in, //Count enable.
|
||||
input wire Clear_in, //Count reset.
|
||||
|
||||
input wire Clk);
|
||||
|
||||
/////////Internal connections & variables///////
|
||||
reg [COUNTER_WIDTH-1:0] BinaryCount;
|
||||
|
||||
/////////Code///////////////////////
|
||||
|
||||
always @ (posedge Clk)
|
||||
if (Clear_in) begin
|
||||
BinaryCount <= {COUNTER_WIDTH{1'b 0}} + 1; //Gray count begins @ '1' with
|
||||
GrayCount_out <= {COUNTER_WIDTH{1'b 0}}; // first 'Enable_in'.
|
||||
end
|
||||
else if (Enable_in) begin
|
||||
BinaryCount <= BinaryCount + 1;
|
||||
GrayCount_out <= {BinaryCount[COUNTER_WIDTH-1],
|
||||
BinaryCount[COUNTER_WIDTH-2:0] ^ BinaryCount[COUNTER_WIDTH-1:1]};
|
||||
end
|
||||
|
||||
endmodule
|
||||
182
lm32/logic/sakc/cores/vgafb/rtl/vgafb_pixelfeed.v
Normal file
182
lm32/logic/sakc/cores/vgafb/rtl/vgafb_pixelfeed.v
Normal file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Milkymist VJ SoC
|
||||
* Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
module vgafb_pixelfeed #(
|
||||
parameter fml_depth = 26
|
||||
) (
|
||||
input sys_clk,
|
||||
/* We must take into account both resets :
|
||||
* VGA reset should not interrupt a pending FML request
|
||||
* but system reset should.
|
||||
*/
|
||||
input sys_rst,
|
||||
input vga_rst,
|
||||
|
||||
input [17:0] nbursts,
|
||||
input [fml_depth-1:0] baseaddress,
|
||||
output baseaddress_ack,
|
||||
|
||||
output reg [fml_depth-1:0] fml_adr,
|
||||
output reg fml_stb,
|
||||
input fml_ack,
|
||||
input [63:0] fml_di,
|
||||
|
||||
output pixel_valid,
|
||||
output [15:0] pixel,
|
||||
input pixel_ack
|
||||
);
|
||||
|
||||
/* FIFO that stores the 64-bit bursts and slices it in 16-bit words */
|
||||
|
||||
reg fifo_stb;
|
||||
wire fifo_valid;
|
||||
|
||||
vgafb_fifo64to16 fifo64to16(
|
||||
.sys_clk(sys_clk),
|
||||
.vga_rst(vga_rst),
|
||||
|
||||
.stb(fifo_stb),
|
||||
.di(fml_di),
|
||||
|
||||
.do_valid(fifo_valid),
|
||||
.do(pixel),
|
||||
.next(pixel_ack)
|
||||
);
|
||||
|
||||
assign pixel_valid = fifo_valid;
|
||||
|
||||
/* BURST COUNTER */
|
||||
reg sof;
|
||||
wire counter_en;
|
||||
|
||||
reg [17:0] bcounter;
|
||||
|
||||
always @(posedge sys_clk) begin
|
||||
if(vga_rst) begin
|
||||
bcounter <= 18'd1;
|
||||
sof <= 1'b1;
|
||||
end else begin
|
||||
if(counter_en) begin
|
||||
if(bcounter == nbursts) begin
|
||||
bcounter <= 18'd1;
|
||||
sof <= 1'b1;
|
||||
end else begin
|
||||
bcounter <= bcounter + 18'd1;
|
||||
sof <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
/* FML ADDRESS GENERATOR */
|
||||
wire next_address;
|
||||
|
||||
assign baseaddress_ack = sof & next_address;
|
||||
|
||||
always @(posedge sys_clk) begin
|
||||
if(sys_rst) begin
|
||||
fml_adr <= {fml_depth{1'b0}};
|
||||
end else begin
|
||||
if(next_address) begin
|
||||
if(sof)
|
||||
fml_adr <= baseaddress;
|
||||
else
|
||||
fml_adr <= fml_adr + {{fml_depth-6{1'b0}}, 6'd32};
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
/* CONTROLLER */
|
||||
reg [2:0] state;
|
||||
reg [2:0] next_state;
|
||||
|
||||
parameter IDLE = 3'd0;
|
||||
parameter WAIT = 3'd1;
|
||||
parameter FETCH2 = 3'd2;
|
||||
parameter FETCH3 = 3'd3;
|
||||
parameter FETCH4 = 3'd4;
|
||||
|
||||
always @(posedge sys_clk) begin
|
||||
if(sys_rst)
|
||||
state <= IDLE;
|
||||
else
|
||||
state <= next_state;
|
||||
end
|
||||
|
||||
/*
|
||||
* Do not put spurious data into the FIFO if the VGA reset
|
||||
* is asserted and released during the FML access. Getting
|
||||
* the FIFO out of sync would result in distorted pictures
|
||||
* we really want to avoid.
|
||||
*/
|
||||
|
||||
reg ignore;
|
||||
reg ignore_clear;
|
||||
|
||||
always @(posedge sys_clk) begin
|
||||
if(vga_rst)
|
||||
ignore <= 1'b1;
|
||||
else if(ignore_clear)
|
||||
ignore <= 1'b0;
|
||||
end
|
||||
|
||||
reg next_burst;
|
||||
|
||||
assign counter_en = next_burst;
|
||||
assign next_address = next_burst;
|
||||
|
||||
always @(*) begin
|
||||
next_state = state;
|
||||
|
||||
fifo_stb = 1'b0;
|
||||
next_burst = 1'b0;
|
||||
|
||||
fml_stb = 1'b0;
|
||||
ignore_clear = 1'b0;
|
||||
|
||||
case(state)
|
||||
IDLE: begin
|
||||
if(~fifo_valid & ~vga_rst) begin
|
||||
/* We're in need of pixels ! */
|
||||
next_burst = 1'b1;
|
||||
ignore_clear = 1'b1;
|
||||
next_state = WAIT;
|
||||
end
|
||||
end
|
||||
WAIT: begin
|
||||
fml_stb = 1'b1;
|
||||
if(fml_ack) begin
|
||||
if(~ignore) fifo_stb = 1'b1;
|
||||
next_state = FETCH2;
|
||||
end
|
||||
end
|
||||
FETCH2: begin
|
||||
if(~ignore) fifo_stb = 1'b1;
|
||||
next_state = FETCH3;
|
||||
end
|
||||
FETCH3: begin
|
||||
if(~ignore) fifo_stb = 1'b1;
|
||||
next_state = FETCH4;
|
||||
end
|
||||
FETCH4: begin
|
||||
if(~ignore) fifo_stb = 1'b1;
|
||||
next_state = IDLE;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user