From: Thomas Pietrzak Date: Thu, 11 Oct 2018 07:22:26 +0000 (+0200) Subject: initial X-Git-Url: https://git.thomaspietrzak.com/?a=commitdiff_plain;h=dbf01698cda093e6b74636624d2948bd9cf91e9a;p=testlcd.git initial --- dbf01698cda093e6b74636624d2948bd9cf91e9a diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c89fea8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,42 @@ +*.ngd +*.pad +*.par +*.pcf +*.prj +*.ptwx +*.stx +*.syr +*.twr +*.twx +*.unroutes +*.xpi +*.xst +*.ncd +*.map +*.mrp +*.ncd +*.ngm +*.xrpt +*.csv +*.txt +*.xml +*.bgn +*.bit +*.bld +*.cmd_log +*.drc +*.lso +*.ngc +*.ngr +*.ut +*.xwbt +*.html +*.gise +*.log +_ngo +_xmsgs +ipcore_dir +iseconfig +netgen +xlnx_auto_0_xdb +xst diff --git a/clocks.v b/clocks.v new file mode 100644 index 0000000..1db0971 --- /dev/null +++ b/clocks.v @@ -0,0 +1,124 @@ +module clocks( + clkpin, // 50MHz + rst, + locked, + clk, // 300MHz + spiclk, // 20MHz + tftclk // 6.667MHz +); + +input clkpin; +input rst; +output locked; +output clk; +output spiclk; +output tftclk; + +wire GROUND; +wire U1_CLKDV_BUF; +wire U1_CLKFX_BUF; +wire U1_CLKIN_IBUFG; +wire U1_CLK0_BUF; +wire U1_LOCKED_INV_IN; +wire U2_CLKFB_IN; +wire U2_CLKFX_BUF; +wire U2_CLKIN_IN; +wire U2_CLK0_BUF; +wire U2_FDS_Q_OUT; +wire U2_FD1_Q_OUT; +wire U2_FD2_Q_OUT; +wire U2_FD3_Q_OUT; +wire U2_LOCKED_INV_RST; +wire U2_OR3_O_OUT; +wire U2_RST_IN; + +assign GROUND = 0; +DCM_SP #( + .CLK_FEEDBACK("1X"), + .CLKDV_DIVIDE(2.5), + .CLKFX_DIVIDE(1), + .CLKFX_MULTIPLY(6), + .CLKIN_DIVIDE_BY_2("FALSE"), + .CLKIN_PERIOD(20.000), + .CLKOUT_PHASE_SHIFT("NONE"), + .DESKEW_ADJUST("SYSTEM_SYNCHRONOUS"), + .DFS_FREQUENCY_MODE("LOW"), + .DLL_FREQUENCY_MODE("LOW"), + .DUTY_CYCLE_CORRECTION("TRUE"), + .FACTORY_JF(16'hC080), + .PHASE_SHIFT(0), + .STARTUP_WAIT("FALSE") +) +DCM_SP_INST1( + .CLKFB(U2_CLKIN_IN), + .CLKIN(U1_CLKIN_IBUFG), + .DSSEN(GROUND), + .PSCLK(GROUND), + .PSEN(GROUND), + .PSINCDEC(GROUND), + .RST(rst), + .CLKDV(U1_CLKDV_BUF), + .CLKFX(U1_CLKFX_BUF), + .CLKFX180(), + .CLK0(U1_CLK0_BUF), + .CLK2X(), + .CLK2X180(), + .CLK90(), + .CLK180(), + .CLK270(), + .LOCKED(U1_LOCKED_INV_IN), + .PSDONE(), + .STATUS() +); +DCM_SP #( + .CLK_FEEDBACK("1X"), + .CLKDV_DIVIDE(2.0), + .CLKFX_DIVIDE(15), + .CLKFX_MULTIPLY(2), + .CLKIN_DIVIDE_BY_2("FALSE"), + .CLKIN_PERIOD(20.000), + .CLKOUT_PHASE_SHIFT("NONE"), + .DESKEW_ADJUST("SYSTEM_SYNCHRONOUS"), + .DFS_FREQUENCY_MODE("LOW"), + .DLL_FREQUENCY_MODE("LOW"), + .DUTY_CYCLE_CORRECTION("TRUE"), + .FACTORY_JF(16'hC080), + .PHASE_SHIFT(0), + .STARTUP_WAIT("FALSE") +) +DCM_SP_INST2( + .CLKFB(U2_CLKFB_IN), + .CLKIN(U2_CLKIN_IN), + .DSSEN(GROUND), + .PSCLK(GROUND), + .PSEN(GROUND), + .PSINCDEC(GROUND), + .RST(U2_RST_IN), + .CLKDV(), + .CLKFX(U2_CLKFX_BUF), + .CLKFX180(), + .CLK0(U2_CLK0_BUF), + .CLK2X(), + .CLK2X180(), + .CLK90(), + .CLK180(), + .CLK270(), + .LOCKED(locked), + .PSDONE(), + .STATUS() +); +BUFG U1_CLKDV_BUFG_INST(.I(U1_CLKDV_BUF), .O(spiclk)); +BUFG U1_CLKFX_BUFG_INST(.I(U1_CLKFX_BUF), .O(clk)); +IBUFG U1_CLKIN_IBUFG_INST(.I(clkpin), .O(U1_CLKIN_IBUFG)); +BUFG U1_CLK0_BUFG_INST(.I(U1_CLK0_BUF), .O(U2_CLKIN_IN)); +INV U1_INV_INST(.I(U1_LOCKED_INV_IN), .O(U2_LOCKED_INV_RST)); +BUFG U2_CLKFX_BUFG_INST(.I(U2_CLKFX_BUF), .O(tftclk)); +BUFG U2_CLK0_BUFG_INST(.I(U2_CLK0_BUF), .O(U2_CLKFB_IN)); +FDS U2_FDS_INST(.C(U2_CLKIN_IN), .D(GROUND), .S(GROUND), .Q(U2_FDS_Q_OUT)); +FD U2_FD1_INST(.C(U2_CLKIN_IN), .D(U2_FDS_Q_OUT), .Q(U2_FD1_Q_OUT)); +FD U2_FD2_INST(.C(U2_CLKIN_IN), .D(U2_FD1_Q_OUT), .Q(U2_FD2_Q_OUT)); +FD U2_FD3_INST(.C(U2_CLKIN_IN), .D(U2_FD2_Q_OUT), .Q(U2_FD3_Q_OUT)); +OR2 U2_OR2_INST(.I0(U2_LOCKED_INV_RST), .I1(U2_OR3_O_OUT), .O(U2_RST_IN)); +OR3 U2_OR3_INST(.I0(U2_FD3_Q_OUT), .I1(U2_FD2_Q_OUT), .I2(U2_FD1_Q_OUT), .O(U2_OR3_O_OUT)); + +endmodule diff --git a/lcd.ucf b/lcd.ucf new file mode 100644 index 0000000..f24b1fa --- /dev/null +++ b/lcd.ucf @@ -0,0 +1,57 @@ +//50Mhz clock +NET "clkpin" LOC = "E12"| IOSTANDARD = LVCMOS33 ; + +NET "LED<2>" LOC = "U20" | IOSTANDARD = LVTTL | SLEW = QUIETIO | DRIVE = 4 ; +NET "LED<0>" LOC = "R20" | IOSTANDARD = LVTTL | SLEW = QUIETIO | DRIVE = 4 ; +NET "LED<1>" LOC = "T19" | IOSTANDARD = LVTTL | SLEW = QUIETIO | DRIVE = 4 ; + +NET "BUTTON" LOC = "T14" | IOSTANDARD = LVTTL | PULLDOWN ; + +//NET "RL" LOC = "A13" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; +//NET "TB" LOC = "B13" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; + +/* LCD Input control */ +//NET "dclk" LOC = "A14" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; +//NET "vsync" LOC = "B15" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; +//NET "hsync" LOC = "A15" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; +//NET "de" LOC = "A16" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; + +/* Data red */ +//NET "tft_r_pins<7>" LOC = "A17" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; +//NET "tft_r_pins<6>" LOC = "B17" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; +//NET "tft_r_pins<5>" LOC = "A18" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; +//NET "tft_r_pins<4>" LOC = "C18" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; +//NET "tft_r_pins<3>" LOC = "A19" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; +//NET "tft_r_pins<2>" LOC = "B19" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; +//NET "tft_r_pins<1>" LOC = "A20" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; +//NET "tft_r_pins<0>" LOC = "B20" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; + + +/* Data green */ +//NET "tft_g_pins<7>" LOC = "D19" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; +//NET "tft_g_pins<6>" LOC = "D18" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; +//NET "tft_g_pins<5>" LOC = "E17" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; +//NET "tft_g_pins<4>" LOC = "D20" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; +//NET "tft_g_pins<3>" LOC = "D21" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; +//NET "tft_g_pins<2>" LOC = "D22" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; +//NET "tft_g_pins<1>" LOC = "E22" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; +//NET "tft_g_pins<0>" LOC = "F18" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; + + +/* Data blue */ +//NET "tft_b_pins<7>" LOC = "F20" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; +//NET "tft_b_pins<6>" LOC = "E20" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; +//NET "tft_b_pins<5>" LOC = "G20" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; +//NET "tft_b_pins<4>" LOC = "G19" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; +//NET "tft_b_pins<3>" LOC = "H19" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; +//NET "tft_b_pins<2>" LOC = "J18" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; +//NET "tft_b_pins<1>" LOC = "K18" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; +//NET "tft_b_pins<0>" LOC = "K17" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; + +/* serial port */ +//NET "SDI" LOC = "K19" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; +//NET "SDO" LOC = "M20" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; +//NET "SCL" LOC = "K20" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; +//NET "CS" LOC = "L19" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; + +//NET "RESET" LOC = "L18" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; diff --git a/lcd.v b/lcd.v new file mode 100644 index 0000000..4e3aa35 --- /dev/null +++ b/lcd.v @@ -0,0 +1,72 @@ +module lcd( + input clkpin, + output reg [1:0]led, + output rl, + output tb, + output dclk, + output vsync, + output hsync, + output de, + output reg [7:0]tft_r_pins, + output reg [7:0]tft_g_pins, + output reg [7:0]tft_b_pins, + output sdi, + input sdo, + output scl, + output cs, + output reset + ); + +wire clk; // 300 MHz +wire spiclk; // 20 MHz +reg tftclk; // 6.522 Mhz + +dcm dcm_instance( + .CLKIN_IN(clkpin), + .CLKFX_OUT(clk), + .CLKDV_OUT(spiclk)); + +reg [4:0] counter; +always @(posedge clk) + if (counter == 23) + begin counter <= 0; tftclk <= ~tftclk; end + else + counter <= counter + 1; + +always @(posedge clk) led <= 2'b0; + +assign rl = 0; +assign tb = 0; +assign vsync = 0; +assign hsync = 0; +assign de = 0; +always @(posedge clk) tft_r_pins <= 8'b0; +always @(posedge clk) tft_g_pins <= 8'b0; +always @(posedge clk) tft_b_pins <= 8'b0; +assign sdi = sdo; +assign cs = 0; +assign reset = 0; + +ODDR2 #(.DDR_ALIGNMENT("NONE"), .INIT(1'b0), .SRTYPE("SYNC")) + oddr2_spi_clk( + .Q(scl), + .C0(spiclk), + .C1(~spiclk), + .CE(1'b1), + .D0(1'b1), + .D1(1'b0), + .R(1'b0), + .S(1'b0)); + +ODDR2 #(.DDR_ALIGNMENT("NONE"), .INIT(1'b0), .SRTYPE("SYNC")) + oddr2_tft_clk( + .Q(dclk), + .C0(tftclk), + .C1(~tftclk), + .CE(1'b1), + .D0(1'b1), + .D1(1'b0), + .R(1'b0), + .S(1'b0)); + +endmodule diff --git a/spi.v b/spi.v new file mode 100644 index 0000000..5c8111d --- /dev/null +++ b/spi.v @@ -0,0 +1,70 @@ +module master_spi +#( + parameter WIDTH = 8 +) + +( + clk, + mosi, + miso, + ssel, + din, + dout, + ready, + enable +); + +function integer log2; + input integer value; + begin + value = value - 1; + for (log2 = 0; value > 0; log2 = log2 + 1) value = value >> 1; + end +endfunction + +input clk; +input miso; +output reg mosi = 0; +output reg ssel = 1; +input [WIDTH-1:0] din; +output [WIDTH-1:0] dout; +output reg ready; +input enable; + +initial ready = 1; + +reg started = 0; +reg [log2(WIDTH)-1:0] counter; +reg [WIDTH-1:0] sp_in = 0; +reg [WIDTH-1:0] sp_out = 0; + +assign dout = sp_out; + +always @(posedge clk) if (enable) begin + if (!started) begin + sp_in <= din; + sp_out <= 0; + started <= 1; + ssel <= 1; + ready <= 0; + counter <= WIDTH; + end else begin + if (counter == 0) begin + started <= 0; + ssel <= 1; + ready <= 1; + end else begin + ssel <= 0; + ready <= 0; + mosi <= sp_in[WIDTH-1]; + sp_in <= sp_in << 1; + sp_out <= (sp_out << 1) | miso; + counter <= counter - 1; + end + end +end else begin + ssel <= 1; + ready <= 1; +end + +endmodule \ No newline at end of file diff --git a/top.v b/top.v new file mode 100644 index 0000000..a3bea87 --- /dev/null +++ b/top.v @@ -0,0 +1,134 @@ +module top( + clkpin, + button, + led +); + +input clkpin; +input button; +output [3:0] led; + +wire clk; // 300MHz +wire spiclk; // 20MHz +wire tftclk; // 6.667MHz + +clocks clocks_instance( + .clkpin(clkpin), + .rst(1'b0), + .clk(clk), + .spiclk(spiclk), + .tftclk(tftclk) +); + +reg slowclk; // 1Hz +reg [31:0] counter = 0; +wire [23:0] spi_in; +wire [23:0] spi_out; +wire spi_ready; +reg spi_enable = 0; +wire mosi; +wire ssel; + +assign led[0] = slowclk; +assign led[1] = ssel; +assign led[2] = mosi; +assign led[3] = spi_ready; + +master_spi #( + .WIDTH(24) +) +master_spi_instance ( + .clk(slowclk), + .mosi(mosi), + .miso(1'b0), + .ssel(ssel), + .din(spi_in), + .dout(spi_out), + .ready(spi_ready), + .enable(spi_enable) +); + +reg [1:0] state = 0; +reg [5:0] index = 0; + +reg [23:0] init_sequence [0:45]; + +initial begin + init_sequence[ 0] = 24'h700001; + init_sequence[ 1] = 24'h726300; + init_sequence[ 2] = 24'h700002; + init_sequence[ 3] = 24'h720200; + init_sequence[ 4] = 24'h700003; + init_sequence[ 5] = 24'h726064; + init_sequence[ 6] = 24'h700004; + init_sequence[ 7] = 24'h720447; + init_sequence[ 8] = 24'h700005; + init_sequence[ 9] = 24'h72b084; + init_sequence[10] = 24'h70000a; + init_sequence[11] = 24'h724008; + init_sequence[12] = 24'h70000b; + init_sequence[13] = 24'h72d400; + init_sequence[14] = 24'h70000d; + init_sequence[15] = 24'h72423d; + init_sequence[16] = 24'h70000e; + init_sequence[17] = 24'h723140; + init_sequence[18] = 24'h70000f; + init_sequence[19] = 24'h720000; + init_sequence[20] = 24'h700016; + init_sequence[21] = 24'h729f80; + init_sequence[22] = 24'h700017; + init_sequence[23] = 24'h722212; + init_sequence[24] = 24'h70001e; + init_sequence[25] = 24'h7200db; + init_sequence[26] = 24'h700030; + init_sequence[27] = 24'h720000; + init_sequence[28] = 24'h700031; + init_sequence[29] = 24'h720607; + init_sequence[30] = 24'h700032; + init_sequence[31] = 24'h720006; + init_sequence[32] = 24'h700033; + init_sequence[33] = 24'h720307; + init_sequence[34] = 24'h700034; + init_sequence[35] = 24'h720107; + init_sequence[36] = 24'h700035; + init_sequence[37] = 24'h720001; + init_sequence[38] = 24'h700036; + init_sequence[39] = 24'h720707; + init_sequence[40] = 24'h700037; + init_sequence[41] = 24'h720703; + init_sequence[42] = 24'h70003a; + init_sequence[43] = 24'h720c00; + init_sequence[44] = 24'h70003b; + init_sequence[45] = 24'h720006; +end + +assign spi_in = init_sequence[index]; + +reg [1:0] button_state = 0; +always @(posedge clk) begin + if (button_state == 2'b10) state <= 1; + button_state <= {button_state[0], button}; +end + +always @(posedge slowclk) begin + case(state) + 1: begin state <= 2; index <= 0; end + 2: if (spi_ready) spi_enable <= 1; + 3: if (spi_ready) begin + spi_enable <= 0; + state <= index == 45 ? 0 : 2; + index <= index + 1; + end + endcase +end + +always @(posedge clk) begin + if (counter == 150000000) begin + counter <= 0; + slowclk <= ~slowclk; + end else begin + counter <= counter + 1; + end +end + +endmodule