Update sys.

This commit is contained in:
Sorgelig 2022-03-07 17:07:01 +08:00
parent 4cd1724296
commit 89236bc26c
19 changed files with 1739 additions and 1101 deletions

View File

@ -13,7 +13,7 @@ set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
set_global_assignment -name LAST_QUARTUS_VERSION "17.0.2 Lite Edition"
set_global_assignment -name LAST_QUARTUS_VERSION "17.0.2 Standard Edition"
set_global_assignment -name GENERATE_RBF_FILE ON
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files

View File

@ -29,7 +29,7 @@ module emu
input RESET,
//Must be passed to hps_io module
inout [45:0] HPS_BUS,
inout [48:0] HPS_BUS,
//Base video clock. Usually equals to CLK_SYS.
output CLK_VIDEO,
@ -39,9 +39,9 @@ module emu
output CE_PIXEL,
//Video aspect ratio for HDMI. Most retro systems have ratio 4:3.
//if VIDEO_ARX[12] or VIDEO_ARY[12] is set then [11:0] contains scaled size instead of aspect ratio.
output [12:0] VIDEO_ARX,
output [12:0] VIDEO_ARY,
//if VIDEO_ARX[12] or VIDEO_ARY[12] is set then [11:0] contains scaled size instead of aspect ratio.
output [12:0] VIDEO_ARX,
output [12:0] VIDEO_ARY,
output [7:0] VGA_R,
output [7:0] VGA_G,
@ -52,11 +52,12 @@ module emu
output VGA_F1,
output [1:0] VGA_SL,
output VGA_SCALER, // Force VGA scaler
input [11:0] HDMI_WIDTH,
input [11:0] HDMI_HEIGHT,
`ifdef USE_FB
input [11:0] HDMI_WIDTH,
input [11:0] HDMI_HEIGHT,
output HDMI_FREEZE,
`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,
@ -184,6 +184,7 @@ assign LED_DISK = 0;
assign LED_POWER = 0;
assign BUTTONS = 0;
assign VGA_SCALER= 0;
assign HDMI_FREEZE = 0;
wire [1:0] ar = status[8:7];
video_freak video_freak
@ -265,13 +266,13 @@ end
// the status register is controlled by the on screen display (OSD)
wire [31:0] status;
wire [1:0] buttons;
wire [31:0] sd_lba;
wire [31:0] sd_lba[2];
wire [1:0] sd_rd;
wire [1:0] sd_wr;
wire sd_ack;
wire [1:0] sd_ack;
wire [7:0] sd_buff_addr;
wire [15:0] sd_buff_dout;
wire [15:0] sd_buff_din;
wire [15:0] sd_buff_din[2];
wire sd_buff_wr;
wire [1:0] img_mounted;
wire [31:0] img_size;
@ -288,13 +289,11 @@ wire [15:0] ioctl_data;
wire [32:0] TIMESTAMP;
hps_io #(.STRLEN($size(CONF_STR)>>3), .VDNUM(2), .WIDE(1)) hps_io
hps_io #(.CONF_STR(CONF_STR), .VDNUM(2), .WIDE(1)) hps_io
(
.clk_sys(clk_sys),
.HPS_BUS(HPS_BUS),
.conf_str(CONF_STR),
.buttons(buttons),
.status(status),
@ -303,7 +302,6 @@ hps_io #(.STRLEN($size(CONF_STR)>>3), .VDNUM(2), .WIDE(1)) hps_io
.sd_wr(sd_wr),
.sd_ack(sd_ack),
.sd_conf(0),
.sd_buff_addr(sd_buff_addr),
.sd_buff_dout(sd_buff_dout),
.sd_buff_din(sd_buff_din),
@ -689,14 +687,16 @@ dataController_top dc0
// block device interface for scsi disk
.img_mounted(img_mounted),
.img_size(img_size),
.io_lba(sd_lba),
.io_lba0(sd_lba[0]),
.io_lba1(sd_lba[1]),
.io_rd(sd_rd),
.io_wr(sd_wr),
.io_ack(sd_ack),
.sd_buff_addr(sd_buff_addr),
.sd_buff_dout(sd_buff_dout),
.sd_buff_din(sd_buff_din),
.sd_buff_din0(sd_buff_din[0]),
.sd_buff_din1(sd_buff_din[1]),
.sd_buff_wr(sd_buff_wr)
);

