mirror of
https://github.com/Gehstock/Mist_FPGA.git
synced 2026-01-19 01:16:58 +00:00
Update MiST modules
This commit is contained in:
parent
6355a42aed
commit
a2218de281
33
common/mist/README.md
Normal file
33
common/mist/README.md
Normal file
@ -0,0 +1,33 @@
|
||||
Common components for MiST board
|
||||
================================
|
||||
|
||||
This repository contains common components, which should be used by almost all cores.
|
||||
The modules:
|
||||
|
||||
- user_io.v - communicating with the IO controller.
|
||||
- data_io.v - handling file uploads from the IO controller.
|
||||
- mist_video.v - a video pipeline, which gives an optional scandoubler, OSD and rgb2ypbpr conversion.
|
||||
- osd.v, scandoubler.v, rgb2ypbpr.sv, cofi.sv - these are used in mist_video, but can be used separately, too.
|
||||
- sd_card.v - gives an SPI interface with SD-Card commands towards the IO-Controller, accessing .VHD and other mounted files.
|
||||
- dac.vhd - a simple sigma-delta DAC for audio output.
|
||||
- arcade_inputs.v - mostly for arcade-style games, gives access to the joysticks with MAME-style keyboard mapping.
|
||||
- mist.vhd - VHDL component declarations for user_io and mist_video.
|
||||
- mist_core.qip - collects the core components, which are needed in almost every case.
|
||||
|
||||
Usage hints
|
||||
===========
|
||||
|
||||
All of these components should be clocked by a synchronous clock to the core. The data between the external SPI
|
||||
interface and this internal clock are synchronized. However to make Quartus' job easier, you have to tell it to
|
||||
don't try to optimize paths between the SPI and the system clock domain. Also you have to define the incoming
|
||||
27 MHz and the SPI clocks. These lines in the .sdc file do that:
|
||||
|
||||
```
|
||||
set sys_clk "your_system_clock"
|
||||
|
||||
create_clock -name {clk_27} -period 37.037 -waveform { 0.000 18.500 } [get_ports {CLOCK_27[0]}]
|
||||
create_clock -name {SPI_SCK} -period 41.666 -waveform { 20.8 41.666 } [get_ports {SPI_SCK}]
|
||||
set_clock_groups -asynchronous -group [get_clocks {SPI_SCK}] -group [get_clocks $sys_clk]
|
||||
```
|
||||
|
||||
Replace "your_system_clock" with the name of the pll clock, like "pll|altpll_component|auto_generated|pll1|clk[0]".
|
||||
@ -1,5 +1,7 @@
|
||||
// Composite-like horizontal blending by Kitrinx
|
||||
|
||||
// AMR - disable shift register recognition
|
||||
(* altera_attribute = "-name AUTO_SHIFT_REGISTER_RECOGNITION OFF" *)
|
||||
module cofi (
|
||||
input clk,
|
||||
input pix_ce,
|
||||
@ -9,22 +11,24 @@ module cofi (
|
||||
input vblank,
|
||||
input hs,
|
||||
input vs,
|
||||
input [5:0] red,
|
||||
input [5:0] green,
|
||||
input [5:0] blue,
|
||||
input [VIDEO_DEPTH-1:0] red,
|
||||
input [VIDEO_DEPTH-1:0] green,
|
||||
input [VIDEO_DEPTH-1:0] blue,
|
||||
|
||||
output reg hblank_out,
|
||||
output reg vblank_out,
|
||||
output reg hs_out,
|
||||
output reg vs_out,
|
||||
output reg [5:0] red_out,
|
||||
output reg [5:0] green_out,
|
||||
output reg [5:0] blue_out
|
||||
output reg [VIDEO_DEPTH-1:0] red_out,
|
||||
output reg [VIDEO_DEPTH-1:0] green_out,
|
||||
output reg [VIDEO_DEPTH-1:0] blue_out
|
||||
);
|
||||
|
||||
function bit [5:0] color_blend (
|
||||
input [5:0] color_prev,
|
||||
input [5:0] color_curr,
|
||||
parameter VIDEO_DEPTH=8;
|
||||
|
||||
function bit [VIDEO_DEPTH-1:0] color_blend (
|
||||
input [VIDEO_DEPTH-1:0] color_prev,
|
||||
input [VIDEO_DEPTH-1:0] color_curr,
|
||||
input blank_last
|
||||
);
|
||||
begin
|
||||
@ -32,9 +36,9 @@ module cofi (
|
||||
end
|
||||
endfunction
|
||||
|
||||
reg [5:0] red_last;
|
||||
reg [5:0] green_last;
|
||||
reg [5:0] blue_last;
|
||||
reg [VIDEO_DEPTH-1:0] red_last;
|
||||
reg [VIDEO_DEPTH-1:0] green_last;
|
||||
reg [VIDEO_DEPTH-1:0] blue_last;
|
||||
|
||||
wire ce = enable ? pix_ce : 1'b1;
|
||||
always @(posedge clk) if (ce) begin
|
||||
|
||||
@ -15,7 +15,9 @@ component user_io
|
||||
generic(
|
||||
STRLEN : integer := 0;
|
||||
PS2DIV : integer := 100;
|
||||
ROM_DIRECT_UPLOAD : boolean := false
|
||||
ROM_DIRECT_UPLOAD : boolean := false;
|
||||
SD_IMAGES: integer := 2;
|
||||
PS2BIDIR : boolean := false
|
||||
);
|
||||
port (
|
||||
clk_sys : in std_logic;
|
||||
@ -39,14 +41,14 @@ port (
|
||||
core_mod : out std_logic_vector(6 downto 0);
|
||||
|
||||
sd_lba : in std_logic_vector(31 downto 0) := (others => '0');
|
||||
sd_rd : in std_logic_vector(1 downto 0) := (others => '0');
|
||||
sd_wr : in std_logic_vector(1 downto 0) := (others => '0');
|
||||
sd_rd : in std_logic_vector(SD_IMAGES-1 downto 0) := (others => '0');
|
||||
sd_wr : in std_logic_vector(SD_IMAGES-1 downto 0) := (others => '0');
|
||||
sd_ack : out std_logic;
|
||||
sd_ack_conf : out std_logic;
|
||||
sd_conf : in std_logic := '0';
|
||||
sd_sdhc : in std_logic := '1';
|
||||
img_size : out std_logic_vector(31 downto 0);
|
||||
img_mounted : out std_logic_vector(1 downto 0);
|
||||
img_size : out std_logic_vector(63 downto 0);
|
||||
img_mounted : out std_logic_vector(SD_IMAGES-1 downto 0);
|
||||
|
||||
sd_buff_addr : out std_logic_vector(8 downto 0);
|
||||
sd_dout : out std_logic_vector(7 downto 0);
|
||||
@ -56,6 +58,8 @@ port (
|
||||
|
||||
ps2_kbd_clk : out std_logic;
|
||||
ps2_kbd_data : out std_logic;
|
||||
ps2_kbd_clk_i : in std_logic := '1';
|
||||
ps2_kbd_data_i : in std_logic := '1';
|
||||
key_pressed : out std_logic;
|
||||
key_extended : out std_logic;
|
||||
key_code : out std_logic_vector(7 downto 0);
|
||||
@ -63,6 +67,8 @@ port (
|
||||
|
||||
ps2_mouse_clk : out std_logic;
|
||||
ps2_mouse_data : out std_logic;
|
||||
ps2_mouse_clk_i : in std_logic := '1';
|
||||
ps2_mouse_data_i : in std_logic := '1';
|
||||
mouse_x : out signed(8 downto 0);
|
||||
mouse_y : out signed(8 downto 0);
|
||||
mouse_z : out signed(3 downto 0);
|
||||
|
||||
7
common/mist/mist_core.qip
Normal file
7
common/mist/mist_core.qip
Normal file
@ -0,0 +1,7 @@
|
||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) mist.vhd]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) user_io.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) mist_video.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) scandoubler.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) osd.v]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) rgb2ypbpr.v]
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) cofi.sv]
|
||||
@ -38,11 +38,11 @@ module mist_video
|
||||
input VSync,
|
||||
|
||||
// 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
|
||||
output reg [5:0] VGA_R,
|
||||
output reg [5:0] VGA_G,
|
||||
output reg [5:0] VGA_B,
|
||||
output reg VGA_VS,
|
||||
output reg VGA_HS
|
||||
);
|
||||
|
||||
parameter OSD_COLOR = 3'd4;
|
||||
@ -59,59 +59,15 @@ wire [5:0] SD_B_O;
|
||||
wire SD_HS_O;
|
||||
wire SD_VS_O;
|
||||
|
||||
reg [5:0] R_full;
|
||||
reg [5:0] G_full;
|
||||
reg [5:0] B_full;
|
||||
|
||||
always @(*) begin
|
||||
if (COLOR_DEPTH == 6) begin
|
||||
R_full = R;
|
||||
G_full = G;
|
||||
B_full = B;
|
||||
end else if (COLOR_DEPTH == 2) begin
|
||||
R_full = {3{R}};
|
||||
G_full = {3{G}};
|
||||
B_full = {3{B}};
|
||||
end else if (COLOR_DEPTH == 1) begin
|
||||
R_full = {6{R}};
|
||||
G_full = {6{G}};
|
||||
B_full = {6{B}};
|
||||
end else begin
|
||||
R_full = { R, R[COLOR_DEPTH-1 -:(6-COLOR_DEPTH)] };
|
||||
G_full = { G, G[COLOR_DEPTH-1 -:(6-COLOR_DEPTH)] };
|
||||
B_full = { B, B[COLOR_DEPTH-1 -:(6-COLOR_DEPTH)] };
|
||||
end
|
||||
end
|
||||
|
||||
reg [1:0] i_div;
|
||||
reg ce_x1, ce_x2;
|
||||
|
||||
always @(posedge clk_sys) begin
|
||||
reg last_hs_in;
|
||||
last_hs_in <= HSync;
|
||||
if(last_hs_in & !HSync) begin
|
||||
i_div <= 2'b00;
|
||||
end else begin
|
||||
i_div <= i_div + 2'd1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(*) begin
|
||||
if (!ce_divider) begin
|
||||
ce_x1 = (i_div == 2'b01);
|
||||
ce_x2 = i_div[0];
|
||||
end else begin
|
||||
ce_x1 = i_div[0];
|
||||
ce_x2 = 1'b1;
|
||||
end
|
||||
end
|
||||
wire pixel_ena;
|
||||
|
||||
scandoubler #(SD_HCNT_WIDTH, COLOR_DEPTH) scandoubler
|
||||
(
|
||||
.clk_sys ( clk_sys ),
|
||||
.bypass ( scandoubler_disable ),
|
||||
.ce_divider ( ce_divider ),
|
||||
.scanlines ( scanlines ),
|
||||
.ce_x1 ( ce_x1 ),
|
||||
.ce_x2 ( ce_x2 ),
|
||||
.pixel_ena ( pixel_ena ),
|
||||
.hs_in ( HSync ),
|
||||
.vs_in ( VSync ),
|
||||
.r_in ( R ),
|
||||
@ -132,15 +88,15 @@ osd #(OSD_X_OFFSET, OSD_Y_OFFSET, OSD_COLOR, OSD_AUTO_CE) osd
|
||||
(
|
||||
.clk_sys ( clk_sys ),
|
||||
.rotate ( rotate ),
|
||||
.ce ( scandoubler_disable ? ce_x1 : ce_x2 ),
|
||||
.ce ( pixel_ena ),
|
||||
.SPI_DI ( SPI_DI ),
|
||||
.SPI_SCK ( SPI_SCK ),
|
||||
.SPI_SS3 ( SPI_SS3 ),
|
||||
.R_in ( scandoubler_disable ? R_full : SD_R_O ),
|
||||
.G_in ( scandoubler_disable ? G_full : SD_G_O ),
|
||||
.B_in ( scandoubler_disable ? B_full : SD_B_O ),
|
||||
.HSync ( scandoubler_disable ? HSync : SD_HS_O ),
|
||||
.VSync ( scandoubler_disable ? VSync : SD_VS_O ),
|
||||
.R_in ( SD_R_O ),
|
||||
.G_in ( SD_G_O ),
|
||||
.B_in ( SD_B_O ),
|
||||
.HSync ( SD_HS_O ),
|
||||
.VSync ( SD_VS_O ),
|
||||
.R_out ( osd_r_o ),
|
||||
.G_out ( osd_g_o ),
|
||||
.B_out ( osd_b_o )
|
||||
@ -149,13 +105,13 @@ osd #(OSD_X_OFFSET, OSD_Y_OFFSET, OSD_COLOR, OSD_AUTO_CE) osd
|
||||
wire [5:0] cofi_r, cofi_g, cofi_b;
|
||||
wire cofi_hs, cofi_vs;
|
||||
|
||||
cofi cofi (
|
||||
cofi #(6) cofi (
|
||||
.clk ( clk_sys ),
|
||||
.pix_ce ( scandoubler_disable ? ce_x1 : ce_x2 ),
|
||||
.pix_ce ( pixel_ena ),
|
||||
.enable ( blend ),
|
||||
.hblank ( ~(scandoubler_disable ? HSync : SD_HS_O) ),
|
||||
.hs ( scandoubler_disable ? HSync : SD_HS_O ),
|
||||
.vs ( scandoubler_disable ? VSync : SD_VS_O ),
|
||||
.hblank ( ~SD_HS_O ),
|
||||
.hs ( SD_HS_O ),
|
||||
.vs ( SD_VS_O ),
|
||||
.red ( osd_r_o ),
|
||||
.green ( osd_g_o ),
|
||||
.blue ( osd_b_o ),
|
||||
@ -166,7 +122,8 @@ cofi cofi (
|
||||
.blue_out( cofi_b )
|
||||
);
|
||||
|
||||
wire hs, vs;
|
||||
wire hs, vs, cs;
|
||||
wire [5:0] r,g,b;
|
||||
|
||||
RGBtoYPbPr #(6) rgb2ypbpr
|
||||
(
|
||||
@ -178,18 +135,22 @@ RGBtoYPbPr #(6) rgb2ypbpr
|
||||
.blue_in ( cofi_b ),
|
||||
.hs_in ( cofi_hs ),
|
||||
.vs_in ( cofi_vs ),
|
||||
.red_out ( VGA_R ),
|
||||
.green_out ( VGA_G ),
|
||||
.blue_out ( VGA_B ),
|
||||
.cs_in ( SYNC_AND ? (cofi_hs & cofi_vs) : ~(cofi_hs ^ cofi_vs) ),
|
||||
.red_out ( r ),
|
||||
.green_out ( g ),
|
||||
.blue_out ( b ),
|
||||
.hs_out ( hs ),
|
||||
.vs_out ( vs )
|
||||
.vs_out ( vs ),
|
||||
.cs_out ( cs )
|
||||
);
|
||||
|
||||
wire cs = SYNC_AND ? (hs & vs) : ~(hs ^ vs);
|
||||
|
||||
// a minimig vga->scart cable expects a composite sync signal on the VGA_HS output.
|
||||
// and VCC on VGA_VS (to switch into rgb mode)
|
||||
assign VGA_HS = ((~no_csync & scandoubler_disable) || ypbpr)? cs : hs;
|
||||
assign VGA_VS = ((~no_csync & scandoubler_disable) || ypbpr)? 1'b1 : vs;
|
||||
|
||||
always @(posedge clk_sys) begin
|
||||
VGA_R <= r;
|
||||
VGA_G <= g;
|
||||
VGA_B <= b;
|
||||
// a minimig vga->scart cable expects a composite sync signal on the VGA_HS output.
|
||||
// and VCC on VGA_VS (to switch into rgb mode)
|
||||
VGA_HS <= ((~no_csync & scandoubler_disable) || ypbpr)? cs : hs;
|
||||
VGA_VS <= ((~no_csync & scandoubler_disable) || ypbpr)? 1'b1 : vs;
|
||||
end
|
||||
endmodule
|
||||
|
||||
@ -22,11 +22,12 @@ module scandoubler
|
||||
(
|
||||
// system interface
|
||||
input clk_sys,
|
||||
input bypass,
|
||||
input ce_divider,
|
||||
output pixel_ena,
|
||||
|
||||
// scanlines (00-none 01-25% 10-50% 11-75%)
|
||||
input [1:0] scanlines,
|
||||
input ce_x1,
|
||||
input ce_x2,
|
||||
|
||||
// shifter video interface
|
||||
input hs_in,
|
||||
@ -46,6 +47,32 @@ module scandoubler
|
||||
parameter HCNT_WIDTH = 9;
|
||||
parameter COLOR_DEPTH = 6;
|
||||
|
||||
// pixel clock divider
|
||||
reg [1:0] i_div;
|
||||
reg ce_x1, ce_x2;
|
||||
|
||||
always @(posedge clk_sys) begin
|
||||
reg last_hs_in;
|
||||
last_hs_in <= hs_in;
|
||||
if(last_hs_in & !hs_in) begin
|
||||
i_div <= 2'b00;
|
||||
end else begin
|
||||
i_div <= i_div + 2'd1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(*) begin
|
||||
if (!ce_divider) begin
|
||||
ce_x1 = (i_div == 2'b01);
|
||||
ce_x2 = i_div[0];
|
||||
end else begin
|
||||
ce_x1 = i_div[0];
|
||||
ce_x2 = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
assign pixel_ena = bypass ? ce_x1 : ce_x2;
|
||||
|
||||
// --------------------- create output signals -----------------
|
||||
// latch everything once more to make it glitch free and apply scanline effect
|
||||
reg scanline;
|
||||
@ -74,9 +101,15 @@ always @(*) begin
|
||||
end
|
||||
|
||||
always @(posedge clk_sys) begin
|
||||
if(ce_x2) begin
|
||||
if(bypass) begin
|
||||
r_out <= r;
|
||||
g_out <= g;
|
||||
b_out <= b;
|
||||
hs_out <= hs_sd;
|
||||
vs_out <= vs_in;
|
||||
vs_out <= vs_sd;
|
||||
end else if(ce_x2) begin
|
||||
hs_out <= hs_sd;
|
||||
vs_out <= vs_sd;
|
||||
|
||||
// reset scanlines at every new screen
|
||||
if(vs_out != vs_in) scanline <= 0;
|
||||
@ -114,7 +147,7 @@ always @(posedge clk_sys) begin
|
||||
end
|
||||
|
||||
// scan doubler output register
|
||||
reg [COLOR_DEPTH*3-1:0] sd_out;
|
||||
wire [COLOR_DEPTH*3-1:0] sd_out = bypass ? sd_bypass_out : sd_buffer_out;
|
||||
|
||||
// ==================================================================
|
||||
// ======================== the line buffers ========================
|
||||
@ -162,8 +195,9 @@ end
|
||||
// ==================== output timing generation ====================
|
||||
// ==================================================================
|
||||
|
||||
reg [HCNT_WIDTH-1:0] sd_hcnt;
|
||||
reg hs_sd;
|
||||
reg [COLOR_DEPTH*3-1:0] sd_buffer_out, sd_bypass_out;
|
||||
reg [HCNT_WIDTH-1:0] sd_hcnt;
|
||||
reg hs_sd, vs_sd;
|
||||
|
||||
// timing generation runs 32 MHz (twice the input signal analysis speed)
|
||||
always @(posedge clk_sys) begin
|
||||
@ -182,7 +216,13 @@ always @(posedge clk_sys) begin
|
||||
if(sd_hcnt == hs_rise) hs_sd <= 1;
|
||||
|
||||
// read data from line sd_buffer
|
||||
sd_out <= sd_buffer[{~line_toggle, sd_hcnt}];
|
||||
sd_buffer_out <= sd_buffer[{~line_toggle, sd_hcnt}];
|
||||
vs_sd <= vs_in;
|
||||
end
|
||||
if(bypass) begin
|
||||
sd_bypass_out <= {r_in, g_in, b_in};
|
||||
hs_sd <= hs_in;
|
||||
vs_sd <= vs_in;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -66,10 +66,11 @@ wire [7:0] READ_DATA_TOKEN = 8'hfe;
|
||||
localparam NCR=4;
|
||||
|
||||
localparam RD_STATE_IDLE = 3'd0;
|
||||
localparam RD_STATE_WAIT_IO = 3'd1;
|
||||
localparam RD_STATE_SEND_TOKEN = 3'd2;
|
||||
localparam RD_STATE_SEND_DATA = 3'd3;
|
||||
localparam RD_STATE_DELAY = 3'd4;
|
||||
localparam RD_STATE_WAIT_BUSY = 3'd1;
|
||||
localparam RD_STATE_WAIT_IO = 3'd2;
|
||||
localparam RD_STATE_SEND_TOKEN = 3'd3;
|
||||
localparam RD_STATE_SEND_DATA = 3'd4;
|
||||
localparam RD_STATE_DELAY = 3'd5;
|
||||
reg [2:0] read_state = RD_STATE_IDLE;
|
||||
|
||||
localparam WR_STATE_IDLE = 3'd0;
|
||||
@ -78,7 +79,8 @@ localparam WR_STATE_RECV_DATA = 3'd2;
|
||||
localparam WR_STATE_RECV_CRC0 = 3'd3;
|
||||
localparam WR_STATE_RECV_CRC1 = 3'd4;
|
||||
localparam WR_STATE_SEND_DRESP = 3'd5;
|
||||
localparam WR_STATE_BUSY = 3'd6;
|
||||
localparam WR_STATE_WRITE = 3'd6;
|
||||
localparam WR_STATE_BUSY = 3'd7;
|
||||
reg [2:0] write_state = WR_STATE_IDLE;
|
||||
|
||||
reg card_is_reset = 1'b0; // flag that card has received a reset command
|
||||
@ -89,6 +91,7 @@ reg [7:0] cmd = 8'h00;
|
||||
reg [2:0] bit_cnt = 3'd0; // counts bits 0-7 0-7 ...
|
||||
reg [3:0] byte_cnt= 4'd15; // counts bytes
|
||||
reg [4:0] delay_cnt;
|
||||
reg wr_first;
|
||||
|
||||
reg [39:0] args;
|
||||
|
||||
@ -110,7 +113,7 @@ sd_card_dpram #(8, 10) buffer_dpram
|
||||
.clock_a (clk_sys),
|
||||
.address_a ({sd_buff_sel, sd_buff_addr}),
|
||||
.data_a (sd_buff_dout),
|
||||
.wren_a (sd_buff_wr & sd_ack),
|
||||
.wren_a (sd_buff_wr & sd_ack & read_state != RD_STATE_IDLE),
|
||||
.q_a (sd_buff_din),
|
||||
|
||||
.clock_b (clk_sys),
|
||||
@ -152,7 +155,7 @@ always @(posedge clk_sys) begin
|
||||
// update card size in case of a virtual SD image
|
||||
if (sd_sdhc)
|
||||
// CSD V2.0 size = (c_size + 1) * 512K
|
||||
csdcid[69:48] <= {9'd0, img_size[31:19] };
|
||||
csdcid[69:48] <= {9'd0, img_size[31:19] } - 1'd1;
|
||||
else begin
|
||||
// CSD V1.0 no. of blocks = c_size ** (c_size_mult + 2)
|
||||
csdcid[49:47] <= 3'd7; //c_size_mult
|
||||
@ -196,12 +199,9 @@ always@(posedge clk_sys) begin
|
||||
|
||||
// CMD17: READ_SINGLE_BLOCK
|
||||
// CMD18: READ_MULTIPLE_BLOCK
|
||||
if((cmd == 8'h51 || cmd == 8'h52) && !terminate_cmd) begin
|
||||
sd_lba <= sd_sdhc?args[39:8]:{9'd0, args[39:17]};
|
||||
read_state <= RD_STATE_WAIT_IO; // start waiting for data from io controller
|
||||
sd_rd <= 1; // trigger request to io controller
|
||||
sd_busy <= 1;
|
||||
end
|
||||
if((cmd == 8'h51 || cmd == 8'h52) && !terminate_cmd)
|
||||
read_state <= RD_STATE_WAIT_BUSY; // start waiting for data from io controller
|
||||
|
||||
end
|
||||
end
|
||||
else if((reply_len > 0) && (byte_cnt == 5+NCR+1))
|
||||
@ -219,10 +219,19 @@ always@(posedge clk_sys) begin
|
||||
RD_STATE_IDLE: ;
|
||||
// don't do anything
|
||||
|
||||
// wait until the IO controller is free and issue a read
|
||||
RD_STATE_WAIT_BUSY:
|
||||
if (~sd_busy) begin
|
||||
sd_buff_sel <= 0;
|
||||
sd_lba <= sd_sdhc?args[39:8]:{9'd0, args[39:17]};
|
||||
sd_rd <= 1; // trigger request to io controller
|
||||
sd_busy <= 1;
|
||||
read_state <= RD_STATE_WAIT_IO;
|
||||
end
|
||||
|
||||
// waiting for io controller to return data
|
||||
RD_STATE_WAIT_IO: begin
|
||||
buffer_ptr <= 0;
|
||||
sd_buff_sel <= 0;
|
||||
if(~sd_busy) begin
|
||||
if (terminate_cmd) begin
|
||||
cmd <= 0;
|
||||
@ -299,7 +308,7 @@ always@(posedge clk_sys) begin
|
||||
sd_sdo <= WRITE_DATA_RESPONSE[~bit_cnt];
|
||||
|
||||
// busy after write until the io controller sends ack
|
||||
if(write_state == WR_STATE_BUSY)
|
||||
if(write_state == WR_STATE_WRITE || write_state == WR_STATE_BUSY)
|
||||
sd_sdo <= 1'b0;
|
||||
end
|
||||
|
||||
@ -310,6 +319,7 @@ always@(posedge clk_sys) begin
|
||||
terminate_cmd <= 0;
|
||||
cmd <= 0;
|
||||
read_state <= RD_STATE_IDLE;
|
||||
reply_len <= 0;
|
||||
end else if (~old_sd_sck & sd_sck) begin
|
||||
bit_cnt <= bit_cnt + 3'd1;
|
||||
|
||||
@ -325,7 +335,7 @@ always@(posedge clk_sys) begin
|
||||
// byte_cnt > 6 -> complete command received
|
||||
// first byte of valid command is 01xxxxxx
|
||||
// don't accept new commands (except STOP TRANSMISSION) once a write or read command has been accepted
|
||||
if((byte_cnt > 5) &&
|
||||
if((byte_cnt > (reply_len == 0 ? 5 : (5+NCR+reply_len))) &&
|
||||
(write_state == WR_STATE_IDLE) &&
|
||||
(read_state == RD_STATE_IDLE || (read_state != RD_STATE_IDLE && { sbuf, sd_sdi} == 8'h4c)) &&
|
||||
sbuf[6:5] == 2'b01)
|
||||
@ -406,9 +416,11 @@ always@(posedge clk_sys) begin
|
||||
8'h52: reply <= 8'h00; // ok
|
||||
|
||||
// CMD24: WRITE_BLOCK
|
||||
8'h58: begin
|
||||
// CMD25: WRITE_MULTIPLE_BLOCKS
|
||||
8'h58, 8'h59: begin
|
||||
reply <= 8'h00; // ok
|
||||
sd_lba <= sd_sdhc?args[39:8]:{9'd0, args[39:17]};
|
||||
buffer_ptr <= 0;
|
||||
wr_first <= 1;
|
||||
write_state <= WR_STATE_EXP_DTOKEN; // expect data token
|
||||
end
|
||||
|
||||
@ -433,58 +445,83 @@ always@(posedge clk_sys) begin
|
||||
reply3 <= OCR[7:0];
|
||||
reply_len <= 4'd4;
|
||||
end
|
||||
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
// ---------- handle write -----------
|
||||
case(write_state)
|
||||
// don't do anything in idle state
|
||||
WR_STATE_IDLE: ;
|
||||
|
||||
// waiting for data token
|
||||
WR_STATE_EXP_DTOKEN:
|
||||
if({ sbuf, sd_sdi} == 8'hfe ) begin
|
||||
write_state <= WR_STATE_RECV_DATA;
|
||||
buffer_ptr <= 0;
|
||||
sd_buff_sel <= 0;
|
||||
end
|
||||
|
||||
// transfer 512 bytes
|
||||
WR_STATE_RECV_DATA: begin
|
||||
// push one byte into local buffer
|
||||
buffer_write_strobe <= 1'b1;
|
||||
buffer_din <= { sbuf, sd_sdi };
|
||||
|
||||
// all bytes written?
|
||||
if(&buffer_ptr[8:0])
|
||||
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: begin
|
||||
write_state <= WR_STATE_BUSY;
|
||||
sd_wr <= 1; // trigger write request to io ontroller
|
||||
sd_busy <= 1;
|
||||
end
|
||||
|
||||
// wait for io controller to accept data
|
||||
WR_STATE_BUSY:
|
||||
if(~sd_busy)
|
||||
write_state <= WR_STATE_IDLE;
|
||||
|
||||
default: ;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
// ---------- handle write -----------
|
||||
case(write_state)
|
||||
// don't do anything in idle state
|
||||
WR_STATE_IDLE: ;
|
||||
|
||||
// waiting for data token
|
||||
WR_STATE_EXP_DTOKEN:
|
||||
if (sd_cs) write_state <= WR_STATE_IDLE;
|
||||
else if (~old_sd_sck && sd_sck && bit_cnt == 7) begin
|
||||
if({ sbuf, sd_sdi} == 8'hfd && cmd == 8'h59)
|
||||
// stop multiple write (and wait until the last write finishes)
|
||||
write_state <= WR_STATE_BUSY;
|
||||
else
|
||||
if({ sbuf, sd_sdi} == ((cmd == 8'h59) ? 8'hfc : 8'hfe))
|
||||
write_state <= WR_STATE_RECV_DATA;
|
||||
end
|
||||
|
||||
// transfer 512 bytes
|
||||
WR_STATE_RECV_DATA:
|
||||
if (sd_cs) write_state <= WR_STATE_IDLE;
|
||||
else if (~old_sd_sck && sd_sck && bit_cnt == 7) begin
|
||||
// push one byte into local buffer
|
||||
buffer_write_strobe <= 1'b1;
|
||||
buffer_din <= { sbuf, sd_sdi };
|
||||
|
||||
// all bytes written?
|
||||
if(&buffer_ptr[8:0])
|
||||
write_state <= WR_STATE_RECV_CRC0;
|
||||
end
|
||||
|
||||
// transfer 1st crc byte
|
||||
WR_STATE_RECV_CRC0:
|
||||
if (sd_cs) write_state <= WR_STATE_IDLE;
|
||||
else if (~old_sd_sck && sd_sck && bit_cnt == 7) write_state <= WR_STATE_RECV_CRC1;
|
||||
|
||||
// transfer 2nd crc byte
|
||||
WR_STATE_RECV_CRC1:
|
||||
if (sd_cs) write_state <= WR_STATE_IDLE;
|
||||
else if (~old_sd_sck && sd_sck && bit_cnt == 7) write_state <= WR_STATE_SEND_DRESP;
|
||||
|
||||
// send data response
|
||||
WR_STATE_SEND_DRESP:
|
||||
if (sd_cs) write_state <= WR_STATE_IDLE;
|
||||
else if (~old_sd_sck && sd_sck && bit_cnt == 7) write_state <= WR_STATE_WRITE;
|
||||
|
||||
WR_STATE_WRITE:
|
||||
if (~sd_busy) begin
|
||||
if (wr_first) begin
|
||||
sd_buff_sel <= 0;
|
||||
sd_lba <= sd_sdhc?args[39:8]:{9'd0, args[39:17]};
|
||||
wr_first <= 0;
|
||||
end else begin
|
||||
sd_buff_sel <= !sd_buff_sel;
|
||||
sd_lba <= sd_lba + 1'd1;
|
||||
end
|
||||
sd_wr <= 1; // trigger write request to io controller
|
||||
sd_busy <= 1;
|
||||
|
||||
if (sd_cs || cmd == 8'h58)
|
||||
write_state <= WR_STATE_BUSY;
|
||||
else
|
||||
write_state <= WR_STATE_EXP_DTOKEN; // multi-sector writes
|
||||
|
||||
end
|
||||
|
||||
WR_STATE_BUSY:
|
||||
if (~sd_busy) write_state <= WR_STATE_IDLE;
|
||||
|
||||
default: ;
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
|
||||
// parameter STRLEN and the actual length of conf_str have to match
|
||||
|
||||
module user_io #(parameter STRLEN=0, parameter PS2DIV=100, parameter ROM_DIRECT_UPLOAD=0) (
|
||||
module user_io (
|
||||
input [(8*STRLEN)-1:0] conf_str,
|
||||
output [9:0] conf_addr, // RAM address for config string, if STRLEN=0
|
||||
input [7:0] conf_chr,
|
||||
@ -55,8 +55,8 @@ module user_io #(parameter STRLEN=0, parameter PS2DIV=100, parameter ROM_DIRECT_
|
||||
|
||||
// connection to sd card emulation
|
||||
input [31:0] sd_lba,
|
||||
input [1:0] sd_rd,
|
||||
input [1:0] sd_wr,
|
||||
input [SD_IMAGES-1:0] sd_rd,
|
||||
input [SD_IMAGES-1:0] sd_wr,
|
||||
output reg sd_ack,
|
||||
output reg sd_ack_conf,
|
||||
input sd_conf,
|
||||
@ -67,14 +67,18 @@ module user_io #(parameter STRLEN=0, parameter PS2DIV=100, parameter ROM_DIRECT_
|
||||
output reg sd_din_strobe,
|
||||
output reg [8:0] sd_buff_addr,
|
||||
|
||||
output reg [1:0] img_mounted, // rising edge if a new image is mounted
|
||||
output reg [31:0] img_size, // size of image in bytes
|
||||
output reg [SD_IMAGES-1:0] img_mounted, // rising edge if a new image is mounted
|
||||
output reg [63:0] img_size, // size of image in bytes
|
||||
|
||||
// ps2 keyboard/mouse emulation
|
||||
output ps2_kbd_clk,
|
||||
output reg ps2_kbd_data,
|
||||
input ps2_kbd_clk_i,
|
||||
input ps2_kbd_data_i,
|
||||
output ps2_mouse_clk,
|
||||
output reg ps2_mouse_data,
|
||||
input ps2_mouse_clk_i,
|
||||
input ps2_mouse_data_i,
|
||||
|
||||
// keyboard data
|
||||
output reg key_pressed, // 1-make (pressed), 0-break (released)
|
||||
@ -95,6 +99,14 @@ module user_io #(parameter STRLEN=0, parameter PS2DIV=100, parameter ROM_DIRECT_
|
||||
input serial_strobe
|
||||
);
|
||||
|
||||
parameter STRLEN=0; // config string length
|
||||
parameter PS2DIV=100; // master clock divider for psk2_kbd/mouse clk
|
||||
parameter ROM_DIRECT_UPLOAD=0; // direct upload used for file uploads from the ARM
|
||||
parameter SD_IMAGES=2; // number of block-access images (max. 4 supported in current firmware)
|
||||
parameter PS2BIDIR=0; // bi-directional PS2 interface
|
||||
|
||||
localparam W = $clog2(SD_IMAGES);
|
||||
|
||||
reg [6:0] sbuf;
|
||||
reg [7:0] cmd;
|
||||
reg [2:0] bit_cnt; // counts bits 0-7 0-7 ...
|
||||
@ -114,7 +126,13 @@ assign conf_addr = byte_cnt;
|
||||
// bit 4 indicates ROM direct upload capability
|
||||
wire [7:0] core_type = ROM_DIRECT_UPLOAD ? 8'hb4 : 8'ha4;
|
||||
|
||||
wire drive_sel = sd_rd[1] | sd_wr[1];
|
||||
reg [W:0] drive_sel;
|
||||
always begin
|
||||
integer i;
|
||||
drive_sel = 0;
|
||||
for(i = 0; i < SD_IMAGES; i = i + 1) if(sd_rd[i] | sd_wr[i]) drive_sel = i[W:0];
|
||||
end
|
||||
|
||||
// command byte read by the io controller
|
||||
wire [7:0] sd_cmd = { 4'h6, sd_conf, sd_sdhc, sd_wr[drive_sel], sd_rd[drive_sel] };
|
||||
|
||||
@ -125,7 +143,7 @@ wire spi_sck = SPI_CLK;
|
||||
localparam PS2_FIFO_BITS = 3;
|
||||
|
||||
reg ps2_clk;
|
||||
always @(negedge clk_sys) begin
|
||||
always @(posedge clk_sys) begin
|
||||
integer cnt;
|
||||
cnt <= cnt + 1'd1;
|
||||
if(cnt == PS2DIV) begin
|
||||
@ -144,14 +162,24 @@ reg [3:0] ps2_kbd_tx_state;
|
||||
reg [7:0] ps2_kbd_tx_byte;
|
||||
reg ps2_kbd_parity;
|
||||
|
||||
assign ps2_kbd_clk = ps2_clk || (ps2_kbd_tx_state == 0);
|
||||
// ps2 receiver state machine
|
||||
reg [3:0] ps2_kbd_rx_state = 0;
|
||||
reg [1:0] ps2_kbd_rx_start = 0;
|
||||
reg [7:0] ps2_kbd_rx_byte = 0;
|
||||
reg ps2_kbd_rx_strobe = 0;
|
||||
|
||||
// ps2 transmitter
|
||||
assign ps2_kbd_clk = ps2_clk || (ps2_kbd_tx_state == 0 && ps2_kbd_rx_state == 0);
|
||||
|
||||
// ps2 transmitter/receiver
|
||||
// Takes a byte from the FIFO and sends it in a ps2 compliant serial format.
|
||||
reg ps2_kbd_r_inc;
|
||||
// Sends a command to the IO controller if bidirectional mode is enabled.
|
||||
always@(posedge clk_sys) begin : ps2_kbd
|
||||
reg ps2_clkD;
|
||||
|
||||
reg ps2_clkD;
|
||||
reg ps2_clk_iD, ps2_dat_iD;
|
||||
reg ps2_kbd_r_inc;
|
||||
|
||||
// send data
|
||||
ps2_clkD <= ps2_clk;
|
||||
if (~ps2_clkD & ps2_clk) begin
|
||||
ps2_kbd_r_inc <= 1'b0;
|
||||
@ -161,8 +189,9 @@ always@(posedge clk_sys) begin : ps2_kbd
|
||||
|
||||
// transmitter is idle?
|
||||
if(ps2_kbd_tx_state == 0) begin
|
||||
ps2_kbd_data <= 1;
|
||||
// data in fifo present?
|
||||
if(ps2_kbd_wptr != ps2_kbd_rptr) begin
|
||||
if(ps2_kbd_wptr != ps2_kbd_rptr && (ps2_kbd_clk_i | !PS2BIDIR)) begin
|
||||
// load tx register from fifo
|
||||
ps2_kbd_tx_byte <= ps2_kbd_fifo[ps2_kbd_rptr];
|
||||
ps2_kbd_r_inc <= 1'b1;
|
||||
@ -201,6 +230,43 @@ always@(posedge clk_sys) begin : ps2_kbd
|
||||
ps2_kbd_tx_state <= 4'd0;
|
||||
end
|
||||
end
|
||||
|
||||
if (PS2BIDIR) begin
|
||||
ps2_clk_iD <= ps2_kbd_clk_i;
|
||||
ps2_dat_iD <= ps2_kbd_data_i;
|
||||
|
||||
// receive command
|
||||
case (ps2_kbd_rx_start)
|
||||
2'd0:
|
||||
// first: host pulls down the clock line
|
||||
if (ps2_clk_iD & ~ps2_kbd_clk_i) ps2_kbd_rx_start <= 1;
|
||||
2'd1:
|
||||
// second: host pulls down the data line, while releasing the clock
|
||||
if (ps2_dat_iD && !ps2_kbd_data_i) ps2_kbd_rx_start <= 2'd2;
|
||||
// if it releases the clock without pulling down the data line: goto 0
|
||||
else if (ps2_kbd_clk_i) ps2_kbd_rx_start <= 0;
|
||||
2'd2:
|
||||
if (ps2_clkD && ~ps2_clk) begin
|
||||
ps2_kbd_rx_state <= 4'd1;
|
||||
ps2_kbd_rx_start <= 0;
|
||||
end
|
||||
default: ;
|
||||
endcase
|
||||
|
||||
// host data is valid after the rising edge of the clock
|
||||
if(ps2_kbd_rx_state != 0 && ~ps2_clkD && ps2_clk) begin
|
||||
ps2_kbd_rx_state <= ps2_kbd_rx_state + 1'd1;
|
||||
if (ps2_kbd_rx_state == 9) ;// parity
|
||||
else if (ps2_kbd_rx_state == 10) begin
|
||||
ps2_kbd_data <= 0; // ack the received byte
|
||||
end else if (ps2_kbd_rx_state == 11) begin
|
||||
ps2_kbd_rx_state <= 0;
|
||||
ps2_kbd_rx_strobe <= ~ps2_kbd_rx_strobe;
|
||||
end else begin
|
||||
ps2_kbd_rx_byte <= {ps2_kbd_data_i, ps2_kbd_rx_byte[7:1]};
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// mouse
|
||||
@ -213,13 +279,21 @@ reg [3:0] ps2_mouse_tx_state;
|
||||
reg [7:0] ps2_mouse_tx_byte;
|
||||
reg ps2_mouse_parity;
|
||||
|
||||
assign ps2_mouse_clk = ps2_clk || (ps2_mouse_tx_state == 0);
|
||||
// ps2 receiver state machine
|
||||
reg [3:0] ps2_mouse_rx_state = 0;
|
||||
reg [1:0] ps2_mouse_rx_start = 0;
|
||||
reg [7:0] ps2_mouse_rx_byte = 0;
|
||||
reg ps2_mouse_rx_strobe = 0;
|
||||
|
||||
// ps2 transmitter
|
||||
assign ps2_mouse_clk = ps2_clk || (ps2_mouse_tx_state == 0 && ps2_mouse_rx_state == 0);
|
||||
|
||||
// ps2 transmitter/receiver
|
||||
// Takes a byte from the FIFO and sends it in a ps2 compliant serial format.
|
||||
reg ps2_mouse_r_inc;
|
||||
// Sends a command to the IO controller if bidirectional mode is enabled.
|
||||
always@(posedge clk_sys) begin : ps2_mouse
|
||||
reg ps2_clkD;
|
||||
reg ps2_clk_iD, ps2_dat_iD;
|
||||
reg ps2_mouse_r_inc;
|
||||
|
||||
ps2_clkD <= ps2_clk;
|
||||
if (~ps2_clkD & ps2_clk) begin
|
||||
@ -230,8 +304,9 @@ always@(posedge clk_sys) begin : ps2_mouse
|
||||
|
||||
// transmitter is idle?
|
||||
if(ps2_mouse_tx_state == 0) begin
|
||||
ps2_mouse_data <= 1;
|
||||
// data in fifo present?
|
||||
if(ps2_mouse_wptr != ps2_mouse_rptr) begin
|
||||
if(ps2_mouse_wptr != ps2_mouse_rptr && (ps2_mouse_clk_i | !PS2BIDIR)) begin
|
||||
// load tx register from fifo
|
||||
ps2_mouse_tx_byte <= ps2_mouse_fifo[ps2_mouse_rptr];
|
||||
ps2_mouse_r_inc <= 1'b1;
|
||||
@ -270,6 +345,44 @@ always@(posedge clk_sys) begin : ps2_mouse
|
||||
ps2_mouse_tx_state <= 4'd0;
|
||||
end
|
||||
end
|
||||
|
||||
if (PS2BIDIR) begin
|
||||
|
||||
ps2_clk_iD <= ps2_mouse_clk_i;
|
||||
ps2_dat_iD <= ps2_mouse_data_i;
|
||||
|
||||
// receive command
|
||||
case (ps2_mouse_rx_start)
|
||||
2'd0:
|
||||
// first: host pulls down the clock line
|
||||
if (ps2_clk_iD & ~ps2_mouse_clk_i) ps2_mouse_rx_start <= 1;
|
||||
2'd1:
|
||||
// second: host pulls down the data line, while releasing the clock
|
||||
if (ps2_dat_iD && !ps2_mouse_data_i) ps2_mouse_rx_start <= 2'd2;
|
||||
// if it releases the clock without pulling down the data line: goto 0
|
||||
else if (ps2_mouse_clk_i) ps2_mouse_rx_start <= 0;
|
||||
2'd2:
|
||||
if (ps2_clkD && ~ps2_clk) begin
|
||||
ps2_mouse_rx_state <= 4'd1;
|
||||
ps2_mouse_rx_start <= 0;
|
||||
end
|
||||
default: ;
|
||||
endcase
|
||||
|
||||
// host data is valid after the rising edge of the clock
|
||||
if(ps2_mouse_rx_state != 0 && ~ps2_clkD && ps2_clk) begin
|
||||
ps2_mouse_rx_state <= ps2_mouse_rx_state + 1'd1;
|
||||
if (ps2_mouse_rx_state == 9) ;// parity
|
||||
else if (ps2_mouse_rx_state == 10) begin
|
||||
ps2_mouse_data <= 0; // ack the received byte
|
||||
end else if (ps2_mouse_rx_state == 11) begin
|
||||
ps2_mouse_rx_state <= 0;
|
||||
ps2_mouse_rx_strobe <= ~ps2_mouse_rx_strobe;
|
||||
end else begin
|
||||
ps2_mouse_rx_byte <= {ps2_mouse_data_i, ps2_mouse_rx_byte[7:1]};
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// fifo to receive serial data from core to be forwarded to io controller
|
||||
@ -334,7 +447,9 @@ end
|
||||
|
||||
always@(posedge spi_sck or posedge SPI_SS_IO) begin : spi_transmitter
|
||||
reg [31:0] sd_lba_r;
|
||||
reg [7:0] drive_sel_r;
|
||||
reg [W:0] drive_sel_r;
|
||||
reg ps2_kbd_rx_strobeD;
|
||||
reg ps2_mouse_rx_strobeD;
|
||||
|
||||
if(SPI_SS_IO == 1) begin
|
||||
spi_byte_out <= core_type;
|
||||
@ -345,6 +460,20 @@ always@(posedge spi_sck or posedge SPI_SS_IO) begin : spi_transmitter
|
||||
|
||||
spi_byte_out <= 0;
|
||||
case({(!byte_cnt) ? {sbuf, SPI_MOSI} : cmd})
|
||||
// PS2 keyboard command
|
||||
8'h0e: if (byte_cnt == 0) begin
|
||||
ps2_kbd_rx_strobeD <= ps2_kbd_rx_strobe;
|
||||
//echo the command code if there's a byte to send, indicating the core supports the command
|
||||
spi_byte_out <= (ps2_kbd_rx_strobe ^ ps2_kbd_rx_strobeD) ? 8'h0e : 8'h00;
|
||||
end else spi_byte_out <= ps2_kbd_rx_byte;
|
||||
|
||||
// PS2 mouse command
|
||||
8'h0f: if (byte_cnt == 0) begin
|
||||
ps2_mouse_rx_strobeD <= ps2_mouse_rx_strobe;
|
||||
//echo the command code if there's a byte to send, indicating the core supports the command
|
||||
spi_byte_out <= (ps2_mouse_rx_strobe ^ ps2_mouse_rx_strobeD) ? 8'h0f : 8'h00;
|
||||
end else spi_byte_out <= ps2_mouse_rx_byte;
|
||||
|
||||
// reading config string
|
||||
8'h14: if (STRLEN == 0) spi_byte_out <= conf_chr; else
|
||||
if(byte_cnt < STRLEN) spi_byte_out <= conf_str[(STRLEN - byte_cnt - 1)<<3 +:8];
|
||||
@ -353,7 +482,7 @@ always@(posedge spi_sck or posedge SPI_SS_IO) begin : spi_transmitter
|
||||
8'h16: if(byte_cnt == 0) begin
|
||||
spi_byte_out <= sd_cmd;
|
||||
sd_lba_r <= sd_lba;
|
||||
drive_sel_r <= {7'b0, drive_sel};
|
||||
drive_sel_r <= drive_sel;
|
||||
end
|
||||
else if(byte_cnt == 1) spi_byte_out <= drive_sel_r;
|
||||
else if(byte_cnt < 6) spi_byte_out <= sd_lba_r[(5-byte_cnt)<<3 +:8];
|
||||
@ -521,7 +650,7 @@ always @(posedge clk_sd) begin : sd_block
|
||||
reg spi_transfer_end;
|
||||
reg spi_receiver_strobeD;
|
||||
reg spi_transfer_endD;
|
||||
reg [1:0] sd_wrD;
|
||||
reg [SD_IMAGES-1:0] sd_wrD;
|
||||
reg [7:0] acmd;
|
||||
reg [7:0] abyte_cnt; // counts bytes
|
||||
|
||||
@ -539,7 +668,7 @@ always @(posedge clk_sd) begin : sd_block
|
||||
sd_din_strobe<= 0;
|
||||
sd_wrD <= sd_wr;
|
||||
// fetch the first byte immediately after the write command seen
|
||||
if ((~sd_wrD[0] & sd_wr[0]) || (~sd_wrD[1] & sd_wrD[1])) begin
|
||||
if (|(~sd_wrD & sd_wr)) begin
|
||||
sd_buff_addr <= 0;
|
||||
sd_din_strobe <= 1;
|
||||
end
|
||||
@ -550,8 +679,6 @@ always @(posedge clk_sd) begin : sd_block
|
||||
abyte_cnt <= 8'd0;
|
||||
sd_ack <= 1'b0;
|
||||
sd_ack_conf <= 1'b0;
|
||||
sd_dout_strobe <= 1'b0;
|
||||
sd_din_strobe <= 1'b0;
|
||||
sd_buff_addr <= 0;
|
||||
end else if (spi_receiver_strobeD ^ spi_receiver_strobe) begin
|
||||
|
||||
@ -591,10 +718,10 @@ always @(posedge clk_sd) begin : sd_block
|
||||
end
|
||||
end
|
||||
|
||||
8'h1c: img_mounted[spi_byte_in[0]] <= 1;
|
||||
8'h1c: img_mounted[spi_byte_in[W:0]] <= 1;
|
||||
|
||||
// send image info
|
||||
8'h1d: if(abyte_cnt<5) img_size[(abyte_cnt-1)<<3 +:8] <= spi_byte_in;
|
||||
8'h1d: if(abyte_cnt<9) img_size[(abyte_cnt-1)<<3 +:8] <= spi_byte_in;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user