1
0
mirror of https://github.com/Gehstock/Mist_FPGA.git synced 2026-01-25 19:45:57 +00:00

Use Common Units

This commit is contained in:
Marcel
2019-07-23 22:51:10 +02:00
parent f286d4a42b
commit 1833d64055
19 changed files with 279 additions and 2196 deletions

Binary file not shown.

View File

@@ -58,15 +58,8 @@ set_global_assignment -name VHDL_FILE rtl/T65/t65_MCode.vhd
set_global_assignment -name VHDL_FILE rtl/T65/t65_alu.vhd
set_global_assignment -name VHDL_FILE rtl/T65/t65.vhd
set_global_assignment -name VHDL_FILE rtl/T65/pack_t65.vhd
set_global_assignment -name VERILOG_FILE rtl/mist_io.v
set_global_assignment -name SYSTEMVERILOG_FILE rtl/hq2x.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/video_mixer.sv
set_global_assignment -name VHDL_FILE rtl/spram.vhd
set_global_assignment -name VERILOG_FILE rtl/osd.v
set_global_assignment -name VERILOG_FILE rtl/scandoubler.v
set_global_assignment -name VERILOG_FILE rtl/pll.v
set_global_assignment -name SYSTEMVERILOG_FILE rtl/keyboard.sv
set_global_assignment -name VHDL_FILE rtl/dac.vhd
# Pin & Location Assignments
# ==========================
@@ -216,10 +209,12 @@ set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
# end DESIGN_PARTITION(Top)
# -------------------------
# end ENTITY(OricAtmos_MiST)
# --------------------------
# --------------------------
set_global_assignment -name SYSTEMVERILOG_FILE rtl/keyboard.sv
set_global_assignment -name QIP_FILE ../../common/mist/mist.qip
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

View File

@@ -18,3 +18,4 @@
{ "" "" "" "7 pins must meet Altera requirements for 3.3-, 3.0-, and 2.5-V interfaces. For more information, refer to AN 447: Interfacing Cyclone III Devices with 3.3/3.0/2.5-V LVTTL/LVCMOS I/O Systems." { } { } 0 169177 "" 0 0 "Quartus II" 0 -1 0 ""}
{ "" "" "" "Some pins have incomplete I/O assignments. Refer to the I/O Assignment Warnings report for details" { } { } 0 15714 "" 0 0 "Quartus II" 0 -1 0 ""}
{ "" "" "" "PCI-clamp diode is not supported in this mode. The following 1 pins must meet the Altera requirements for 3.3V, 3.0V, and 2.5V interfaces if they are connected to devices other than the supported configuration devices. In these cases, Altera recommends termination method as specified in the Application Note 447." { } { } 0 169203 "" 0 0 "Quartus II" 0 -1 0 ""}
{ "" "" "" "Inferred dual-clock RAM node \"mist_video:mist_video\|osd:osd\|osd_buffer_rtl_0\" from synchronous design logic. The read-during-write behavior of a dual-clock RAM is undefined and may not match the behavior of the original design." { } { } 0 276027 "" 0 0 "Quartus II" 0 -1 0 ""}

View File

