mirror of
https://github.com/MiSTer-devel/SMS_MiSTer.git
synced 2026-04-19 03:05:00 +00:00
Update sys.
This commit is contained in:
24
SMS.sv
24
SMS.sv
@@ -55,8 +55,9 @@ module emu
|
||||
|
||||
input [11:0] HDMI_WIDTH,
|
||||
input [11:0] HDMI_HEIGHT,
|
||||
output HDMI_FREEZE,
|
||||
|
||||
`ifdef USE_FB
|
||||
`ifdef MISTER_FB
|
||||
// Use framebuffer in DDRAM (USE_FB=1 in qsf)
|
||||
// FB_FORMAT:
|
||||
// [2:0] : 011=8bpp(palette) 100=16bpp 101=24bpp 110=32bpp
|
||||
@@ -74,6 +75,7 @@ module emu
|
||||
input FB_LL,
|
||||
output FB_FORCE_BLANK,
|
||||
|
||||
`ifdef MISTER_FB_PALETTE
|
||||
// Palette control for 8bit modes.
|
||||
// Ignored for other video modes.
|
||||
output FB_PAL_CLK,
|
||||
@@ -81,6 +83,7 @@ module emu
|
||||
output [23:0] FB_PAL_DOUT,
|
||||
input [23:0] FB_PAL_DIN,
|
||||
output FB_PAL_WR,
|
||||
`endif
|
||||
`endif
|
||||
|
||||
output LED_USER, // 1 - ON, 0 - OFF.
|
||||
@@ -112,7 +115,6 @@ module emu
|
||||
output SD_CS,
|
||||
input SD_CD,
|
||||
|
||||
`ifdef USE_DDRAM
|
||||
//High latency DDR3 RAM interface
|
||||
//Use for non-critical time purposes
|
||||
output DDRAM_CLK,
|
||||
@@ -125,9 +127,7 @@ module emu
|
||||
output [63:0] DDRAM_DIN,
|
||||
output [7:0] DDRAM_BE,
|
||||
output DDRAM_WE,
|
||||
`endif
|
||||
|
||||
`ifdef USE_SDRAM
|
||||
//SDRAM interface with lower latency
|
||||
output SDRAM_CLK,
|
||||
output SDRAM_CKE,
|
||||
@@ -140,10 +140,10 @@ module emu
|
||||
output SDRAM_nCAS,
|
||||
output SDRAM_nRAS,
|
||||
output SDRAM_nWE,
|
||||
`endif
|
||||
|
||||
`ifdef DUAL_SDRAM
|
||||
`ifdef MISTER_DUAL_SDRAM
|
||||
//Secondary SDRAM
|
||||
//Set all output SDRAM_* signals to Z ASAP if SDRAM2_EN is 0
|
||||
input SDRAM2_EN,
|
||||
output SDRAM2_CLK,
|
||||
output [12:0] SDRAM2_A,
|
||||
@@ -173,6 +173,7 @@ module emu
|
||||
input OSD_STATUS
|
||||
);
|
||||
|
||||
|
||||
assign ADC_BUS = 'Z;
|
||||
assign VGA_F1 = 0;
|
||||
|
||||
@@ -186,6 +187,7 @@ assign LED_DISK = 0;
|
||||
assign LED_POWER = 0;
|
||||
assign BUTTONS = 0;
|
||||
assign VGA_SCALER= 0;
|
||||
assign HDMI_FREEZE = 0;
|
||||
|
||||
reg en216p;
|
||||
always @(posedge CLK_VIDEO) en216p <= ((HDMI_WIDTH == 1920) && (HDMI_HEIGHT == 1080) && !forced_scandoubler && !scale);
|
||||
@@ -321,13 +323,11 @@ wire [21:0] gamma_bus;
|
||||
|
||||
wire [24:0] ps2_mouse;
|
||||
|
||||
hps_io #(.STRLEN($size(CONF_STR)>>3), .WIDE(0)) hps_io
|
||||
hps_io #(.CONF_STR(CONF_STR), .WIDE(0)) hps_io
|
||||
(
|
||||
.clk_sys(clk_sys),
|
||||
.HPS_BUS(HPS_BUS),
|
||||
|
||||
.conf_str(CONF_STR),
|
||||
|
||||
.joystick_0(joy_0),
|
||||
.joystick_1(joy_1),
|
||||
.joystick_2(joy_2),
|
||||
@@ -354,16 +354,15 @@ hps_io #(.STRLEN($size(CONF_STR)>>3), .WIDE(0)) hps_io
|
||||
.ioctl_download(ioctl_download),
|
||||
.ioctl_index(ioctl_index),
|
||||
|
||||
.sd_conf(0),
|
||||
.ioctl_wait(ioctl_wait),
|
||||
|
||||
.sd_lba(sd_lba),
|
||||
.sd_lba('{sd_lba}),
|
||||
.sd_rd(sd_rd),
|
||||
.sd_wr(sd_wr),
|
||||
.sd_ack(sd_ack),
|
||||
.sd_buff_addr(sd_buff_addr),
|
||||
.sd_buff_dout(sd_buff_dout),
|
||||
.sd_buff_din(sd_buff_din),
|
||||
.sd_buff_din('{sd_buff_din}),
|
||||
.sd_buff_wr(sd_buff_wr),
|
||||
.img_mounted(img_mounted),
|
||||
.img_readonly(img_readonly),
|
||||
@@ -858,6 +857,7 @@ video_mixer #(.HALF_DEPTH(1), .LINE_LENGTH(300), .GAMMA(1)) video_mixer
|
||||
.*,
|
||||
.scandoubler(scale || forced_scandoubler),
|
||||
.hq2x(scale==1),
|
||||
.freeze_sync(),
|
||||
|
||||
.VGA_DE(vga_de),
|
||||
.R((gun_en & gun_target) ? 8'd255 : {2{color[3:0]}}),
|
||||
|
||||
@@ -382,8 +382,9 @@ ARCHITECTURE rtl OF ascal IS
|
||||
SIGNAL avl_o_vs_sync,avl_o_vs : std_logic;
|
||||
SIGNAL avl_fb_ena : std_logic;
|
||||
|
||||
FUNCTION buf_next(a,b : natural RANGE 0 TO 2) RETURN natural IS
|
||||
FUNCTION buf_next(a,b : natural RANGE 0 TO 2; freeze : std_logic := '0') RETURN natural IS
|
||||
BEGIN
|
||||
IF (freeze='1') THEN RETURN a; END IF;
|
||||
IF (a=0 AND b=1) OR (a=1 AND b=0) THEN RETURN 2; END IF;
|
||||
IF (a=1 AND b=2) OR (a=2 AND b=1) THEN RETURN 0; END IF;
|
||||
RETURN 1;
|
||||
@@ -400,6 +401,7 @@ ARCHITECTURE rtl OF ascal IS
|
||||
----------------------------------------------------------
|
||||
-- Output
|
||||
SIGNAL o_run : std_logic;
|
||||
SIGNAL o_freeze : std_logic;
|
||||
SIGNAL o_mode,o_hmode,o_vmode : unsigned(4 DOWNTO 0);
|
||||
SIGNAL o_format : unsigned(5 DOWNTO 0);
|
||||
SIGNAL o_fb_pal_dr : unsigned(23 DOWNTO 0);
|
||||
@@ -1730,28 +1732,61 @@ BEGIN
|
||||
-- Triple buffering.
|
||||
-- For intelaced video, half frames are updated independently
|
||||
-- Input : Toggle buffer at end of input frame
|
||||
o_freeze <= freeze;
|
||||
o_inter <=i_inter; -- <ASYNC>
|
||||
o_iendframe0<=i_endframe0; -- <ASYNC>
|
||||
o_iendframe02<=o_iendframe0;
|
||||
IF o_iendframe0='1' AND o_iendframe02='0' THEN
|
||||
o_ibuf0<=buf_next(o_ibuf0,o_obuf0);
|
||||
o_ibuf0<=buf_next(o_ibuf0,o_obuf0,o_freeze);
|
||||
o_bufup0<='1';
|
||||
END IF;
|
||||
o_iendframe1<=i_endframe1; -- <ASYNC>
|
||||
o_iendframe12<=o_iendframe1;
|
||||
IF o_iendframe1='1' AND o_iendframe12='0' THEN
|
||||
o_ibuf1<=buf_next(o_ibuf1,o_obuf1);
|
||||
o_ibuf1<=buf_next(o_ibuf1,o_obuf1,o_freeze);
|
||||
o_bufup1<='1';
|
||||
END IF;
|
||||
|
||||
-- Output : Change framebuffer, and image properties, at VS falling edge
|
||||
IF o_vsv(1)='1' AND o_vsv(0)='0' AND o_bufup0='1' THEN
|
||||
o_obuf0<=buf_next(o_obuf0,o_ibuf0,o_freeze);
|
||||
o_bufup0<='0';
|
||||
END IF;
|
||||
IF o_vsv(1)='1' AND o_vsv(0)='0' AND o_bufup1='1' THEN
|
||||
o_obuf1<=buf_next(o_obuf1,o_ibuf1);
|
||||
o_obuf1<=buf_next(o_obuf1,o_ibuf1,o_freeze);
|
||||
o_bufup1<='0';
|
||||
o_ihsize<=i_hrsize; -- <ASYNC>
|
||||
o_ivsize<=i_vrsize; -- <ASYNC>
|
||||
o_hdown<=i_hdown; -- <ASYNC>
|
||||
o_vdown<=i_vdown; -- <ASYNC>
|
||||
END IF;
|
||||
|
||||
-- Simultaneous change of input and output framebuffers
|
||||
IF o_vsv(1)='1' AND o_vsv(0)='0' AND
|
||||
o_iendframe0='1' AND o_iendframe02='0' THEN
|
||||
o_bufup0<='0';
|
||||
o_obuf0<=o_ibuf0;
|
||||
END IF;
|
||||
IF o_vsv(1)='1' AND o_vsv(0)='0' AND
|
||||
o_iendframe1='1' AND o_iendframe12='0' THEN
|
||||
o_bufup1<='0';
|
||||
o_obuf1<=o_ibuf1;
|
||||
END IF;
|
||||
|
||||
-- Non-interlaced, use same buffer for even and odd lines
|
||||
IF o_inter='0' THEN
|
||||
o_ibuf1<=o_ibuf0;
|
||||
o_obuf1<=o_obuf0;
|
||||
END IF;
|
||||
|
||||
-- Triple buffer disabled
|
||||
IF o_mode(3)='0' THEN
|
||||
o_obuf0<=0;
|
||||
o_obuf1<=0;
|
||||
o_ibuf0<=0;
|
||||
o_ibuf1<=0;
|
||||
END IF;
|
||||
|
||||
-- Framebuffer mode.
|
||||
IF o_fb_ena='1' THEN
|
||||
o_ihsize<=o_fb_hsize;
|
||||
@@ -1771,25 +1806,6 @@ BEGIN
|
||||
o_stride<=to_unsigned(o_ihsize_temp2,14);
|
||||
o_stride(NB_BURST-1 DOWNTO 0)<=(OTHERS =>'0');
|
||||
END IF;
|
||||
|
||||
IF o_vsv(1)='1' AND o_vsv(0)='0' AND o_bufup0='1' THEN
|
||||
o_obuf0<=buf_next(o_obuf0,o_ibuf0);
|
||||
o_bufup0<='0';
|
||||
END IF;
|
||||
|
||||
IF o_inter='0' THEN
|
||||
o_ibuf1<=o_ibuf0;
|
||||
o_obuf1<=o_obuf0;
|
||||
END IF;
|
||||
|
||||
-- Triple buffer disabled
|
||||
IF o_mode(3)='0' THEN
|
||||
o_obuf0<=0;
|
||||
o_obuf1<=0;
|
||||
o_ibuf0<=0;
|
||||
o_ibuf1<=0;
|
||||
END IF;
|
||||
|
||||
------------------------------------------------------
|
||||
o_hmode<=o_mode;
|
||||
IF o_hdown='1' AND DOWNSCALE THEN
|
||||
|
||||
@@ -32,8 +32,10 @@ always @(posedge clk_vid) begin
|
||||
reg [7:0] R_gamma, G_gamma;
|
||||
reg hs,vs,hb,vb;
|
||||
reg [1:0] ctr = 0;
|
||||
reg old_ce;
|
||||
|
||||
if(ce_pix) begin
|
||||
old_ce <= ce_pix;
|
||||
if(~old_ce & ce_pix) begin
|
||||
{R_in,G_in,B_in} <= RGB_in;
|
||||
hs <= HSync; vs <= VSync;
|
||||
hb <= HBlank; vb <= VBlank;
|
||||
|
||||
@@ -24,15 +24,14 @@
|
||||
// Use buffer to access SD card. It's time-critical part.
|
||||
//
|
||||
// WIDE=1 for 16 bit file I/O
|
||||
// VDNUM 1-4
|
||||
module hps_io #(parameter STRLEN=0, PS2DIV=0, WIDE=0, VDNUM=1, PS2WE=0)
|
||||
// VDNUM 1..4
|
||||
// BLKSZ 0..7: 0 = 128, 1 = 256, 2 = 512(default), .. 7 = 16384
|
||||
//
|
||||
module hps_io #(parameter CONF_STR, CONF_STR_BRAM=1, PS2DIV=0, WIDE=0, VDNUM=1, BLKSZ=2, PS2WE=0)
|
||||
(
|
||||
input clk_sys,
|
||||
inout [45:0] HPS_BUS,
|
||||
|
||||
// parameter STRLEN and the actual length of conf_str have to match
|
||||
input [(8*STRLEN)-1:0] conf_str,
|
||||
|
||||
// buttons up to 32
|
||||
output reg [31:0] joystick_0,
|
||||
output reg [31:0] joystick_1,
|
||||
@@ -86,22 +85,17 @@ module hps_io #(parameter STRLEN=0, PS2DIV=0, WIDE=0, VDNUM=1, PS2WE=0)
|
||||
output reg [63:0] img_size, // size of image in bytes. valid only for active bit in img_mounted
|
||||
|
||||
// SD block level access
|
||||
input [31:0] sd_lba,
|
||||
input [VD:0] sd_rd, // only single sd_rd can be active at any given time
|
||||
input [VD:0] sd_wr, // only single sd_wr can be active at any given time
|
||||
output reg sd_ack,
|
||||
|
||||
// do not use in new projects.
|
||||
// CID and CSD are fake except CSD image size field.
|
||||
input sd_conf,
|
||||
output reg sd_ack_conf,
|
||||
input [31:0] sd_lba[VDNUM],
|
||||
input [5:0] sd_blk_cnt[VDNUM], // number of blocks-1, total size ((sd_blk_cnt+1)*(1<<(BLKSZ+7))) must be <= 16384!
|
||||
input [VD:0] sd_rd,
|
||||
input [VD:0] sd_wr,
|
||||
output reg [VD:0] sd_ack,
|
||||
|
||||
// SD byte level access. Signals for 2-PORT altsyncram.
|
||||
output reg [AW:0] sd_buff_addr,
|
||||
output reg [DW:0] sd_buff_dout,
|
||||
input [DW:0] sd_buff_din,
|
||||
input [DW:0] sd_buff_din[VDNUM],
|
||||
output reg sd_buff_wr,
|
||||
input [15:0] sd_req_type,
|
||||
|
||||
// ARM -> FPGA download
|
||||
output reg ioctl_download = 0, // signal indicating an active download
|
||||
@@ -110,6 +104,7 @@ module hps_io #(parameter STRLEN=0, PS2DIV=0, WIDE=0, VDNUM=1, PS2WE=0)
|
||||
output reg [26:0] ioctl_addr, // in WIDE mode address will be incremented by 2
|
||||
output reg [DW:0] ioctl_dout,
|
||||
output reg ioctl_upload = 0, // signal indicating an active upload
|
||||
input ioctl_upload_req,
|
||||
input [DW:0] ioctl_din,
|
||||
output reg ioctl_rd,
|
||||
output reg [31:0] ioctl_file_ext,
|
||||
@@ -161,10 +156,8 @@ module hps_io #(parameter STRLEN=0, PS2DIV=0, WIDE=0, VDNUM=1, PS2WE=0)
|
||||
assign EXT_BUS[31:16] = HPS_BUS[31:16];
|
||||
assign EXT_BUS[35:33] = HPS_BUS[35:33];
|
||||
|
||||
localparam MAX_W = $clog2((512 > (STRLEN+1)) ? 512 : (STRLEN+1))-1;
|
||||
|
||||
localparam DW = (WIDE) ? 15 : 7;
|
||||
localparam AW = (WIDE) ? 7 : 8;
|
||||
localparam AW = (WIDE) ? 12 : 13;
|
||||
localparam VD = VDNUM-1;
|
||||
|
||||
wire io_strobe= HPS_BUS[33];
|
||||
@@ -187,22 +180,18 @@ assign forced_scandoubler = cfg[4];
|
||||
//cfg[5] - ypbpr handled in sys_top
|
||||
assign direct_video = cfg[10];
|
||||
|
||||
// command byte read by the io controller
|
||||
wire [15:0] sd_cmd =
|
||||
{
|
||||
2'b00,
|
||||
(VDNUM>=4) ? sd_wr[3] : 1'b0,
|
||||
(VDNUM>=3) ? sd_wr[2] : 1'b0,
|
||||
(VDNUM>=2) ? sd_wr[1] : 1'b0,
|
||||
reg [3:0] sdn;
|
||||
reg [3:0] sd_rrb = 0;
|
||||
always_comb begin
|
||||
int n, i;
|
||||
|
||||
(VDNUM>=4) ? sd_rd[3] : 1'b0,
|
||||
(VDNUM>=3) ? sd_rd[2] : 1'b0,
|
||||
(VDNUM>=2) ? sd_rd[1] : 1'b0,
|
||||
|
||||
4'h5, sd_conf, 1'b1,
|
||||
sd_wr[0],
|
||||
sd_rd[0]
|
||||
};
|
||||
sdn = 0;
|
||||
for(i = VDNUM - 1; i >= 0; i = i - 1) begin
|
||||
n = i + sd_rrb;
|
||||
if(n >= VDNUM) n = n - VDNUM;
|
||||
if(sd_wr[n] | sd_rd[n]) sdn = n[3:0];
|
||||
end
|
||||
end
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
@@ -226,6 +215,19 @@ video_calc video_calc
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
localparam STRLEN = $size(CONF_STR)>>3;
|
||||
localparam MAX_W = $clog2((32 > (STRLEN+2)) ? 32 : (STRLEN+2))-1;
|
||||
|
||||
wire [7:0] conf_byte;
|
||||
generate
|
||||
if(CONF_STR_BRAM) begin
|
||||
confstr_rom #(CONF_STR, STRLEN) confstr_rom(.*, .conf_addr(byte_cnt - 1'd1));
|
||||
end
|
||||
else begin
|
||||
assign conf_byte = CONF_STR[{(STRLEN - byte_cnt),3'b000} +:8];
|
||||
end
|
||||
endgenerate
|
||||
|
||||
assign gamma_bus[20:0] = {clk_sys, gamma_en, gamma_wr, gamma_wr_addr, gamma_value};
|
||||
reg gamma_en;
|
||||
reg gamma_wr;
|
||||
@@ -237,6 +239,8 @@ 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));
|
||||
|
||||
reg [MAX_W:0] byte_cnt;
|
||||
reg [3:0] sdn_ack;
|
||||
wire [15:0] disk = 16'd1 << io_din[11:8];
|
||||
|
||||
always@(posedge clk_sys) begin : uio_block
|
||||
reg [15:0] cmd;
|
||||
@@ -247,16 +251,22 @@ always@(posedge clk_sys) begin : uio_block
|
||||
reg [3:0] stflg = 0;
|
||||
reg [63:0] status_req;
|
||||
reg old_status_set = 0;
|
||||
reg old_upload_req = 0;
|
||||
reg upload_req = 0;
|
||||
reg old_info = 0;
|
||||
reg [7:0] info_n = 0;
|
||||
reg [15:0] tmp1;
|
||||
reg [7:0] tmp2;
|
||||
reg [3:0] sdn_r;
|
||||
|
||||
old_status_set <= status_set;
|
||||
if(~old_status_set & status_set) begin
|
||||
stflg <= stflg + 1'd1;
|
||||
status_req <= status_in;
|
||||
end
|
||||
|
||||
old_upload_req <= ioctl_upload_req;
|
||||
if(~old_upload_req & ioctl_upload_req) upload_req <= 1;
|
||||
|
||||
old_info <= info_req;
|
||||
if(~old_info & info_req) info_n <= info;
|
||||
@@ -282,7 +292,6 @@ always@(posedge clk_sys) begin : uio_block
|
||||
cmd <= 0;
|
||||
byte_cnt <= 0;
|
||||
sd_ack <= 0;
|
||||
sd_ack_conf <= 0;
|
||||
io_dout <= 0;
|
||||
ps2skip <= 0;
|
||||
img_mounted <= 0;
|
||||
@@ -295,23 +304,24 @@ always@(posedge clk_sys) begin : uio_block
|
||||
if(byte_cnt == 0) begin
|
||||
cmd <= io_din;
|
||||
|
||||
case(io_din)
|
||||
'h19: sd_ack_conf <= 1;
|
||||
'h17,
|
||||
'h18: sd_ack <= 1;
|
||||
'h29: io_dout <= {4'hA, stflg};
|
||||
'h2B: io_dout <= 1;
|
||||
'h2F: io_dout <= 1;
|
||||
'h32: io_dout <= gamma_bus[21];
|
||||
'h36: begin io_dout <= info_n; info_n <= 0; end
|
||||
'h39: io_dout <= 1;
|
||||
casex(io_din)
|
||||
'h16: begin io_dout <= {1'b1, sd_blk_cnt[sdn], BLKSZ[2:0], sdn, sd_wr[sdn], sd_rd[sdn]}; sdn_r <= sdn; end
|
||||
'h0X17,
|
||||
'h0X18: begin sd_ack <= disk[VD:0]; sdn_ack <= io_din[11:8]; end
|
||||
'h29: io_dout <= {4'hA, stflg};
|
||||
'h2B: io_dout <= 1;
|
||||
'h2F: io_dout <= 1;
|
||||
'h32: io_dout <= gamma_bus[21];
|
||||
'h36: begin io_dout <= info_n; info_n <= 0; end
|
||||
'h39: io_dout <= 1;
|
||||
'h3C: if(upload_req) begin io_dout <= 1; upload_req <= 0; end
|
||||
endcase
|
||||
|
||||
sd_buff_addr <= 0;
|
||||
if(io_din == 5) ps2_key_raw <= 0;
|
||||
end else begin
|
||||
|
||||
case(cmd)
|
||||
casex(cmd)
|
||||
// buttons and switches
|
||||
'h01: cfg <= io_din;
|
||||
'h02: if(byte_cnt==1) joystick_0[15:0] <= io_din; else joystick_0[31:16] <= io_din;
|
||||
@@ -353,34 +363,28 @@ always@(posedge clk_sys) begin : uio_block
|
||||
end
|
||||
|
||||
// reading config string, returning a byte from string
|
||||
'h14: if(byte_cnt < STRLEN + 1) io_dout[7:0] <= conf_str[(STRLEN - byte_cnt)<<3 +:8];
|
||||
'h14: if(byte_cnt <= STRLEN) io_dout[7:0] <= conf_byte;
|
||||
|
||||
// reading sd card status
|
||||
'h16: if(!byte_cnt[MAX_W:3]) begin
|
||||
case(byte_cnt[2:0])
|
||||
1: io_dout <= sd_cmd;
|
||||
2: io_dout <= sd_lba[15:0];
|
||||
3: io_dout <= sd_lba[31:16];
|
||||
4: io_dout <= sd_req_type;
|
||||
'h16: if(!byte_cnt[MAX_W:2]) begin
|
||||
case(byte_cnt[1:0])
|
||||
1: sd_rrb <= (sd_rrb == VD) ? 4'd0 : (sd_rrb + 1'd1);
|
||||
2: io_dout <= sd_lba[sdn_r][15:0];
|
||||
3: io_dout <= sd_lba[sdn_r][31:16];
|
||||
endcase
|
||||
end
|
||||
|
||||
// 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)
|
||||
'h19,
|
||||
// send sector IO -> FPGA
|
||||
// flag that download begins
|
||||
'h17: begin
|
||||
'h0X17: begin
|
||||
sd_buff_dout <= io_din[DW:0];
|
||||
b_wr <= 1;
|
||||
end
|
||||
|
||||
// reading sd card write data
|
||||
'h18: begin
|
||||
'h0X18: begin
|
||||
if(~&sd_buff_addr) sd_buff_addr <= sd_buff_addr + 1'b1;
|
||||
io_dout <= sd_buff_din;
|
||||
io_dout <= sd_buff_din[sdn_ack];
|
||||
end
|
||||
|
||||
// joystick analog
|
||||
@@ -936,3 +940,16 @@ always @(posedge clk_100) begin
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module confstr_rom #(parameter CONF_STR, STRLEN)
|
||||
(
|
||||
input clk_sys,
|
||||
input [$clog2(STRLEN+1)-1:0] conf_addr,
|
||||
output reg [7:0] conf_byte
|
||||
);
|
||||
|
||||
wire [7:0] rom[STRLEN];
|
||||
initial for(int i = 0; i < STRLEN; i++) rom[i] = CONF_STR[((STRLEN-i)*8)-1 -:8];
|
||||
always @ (posedge clk_sys) conf_byte <= rom[conf_addr];
|
||||
|
||||
endmodule
|
||||
@@ -72,7 +72,7 @@ always@(posedge clk_sys) begin
|
||||
// command 0x40: OSDCMDENABLE, OSDCMDDISABLE
|
||||
if(io_din[7:4] == 4) begin
|
||||
if(!io_din[0]) {osd_status,highres} <= 0;
|
||||
else {osd_status,info} <= {~io_din[2],io_din[2]};
|
||||
else {osd_status,info} <= {~io_din[2] & ~io_din[3],io_din[2]};
|
||||
bcnt <= 0;
|
||||
end
|
||||
// command 0x20: OSDCMDWRITE
|
||||
|
||||
798
sys/sd_card.sv
798
sys/sd_card.sv
@@ -23,52 +23,55 @@
|
||||
|
||||
//
|
||||
// Made module syncrhronous. Total code refactoring. (Sorgelig)
|
||||
// clk_spi must be at least 4 x sck for proper work.
|
||||
// clk_spi must be at least 2 x sck for proper work.
|
||||
|
||||
module sd_card #(parameter WIDE = 0)
|
||||
module sd_card #(parameter WIDE = 0, OCTAL=0)
|
||||
(
|
||||
input clk_sys,
|
||||
input reset,
|
||||
input clk_sys,
|
||||
input reset,
|
||||
|
||||
input sdhc,
|
||||
|
||||
output [31:0] sd_lba,
|
||||
output reg sd_rd,
|
||||
output reg sd_wr,
|
||||
input sd_ack,
|
||||
input sd_ack_conf,
|
||||
input sdhc,
|
||||
input img_mounted,
|
||||
input [63:0] img_size,
|
||||
|
||||
input [AW:0] sd_buff_addr,
|
||||
input [DW:0] sd_buff_dout,
|
||||
output [DW:0] sd_buff_din,
|
||||
input sd_buff_wr,
|
||||
output reg [31:0] sd_lba,
|
||||
output reg sd_rd,
|
||||
output reg sd_wr,
|
||||
input sd_ack,
|
||||
|
||||
input [AW:0] sd_buff_addr,
|
||||
input [DW:0] sd_buff_dout,
|
||||
output [DW:0] sd_buff_din,
|
||||
input sd_buff_wr,
|
||||
|
||||
// SPI interface
|
||||
input clk_spi,
|
||||
input clk_spi,
|
||||
|
||||
input ss,
|
||||
input sck,
|
||||
input mosi,
|
||||
output reg miso
|
||||
input ss,
|
||||
input sck,
|
||||
input [SW:0] mosi,
|
||||
output reg [SW:0] miso
|
||||
);
|
||||
|
||||
localparam AW = WIDE ? 7 : 8;
|
||||
localparam DW = WIDE ? 15 : 7;
|
||||
localparam AW = WIDE ? 7 : 8;
|
||||
localparam DW = WIDE ? 15 : 7;
|
||||
localparam SZ = OCTAL ? 8 : 1;
|
||||
localparam SW = SZ-1;
|
||||
|
||||
assign sd_lba = sdhc ? lba : {9'd0, lba[31:9]};
|
||||
|
||||
wire[31:0] OCR = { 1'b1, sdhc, 30'd0 }; // bit30 = 1 -> high capaciry card (sdhc) // bit31 = 0 -> card power up finished
|
||||
wire [7:0] READ_DATA_TOKEN = 8'hfe;
|
||||
wire [7:0] DATA_TOKEN_CMD25 = 8'hfc;
|
||||
wire [7:0] STOP_TRAN = 8'hfd;
|
||||
wire [7:0] DATA_TOKEN = 8'hfe;
|
||||
wire [7:0] WRITE_DATA_RESPONSE = 8'h05;
|
||||
|
||||
// number of bytes to wait after a command before sending the reply
|
||||
localparam NCR=3;
|
||||
localparam NCR = 5+3; // 5 bytes are required (command length)
|
||||
|
||||
localparam RD_STATE_IDLE = 0;
|
||||
localparam RD_STATE_WAIT_IO = 1;
|
||||
localparam RD_STATE_SEND_TOKEN = 2;
|
||||
localparam RD_STATE_SEND_DATA = 3;
|
||||
localparam RD_STATE_WAIT_M = 4;
|
||||
localparam RD_STATE_START = 1;
|
||||
localparam RD_STATE_WAIT_IO = 2;
|
||||
localparam RD_STATE_SEND_TOKEN = 3;
|
||||
localparam RD_STATE_SEND_DATA = 4;
|
||||
localparam RD_STATE_WAIT_M = 5;
|
||||
|
||||
localparam WR_STATE_IDLE = 0;
|
||||
localparam WR_STATE_EXP_DTOKEN = 1;
|
||||
@@ -78,460 +81,383 @@ localparam WR_STATE_RECV_CRC1 = 4;
|
||||
localparam WR_STATE_SEND_DRESP = 5;
|
||||
localparam WR_STATE_BUSY = 6;
|
||||
|
||||
sdbuf #(WIDE) buffer
|
||||
localparam PREF_STATE_IDLE = 0;
|
||||
localparam PREF_STATE_RD = 1;
|
||||
localparam PREF_STATE_FINISH = 2;
|
||||
|
||||
altsyncram sdbuf
|
||||
(
|
||||
.clock_a(clk_sys),
|
||||
.address_a(sd_buff_addr),
|
||||
.data_a(sd_buff_dout),
|
||||
.wren_a(sd_ack & sd_buff_wr),
|
||||
.q_a(sd_buff_din),
|
||||
.clock0 (clk_sys),
|
||||
.address_a ({sd_buf,sd_buff_addr}),
|
||||
.data_a (sd_buff_dout),
|
||||
.wren_a (sd_ack & sd_buff_wr),
|
||||
.q_a (sd_buff_din),
|
||||
|
||||
.clock_b(clk_spi),
|
||||
.address_b(buffer_ptr),
|
||||
.data_b(buffer_din),
|
||||
.wren_b(buffer_wr),
|
||||
.q_b(buffer_dout)
|
||||
.clock1 (clk_spi),
|
||||
.address_b ({spi_buf,buffer_ptr}),
|
||||
.data_b (buffer_din),
|
||||
.wren_b (buffer_wr),
|
||||
.q_b (buffer_dout),
|
||||
|
||||
.aclr0(1'b0),
|
||||
.aclr1(1'b0),
|
||||
.addressstall_a(1'b0),
|
||||
.addressstall_b(1'b0),
|
||||
.byteena_a(1'b1),
|
||||
.byteena_b(1'b1),
|
||||
.clocken0(1'b1),
|
||||
.clocken1(1'b1),
|
||||
.clocken2(1'b1),
|
||||
.clocken3(1'b1),
|
||||
.eccstatus(),
|
||||
.rden_a(1'b1),
|
||||
.rden_b(1'b1)
|
||||
);
|
||||
defparam
|
||||
sdbuf.numwords_a = 1<<(AW+3),
|
||||
sdbuf.widthad_a = AW+3,
|
||||
sdbuf.width_a = DW+1,
|
||||
sdbuf.numwords_b = 2048,
|
||||
sdbuf.widthad_b = 11,
|
||||
sdbuf.width_b = 8,
|
||||
sdbuf.address_reg_b = "CLOCK1",
|
||||
sdbuf.clock_enable_input_a = "BYPASS",
|
||||
sdbuf.clock_enable_input_b = "BYPASS",
|
||||
sdbuf.clock_enable_output_a = "BYPASS",
|
||||
sdbuf.clock_enable_output_b = "BYPASS",
|
||||
sdbuf.indata_reg_b = "CLOCK1",
|
||||
sdbuf.intended_device_family = "Cyclone V",
|
||||
sdbuf.lpm_type = "altsyncram",
|
||||
sdbuf.operation_mode = "BIDIR_DUAL_PORT",
|
||||
sdbuf.outdata_aclr_a = "NONE",
|
||||
sdbuf.outdata_aclr_b = "NONE",
|
||||
sdbuf.outdata_reg_a = "UNREGISTERED",
|
||||
sdbuf.outdata_reg_b = "UNREGISTERED",
|
||||
sdbuf.power_up_uninitialized = "FALSE",
|
||||
sdbuf.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ",
|
||||
sdbuf.read_during_write_mode_port_b = "NEW_DATA_NO_NBE_READ",
|
||||
sdbuf.width_byteena_a = 1,
|
||||
sdbuf.width_byteena_b = 1,
|
||||
sdbuf.wrcontrol_wraddress_reg_b = "CLOCK1";
|
||||
|
||||
sdbuf #(WIDE) conf
|
||||
(
|
||||
.clock_a(clk_sys),
|
||||
.address_a(sd_buff_addr),
|
||||
.data_a(sd_buff_dout),
|
||||
.wren_a(sd_ack_conf & sd_buff_wr),
|
||||
reg [26:0] csd_size;
|
||||
reg csd_sdhc;
|
||||
always @(posedge clk_sys) begin
|
||||
if (img_mounted) begin
|
||||
csd_sdhc <= sdhc;
|
||||
if (sdhc) begin
|
||||
csd_size[0] <= 0;
|
||||
csd_size[22:1] <= img_size[40:19]; // in 512K units
|
||||
csd_size[26:23] <= 0;
|
||||
end
|
||||
else begin
|
||||
csd_size[2:0] <= 7; // C_SIZE_MULT
|
||||
csd_size[14:3] <= 12'b101101101101;
|
||||
csd_size[26:15] <= img_size[29:18]; // in 256K units ((2**(C_SIZE_MULT+2))*512)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
.clock_b(clk_spi),
|
||||
.address_b(buffer_ptr),
|
||||
.q_b(config_dout)
|
||||
);
|
||||
wire [127:0] CSD = {1'b0,csd_sdhc,6'h00,8'h0e,8'h00,8'h32,8'h5b,8'h59,6'h00,csd_size,7'h7f,8'h80,8'h0a,8'h40,8'h40,8'hf1};
|
||||
wire [127:0] CID = {8'hcd,8'hc7,8'h00,8'h93,8'h6f,8'h2f,8'h73,8'h00,8'h00,8'h44,8'h32,8'h38,8'h34,8'h00,8'h00,8'h3e};
|
||||
|
||||
reg [31:0] lba, new_lba;
|
||||
reg [8:0] buffer_ptr;
|
||||
reg [7:0] buffer_din;
|
||||
wire [7:0] buffer_dout;
|
||||
wire [7:0] config_dout;
|
||||
reg buffer_wr;
|
||||
|
||||
always @(posedge clk_spi) begin
|
||||
reg [2:0] read_state;
|
||||
reg [2:0] write_state;
|
||||
reg [6:0] sbuf;
|
||||
reg cmd55;
|
||||
reg [7:0] cmd;
|
||||
reg [2:0] bit_cnt;
|
||||
reg [3:0] byte_cnt;
|
||||
reg [7:0] reply;
|
||||
reg [7:0] reply0, reply1, reply2, reply3;
|
||||
reg [3:0] reply_len;
|
||||
reg tx_finish;
|
||||
reg rx_finish;
|
||||
reg old_sck;
|
||||
reg synced;
|
||||
reg [5:0] ack;
|
||||
reg io_ack;
|
||||
reg [4:0] idle_cnt = 0;
|
||||
reg [2:0] wait_m_cnt;
|
||||
reg [1:0] sd_buf, spi_buf;
|
||||
|
||||
reg [6:0] sbuf;
|
||||
reg [2:0] bit_cnt;
|
||||
|
||||
wire last_bit = &bit_cnt || OCTAL;
|
||||
wire [7:0] ibuf = OCTAL ? mosi : {sbuf,mosi[0]};
|
||||
|
||||
always @(posedge clk_spi) begin
|
||||
reg [2:0] read_state;
|
||||
reg [2:0] write_state;
|
||||
reg [1:0] pref_state;
|
||||
reg [5:0] cmd;
|
||||
reg cmd55;
|
||||
reg [39:0] reply;
|
||||
reg [3:0] byte_cnt;
|
||||
reg old_sck;
|
||||
reg [2:0] ack;
|
||||
reg [2:0] wait_m_cnt;
|
||||
reg [31:0] arg;
|
||||
|
||||
ack[1:0] <= {ack[0],sd_ack};
|
||||
if(ack[1] == ack[0]) ack[2] <= ack[1];
|
||||
|
||||
if(~ack[2] & ack[1]) {sd_rd,sd_wr} <= 0;
|
||||
if( ack[2] & ~ack[1]) begin
|
||||
sd_buf <= sd_buf + 1'd1;
|
||||
sd_lba <= sd_lba + 1;
|
||||
end
|
||||
|
||||
if(buffer_wr & ~&buffer_ptr) buffer_ptr <= buffer_ptr + 1'd1;
|
||||
buffer_wr <= 0;
|
||||
|
||||
ack <= {ack[4:0], sd_ack};
|
||||
if(ack[5:4] == 2'b10) io_ack <= 1;
|
||||
if(ack[5:4] == 2'b01) {sd_rd,sd_wr} <= 0;
|
||||
|
||||
old_sck <= sck;
|
||||
|
||||
if(~ss) idle_cnt <= 31;
|
||||
else if(~old_sck && sck && idle_cnt) idle_cnt <= idle_cnt - 1'd1;
|
||||
|
||||
if(reset || !idle_cnt) begin
|
||||
if(reset) begin
|
||||
bit_cnt <= 0;
|
||||
byte_cnt <= 15;
|
||||
synced <= 0;
|
||||
miso <= 1;
|
||||
sbuf <= 7'b1111111;
|
||||
tx_finish <= 0;
|
||||
rx_finish <= 0;
|
||||
byte_cnt <= '1;
|
||||
miso <= '1;
|
||||
cmd <= 0;
|
||||
sd_wr <= 0;
|
||||
sd_rd <= 0;
|
||||
read_state <= RD_STATE_IDLE;
|
||||
write_state <= WR_STATE_IDLE;
|
||||
pref_state <= PREF_STATE_IDLE;
|
||||
end
|
||||
else begin
|
||||
|
||||
if(old_sck & ~sck & ~ss) begin
|
||||
tx_finish <= 0;
|
||||
miso <= 1; // default: send 1's (busy/wait)
|
||||
|
||||
if(byte_cnt == 5+NCR) begin
|
||||
miso <= reply[~bit_cnt];
|
||||
|
||||
if(bit_cnt == 7) begin
|
||||
// these three commands all have a reply_len of 0 and will thus
|
||||
// not send more than a single reply byte
|
||||
|
||||
// CMD9: SEND_CSD
|
||||
// CMD10: SEND_CID
|
||||
if((cmd == 'h49) | (cmd == 'h4a))
|
||||
read_state <= RD_STATE_SEND_TOKEN; // jump directly to data transmission
|
||||
|
||||
// CMD17/CMD18
|
||||
if((cmd == 'h51) | (cmd == 'h52)) begin
|
||||
io_ack <= 0;
|
||||
read_state <= RD_STATE_WAIT_IO; // start waiting for data from io controller
|
||||
lba <= new_lba;
|
||||
sd_rd <= 1; // trigger request to io controller
|
||||
end
|
||||
if(buffer_wr) begin
|
||||
if(~&buffer_ptr) buffer_ptr <= buffer_ptr + 1'd1;
|
||||
else begin
|
||||
spi_buf <= spi_buf + 1'd1;
|
||||
sd_wr <= 1;
|
||||
end
|
||||
end
|
||||
else if((reply_len > 0) && (byte_cnt == 5+NCR+1)) miso <= reply0[~bit_cnt];
|
||||
else if((reply_len > 1) && (byte_cnt == 5+NCR+2)) miso <= reply1[~bit_cnt];
|
||||
else if((reply_len > 2) && (byte_cnt == 5+NCR+3)) miso <= reply2[~bit_cnt];
|
||||
else if((reply_len > 3) && (byte_cnt == 5+NCR+4)) miso <= reply3[~bit_cnt];
|
||||
else begin
|
||||
if(byte_cnt > 5+NCR && read_state==RD_STATE_IDLE && write_state==WR_STATE_IDLE) tx_finish <= 1;
|
||||
end
|
||||
|
||||
// ---------- read state machine processing -------------
|
||||
|
||||
case(read_state)
|
||||
RD_STATE_IDLE: ; // do nothing
|
||||
|
||||
|
||||
// waiting for io controller to return data
|
||||
RD_STATE_WAIT_IO: begin
|
||||
if(io_ack & (bit_cnt == 7)) read_state <= RD_STATE_SEND_TOKEN;
|
||||
end
|
||||
|
||||
// send data token
|
||||
RD_STATE_SEND_TOKEN: begin
|
||||
miso <= READ_DATA_TOKEN[~bit_cnt];
|
||||
|
||||
if(bit_cnt == 7) begin
|
||||
read_state <= RD_STATE_SEND_DATA; // next: send data
|
||||
buffer_ptr <= 0;
|
||||
if(cmd == 'h49) buffer_ptr <= 16;
|
||||
case(pref_state)
|
||||
PREF_STATE_IDLE:
|
||||
if(((sd_buf - spi_buf) <= 1) && (read_state != RD_STATE_IDLE) && (cmd == 17 || cmd == 18)) begin
|
||||
sd_rd <= 1;
|
||||
pref_state <= PREF_STATE_RD;
|
||||
end
|
||||
end
|
||||
|
||||
// send data
|
||||
RD_STATE_SEND_DATA: begin
|
||||
|
||||
miso <= ((cmd == 'h49) | (cmd == 'h4A)) ? config_dout[~bit_cnt] : buffer_dout[~bit_cnt];
|
||||
|
||||
if(bit_cnt == 7) begin
|
||||
|
||||
// sent 512 sector data bytes?
|
||||
if((cmd == 'h51) & &buffer_ptr) read_state <= RD_STATE_IDLE;
|
||||
else if((cmd == 'h52) & &buffer_ptr) begin
|
||||
read_state <= RD_STATE_WAIT_M;
|
||||
wait_m_cnt <= 0;
|
||||
end
|
||||
|
||||
// sent 16 cid/csd data bytes?
|
||||
else if(((cmd == 'h49) | (cmd == 'h4a)) & (&buffer_ptr[3:0])) read_state <= RD_STATE_IDLE;
|
||||
|
||||
// not done yet -> trigger read of next data byte
|
||||
else buffer_ptr <= buffer_ptr + 1'd1;
|
||||
PREF_STATE_RD:
|
||||
if(read_state == RD_STATE_IDLE) begin
|
||||
pref_state <= PREF_STATE_IDLE;
|
||||
end
|
||||
end
|
||||
|
||||
RD_STATE_WAIT_M: begin
|
||||
if(bit_cnt == 7) begin
|
||||
wait_m_cnt <= wait_m_cnt + 1'd1;
|
||||
if(&wait_m_cnt) begin
|
||||
lba <= lba + 1;
|
||||
io_ack <= 0;
|
||||
sd_rd <= 1;
|
||||
read_state <= RD_STATE_WAIT_IO;
|
||||
end
|
||||
else if(ack[2] & ~ack[1]) begin
|
||||
pref_state <= (cmd == 18) ? PREF_STATE_IDLE : PREF_STATE_FINISH;
|
||||
end
|
||||
|
||||
PREF_STATE_FINISH:
|
||||
if(read_state == RD_STATE_IDLE) begin
|
||||
pref_state <= PREF_STATE_IDLE;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
|
||||
// ------------------ write support ----------------------
|
||||
// send write data response
|
||||
if(write_state == WR_STATE_SEND_DRESP) miso <= WRITE_DATA_RESPONSE[~bit_cnt];
|
||||
|
||||
// busy after write until the io controller sends ack
|
||||
if(write_state == WR_STATE_BUSY) miso <= 0;
|
||||
end
|
||||
|
||||
if(~old_sck & sck & ~ss) begin
|
||||
|
||||
if(synced) bit_cnt <= bit_cnt + 1'd1;
|
||||
|
||||
// assemble byte
|
||||
if(bit_cnt != 7) begin
|
||||
sbuf[6:0] <= { sbuf[5:0], mosi };
|
||||
|
||||
// resync while waiting for token
|
||||
if(write_state==WR_STATE_EXP_DTOKEN) begin
|
||||
if(cmd == 'h58) begin
|
||||
if({sbuf,mosi} == 8'hfe) begin
|
||||
write_state <= WR_STATE_RECV_DATA;
|
||||
buffer_ptr <= 0;
|
||||
bit_cnt <= 0;
|
||||
end
|
||||
end
|
||||
else begin
|
||||
if({sbuf,mosi} == 8'hfc) begin
|
||||
write_state <= WR_STATE_RECV_DATA;
|
||||
buffer_ptr <= 0;
|
||||
bit_cnt <= 0;
|
||||
end
|
||||
if({sbuf,mosi} == 8'hfd) begin
|
||||
write_state <= WR_STATE_IDLE;
|
||||
rx_finish <= 1;
|
||||
bit_cnt <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
old_sck <= sck;
|
||||
if(ss) begin
|
||||
bit_cnt <= 0;
|
||||
byte_cnt <= '1;
|
||||
miso <= '1;
|
||||
end
|
||||
else begin
|
||||
// finished reading one byte
|
||||
// byte counter runs against 15 byte boundary
|
||||
if(byte_cnt != 15) byte_cnt <= byte_cnt + 1'd1;
|
||||
else if(old_sck & ~sck) begin
|
||||
miso <= '1; // default: send 1's (busy/wait)
|
||||
if(byte_cnt >= NCR) {miso,reply} <= {reply, {SZ{1'b1}}};
|
||||
|
||||
// byte_cnt > 6 -> complete command received
|
||||
// first byte of valid command is 01xxxxxx
|
||||
// don't accept new commands once a write or read command has been accepted
|
||||
if((byte_cnt > 5) & (write_state == WR_STATE_IDLE) & (read_state == RD_STATE_IDLE) && !rx_finish) begin
|
||||
byte_cnt <= 0;
|
||||
cmd <= { sbuf, mosi};
|
||||
// ---------- read state machine processing -------------
|
||||
case(read_state)
|
||||
RD_STATE_IDLE: ;
|
||||
|
||||
// set cmd55 flag if previous command was 55
|
||||
cmd55 <= (cmd == 'h77);
|
||||
end
|
||||
RD_STATE_START: begin
|
||||
if(byte_cnt == NCR && last_bit) read_state <= (cmd == 9 || cmd == 10) ? RD_STATE_SEND_TOKEN : RD_STATE_WAIT_IO;
|
||||
end
|
||||
|
||||
if((byte_cnt > 5) & (read_state == RD_STATE_WAIT_M) && ({sbuf, mosi} == 8'h4c)) begin
|
||||
byte_cnt <= 0;
|
||||
rx_finish <= 0;
|
||||
cmd <= {sbuf, mosi};
|
||||
read_state <= RD_STATE_IDLE;
|
||||
end
|
||||
// waiting for io controller to return data
|
||||
RD_STATE_WAIT_IO: begin
|
||||
if(sd_buf != spi_buf && last_bit) read_state <= RD_STATE_SEND_TOKEN;
|
||||
end
|
||||
|
||||
// parse additional command bytes
|
||||
if(byte_cnt == 0) new_lba[31:24] <= { sbuf, mosi};
|
||||
if(byte_cnt == 1) new_lba[23:16] <= { sbuf, mosi};
|
||||
if(byte_cnt == 2) new_lba[15:8] <= { sbuf, mosi};
|
||||
if(byte_cnt == 3) new_lba[7:0] <= { sbuf, mosi};
|
||||
|
||||
// last byte (crc) received, evaluate
|
||||
if(byte_cnt == 4) begin
|
||||
|
||||
// default:
|
||||
reply <= 4; // illegal command
|
||||
reply_len <= 0; // no extra reply bytes
|
||||
rx_finish <= 1;
|
||||
|
||||
case(cmd)
|
||||
// CMD0: GO_IDLE_STATE
|
||||
'h40: reply <= 1; // ok, busy
|
||||
|
||||
// CMD1: SEND_OP_COND
|
||||
'h41: reply <= 0; // ok, not busy
|
||||
|
||||
// CMD8: SEND_IF_COND (V2 only)
|
||||
'h48: begin
|
||||
reply <= 1; // ok, busy
|
||||
|
||||
reply0 <= 'h00;
|
||||
reply1 <= 'h00;
|
||||
reply2 <= 'h01;
|
||||
reply3 <= 'hAA;
|
||||
reply_len <= 4;
|
||||
end
|
||||
|
||||
// CMD9: SEND_CSD
|
||||
'h49: reply <= 0; // ok
|
||||
|
||||
// CMD10: SEND_CID
|
||||
'h4a: reply <= 0; // ok
|
||||
|
||||
// CMD12: STOP_TRANSMISSION
|
||||
'h4c: reply <= 0; // ok
|
||||
|
||||
// CMD13: SEND_STATUS
|
||||
'h4d: begin
|
||||
reply <= 'h00; // ok
|
||||
reply0 <='h00;
|
||||
reply_len <= 1;
|
||||
end
|
||||
|
||||
// CMD16: SET_BLOCKLEN
|
||||
'h50: begin
|
||||
// we only support a block size of 512
|
||||
if(new_lba == 512) reply <= 0; // ok
|
||||
else reply <= 'h40; // parmeter error
|
||||
end
|
||||
|
||||
// CMD17: READ_SINGLE_BLOCK
|
||||
'h51: reply <= 0; // ok
|
||||
|
||||
// CMD18: READ_MULTIPLE
|
||||
'h52: reply <= 0; // ok
|
||||
// ACMD23: SET_WR_BLK_ERASE_COUNT
|
||||
'h57: reply <= 0; //ok
|
||||
|
||||
// CMD24: WRITE_BLOCK
|
||||
'h58,
|
||||
// CMD25: WRITE_MULTIPLE
|
||||
'h59: begin
|
||||
reply <= 0; // ok
|
||||
write_state <= WR_STATE_EXP_DTOKEN; // expect data token
|
||||
rx_finish <=0;
|
||||
lba <= new_lba;
|
||||
end
|
||||
|
||||
// ACMD41: APP_SEND_OP_COND
|
||||
'h69: if(cmd55) reply <= 0; // ok, not busy
|
||||
|
||||
// CMD55: APP_COND
|
||||
'h77: reply <= 1; // ok, busy
|
||||
|
||||
// CMD58: READ_OCR
|
||||
'h7a: begin
|
||||
reply <= 0; // ok
|
||||
|
||||
reply0 <= OCR[31:24]; // bit 30 = 1 -> high capacity card
|
||||
reply1 <= OCR[23:16];
|
||||
reply2 <= OCR[15:8];
|
||||
reply3 <= OCR[7:0];
|
||||
reply_len <= 4;
|
||||
end
|
||||
|
||||
// CMD59: CRC_ON_OFF
|
||||
'h7b: reply <= 0; // ok
|
||||
endcase
|
||||
end
|
||||
|
||||
// ---------- handle write -----------
|
||||
case(write_state)
|
||||
// do nothing in idle state
|
||||
WR_STATE_IDLE: ;
|
||||
|
||||
// waiting for data token
|
||||
WR_STATE_EXP_DTOKEN: begin
|
||||
buffer_ptr <= 0;
|
||||
if(cmd == 'h58) begin
|
||||
if({sbuf,mosi} == 8'hfe) write_state <= WR_STATE_RECV_DATA;
|
||||
end
|
||||
else begin
|
||||
if({sbuf,mosi} == 8'hfc) write_state <= WR_STATE_RECV_DATA;
|
||||
if({sbuf,mosi} == 8'hfd) begin
|
||||
write_state <= WR_STATE_IDLE;
|
||||
rx_finish <= 1;
|
||||
end
|
||||
// send data token
|
||||
RD_STATE_SEND_TOKEN: begin
|
||||
miso <= DATA_TOKEN[~bit_cnt -:SZ];
|
||||
if(last_bit) begin
|
||||
read_state <= RD_STATE_SEND_DATA; // next: send data
|
||||
buffer_ptr <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
// transfer 512 bytes
|
||||
WR_STATE_RECV_DATA: begin
|
||||
// push one byte into local buffer
|
||||
buffer_wr <= 1;
|
||||
buffer_din <= {sbuf, mosi};
|
||||
// send data
|
||||
RD_STATE_SEND_DATA: begin
|
||||
|
||||
// all bytes written?
|
||||
if(&buffer_ptr) write_state <= WR_STATE_RECV_CRC0;
|
||||
miso <= (cmd == 9) ? CSD[{buffer_ptr[3:0],~bit_cnt} -:SZ] : (cmd == 10) ? CID[{buffer_ptr[3:0],~bit_cnt} -:SZ] : buffer_dout[~bit_cnt -:SZ];
|
||||
|
||||
if(last_bit) begin
|
||||
|
||||
// sent 512 sector data bytes?
|
||||
if(cmd == 17 && &buffer_ptr) read_state <= RD_STATE_IDLE;
|
||||
else if(cmd == 18 && &buffer_ptr) begin
|
||||
read_state <= RD_STATE_WAIT_M;
|
||||
wait_m_cnt <= 0;
|
||||
end
|
||||
|
||||
// sent 16 cid/csd data bytes?
|
||||
else if((cmd == 9 || cmd == 10) && &buffer_ptr[3:0]) read_state <= RD_STATE_IDLE;
|
||||
|
||||
// not done yet -> trigger read of next data byte
|
||||
else buffer_ptr <= buffer_ptr + 1'd1;
|
||||
end
|
||||
end
|
||||
|
||||
// transfer 1st crc byte
|
||||
WR_STATE_RECV_CRC0:
|
||||
write_state <= WR_STATE_RECV_CRC1;
|
||||
RD_STATE_WAIT_M: begin
|
||||
if(last_bit) begin
|
||||
wait_m_cnt <= wait_m_cnt + 1'd1;
|
||||
if(&wait_m_cnt) begin
|
||||
spi_buf <= spi_buf + 1'd1;
|
||||
read_state <= RD_STATE_WAIT_IO;
|
||||
end
|
||||
end
|
||||
end
|
||||
endcase
|
||||
|
||||
// transfer 2nd crc byte
|
||||
WR_STATE_RECV_CRC1:
|
||||
write_state <= WR_STATE_SEND_DRESP;
|
||||
// ------------------ write support ----------------------
|
||||
// send write data response
|
||||
if(write_state == WR_STATE_SEND_DRESP) miso <= WRITE_DATA_RESPONSE[~bit_cnt -:SZ];
|
||||
|
||||
// send data response
|
||||
WR_STATE_SEND_DRESP: begin
|
||||
write_state <= WR_STATE_BUSY;
|
||||
io_ack <= 0;
|
||||
sd_wr <= 1;
|
||||
// busy after write until the io controller sends ack
|
||||
if(write_state == WR_STATE_BUSY) miso <= 0;
|
||||
end
|
||||
else if(~old_sck & sck) begin
|
||||
|
||||
sbuf[6:0] <= {sbuf[5:0],mosi[0]};
|
||||
bit_cnt <= bit_cnt + SZ[2:0];
|
||||
|
||||
if(last_bit) begin
|
||||
// finished reading one byte
|
||||
// byte counter runs against 15 byte boundary
|
||||
if(~&byte_cnt) byte_cnt <= byte_cnt + 1'd1;
|
||||
|
||||
// byte_cnt > 6 -> complete command received
|
||||
// first byte of valid command is 01xxxxxx
|
||||
// don't accept new commands once a write or read command has been accepted
|
||||
if(byte_cnt > 5 &&
|
||||
((write_state == WR_STATE_IDLE && read_state == RD_STATE_IDLE && ibuf[7:6] == 1) ||
|
||||
(read_state != RD_STATE_IDLE && ibuf == 8'h4c))) begin
|
||||
byte_cnt <= 0;
|
||||
cmd <= ibuf[5:0];
|
||||
cmd55 <= (cmd == 55); // set cmd55 flag if previous command was 55
|
||||
if(ibuf[5:0] == 12) read_state <= RD_STATE_IDLE;
|
||||
end
|
||||
|
||||
// wait for io controller to accept data
|
||||
WR_STATE_BUSY:
|
||||
if(io_ack) begin
|
||||
if(cmd == 'h59) begin
|
||||
write_state <= WR_STATE_EXP_DTOKEN;
|
||||
lba <= lba + 1;
|
||||
// parse additional command bytes
|
||||
if(byte_cnt == 0) arg[31:24] <= ibuf;
|
||||
if(byte_cnt == 1) arg[23:16] <= ibuf;
|
||||
if(byte_cnt == 2) arg[15:8] <= ibuf;
|
||||
if(byte_cnt == 3) arg[7:0] <= ibuf;
|
||||
|
||||
// last byte (crc) received, evaluate
|
||||
if(byte_cnt == 4) begin
|
||||
|
||||
// default:
|
||||
reply <= 40'h04FFFFFFFF; // illegal command
|
||||
|
||||
case(cmd)
|
||||
// CMD0: GO_IDLE_STATE
|
||||
0: reply[39:32] <= 1; // ok, busy
|
||||
|
||||
// CMD1: SEND_OP_COND
|
||||
1: reply[39:32] <= 0;
|
||||
|
||||
// CMD8: SEND_IF_COND (V2 only)
|
||||
8: reply <= 40'h01000001AA; // ok, busy
|
||||
|
||||
// CMD9: SEND_CSD
|
||||
9,
|
||||
// CMD10: SEND_CID
|
||||
10: begin
|
||||
reply[39:32] <= 0;
|
||||
read_state <= RD_STATE_START;
|
||||
end
|
||||
|
||||
// CMD12: STOP_TRANSMISSION
|
||||
12: reply[39:32] <= 0;
|
||||
|
||||
// CMD13: SEND_STATUS
|
||||
13: reply[39:24] <= 16'h0000;
|
||||
|
||||
// CMD16: SET_BLOCKLEN
|
||||
16: reply[39:32] <= (arg == 512) ? 8'h00 : 8'h40; // we only support a block size of 512
|
||||
|
||||
// CMD17: READ_SINGLE_BLOCK
|
||||
17,
|
||||
// CMD18: READ_MULTIPLE
|
||||
18: begin
|
||||
reply[39:32] <= 0;
|
||||
read_state <= RD_STATE_START;
|
||||
spi_buf <= 0;
|
||||
sd_buf <= 0;
|
||||
sd_lba <= csd_sdhc ? arg : {9'd0, arg[31:9]};
|
||||
end
|
||||
|
||||
// ACMD23: SET_WR_BLK_ERASE_COUNT
|
||||
23: reply[39:32] <= 0;
|
||||
|
||||
// CMD24: WRITE_BLOCK
|
||||
24,
|
||||
// CMD25: WRITE_MULTIPLE
|
||||
25: begin
|
||||
reply[39:32] <= 0;
|
||||
write_state <= WR_STATE_EXP_DTOKEN; // expect data token
|
||||
spi_buf <= 0;
|
||||
sd_buf <= 0;
|
||||
sd_lba <= csd_sdhc ? arg : {9'd0, arg[31:9]};
|
||||
end
|
||||
|
||||
// ACMD41: APP_SEND_OP_COND
|
||||
41: if(cmd55) reply[39:32] <= 0; // ok, not busy
|
||||
|
||||
// CMD55: APP_COND
|
||||
55: reply[39:32] <= 1; // ok, busy
|
||||
|
||||
// CMD58: READ_OCR
|
||||
58: reply <= { 8'h00, 1'b1, csd_sdhc, 30'd0 }; // bit 30 = 1 -> high capacity card
|
||||
|
||||
// CMD59: CRC_ON_OFF
|
||||
59: reply[39:32] <= 0;
|
||||
endcase
|
||||
end
|
||||
|
||||
// ---------- handle write -----------
|
||||
case(write_state)
|
||||
// do nothing in idle state
|
||||
WR_STATE_IDLE: ;
|
||||
|
||||
// waiting for data token
|
||||
WR_STATE_EXP_DTOKEN: begin
|
||||
buffer_ptr <= 0;
|
||||
if(cmd == 24) begin
|
||||
if(ibuf == DATA_TOKEN) write_state <= WR_STATE_RECV_DATA;
|
||||
end
|
||||
else begin
|
||||
write_state <= WR_STATE_IDLE;
|
||||
rx_finish <= 1;
|
||||
if(ibuf == DATA_TOKEN_CMD25) write_state <= WR_STATE_RECV_DATA;
|
||||
if(ibuf == STOP_TRAN) write_state <= WR_STATE_IDLE;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
// wait for first 0 bit until start counting bits
|
||||
if(!synced && !mosi) begin
|
||||
synced <= 1;
|
||||
bit_cnt <= 1; // byte assembly prepare for next time loop
|
||||
sbuf <= 7'b1111110; // byte assembly prepare for next time loop
|
||||
rx_finish<= 0;
|
||||
end else if (synced && tx_finish && rx_finish ) begin
|
||||
synced <= 0;
|
||||
bit_cnt <= 0;
|
||||
rx_finish<= 0;
|
||||
|
||||
// transfer 512 bytes
|
||||
WR_STATE_RECV_DATA: begin
|
||||
// push one byte into local buffer
|
||||
buffer_wr <= 1;
|
||||
buffer_din <= ibuf;
|
||||
|
||||
// all bytes written?
|
||||
if(&buffer_ptr) write_state <= WR_STATE_RECV_CRC0;
|
||||
end
|
||||
|
||||
// transfer 1st crc byte
|
||||
WR_STATE_RECV_CRC0:
|
||||
write_state <= WR_STATE_RECV_CRC1;
|
||||
|
||||
// transfer 2nd crc byte
|
||||
WR_STATE_RECV_CRC1:
|
||||
write_state <= WR_STATE_SEND_DRESP;
|
||||
|
||||
// send data response
|
||||
WR_STATE_SEND_DRESP:
|
||||
write_state <= WR_STATE_BUSY;
|
||||
|
||||
// wait for io controller to accept data
|
||||
WR_STATE_BUSY:
|
||||
if(spi_buf == sd_buf) write_state <= (cmd == 25) ? WR_STATE_EXP_DTOKEN : WR_STATE_IDLE;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module sdbuf #(parameter WIDE)
|
||||
(
|
||||
input clock_a,
|
||||
input [AW:0] address_a,
|
||||
input [DW:0] data_a,
|
||||
input wren_a,
|
||||
output reg [DW:0] q_a,
|
||||
|
||||
input clock_b,
|
||||
input [8:0] address_b,
|
||||
input [7:0] data_b,
|
||||
input wren_b,
|
||||
output reg [7:0] q_b
|
||||
);
|
||||
|
||||
localparam AW = WIDE ? 7 : 8;
|
||||
localparam DW = WIDE ? 15 : 7;
|
||||
|
||||
always@(posedge clock_a) begin
|
||||
if(wren_a) begin
|
||||
ram[address_a] <= data_a;
|
||||
q_a <= data_a;
|
||||
end
|
||||
else begin
|
||||
q_a <= ram[address_a];
|
||||
end
|
||||
end
|
||||
|
||||
generate
|
||||
if(WIDE) begin
|
||||
reg [1:0][7:0] ram[1<<8];
|
||||
always@(posedge clock_b) begin
|
||||
if(wren_b) begin
|
||||
ram[address_b[8:1]][address_b[0]] <= data_b;
|
||||
q_b <= data_b;
|
||||
end
|
||||
else begin
|
||||
q_b <= ram[address_b[8:1]][address_b[0]];
|
||||
end
|
||||
end
|
||||
end
|
||||
else begin
|
||||
reg [7:0] ram[1<<9];
|
||||
always@(posedge clock_b) begin
|
||||
if(wren_b) begin
|
||||
ram[address_b] <= data_b;
|
||||
q_b <= data_b;
|
||||
end
|
||||
else begin
|
||||
q_b <= ram[address_b];
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -11,6 +11,7 @@ set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) v
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) gamma_corr.sv ]
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_mixer.sv ]
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_freak.sv ]
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_freezer.sv ]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) arcade_video.v ]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) osd.v ]
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) vga_out.sv ]
|
||||
@@ -29,4 +30,4 @@ set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) f
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ddr_svc.sv ]
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) sysmem.sv ]
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) sd_card.sv ]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) hps_io.v ]
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) hps_io.sv ]
|
||||
|
||||
@@ -67,3 +67,5 @@ set_false_path -from {ascal|o_hdisp* ascal|o_vdisp*}
|
||||
set_false_path -from {ascal|o_htotal* ascal|o_vtotal*}
|
||||
set_false_path -from {ascal|o_hsstart* ascal|o_vsstart* ascal|o_hsend* ascal|o_vsend*}
|
||||
set_false_path -from {ascal|o_hsize* ascal|o_vsize*}
|
||||
|
||||
set_false_path -from {mcp23009|sd_cd}
|
||||
|
||||
195
sys/sys_top.v
195
sys/sys_top.v
@@ -19,18 +19,6 @@
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
`ifndef ARCADE_SYS
|
||||
`define USE_DDRAM
|
||||
`define USE_SDRAM
|
||||
`endif
|
||||
|
||||
`ifndef USE_DDRAM
|
||||
`ifdef USE_FB
|
||||
`define USE_DDRAM
|
||||
`endif
|
||||
`endif
|
||||
|
||||
|
||||
module sys_top
|
||||
(
|
||||
/////////// CLOCK //////////
|
||||
@@ -68,7 +56,7 @@ module sys_top
|
||||
output SDRAM_CLK,
|
||||
output SDRAM_CKE,
|
||||
|
||||
`ifdef DUAL_SDRAM
|
||||
`ifdef MISTER_DUAL_SDRAM
|
||||
////////// SDR #2 //////////
|
||||
output [12:0] SDRAM2_A,
|
||||
inout [15:0] SDRAM2_DQ,
|
||||
@@ -139,20 +127,14 @@ module sys_top
|
||||
////////////////////// Secondary SD ///////////////////////////////////
|
||||
wire SD_CS, SD_CLK, SD_MOSI;
|
||||
|
||||
`ifdef ARCADE_SYS
|
||||
assign SD_CS = 1'bZ;
|
||||
assign SD_CLK = 1'bZ;
|
||||
assign SD_MOSI = 1'bZ;
|
||||
`ifndef MISTER_DUAL_SDRAM
|
||||
wire sd_miso = SW[3] | SDIO_DAT[0];
|
||||
`else
|
||||
`ifndef DUAL_SDRAM
|
||||
wire sd_miso = SW[3] | SDIO_DAT[0];
|
||||
`else
|
||||
wire sd_miso = 1;
|
||||
`endif
|
||||
wire SD_MISO = mcp_sdcd ? sd_miso : SD_SPI_MISO;
|
||||
wire sd_miso = 1;
|
||||
`endif
|
||||
wire SD_MISO = mcp_sdcd ? sd_miso : SD_SPI_MISO;
|
||||
|
||||
`ifndef DUAL_SDRAM
|
||||
`ifndef MISTER_DUAL_SDRAM
|
||||
assign SDIO_DAT[2:1]= 2'bZZ;
|
||||
assign SDIO_DAT[3] = SW[3] ? 1'bZ : SD_CS;
|
||||
assign SDIO_CLK = SW[3] ? 1'bZ : SD_CLK;
|
||||
@@ -175,7 +157,7 @@ wire led_d = led_disk[1] ? ~led_disk[0] : ~(led_disk[0] | gp_out[29]);
|
||||
wire led_u = ~led_user;
|
||||
wire led_locked;
|
||||
|
||||
`ifndef DUAL_SDRAM
|
||||
`ifndef MISTER_DUAL_SDRAM
|
||||
assign LED_POWER = (SW[3] | led_p) ? 1'bZ : 1'b0;
|
||||
assign LED_HDD = (SW[3] | led_d) ? 1'bZ : 1'b0;
|
||||
assign LED_USER = (SW[3] | led_u) ? 1'bZ : 1'b0;
|
||||
@@ -185,7 +167,7 @@ wire led_locked;
|
||||
assign LED = (led_overtake & led_state) | (~led_overtake & {1'b0,led_locked,1'b0, ~led_p, 1'b0, ~led_d, 1'b0, ~led_u});
|
||||
|
||||
wire btn_r, btn_o, btn_u;
|
||||
`ifdef DUAL_SDRAM
|
||||
`ifdef MISTER_DUAL_SDRAM
|
||||
assign {btn_r,btn_o,btn_u} = {mcp_btn[1],mcp_btn[2],mcp_btn[0]};
|
||||
`else
|
||||
assign {btn_r,btn_o,btn_u} = ~{BTN_RESET,BTN_OSD,BTN_USER} | {mcp_btn[1],mcp_btn[2],mcp_btn[0]};
|
||||
@@ -233,7 +215,7 @@ end
|
||||
wire [31:0] gp_in = {1'b0, btn_user | btn[1], btn_osd | btn[0], SW[3], 8'd0, io_ver, io_ack, io_wide, io_dout};
|
||||
wire [31:0] gp_out;
|
||||
|
||||
wire [1:0] io_ver = 1; // 0 - standard MiST I/O (for quick porting of complex MiST cores). 1 - optimized HPS I/O. 2,3 - reserved for future.
|
||||
wire [1:0] io_ver = 1; // 0 - obsolete. 1 - optimized HPS I/O. 2,3 - reserved for future.
|
||||
wire io_wait;
|
||||
wire io_wide;
|
||||
wire [15:0] io_dout;
|
||||
@@ -243,7 +225,7 @@ wire io_ss0 = gp_outr[18];
|
||||
wire io_ss1 = gp_outr[19];
|
||||
wire io_ss2 = gp_outr[20];
|
||||
|
||||
`ifndef DEBUG_NOHDMI
|
||||
`ifndef MISTER_DEBUG_NOHDMI
|
||||
wire io_osd_hdmi = io_ss1 & ~io_ss0;
|
||||
`endif
|
||||
|
||||
@@ -268,7 +250,7 @@ always @(posedge clk_sys) begin
|
||||
gp_outd <= gp_out;
|
||||
end
|
||||
|
||||
`ifdef DUAL_SDRAM
|
||||
`ifdef MISTER_DUAL_SDRAM
|
||||
wire [7:0] core_type = 'hA8; // generic core, dual SDRAM.
|
||||
`else
|
||||
wire [7:0] core_type = 'hA4; // generic core.
|
||||
@@ -290,7 +272,7 @@ reg cfg_set = 0;
|
||||
wire vga_fb = cfg[12] | vga_force_scaler;
|
||||
wire [1:0] hdmi_limited = {cfg[11],cfg[8]};
|
||||
|
||||
`ifdef DEBUG_NOHDMI
|
||||
`ifdef MISTER_DEBUG_NOHDMI
|
||||
wire direct_video = 1;
|
||||
`else
|
||||
wire direct_video = cfg[10];
|
||||
@@ -301,7 +283,7 @@ wire audio_96k = cfg[6];
|
||||
wire csync_en = cfg[3];
|
||||
wire ypbpr_en = cfg[5];
|
||||
wire io_osd_vga = io_ss1 & ~io_ss2;
|
||||
`ifndef DUAL_SDRAM
|
||||
`ifndef MISTER_DUAL_SDRAM
|
||||
wire sog = cfg[9];
|
||||
wire vga_scaler = cfg[2] | vga_force_scaler;
|
||||
`endif
|
||||
@@ -310,7 +292,8 @@ reg cfg_custom_t = 0;
|
||||
reg [5:0] cfg_custom_p1;
|
||||
reg [31:0] cfg_custom_p2;
|
||||
|
||||
reg [4:0] vol_att = 0;
|
||||
reg [4:0] vol_att;
|
||||
initial vol_att = 5'b11111;
|
||||
|
||||
reg [6:0] coef_addr;
|
||||
reg [8:0] coef_data;
|
||||
@@ -399,7 +382,7 @@ always@(posedge clk_sys) begin
|
||||
6: if(VS != io_din[11:0]) VS <= io_din[11:0];
|
||||
7: if(VBP != io_din[11:0]) VBP <= io_din[11:0];
|
||||
endcase
|
||||
`ifndef DEBUG_NOHDMI
|
||||
`ifndef MISTER_DEBUG_NOHDMI
|
||||
if(cnt == 1) begin
|
||||
cfg_custom_p1 <= 0;
|
||||
cfg_custom_p2 <= 0;
|
||||
@@ -481,9 +464,7 @@ end
|
||||
|
||||
cyclonev_hps_interface_peripheral_uart uart
|
||||
(
|
||||
.ri(0)
|
||||
`ifndef ARCADE_SYS
|
||||
,
|
||||
.ri(0),
|
||||
.dsr(uart_dsr),
|
||||
.dcd(uart_dsr),
|
||||
.dtr(uart_dtr),
|
||||
@@ -492,7 +473,6 @@ cyclonev_hps_interface_peripheral_uart uart
|
||||
.rts(uart_rts),
|
||||
.rxd(uart_rxd),
|
||||
.txd(uart_txd)
|
||||
`endif
|
||||
);
|
||||
|
||||
wire aspi_sck,aspi_mosi,aspi_ss,aspi_miso;
|
||||
@@ -547,7 +527,6 @@ sysmem_lite sysmem
|
||||
//DE10-nano has no reset signal on GPIO, so core has to emulate cold reset button.
|
||||
.reset_hps_cold_req(btn_r),
|
||||
|
||||
`ifdef USE_DDRAM
|
||||
//64-bit DDR3 RAM access
|
||||
.ram1_clk(ram_clk),
|
||||
.ram1_address(ram_address),
|
||||
@@ -559,7 +538,6 @@ sysmem_lite sysmem
|
||||
.ram1_writedata(ram_writedata),
|
||||
.ram1_byteenable(ram_byteenable),
|
||||
.ram1_write(ram_write),
|
||||
`endif
|
||||
|
||||
//64-bit DDR3 RAM access
|
||||
.ram2_clk(clk_audio),
|
||||
@@ -641,15 +619,20 @@ wire vbuf_write;
|
||||
|
||||
wire [23:0] hdmi_data;
|
||||
wire hdmi_vs, hdmi_hs, hdmi_de, hdmi_vbl;
|
||||
wire freeze;
|
||||
|
||||
`ifndef DEBUG_NOHDMI
|
||||
`ifndef MISTER_DEBUG_NOHDMI
|
||||
wire clk_hdmi = hdmi_clk_out;
|
||||
|
||||
ascal
|
||||
#(
|
||||
.RAMBASE(32'h20000000),
|
||||
`ifndef USE_FB
|
||||
`ifndef MISTER_FB
|
||||
.PALETTE2("false"),
|
||||
`else
|
||||
`ifndef MISTER_FB_PALETTE
|
||||
.PALETTE2("false"),
|
||||
`endif
|
||||
`endif
|
||||
.N_DW(128),
|
||||
.N_AW(28)
|
||||
@@ -658,7 +641,7 @@ ascal
|
||||
(
|
||||
.reset_na (~reset_req),
|
||||
.run (1),
|
||||
.freeze (0),
|
||||
.freeze (freeze),
|
||||
|
||||
.i_clk (clk_ihdmi),
|
||||
.i_ce (ce_hpix),
|
||||
@@ -709,13 +692,15 @@ ascal
|
||||
.pal1_a (pal_a),
|
||||
.pal1_wr (pal_wr),
|
||||
|
||||
`ifdef USE_FB
|
||||
.pal2_clk (fb_pal_clk),
|
||||
.pal2_dw (fb_pal_d),
|
||||
.pal2_dr (fb_pal_q),
|
||||
.pal2_a (fb_pal_a),
|
||||
.pal2_wr (fb_pal_wr),
|
||||
.pal_n (fb_en),
|
||||
`ifdef MISTER_FB
|
||||
`ifdef MISTER_FB_PALETTE
|
||||
.pal2_clk (fb_pal_clk),
|
||||
.pal2_dw (fb_pal_d),
|
||||
.pal2_dr (fb_pal_q),
|
||||
.pal2_a (fb_pal_a),
|
||||
.pal2_wr (fb_pal_wr),
|
||||
.pal_n (fb_en),
|
||||
`endif
|
||||
`endif
|
||||
|
||||
.o_fb_ena (FB_EN),
|
||||
@@ -775,7 +760,7 @@ always @(posedge clk_sys) begin
|
||||
end
|
||||
end
|
||||
|
||||
`ifdef USE_FB
|
||||
`ifdef MISTER_FB
|
||||
reg fb_vbl;
|
||||
always @(posedge clk_vid) fb_vbl <= hdmi_vbl;
|
||||
`endif
|
||||
@@ -899,7 +884,7 @@ always @(posedge clk_vid) begin
|
||||
vmax <= vmaxi;
|
||||
end
|
||||
|
||||
`ifndef DEBUG_NOHDMI
|
||||
`ifndef MISTER_DEBUG_NOHDMI
|
||||
wire [15:0] lltune;
|
||||
pll_hdmi_adj pll_hdmi_adj
|
||||
(
|
||||
@@ -942,7 +927,7 @@ end
|
||||
|
||||
|
||||
///////////////////////// HDMI output /////////////////////////////////
|
||||
`ifndef DEBUG_NOHDMI
|
||||
`ifndef MISTER_DEBUG_NOHDMI
|
||||
wire hdmi_clk_out;
|
||||
pll_hdmi pll_hdmi
|
||||
(
|
||||
@@ -974,7 +959,7 @@ reg adj_write;
|
||||
reg [5:0] adj_address;
|
||||
reg [31:0] adj_data;
|
||||
|
||||
`ifndef DEBUG_NOHDMI
|
||||
`ifndef MISTER_DEBUG_NOHDMI
|
||||
pll_cfg pll_cfg
|
||||
(
|
||||
.mgmt_clk(FPGA_CLK1_50),
|
||||
@@ -1063,11 +1048,11 @@ cyclonev_hps_interface_peripheral_i2c hdmi_i2c
|
||||
.sda(HDMI_I2C_SDA)
|
||||
);
|
||||
|
||||
`ifndef DEBUG_NOHDMI
|
||||
`ifndef MISTER_DEBUG_NOHDMI
|
||||
wire [23:0] hdmi_data_sl;
|
||||
wire hdmi_de_sl, hdmi_vs_sl, hdmi_hs_sl;
|
||||
|
||||
`ifdef USE_FB
|
||||
`ifdef MISTER_FB
|
||||
reg dis_output;
|
||||
always @(posedge clk_hdmi) begin
|
||||
reg dis;
|
||||
@@ -1115,10 +1100,6 @@ osd hdmi_osd
|
||||
.hs_out(hdmi_hs_osd),
|
||||
.vs_out(hdmi_vs_osd),
|
||||
.de_out(hdmi_de_osd)
|
||||
`ifndef ARCADE_SYS
|
||||
,
|
||||
.osd_status(osd_status)
|
||||
`endif
|
||||
);
|
||||
`endif
|
||||
|
||||
@@ -1167,7 +1148,7 @@ always @(posedge clk_vid) begin
|
||||
end
|
||||
|
||||
wire hdmi_tx_clk;
|
||||
`ifndef DEBUG_NOHDMI
|
||||
`ifndef MISTER_DEBUG_NOHDMI
|
||||
cyclonev_clkselect hdmi_clk_sw
|
||||
(
|
||||
.clkselect({1'b1, ~vga_fb & direct_video}),
|
||||
@@ -1257,6 +1238,7 @@ osd vga_osd
|
||||
.io_osd(io_osd_vga),
|
||||
.io_strobe(io_strobe),
|
||||
.io_din(io_din),
|
||||
.osd_status(osd_status),
|
||||
|
||||
.clk_video(clk_vid),
|
||||
.din(vga_data_sl),
|
||||
@@ -1272,7 +1254,7 @@ osd vga_osd
|
||||
wire vga_cs_osd;
|
||||
csync csync_vga(clk_vid, vga_hs_osd, vga_vs_osd, vga_cs_osd);
|
||||
|
||||
`ifndef DUAL_SDRAM
|
||||
`ifndef MISTER_DUAL_SDRAM
|
||||
wire [23:0] vgas_o;
|
||||
wire vgas_hs, vgas_vs, vgas_cs;
|
||||
vga_out vga_scaler_out
|
||||
@@ -1343,7 +1325,7 @@ end
|
||||
|
||||
assign SDCD_SPDIF =(SW[3] & ~spdif) ? 1'b0 : 1'bZ;
|
||||
|
||||
`ifndef DUAL_SDRAM
|
||||
`ifndef MISTER_DUAL_SDRAM
|
||||
wire analog_l, analog_r;
|
||||
|
||||
assign AUDIO_SPDIF = SW[3] ? 1'bZ : SW[0] ? HDMI_LRCLK : spdif;
|
||||
@@ -1390,7 +1372,7 @@ audio_out audio_out
|
||||
.i2s_bclk(HDMI_SCLK),
|
||||
.i2s_lrclk(HDMI_LRCLK),
|
||||
.i2s_data(HDMI_I2S),
|
||||
`ifndef DUAL_SDRAM
|
||||
`ifndef MISTER_DUAL_SDRAM
|
||||
.dac_l(analog_l),
|
||||
.dac_r(analog_r),
|
||||
`endif
|
||||
@@ -1457,18 +1439,16 @@ wire hvs_fix, hhs_fix, hde_emu;
|
||||
wire clk_vid, ce_pix, clk_ihdmi, ce_hpix;
|
||||
wire vga_force_scaler;
|
||||
|
||||
`ifdef USE_DDRAM
|
||||
wire ram_clk;
|
||||
wire [28:0] ram_address;
|
||||
wire [7:0] ram_burstcount;
|
||||
wire ram_waitrequest;
|
||||
wire [63:0] ram_readdata;
|
||||
wire ram_readdatavalid;
|
||||
wire ram_read;
|
||||
wire [63:0] ram_writedata;
|
||||
wire [7:0] ram_byteenable;
|
||||
wire ram_write;
|
||||
`endif
|
||||
wire ram_clk;
|
||||
wire [28:0] ram_address;
|
||||
wire [7:0] ram_burstcount;
|
||||
wire ram_waitrequest;
|
||||
wire [63:0] ram_readdata;
|
||||
wire ram_readdatavalid;
|
||||
wire ram_read;
|
||||
wire [63:0] ram_writedata;
|
||||
wire [7:0] ram_byteenable;
|
||||
wire ram_write;
|
||||
|
||||
wire led_user;
|
||||
wire [1:0] led_power;
|
||||
@@ -1480,10 +1460,6 @@ sync_fix sync_h(clk_vid, hs_emu, hs_fix);
|
||||
|
||||
wire [6:0] user_out, user_in;
|
||||
|
||||
`ifndef USE_SDRAM
|
||||
assign {SDRAM_DQ, SDRAM_A, SDRAM_BA, SDRAM_CLK, SDRAM_CKE, SDRAM_DQML, SDRAM_DQMH, SDRAM_nWE, SDRAM_nCAS, SDRAM_nRAS, SDRAM_nCS} = {39'bZ};
|
||||
`endif
|
||||
|
||||
assign clk_ihdmi= clk_vid;
|
||||
assign ce_hpix = ce_pix;
|
||||
assign hr_out = r_out;
|
||||
@@ -1493,19 +1469,14 @@ assign hhs_fix = hs_fix;
|
||||
assign hvs_fix = vs_fix;
|
||||
assign hde_emu = de_emu;
|
||||
|
||||
`ifdef ARCADE_SYS
|
||||
assign audio_mix = 0;
|
||||
assign {ADC_SCK, ADC_SDI, ADC_CONVST} = 0;
|
||||
assign btn = 0;
|
||||
`else
|
||||
wire uart_dtr;
|
||||
wire uart_dsr;
|
||||
wire uart_cts;
|
||||
wire uart_rts;
|
||||
wire uart_rxd;
|
||||
wire uart_txd;
|
||||
wire osd_status;
|
||||
`endif
|
||||
wire uart_dtr;
|
||||
wire uart_dsr;
|
||||
wire uart_cts;
|
||||
wire uart_rts;
|
||||
wire uart_rxd;
|
||||
wire uart_txd;
|
||||
|
||||
wire osd_status;
|
||||
|
||||
wire fb_en;
|
||||
wire [4:0] fb_fmt;
|
||||
@@ -1514,13 +1485,16 @@ wire [11:0] fb_height;
|
||||
wire [31:0] fb_base;
|
||||
wire [13:0] fb_stride;
|
||||
|
||||
`ifdef USE_FB
|
||||
wire fb_pal_clk;
|
||||
wire [7:0] fb_pal_a;
|
||||
wire [23:0] fb_pal_d;
|
||||
wire [23:0] fb_pal_q;
|
||||
wire fb_pal_wr;
|
||||
wire fb_force_blank;
|
||||
|
||||
`ifdef MISTER_FB
|
||||
`ifdef MISTER_FB_PALETTE
|
||||
wire fb_pal_clk;
|
||||
wire [7:0] fb_pal_a;
|
||||
wire [23:0] fb_pal_d;
|
||||
wire [23:0] fb_pal_q;
|
||||
wire fb_pal_wr;
|
||||
`endif
|
||||
wire fb_force_blank;
|
||||
`else
|
||||
assign fb_en = 0;
|
||||
assign fb_fmt = 0;
|
||||
@@ -1550,6 +1524,7 @@ emu emu
|
||||
|
||||
.HDMI_WIDTH(direct_video ? 12'd0 : hdmi_width),
|
||||
.HDMI_HEIGHT(direct_video ? 12'd0 : hdmi_height),
|
||||
.HDMI_FREEZE(freeze),
|
||||
|
||||
.CLK_VIDEO(clk_vid),
|
||||
.CE_PIXEL(ce_pix),
|
||||
@@ -1557,7 +1532,7 @@ emu emu
|
||||
.VIDEO_ARX(ARX),
|
||||
.VIDEO_ARY(ARY),
|
||||
|
||||
`ifdef USE_FB
|
||||
`ifdef MISTER_FB
|
||||
.FB_EN(fb_en),
|
||||
.FB_FORMAT(fb_fmt),
|
||||
.FB_WIDTH(fb_width),
|
||||
@@ -1568,11 +1543,14 @@ emu emu
|
||||
.FB_LL(lowlat),
|
||||
.FB_FORCE_BLANK(fb_force_blank),
|
||||
|
||||
`ifdef MISTER_FB_PALETTE
|
||||
.FB_PAL_CLK (fb_pal_clk),
|
||||
.FB_PAL_ADDR(fb_pal_a),
|
||||
.FB_PAL_DOUT(fb_pal_d),
|
||||
.FB_PAL_DIN (fb_pal_q),
|
||||
.FB_PAL_WR (fb_pal_wr),
|
||||
`endif
|
||||
|
||||
`endif
|
||||
|
||||
.LED_USER(led_user),
|
||||
@@ -1583,13 +1561,10 @@ emu emu
|
||||
.AUDIO_L(audio_l),
|
||||
.AUDIO_R(audio_r),
|
||||
.AUDIO_S(audio_s),
|
||||
|
||||
`ifndef ARCADE_SYS
|
||||
.AUDIO_MIX(audio_mix),
|
||||
.ADC_BUS({ADC_SCK,ADC_SDO,ADC_SDI,ADC_CONVST}),
|
||||
`endif
|
||||
|
||||
`ifdef USE_DDRAM
|
||||
.ADC_BUS({ADC_SCK,ADC_SDO,ADC_SDI,ADC_CONVST}),
|
||||
|
||||
.DDRAM_CLK(ram_clk),
|
||||
.DDRAM_ADDR(ram_address),
|
||||
.DDRAM_BURSTCNT(ram_burstcount),
|
||||
@@ -1600,9 +1575,7 @@ emu emu
|
||||
.DDRAM_DIN(ram_writedata),
|
||||
.DDRAM_BE(ram_byteenable),
|
||||
.DDRAM_WE(ram_write),
|
||||
`endif
|
||||
|
||||
`ifdef USE_SDRAM
|
||||
.SDRAM_DQ(SDRAM_DQ),
|
||||
.SDRAM_A(SDRAM_A),
|
||||
.SDRAM_DQML(SDRAM_DQML),
|
||||
@@ -1614,9 +1587,8 @@ emu emu
|
||||
.SDRAM_nCAS(SDRAM_nCAS),
|
||||
.SDRAM_CLK(SDRAM_CLK),
|
||||
.SDRAM_CKE(SDRAM_CKE),
|
||||
`endif
|
||||
|
||||
`ifdef DUAL_SDRAM
|
||||
`ifdef MISTER_DUAL_SDRAM
|
||||
.SDRAM2_DQ(SDRAM2_DQ),
|
||||
.SDRAM2_A(SDRAM2_A),
|
||||
.SDRAM2_BA(SDRAM2_BA),
|
||||
@@ -1628,14 +1600,14 @@ emu emu
|
||||
.SDRAM2_EN(SW[3]),
|
||||
`endif
|
||||
|
||||
`ifndef ARCADE_SYS
|
||||
.BUTTONS(btn),
|
||||
.OSD_STATUS(osd_status),
|
||||
|
||||
.SD_SCK(SD_CLK),
|
||||
.SD_MOSI(SD_MOSI),
|
||||
.SD_MISO(SD_MISO),
|
||||
.SD_CS(SD_CS),
|
||||
`ifdef DUAL_SDRAM
|
||||
`ifdef MISTER_DUAL_SDRAM
|
||||
.SD_CD(mcp_sdcd),
|
||||
`else
|
||||
.SD_CD(mcp_sdcd & (SW[0] ? VGA_HS : (SW[3] | SDCD_SPDIF))),
|
||||
@@ -1647,7 +1619,6 @@ emu emu
|
||||
.UART_TXD(uart_rxd),
|
||||
.UART_DTR(uart_dsr),
|
||||
.UART_DSR(uart_dtr),
|
||||
`endif
|
||||
|
||||
.USER_OUT(user_out),
|
||||
.USER_IN(user_in)
|
||||
|
||||
@@ -25,27 +25,44 @@ wire [5:0] blue = din[7:2];
|
||||
// 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)
|
||||
|
||||
reg [18:0] y_2, pb_2, pr_2;
|
||||
reg [7:0] y, pb, pr;
|
||||
reg [23:0] din2, din3;
|
||||
reg hsync2, vsync2, csync2;
|
||||
reg [23:0] rgb;
|
||||
always @(posedge clk) begin
|
||||
y_2 <= 19'd04096 + ({red, 8'd0} + {red, 3'd0}) + ({green, 9'd0} + {green, 2'd0}) + ({blue, 6'd0} + {blue, 5'd0} + {blue, 2'd0});
|
||||
pb_2 <= 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});
|
||||
pr_2 <= 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});
|
||||
reg [18:0] y_1r, pb_1r, pr_1r;
|
||||
reg [18:0] y_1g, pb_1g, pr_1g;
|
||||
reg [18:0] y_1b, pb_1b, pr_1b;
|
||||
reg [18:0] y_2, pb_2, pr_2;
|
||||
reg [23:0] din1, din2;
|
||||
reg hsync2, vsync2, csync2;
|
||||
reg hsync1, vsync1, csync1;
|
||||
|
||||
y_1r <= 19'd04096 + ({red, 8'd0} + {red, 3'd0});
|
||||
pb_1r <= 19'd32768 - ({red, 7'd0} + {red, 4'd0} + {red, 3'd0});
|
||||
pr_1r <= 19'd32768 + ({red, 8'd0} + {red, 7'd0} + {red, 6'd0});
|
||||
|
||||
y_1g <= {green, 9'd0} + {green, 2'd0};
|
||||
pb_1g <= {green, 8'd0} + {green, 5'd0} + {green, 3'd0};
|
||||
pr_1g <= {green, 8'd0} + {green, 6'd0} + {green, 5'd0} + {green, 4'd0} + {green, 3'd0};
|
||||
|
||||
y_1b <= {blue, 6'd0} + {blue, 5'd0} + {blue, 2'd0};
|
||||
pb_1b <= {blue, 8'd0} + {blue, 7'd0} + {blue, 6'd0};
|
||||
pr_1b <= {blue, 6'd0} + {blue, 3'd0};
|
||||
|
||||
y_2 <= y_1r + y_1g + y_1b;
|
||||
pb_2 <= pb_1r - pb_1g + pb_1b;
|
||||
pr_2 <= pr_1r - pr_1g - pr_1b;
|
||||
|
||||
y <= ( y_2[18] || !y_2[17:12]) ? 8'd16 : (y_2[17:8] > 235) ? 8'd235 : y_2[15:8];
|
||||
pb <= (pb_2[18] || !pb_2[17:12]) ? 8'd16 : (&pb_2[17:12]) ? 8'd240 : pb_2[15:8];
|
||||
pr <= (pr_2[18] || !pr_2[17:12]) ? 8'd16 : (&pr_2[17:12]) ? 8'd240 : pr_2[15:8];
|
||||
|
||||
hsync_o <= hsync2; hsync2 <= hsync;
|
||||
vsync_o <= vsync2; vsync2 <= vsync;
|
||||
csync_o <= csync2; csync2 <= csync;
|
||||
hsync_o <= hsync2; hsync2 <= hsync1; hsync1 <= hsync;
|
||||
vsync_o <= vsync2; vsync2 <= vsync1; vsync1 <= vsync;
|
||||
csync_o <= csync2; csync2 <= csync1; csync1 <= csync;
|
||||
|
||||
din2 <= din;
|
||||
din3 <= din2;
|
||||
rgb <= din2; din2 <= din1; din1 <= din;
|
||||
end
|
||||
|
||||
assign dout = ypbpr_en ? {pr, y, pb} : din3;
|
||||
assign dout = ypbpr_en ? {pr, y, pb} : rgb;
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -28,21 +28,29 @@ module video_freak
|
||||
input [11:0] ARX,
|
||||
input [11:0] ARY,
|
||||
input [11:0] CROP_SIZE,
|
||||
input [4:0] CROP_OFF,
|
||||
input [1:0] SCALE
|
||||
input [4:0] CROP_OFF, // -16...+15
|
||||
input [2:0] SCALE //0 - normal, 1 - V-integer, 2 - HV-Integer-, 3 - HV-Integer+, 4 - HV-Integer
|
||||
);
|
||||
|
||||
reg mul_start;
|
||||
wire mul_run;
|
||||
reg [11:0] mul_arg1, mul_arg2;
|
||||
wire [23:0] mul_res;
|
||||
sys_umul #(12,12) mul(CLK_VIDEO,mul_start,mul_run, mul_arg1,mul_arg2,mul_res);
|
||||
|
||||
reg vde;
|
||||
reg [11:0] arxo,aryo;
|
||||
reg [11:0] vsize;
|
||||
reg [11:0] hsize;
|
||||
|
||||
always @(posedge CLK_VIDEO) begin
|
||||
reg old_de, old_vs,vcalc,ovde;
|
||||
reg old_de, old_vs,ovde;
|
||||
reg [11:0] vtot,vcpt,vcrop,voff;
|
||||
reg [11:0] hcpt;
|
||||
reg [11:0] vadj;
|
||||
reg [23:0] ARXG,ARYG,arx,ary;
|
||||
reg [23:0] ARXG,ARYG;
|
||||
reg [11:0] arx,ary;
|
||||
reg [1:0] vcalc;
|
||||
|
||||
if (CE_PIXEL) begin
|
||||
old_de <= VGA_DE_IN;
|
||||
@@ -51,7 +59,7 @@ always @(posedge CLK_VIDEO) begin
|
||||
vcpt <= 0;
|
||||
vtot <= vcpt;
|
||||
vcalc <= 1;
|
||||
vcrop <= ((CROP_SIZE >= vcpt) || !CROP_SIZE) ? 12'd0 : CROP_SIZE;
|
||||
vcrop <= (CROP_SIZE >= vcpt) ? 12'd0 : CROP_SIZE;
|
||||
end
|
||||
|
||||
if (VGA_DE_IN) hcpt <= hcpt + 1'd1;
|
||||
@@ -65,17 +73,36 @@ always @(posedge CLK_VIDEO) begin
|
||||
arx <= ARX;
|
||||
ary <= ARY;
|
||||
|
||||
vsize <= vcrop;
|
||||
vsize <= vcrop ? vcrop : vtot;
|
||||
|
||||
mul_start <= 0;
|
||||
|
||||
if(!vcrop || !ary || !arx) begin
|
||||
arxo <= arx[11:0];
|
||||
aryo <= ary[11:0];
|
||||
vsize <= vtot;
|
||||
arxo <= arx;
|
||||
aryo <= ary;
|
||||
end
|
||||
else if (vcalc) begin
|
||||
ARXG <= arx * vtot;
|
||||
ARYG <= ary * vcrop;
|
||||
vcalc <= 0;
|
||||
if(~mul_start & ~mul_run) begin
|
||||
vcalc <= vcalc + 1'd1;
|
||||
case(vcalc)
|
||||
1: begin
|
||||
mul_arg1 <= arx;
|
||||
mul_arg2 <= vtot;
|
||||
mul_start <= 1;
|
||||
end
|
||||
|
||||
2: begin
|
||||
ARXG <= mul_res;
|
||||
mul_arg1 <= ary;
|
||||
mul_arg2 <= vcrop;
|
||||
mul_start <= 1;
|
||||
end
|
||||
|
||||
3: begin
|
||||
ARYG <= mul_res;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
else if (ARXG[23] | ARYG[23]) begin
|
||||
arxo <= ARXG[23:12];
|
||||
@@ -94,6 +121,42 @@ end
|
||||
|
||||
assign VGA_DE = vde & VGA_DE_IN;
|
||||
|
||||
video_scale_int scale
|
||||
(
|
||||
.CLK_VIDEO(CLK_VIDEO),
|
||||
.HDMI_WIDTH(HDMI_WIDTH),
|
||||
.HDMI_HEIGHT(HDMI_HEIGHT),
|
||||
.SCALE(SCALE),
|
||||
.hsize(hsize),
|
||||
.vsize(vsize),
|
||||
.arx_i(arxo),
|
||||
.ary_i(aryo),
|
||||
.arx_o(VIDEO_ARX),
|
||||
.ary_o(VIDEO_ARY)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
module video_scale_int
|
||||
(
|
||||
input CLK_VIDEO,
|
||||
|
||||
input [11:0] HDMI_WIDTH,
|
||||
input [11:0] HDMI_HEIGHT,
|
||||
|
||||
input [2:0] SCALE,
|
||||
|
||||
input [11:0] hsize,
|
||||
input [11:0] vsize,
|
||||
|
||||
input [11:0] arx_i,
|
||||
input [11:0] ary_i,
|
||||
|
||||
output reg [12:0] arx_o,
|
||||
output reg [12:0] ary_o
|
||||
);
|
||||
|
||||
reg div_start;
|
||||
wire div_run;
|
||||
reg [23:0] div_num;
|
||||
@@ -110,16 +173,17 @@ sys_umul #(12,12) mul(CLK_VIDEO,mul_start,mul_run, mul_arg1,mul_arg2,mul_res);
|
||||
wire [11:0] wideres = mul_res[11:0] + hsize;
|
||||
|
||||
always @(posedge CLK_VIDEO) begin
|
||||
reg [11:0] oheight;
|
||||
reg [11:0] oheight,wres;
|
||||
reg [12:0] arxf,aryf;
|
||||
reg [3:0] cnt;
|
||||
reg narrow;
|
||||
|
||||
div_start <= 0;
|
||||
mul_start <= 0;
|
||||
|
||||
if (!SCALE || !aryo || !arxo) begin
|
||||
arxf <= arxo;
|
||||
aryf <= aryo;
|
||||
if (!SCALE || (!ary_i && arx_i)) begin
|
||||
arxf <= arx_i;
|
||||
aryf <= ary_i;
|
||||
end
|
||||
else if(~div_start & ~div_run & ~mul_start & ~mul_run) begin
|
||||
cnt <= cnt + 1'd1;
|
||||
@@ -133,8 +197,8 @@ always @(posedge CLK_VIDEO) begin
|
||||
1: if(!div_res[11:0]) begin
|
||||
// screen resolution is lower than video resolution.
|
||||
// Integer scaling is impossible.
|
||||
arxf <= arxo;
|
||||
aryf <= aryo;
|
||||
arxf <= arx_i;
|
||||
aryf <= ary_i;
|
||||
cnt <= 0;
|
||||
end
|
||||
else begin
|
||||
@@ -145,51 +209,70 @@ always @(posedge CLK_VIDEO) begin
|
||||
|
||||
2: begin
|
||||
oheight <= mul_res[11:0];
|
||||
if(!ary_i) begin
|
||||
cnt <= 8;
|
||||
end
|
||||
end
|
||||
|
||||
3: begin
|
||||
mul_arg1 <= mul_res[11:0];
|
||||
mul_arg2 <= arxo;
|
||||
mul_arg2 <= arx_i;
|
||||
mul_start <= 1;
|
||||
end
|
||||
|
||||
3: begin
|
||||
4: begin
|
||||
div_num <= mul_res;
|
||||
div_den <= aryo;
|
||||
div_den <= ary_i;
|
||||
div_start <= 1;
|
||||
end
|
||||
|
||||
4: begin
|
||||
5: begin
|
||||
div_num <= div_res;
|
||||
div_den <= hsize;
|
||||
div_start <= 1;
|
||||
end
|
||||
|
||||
5: begin
|
||||
6: begin
|
||||
mul_arg1 <= hsize;
|
||||
mul_arg2 <= div_res[11:0] ? div_res[11:0] : 12'd1;
|
||||
mul_start <= 1;
|
||||
end
|
||||
|
||||
6: if(mul_res <= HDMI_WIDTH) cnt <= 8;
|
||||
else begin
|
||||
7: if(mul_res <= HDMI_WIDTH) begin
|
||||
cnt <= 10;
|
||||
end
|
||||
|
||||
8: begin
|
||||
div_num <= HDMI_WIDTH;
|
||||
div_den <= hsize;
|
||||
div_start <= 1;
|
||||
end
|
||||
|
||||
7: begin
|
||||
9: begin
|
||||
mul_arg1 <= hsize;
|
||||
mul_arg2 <= div_res[11:0] ? div_res[11:0] : 12'd1;
|
||||
mul_start <= 1;
|
||||
end
|
||||
|
||||
8: begin
|
||||
arxf <= {1'b1, ~SCALE[1] ? div_num[11:0] : (SCALE[0] && (wideres <= HDMI_WIDTH)) ? wideres : mul_res[11:0]};
|
||||
10: begin
|
||||
narrow <= ((div_num[11:0] - mul_res[11:0]) <= (wideres - div_num[11:0])) || (wideres > HDMI_WIDTH);
|
||||
wres <= wideres;
|
||||
end
|
||||
|
||||
11: begin
|
||||
case(SCALE)
|
||||
2: arxf <= {1'b1, mul_res[11:0]};
|
||||
3: arxf <= {1'b1, (wres > HDMI_WIDTH) ? mul_res[11:0] : wres};
|
||||
4: arxf <= {1'b1, narrow ? mul_res[11:0] : wres};
|
||||
default: arxf <= {1'b1, div_num[11:0]};
|
||||
endcase
|
||||
aryf <= {1'b1, oheight};
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
VIDEO_ARX <= arxf;
|
||||
VIDEO_ARY <= aryf;
|
||||
arx_o <= arxf;
|
||||
ary_o <= aryf;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
143
sys/video_freezer.sv
Normal file
143
sys/video_freezer.sv
Normal file
@@ -0,0 +1,143 @@
|
||||
//
|
||||
// video freeze with sync
|
||||
// (C) Alexey Melnikov
|
||||
//
|
||||
//
|
||||
// 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; either version 2 of the License, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// 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, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
|
||||
module video_freezer
|
||||
(
|
||||
input clk,
|
||||
|
||||
output sync,
|
||||
input freeze,
|
||||
|
||||
input hs_in,
|
||||
input vs_in,
|
||||
input hbl_in,
|
||||
input vbl_in,
|
||||
|
||||
output hs_out,
|
||||
output vs_out,
|
||||
output hbl_out,
|
||||
output vbl_out
|
||||
);
|
||||
|
||||
sync_lock #(33) vs_lock
|
||||
(
|
||||
.clk(clk),
|
||||
.sync_in(vs_in),
|
||||
.sync_out(vs_out),
|
||||
.de_in(vbl_in),
|
||||
.de_out(vbl_out),
|
||||
.freeze(freeze)
|
||||
);
|
||||
|
||||
wire sync_pt;
|
||||
sync_lock #(21) hs_lock
|
||||
(
|
||||
.clk(clk),
|
||||
.sync_in(hs_in),
|
||||
.sync_out(hs_out),
|
||||
.de_in(hbl_in),
|
||||
.de_out(hbl_out),
|
||||
.freeze(freeze),
|
||||
.sync_pt(sync_pt)
|
||||
);
|
||||
|
||||
reg sync_o;
|
||||
always @(posedge clk) begin
|
||||
reg old_hs, old_vs;
|
||||
reg vs_sync;
|
||||
|
||||
old_vs <= vs_out;
|
||||
|
||||
if(~old_vs & vs_out) vs_sync <= 1;
|
||||
if(sync_pt & vs_sync) begin
|
||||
vs_sync <= 0;
|
||||
sync_o <= ~sync_o;
|
||||
end
|
||||
end
|
||||
|
||||
assign sync = sync_o;
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
module sync_lock #(parameter WIDTH)
|
||||
(
|
||||
input clk,
|
||||
|
||||
input sync_in,
|
||||
input de_in,
|
||||
|
||||
output sync_out,
|
||||
output de_out,
|
||||
|
||||
input freeze,
|
||||
output sync_pt,
|
||||
output valid
|
||||
);
|
||||
|
||||
reg [WIDTH-1:0] f_len, s_len, de_start, de_end;
|
||||
reg sync_valid;
|
||||
|
||||
reg old_sync;
|
||||
always @(posedge clk) old_sync <= sync_in;
|
||||
|
||||
always @(posedge clk) begin
|
||||
reg [WIDTH-1:0] cnti;
|
||||
reg f_valid;
|
||||
reg old_de;
|
||||
|
||||
cnti <= cnti + 1'd1;
|
||||
if(~old_sync & sync_in) begin
|
||||
if(sync_valid) f_len <= cnti;
|
||||
f_valid <= 1;
|
||||
sync_valid <= f_valid;
|
||||
cnti <= 0;
|
||||
end
|
||||
|
||||
if(old_sync & ~sync_in & sync_valid) s_len <= cnti;
|
||||
|
||||
old_de <= de_in;
|
||||
if(~old_de & de_in & sync_valid) de_start <= cnti;
|
||||
if(old_de & ~de_in & sync_valid) de_end <= cnti;
|
||||
|
||||
if(freeze) {f_valid, sync_valid} <= 0;
|
||||
end
|
||||
|
||||
reg sync_o, de_o, sync_o_pre;
|
||||
always @(posedge clk) begin
|
||||
reg [WIDTH-1:0] cnto;
|
||||
|
||||
cnto <= cnto + 1'd1;
|
||||
if(old_sync & ~sync_in & sync_valid) cnto <= s_len + 2'd2;
|
||||
if(cnto == f_len) cnto <= 0;
|
||||
|
||||
sync_o_pre <= (cnto == (s_len>>1)); // middle in sync
|
||||
if(cnto == f_len) sync_o <= 1;
|
||||
if(cnto == s_len) sync_o <= 0;
|
||||
if(cnto == de_start) de_o <= 1;
|
||||
if(cnto == de_end) de_o <= 0;
|
||||
end
|
||||
|
||||
assign sync_out = freeze ? sync_o : sync_in;
|
||||
assign valid = sync_valid;
|
||||
assign sync_pt = sync_o_pre;
|
||||
assign de_out = freeze ? de_o : de_in;
|
||||
|
||||
endmodule
|
||||
@@ -10,10 +10,7 @@
|
||||
`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.
|
||||
//
|
||||
// LINE_LENGTH: Length of display line in pixels when HBlank = 0;
|
||||
// HALF_DEPTH: If =1 then color dept is 4 bits per component
|
||||
//
|
||||
// altera message_off 10720
|
||||
@@ -47,6 +44,12 @@ module video_mixer
|
||||
input HBlank,
|
||||
input VBlank,
|
||||
|
||||
// Freeze engine
|
||||
// HDMI: displays last frame
|
||||
// VGA: black screen with HSync and VSync
|
||||
input HDMI_FREEZE,
|
||||
output freeze_sync,
|
||||
|
||||
// video output signals
|
||||
output reg [7:0] VGA_R,
|
||||
output reg [7:0] VGA_G,
|
||||
@@ -60,19 +63,43 @@ localparam DWIDTH = HALF_DEPTH ? 3 : 7;
|
||||
localparam DWIDTH_SD = GAMMA ? 7 : DWIDTH;
|
||||
localparam HALF_DEPTH_SD = GAMMA ? 0 : HALF_DEPTH;
|
||||
|
||||
wire frz_hs, frz_vs;
|
||||
wire frz_hbl, frz_vbl;
|
||||
video_freezer freezer
|
||||
(
|
||||
.clk(CLK_VIDEO),
|
||||
.freeze(HDMI_FREEZE),
|
||||
.hs_in(HSync),
|
||||
.vs_in(VSync),
|
||||
.hbl_in(HBlank),
|
||||
.vbl_in(VBlank),
|
||||
.sync(freeze_sync),
|
||||
.hs_out(frz_hs),
|
||||
.vs_out(frz_vs),
|
||||
.hbl_out(frz_hbl),
|
||||
.vbl_out(frz_vbl)
|
||||
);
|
||||
|
||||
reg frz;
|
||||
always @(posedge CLK_VIDEO) begin
|
||||
reg frz1;
|
||||
|
||||
frz1 <= HDMI_FREEZE;
|
||||
frz <= frz1;
|
||||
end
|
||||
|
||||
generate
|
||||
if(GAMMA && HALF_DEPTH) begin
|
||||
wire [7:0] R_in = {R,R};
|
||||
wire [7:0] G_in = {G,G};
|
||||
wire [7:0] B_in = {B,B};
|
||||
wire [7:0] R_in = frz ? 8'd0 : {R,R};
|
||||
wire [7:0] G_in = frz ? 8'd0 : {G,G};
|
||||
wire [7:0] B_in = frz ? 8'd0 : {B,B};
|
||||
end else begin
|
||||
wire [DWIDTH:0] R_in = R;
|
||||
wire [DWIDTH:0] G_in = G;
|
||||
wire [DWIDTH:0] B_in = B;
|
||||
wire [DWIDTH:0] R_in = frz ? 1'd0 : R;
|
||||
wire [DWIDTH:0] G_in = frz ? 1'd0 : G;
|
||||
wire [DWIDTH:0] B_in = frz ? 1'd0 : B;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
|
||||
wire hs_g, vs_g;
|
||||
wire hb_g, vb_g;
|
||||
wire [DWIDTH_SD:0] R_gamma, G_gamma, B_gamma;
|
||||
@@ -90,10 +117,10 @@ generate
|
||||
.gamma_wr_addr(gamma_bus[17:8]),
|
||||
.gamma_value(gamma_bus[7:0]),
|
||||
|
||||
.HSync(HSync),
|
||||
.VSync(VSync),
|
||||
.HBlank(HBlank),
|
||||
.VBlank(VBlank),
|
||||
.HSync(frz_hs),
|
||||
.VSync(frz_vs),
|
||||
.HBlank(frz_hbl),
|
||||
.VBlank(frz_vbl),
|
||||
.RGB_in({R_in,G_in,B_in}),
|
||||
|
||||
.HSync_out(hs_g),
|
||||
@@ -105,7 +132,7 @@ generate
|
||||
end else begin
|
||||
assign gamma_bus[21] = 0;
|
||||
assign {R_gamma,G_gamma,B_gamma} = {R_in,G_in,B_in};
|
||||
assign {hs_g, vs_g, hb_g, vb_g} = {HSync, VSync, HBlank, VBlank};
|
||||
assign {hs_g, vs_g, hb_g, vb_g} = {frz_hs, frz_vs, frz_hbl, frz_vbl};
|
||||
end
|
||||
endgenerate
|
||||
|
||||
|
||||
Reference in New Issue
Block a user