View File

@ -81,13 +81,15 @@ module dataController_top(
// connections to io controller
input [1:0] img_mounted,
input [31:0] img_size,
output [31:0] io_lba,
output [31:0] io_lba0,
output [31:0] io_lba1,
output [1:0] io_rd,
output [1:0] io_wr,
input io_ack,
input [1:0] io_ack,
input [7:0] sd_buff_addr,
input [15:0] sd_buff_dout,
output [15:0] sd_buff_din,
output [15:0] sd_buff_din0,
output [15:0] sd_buff_din1,
input sd_buff_wr
);
@ -179,14 +181,16 @@ module dataController_top(
// connections to io controller
.img_mounted( img_mounted ),
.img_size( img_size ),
.io_lba ( io_lba ),
.io_lba0 ( io_lba0 ),
.io_lba1 ( io_lba1 ),
.io_rd ( io_rd ),
.io_wr ( io_wr ),
.io_ack ( io_ack ),
.sd_buff_addr(sd_buff_addr),
.sd_buff_dout(sd_buff_dout),
.sd_buff_din(sd_buff_din),
.sd_buff_din0(sd_buff_din0),
.sd_buff_din1(sd_buff_din1),
.sd_buff_wr(sd_buff_wr)
);

View File

@ -65,15 +65,16 @@ module ncr5380
input [1:0] img_mounted,
input [31:0] img_size,
output [15:0] io_req_type,
output [31:0] io_lba,
output [31:0] io_lba0,
output [31:0] io_lba1,
output [1:0] io_rd,
output [1:0] io_wr,
input io_ack,
input [1:0] io_ack,
input [7:0] sd_buff_addr,
input [15:0] sd_buff_dout,
output [15:0] sd_buff_din,
output [15:0] sd_buff_din0,
output [15:0] sd_buff_din1,
input sd_buff_wr
);
@ -278,17 +279,10 @@ module ncr5380
scsi6_bsy ? scsi6_dout :
8'h55;
assign io_lba = (scsi2_bsy) ? io_lba_2 : io_lba_6;
assign sd_buff_din = (scsi2_bsy) ? sd_buff_din_2 : sd_buff_din_6;
assign io_req_type = 16'h0000; // Not used atm. Could be used for CD-ROM sector requests later. ElectronAsh.
// input signals from target 2
wire scsi2_bsy, scsi2_msg, scsi2_io, scsi2_cd, scsi2_req;
wire [7:0] scsi2_dout;
wire [31:0] io_lba_2;
wire [15:0] sd_buff_din_2;
// connect a target
scsi #(.ID(2)) scsi2
(
@ -312,15 +306,15 @@ module ncr5380
// to sd card
.img_mounted(img_mounted[1]),
.img_blocks(img_size[31:9]),
.io_lba ( io_lba_2 ),
.io_lba ( io_lba1 ),
.io_rd ( io_rd[1] ),
.io_wr ( io_wr[1] ),
.io_ack ( io_ack & scsi2_bsy ),
.io_ack ( io_ack[1] ),
.sd_buff_addr( sd_buff_addr ),
.sd_buff_dout( sd_buff_dout ),
.sd_buff_din( sd_buff_din_2 ),
.sd_buff_wr( sd_buff_wr & scsi2_bsy )
.sd_buff_din( sd_buff_din1 ),
.sd_buff_wr( sd_buff_wr )
);
@ -328,9 +322,6 @@ module ncr5380
wire scsi6_bsy, scsi6_msg, scsi6_io, scsi6_cd, scsi6_req;
wire [7:0] scsi6_dout;
wire [31:0] io_lba_6;
wire [15:0] sd_buff_din_6;
scsi #(.ID(6)) scsi6
(
.clk ( clk ) , // input clk
@ -353,15 +344,15 @@ module ncr5380
// to sd card
.img_mounted( img_mounted[0] ),
.img_blocks( img_size[31:9] ),
.io_lba ( io_lba_6 ) , // output [31:0] io_lba
.io_lba ( io_lba0 ) , // output [31:0] io_lba
.io_rd ( io_rd[0] ) , // output io_rd
.io_wr ( io_wr[0] ) , // output io_wr
.io_ack ( io_ack & scsi6_bsy ) , // input io_ack
.io_ack ( io_ack[0] ) , // input io_ack
.sd_buff_addr( sd_buff_addr ) , // input [8:0] sd_buff_addr
.sd_buff_dout( sd_buff_dout ) , // input [7:0] sd_buff_dout
.sd_buff_din( sd_buff_din_6 ) , // output [7:0] sd_buff_din
.sd_buff_wr( sd_buff_wr & scsi6_bsy ) // input sd_buff_wr
.sd_buff_din( sd_buff_din0 ) , // output [7:0] sd_buff_din
.sd_buff_wr( sd_buff_wr ) // input sd_buff_wr
);