@@ -25,8 +25,11 @@ localparam CONF_STR = {
"T9,Reset;",
"V,v1.00.",`BUILD_DATE
};
wire clk_24, clk_6;
wire [10:0] ps2_key;
wire clk_24;
wire key_pressed;
wire [7:0] key_code;
wire key_strobe;
wire key_extended;
wire r, g, b;
wire hs, vs;
wire [1:0] buttons, switches;
@@ -38,76 +41,75 @@ assign LED = 1'b1;
assign AUDIO_R = AUDIO_L;
pll pll (
.inclk0 ( CLOCK_27 ),
.c0 ( clk_24 ),
.c1 ( clk_6 )
.inclk0 (CLOCK_27 ),
.c0 (clk_24 )
);
mist_io #(
.STRLEN($size(CONF_STR)>>3))
user_io (
.clk_sys(clk_24),
.CONF_DATA0(CONF_DATA0),
.SPI_SCK(SPI_SCK),
.SPI_DI(SPI_DI),
.SPI_DO(SPI_DO),
.SPI_SS2(SPI_SS2),
.conf_str(CONF_STR),
.ypbpr(ypbpr),
.status(status),
.scandoublerD(scandoublerD),
.buttons(buttons),
.switches(switches),
.ps2_key(ps2_key)
user_io #(
.STRLEN (($size(CONF_STR)>>3)))
user_io(
.clk_sys (clk_24 ),
.conf_str (CONF_STR ),
.SPI_CLK (SPI_SCK ),
.SPI_SS_IO (CONF_DATA0 ),
.SPI_MISO (SPI_DO ),
.SPI_MOSI (SPI_DI ),
.buttons (buttons ),
.switches (switches ),
.scandoubler_disable (scandoublerD ),
.ypbpr (ypbpr ),
.key_strobe (key_strobe ),
.key_pressed (key_pressed ),
.key_extended (key_extended ),
.key_code (key_code ),
.status (status )
);
video_mixer video_mixer (
.clk_sys ( clk_24 ),
.ce_pix ( clk_6 ),
.ce_pix_actual ( clk_6 ),
.SPI_SCK ( SPI_SCK ),
.SPI_SS3 ( SPI_SS3 ),
.SPI_DI ( SPI_DI ),
.R ( {r,r,r}),
.G ( {g,g,g}),
.B ( {b,b,b}),
.HSync ( hs ),
.VSync ( vs ),
.VGA_R ( VGA_R ),
.VGA_G ( VGA_G ),
.VGA_B ( VGA_B ),
.VGA_VS ( VGA_VS ),
.VGA_HS ( VGA_HS ),
.scanlines (scandoublerD ? 2'b00 : status[3:2]),
.scandoublerD (scandoublerD ),
.ypbpr ( ypbpr ),
.ypbpr_full ( 1 ),
.line_start ( 0 ),
.mono ( 0 )
mist_video #(.COLOR_DEPTH(3)) mist_video(
.clk_sys (clk_24 ),
.SPI_SCK (SPI_SCK ),
.SPI_SS3 (SPI_SS3 ),
.SPI_DI (SPI_DI ),
.R ({r,r,r} ),
.G ({g,g,g} ),
.B ({b,b,b} ),
.HSync (hs ),
.VSync (vs ),
.VGA_R (VGA_R ),
.VGA_G (VGA_G ),
.VGA_B (VGA_B ),
.VGA_VS (VGA_VS ),
.VGA_HS (VGA_HS ),
.ce_divider (1'b0 ),
.scandoubler_disable(scandoublerD ),
.scanlines (scandoublerD ? 2'b00 : status[4:3]),
.ypbpr (ypbpr )
);
oricatmos oricatmos(
.RESET(status[0] | status[9] | buttons[1]),
.ps2_key(ps2_key),
.PSG_OUT(audio),
.VIDEO_R(r),
.VIDEO_G(g),
.VIDEO_B(b),
.VIDEO_HSYNC(hs),
.VIDEO_VSYNC(vs),
.K7_TAPEIN(UART_RXD),
.K7_TAPEOUT(UART_TXD),
.clk_in(clk_24)
.RESET (status[0] | status[9] | buttons[1]),
.key_pressed (key_pressed ),
.key_code (key_code ),
.key_extended (key_extended ),
.key_strobe (key_strobe ),
.PSG_OUT (audio ),
.VIDEO_R (r ),
.VIDEO_G (g ),
.VIDEO_B (b ),
.VIDEO_HSYNC (hs ),
.VIDEO_VSYNC (vs ),
.K7_TAPEIN (UART_RXD ),
.K7_TAPEOUT (UART_TXD ),
.clk_in (clk_24 )
);
dac #(
.msbi_g(15))
.c_bits (16 ))
dac(
.clk_i(clk_24),
.res_n_i(1'b1),
.dac_i(audio),
.dac_o(AUDIO_L)
.clk_i (clk_24 ),
.res_n_i (1 ),
.dac_i (audio ),
.dac_o (AUDIO_L )
);
endmodule

View File

@@ -1,71 +0,0 @@
-------------------------------------------------------------------------------
--
-- Delta-Sigma DAC
--
-- $Id: dac.vhd,v 1.1 2005/10/25 21:09:42 arnim Exp $
--
-- Refer to Xilinx Application Note XAPP154.
--
-- This DAC requires an external RC low-pass filter:
--
-- dac_o 0---XXXXX---+---0 analog audio
-- 3k3 |
-- === 4n7
-- |
-- GND
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
entity dac is
generic (
msbi_g : integer := 7
);
port (
clk_i : in std_logic;
res_n_i : in std_logic;
dac_i : in std_logic_vector(msbi_g downto 0);
dac_o : out std_logic
);
end dac;
library ieee;
use ieee.numeric_std.all;
architecture rtl of dac is
signal DACout_q : std_logic;
signal DeltaAdder_s,
SigmaAdder_s,
SigmaLatch_q,
DeltaB_s : unsigned(msbi_g+2 downto 0);
begin
DeltaB_s(msbi_g+2 downto msbi_g+1) <= SigmaLatch_q(msbi_g+2) &
SigmaLatch_q(msbi_g+2);
DeltaB_s(msbi_g downto 0) <= (others => '0');
DeltaAdder_s <= unsigned('0' & '0' & dac_i) + DeltaB_s;
SigmaAdder_s <= DeltaAdder_s + SigmaLatch_q;
seq: process (clk_i, res_n_i)
begin
if res_n_i = '0' then
SigmaLatch_q <= to_unsigned(2**(msbi_g+1), SigmaLatch_q'length);
DACout_q <= '0';
elsif clk_i'event and clk_i = '1' then
SigmaLatch_q <= SigmaAdder_s;
DACout_q <= SigmaLatch_q(msbi_g+2);
end if;
end process seq;
dac_o <= DACout_q;
end rtl;

View File

@@ -1,454 +0,0 @@
//
//
// Copyright (c) 2012-2013 Ludvig Strigeus
// Copyright (c) 2017 Sorgelig
//
// This program is GPL Licensed. See COPYING for the full license.
//
//
////////////////////////////////////////////////////////////////////////////////////////////////////////
// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
`define BITS_TO_FIT(N) ( \
N <= 2 ? 0 : \
N <= 4 ? 1 : \
N <= 8 ? 2 : \
N <= 16 ? 3 : \
N <= 32 ? 4 : \
N <= 64 ? 5 : \
N <= 128 ? 6 : \
N <= 256 ? 7 : \
N <= 512 ? 8 : \
N <=1024 ? 9 : 10 )
module hq2x_in #(parameter LENGTH, parameter DWIDTH)
(
input clk,
input [AWIDTH:0] rdaddr,
input rdbuf,
output[DWIDTH:0] q,
input [AWIDTH:0] wraddr,
input wrbuf,
input [DWIDTH:0] data,
input wren
);
localparam AWIDTH = `BITS_TO_FIT(LENGTH);
wire [DWIDTH:0] out[2];
assign q = out[rdbuf];
hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf0(clk,data,rdaddr,wraddr,wren && (wrbuf == 0),out[0]);
hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf1(clk,data,rdaddr,wraddr,wren && (wrbuf == 1),out[1]);
endmodule
module hq2x_out #(parameter LENGTH, parameter DWIDTH)
(
input clk,
input [AWIDTH:0] rdaddr,
input [1:0] rdbuf,
output[DWIDTH:0] q,
input [AWIDTH:0] wraddr,
input [1:0] wrbuf,
input [DWIDTH:0] data,
input wren
);
localparam AWIDTH = `BITS_TO_FIT(LENGTH*2);
wire [DWIDTH:0] out[4];
assign q = out[rdbuf];
hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf0(clk,data,rdaddr,wraddr,wren && (wrbuf == 0),out[0]);
hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf1(clk,data,rdaddr,wraddr,wren && (wrbuf == 1),out[1]);
hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf2(clk,data,rdaddr,wraddr,wren && (wrbuf == 2),out[2]);
hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf3(clk,data,rdaddr,wraddr,wren && (wrbuf == 3),out[3]);
endmodule
module hq2x_buf #(parameter NUMWORDS, parameter AWIDTH, parameter DWIDTH)
(
input clock,
input [DWIDTH:0] data,
input [AWIDTH:0] rdaddress,
input [AWIDTH:0] wraddress,
input wren,
output [DWIDTH:0] q
);
altsyncram altsyncram_component (
.address_a (wraddress),
.clock0 (clock),
.data_a (data),
.wren_a (wren),
.address_b (rdaddress),
.q_b(q),
.aclr0 (1'b0),
.aclr1 (1'b0),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clock1 (1'b1),
.clocken0 (1'b1),
.clocken1 (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.data_b ({(DWIDTH+1){1'b1}}),
.eccstatus (),
.q_a (),
.rden_a (1'b1),
.rden_b (1'b1),
.wren_b (1'b0));
defparam
altsyncram_component.address_aclr_b = "NONE",
altsyncram_component.address_reg_b = "CLOCK0",
altsyncram_component.clock_enable_input_a = "BYPASS",
altsyncram_component.clock_enable_input_b = "BYPASS",
altsyncram_component.clock_enable_output_b = "BYPASS",
altsyncram_component.intended_device_family = "Cyclone III",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = NUMWORDS,
altsyncram_component.numwords_b = NUMWORDS,
altsyncram_component.operation_mode = "DUAL_PORT",
altsyncram_component.outdata_aclr_b = "NONE",
altsyncram_component.outdata_reg_b = "UNREGISTERED",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_mixed_ports = "DONT_CARE",
altsyncram_component.widthad_a = AWIDTH+1,
altsyncram_component.widthad_b = AWIDTH+1,
altsyncram_component.width_a = DWIDTH+1,
altsyncram_component.width_b = DWIDTH+1,
altsyncram_component.width_byteena_a = 1;
endmodule
////////////////////////////////////////////////////////////////////////////////////////////////////////
module DiffCheck
(
input [17:0] rgb1,
input [17:0] rgb2,
output result
);
wire [5:0] r = rgb1[5:1] - rgb2[5:1];
wire [5:0] g = rgb1[11:7] - rgb2[11:7];
wire [5:0] b = rgb1[17:13] - rgb2[17:13];
wire [6:0] t = $signed(r) + $signed(b);
wire [6:0] gx = {g[5], g};
wire [7:0] y = $signed(t) + $signed(gx);
wire [6:0] u = $signed(r) - $signed(b);
wire [7:0] v = $signed({g, 1'b0}) - $signed(t);
// if y is inside (-24..24)
wire y_inside = (y < 8'h18 || y >= 8'he8);
// if u is inside (-4, 4)
wire u_inside = (u < 7'h4 || u >= 7'h7c);
// if v is inside (-6, 6)
wire v_inside = (v < 8'h6 || v >= 8'hfA);
assign result = !(y_inside && u_inside && v_inside);
endmodule
module InnerBlend
(
input [8:0] Op,
input [5:0] A,
input [5:0] B,
input [5:0] C,
output [5:0] O
);
function [8:0] mul6x3;
input [5:0] op1;
input [2:0] op2;
begin
mul6x3 = 9'd0;
if(op2[0]) mul6x3 = mul6x3 + op1;
if(op2[1]) mul6x3 = mul6x3 + {op1, 1'b0};
if(op2[2]) mul6x3 = mul6x3 + {op1, 2'b00};
end
endfunction
wire OpOnes = Op[4];
wire [8:0] Amul = mul6x3(A, Op[7:5]);
wire [8:0] Bmul = mul6x3(B, {Op[3:2], 1'b0});
wire [8:0] Cmul = mul6x3(C, {Op[1:0], 1'b0});
wire [8:0] At = Amul;
wire [8:0] Bt = (OpOnes == 0) ? Bmul : {3'b0, B};
wire [8:0] Ct = (OpOnes == 0) ? Cmul : {3'b0, C};
wire [9:0] Res = {At, 1'b0} + Bt + Ct;
assign O = Op[8] ? A : Res[9:4];
endmodule
module Blend
(
input [5:0] rule,
input disable_hq2x,
input [17:0] E,
input [17:0] A,
input [17:0] B,
input [17:0] D,
input [17:0] F,
input [17:0] H,
output [17:0] Result
);
reg [1:0] input_ctrl;
reg [8:0] op;
localparam BLEND0 = 9'b1_xxx_x_xx_xx; // 0: A
localparam BLEND1 = 9'b0_110_0_10_00; // 1: (A * 12 + B * 4) >> 4
localparam BLEND2 = 9'b0_100_0_10_10; // 2: (A * 8 + B * 4 + C * 4) >> 4
localparam BLEND3 = 9'b0_101_0_10_01; // 3: (A * 10 + B * 4 + C * 2) >> 4
localparam BLEND4 = 9'b0_110_0_01_01; // 4: (A * 12 + B * 2 + C * 2) >> 4
localparam BLEND5 = 9'b0_010_0_11_11; // 5: (A * 4 + (B + C) * 6) >> 4
localparam BLEND6 = 9'b0_111_1_xx_xx; // 6: (A * 14 + B + C) >> 4
localparam AB = 2'b00;
localparam AD = 2'b01;
localparam DB = 2'b10;
localparam BD = 2'b11;
wire is_diff;
DiffCheck diff_checker(rule[1] ? B : H, rule[0] ? D : F, is_diff);
always @* begin
case({!is_diff, rule[5:2]})
1,17: {op, input_ctrl} = {BLEND1, AB};
2,18: {op, input_ctrl} = {BLEND1, DB};
3,19: {op, input_ctrl} = {BLEND1, BD};
4,20: {op, input_ctrl} = {BLEND2, DB};
5,21: {op, input_ctrl} = {BLEND2, AB};
6,22: {op, input_ctrl} = {BLEND2, AD};
8: {op, input_ctrl} = {BLEND0, 2'bxx};
9: {op, input_ctrl} = {BLEND0, 2'bxx};
10: {op, input_ctrl} = {BLEND0, 2'bxx};
11: {op, input_ctrl} = {BLEND1, AB};
12: {op, input_ctrl} = {BLEND1, AB};
13: {op, input_ctrl} = {BLEND1, AB};
14: {op, input_ctrl} = {BLEND1, DB};
15: {op, input_ctrl} = {BLEND1, BD};
24: {op, input_ctrl} = {BLEND2, DB};
25: {op, input_ctrl} = {BLEND5, DB};
26: {op, input_ctrl} = {BLEND6, DB};
27: {op, input_ctrl} = {BLEND2, DB};
28: {op, input_ctrl} = {BLEND4, DB};
29: {op, input_ctrl} = {BLEND5, DB};
30: {op, input_ctrl} = {BLEND3, BD};
31: {op, input_ctrl} = {BLEND3, DB};
default: {op, input_ctrl} = 11'bx;
endcase
// Setting op[8] effectively disables HQ2X because blend will always return E.
if (disable_hq2x) op[8] = 1;
end
// Generate inputs to the inner blender. Valid combinations.
// 00: E A B
// 01: E A D
// 10: E D B
// 11: E B D
wire [17:0] Input1 = E;
wire [17:0] Input2 = !input_ctrl[1] ? A :
!input_ctrl[0] ? D : B;
wire [17:0] Input3 = !input_ctrl[0] ? B : D;
InnerBlend inner_blend1(op, Input1[5:0], Input2[5:0], Input3[5:0], Result[5:0]);
InnerBlend inner_blend2(op, Input1[11:6], Input2[11:6], Input3[11:6], Result[11:6]);
InnerBlend inner_blend3(op, Input1[17:12], Input2[17:12], Input3[17:12], Result[17:12]);
endmodule
////////////////////////////////////////////////////////////////////////////////////////////////////
module Hq2x #(parameter LENGTH, parameter HALF_DEPTH)
(
input clk,
input ce_x4,
input [DWIDTH:0] inputpixel,
input mono,
input disable_hq2x,
input reset_frame,
input reset_line,
input [1:0] read_y,
input [AWIDTH+1:0] read_x,
output [DWIDTH:0] outpixel
);
localparam AWIDTH = `BITS_TO_FIT(LENGTH);
localparam DWIDTH = HALF_DEPTH ? 8 : 17;
wire [5:0] hqTable[256] = '{
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39,
19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 35, 35, 23, 15, 7, 35,
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43,
19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 51, 35, 23, 15, 7, 43,
19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 35, 35, 23, 61, 51, 35,
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35,
19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 7, 35, 23, 61, 7, 43,
19, 19, 26, 11, 19, 19, 26, 58, 23, 15, 51, 35, 23, 61, 7, 43,
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39,
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35,
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43,
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 39, 23, 15, 7, 43,
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 39,
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 35,
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 43,
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 7, 35, 23, 15, 7, 43
};
reg [17:0] Prev0, Prev1, Prev2, Curr0, Curr1, Next0, Next1, Next2;
reg [17:0] A, B, D, F, G, H;
reg [7:0] pattern, nextpatt;
reg [1:0] i;
reg [7:0] y;
wire curbuf = y[0];
reg prevbuf = 0;
wire iobuf = !curbuf;
wire diff0, diff1;
DiffCheck diffcheck0(Curr1, (i == 0) ? Prev0 : (i == 1) ? Curr0 : (i == 2) ? Prev2 : Next1, diff0);
DiffCheck diffcheck1(Curr1, (i == 0) ? Prev1 : (i == 1) ? Next0 : (i == 2) ? Curr2 : Next2, diff1);
wire [7:0] new_pattern = {diff1, diff0, pattern[7:2]};
wire [17:0] X = (i == 0) ? A : (i == 1) ? Prev1 : (i == 2) ? Next1 : G;
wire [17:0] blend_result;
Blend blender(hqTable[nextpatt], disable_hq2x, Curr0, X, B, D, F, H, blend_result);
reg Curr2_addr1;
reg [AWIDTH:0] Curr2_addr2;
wire [17:0] Curr2 = HALF_DEPTH ? h2rgb(Curr2tmp) : Curr2tmp;
wire [DWIDTH:0] Curr2tmp;
reg [AWIDTH:0] wrin_addr2;
reg [DWIDTH:0] wrpix;
reg wrin_en;
function [17:0] h2rgb;
input [8:0] v;
begin
h2rgb = mono ? {v[5:3],v[2:0], v[5:3],v[2:0], v[5:3],v[2:0]} : {v[8:6],v[8:6],v[5:3],v[5:3],v[2:0],v[2:0]};
end
endfunction
function [8:0] rgb2h;
input [17:0] v;
begin
rgb2h = mono ? {3'b000, v[17:15], v[14:12]} : {v[17:15], v[11:9], v[5:3]};
end
endfunction
hq2x_in #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_in
(
.clk(clk),
.rdaddr(Curr2_addr2),
.rdbuf(Curr2_addr1),
.q(Curr2tmp),
.wraddr(wrin_addr2),
.wrbuf(iobuf),
.data(wrpix),
.wren(wrin_en)
);
reg [1:0] wrout_addr1;
reg [AWIDTH+1:0] wrout_addr2;
reg wrout_en;
reg [DWIDTH:0] wrdata;
hq2x_out #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_out
(
.clk(clk),
.rdaddr(read_x),
.rdbuf(read_y),
.q(outpixel),
.wraddr(wrout_addr2),
.wrbuf(wrout_addr1),
.data(wrdata),
.wren(wrout_en)
);
always @(posedge clk) begin
reg [AWIDTH:0] offs;
reg old_reset_line;
reg old_reset_frame;
wrout_en <= 0;
wrin_en <= 0;
if(ce_x4) begin
pattern <= new_pattern;
if(~&offs) begin
if (i == 0) begin
Curr2_addr1 <= prevbuf;
Curr2_addr2 <= offs;
end
if (i == 1) begin
Prev2 <= Curr2;
Curr2_addr1 <= curbuf;
Curr2_addr2 <= offs;
end
if (i == 2) begin
Next2 <= HALF_DEPTH ? h2rgb(inputpixel) : inputpixel;
wrpix <= inputpixel;
wrin_addr2 <= offs;
wrin_en <= 1;
end
if (i == 3) begin
offs <= offs + 1'd1;
end
if(HALF_DEPTH) wrdata <= rgb2h(blend_result);
else wrdata <= blend_result;
wrout_addr1 <= {curbuf, i[1]};
wrout_addr2 <= {offs, i[1]^i[0]};
wrout_en <= 1;
end
if(i==3) begin
nextpatt <= {new_pattern[7:6], new_pattern[3], new_pattern[5], new_pattern[2], new_pattern[4], new_pattern[1:0]};
{A, G} <= {Prev0, Next0};
{B, F, H, D} <= {Prev1, Curr2, Next1, Curr0};
{Prev0, Prev1} <= {Prev1, Prev2};
{Curr0, Curr1} <= {Curr1, Curr2};
{Next0, Next1} <= {Next1, Next2};
end else begin
nextpatt <= {nextpatt[5], nextpatt[3], nextpatt[0], nextpatt[6], nextpatt[1], nextpatt[7], nextpatt[4], nextpatt[2]};
{B, F, H, D} <= {F, H, D, B};
end
i <= i + 1'b1;
if(old_reset_line && ~reset_line) begin
old_reset_frame <= reset_frame;
offs <= 0;
i <= 0;
y <= y + 1'd1;
prevbuf <= curbuf;
if(old_reset_frame & ~reset_frame) begin
y <= 0;
prevbuf <= 0;
end
end
old_reset_line <= reset_line;
end
end
endmodule // Hq2x

View File

@@ -5,7 +5,11 @@ module keyboard
input clk_24,
input clk,
input reset,
input [10:0] ps2_key,
// input [10:0] ps2_key,
input key_pressed, // 1-make (pressed), 0-break (released)
input key_extended, // extended code
input key_strobe, // strobe
input [7:0] key_code, // key scan code
input [2:0] col,
input [7:0] row,
output [7:0] ROWbit,
@@ -84,82 +88,79 @@ reg swf4 = 1'b0;
reg swf5 = 1'b0;
reg swf6 = 1'b0;
wire pressed = ps2_key[9];
wire [8:0] code = ps2_key[8:0];
always @(posedge clk_24) begin
reg old_state;
old_state <= ps2_key[10];
old_state <= key_strobe;
if(old_state != ps2_key[10]) begin
casex(code)
'h045: sw0 <= pressed; // 0
'h016: sw1 <= pressed; // 1
'h01e: sw2 <= pressed; // 2
'h026: sw3 <= pressed; // 3
'h025: sw4 <= pressed; // 4
'h02e: sw5 <= pressed; // 5
'h036: sw6 <= pressed; // 6
'h03d: sw7 <= pressed; // 7
'h03e: sw8 <= pressed; // 8
'h046: sw9 <= pressed; // 9
'h01c: swa <= pressed; // a
'h032: swb <= pressed; // b
'h021: swc <= pressed; // c
'h023: swd <= pressed; // d
'h024: swe <= pressed; // e
'h02b: swf <= pressed; // f
'h034: swg <= pressed; // g
'h033: swh <= pressed; // h
'h043: swi <= pressed; // i
'h03b: swj <= pressed; // j
'h042: swk <= pressed; // k
'h04b: swl <= pressed; // l
'h03a: swm <= pressed; // m
'h031: swn <= pressed; // n
'h044: swo <= pressed; // o
'h04d: swp <= pressed; // p
'h015: swq <= pressed; // q
'h02d: swr <= pressed; // r
'h01b: sws <= pressed; // s
'h02c: swt <= pressed; // t
'h03c: swu <= pressed; // u
'h02a: swv <= pressed; // v
'h01d: sww <= pressed; // w
'h022: swx <= pressed; // x
'h035: swy <= pressed; // y
'h01a: swz <= pressed; // z
if(old_state != key_strobe) begin
casex(key_code)
'h045: sw0 <= key_pressed; // 0
'h016: sw1 <= key_pressed; // 1
'h01e: sw2 <= key_pressed; // 2
'h026: sw3 <= key_pressed; // 3
'h025: sw4 <= key_pressed; // 4
'h02e: sw5 <= key_pressed; // 5
'h036: sw6 <= key_pressed; // 6
'h03d: sw7 <= key_pressed; // 7
'h03e: sw8 <= key_pressed; // 8
'h046: sw9 <= key_pressed; // 9
'h01c: swa <= key_pressed; // a
'h032: swb <= key_pressed; // b
'h021: swc <= key_pressed; // c
'h023: swd <= key_pressed; // d
'h024: swe <= key_pressed; // e
'h02b: swf <= key_pressed; // f
'h034: swg <= key_pressed; // g
'h033: swh <= key_pressed; // h
'h043: swi <= key_pressed; // i
'h03b: swj <= key_pressed; // j
'h042: swk <= key_pressed; // k
'h04b: swl <= key_pressed; // l
'h03a: swm <= key_pressed; // m
'h031: swn <= key_pressed; // n
'h044: swo <= key_pressed; // o
'h04d: swp <= key_pressed; // p
'h015: swq <= key_pressed; // q
'h02d: swr <= key_pressed; // r
'h01b: sws <= key_pressed; // s
'h02c: swt <= key_pressed; // t
'h03c: swu <= key_pressed; // u
'h02a: swv <= key_pressed; // v
'h01d: sww <= key_pressed; // w
'h022: swx <= key_pressed; // x
'h035: swy <= key_pressed; // y
'h01a: swz <= key_pressed; // z
'hX75: swU <= pressed; // up
'hX72: swD <= pressed; // down
'hx6b: swL <= pressed; // left
'hx74: swR <= pressed; // right
'h059: swrs <= pressed; // right shift
'h012: swls <= pressed; // left shift
'h029: swsp <= pressed; // space
'h041: swcom <= pressed; // comma
'h049: swdot <= pressed; // full stop
'h05a: swret <= pressed; // return
'h04a: swfs <= pressed; // forward slash
'h055: sweq <= pressed; // equals
'h011: swfcn <= pressed; // ALT
'hx71: swdel <= pressed; // delete
'h05b: swrsb <= pressed; // right sq bracket
'h054: swlsb <= pressed; // left sq bracket
'h05d: swbs <= pressed; // back slash h05d
'h04e: swdsh <= pressed; // dash
'h052: swsq <= pressed; // single quote
'h04c: swsc <= pressed; // semi colon
'h076: swesc <= pressed; // escape
'h014: swctl <= pressed; // left control
'hX75: swU <= key_pressed; // up
'hX72: swD <= key_pressed; // down
'hx6b: swL <= key_pressed; // left
'hx74: swR <= key_pressed; // right
'h059: swrs <= key_pressed; // right shift
'h012: swls <= key_pressed; // left shift
'h029: swsp <= key_pressed; // space
'h041: swcom <= key_pressed; // comma
'h049: swdot <= key_pressed; // full stop
'h05a: swret <= key_pressed; // return
'h04a: swfs <= key_pressed; // forward slash
'h055: sweq <= key_pressed; // equals
'h011: swfcn <= key_pressed; // ALT
'hx71: swdel <= key_pressed; // delete
'h05b: swrsb <= key_pressed; // right sq bracket
'h054: swlsb <= key_pressed; // left sq bracket
'h05d: swbs <= key_pressed; // back slash h05d
'h04e: swdsh <= key_pressed; // dash
'h052: swsq <= key_pressed; // single quote
'h04c: swsc <= key_pressed; // semi colon
'h076: swesc <= key_pressed; // escape
'h014: swctl <= key_pressed; // left control
'h009: swrst <= pressed; // F10 break
'h005: swf1 <= pressed; // f1
'h006: swf2 <= pressed; // f2
'h004: swf3 <= pressed; // f3
'h00c: swf4 <= pressed; // f4
'h003: swf5 <= pressed; // f5
'h00b: swf6 <= pressed; // f6
'h009: swrst <= key_pressed; // F10 break
'h005: swf1 <= key_pressed; // f1
'h006: swf2 <= key_pressed; // f2
'h004: swf3 <= key_pressed; // f3
'h00c: swf4 <= key_pressed; // f4
'h003: swf5 <= key_pressed; // f5
'h00b: swf6 <= key_pressed; // f6
endcase
end
@@ -171,7 +172,7 @@ wire no_key = (~sw0 & ~sw1 & ~sw2 & ~sw3 & ~sw4 & ~sw5 & ~sw6 & ~sw7 & ~sw8 & ~s
~sweq & ~swfcn & ~swdel & ~swrsb & ~swlsb & ~swbs & ~swdsh & ~swsq & ~swsc & ~swesc & ~swctl & ~swf1 & ~swf2 &
~swf3 & ~swf4 & ~swf5 & ~swf6);
wire sp_key = ( swls | swrs | swctl | swfcn );
//wire sp_key = ( swls | swrs | swctl | swfcn );
always @(posedge clk) begin
if (no_key) ROWbit <= 8'b11111111;

View File

@@ -1,530 +0,0 @@
//
// mist_io.v
//
// mist_io for the MiST board
// http://code.google.com/p/mist-board/
//
// Copyright (c) 2014 Till Harbaum <till@harbaum.org>
// Copyright (c) 2015-2017 Sorgelig
//
// This source file 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, either version 3 of the License, or
// (at your option) any later version.
//
// This source file 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/>.
//
///////////////////////////////////////////////////////////////////////
//
// Use buffer to access SD card. It's time-critical part.
// Made module synchroneous with 2 clock domains: clk_sys and SPI_SCK
// (Sorgelig)
//
// for synchronous projects default value for PS2DIV is fine for any frequency of system clock.
// clk_ps2 = clk_sys/(PS2DIV*2)
//
module mist_io #(parameter STRLEN=0, parameter PS2DIV=100)
(
// parameter STRLEN and the actual length of conf_str have to match
input [(8*STRLEN)-1:0] conf_str,
// Global clock. It should be around 100MHz (higher is better).
input clk_sys,
// Global SPI clock from ARM. 24MHz
input SPI_SCK,
input CONF_DATA0,
input SPI_SS2,
output SPI_DO,
input SPI_DI,
output reg [7:0] joystick_0,
output reg [7:0] joystick_1,
// output reg [31:0] joystick_2,
// output reg [31:0] joystick_3,
// output reg [31:0] joystick_4,
output reg [15:0] joystick_analog_0,
output reg [15:0] joystick_analog_1,
output [1:0] buttons,
output [1:0] switches,
output scandoublerD,
output ypbpr,
output reg [31:0] status,
// SD config
input sd_conf,
input sd_sdhc,
output [1:0] img_mounted, // signaling that new image has been mounted
output reg [31:0] img_size, // size of image in bytes
// SD block level access
input [31:0] sd_lba,
input [1:0] sd_rd,
input [1:0] sd_wr,
output reg sd_ack,
output reg sd_ack_conf,
// SD byte level access. Signals for 2-PORT altsyncram.
output reg [8:0] sd_buff_addr,
output reg [7:0] sd_buff_dout,
input [7:0] sd_buff_din,
output reg sd_buff_wr,
// ps2 keyboard emulation
output ps2_kbd_clk,
output reg ps2_kbd_data,
output ps2_mouse_clk,
output reg ps2_mouse_data,
// ps2 alternative interface.
// [8] - extended, [9] - pressed, [10] - toggles with every press/release
output reg [10:0] ps2_key = 0,
// [24] - toggles with every event
output reg [24:0] ps2_mouse = 0,
// ARM -> FPGA download
input ioctl_ce,
output reg ioctl_download = 0, // signal indicating an active download
output reg [7:0] ioctl_index, // menu index used to upload the file
output reg ioctl_wr = 0,
output reg [24:0] ioctl_addr,
output reg [7:0] ioctl_dout
);
reg [7:0] but_sw;
reg [2:0] stick_idx;
reg [1:0] mount_strobe = 0;
assign img_mounted = mount_strobe;
assign buttons = but_sw[1:0];
assign switches = but_sw[3:2];
assign scandoublerD = but_sw[4];
assign ypbpr = but_sw[5];
// this variant of user_io is for 8 bit cores (type == a4) only
wire [7:0] core_type = 8'ha4;
// command byte read by the io controller
wire drive_sel = sd_rd[1] | sd_wr[1];
wire [7:0] sd_cmd = { 4'h6, sd_conf, sd_sdhc, sd_wr[drive_sel], sd_rd[drive_sel] };
reg [7:0] cmd;
reg [2:0] bit_cnt; // counts bits 0-7 0-7 ...
reg [9:0] byte_cnt; // counts bytes
reg spi_do;
assign SPI_DO = CONF_DATA0 ? 1'bZ : spi_do;
reg [7:0] spi_data_out;
// SPI transmitter
always@(negedge SPI_SCK) spi_do <= spi_data_out[~bit_cnt];
reg [7:0] spi_data_in;
reg spi_data_ready = 0;
// SPI receiver
always@(posedge SPI_SCK or posedge CONF_DATA0) begin
reg [6:0] sbuf;
reg [31:0] sd_lba_r;
reg drive_sel_r;
if(CONF_DATA0) begin
bit_cnt <= 0;
byte_cnt <= 0;
spi_data_out <= core_type;
end
else
begin
bit_cnt <= bit_cnt + 1'd1;
sbuf <= {sbuf[5:0], SPI_DI};
// finished reading command byte
if(bit_cnt == 7) begin
if(!byte_cnt) cmd <= {sbuf, SPI_DI};
spi_data_in <= {sbuf, SPI_DI};
spi_data_ready <= ~spi_data_ready;
if(~&byte_cnt) byte_cnt <= byte_cnt + 8'd1;
spi_data_out <= 0;
case({(!byte_cnt) ? {sbuf, SPI_DI} : cmd})
// reading config string
8'h14: if(byte_cnt < STRLEN) spi_data_out <= conf_str[(STRLEN - byte_cnt - 1)<<3 +:8];
// reading sd card status
8'h16: if(byte_cnt == 0) begin
spi_data_out <= sd_cmd;
sd_lba_r <= sd_lba;
drive_sel_r <= drive_sel;
end else if (byte_cnt == 1) begin
spi_data_out <= drive_sel_r;
end else if(byte_cnt < 6) spi_data_out <= sd_lba_r[(5-byte_cnt)<<3 +:8];
// reading sd card write data
8'h18: spi_data_out <= sd_buff_din;
endcase
end
end
end
reg [31:0] ps2_key_raw = 0;
wire pressed = (ps2_key_raw[15:8] != 8'hf0);
wire extended = (~pressed ? (ps2_key_raw[23:16] == 8'he0) : (ps2_key_raw[15:8] == 8'he0));
// transfer to clk_sys domain
always@(posedge clk_sys) begin
reg old_ss1, old_ss2;
reg old_ready1, old_ready2;
reg [2:0] b_wr;
reg got_ps2 = 0;
old_ss1 <= CONF_DATA0;
old_ss2 <= old_ss1;
old_ready1 <= spi_data_ready;
old_ready2 <= old_ready1;
sd_buff_wr <= b_wr[0];
if(b_wr[2] && (~&sd_buff_addr)) sd_buff_addr <= sd_buff_addr + 1'b1;
b_wr <= (b_wr<<1);
if(old_ss2) begin
got_ps2 <= 0;
sd_ack <= 0;
sd_ack_conf <= 0;
sd_buff_addr <= 0;
if(got_ps2) begin
if(cmd == 4) ps2_mouse[24] <= ~ps2_mouse[24];
if(cmd == 5) begin
ps2_key <= {~ps2_key[10], pressed, extended, ps2_key_raw[7:0]};
if(ps2_key_raw == 'hE012E07C) ps2_key[9:0] <= 'h37C; // prnscr pressed
if(ps2_key_raw == 'h7CE0F012) ps2_key[9:0] <= 'h17C; // prnscr released
if(ps2_key_raw == 'hF014F077) ps2_key[9:0] <= 'h377; // pause pressed
end
end
end
else
if(old_ready2 ^ old_ready1) begin
if(cmd == 8'h18 && ~&sd_buff_addr) sd_buff_addr <= sd_buff_addr + 1'b1;
if(byte_cnt < 2) begin
if (cmd == 8'h19) sd_ack_conf <= 1;
if((cmd == 8'h17) || (cmd == 8'h18)) sd_ack <= 1;
mount_strobe <= 0;
if(cmd == 5) ps2_key_raw <= 0;
end else begin
case(cmd)
// buttons and switches
8'h01: but_sw <= spi_data_in;
8'h02: joystick_0 <= spi_data_in;
8'h03: joystick_1 <= spi_data_in;
// 8'h60: if (byte_cnt < 5) joystick_0[(byte_cnt-1)<<3 +:8] <= spi_data_in;
// 8'h61: if (byte_cnt < 5) joystick_1[(byte_cnt-1)<<3 +:8] <= spi_data_in;
// 8'h62: if (byte_cnt < 5) joystick_2[(byte_cnt-1)<<3 +:8] <= spi_data_in;
// 8'h63: if (byte_cnt < 5) joystick_3[(byte_cnt-1)<<3 +:8] <= spi_data_in;
// 8'h64: if (byte_cnt < 5) joystick_4[(byte_cnt-1)<<3 +:8] <= spi_data_in;
// store incoming ps2 mouse bytes
8'h04: begin
got_ps2 <= 1;
case(byte_cnt)
2: ps2_mouse[7:0] <= spi_data_in;
3: ps2_mouse[15:8] <= spi_data_in;
4: ps2_mouse[23:16] <= spi_data_in;
endcase
ps2_mouse_fifo[ps2_mouse_wptr] <= spi_data_in;
ps2_mouse_wptr <= ps2_mouse_wptr + 1'd1;
end
// store incoming ps2 keyboard bytes
8'h05: begin
got_ps2 <= 1;
ps2_key_raw[31:0] <= {ps2_key_raw[23:0], spi_data_in};
ps2_kbd_fifo[ps2_kbd_wptr] <= spi_data_in;
ps2_kbd_wptr <= ps2_kbd_wptr + 1'd1;
end
8'h15: status[7:0] <= spi_data_in;
// send SD config IO -> FPGA
// flag that download begins
// sd card knows data is config if sd_dout_strobe is asserted
// with sd_ack still being inactive (low)
8'h19,
// send sector IO -> FPGA
// flag that download begins
8'h17: begin
sd_buff_dout <= spi_data_in;
b_wr <= 1;
end
// joystick analog
8'h1a: begin
// first byte is joystick index
if(byte_cnt == 2) stick_idx <= spi_data_in[2:0];
else if(byte_cnt == 3) begin
// second byte is x axis
if(stick_idx == 0) joystick_analog_0[15:8] <= spi_data_in;
else if(stick_idx == 1) joystick_analog_1[15:8] <= spi_data_in;
end else if(byte_cnt == 4) begin
// third byte is y axis
if(stick_idx == 0) joystick_analog_0[7:0] <= spi_data_in;
else if(stick_idx == 1) joystick_analog_1[7:0] <= spi_data_in;
end
end
// notify image selection
8'h1c: mount_strobe[spi_data_in[0]] <= 1;
// send image info
8'h1d: if(byte_cnt<6) img_size[(byte_cnt-2)<<3 +:8] <= spi_data_in;
// status, 32bit version
8'h1e: if(byte_cnt<6) status[(byte_cnt-2)<<3 +:8] <= spi_data_in;
default: ;
endcase
end
end
end
/////////////////////////////// PS2 ///////////////////////////////
// 8 byte fifos to store ps2 bytes
localparam PS2_FIFO_BITS = 3;
reg clk_ps2;
always @(negedge clk_sys) begin
integer cnt;
cnt <= cnt + 1'd1;
if(cnt == PS2DIV) begin
clk_ps2 <= ~clk_ps2;
cnt <= 0;
end
end
// keyboard
reg [7:0] ps2_kbd_fifo[1<<PS2_FIFO_BITS];
reg [PS2_FIFO_BITS-1:0] ps2_kbd_wptr;
reg [PS2_FIFO_BITS-1:0] ps2_kbd_rptr;
// ps2 transmitter state machine
reg [3:0] ps2_kbd_tx_state;
reg [7:0] ps2_kbd_tx_byte;
reg ps2_kbd_parity;
assign ps2_kbd_clk = clk_ps2 || (ps2_kbd_tx_state == 0);
// ps2 transmitter
// Takes a byte from the FIFO and sends it in a ps2 compliant serial format.
reg ps2_kbd_r_inc;
always@(posedge clk_sys) begin
reg old_clk;
old_clk <= clk_ps2;
if(~old_clk & clk_ps2) begin
ps2_kbd_r_inc <= 0;
if(ps2_kbd_r_inc) ps2_kbd_rptr <= ps2_kbd_rptr + 1'd1;
// transmitter is idle?
if(ps2_kbd_tx_state == 0) begin
// data in fifo present?
if(ps2_kbd_wptr != ps2_kbd_rptr) begin
// load tx register from fifo
ps2_kbd_tx_byte <= ps2_kbd_fifo[ps2_kbd_rptr];
ps2_kbd_r_inc <= 1;
// reset parity
ps2_kbd_parity <= 1;
// start transmitter
ps2_kbd_tx_state <= 1;
// put start bit on data line
ps2_kbd_data <= 0; // start bit is 0
end
end else begin
// transmission of 8 data bits
if((ps2_kbd_tx_state >= 1)&&(ps2_kbd_tx_state < 9)) begin
ps2_kbd_data <= ps2_kbd_tx_byte[0]; // data bits
ps2_kbd_tx_byte[6:0] <= ps2_kbd_tx_byte[7:1]; // shift down
if(ps2_kbd_tx_byte[0])
ps2_kbd_parity <= !ps2_kbd_parity;
end
// transmission of parity
if(ps2_kbd_tx_state == 9) ps2_kbd_data <= ps2_kbd_parity;
// transmission of stop bit
if(ps2_kbd_tx_state == 10) ps2_kbd_data <= 1; // stop bit is 1
// advance state machine
if(ps2_kbd_tx_state < 11) ps2_kbd_tx_state <= ps2_kbd_tx_state + 1'd1;
else ps2_kbd_tx_state <= 0;
end
end
end
// mouse
reg [7:0] ps2_mouse_fifo[1<<PS2_FIFO_BITS];
reg [PS2_FIFO_BITS-1:0] ps2_mouse_wptr;
reg [PS2_FIFO_BITS-1:0] ps2_mouse_rptr;
// ps2 transmitter state machine
reg [3:0] ps2_mouse_tx_state;
reg [7:0] ps2_mouse_tx_byte;
reg ps2_mouse_parity;
assign ps2_mouse_clk = clk_ps2 || (ps2_mouse_tx_state == 0);
// ps2 transmitter
// Takes a byte from the FIFO and sends it in a ps2 compliant serial format.
reg ps2_mouse_r_inc;
always@(posedge clk_sys) begin
reg old_clk;
old_clk <= clk_ps2;
if(~old_clk & clk_ps2) begin
ps2_mouse_r_inc <= 0;
if(ps2_mouse_r_inc) ps2_mouse_rptr <= ps2_mouse_rptr + 1'd1;
// transmitter is idle?
if(ps2_mouse_tx_state == 0) begin
// data in fifo present?
if(ps2_mouse_wptr != ps2_mouse_rptr) begin
// load tx register from fifo
ps2_mouse_tx_byte <= ps2_mouse_fifo[ps2_mouse_rptr];
ps2_mouse_r_inc <= 1;
// reset parity
ps2_mouse_parity <= 1;
// start transmitter
ps2_mouse_tx_state <= 1;
// put start bit on data line
ps2_mouse_data <= 0; // start bit is 0
end
end else begin
// transmission of 8 data bits
if((ps2_mouse_tx_state >= 1)&&(ps2_mouse_tx_state < 9)) begin
ps2_mouse_data <= ps2_mouse_tx_byte[0]; // data bits
ps2_mouse_tx_byte[6:0] <= ps2_mouse_tx_byte[7:1]; // shift down
if(ps2_mouse_tx_byte[0])
ps2_mouse_parity <= !ps2_mouse_parity;
end
// transmission of parity
if(ps2_mouse_tx_state == 9) ps2_mouse_data <= ps2_mouse_parity;
// transmission of stop bit
if(ps2_mouse_tx_state == 10) ps2_mouse_data <= 1; // stop bit is 1
// advance state machine
if(ps2_mouse_tx_state < 11) ps2_mouse_tx_state <= ps2_mouse_tx_state + 1'd1;
else ps2_mouse_tx_state <= 0;
end
end
end
/////////////////////////////// DOWNLOADING ///////////////////////////////
reg [7:0] data_w;
reg [24:0] addr_w;
reg rclk = 0;
localparam UIO_FILE_TX = 8'h53;
localparam UIO_FILE_TX_DAT = 8'h54;
localparam UIO_FILE_INDEX = 8'h55;
reg rdownload = 0;
// data_io has its own SPI interface to the io controller
always@(posedge SPI_SCK, posedge SPI_SS2) begin
reg [6:0] sbuf;
reg [7:0] cmd;
reg [4:0] cnt;
reg [24:0] addr;
if(SPI_SS2) cnt <= 0;
else begin
// don't shift in last bit. It is evaluated directly
// when writing to ram
if(cnt != 15) sbuf <= { sbuf[5:0], SPI_DI};
// count 0-7 8-15 8-15 ...
if(cnt < 15) cnt <= cnt + 1'd1;
else cnt <= 8;
// finished command byte
if(cnt == 7) cmd <= {sbuf, SPI_DI};
// prepare/end transmission
if((cmd == UIO_FILE_TX) && (cnt == 15)) begin
// prepare
if(SPI_DI) begin
case(ioctl_index[4:0])
1: addr <= 25'h200000; // TRD buffer at 2MB
2: addr <= 25'h400000; // tape buffer at 4MB
default: addr <= 25'h150000; // boot rom
endcase
rdownload <= 1;
end else begin
addr_w <= addr;
rdownload <= 0;
end
end
// command 0x54: UIO_FILE_TX
if((cmd == UIO_FILE_TX_DAT) && (cnt == 15)) begin
addr_w <= addr;
data_w <= {sbuf, SPI_DI};
addr <= addr + 1'd1;
rclk <= ~rclk;
end
// expose file (menu) index
if((cmd == UIO_FILE_INDEX) && (cnt == 15)) ioctl_index <= {sbuf, SPI_DI};
end
end
// transfer to ioctl_clk domain.
// ioctl_index is set before ioctl_download, so it's stable already
always@(posedge clk_sys) begin
reg rclkD, rclkD2;
if(ioctl_ce) begin
ioctl_download <= rdownload;
rclkD <= rclk;
rclkD2 <= rclkD;
ioctl_wr <= 0;
if(rclkD != rclkD2) begin
ioctl_dout <= data_w;
ioctl_addr <= addr_w;
ioctl_wr <= 1;
end
end
end
endmodule

View File

@@ -60,7 +60,11 @@
entity oricatmos is
port (
RESET : in std_logic;
ps2_key : in std_logic_vector(10 downto 0);
ps2_key : in std_logic_vector(10 downto 0);
key_pressed : in std_logic;
key_extended : in std_logic;
key_code : in std_logic_vector(7 downto 0);
key_strobe : in std_logic;
K7_TAPEIN : in std_logic;
K7_TAPEOUT : out std_logic;
K7_REMOTE : out std_logic;
@@ -91,7 +95,7 @@ architecture RTL of oricatmos is
signal cpu_irq : std_logic;
-- VIA
signal via_pa_out_oe : std_logic_vector(7 downto 0);
-- signal via_pa_out_oe : std_logic_vector(7 downto 0);
signal via_pa_in : std_logic_vector(7 downto 0);
signal via_pa_out : std_logic_vector(7 downto 0);
signal via_ca1_in : std_logic;
@@ -99,14 +103,14 @@ architecture RTL of oricatmos is
-- le 17/11/2009 signal via_ca2_out : std_logic;
-- le 17/11/2009 signal via_ca2_oe_l : std_logic;
-- le 17/11/2009 signal via_cb1_in : std_logic;
signal via_cb1_out : std_logic;
signal via_cb1_oe_l : std_logic;
-- signal via_cb1_out : std_logic;
-- signal via_cb1_oe_l : std_logic;
signal via_cb2_in : std_logic;
signal via_cb2_out : std_logic;
signal via_cb2_oe_l : std_logic;
-- signal via_cb2_oe_l : std_logic;
signal via_in : std_logic_vector(7 downto 0);
signal via_out : std_logic_vector(7 downto 0);
signal via_oe_l : std_logic_vector(7 downto 0);
-- signal via_oe_l : std_logic_vector(7 downto 0);
signal VIA_DO : std_logic_vector(7 downto 0);
-- Clavier : émulation par port PS2
@@ -121,7 +125,7 @@ architecture RTL of oricatmos is
signal ula_CSIOn : std_logic;
signal ula_CSIO : std_logic;
signal ula_CSROMn : std_logic;
signal ula_CSRAMn : std_logic; -- add 05/02/09
-- signal ula_CSRAMn : std_logic; -- add 05/02/09
signal ula_AD_RAM : std_logic_vector(7 downto 0);
signal ula_AD_SRAM : std_logic_vector(15 downto 0);
signal ula_CE_SRAM : std_logic;
@@ -148,17 +152,22 @@ architecture RTL of oricatmos is
signal SRAM_DO : std_logic_vector(7 downto 0);
signal break : std_logic;
component keyboard port (
clk_24 : in std_logic;
clk : in std_logic;
reset : in std_logic;
ps2_key : in std_logic_vector(10 downto 0);
row : in std_logic_vector(7 downto 0);
col : in std_logic_vector(2 downto 0);
ROWbit : out std_logic_vector(7 downto 0);
swrst : out std_logic
COMPONENT keyboard
PORT
(
clk_24 : IN STD_LOGIC;
clk : IN STD_LOGIC;
reset : IN STD_LOGIC;
key_pressed : IN STD_LOGIC;
key_extended: IN STD_LOGIC;
key_strobe : IN STD_LOGIC;
key_code : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
col : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
row : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
ROWbit : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
swrst : OUT STD_LOGIC
);
end component;
END COMPONENT;
begin
RESETn <= not RESET;
@@ -217,7 +226,7 @@ inst_ula : entity work.ULA
LATCH_SRAM => ula_LATCH_SRAM,
CSIOn => ula_CSIOn,
CSROMn => ula_CSROMn,
CSRAMn => ula_CSRAMn,
-- CSRAMn => ula_CSRAMn,
R => VIDEO_R,
G => VIDEO_G,
B => VIDEO_B,
@@ -241,16 +250,16 @@ inst_via : entity work.M6522
O_CA2 => psg_bdir, -- via_ca2_out
I_PA => via_pa_in,
O_PA => via_pa_out,
O_PA_OE_L => via_pa_out_oe,
-- O_PA_OE_L => via_pa_out_oe,
I_CB1 => K7_TAPEIN,
O_CB1 => via_cb1_out,
O_CB1_OE_L => via_cb1_oe_l,
-- O_CB1 => via_cb1_out,
-- O_CB1_OE_L => via_cb1_oe_l,
I_CB2 => '1',
O_CB2 => via_cb2_out,
O_CB2_OE_L => via_cb2_oe_l,
-- O_CB2_OE_L => via_cb2_oe_l,
I_PB => via_in,
O_PB => via_out,
O_PB_OE_L => via_oe_l,
-- O_PB_OE_L => via_oe_l,
RESET_L => RESETn,
I_P2_H => ula_phi2,
ENA_4 => '1',
@@ -275,7 +284,10 @@ inst_key : keyboard
clk_24 => CLK_IN,
clk => ula_phi2,
reset => not RESETn,
ps2_key => ps2_key,
key_pressed => key_pressed,
key_extended => key_extended,
key_strobe => key_strobe,
key_code => key_code,
row => via_pa_out,
col => via_out(2 downto 0),
ROWbit => KEY_ROW,

View File

@@ -1,194 +0,0 @@
// A simple OSD implementation. Can be hooked up between a cores
// VGA output and the physical VGA pins
module osd (
// OSDs pixel clock, should be synchronous to cores pixel clock to
// avoid jitter.
input clk_sys,
// SPI interface
input SPI_SCK,
input SPI_SS3,
input SPI_DI,
input [1:0] rotate, //[0] - rotate [1] - left or right
// VGA signals coming from core
input [5:0] R_in,
input [5:0] G_in,
input [5:0] B_in,
input HSync,
input VSync,
// VGA signals going to video connector
output [5:0] R_out,
output [5:0] G_out,
output [5:0] B_out
);
parameter OSD_X_OFFSET = 10'd0;
parameter OSD_Y_OFFSET = 10'd0;
parameter OSD_COLOR = 3'd0;
localparam OSD_WIDTH = 10'd256;
localparam OSD_HEIGHT = 10'd128;
// *********************************************************************************
// spi client
// *********************************************************************************
// this core supports only the display related OSD commands
// of the minimig
reg osd_enable;
(* ramstyle = "no_rw_check" *) reg [7:0] osd_buffer[2047:0]; // the OSD buffer itself
// the OSD has its own SPI interface to the io controller
always@(posedge SPI_SCK, posedge SPI_SS3) begin
reg [4:0] cnt;
reg [10:0] bcnt;
reg [7:0] sbuf;
reg [7:0] cmd;
if(SPI_SS3) begin
cnt <= 0;
bcnt <= 0;
end else begin
sbuf <= {sbuf[6:0], SPI_DI};
// 0:7 is command, rest payload
if(cnt < 15) cnt <= cnt + 1'd1;
else cnt <= 8;
if(cnt == 7) begin
cmd <= {sbuf[6:0], SPI_DI};
// lower three command bits are line address
bcnt <= {sbuf[1:0], SPI_DI, 8'h00};
// command 0x40: OSDCMDENABLE, OSDCMDDISABLE
if(sbuf[6:3] == 4'b0100) osd_enable <= SPI_DI;
end
// command 0x20: OSDCMDWRITE
if((cmd[7:3] == 5'b00100) && (cnt == 15)) begin
osd_buffer[bcnt] <= {sbuf[6:0], SPI_DI};
bcnt <= bcnt + 1'd1;
end
end
end
// *********************************************************************************
// video timing and sync polarity anaylsis
// *********************************************************************************
// horizontal counter
reg [9:0] h_cnt;
reg [9:0] hs_low, hs_high;
wire hs_pol = hs_high < hs_low;
wire [9:0] dsp_width = hs_pol ? hs_low : hs_high;
// vertical counter
reg [9:0] v_cnt;
reg [9:0] vs_low, vs_high;
wire vs_pol = vs_high < vs_low;
wire [9:0] dsp_height = vs_pol ? vs_low : vs_high;
wire doublescan = (dsp_height>350);
reg ce_pix;
always @(negedge clk_sys) begin
integer cnt = 0;
integer pixsz, pixcnt;
reg hs;
cnt <= cnt + 1;
hs <= HSync;
pixcnt <= pixcnt + 1;
if(pixcnt == pixsz) pixcnt <= 0;
ce_pix <= !pixcnt;
if(hs && ~HSync) begin
cnt <= 0;
pixsz <= (cnt >> 9) - 1;
pixcnt <= 0;
ce_pix <= 1;
end
end
always @(posedge clk_sys) begin
reg hsD, hsD2;
reg vsD, vsD2;
if(ce_pix) begin
// bring hsync into local clock domain
hsD <= HSync;
hsD2 <= hsD;
// falling edge of HSync
if(!hsD && hsD2) begin
h_cnt <= 0;
hs_high <= h_cnt;
end
// rising edge of HSync
else if(hsD && !hsD2) begin
h_cnt <= 0;
hs_low <= h_cnt;
v_cnt <= v_cnt + 1'd1;
end else begin
h_cnt <= h_cnt + 1'd1;
end
vsD <= VSync;
vsD2 <= vsD;
// falling edge of VSync
if(!vsD && vsD2) begin
v_cnt <= 0;
vs_high <= v_cnt;
end
// rising edge of VSync
else if(vsD && !vsD2) begin
v_cnt <= 0;
vs_low <= v_cnt;
end
end
end
// area in which OSD is being displayed
wire [9:0] h_osd_start = ((dsp_width - OSD_WIDTH)>> 1) + OSD_X_OFFSET;
wire [9:0] h_osd_end = h_osd_start + OSD_WIDTH;
wire [9:0] v_osd_start = ((dsp_height- (OSD_HEIGHT<<doublescan))>> 1) + OSD_Y_OFFSET;
wire [9:0] v_osd_end = v_osd_start + (OSD_HEIGHT<<doublescan);
wire [9:0] osd_hcnt = h_cnt - h_osd_start;
wire [9:0] osd_vcnt = v_cnt - v_osd_start;
wire [9:0] osd_hcnt_next = osd_hcnt + 2'd1; // one pixel offset for osd pixel
wire [9:0] osd_hcnt_next2 = osd_hcnt + 2'd2; // two pixel offset for osd byte address register
wire osd_de = osd_enable &&
(HSync != hs_pol) && (h_cnt >= h_osd_start) && (h_cnt < h_osd_end) &&
(VSync != vs_pol) && (v_cnt >= v_osd_start) && (v_cnt < v_osd_end);
reg [10:0] osd_buffer_addr;
wire [7:0] osd_byte = osd_buffer[osd_buffer_addr];
reg osd_pixel;
always @(posedge clk_sys) begin
if(ce_pix) begin
osd_buffer_addr <= rotate[0] ? {rotate[1] ? osd_hcnt_next2[7:5] : ~osd_hcnt_next2[7:5],
rotate[1] ? (doublescan ? ~osd_vcnt[7:0] : ~{osd_vcnt[6:0], 1'b0}) :
(doublescan ? osd_vcnt[7:0] : {osd_vcnt[6:0], 1'b0})} :
{doublescan ? osd_vcnt[7:5] : osd_vcnt[6:4], osd_hcnt_next2[7:0]};
osd_pixel <= rotate[0] ? osd_byte[rotate[1] ? osd_hcnt_next[4:2] : ~osd_hcnt_next[4:2]] :
osd_byte[doublescan ? osd_vcnt[4:2] : osd_vcnt[3:1]];
end
end
assign R_out = !osd_de ? R_in : {osd_pixel, osd_pixel, OSD_COLOR[2], R_in[5:3]};
assign G_out = !osd_de ? G_in : {osd_pixel, osd_pixel, OSD_COLOR[1], G_in[5:3]};
assign B_out = !osd_de ? B_in : {osd_pixel, osd_pixel, OSD_COLOR[0], B_in[5:3]};
endmodule

View File

@@ -38,24 +38,20 @@
// synopsys translate_on
module pll (
inclk0,
c0,
c1);
c0);
input inclk0;
output c0;
output c1;
wire [4:0] sub_wire0;
wire [0:0] sub_wire5 = 1'h0;
wire [1:1] sub_wire2 = sub_wire0[1:1];
wire [0:0] sub_wire4 = 1'h0;
wire [0:0] sub_wire1 = sub_wire0[0:0];
wire c0 = sub_wire1;
wire c1 = sub_wire2;
wire sub_wire3 = inclk0;
wire [1:0] sub_wire4 = {sub_wire5, sub_wire3};
wire sub_wire2 = inclk0;
wire [1:0] sub_wire3 = {sub_wire4, sub_wire2};
altpll altpll_component (
.inclk (sub_wire4),
.inclk (sub_wire3),
.clk (sub_wire0),
.activeclock (),
.areset (1'b0),
@@ -98,10 +94,6 @@ module pll (
altpll_component.clk0_duty_cycle = 50,
altpll_component.clk0_multiply_by = 8,
altpll_component.clk0_phase_shift = "0",
altpll_component.clk1_divide_by = 9,
altpll_component.clk1_duty_cycle = 50,
altpll_component.clk1_multiply_by = 2,
altpll_component.clk1_phase_shift = "0",
altpll_component.compensate_clock = "CLK0",
altpll_component.inclk0_input_frequency = 37037,
altpll_component.intended_device_family = "Cyclone III",
@@ -135,7 +127,7 @@ module pll (
altpll_component.port_scanread = "PORT_UNUSED",
altpll_component.port_scanwrite = "PORT_UNUSED",
altpll_component.port_clk0 = "PORT_USED",
altpll_component.port_clk1 = "PORT_USED",
altpll_component.port_clk1 = "PORT_UNUSED",
altpll_component.port_clk2 = "PORT_UNUSED",
altpll_component.port_clk3 = "PORT_UNUSED",
altpll_component.port_clk4 = "PORT_UNUSED",
@@ -175,11 +167,8 @@ endmodule
// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0"
// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8"
// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "9"
// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "9"
// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "24.000000"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "6.000000"
// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
@@ -200,26 +189,18 @@ endmodule
// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available"
// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0"
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg"
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "ps"
// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any"
// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"
// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0"
// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "8"
// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "2"
// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1"
// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "24.00000000"
// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "6.00000000"
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0"
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0"
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz"
// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0"
// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000"
// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000"
// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0"
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg"
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg"
// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1"
@@ -242,14 +223,11 @@ endmodule
// Retrieval info: PRIVATE: SPREAD_USE STRING "0"
// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0"
// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1"
// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1"
// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1"
// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
// Retrieval info: PRIVATE: USE_CLK0 STRING "1"
// Retrieval info: PRIVATE: USE_CLK1 STRING "1"
// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0"
// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0"
// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0"
// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0"
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
@@ -258,10 +236,6 @@ endmodule
// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "8"
// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "9"
// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50"
// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "2"
// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0"
// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0"
// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "37037"
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
@@ -294,7 +268,7 @@ endmodule
// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED"
@@ -312,12 +286,10 @@ endmodule
// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5"
// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]"
// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0"
// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1"
// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0"
// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0
// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0
// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0
// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE

View File

@@ -1,183 +0,0 @@
//
// scandoubler.v
//
// Copyright (c) 2015 Till Harbaum <till@harbaum.org>
// Copyright (c) 2017 Sorgelig
//
// This source file 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, either version 3 of the License, or
// (at your option) any later version.
//
// This source file 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/>.
// TODO: Delay vsync one line
module scandoubler #(parameter LENGTH, parameter HALF_DEPTH)
(
// system interface
input clk_sys,
input ce_pix,
input ce_pix_actual,
input hq2x,
// shifter video interface
input hs_in,
input vs_in,
input line_start,
input [DWIDTH:0] r_in,
input [DWIDTH:0] g_in,
input [DWIDTH:0] b_in,
input mono,
// output interface
output reg hs_out,
output vs_out,
output [DWIDTH:0] r_out,
output [DWIDTH:0] g_out,
output [DWIDTH:0] b_out
);
localparam DWIDTH = HALF_DEPTH ? 2 : 5;
assign vs_out = vs_in;
reg [2:0] phase;
reg [2:0] ce_div;
reg [7:0] pix_len = 0;
wire [7:0] pl = pix_len + 1'b1;
reg ce_x1, ce_x4;
reg req_line_reset;
wire ls_in = hs_in | line_start;
always @(negedge clk_sys) begin
reg old_ce;
reg [2:0] ce_cnt;
reg [7:0] pixsz2, pixsz4 = 0;
old_ce <= ce_pix;
if(~&pix_len) pix_len <= pix_len + 1'd1;
ce_x4 <= 0;
ce_x1 <= 0;
// use such odd comparison to place c_x4 evenly if master clock isn't multiple 4.
if((pl == pixsz4) || (pl == pixsz2) || (pl == (pixsz2+pixsz4))) begin
phase <= phase + 1'd1;
ce_x4 <= 1;
end
if(~old_ce & ce_pix) begin
pixsz2 <= {1'b0, pl[7:1]};
pixsz4 <= {2'b00, pl[7:2]};
ce_x1 <= 1;
ce_x4 <= 1;
pix_len <= 0;
phase <= phase + 1'd1;
ce_cnt <= ce_cnt + 1'd1;
if(ce_pix_actual) begin
phase <= 0;
ce_div <= ce_cnt + 1'd1;
ce_cnt <= 0;
req_line_reset <= 0;
end
if(ls_in) req_line_reset <= 1;
end
end
reg ce_sd;
always @(*) begin
case(ce_div)
2: ce_sd = !phase[0];
4: ce_sd = !phase[1:0];
default: ce_sd <= 1;
endcase
end
localparam AWIDTH = `BITS_TO_FIT(LENGTH);
Hq2x #(.LENGTH(LENGTH), .HALF_DEPTH(HALF_DEPTH)) Hq2x
(
.clk(clk_sys),
.ce_x4(ce_x4 & ce_sd),
.inputpixel({b_in,g_in,r_in}),
.mono(mono),
.disable_hq2x(~hq2x),
.reset_frame(vs_in),
.reset_line(req_line_reset),
.read_y(sd_line),
.read_x(sd_h_actual),
.outpixel({b_out,g_out,r_out})
);
reg [10:0] sd_h_actual;
always @(*) begin
case(ce_div)
2: sd_h_actual = sd_h[10:1];
4: sd_h_actual = sd_h[10:2];
default: sd_h_actual = sd_h;
endcase
end
reg [10:0] sd_h;
reg [1:0] sd_line;
always @(posedge clk_sys) begin
reg [11:0] hs_max,hs_rise,hs_ls;
reg [10:0] hcnt;
reg [11:0] sd_hcnt;
reg hs, hs2, vs, ls;
if(ce_x1) begin
hs <= hs_in;
ls <= ls_in;
if(ls && !ls_in) hs_ls <= {hcnt,1'b1};
// falling edge of hsync indicates start of line
if(hs && !hs_in) begin
hs_max <= {hcnt,1'b1};
hcnt <= 0;
if(ls && !ls_in) hs_ls <= {10'd0,1'b1};
end else begin
hcnt <= hcnt + 1'd1;
end
// save position of rising edge
if(!hs && hs_in) hs_rise <= {hcnt,1'b1};
vs <= vs_in;
if(vs && ~vs_in) sd_line <= 0;
end
if(ce_x4) begin
hs2 <= hs_in;
// output counter synchronous to input and at twice the rate
sd_hcnt <= sd_hcnt + 1'd1;
sd_h <= sd_h + 1'd1;
if(hs2 && !hs_in) sd_hcnt <= hs_max;
if(sd_hcnt == hs_max) sd_hcnt <= 0;
// replicate horizontal sync at twice the speed
if(sd_hcnt == hs_max) hs_out <= 0;
if(sd_hcnt == hs_rise) hs_out <= 1;
if(sd_hcnt == hs_ls) sd_h <= 0;
if(sd_hcnt == hs_ls) sd_line <= sd_line + 1'd1;
end
end
endmodule

View File

@@ -1,243 +0,0 @@
//
//
// Copyright (c) 2017 Sorgelig
//
// This program is GPL Licensed. See COPYING for the full license.
//
//
////////////////////////////////////////////////////////////////////////////////////////////////////////
`timescale 1ns / 1ps
//
// LINE_LENGTH: Length of display line in pixels
// Usually it's length from HSync to HSync.
// May be less if line_start is used.
//
// HALF_DEPTH: If =1 then color dept is 3 bits per component
// For half depth 6 bits monochrome is available with
// mono signal enabled and color = {G, R}
module video_mixer
#(
parameter LINE_LENGTH = 480,
parameter HALF_DEPTH = 1,
parameter OSD_COLOR = 3'd4,
parameter OSD_X_OFFSET = 10'd0,
parameter OSD_Y_OFFSET = 10'd0
)
(
// master clock
// it should be multiple by (ce_pix*4).
input clk_sys,
// Pixel clock or clock_enable (both are accepted).
input ce_pix,
// Some systems have multiple resolutions.
// ce_pix_actual should match ce_pix where every second or fourth pulse is enabled,
// thus half or qurter resolutions can be used without brake video sync while switching resolutions.
// For fixed single resolution (or when video sync stability isn't required) ce_pix_actual = ce_pix.
input ce_pix_actual,
// OSD SPI interface
input SPI_SCK,
input SPI_SS3,
input SPI_DI,
// scanlines (00-none 01-25% 10-50% 11-75%)
input [1:0] scanlines,
// 0 = HVSync 31KHz, 1 = CSync 15KHz
input scandoublerD,
// High quality 2x scaling
input hq2x,
// YPbPr always uses composite sync
input ypbpr,
// 0 = 16-240 range. 1 = 0-255 range. (only for YPbPr color space)
input ypbpr_full,
input [1:0] rotate, //[0] - rotate [1] - left or right
// color
input [DWIDTH:0] R,
input [DWIDTH:0] G,
input [DWIDTH:0] B,
// Monochrome mode (for HALF_DEPTH only)
input mono,
// interlace sync. Positive pulses.
input HSync,
input VSync,
// Falling of this signal means start of informative part of line.
// It can be horizontal blank signal.
// This signal can be used to reduce amount of required FPGA RAM for HQ2x scan doubler
// If FPGA RAM is not an issue, then simply set it to 0 for whole line processing.
// Keep in mind: due to algo first and last pixels of line should be black to avoid side artefacts.
// Thus, if blank signal is used to reduce the line, make sure to feed at least one black (or paper) pixel
// before first informative pixel.
input line_start,
// MiST video output signals
output [5:0] VGA_R,
output [5:0] VGA_G,
output [5:0] VGA_B,
output VGA_VS,
output VGA_HS
);
localparam DWIDTH = HALF_DEPTH ? 2 : 5;
wire [DWIDTH:0] R_sd;
wire [DWIDTH:0] G_sd;
wire [DWIDTH:0] B_sd;
wire hs_sd, vs_sd;
scandoubler #(.LENGTH(LINE_LENGTH), .HALF_DEPTH(HALF_DEPTH)) scandoubler
(
.*,
.hs_in(HSync),
.vs_in(VSync),
.r_in(R),
.g_in(G),
.b_in(B),
.hs_out(hs_sd),
.vs_out(vs_sd),
.r_out(R_sd),
.g_out(G_sd),
.b_out(B_sd)
);
wire [DWIDTH:0] rt = (scandoublerD ? R : R_sd);
wire [DWIDTH:0] gt = (scandoublerD ? G : G_sd);
wire [DWIDTH:0] bt = (scandoublerD ? B : B_sd);
generate
if(HALF_DEPTH) begin
wire [5:0] r = mono ? {gt,rt} : {rt,rt};
wire [5:0] g = mono ? {gt,rt} : {gt,gt};
wire [5:0] b = mono ? {gt,rt} : {bt,bt};
end else begin
wire [5:0] r = rt;
wire [5:0] g = gt;
wire [5:0] b = bt;
end
endgenerate
wire hs = (scandoublerD ? HSync : hs_sd);
wire vs = (scandoublerD ? VSync : vs_sd);
reg scanline = 0;
always @(posedge clk_sys) begin
reg old_hs, old_vs;
old_hs <= hs;
old_vs <= vs;
if(old_hs && ~hs) scanline <= ~scanline;
if(old_vs && ~vs) scanline <= 0;
end
wire [5:0] r_out, g_out, b_out;
always @(*) begin
case(scanlines & {scanline, scanline})
1: begin // reduce 25% = 1/2 + 1/4
r_out = {1'b0, r[5:1]} + {2'b00, r[5:2]};
g_out = {1'b0, g[5:1]} + {2'b00, g[5:2]};
b_out = {1'b0, b[5:1]} + {2'b00, b[5:2]};
end
2: begin // reduce 50% = 1/2
r_out = {1'b0, r[5:1]};
g_out = {1'b0, g[5:1]};
b_out = {1'b0, b[5:1]};
end
3: begin // reduce 75% = 1/4
r_out = {2'b00, r[5:2]};
g_out = {2'b00, g[5:2]};
b_out = {2'b00, b[5:2]};
end
default: begin
r_out = r;
g_out = g;
b_out = b;
end
endcase
end
wire [5:0] red, green, blue;
osd #(OSD_X_OFFSET, OSD_Y_OFFSET, OSD_COLOR) osd
(
.*,
.R_in(r_out),
.G_in(g_out),
.B_in(b_out),
.HSync(hs),
.VSync(vs),
.rotate(rotate),
.R_out(red),
.G_out(green),
.B_out(blue)
);
wire [5:0] yuv_full[225] = '{
6'd0, 6'd0, 6'd0, 6'd0, 6'd1, 6'd1, 6'd1, 6'd1,
6'd2, 6'd2, 6'd2, 6'd3, 6'd3, 6'd3, 6'd3, 6'd4,
6'd4, 6'd4, 6'd5, 6'd5, 6'd5, 6'd5, 6'd6, 6'd6,
6'd6, 6'd7, 6'd7, 6'd7, 6'd7, 6'd8, 6'd8, 6'd8,
6'd9, 6'd9, 6'd9, 6'd9, 6'd10, 6'd10, 6'd10, 6'd11,
6'd11, 6'd11, 6'd11, 6'd12, 6'd12, 6'd12, 6'd13, 6'd13,
6'd13, 6'd13, 6'd14, 6'd14, 6'd14, 6'd15, 6'd15, 6'd15,
6'd15, 6'd16, 6'd16, 6'd16, 6'd17, 6'd17, 6'd17, 6'd17,
6'd18, 6'd18, 6'd18, 6'd19, 6'd19, 6'd19, 6'd19, 6'd20,
6'd20, 6'd20, 6'd21, 6'd21, 6'd21, 6'd21, 6'd22, 6'd22,
6'd22, 6'd23, 6'd23, 6'd23, 6'd23, 6'd24, 6'd24, 6'd24,
6'd25, 6'd25, 6'd25, 6'd25, 6'd26, 6'd26, 6'd26, 6'd27,
6'd27, 6'd27, 6'd27, 6'd28, 6'd28, 6'd28, 6'd29, 6'd29,
6'd29, 6'd29, 6'd30, 6'd30, 6'd30, 6'd31, 6'd31, 6'd31,
6'd31, 6'd32, 6'd32, 6'd32, 6'd33, 6'd33, 6'd33, 6'd33,
6'd34, 6'd34, 6'd34, 6'd35, 6'd35, 6'd35, 6'd35, 6'd36,
6'd36, 6'd36, 6'd36, 6'd37, 6'd37, 6'd37, 6'd38, 6'd38,
6'd38, 6'd38, 6'd39, 6'd39, 6'd39, 6'd40, 6'd40, 6'd40,
6'd40, 6'd41, 6'd41, 6'd41, 6'd42, 6'd42, 6'd42, 6'd42,
6'd43, 6'd43, 6'd43, 6'd44, 6'd44, 6'd44, 6'd44, 6'd45,
6'd45, 6'd45, 6'd46, 6'd46, 6'd46, 6'd46, 6'd47, 6'd47,
6'd47, 6'd48, 6'd48, 6'd48, 6'd48, 6'd49, 6'd49, 6'd49,
6'd50, 6'd50, 6'd50, 6'd50, 6'd51, 6'd51, 6'd51, 6'd52,
6'd52, 6'd52, 6'd52, 6'd53, 6'd53, 6'd53, 6'd54, 6'd54,
6'd54, 6'd54, 6'd55, 6'd55, 6'd55, 6'd56, 6'd56, 6'd56,
6'd56, 6'd57, 6'd57, 6'd57, 6'd58, 6'd58, 6'd58, 6'd58,
6'd59, 6'd59, 6'd59, 6'd60, 6'd60, 6'd60, 6'd60, 6'd61,
6'd61, 6'd61, 6'd62, 6'd62, 6'd62, 6'd62, 6'd63, 6'd63,
6'd63
};
// http://marsee101.blog19.fc2.com/blog-entry-2311.html
// Y = 16 + 0.257*R + 0.504*G + 0.098*B (Y = 0.299*R + 0.587*G + 0.114*B)
// Pb = 128 - 0.148*R - 0.291*G + 0.439*B (Pb = -0.169*R - 0.331*G + 0.500*B)
// Pr = 128 + 0.439*R - 0.368*G - 0.071*B (Pr = 0.500*R - 0.419*G - 0.081*B)
wire [18:0] y_8 = 19'd04096 + ({red, 8'd0} + {red, 3'd0}) + ({green, 9'd0} + {green, 2'd0}) + ({blue, 6'd0} + {blue, 5'd0} + {blue, 2'd0});
wire [18:0] pb_8 = 19'd32768 - ({red, 7'd0} + {red, 4'd0} + {red, 3'd0}) - ({green, 8'd0} + {green, 5'd0} + {green, 3'd0}) + ({blue, 8'd0} + {blue, 7'd0} + {blue, 6'd0});
wire [18:0] pr_8 = 19'd32768 + ({red, 8'd0} + {red, 7'd0} + {red, 6'd0}) - ({green, 8'd0} + {green, 6'd0} + {green, 5'd0} + {green, 4'd0} + {green, 3'd0}) - ({blue, 6'd0} + {blue , 3'd0});
wire [7:0] y = ( y_8[17:8] < 16) ? 8'd16 : ( y_8[17:8] > 235) ? 8'd235 : y_8[15:8];
wire [7:0] pb = (pb_8[17:8] < 16) ? 8'd16 : (pb_8[17:8] > 240) ? 8'd240 : pb_8[15:8];
wire [7:0] pr = (pr_8[17:8] < 16) ? 8'd16 : (pr_8[17:8] > 240) ? 8'd240 : pr_8[15:8];
assign VGA_R = ypbpr ? (ypbpr_full ? yuv_full[pr-8'd16] : pr[7:2]) : red;
assign VGA_G = ypbpr ? (ypbpr_full ? yuv_full[y -8'd16] : y[7:2]) : green;
assign VGA_B = ypbpr ? (ypbpr_full ? yuv_full[pb-8'd16] : pb[7:2]) : blue;
assign VGA_VS = (scandoublerD | ypbpr) ? 1'b1 : ~vs_sd;
assign VGA_HS = scandoublerD ? ~(HSync ^ VSync) : ypbpr ? ~(hs_sd ^ vs_sd) : ~hs_sd;
endmodule