View File

@ -61,10 +61,10 @@ always @(posedge clk) sd_buff_din[15:8] <= buffer_out1[sd_buff_addr];
// ---------------- buffer write engine ----------------------
// the buffer itself. Can hold one sector
reg [7:0] buffer_in0 [256];
always @(posedge clk) if(sd_buff_wr) buffer_in0[sd_buff_addr] <= sd_buff_dout[7:0];
always @(posedge clk) if(sd_buff_wr & io_ack) buffer_in0[sd_buff_addr] <= sd_buff_dout[7:0];
reg [7:0] buffer_in1 [256];
always @(posedge clk) if(sd_buff_wr) buffer_in1[sd_buff_addr] <= sd_buff_dout[15:8];
always @(posedge clk) if(sd_buff_wr & io_ack) buffer_in1[sd_buff_addr] <= sd_buff_dout[15:8];
// -----------------------------------------------------------

View File

@ -174,15 +174,17 @@ module screen_rotate
input rotate_ccw,
input no_rotate,
input flip,
output video_rotated,
output FB_EN,
output [4:0] FB_FORMAT,
output [11:0] FB_WIDTH,
output [11:0] FB_HEIGHT,
output [31:0] FB_BASE,
output [13:0] FB_STRIDE,
input FB_VBL,
input FB_LL,
output FB_EN,
output [4:0] FB_FORMAT,
output reg [11:0] FB_WIDTH,
output reg [11:0] FB_HEIGHT,
output [31:0] FB_BASE,
output [13:0] FB_STRIDE,
input FB_VBL,
input FB_LL,
output DDRAM_CLK,
input DDRAM_BUSY,
@ -196,6 +198,8 @@ module screen_rotate
parameter MEM_BASE = 7'b0010010; // buffer at 0x24000000, 3x8MB
reg do_flip;
assign DDRAM_CLK = CLK_VIDEO;
assign DDRAM_BURSTCNT = 1;
assign DDRAM_ADDR = {MEM_BASE, i_fb, ram_addr[22:3]};
@ -207,8 +211,6 @@ assign DDRAM_RD = 0;
assign FB_EN = fb_en[2];
assign FB_FORMAT = 5'b00110;
assign FB_BASE = {MEM_BASE,o_fb,23'd0};
assign FB_WIDTH = vsz;
assign FB_HEIGHT = hsz;
assign FB_STRIDE = stride;
function [1:0] buf_next;
@ -220,6 +222,19 @@ function [1:0] buf_next;
end
endfunction
assign video_rotated = ~no_rotate;
always @(posedge CLK_VIDEO) begin
do_flip <= no_rotate && flip;
if( do_flip ) begin
FB_WIDTH <= hsz;
FB_HEIGHT <= vsz;
end else begin
FB_WIDTH <= vsz;
FB_HEIGHT <= hsz;
end
end
reg [1:0] i_fb,o_fb;
always @(posedge CLK_VIDEO) begin
reg old_vbl,old_vs;
@ -251,20 +266,23 @@ always @(posedge CLK_VIDEO) begin
if(CE_PIXEL) begin
old_vs <= VGA_VS;
old_de <= VGA_DE;
hcnt <= hcnt + 1'd1;
if(~old_de & VGA_DE) begin
hcnt <= 1;
vcnt <= vcnt + 1'd1;
end
if(old_de & ~VGA_DE) hsz <= hcnt;
if(old_de & ~VGA_DE) begin
hsz <= hcnt;
if( do_flip ) bwidth <= hcnt + 2'd3;
end
if(~old_vs & VGA_VS) begin
vsz <= vcnt;
bwidth <= vcnt + 2'd3;
if( !do_flip ) bwidth <= vcnt + 2'd3;
vcnt <= 0;
fb_en <= {fb_en[1:0], ~no_rotate};
fb_en <= {fb_en[1:0], ~no_rotate | flip};
end
if(old_vs & ~VGA_VS) bufsize <= hsz * stride;
if(old_vs & ~VGA_VS) bufsize <= (do_flip ? vsz : hsz ) * stride;
end
end
@ -278,21 +296,25 @@ always @(posedge CLK_VIDEO) begin
reg old_vs, old_de;
ram_wr <= 0;
if(CE_PIXEL) begin
if(CE_PIXEL && FB_EN) begin
old_vs <= VGA_VS;
old_de <= VGA_DE;
if(~old_vs & VGA_VS) begin
next_addr <= rotate_ccw ? (bufsize - stride) : {vsz-1'd1, 2'b00};
next_addr <=
do_flip ? bufsize-3'd4 :
rotate_ccw ? (bufsize - stride) : {vsz-1'd1, 2'b00};
hcnt <= rotate_ccw ? 3'd4 : {vsz-2'd2, 2'b00};
end
if(VGA_DE) begin
ram_wr <= 1;
ram_data <= {VGA_B,VGA_G,VGA_R};
ram_data <= {8'd0,VGA_B,VGA_G,VGA_R};
ram_addr <= next_addr;
next_addr <= rotate_ccw ? (next_addr - stride) : (next_addr + stride);
next_addr <=
do_flip ? next_addr-3'd4 :
rotate_ccw ? (next_addr - stride) : (next_addr + stride);
end
if(old_de & ~VGA_DE) begin
if(old_de & ~VGA_DE & ~do_flip) begin
next_addr <= rotate_ccw ? (bufsize - stride + hcnt) : hcnt;
hcnt <= rotate_ccw ? (hcnt + 3'd4) : (hcnt - 3'd4);
end

File diff suppressed because it is too large Load Diff

View File

@ -24,14 +24,13 @@
// 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..10
// 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,
inout [48:0] HPS_BUS,
// buttons up to 32
output reg [31:0] joystick_0,
@ -42,12 +41,19 @@ module hps_io #(parameter STRLEN=0, PS2DIV=0, WIDE=0, VDNUM=1, PS2WE=0)
output reg [31:0] joystick_5,
// analog -127..+127, Y: [15:8], X: [7:0]
output reg [15:0] joystick_analog_0,
output reg [15:0] joystick_analog_1,
output reg [15:0] joystick_analog_2,
output reg [15:0] joystick_analog_3,
output reg [15:0] joystick_analog_4,
output reg [15:0] joystick_analog_5,
output reg [15:0] joystick_l_analog_0,
output reg [15:0] joystick_l_analog_1,
output reg [15:0] joystick_l_analog_2,
output reg [15:0] joystick_l_analog_3,
output reg [15:0] joystick_l_analog_4,
output reg [15:0] joystick_l_analog_5,
output reg [15:0] joystick_r_analog_0,
output reg [15:0] joystick_r_analog_1,
output reg [15:0] joystick_r_analog_2,
output reg [15:0] joystick_r_analog_3,
output reg [15:0] joystick_r_analog_4,
output reg [15:0] joystick_r_analog_5,
// paddle 0..255
output reg [7:0] paddle_0,
@ -68,6 +74,10 @@ module hps_io #(parameter STRLEN=0, PS2DIV=0, WIDE=0, VDNUM=1, PS2WE=0)
output [1:0] buttons,
output forced_scandoubler,
output direct_video,
input video_rotated,
//toggle to force notify of video mode change
input new_vmode,
output reg [63:0] status,
input [63:0] status_in,
@ -77,31 +87,23 @@ module hps_io #(parameter STRLEN=0, PS2DIV=0, WIDE=0, VDNUM=1, PS2WE=0)
input info_req,
input [7:0] info,
//toggle to force notify of video mode change
input new_vmode,
// SD config
output reg [VD:0] img_mounted, // signaling that new image has been mounted
output reg img_readonly, // mounted as read only. valid only for active bit in img_mounted
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 +112,8 @@ 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, // request to save (must be supported on HPS side for specific core)
input [7:0] ioctl_upload_index,
input [DW:0] ioctl_din,
output reg ioctl_rd,
output reg [31:0] ioctl_file_ext,
@ -161,10 +165,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 +189,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
/////////////////////////////////////////////////////////
@ -219,6 +217,7 @@ video_calc video_calc
.vs_hdmi(HPS_BUS[44]),
.f1(HPS_BUS[45]),
.new_vmode(new_vmode),
.video_rotated(video_rotated),
.par_num(byte_cnt[3:0]),
.dout(vc_dout)
@ -226,6 +225,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 +249,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 +261,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 +302,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 +314,29 @@ 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};
`ifdef MISTER_DISABLE_ADAPTIVE
'h2B: io_dout <= {HPS_BUS[48:46],4'b0110};
`else
'h2B: io_dout <= {HPS_BUS[48:46],4'b0111};
`endif
'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 <= {ioctl_upload_index, 8'd1}; upload_req <= 0; end
'h3E: io_dout <= 1; // shadow mask
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,47 +378,41 @@ 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
// joystick left analog
'h1a: if(!byte_cnt[MAX_W:2]) begin
case(byte_cnt[1:0])
1: {pdsp_idx,stick_idx} <= io_din[7:0]; // first byte is joystick index
2: case(stick_idx)
0: joystick_analog_0 <= io_din;
1: joystick_analog_1 <= io_din;
2: joystick_analog_2 <= io_din;
3: joystick_analog_3 <= io_din;
4: joystick_analog_4 <= io_din;
5: joystick_analog_5 <= io_din;
0: joystick_l_analog_0 <= io_din;
1: joystick_l_analog_1 <= io_din;
2: joystick_l_analog_2 <= io_din;
3: joystick_l_analog_3 <= io_din;
4: joystick_l_analog_4 <= io_din;
5: joystick_l_analog_5 <= io_din;
15: case(pdsp_idx)
0: paddle_0 <= io_din[7:0];
1: paddle_1 <= io_din[7:0];
@ -412,6 +431,21 @@ always@(posedge clk_sys) begin : uio_block
endcase
end
// joystick right analog
'h3d: if(!byte_cnt[MAX_W:2]) begin
case(byte_cnt[1:0])
1: stick_idx <= io_din[3:0]; // first byte is joystick index
2: case(stick_idx)
0: joystick_r_analog_0 <= io_din;
1: joystick_r_analog_1 <= io_din;
2: joystick_r_analog_2 <= io_din;
3: joystick_r_analog_3 <= io_din;
4: joystick_r_analog_4 <= io_din;
5: joystick_r_analog_5 <= io_din;
endcase
endcase
end
// notify image selection
'h1c: begin
img_mounted <= io_din[VD:0] ? io_din[VD:0] : 1'b1;
@ -815,6 +849,7 @@ module video_calc
input vs_hdmi,
input f1,
input new_vmode,
input video_rotated,
input [3:0] par_num,
output reg [15:0] dout
@ -822,7 +857,7 @@ module video_calc
always @(posedge clk_sys) begin
case(par_num)
1: dout <= {|vid_int, vid_nres};
1: dout <= {video_rotated, |vid_int, vid_nres};
2: dout <= vid_hcnt[15:0];
3: dout <= vid_hcnt[31:16];
4: dout <= vid_vcnt[15:0];
@ -936,3 +971,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

View File

@ -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

View File

@ -5,11 +5,11 @@ module scanlines #(parameter v2=0)
input [1:0] scanlines,
input [23:0] din,
input hs_in,vs_in,
input de_in,
input de_in,ce_in,
output reg [23:0] dout,
output reg hs_out,vs_out,
output reg de_out
output reg de_out,ce_out
);
reg [1:0] scanline;
@ -56,12 +56,13 @@ end
always @(posedge clk) begin
reg [23:0] dout1, dout2;
reg de1,de2,vs1,vs2,hs1,hs2;
reg de1,de2,vs1,vs2,hs1,hs2,ce1,ce2;
dout <= dout2; dout2 <= dout1; dout1 <= d;
vs_out <= vs2; vs2 <= vs1; vs1 <= vs_in;
hs_out <= hs2; hs2 <= hs1; hs1 <= hs_in;
de_out <= de2; de2 <= de1; de1 <= de_in;
ce_out <= ce2; ce2 <= ce1; ce1 <= ce_in;
end
endmodule

View File

@ -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