usb bug fix
diff --git a/signoff/pinmux/final_summary_report.csv b/signoff/pinmux/final_summary_report.csv index a03bb10..f0549cd 100644 --- a/signoff/pinmux/final_summary_report.csv +++ b/signoff/pinmux/final_summary_report.csv
@@ -1,2 +1,2 @@ ,design,design_name,config,flow_status,total_runtime,routed_runtime,(Cell/mm^2)/Core_Util,DIEAREA_mm^2,CellPer_mm^2,OpenDP_Util,Peak_Memory_Usage_MB,cell_count,tritonRoute_violations,Short_violations,MetSpc_violations,OffGrid_violations,MinHole_violations,Other_violations,Magic_violations,antenna_violations,lvs_total_errors,cvc_total_errors,klayout_violations,wire_length,vias,wns,pl_wns,optimized_wns,fastroute_wns,spef_wns,tns,pl_tns,optimized_tns,fastroute_tns,spef_tns,HPWL,routing_layer1_pct,routing_layer2_pct,routing_layer3_pct,routing_layer4_pct,routing_layer5_pct,routing_layer6_pct,wires_count,wire_bits,public_wires_count,public_wire_bits,memories_count,memory_bits,processes_count,cells_pre_abc,AND,DFF,NAND,NOR,OR,XOR,XNOR,MUX,inputs,outputs,level,EndCaps,TapCells,Diodes,Total_Physical_Cells,suggested_clock_frequency,suggested_clock_period,CLOCK_PERIOD,SYNTH_STRATEGY,SYNTH_MAX_FANOUT,FP_CORE_UTIL,FP_ASPECT_RATIO,FP_PDN_VPITCH,FP_PDN_HPITCH,PL_TARGET_DENSITY,GLB_RT_ADJUSTMENT,STD_CELL_LIBRARY,CELL_PAD,DIODE_INSERTION_STRATEGY -0,/project/openlane/pinmux,pinmux,pinmux,flow completed,0h8m12s0ms,0h5m24s0ms,44129.29292929293,0.2475,22064.646464646466,26.19,882.68,5461,0,0,0,0,0,0,0,-1,0,-1,-1,446336,56211,0.0,0.0,-1,0.0,0.0,0.0,0.0,-1,0.0,0.0,349213339.0,0.0,58.21,42.89,33.48,21.65,-1,3480,8519,562,5601,0,0,0,4063,123,107,40,77,933,109,14,285,1086,1034,11,314,3259,0,3573,100.0,10.0,10,AREA 0,4,50,1,100,100,0.3,0.3,sky130_fd_sc_hd,4,4 +0,/project/openlane/pinmux,pinmux,pinmux,flow completed,0h8m38s0ms,0h5m38s0ms,44129.29292929293,0.2475,22064.646464646466,26.19,891.48,5461,0,0,0,0,0,0,0,-1,0,-1,-1,445725,56513,0.0,0.0,-1,0.0,0.0,0.0,0.0,-1,0.0,0.0,349875542.0,0.0,58.45,43.05,33.36,20.01,-1,3480,8519,562,5601,0,0,0,4063,123,107,40,77,933,109,14,285,1086,1034,11,314,3259,0,3573,100.0,10.0,10,AREA 0,4,50,1,100,100,0.3,0.3,sky130_fd_sc_hd,4,4
diff --git a/signoff/uart_i2cm_usb_spi_top/final_summary_report.csv b/signoff/uart_i2cm_usb_spi_top/final_summary_report.csv index ac30b2a..d98fd15 100644 --- a/signoff/uart_i2cm_usb_spi_top/final_summary_report.csv +++ b/signoff/uart_i2cm_usb_spi_top/final_summary_report.csv
@@ -1,2 +1,2 @@ ,design,design_name,config,flow_status,total_runtime,routed_runtime,(Cell/mm^2)/Core_Util,DIEAREA_mm^2,CellPer_mm^2,OpenDP_Util,Peak_Memory_Usage_MB,cell_count,tritonRoute_violations,Short_violations,MetSpc_violations,OffGrid_violations,MinHole_violations,Other_violations,Magic_violations,antenna_violations,lvs_total_errors,cvc_total_errors,klayout_violations,wire_length,vias,wns,pl_wns,optimized_wns,fastroute_wns,spef_wns,tns,pl_tns,optimized_tns,fastroute_tns,spef_tns,HPWL,routing_layer1_pct,routing_layer2_pct,routing_layer3_pct,routing_layer4_pct,routing_layer5_pct,routing_layer6_pct,wires_count,wire_bits,public_wires_count,public_wire_bits,memories_count,memory_bits,processes_count,cells_pre_abc,AND,DFF,NAND,NOR,OR,XOR,XNOR,MUX,inputs,outputs,level,EndCaps,TapCells,Diodes,Total_Physical_Cells,suggested_clock_frequency,suggested_clock_period,CLOCK_PERIOD,SYNTH_STRATEGY,SYNTH_MAX_FANOUT,FP_CORE_UTIL,FP_ASPECT_RATIO,FP_PDN_VPITCH,FP_PDN_HPITCH,PL_TARGET_DENSITY,GLB_RT_ADJUSTMENT,STD_CELL_LIBRARY,CELL_PAD,DIODE_INSERTION_STRATEGY -0,/project/openlane/uart_i2cm_usb_spi_top,uart_i2c_usb_spi_top,uart_i2cm_usb_spi_top,flow completed,0h15m33s0ms,0h11m2s0ms,69400.0,0.35,34700.0,39.27,1463.03,12145,0,0,0,0,0,0,0,-1,0,-1,-1,630996,105793,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,373528655.0,0.0,53.48,52.78,23.7,25.92,-1,8698,13063,1552,5853,0,0,0,9820,378,189,259,276,2194,356,86,807,2409,2348,19,498,4643,0,5141,100.0,10.0,10,AREA 0,4,50,1,100,100,0.45,0.3,sky130_fd_sc_hd,4,4 +0,/project/openlane/uart_i2cm_usb_spi_top,uart_i2c_usb_spi_top,uart_i2cm_usb_spi_top,flow completed,0h18m2s0ms,0h13m15s0ms,69285.71428571429,0.35,34642.857142857145,39.21,1430.34,12125,0,0,0,0,0,0,0,-1,0,-1,-1,594439,103896,0.0,0.0,0.0,0.0,-0.02,0.0,0.0,0.0,0.0,-0.02,369917177.0,0.0,51.11,51.47,19.26,22.98,-1,8702,13067,1552,5853,0,0,0,9824,392,189,256,272,2200,354,88,807,2409,2348,18,498,4643,0,5141,99.8003992015968,10.02,10,AREA 0,4,50,1,100,100,0.45,0.3,sky130_fd_sc_hd,4,4
diff --git a/signoff/user_project_wrapper/final_summary_report.csv b/signoff/user_project_wrapper/final_summary_report.csv index 4680658..54ca8c7 100644 --- a/signoff/user_project_wrapper/final_summary_report.csv +++ b/signoff/user_project_wrapper/final_summary_report.csv
@@ -1,2 +1,2 @@ ,design,design_name,config,flow_status,total_runtime,routed_runtime,(Cell/mm^2)/Core_Util,DIEAREA_mm^2,CellPer_mm^2,OpenDP_Util,Peak_Memory_Usage_MB,cell_count,tritonRoute_violations,Short_violations,MetSpc_violations,OffGrid_violations,MinHole_violations,Other_violations,Magic_violations,antenna_violations,lvs_total_errors,cvc_total_errors,klayout_violations,wire_length,vias,wns,pl_wns,optimized_wns,fastroute_wns,spef_wns,tns,pl_tns,optimized_tns,fastroute_tns,spef_tns,HPWL,routing_layer1_pct,routing_layer2_pct,routing_layer3_pct,routing_layer4_pct,routing_layer5_pct,routing_layer6_pct,wires_count,wire_bits,public_wires_count,public_wire_bits,memories_count,memory_bits,processes_count,cells_pre_abc,AND,DFF,NAND,NOR,OR,XOR,XNOR,MUX,inputs,outputs,level,EndCaps,TapCells,Diodes,Total_Physical_Cells,suggested_clock_frequency,suggested_clock_period,CLOCK_PERIOD,SYNTH_STRATEGY,SYNTH_MAX_FANOUT,FP_CORE_UTIL,FP_ASPECT_RATIO,FP_PDN_VPITCH,FP_PDN_HPITCH,PL_TARGET_DENSITY,GLB_RT_ADJUSTMENT,STD_CELL_LIBRARY,CELL_PAD,DIODE_INSERTION_STRATEGY -0,/project/openlane/user_project_wrapper,user_project_wrapper,user_project_wrapper,flow completed,1h30m35s0ms,0h4m36s0ms,-2.0,-1,-1,-1,547.92,12,0,0,0,0,0,0,0,0,0,-1,-1,1395458,6924,0.0,-1,-1,0.0,0.0,0.0,-1,-1,0.0,0.0,-1,0.0,5.97,8.97,0.84,0.47,0.0,226,2315,226,2315,0,0,0,12,0,0,0,0,0,0,0,0,-1,-1,-1,0,0,0,0,100.0,10.0,10,AREA 0,5,50,1,80,130,0.55,0.3,sky130_fd_sc_hd,4,0 +0,/project/openlane/user_project_wrapper,user_project_wrapper,user_project_wrapper,flow completed,1h30m55s0ms,0h4m38s0ms,-2.0,-1,-1,-1,541.58,12,0,0,0,0,0,0,0,0,0,-1,-1,1395490,6872,0.0,-1,-1,0.0,0.0,0.0,-1,-1,0.0,0.0,-1,0.0,5.93,9.0,0.93,0.38,0.0,226,2315,226,2315,0,0,0,12,0,0,0,0,0,0,0,0,-1,-1,-1,0,0,0,0,100.0,10.0,10,AREA 0,5,50,1,80,130,0.55,0.3,sky130_fd_sc_hd,4,0
diff --git a/signoff/wb_host/final_summary_report.csv b/signoff/wb_host/final_summary_report.csv index d3d1f84..0bbe179 100644 --- a/signoff/wb_host/final_summary_report.csv +++ b/signoff/wb_host/final_summary_report.csv
@@ -1,2 +1,2 @@ ,design,design_name,config,flow_status,total_runtime,routed_runtime,(Cell/mm^2)/Core_Util,DIEAREA_mm^2,CellPer_mm^2,OpenDP_Util,Peak_Memory_Usage_MB,cell_count,tritonRoute_violations,Short_violations,MetSpc_violations,OffGrid_violations,MinHole_violations,Other_violations,Magic_violations,antenna_violations,lvs_total_errors,cvc_total_errors,klayout_violations,wire_length,vias,wns,pl_wns,optimized_wns,fastroute_wns,spef_wns,tns,pl_tns,optimized_tns,fastroute_tns,spef_tns,HPWL,routing_layer1_pct,routing_layer2_pct,routing_layer3_pct,routing_layer4_pct,routing_layer5_pct,routing_layer6_pct,wires_count,wire_bits,public_wires_count,public_wire_bits,memories_count,memory_bits,processes_count,cells_pre_abc,AND,DFF,NAND,NOR,OR,XOR,XNOR,MUX,inputs,outputs,level,EndCaps,TapCells,Diodes,Total_Physical_Cells,suggested_clock_frequency,suggested_clock_period,CLOCK_PERIOD,SYNTH_STRATEGY,SYNTH_MAX_FANOUT,FP_CORE_UTIL,FP_ASPECT_RATIO,FP_PDN_VPITCH,FP_PDN_HPITCH,PL_TARGET_DENSITY,GLB_RT_ADJUSTMENT,STD_CELL_LIBRARY,CELL_PAD,DIODE_INSERTION_STRATEGY -0,/project/openlane/wb_host,wb_host,wb_host,flow completed,0h5m24s0ms,0h3m35s0ms,60517.64705882353,0.14875,30258.823529411766,36.67,759.34,4501,0,0,0,0,0,0,0,9,0,0,-1,206351,36529,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,156181924.0,0.0,45.83,48.0,4.16,12.69,-1,3461,6134,1009,3538,0,0,0,3773,372,52,74,184,652,130,23,458,1014,989,11,296,1950,0,2246,100.0,10.0,10,AREA 0,4,50,1,100,100,0.38,0.3,sky130_fd_sc_hd,4,4 +0,/project/openlane/wb_host,wb_host,wb_host,flow completed,0h5m9s0ms,0h3m24s0ms,61297.47899159664,0.14875,30648.73949579832,37.15,777.15,4559,0,0,0,0,0,0,0,12,0,0,-1,209244,37027,0.0,-0.21,0.0,0.0,0.0,0.0,-17.73,0.0,0.0,0.0,158619913.0,0.0,46.06,48.87,4.05,12.29,-1,3513,6206,1009,3558,0,0,0,3833,380,52,75,186,650,146,23,466,1022,997,11,296,1950,0,2246,100.0,10.0,10,AREA 0,4,50,1,100,100,0.38,0.3,sky130_fd_sc_hd,4,4
diff --git a/verilog/dv/Makefile b/verilog/dv/Makefile index 836d0cd..ddbf7d0 100644 --- a/verilog/dv/Makefile +++ b/verilog/dv/Makefile
@@ -19,7 +19,7 @@ .SUFFIXES: .SILENT: clean all -PATTERNS = wb_port risc_boot user_risc_boot user_uart user_qspi user_i2cm riscv_regress user_basic user_uart_master uart_master +PATTERNS = wb_port risc_boot user_risc_boot user_uart user_qspi user_i2cm riscv_regress user_basic user_usb user_uart_master uart_master all: ${PATTERNS} for i in ${PATTERNS}; do \
diff --git a/verilog/dv/agents/test_control.v b/verilog/dv/agents/test_control.v new file mode 100755 index 0000000..2eb066a --- /dev/null +++ b/verilog/dv/agents/test_control.v
@@ -0,0 +1,82 @@ + +module test_control(); + + event error_detected; + integer error_count; + reg verbose_msg; + + // initialize debug variables + initial + begin + error_count = 0; + verbose_msg = 0; + end + + + // count the number error + always @(error_detected) + begin + error_count = error_count + 1; + end + + + // enabling/disabling message + task msg_enable; + input [20*8:1] msg_src; + input msg_enable; + begin + verbose_msg = msg_enable; + if (msg_enable) + $display(" At time %t ** %s: enabling messages",$time, msg_src); + else + $display(" At time %t ** %s: disabling messages",$time, msg_src); + end + endtask // msg + + // generating message + task msg; + input [20*8:1] msg_src; + input [40*8:1] msg_text; + begin + if (verbose_msg) + $display(" At time %t ** %s: Msg: %s",$time, msg_src, msg_text); + end + endtask // msg + + // generating long message + task msgl; + input [40*8:1] msg_src; + input [80*8:1] msg_text; + begin + if (verbose_msg) + $display(" At time %t ** %s: Msg: %s",$time, msg_src, msg_text); + end + endtask // msg + + // generating the error message + task err; + input [20*8:1] err_src; + input [40*8:1] err_text; + begin + -> error_detected; + $display("Time %0d, %s Error: %s",$time, err_src, err_text); + end + endtask // err + + +task finish_test; +begin + + $display("****************************************"); + if ( error_count == 0 ) + $display("* TEST: PASSED"); + else + $display("* TEST: FAILED\n*\tError(s) = %d", error_count); + + $display("****************************************"); +end +endtask + + +endmodule // debug_proc +
diff --git a/verilog/dv/agents/usb_agents.v b/verilog/dv/agents/usb_agents.v new file mode 100644 index 0000000..c266567 --- /dev/null +++ b/verilog/dv/agents/usb_agents.v
@@ -0,0 +1,1010 @@ + +`define TOP user_usb_tb + +module usb_agent; + +//----------------------------------------------------------------- +// Defines: +//----------------------------------------------------------------- + +// Response values +`define USB_RES_OK 8'h0 +`define USB_RES_NAK 8'hFF +`define USB_RES_STALL 8'hFE +`define USB_RES_TIMEOUT 8'hFD + + +// USB PID values +`define PID_OUT 8'hE1 +`define PID_IN 8'h69 +`define PID_SOF 8'hA5 +`define PID_SETUP 8'h2D + +`define PID_DATA0 8'hC3 +`define PID_DATA1 8'h4B + +`define PID_ACK 8'hD2 +`define PID_NAK 8'h5A +`define PID_STALL 8'h1E + +// Standard requests (via SETUP packets) +`define REQ_GET_STATUS 8'h00 +`define REQ_CLEAR_FEATURE 8'h01 +`define REQ_SET_FEATURE 8'h03 +`define REQ_SET_ADDRESS 8'h05 +`define REQ_GET_DESCRIPTOR 8'h06 +`define REQ_SET_DESCRIPTOR 8'h07 +`define REQ_GET_CONFIGURATION 8'h08 +`define REQ_SET_CONFIGURATION 8'h09 +`define REQ_GET_INTERFACE 8'h0A +`define REQ_SET_INTERFACE 8'h0B +`define REQ_SYNC_FRAME 8'h0C + +// Descriptor types +`define DESC_DEVICE 8'h01 +`define DESC_CONFIGURATION 8'h02 +`define DESC_STRING 8'h03 +`define DESC_INTERFACE 8'h04 +`define DESC_ENDPOINT 8'h05 +`define DESC_DEV_QUALIFIER 8'h06 +`define DESC_OTHER_SPEED_CONF 8'h07 +`define DESC_IF_POWER 8'h08 + +// Device class +`define DEV_CLASS_RESERVED 8'h00 +`define DEV_CLASS_AUDIO 8'h01 +`define DEV_CLASS_COMMS 8'h02 +`define DEV_CLASS_HID 8'h03 +`define DEV_CLASS_MONITOR 8'h04 +`define DEV_CLASS_PHY_IF 8'h05 +`define DEV_CLASS_POWER 8'h06 +`define DEV_CLASS_PRINTER 8'h07 +`define DEV_CLASS_STORAGE 8'h08 +`define DEV_CLASS_HUB 8'h09 +`define DEV_CLASS_TMC 8'hFE +`define DEV_CLASS_VENDOR_CUSTOM 8'hFF + +// Device Requests (bmRequestType) +`define REQDIR_HOSTTODEVICE (0 << 7) +`define REQDIR_DEVICETOHOST (1 << 7) +`define REQTYPE_STANDARD (0 << 5) +`define REQTYPE_CLASS (1 << 5) +`define REQTYPE_VENDOR (2 << 5) +`define REQREC_DEVICE (0 << 0) +`define REQREC_INTERFACE (1 << 0) +`define REQREC_ENDPOINT (2 << 0) +`define REQREC_OTHER (3 << 0) + +// Endpoints +`define ENDPOINT_DIR_MASK (1 << 7) +`define ENDPOINT_DIR_IN (1 << 7) +`define ENDPOINT_DIR_OUT (0 << 7) +`define ENDPOINT_ADDR_MASK (8'h7F) +`define ENDPOINT_TYPE_MASK (8'h3) +`define ENDPOINT_TYPE_CONTROL (0) +`define ENDPOINT_TYPE_ISO (1) +`define ENDPOINT_TYPE_BULK (2) +`define ENDPOINT_TYPE_INTERRUPT (3) + + +//----------------------------------------------------------------- +// Defines: +//----------------------------------------------------------------- +`define USB_CTRL 8'h0 + `define USB_CTRL_TX_FLUSH 8 + `define USB_CTRL_TX_FLUSH_SHIFT 8 + `define USB_CTRL_TX_FLUSH_MASK 8'h1 + + `define USB_CTRL_PHY_DMPULLDOWN 7 + `define USB_CTRL_PHY_DMPULLDOWN_SHIFT 7 + `define USB_CTRL_PHY_DMPULLDOWN_MASK 8'h1 + + `define USB_CTRL_PHY_DPPULLDOWN 6 + `define USB_CTRL_PHY_DPPULLDOWN_SHIFT 6 + `define USB_CTRL_PHY_DPPULLDOWN_MASK 8'h1 + + `define USB_CTRL_PHY_TERMSELECT 5 + `define USB_CTRL_PHY_TERMSELECT_SHIFT 5 + `define USB_CTRL_PHY_TERMSELECT_MASK 8'h1 + + `define USB_CTRL_PHY_XCVRSELECT_SHIFT 3 + `define USB_CTRL_PHY_XCVRSELECT_MASK 8'h3 + + `define USB_CTRL_PHY_OPMODE_SHIFT 1 + `define USB_CTRL_PHY_OPMODE_MASK 8'h3 + + `define USB_CTRL_ENABLE_SOF 0 + `define USB_CTRL_ENABLE_SOF_SHIFT 0 + `define USB_CTRL_ENABLE_SOF_MASK 8'h1 + +`define USB_STATUS 8'h4 + `define USB_STATUS_SOF_TIME_SHIFT 16 + `define USB_STATUS_SOF_TIME_MASK 16'hffff + + `define USB_STATUS_RX_ERROR 2 + `define USB_STATUS_RX_ERROR_SHIFT 2 + `define USB_STATUS_RX_ERROR_MASK 8'h1 + + `define USB_STATUS_LINESTATE_BITS_SHIFT 0 + `define USB_STATUS_LINESTATE_BITS_MASK 8'h3 + +`define USB_IRQ_ACK 8'h8 + `define USB_IRQ_ACK_DEVICE_DETECT 3 + `define USB_IRQ_ACK_DEVICE_DETECT_SHIFT 3 + `define USB_IRQ_ACK_DEVICE_DETECT_MASK 8'h1 + + `define USB_IRQ_ACK_ERR 2 + `define USB_IRQ_ACK_ERR_SHIFT 2 + `define USB_IRQ_ACK_ERR_MASK 8'h1 + + `define USB_IRQ_ACK_DONE 1 + `define USB_IRQ_ACK_DONE_SHIFT 1 + `define USB_IRQ_ACK_DONE_MASK 8'h1 + + `define USB_IRQ_ACK_SOF 0 + `define USB_IRQ_ACK_SOF_SHIFT 0 + `define USB_IRQ_ACK_SOF_MASK 8'h1 + +`define USB_IRQ_STS 8'hc + `define USB_IRQ_STS_DEVICE_DETECT 3 + `define USB_IRQ_STS_DEVICE_DETECT_SHIFT 3 + `define USB_IRQ_STS_DEVICE_DETECT_MASK 8'h1 + + `define USB_IRQ_STS_ERR 2 + `define USB_IRQ_STS_ERR_SHIFT 2 + `define USB_IRQ_STS_ERR_MASK 8'h1 + + `define USB_IRQ_STS_DONE 1 + `define USB_IRQ_STS_DONE_SHIFT 1 + `define USB_IRQ_STS_DONE_MASK 8'h1 + + `define USB_IRQ_STS_SOF 0 + `define USB_IRQ_STS_SOF_SHIFT 0 + `define USB_IRQ_STS_SOF_MASK 8'h1 + +`define USB_IRQ_MASK 8'h10 + `define USB_IRQ_MASK_DEVICE_DETECT 3 + `define USB_IRQ_MASK_DEVICE_DETECT_SHIFT 3 + `define USB_IRQ_MASK_DEVICE_DETECT_MASK 8'h1 + + `define USB_IRQ_MASK_ERR 2 + `define USB_IRQ_MASK_ERR_SHIFT 2 + `define USB_IRQ_MASK_ERR_MASK 8'h1 + + `define USB_IRQ_MASK_DONE 1 + `define USB_IRQ_MASK_DONE_SHIFT 1 + `define USB_IRQ_MASK_DONE_MASK 8'h1 + + `define USB_IRQ_MASK_SOF 0 + `define USB_IRQ_MASK_SOF_SHIFT 0 + `define USB_IRQ_MASK_SOF_MASK 8'h1 + +`define USB_XFER_DATA 8'h14 + `define USB_XFER_DATA_TX_LEN_SHIFT 0 + `define USB_XFER_DATA_TX_LEN_MASK 16'hffff + +`define USB_XFER_TOKEN 8'h18 + `define USB_XFER_TOKEN_START 31 + `define USB_XFER_TOKEN_START_SHIFT 31 + `define USB_XFER_TOKEN_START_MASK 8'h1 + + `define USB_XFER_TOKEN_IN 30 + `define USB_XFER_TOKEN_IN_SHIFT 30 + `define USB_XFER_TOKEN_IN_MASK 8'h1 + + `define USB_XFER_TOKEN_ACK 29 + `define USB_XFER_TOKEN_ACK_SHIFT 29 + `define USB_XFER_TOKEN_ACK_MASK 8'h1 + + `define USB_XFER_TOKEN_PID_DATAX 28 + `define USB_XFER_TOKEN_PID_DATAX_SHIFT 28 + `define USB_XFER_TOKEN_PID_DATAX_MASK 8'h1 + + `define USB_XFER_TOKEN_PID_BITS_SHIFT 16 + `define USB_XFER_TOKEN_PID_BITS_MASK 8'hff + + `define USB_XFER_TOKEN_DEV_ADDR_SHIFT 9 + `define USB_XFER_TOKEN_DEV_ADDR_MASK 8'h7f + + `define USB_XFER_TOKEN_EP_ADDR_SHIFT 5 + `define USB_XFER_TOKEN_EP_ADDR_MASK 8'hf + +`define USB_RX_STAT 8'h1c + `define USB_RX_STAT_START_PEND 31 + `define USB_RX_STAT_START_PEND_SHIFT 31 + `define USB_RX_STAT_START_PEND_MASK 8'h1 + + `define USB_RX_STAT_CRC_ERR 30 + `define USB_RX_STAT_CRC_ERR_SHIFT 30 + `define USB_RX_STAT_CRC_ERR_MASK 8'h1 + + `define USB_RX_STAT_RESP_TIMEOUT 29 + `define USB_RX_STAT_RESP_TIMEOUT_SHIFT 29 + `define USB_RX_STAT_RESP_TIMEOUT_MASK 8'h1 + + `define USB_RX_STAT_IDLE 28 + `define USB_RX_STAT_IDLE_SHIFT 28 + `define USB_RX_STAT_IDLE_MASK 8'h1 + + `define USB_RX_STAT_RESP_BITS_SHIFT 16 + `define USB_RX_STAT_RESP_BITS_MASK 8'hff + + `define USB_RX_STAT_COUNT_BITS_SHIFT 0 + `define USB_RX_STAT_COUNT_BITS_MASK 16'hffff + +`define USB_WR_DATA 8'h20 + `define USB_WR_DATA_DATA_SHIFT 0 + `define USB_WR_DATA_DATA_MASK 8'hff + +`define USB_RD_DATA 8'h20 + `define USB_RD_DATA_DATA_SHIFT 0 + `define USB_RD_DATA_DATA_MASK 8'hff + + +task usbhw_reg_write; +input [7:0] addr; +input [31:0] wdata; +begin + `TOP.wb_user_core_write(`ADDR_SPACE_USB+addr,wdata); +end +endtask + +task usbhw_reg_read; +input [7:0] addr; +output [31:0] rdata; +begin + `TOP.wb_user_core_read(`ADDR_SPACE_USB+addr,rdata); +end +endtask + +parameter XMIT_BUF_SIZE = 64; // Xmitbuffer size +parameter RECV_BUF_SIZE = 64; // Recvbuffer size + + +reg [7:0] XmitBuffer [0 : XMIT_BUF_SIZE]; // Xmit buffer +reg [7:0] RecvBuffer [0 : RECV_BUF_SIZE]; // Recv buffer + +//----------------------------------------------------------------- +// usb_setup_packet: Create & send SETUP packet +//----------------------------------------------------------------- +task usb_setup_packet; +input [7:0] device_address; +input [7:0] request_type; +input [7:0] request; +input [15:0] value; +input [15:0] index; +input [15:0] length; +output status; +reg [7:0] status; +integer idx; +begin + + // bmRequestType: + // D7 Data Phase Transfer Direction + // 0 = Host to Device + // 1 = Device to Host + // D6..5 Type + // 0 = Standard + // 1 = Class + // 2 = Vendor + // 3 = Reserved + // D4..0 Recipient + // 0 = Device + // 1 = Interface + // 2 = Endpoint + // 3 = Other + // + idx = 0; + XmitBuffer[idx] = request_type; idx = idx+1; + XmitBuffer[idx] = request; idx = idx+1; + XmitBuffer[idx] = (value >> 0) & 8'hFF; idx = idx+1; + XmitBuffer[idx] = (value >> 8) & 8'hFF; idx = idx+1; + XmitBuffer[idx] = (index >> 0) & 8'hFF; idx = idx+1; + XmitBuffer[idx] = (index >> 8) & 8'hFF; idx = idx+1; + XmitBuffer[idx] = (length >> 0) & 8'hFF; idx = idx+1; + XmitBuffer[idx] = (length >> 8) & 8'hFF; idx = idx+1; + + // Send SETUP token + DATA0 (always DATA0) + usbhw_transfer_out(`PID_SETUP, device_address, 0, 1, `PID_DATA0, idx,status); + +end +endtask + +//----------------------------------------------------------------- +// SetAddress: Set device address +//----------------------------------------------------------------- +task setup; +input [7:0] device_address; +input [3:0] endpoint; +output [7:0]status; +begin + //$display("USB: Set device address %d\n", device_address); + // Send SETUP token + DATA0 (always DATA0) + usbhw_transfer_out(`PID_SETUP, device_address, endpoint, 1, `PID_DATA0, 8,status); + // Device has 50mS to apply the address + usbhw_timer_sleep(50); +end +endtask + +task printstatus; + input [3:0] RecvdStatus; + input [3:0] ExpStatus; +begin + $display(""); + $display(" #######################################################"); + if(RecvdStatus !== ExpStatus ) begin + -> `TOP.test_control.error_detected; + $display(" ERROR: Expected Status and Observed Status didn't match at %0d", $time); + if(ExpStatus==4'b0000) + $display(" Expected Status is ACK at %0d", $time); + else if(ExpStatus==4'b0001) + $display(" Expected Status is NACK at %0d", $time); + else if(ExpStatus==4'b0010) + $display(" Expected Status is STALL at %0d", $time); + else if(ExpStatus==4'b0011) + $display(" Expected Status is TIMEOUT at %0d", $time); + else if(ExpStatus==4'b0100) + $display(" Expected Status is INVALID RESPONSE at %0d", $time); + else if(ExpStatus==4'b0101) + $display(" Expected Status is CRC ERROR at %0d", $time); + end + + if(RecvdStatus==4'b0000) + $display(" Received Status is ACK at %0d", $time); + else if(RecvdStatus==4'b0001) + $display(" Received Status is NACK at %0d", $time); + else if(RecvdStatus==4'b0010) + $display(" Received Status is STALL at %0d", $time); + else if(RecvdStatus==4'b011) + $display(" Received Status is TIMEOUT at %0d", $time); + else if(RecvdStatus==4'b0100) + $display(" Received Status is INVALID RESPONSE at %0d", $time); + else if(RecvdStatus==4'b0101) + $display(" Received Status is CRC ERROR at %0d", $time); + $display(" #######################################################"); + $display(""); +end +endtask +//----------------------------------------------------------------- +// usbhw_reset: Perform USB reset +//----------------------------------------------------------------- +task usbhw_reset; +reg bflag; +begin + $display("HW: Applying USB Reset \n"); + // Assert SE0 / reset + usbhw_hub_reset; + + $display("HW: Reset Wait time Started \n"); + // Wait for some time + usbhw_timer_sleep(11); + + $display("HW: Reset Wait time Over \n"); + + // Stop asserting SE0, set data lines to Hi-Z + usbhw_hub_enable(0); + usbhw_timer_sleep(3); + + $display("HW: Waiting for device insertion\n"); + + // Wait for device detect + usbhw_hub_device_detected(bflag); + while (!bflag)begin + usbhw_hub_device_detected(bflag); + end + + $display("HW: Device detected\n"); + + // Enable SOF + usbhw_hub_enable(1); +end +endtask +//----------------------------------------------------------------- +// usbhw_hub_reset: Put bus into SE0 state (reset) +//----------------------------------------------------------------- +////////////////////////////////////////////////////////////////////////////////// +// +// SendReset : asserts a SE0 on the USB for the number of bit times specified +// by ResetTime. +// Input : ResetTime, number of bit times for which to drive a reset on +// the USB +// +//////////////////////////////////////////////////////////////////////////////// + +task usbhw_hub_reset; +reg [7:0] val; +begin + $display("HW: Enter USB bus reset\n"); + + // Power-up / SE0 + val = 0; + val = val | (0 << `USB_CTRL_PHY_XCVRSELECT_SHIFT); + val = val | (0 << `USB_CTRL_PHY_TERMSELECT_SHIFT); + val = val | (2 << `USB_CTRL_PHY_OPMODE_SHIFT); + val = val | (1 << `USB_CTRL_PHY_DPPULLDOWN_SHIFT); + val = val | (1 << `USB_CTRL_PHY_DMPULLDOWN_SHIFT); + usbhw_reg_write(`USB_CTRL, val); + +end +endtask + + +//----------------------------------------------------------------- +// usbhw_timer_sleep: Perform Sleep +//----------------------------------------------------------------- + +task usbhw_timer_sleep; +input [7:0] ResetTime; +reg [7:0] tskResetTime; +reg [7:0] tskResetTimeCounter; +begin + tskResetTimeCounter = 0; + tskResetTime = ResetTime; + forever @(posedge `TOP.usb_48mhz_clk) begin + tskResetTimeCounter = tskResetTimeCounter + 1'b1; + if (tskResetTimeCounter > tskResetTime) begin + @(posedge `TOP.usb_48mhz_clk); + @(posedge `TOP.usb_48mhz_clk); + disable usbhw_timer_sleep; + end + end +end +endtask + + +//----------------------------------------------------------------- +// usbhw_hub_enable: Enable root hub (drive data lines to HiZ) +// and optionally start SOF periods +//----------------------------------------------------------------- +task usbhw_hub_enable; +input enable_sof; +reg [7:0] val; +begin + $display("HW: Enable root hub\n"); + + // Host Full Speed + val = 0; + val = val | (1 << `USB_CTRL_PHY_XCVRSELECT_SHIFT); + val = val | (1 << `USB_CTRL_PHY_TERMSELECT_SHIFT); + val = val | (0 << `USB_CTRL_PHY_OPMODE_SHIFT); + val = val | (1 << `USB_CTRL_PHY_DPPULLDOWN_SHIFT); + val = val | (1 << `USB_CTRL_PHY_DMPULLDOWN_SHIFT); + val = val | (1 << `USB_CTRL_TX_FLUSH_SHIFT); + + // Enable SOF + if (enable_sof) + val = val | (1 << `USB_CTRL_ENABLE_SOF_SHIFT); + + usbhw_reg_write(`USB_CTRL, val); +end +endtask + + +//----------------------------------------------------------------- +// usbhw_hub_device_detected: Detect device inserted +//----------------------------------------------------------------- +task usbhw_hub_device_detected; +output bflag; +reg _usb_fs_device; +reg [31:0] status; +reg bflag; +begin + // Get line state + usbhw_reg_read(`USB_STATUS,status); + status = status >> `USB_STATUS_LINESTATE_BITS_SHIFT; + status = status & `USB_STATUS_LINESTATE_BITS_MASK; + + // FS: D+ pulled high + // LS: D- pulled high + _usb_fs_device = (status & 1); + if(status != 1) begin + $display("ERROR: USB Pull Up Status is not 1, Only Full Seed Supported"); + end else begin + $display("STATUS: USB Full Speed Detected"); + end + + bflag = (status != 0); +end +endtask + +task status_IN; +input [7:0] device_addr; +input [3:0] endpoint; +output [7:0] exit_code; +reg [7:0] exit_code; +reg [7:0] status; +reg [7:0] rx_count; +begin + usbhw_transfer_in(`PID_IN, device_addr, endpoint, status,exit_code,rx_count); +end +endtask + +task status_OUT; +input [7:0] device_addr; +input [3:0] endpoint; +output [7:0] status; +begin + usbhw_transfer_out(`PID_OUT, device_addr, endpoint, 1, `PID_OUT, 0,status); +end +endtask + +task control_OUT; +input [7:0] device_addr; +input [3:0] endpoint; +input [7:0] ByteCount; +output [7:0] status; +begin + usbhw_transfer_out(`PID_OUT, device_addr, endpoint, 1, `PID_DATA1, ByteCount,status); +end +endtask + +task control_IN; +input [7:0] device_addr; +input [3:0] endpoint; +input [7:0] ByteCount; +output [7:0] exit_code; +reg [7:0] exit_code; +reg [7:0] status; +reg [7:0] rx_count; +begin + usbhw_transfer_in(`PID_IN, device_addr, endpoint, status,exit_code,rx_count); +end +endtask + +task SetAddress; + input [6:0] address; +begin + XmitBuffer[0] = 8'b0000_0000; + XmitBuffer[1] = 8'b0000_0101; // SetAddress + XmitBuffer[2] = {1'b0, address}; + XmitBuffer[3] = 8'b0000_0000; + XmitBuffer[4] = 8'b0000_0000; + XmitBuffer[5] = 8'b0000_0000; + XmitBuffer[6] = 8'b0000_0000; + XmitBuffer[7] = 8'b0000_0000; +end +endtask + + +task SetConfiguration; + input [1:0] cfg_val; +begin + XmitBuffer[0] = 8'b0000_0000; + XmitBuffer[1] = 8'b0000_1001; // Set Configuration + XmitBuffer[2] = {6'b000_000, cfg_val}; + XmitBuffer[3] = 8'b0000_0000; + XmitBuffer[4] = 8'b0000_0000; + XmitBuffer[5] = 8'b0000_0000; + XmitBuffer[6] = 8'b0000_0000; + XmitBuffer[7] = 8'b0000_0000; +end +endtask + +task VenRegWordWr; + input [6:0] address; + input [31:0] reg_address; + input [31:0] dataword; + reg [7:0] Status; +begin + XmitBuffer[0] = 8'b0100_0000; + XmitBuffer[1] = 8'b0001_0000; + XmitBuffer[2] = reg_address[31:24]; + XmitBuffer[3] = reg_address[23:16]; + XmitBuffer[4] = reg_address[15:8]; + XmitBuffer[5] = reg_address[7:0]; + XmitBuffer[6] = 8'b0000_0100; + XmitBuffer[7] = 8'b0000_0000; + + setup (address, 4'h0, Status); + + XmitBuffer[0] = dataword[31:24]; + XmitBuffer[1] = dataword[23:16]; + XmitBuffer[2] = dataword[15:8]; + XmitBuffer[3] = dataword[7:0]; + + control_OUT(address, 4'h0, 4, Status); + status_IN (address, 4'h0, Status); +end +endtask + +task VenRegWordRd; + input [6:0] address; + input [31:0] reg_address; + output [31:0] dataword; + reg [31:0] ByteCount; + reg [7:0] Status; +begin + XmitBuffer[0] = 8'b1100_0000; + XmitBuffer[1] = 8'b0001_0001; + XmitBuffer[2] = reg_address[31:24]; + XmitBuffer[3] = reg_address[23:16]; + XmitBuffer[4] = reg_address[15:8]; + XmitBuffer[5] = reg_address[7:0]; + XmitBuffer[6] = 8'b0000_0100; + XmitBuffer[7] = 8'b0000_0000; + + setup (address, 4'h0, Status); + control_IN(address, 4'h0, ByteCount, Status); + if (Status != `PID_ACK) + control_IN(address, 4'h0, ByteCount, Status); + if (Status != `PID_ACK) + control_IN(address, 4'h0, ByteCount, Status); + dataword[7:0] = RecvBuffer[3]; + dataword[15:8] = RecvBuffer[2]; + dataword[23:16] = RecvBuffer[1]; + dataword[31:24] = RecvBuffer[0]; + dump_recv_buffer(ByteCount); + + status_OUT (address, 4'h0, Status); +end +endtask + +task VenRegWordRdCmp; + input [6:0] address; + input [31:0] reg_address; + input [31:0] dataword; + reg [31:0] ByteCount; + reg [31:0] ReadData; + reg [7:0] Status; +begin + XmitBuffer[0] = 8'b1100_0000; + XmitBuffer[1] = 8'b0001_0001; + XmitBuffer[2] = reg_address[31:24]; + XmitBuffer[3] = reg_address[23:16]; + XmitBuffer[4] = reg_address[15:8]; + XmitBuffer[5] = reg_address[7:0]; + XmitBuffer[6] = 8'b0000_0100; + XmitBuffer[7] = 8'b0000_0000; + + setup (address, 4'h0, Status); + control_IN(address, 4'h0, ByteCount, Status); + if (Status != `PID_ACK) + control_IN(address, 4'h0, ByteCount, Status); + if (Status != `PID_ACK) + control_IN(address, 4'h0, ByteCount, Status); + if ((RecvBuffer[3] !== dataword[7:0]) || (RecvBuffer[2] !== dataword[15:8]) + || (RecvBuffer[1] !== dataword[23:16]) || (RecvBuffer[0] !== dataword[31:24])) + begin + -> `TOP.test_control.error_detected; + $display( "usb_agent check: ERROR: Register Read Byte Mismatch !!! Address: %x Exp: %x ; Rxd: %x",reg_address,dataword[31:0], {RecvBuffer[0],RecvBuffer[1], RecvBuffer[2],RecvBuffer[3]} ); + dump_recv_buffer(ByteCount); + end else begin + $display( "usb_agent check: STATUS: Register Read Byte Match !!! Address: %x ; Rxd: %x",reg_address,{RecvBuffer[0],RecvBuffer[1], RecvBuffer[2],RecvBuffer[3]} ); + + end + + status_OUT (address, 4'h0, Status); +end +endtask +task VenRegHalfWordRd; + input [6:0] address; + input [21:0] reg_address; + input [15:0] dataword; + output [31:0] ByteCount; + reg [7:0] Status; +begin + XmitBuffer[0] = 8'b1100_0000; + XmitBuffer[1] = {2'b00,reg_address[21:16]}; + XmitBuffer[2] = reg_address[7:0]; + XmitBuffer[3] = reg_address[15:8]; + XmitBuffer[4] = 8'b0000_0000; + XmitBuffer[5] = 8'b0000_0000; + XmitBuffer[6] = 8'b0000_0010; + XmitBuffer[7] = 8'b0000_0000; + + setup (address, 4'h0, Status); + control_IN(address, 4'h0, ByteCount, Status); + if (Status != `PID_ACK) + control_IN(address, 4'h0, ByteCount, Status); + if (Status != `PID_ACK) + control_IN(address, 4'h0, ByteCount, Status); + if ((RecvBuffer[0] !== dataword[7:0]) || (RecvBuffer[1] !== dataword[15:8])) + begin + -> `TOP.test_control.error_detected; + $display( "usb_agent check: Register Read Byte Mismatch !!!"); + dump_recv_buffer(ByteCount); + end + status_OUT (address, 4'h0, Status); +end +endtask + +task VenRegByteRd; + input [6:0] address; + input [21:0] reg_address; + input [7:0] dataword; + output [31:0] ByteCount; + reg [7:0] Status; +begin + XmitBuffer[0] = 8'b1100_0000; + XmitBuffer[1] = {2'b00,reg_address[21:16]}; + XmitBuffer[2] = reg_address[7:0]; + XmitBuffer[3] = reg_address[15:8]; + XmitBuffer[4] = 8'b0000_0000; + XmitBuffer[5] = 8'b0000_0000; + XmitBuffer[6] = 8'b0000_0001; + XmitBuffer[7] = 8'b0000_0000; + + setup (address, 4'h0, Status); + control_IN(address, 4'h0, ByteCount, Status); + if (Status != `PID_ACK) + control_IN(address, 4'h0, ByteCount, Status); + if (Status != `PID_ACK) + control_IN(address, 4'h0, ByteCount, Status); + if ((RecvBuffer[0] !== dataword[7:0])) + begin + -> `TOP.test_control.error_detected; + $display( "usb_agent check: Register Read Byte Mismatch !!!"); + dump_recv_buffer(ByteCount); + end + status_OUT (address, 4'h0, Status); +end +endtask + +task VenRegWr; + input [21:0] reg_address; + input [2:0] length; +begin + XmitBuffer[0] = 8'b0100_0000; + XmitBuffer[1] = {2'b00,reg_address[21:16]}; + XmitBuffer[2] = reg_address[7:0]; + XmitBuffer[3] = reg_address[15:8]; + XmitBuffer[4] = 8'b0000_0000; + XmitBuffer[5] = 8'b0000_0000; + XmitBuffer[6] = {5'b0000_0,length}; + XmitBuffer[7] = 8'b0000_0000; + +end +endtask + +task VenRegRd; + input [21:0] reg_address; + input [2:0] length; +begin + XmitBuffer[0] = 8'b1100_0000; + XmitBuffer[1] = {2'b00,reg_address[21:16]}; + XmitBuffer[2] = reg_address[7:0]; + XmitBuffer[3] = reg_address[15:8]; + XmitBuffer[4] = 8'b0000_0000; + XmitBuffer[5] = 8'b0000_0000; + XmitBuffer[6] = {5'b0000_0,length}; + XmitBuffer[7] = 8'b0000_0000; +end +endtask + +task VenRegWrWordData; + input [7:0] Byte0; + input [7:0] Byte1; + input [7:0] Byte2; + input [7:0] Byte3; +begin + XmitBuffer[0] = Byte0; + XmitBuffer[1] = Byte1; + XmitBuffer[2] = Byte2; + XmitBuffer[3] = Byte3; +end +endtask + +task VenRegWrHWordData; + input [7:0] Byte0; + input [7:0] Byte1; +begin + XmitBuffer[0] = Byte0; + XmitBuffer[1] = Byte1; +end +endtask + +task VenRegWrByteData; + input [7:0] Byte0; +begin + XmitBuffer[0] = Byte0; +end +endtask + +task dump_recv_buffer; + input [31:0] NumBytes; + integer i; +begin + for(i=0; i < NumBytes; i=i+1) + $display("RecvBuffer[%0d] = %b : %0d", i, RecvBuffer[i], RecvBuffer[i]); +end +endtask + + +//----------------------------------------------------------------- +// usbhw_transfer_out: Send token then some DATA to the device +//----------------------------------------------------------------- +task usbhw_transfer_out; +input [7:0] pid; +input [7:0] device_addr; +input [3:0] endpoint; +input handshake; +input [7:0] request; +input [7:0] tx_length; +output [7:0] exit_code; + +reg [7:0] exit_code; + +reg [31:0] tdata; +integer l; +reg [31:0] token; +reg [31:0] ctrl; +reg [31:0] resp; +reg [31:0] status; +reg [31:0] status_chk; +begin + //$display("USB TOKEN: %s", (pid == `PID_SETUP) ? "SETUP" : (pid == `PID_DATA0) ? "DATA0": (pid == `PID_DATA1) ? "DATA1" : (pid == `PID_IN) ? "IN" : "OUT"); + //$display("USB DEV %d EP %d\n", device_addr, endpoint); + + // Load DATAx transfer into address 0+ + //$display(" USB Tx: %02x", request); + for (l=0;l<tx_length;l = l + 1) begin + tdata = XmitBuffer[l]; + //$display("USB TX DATA %02x", tdata); + usbhw_reg_write(`USB_WR_DATA, tdata); + end + + // Transfer data length + usbhw_reg_write(`USB_XFER_DATA, tx_length); + + // Configure transfer for DATAx portion + ctrl = (1 << `USB_XFER_TOKEN_START_SHIFT); + + // Wait for response or timeout + ctrl= ctrl | (handshake ? (1 << `USB_XFER_TOKEN_ACK_SHIFT) : 0); + + ctrl= ctrl | ((request == `PID_DATA1) ? (1 << `USB_XFER_TOKEN_PID_DATAX_SHIFT) : (0 << `USB_XFER_TOKEN_PID_DATAX_SHIFT)); + + // Setup token details (don't start transfer yet) + token = (pid<<`USB_XFER_TOKEN_PID_BITS_SHIFT) | (device_addr << `USB_XFER_TOKEN_DEV_ADDR_SHIFT) | (endpoint << `USB_XFER_TOKEN_EP_ADDR_SHIFT); + usbhw_reg_write(`USB_XFER_TOKEN, token | ctrl); + + // Wait for Tx to start + usbhw_reg_read(`USB_RX_STAT,status) ; + status_chk = status & (1 << `USB_RX_STAT_START_PEND_SHIFT); + while (status_chk) begin + usbhw_reg_read(`USB_RX_STAT,status) ; + status_chk = status & (1 << `USB_RX_STAT_START_PEND_SHIFT); + end + + // No handshaking? We are done + if (!handshake) begin + exit_code = `USB_RES_OK; + end + + // Wait for idle + usbhw_reg_read(`USB_RX_STAT,status) ; + status_chk = status & (1 << `USB_RX_STAT_IDLE_SHIFT) ; + while (!(status_chk)) begin + usbhw_reg_read(`USB_RX_STAT,status) ; + status_chk = status & (1 << `USB_RX_STAT_IDLE_SHIFT) ; + end + + $display("USB RESPONSE: %x",status); + + if (status & (1 << `USB_RX_STAT_RESP_TIMEOUT_SHIFT)) begin + $display(" USB TIMEOUT\n"); + $display("USB ERROR: OUT timeout\n"); + exit_code = `USB_RES_TIMEOUT; + end + + // Check for NAK / STALL + resp = ((status >> `USB_RX_STAT_RESP_BITS_SHIFT) & `USB_RX_STAT_RESP_BITS_MASK); + if (resp == `PID_ACK) begin + $display("USB STATUS: ACK\n"); + exit_code = `USB_RES_OK; + end else if (resp == `PID_NAK) begin + $display("USB STATUS: NAK\n"); + exit_code = `USB_RES_NAK; + end else if (resp == `PID_STALL) begin + $display("USB STATUS: STALL\n"); + $display("USB ERROR: OUT STALL\n"); + exit_code = `USB_RES_STALL; + end else begin + $display("USB ERROR: Unknown OUT response (%02x)\n", resp); + + // Unknown + exit_code = `USB_RES_STALL; + end +end +endtask + +//----------------------------------------------------------------- +// usbhw_transfer_in: Perform IN request and expect DATA from device +//----------------------------------------------------------------- +task usbhw_transfer_in; +input [7:0] pid; +input [7:0] device_addr; +input [7:0] endpoint; +output [7:0] response; +output [7:0] exit_code; +output [7:0] rx_count; + +reg [7:0] exit_code; +reg [7:0] response; +reg [7:0] rx_length; +integer l; +reg [7:0] rx_count; +reg [31:0] token; +reg [31:0] data; +reg [31:0] status; +reg [31:0] status_chk; +begin + //$display("USB TOKEN: %s", (pid == `PID_SETUP) ? "SETUP" : (pid == `PID_DATA0) ? "DATA0": (pid == `PID_DATA1) ? "DATA1" : (pid == `PID_IN) ? "IN" : "OUT"); + //$display("USB DEV %d EP %d\n", device_addr, endpoint); + + // No data to send + usbhw_reg_write(`USB_XFER_DATA, 0); + + // Configure transfer + token = (pid<<`USB_XFER_TOKEN_PID_BITS_SHIFT) | (device_addr << `USB_XFER_TOKEN_DEV_ADDR_SHIFT) | (endpoint << `USB_XFER_TOKEN_EP_ADDR_SHIFT); + token= token |(1 << `USB_XFER_TOKEN_START_SHIFT); + token= token | (1 << `USB_XFER_TOKEN_IN_SHIFT); + token= token | (1 << `USB_XFER_TOKEN_ACK_SHIFT); + //$display("USB TOKEN CONFIG : %x",token); + usbhw_reg_write(`USB_XFER_TOKEN, token); + + status_chk = status & (1 << `USB_RX_STAT_START_PEND); + while (status_chk) begin + usbhw_reg_read(`USB_RX_STAT,status); + status_chk = status & (1 << `USB_RX_STAT_START_PEND); + end + + // Wait for rx idle + usbhw_reg_read(`USB_RX_STAT,status); + status_chk = status & (1 << `USB_RX_STAT_IDLE_SHIFT); + while (!(status_chk)) begin + usbhw_reg_read(`USB_RX_STAT,status); + status_chk = status & (1 << `USB_RX_STAT_IDLE_SHIFT); + end + + if (status & (1 << `USB_RX_STAT_CRC_ERR_SHIFT)) begin + $display("USB: CRC ERROR\n"); + exit_code = `USB_RES_TIMEOUT; + end else if (status & (1 << `USB_RX_STAT_RESP_TIMEOUT_SHIFT)) begin + $display("USB: IN timeout\n"); + exit_code = `USB_RES_TIMEOUT; + end else begin + + // Check for NAK / STALL + response = ((status >> `USB_RX_STAT_RESP_BITS_SHIFT) & `USB_RX_STAT_RESP_BITS_MASK); + + if (response == `PID_NAK) begin + $display("USB NAK RECEIVED \n"); + exit_code = `USB_RES_NAK; + end else if (response == `PID_STALL) begin + $display("USB: IN STALL\n"); + exit_code = `USB_RES_STALL; + end else begin + + // Check CRC is ok + if (status & (1 << `USB_RX_STAT_CRC_ERR_SHIFT)) begin + $display("USB: CRC Error\n"); + exit_code = `USB_RES_STALL; + end else begin + + // How much data was actually received? + rx_count = ((status >> `USB_RX_STAT_COUNT_BITS_SHIFT) & `USB_RX_STAT_COUNT_BITS_MASK); + + //$display(" Rx %d (PID=%x):\n", rx_count, response); + + // Assert that user buffer is big enough for the response. + // NOTE: It's not critical to do this, but we can't easily check CRCs without + // reading the whole response into a buffer. + // Hitting this condition may point towards issues with higher level protocol + // implementation... + if(rx_length >= rx_count) + $display("USB ERROR Difference in rx len:%d and Rx Data Count: %d",rx_length,rx_count); + + for (l=0;l<rx_count;l=l+1) begin + usbhw_reg_read(`USB_RD_DATA,data); + //$display(" USB RX Cnt: %d Data: %02x", l, data); + RecvBuffer[l] = data; + end + exit_code = `USB_RES_OK; + end + end + end +end +endtask + +endmodule
diff --git a/verilog/dv/bfm/usb1d_defines.v b/verilog/dv/bfm/usb1d_defines.v new file mode 100755 index 0000000..dc60f4c --- /dev/null +++ b/verilog/dv/bfm/usb1d_defines.v
@@ -0,0 +1,143 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// USB 1.1 function defines file //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb1_funct///// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// +//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// +//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// +//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// +//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// +//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// +//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// +//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// +//// POSSIBILITY OF SUCH DAMAGE. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usb1d_defines.v,v 1.3 2002-09-25 06:06:49 rudi Exp $ +// +// $Date: 2002-09-25 06:06:49 $ +// $Revision: 1.3 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: not supported by cvs2svn $ +// Revision 1.2 2002/09/20 11:46:54 rudi +// fixed a type 'define' was missing ... +// +// Revision 1.1.1.1 2002/09/19 12:07:40 rudi +// Initial Checkin +// +// +// +// +// +// +// +// + + +//`define USBF_DEBUG +//`define USBF_VERBOSE_DEBUG + +// Enable or disable Block Frames +//`define USB1_BF_ENABLE + +///////////////////////////////////////////////////////////////////// +// +// Items below this point should NOT be modified by the end user +// UNLESS you know exactly what you are doing ! +// Modify at you own risk !!! +// +///////////////////////////////////////////////////////////////////// + +`define ROM_SIZE0 7'd018 // Device Descriptor Length +`define ROM_SIZE1 7'd053 // Configuration Descriptor Length +`define ROM_SIZE2A 7'd004 // Language ID Descriptor Start Length +`define ROM_SIZE2B 7'd010 // String Descriptor Length +`define ROM_SIZE2C 7'd010 // for future use +`define ROM_SIZE2D 7'd010 // for future use + +`define ROM_START0 7'h00 // Device Descriptor Start Address +`define ROM_START1 7'h12 // Configuration Descriptor Start Address +`define ROM_START2A 7'h47 // Language ID Descriptor Start Address +`define ROM_START2B 7'h50 // String Descriptor Start Address +`define ROM_START2C 7'h60 // for future use +`define ROM_START2D 7'h70 // for future use + +// Endpoint Configuration Constants +`define IN 14'b00_001_000000000 +`define OUT 14'b00_010_000000000 +`define CTRL 14'b10_100_000000000 +`define ISO 14'b01_000_000000000 +`define BULK 14'b10_000_000000000 +`define INT 14'b00_000_000000000 + +// PID Encodings +`define USBF_T_PID_OUT 4'b0001 +`define USBF_T_PID_IN 4'b1001 +`define USBF_T_PID_SOF 4'b0101 +`define USBF_T_PID_SETUP 4'b1101 +`define USBF_T_PID_DATA0 4'b0011 +`define USBF_T_PID_DATA1 4'b1011 +`define USBF_T_PID_DATA2 4'b0111 +`define USBF_T_PID_MDATA 4'b1111 +`define USBF_T_PID_ACK 4'b0010 +`define USBF_T_PID_NACK 4'b1010 +`define USBF_T_PID_STALL 4'b1110 +`define USBF_T_PID_NYET 4'b0110 +`define USBF_T_PID_PRE 4'b1100 +`define USBF_T_PID_ERR 4'b1100 +`define USBF_T_PID_SPLIT 4'b1000 +`define USBF_T_PID_PING 4'b0100 +`define USBF_T_PID_RES 4'b0000 + +// The HMS_DEL is a constant for the "Half Micro Second" +// Clock pulse generator. This constant specifies how many +// Phy clocks there are between two hms_clock pulses. This +// constant plus 2 represents the actual delay. +// Example: For a 60 Mhz (16.667 nS period) Phy Clock, the +// delay must be 30 phy clock: 500ns / 16.667nS = 30 clocks +`define USBF_HMS_DEL 5'h16 + +// After sending Data in response to an IN token from host, the +// host must reply with an ack. The host has 622nS in Full Speed +// mode and 400nS in High Speed mode to reply. RX_ACK_TO_VAL_FS +// and RX_ACK_TO_VAL_HS are the numbers of UTMI clock cycles +// minus 2 for Full and High Speed modes. +//`define USBF_RX_ACK_TO_VAL_FS 8'd36 +`define USBF_RX_ACK_TO_VAL_FS 8'd200 + +// After sending a OUT token the host must send a data packet. +// The host has 622nS in Full Speed mode and 400nS in High Speed +// mode to send the data packet. +// TX_DATA_TO_VAL_FS and TX_DATA_TO_VAL_HS are is the numbers of +// UTMI clock cycles minus 2. +//`define USBF_TX_DATA_TO_VAL_FS 8'd36 +`define USBF_TX_DATA_TO_VAL_FS 8'd200
diff --git a/verilog/dv/bfm/usb_device/core/usb1d_core.v b/verilog/dv/bfm/usb_device/core/usb1d_core.v new file mode 100755 index 0000000..73f9ea1 --- /dev/null +++ b/verilog/dv/bfm/usb_device/core/usb1d_core.v
@@ -0,0 +1,711 @@ +/********************************************************************** +* Ported to USB2UART Project +* Author: Dinesh Annayya +* Email:- dinesha@opencores.org +* +* Date: 4th Feb 2013 +* Changes: +* A. Warning Clean Up +* B. USB1-phy is move to core level +* +**********************************************************************/ +///////////////////////////////////////////////////////////////////// +//// //// +//// USB 1.1 function IP core //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb1_funct///// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// +//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// +//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// +//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// +//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// +//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// +//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// +//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// +//// POSSIBILITY OF SUCH DAMAGE. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usb1_core.v,v 1.2 2002-10-11 05:48:20 rudi Exp $ +// +// $Date: 2002-10-11 05:48:20 $ +// $Revision: 1.2 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: not supported by cvs2svn $ +// Revision 1.1 2002/09/25 06:06:49 rudi +// - Added New Top Level +// - Remove old top level and associated files +// - Moved FIFOs to "Generic FIFOs" project +// +// +// +// +// +// +// + +`include "usb1d_defines.v" + +/* + + // USB PHY Interface + tx_dp, tx_dn, tx_oe, + rx_d, rx_dp, rx_dn, +These pins are a semi-standard interface to USB 1.1 transceivers. +Just match up the signal names with the IOs of the transceiver. + + // USB Misc + phy_tx_mode, usb_rst, +The PHY supports single ended and differential output to the +transceiver Depending on which device you are using, you have +to tie the phy_tx_mode high or low. +usb_rst is asserted whenever the host signals reset on the USB +bus. The USB core will internally reset itself automatically. +This output is provided for external logic that needs to be +reset when the USB bus is reset. + + // Interrupts + dropped_frame, misaligned_frame, + crc16_err, +dropped_frame, misaligned_frame are interrupt to indicate error +conditions in Block Frame mode. +crc16_err, indicates when a crc 16 error was detected on the +payload of a USB packet. + + // Vendor Features + v_set_int, v_set_feature, wValue, + wIndex, vendor_data, +This signals allow to control vendor specific registers and logic +that can be manipulated and monitored via the control endpoint +through vendor defined commands. + + // USB Status + usb_busy, ep_sel, +usb_busy is asserted when the USB core is busy transferring +data ep_sel indicated the endpoint that is currently busy. +This information might be useful if one desires to reset/clear +the attached FIFOs and want to do this when the endpoint is idle. + + // Endpoint Interface +This implementation supports 8 endpoints. Endpoint 0 is the +control endpoint and used internally. Endpoints 1-7 are available +to the user. replace 'N' with the endpoint number. + + epN_cfg, +This is a constant input used to configure the endpoint by ORing +these defines together and adding the max packet size for this +endpoint: +`IN and `OUT select the transfer direction for this endpoint +`ISO, `BULK and `INT determine the endpoint type + +Example: "`BULK | `IN | 14'd064" defines a BULK IN endpoint with +max packet size of 64 bytes + + epN_din, epN_we, epN_full, +This is the OUT FIFO interface. If this is a IN endpoint, ground +all unused inputs and leave outputs unconnected. + + epN_dout, epN_re, epN_empty, +this is the IN FIFO interface. If this is a OUT endpoint ground +all unused inputs and leave outputs unconnected. + + epN_bf_en, epN_bf_size, +These two constant configure the Block Frame feature. + +*/ + + +module usb1d_core(clk_i, rst_i, + + // UTMI Interface + DataOut, TxValid, TxReady, RxValid, + RxActive, RxError, DataIn, LineState, + // USB Misc + phy_tx_mode, usb_rst, + + // Interrupts + dropped_frame, misaligned_frame, + crc16_err, + + // Vendor Features + v_set_int, v_set_feature, wValue, + wIndex, vendor_data, + + // USB Status + usb_busy, ep_sel, + + // Endpoint Interface + ep1_cfg, + ep1_din, ep1_we, ep1_full, + ep1_dout, ep1_re, ep1_empty, + ep1_bf_en, ep1_bf_size, + + ep2_cfg, + ep2_din, ep2_we, ep2_full, + ep2_dout, ep2_re, ep2_empty, + ep2_bf_en, ep2_bf_size, + + ep3_cfg, + ep3_din, ep3_we, ep3_full, + ep3_dout, ep3_re, ep3_empty, + ep3_bf_en, ep3_bf_size, + + ep4_cfg, + ep4_din, ep4_we, ep4_full, + ep4_dout, ep4_re, ep4_empty, + ep4_bf_en, ep4_bf_size, + + ep5_cfg, + ep5_din, ep5_we, ep5_full, + ep5_dout, ep5_re, ep5_empty, + ep5_bf_en, ep5_bf_size, + + ep6_cfg, + ep6_din, ep6_we, ep6_full, + ep6_dout, ep6_re, ep6_empty, + ep6_bf_en, ep6_bf_size, + + ep7_cfg, + ep7_din, ep7_we, ep7_full, + ep7_dout, ep7_re, ep7_empty, + ep7_bf_en, ep7_bf_size, + + // Register Interface + reg_addr, + reg_rdwrn, + reg_req, + reg_wdata, + reg_rdata, + reg_ack + + ); + +input clk_i; +input rst_i; +//------------------------------------ +// UTMI Interface +// ----------------------------------- +output [7:0] DataOut; +output TxValid; +input TxReady; +input [7:0] DataIn; +input RxValid; +input RxActive; +input RxError; +input [1:0] LineState; + +input phy_tx_mode; +input usb_rst; +output dropped_frame, misaligned_frame; +output crc16_err; + +output v_set_int; +output v_set_feature; +output [15:0] wValue; +output [15:0] wIndex; +input [15:0] vendor_data; + +output usb_busy; +output [3:0] ep_sel; + +//----------------------------------- +// Register Interface +// ---------------------------------- +output [31:0] reg_addr; // Register Address +output reg_rdwrn; // 0 -> write, 1-> read +output reg_req; // Register Req +output [31:0] reg_wdata; // Register write data +input [31:0] reg_rdata; // Register Read Data +input reg_ack; // Register Ack + +// Endpoint Interfaces +input [13:0] ep1_cfg; +input [7:0] ep1_din; +output [7:0] ep1_dout; +output ep1_we, ep1_re; +input ep1_empty, ep1_full; +input ep1_bf_en; +input [6:0] ep1_bf_size; + +input [13:0] ep2_cfg; +input [7:0] ep2_din; +output [7:0] ep2_dout; +output ep2_we, ep2_re; +input ep2_empty, ep2_full; +input ep2_bf_en; +input [6:0] ep2_bf_size; + +input [13:0] ep3_cfg; +input [7:0] ep3_din; +output [7:0] ep3_dout; +output ep3_we, ep3_re; +input ep3_empty, ep3_full; +input ep3_bf_en; +input [6:0] ep3_bf_size; + +input [13:0] ep4_cfg; +input [7:0] ep4_din; +output [7:0] ep4_dout; +output ep4_we, ep4_re; +input ep4_empty, ep4_full; +input ep4_bf_en; +input [6:0] ep4_bf_size; + +input [13:0] ep5_cfg; +input [7:0] ep5_din; +output [7:0] ep5_dout; +output ep5_we, ep5_re; +input ep5_empty, ep5_full; +input ep5_bf_en; +input [6:0] ep5_bf_size; + +input [13:0] ep6_cfg; +input [7:0] ep6_din; +output [7:0] ep6_dout; +output ep6_we, ep6_re; +input ep6_empty, ep6_full; +input ep6_bf_en; +input [6:0] ep6_bf_size; + +input [13:0] ep7_cfg; +input [7:0] ep7_din; +output [7:0] ep7_dout; +output ep7_we, ep7_re; +input ep7_empty, ep7_full; +input ep7_bf_en; +input [6:0] ep7_bf_size; + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +wire [7:0] rx_data; +wire rx_valid, rx_active, rx_err; +wire [7:0] tx_data; +wire tx_valid; +wire tx_ready; +wire tx_first; +wire tx_valid_last; + +// Internal Register File Interface +wire [6:0] funct_adr; // This functions address (set by controller) +wire [3:0] ep_sel; // Endpoint Number Input +wire crc16_err; // Set CRC16 error interrupt +wire int_to_set; // Set time out interrupt +wire int_seqerr_set; // Set PID sequence error interrupt +wire [31:0] frm_nat; // Frame Number and Time Register +wire nse_err; // No Such Endpoint Error +wire pid_cs_err; // PID CS error +wire crc5_err; // CRC5 Error + +reg [7:0] tx_data_st; +wire [7:0] rx_ctrl_data; +wire [7:0] rx_ctrl_data_d; +reg [13:0] cfg; +wire rx_ctrl_dvalid; +wire rx_ctrl_ddone; +wire idma_re; +wire idma_we; +reg ep_empty; +reg ep_full; +wire [7:0] rx_size; +wire rx_done; + +wire [7:0] ep0_din; +wire [7:0] ep0_dout; +wire ep0_re, ep0_we; +wire [13:0] ep0_cfg; +wire [7:0] ep0_size; +wire [7:0] ep0_ctrl_dout, ep0_ctrl_din; +wire ep0_ctrl_re, ep0_ctrl_we; +wire [3:0] ep0_ctrl_stat; + +wire ctrl_setup, ctrl_in, ctrl_out; +wire send_stall; +wire token_valid; +reg rst_local; // internal reset +wire dropped_frame; +wire misaligned_frame; +wire v_set_int; +wire v_set_feature; +wire [15:0] wValue; +wire [15:0] wIndex; + +reg ep_bf_en; +reg [6:0] ep_bf_size; +wire [6:0] rom_adr; +wire [7:0] rom_data; + +wire ep0_full; +wire ep0_empty; + +/////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +// Endpoint type and Max transfer size +assign ep0_cfg = `CTRL | ep0_size; + +always @(posedge clk_i) + rst_local <= #1 rst_i & ~usb_rst; + +/////////////////////////////////////////////////////////////////// +// +// Module Instantiations +// +/******* Move to phy logic is move to core level +usb_phy phy( + .clk( clk_i ), + .rst( rst_i ), // ONLY external reset + .phy_tx_mode( phy_tx_mode ), + .usb_rst( usb_rst ), + + // Transceiver Interface + .rxd( rx_d ), + .rxdp( rx_dp ), + .rxdn( rx_dn ), + .txdp( tx_dp ), + .txdn( tx_dn ), + .txoe( tx_oe ), + + // UTMI Interface + .DataIn_o( DataIn ), + .RxValid_o( RxValid ), + .RxActive_o( RxActive ), + .RxError_o( RxError ), + .DataOut_i( DataOut ), + .TxValid_i( TxValid ), + .TxReady_o( TxReady ), + .LineState_o( LineState ) + ); +*******************************/ +// UTMI Interface +usb1d_utmi_if u0( + .phy_clk( clk_i ), + .rst( rst_local ), + // Interface towards Phy-Tx + .DataOut( DataOut ), + .TxValid( TxValid ), + .TxReady( TxReady ), + + // Interface towards Phy-rx + .RxValid( RxValid ), + .RxActive( RxActive ), + .RxError( RxError ), + .DataIn( DataIn ), + + // Interfcae towards protocol layer-rx + .rx_data( rx_data ), + .rx_valid( rx_valid ), + .rx_active( rx_active ), + .rx_err( rx_err ), + + // Interfcae towards protocol layer-tx + .tx_data( tx_data ), + .tx_valid( tx_valid ), + .tx_valid_last( tx_valid_last ), + .tx_ready( tx_ready ), + .tx_first( tx_first ) + ); + +// Protocol Layer +usb1d_pl u1( .clk( clk_i ), + .rst( rst_local ), + // Interface towards utmi-rx + .rx_data( rx_data ), + .rx_valid( rx_valid ), + .rx_active( rx_active ), + .rx_err( rx_err ), + + // Interface towards utmi-tx + .tx_data( tx_data ), + .tx_valid( tx_valid ), + .tx_valid_last( tx_valid_last ), + .tx_ready( tx_ready ), + .tx_first( tx_first ), + + // Interface towards usb-phy-tx + .tx_valid_out( TxValid ), + + // unused outputs + .token_valid( token_valid ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .pid_cs_err( pid_cs_err ), + .nse_err( nse_err ), + .crc5_err( crc5_err ), + .rx_size( rx_size ), + .rx_done( rx_done ), + + // Interface towards usb-ctrl + .fa( funct_adr ), + .frm_nat( frm_nat ), + .ctrl_setup( ctrl_setup ), + .ctrl_in( ctrl_in ), + .ctrl_out( ctrl_out ), + .send_stall( send_stall ), + + // usb-status + .ep_sel( ep_sel ), + .x_busy( usb_busy ), + .int_crc16_set( crc16_err ), + .dropped_frame( dropped_frame ), + .misaligned_frame( misaligned_frame ), + + .ep_bf_en( ep_bf_en ), + .ep_bf_size( ep_bf_size ), + .csr( cfg ), + .tx_data_st( tx_data_st ), + + .rx_ctrl_data (rx_ctrl_data ), + .rx_ctrl_data_d (rx_ctrl_data_d ), + .rx_ctrl_dvalid (rx_ctrl_dvalid ), + .rx_ctrl_ddone (rx_ctrl_ddone ), + + .idma_re( idma_re ), + .idma_we( idma_we ), + .ep_empty( ep_empty ), + .ep_full( ep_full ) + ); + +usb1d_ctrl u4( .clk( clk_i ), + .rst( rst_local ), + + .rom_adr( rom_adr ), + .rom_data( rom_data ), + + .ctrl_setup( ctrl_setup ), + .ctrl_in( ctrl_in ), + .ctrl_out( ctrl_out ), + + .rx_ctrl_data (rx_ctrl_data ), + .rx_ctrl_dvalid (rx_ctrl_dvalid ), + .rx_ctrl_ddone (rx_ctrl_ddone ), + + + .ep0_din( ep0_ctrl_dout ), + .ep0_dout( ep0_ctrl_din ), + .ep0_re( ep0_ctrl_re ), + .ep0_we( ep0_ctrl_we ), + .ep0_stat( ep0_ctrl_stat ), + .ep0_size( ep0_size ), + + .send_stall( send_stall ), + .frame_no( frm_nat[26:16] ), + .funct_adr( funct_adr ), + .configured( ), + .halt( ), + + .v_set_int( v_set_int ), + .v_set_feature( v_set_feature ), + .wValue( wValue ), + .wIndex( wIndex ), + .vendor_data( vendor_data ), + + // Register Interface + .reg_addr (reg_addr), + .reg_rdwrn (reg_rdwrn), + .reg_req (reg_req), + .reg_wdata (reg_wdata), + .reg_rdata (reg_rdata), + .reg_ack (reg_ack) + + ); + + +usb1d_rom1 rom1( .clk( clk_i ), + .adr( rom_adr ), + .dout( rom_data ) + ); + +// CTRL Endpoint FIFO +/************* +usb1d_generic_fifo #(8,6,0) u10( + .clk( clk_i ), + .rst( rst_i ), + .clr( usb_rst ), + .din( rx_ctrl_data_d ), + .we( ep0_we ), + .dout( ep0_ctrl_dout ), + .re( ep0_ctrl_re ), + .full_r( ), + .empty_r( ), + .full( ep0_full ), + .empty( ep0_ctrl_stat[1] ), + .full_n( ), + .empty_n( ), + .full_n_r( ), + .empty_n_r( ), + .level( ) + ); + +*************/ +// CTRL Endpoint FIFO +usb1d_sync_fifo #(8,8) u10( + .clk (clk_i), + .reset_n (rst_i), + .clr (usb_rst), + .wr_en (ep0_we), + .wr_data (rx_ctrl_data_d), + .full (ep0_full), + .empty (ep0_ctrl_stat[1]), + .rd_en (ep0_ctrl_re), + .rd_data (ep0_ctrl_dout) + ); +usb1d_generic_fifo #(8,6,0) u11( + .clk( clk_i ), + .rst( rst_i ), + .clr( usb_rst ), + .din( ep0_ctrl_din ), + .we( ep0_ctrl_we ), + .dout( ep0_dout ), + .re( ep0_re ), + .full_r( ), + .empty_r( ), + .full( ep0_ctrl_stat[2] ), + .empty( ep0_empty ), + .full_n( ), + .empty_n( ), + .full_n_r( ), + .empty_n_r( ), + .level( ) + ); + + +/////////////////////////////////////////////////////////////////// +// +// Endpoint FIFO Interfaces +// + +always @(ep_sel or ep0_cfg or ep1_cfg or ep2_cfg or ep3_cfg or + ep4_cfg or ep5_cfg or ep6_cfg or ep7_cfg) + case(ep_sel) // synopsys full_case parallel_case + 4'h0: cfg = ep0_cfg; + 4'h1: cfg = ep1_cfg; + 4'h2: cfg = ep2_cfg; + 4'h3: cfg = ep3_cfg; + 4'h4: cfg = ep4_cfg; + 4'h5: cfg = ep5_cfg; + 4'h6: cfg = ep6_cfg; + 4'h7: cfg = ep7_cfg; + endcase + +// In endpoints only +always @(posedge clk_i) + case(ep_sel) // synopsys full_case parallel_case + 4'h0: tx_data_st <= #1 ep0_dout; + 4'h1: tx_data_st <= #1 ep1_din; + 4'h2: tx_data_st <= #1 ep2_din; + 4'h3: tx_data_st <= #1 ep3_din; + 4'h4: tx_data_st <= #1 ep4_din; + 4'h5: tx_data_st <= #1 ep5_din; + 4'h6: tx_data_st <= #1 ep6_din; + 4'h7: tx_data_st <= #1 ep7_din; + endcase + +// In endpoints only +always @(posedge clk_i) + case(ep_sel) // synopsys full_case parallel_case + 4'h0: ep_empty <= #1 ep0_empty; + 4'h1: ep_empty <= #1 ep1_empty; + 4'h2: ep_empty <= #1 ep2_empty; + 4'h3: ep_empty <= #1 ep3_empty; + 4'h4: ep_empty <= #1 ep4_empty; + 4'h5: ep_empty <= #1 ep5_empty; + 4'h6: ep_empty <= #1 ep6_empty; + 4'h7: ep_empty <= #1 ep7_empty; + endcase + +// OUT endpoints only +always @(ep_sel or ep0_full or ep1_full or ep2_full or ep3_full or + ep4_full or ep5_full or ep6_full or ep7_full) + case(ep_sel) // synopsys full_case parallel_case + 4'h0: ep_full = ep0_full; + 4'h1: ep_full = ep1_full; + 4'h2: ep_full = ep2_full; + 4'h3: ep_full = ep3_full; + 4'h4: ep_full = ep4_full; + 4'h5: ep_full = ep5_full; + 4'h6: ep_full = ep6_full; + 4'h7: ep_full = ep7_full; + endcase + +always @(posedge clk_i) + case(ep_sel) // synopsys full_case parallel_case + 4'h0: ep_bf_en = 1'b0; + 4'h1: ep_bf_en = ep1_bf_en; + 4'h2: ep_bf_en = ep2_bf_en; + 4'h3: ep_bf_en = ep3_bf_en; + 4'h4: ep_bf_en = ep4_bf_en; + 4'h5: ep_bf_en = ep5_bf_en; + 4'h6: ep_bf_en = ep6_bf_en; + 4'h7: ep_bf_en = ep7_bf_en; + endcase + +always @(posedge clk_i) + case(ep_sel) // synopsys full_case parallel_case + 4'h1: ep_bf_size = ep1_bf_size; + 4'h2: ep_bf_size = ep2_bf_size; + 4'h3: ep_bf_size = ep3_bf_size; + 4'h4: ep_bf_size = ep4_bf_size; + 4'h5: ep_bf_size = ep5_bf_size; + 4'h6: ep_bf_size = ep6_bf_size; + 4'h7: ep_bf_size = ep7_bf_size; + endcase + +assign ep1_dout = rx_ctrl_data_d; +assign ep2_dout = rx_ctrl_data_d; +assign ep3_dout = rx_ctrl_data_d; +assign ep4_dout = rx_ctrl_data_d; +assign ep5_dout = rx_ctrl_data_d; +assign ep6_dout = rx_ctrl_data_d; +assign ep7_dout = rx_ctrl_data_d; + +assign ep0_re = idma_re & (ep_sel == 4'h0); +assign ep1_re = idma_re & (ep_sel == 4'h1) & !ep1_empty; +assign ep2_re = idma_re & (ep_sel == 4'h2) & !ep2_empty; +assign ep3_re = idma_re & (ep_sel == 4'h3) & !ep3_empty; +assign ep4_re = idma_re & (ep_sel == 4'h4) & !ep4_empty; +assign ep5_re = idma_re & (ep_sel == 4'h5) & !ep5_empty; +assign ep6_re = idma_re & (ep_sel == 4'h6) & !ep6_empty; +assign ep7_re = idma_re & (ep_sel == 4'h7) & !ep7_empty; + +assign ep0_we = idma_we & (ep_sel == 4'h0); +assign ep1_we = idma_we & (ep_sel == 4'h1) & !ep1_full; +assign ep2_we = idma_we & (ep_sel == 4'h2) & !ep2_full; +assign ep3_we = idma_we & (ep_sel == 4'h3) & !ep3_full; +assign ep4_we = idma_we & (ep_sel == 4'h4) & !ep4_full; +assign ep5_we = idma_we & (ep_sel == 4'h5) & !ep5_full; +assign ep6_we = idma_we & (ep_sel == 4'h6) & !ep6_full; +assign ep7_we = idma_we & (ep_sel == 4'h7) & !ep7_full; + +endmodule
diff --git a/verilog/dv/bfm/usb_device/core/usb1d_crc16.v b/verilog/dv/bfm/usb_device/core/usb1d_crc16.v new file mode 100755 index 0000000..acee4d7 --- /dev/null +++ b/verilog/dv/bfm/usb_device/core/usb1d_crc16.v
@@ -0,0 +1,98 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// USB CRC16 Modules //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb1_funct///// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// +//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// +//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// +//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// +//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// +//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// +//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// +//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// +//// POSSIBILITY OF SUCH DAMAGE. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usb1_crc16.v,v 1.1.1.1 2002-09-19 12:07:39 rudi Exp $ +// +// $Date: 2002-09-19 12:07:39 $ +// $Revision: 1.1.1.1 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: not supported by cvs2svn $ +// +// +// +// +// +// +// + +`include "usb1d_defines.v" + +/////////////////////////////////////////////////////////////////// +// +// CRC16 +// +/////////////////////////////////////////////////////////////////// + +module usb1d_crc16(crc_in, din, crc_out); +input [15:0] crc_in; +input [7:0] din; +output [15:0] crc_out; + +assign crc_out[0] = din[7] ^ din[6] ^ din[5] ^ din[4] ^ din[3] ^ + din[2] ^ din[1] ^ din[0] ^ crc_in[8] ^ crc_in[9] ^ + crc_in[10] ^ crc_in[11] ^ crc_in[12] ^ crc_in[13] ^ + crc_in[14] ^ crc_in[15]; +assign crc_out[1] = din[7] ^ din[6] ^ din[5] ^ din[4] ^ din[3] ^ din[2] ^ + din[1] ^ crc_in[9] ^ crc_in[10] ^ crc_in[11] ^ + crc_in[12] ^ crc_in[13] ^ crc_in[14] ^ crc_in[15]; +assign crc_out[2] = din[1] ^ din[0] ^ crc_in[8] ^ crc_in[9]; +assign crc_out[3] = din[2] ^ din[1] ^ crc_in[9] ^ crc_in[10]; +assign crc_out[4] = din[3] ^ din[2] ^ crc_in[10] ^ crc_in[11]; +assign crc_out[5] = din[4] ^ din[3] ^ crc_in[11] ^ crc_in[12]; +assign crc_out[6] = din[5] ^ din[4] ^ crc_in[12] ^ crc_in[13]; +assign crc_out[7] = din[6] ^ din[5] ^ crc_in[13] ^ crc_in[14]; +assign crc_out[8] = din[7] ^ din[6] ^ crc_in[0] ^ crc_in[14] ^ crc_in[15]; +assign crc_out[9] = din[7] ^ crc_in[1] ^ crc_in[15]; +assign crc_out[10] = crc_in[2]; +assign crc_out[11] = crc_in[3]; +assign crc_out[12] = crc_in[4]; +assign crc_out[13] = crc_in[5]; +assign crc_out[14] = crc_in[6]; +assign crc_out[15] = din[7] ^ din[6] ^ din[5] ^ din[4] ^ din[3] ^ din[2] ^ + din[1] ^ din[0] ^ crc_in[7] ^ crc_in[8] ^ crc_in[9] ^ + crc_in[10] ^ crc_in[11] ^ crc_in[12] ^ crc_in[13] ^ + crc_in[14] ^ crc_in[15]; + +endmodule +
diff --git a/verilog/dv/bfm/usb_device/core/usb1d_crc5.v b/verilog/dv/bfm/usb_device/core/usb1d_crc5.v new file mode 100755 index 0000000..4aec0d2 --- /dev/null +++ b/verilog/dv/bfm/usb_device/core/usb1d_crc5.v
@@ -0,0 +1,89 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// USB CRC5 Modules //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb1_funct///// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// +//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// +//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// +//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// +//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// +//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// +//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// +//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// +//// POSSIBILITY OF SUCH DAMAGE. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usb1_crc5.v,v 1.1.1.1 2002-09-19 12:07:05 rudi Exp $ +// +// $Date: 2002-09-19 12:07:05 $ +// $Revision: 1.1.1.1 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: not supported by cvs2svn $ +// +// +// +// +// +// +// + +`include "usb1d_defines.v" + +/////////////////////////////////////////////////////////////////// +// +// CRC5 +// +/////////////////////////////////////////////////////////////////// + +module usb1d_crc5(crc_in, din, crc_out); +input [4:0] crc_in; +input [10:0] din; +output [4:0] crc_out; + +assign crc_out[0] = din[10] ^ din[9] ^ din[6] ^ din[5] ^ din[3] ^ + din[0] ^ crc_in[0] ^ crc_in[3] ^ crc_in[4]; + +assign crc_out[1] = din[10] ^ din[7] ^ din[6] ^ din[4] ^ din[1] ^ + crc_in[0] ^ crc_in[1] ^ crc_in[4]; + +assign crc_out[2] = din[10] ^ din[9] ^ din[8] ^ din[7] ^ din[6] ^ + din[3] ^ din[2] ^ din[0] ^ crc_in[0] ^ crc_in[1] ^ + crc_in[2] ^ crc_in[3] ^ crc_in[4]; + +assign crc_out[3] = din[10] ^ din[9] ^ din[8] ^ din[7] ^ din[4] ^ din[3] ^ + din[1] ^ crc_in[1] ^ crc_in[2] ^ crc_in[3] ^ crc_in[4]; + +assign crc_out[4] = din[10] ^ din[9] ^ din[8] ^ din[5] ^ din[4] ^ din[2] ^ + crc_in[2] ^ crc_in[3] ^ crc_in[4]; + +endmodule +
diff --git a/verilog/dv/bfm/usb_device/core/usb1d_ctrl.v b/verilog/dv/bfm/usb_device/core/usb1d_ctrl.v new file mode 100755 index 0000000..6f1a66c --- /dev/null +++ b/verilog/dv/bfm/usb_device/core/usb1d_ctrl.v
@@ -0,0 +1,844 @@ +/********************************************************************** +* Ported to USB2UART project +* Author: Dinesh Annayya +* Email:- dinesha@opencores.org +* +* Date: 4th Feb 2013 +* Changes: +* A. Warning Clean Up +* +**********************************************************************/ +///////////////////////////////////////////////////////////////////// +//// //// +//// Internal Setup Engine //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb1_funct///// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// +//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// +//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// +//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// +//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// +//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// +//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// +//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// +//// POSSIBILITY OF SUCH DAMAGE. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usb1_ctrl.v,v 1.2 2002-09-25 06:06:49 rudi Exp $ +// +// $Date: 2002-09-25 06:06:49 $ +// $Revision: 1.2 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: not supported by cvs2svn $ +// Revision 1.1.1.1 2002/09/19 12:07:09 rudi +// Initial Checkin +// +// +// +// +// +// + +`include "usb1d_defines.v" + +module usb1d_ctrl( clk, rst, + + rom_adr, rom_data, + + ctrl_setup, ctrl_in, ctrl_out, + + rx_ctrl_data, rx_ctrl_dvalid,rx_ctrl_ddone, + + ep0_din, ep0_dout, ep0_re, ep0_we, ep0_stat, + ep0_size, + + send_stall, frame_no, + funct_adr, configured, halt, + + v_set_int, v_set_feature, wValue, wIndex, vendor_data, + + // Register Interface + reg_addr, + reg_rdwrn, + reg_req, + reg_wdata, + reg_rdata, + reg_ack + + + ); + +input clk, rst; + +output [6:0] rom_adr; +input [7:0] rom_data; + +input ctrl_setup; +input ctrl_in; +input ctrl_out; + + +input [7:0] rx_ctrl_data; +input rx_ctrl_dvalid; +input rx_ctrl_ddone; + +input [7:0] ep0_din; +output [7:0] ep0_dout; +output ep0_re, ep0_we; +input [3:0] ep0_stat; +output [7:0] ep0_size; + +output send_stall; +input [10:0] frame_no; +output [6:0] funct_adr; +output configured, halt; + +output v_set_int; +output v_set_feature; +output [15:0] wValue; +output [15:0] wIndex; +input [15:0] vendor_data; + +//----------------------------------- +// Register Interface +// ---------------------------------- +output [31:0] reg_addr; // Register Address +output reg_rdwrn; // 0 -> write, 1-> read +output reg_req; // Register Req +output [31:0] reg_wdata; // Register write data +input [31:0] reg_rdata; // Register Read Data +input reg_ack; // Register Ack + + + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +parameter IDLE = 20'b0000_0000_0000_0000_0001, + GET_HDR = 20'b0000_0000_0000_0000_0010, + GET_STATUS_S = 20'b0000_0000_0000_0000_0100, + CLEAR_FEATURE_S = 20'b0000_0000_0000_0000_1000, + SET_FEATURE_S = 20'b0000_0000_0000_0001_0000, + SET_ADDRESS_S = 20'b0000_0000_0000_0010_0000, + GET_DESCRIPTOR_S = 20'b0000_0000_0000_0100_0000, + SET_DESCRIPTOR_S = 20'b0000_0000_0000_1000_0000, + GET_CONFIG_S = 20'b0000_0000_0001_0000_0000, + SET_CONFIG_S = 20'b0000_0000_0010_0000_0000, + GET_INTERFACE_S = 20'b0000_0000_0100_0000_0000, + SET_INTERFACE_S = 20'b0000_0000_1000_0000_0000, + SYNCH_FRAME_S = 20'b0000_0001_0000_0000_0000, + WAIT_IN_DATA = 20'b0000_0010_0000_0000_0000, + STATUS_IN = 20'b0000_0100_0000_0000_0000, + STATUS_OUT = 20'b0000_1000_0000_0000_0000, + V_SET_INT_S = 20'b0001_0000_0000_0000_0000, + V_GET_STATUS_S = 20'b0010_0000_0000_0000_0000, + V_GET_REG_RDATA_S = 20'b0100_0000_0000_0000_0000, + V_WAIT_RDATA_DONE_S = 20'b1000_0000_0000_0000_0000; + + +wire [7:0] bmReqType, bRequest; +wire [15:0] wValue, wIndex, wLength; +wire bm_req_dir; +wire [1:0] bm_req_type; +wire [4:0] bm_req_recp; + +reg get_status, clear_feature, set_feature, set_address; +reg get_descriptor, set_descriptor, get_config, set_config; +reg get_interface, set_interface, synch_frame; +reg hdr_done_r, config_err; +reg v_set_int, v_set_feature, v_get_status; + +reg v_set_reg_waddr; // Set the Reg Bus Address +reg v_set_reg_raddr; // Set the Reg Bus Address + +wire fifo_re1, fifo_full, fifo_empty; +reg fifo_we_d; +reg [5:0] data_sel; +reg ep0_we; +reg [7:0] ep0_dout; +reg [7:0] ep0_size; +reg send_stall; +reg [19:0] state, next_state; +reg get_hdr; +reg [7:0] le; +wire hdr_done; +reg adv; +reg [7:0] hdr0, hdr1, hdr2, hdr3, hdr4, hdr5, hdr6, hdr7; +reg [6:0] funct_adr; +reg set_adr_pending; +reg [6:0] funct_adr_tmp; + +reg in_size_0; +reg in_size_1; +reg in_size_2; +reg in_size_4; +wire high_sel; +reg write_done; + +//---------------------------- +// Register Interface +// ---------------------------- +reg [31:0] reg_addr; +reg [31:0] reg_wdata; +reg [31:0] reg_rdata_r; +reg reg_req; +reg reg_rdwrn; // 0 - write, 1 -> read +reg reg_wphase; // register write phase +reg reg_rphase; // register read phase +reg [3:0] tx_bcnt; // transmit byte count +/////////////////////////////////////////////////////////////////// +// +// FIFO interface +// + +assign ep0_re = fifo_re1; +assign fifo_empty = ep0_stat[1]; +assign fifo_full = ep0_stat[2]; + +/////////////////////////////////////////////////////////////////// +// +// Current States +// +reg addressed; +reg configured; +reg halt; +wire clr_halt; +wire set_halt=0; // FIX_ME + +// For this implementation we do not implement HALT for the +// device nor for any of the endpoints. This is useless for +// this device, but can be added here later ... +// FYI, we report device/endpoint errors via interrupts, +// instead of halting the entire or part of the device, much +// nicer for non-critical errors. + +assign clr_halt = ctrl_setup; + +always @(posedge clk) + if(!rst) addressed <= #1 1'b0; + else + if(set_address) addressed <= #1 1'b1; + +always @(posedge clk) + if(!rst) configured <= #1 1'b0; + else + if(set_config) configured <= #1 1'b1; + +always @(posedge clk) + if(!rst) halt <= #1 1'b0; + else + if(clr_halt) halt <= #1 1'b0; + else + if(set_halt) halt <= #1 1'b1; + +/////////////////////////////////////////////////////////////////// +// +// Descriptor ROM +// +reg [6:0] rom_adr; +reg rom_sel, rom_sel_r; +wire rom_done; +reg [6:0] rom_size; +reg fifo_we_rom_r; +reg fifo_we_rom_r2; +wire fifo_we_rom; +reg [7:0] rom_start_d; +reg [6:0] rom_size_dd; +wire [6:0] rom_size_d; + +always @(wValue) + case(wValue[11:8]) // synopsys full_case parallel_case + 4'h1: rom_start_d = `ROM_START0; + 4'h2: rom_start_d = `ROM_START1; + 4'h3: + case(wValue[3:0]) // synopsys full_case parallel_case + 4'h0: rom_start_d = `ROM_START2A; + 4'h1: rom_start_d = `ROM_START2B; + 4'h2: rom_start_d = `ROM_START2C; + 4'h3: rom_start_d = `ROM_START2D; + default: rom_start_d = `ROM_START2A; + endcase + default: rom_start_d = 7'h00; + endcase + +always @(wValue) + case(wValue[11:8]) // synopsys full_case parallel_case + 4'h1: rom_size_dd = `ROM_SIZE0; + 4'h2: rom_size_dd = `ROM_SIZE1; + 4'h3: + case(wValue[3:0]) // synopsys full_case parallel_case + 4'h0: rom_size_dd = `ROM_SIZE2A; + 4'h1: rom_size_dd = `ROM_SIZE2B; + 4'h2: rom_size_dd = `ROM_SIZE2C; + 4'h3: rom_size_dd = `ROM_SIZE2D; + default: rom_size_dd = `ROM_SIZE2A; + endcase + default: rom_size_dd = 7'h01; + endcase + +assign rom_size_d = (rom_size_dd > wLength[6:0]) ? wLength[6:0] : rom_size_dd; + +always @(posedge clk) + rom_sel_r <= #1 rom_sel; + +always @(posedge clk) + if(!rst) rom_adr <= #1 7'h0; + else + if(rom_sel & !rom_sel_r) rom_adr <= #1 rom_start_d; + else + if(rom_sel & !fifo_full) rom_adr <= #1 rom_adr + 7'h1; + +always @(posedge clk) + if(!rst) rom_size <= #1 7'h0; + else + if(rom_sel & !rom_sel_r) rom_size <= #1 rom_size_d; + else + if(rom_sel & !fifo_full) rom_size <= #1 rom_size - 7'h01; + +always @(posedge clk) + fifo_we_rom_r <= #1 rom_sel; + +always @(posedge clk) + fifo_we_rom_r2 <= #1 fifo_we_rom_r; + +assign fifo_we_rom = rom_sel & fifo_we_rom_r2; + +assign rom_done = (rom_size == 7'h0) & !(rom_sel & !rom_sel_r); + +/////////////////////////////////////////////////////////////////// +// +// Get Header +// + +assign fifo_re1 = (get_hdr | reg_wphase) & !fifo_empty; + +always @(posedge clk) + adv <= #1 get_hdr & !fifo_empty & !adv; + +always @(posedge clk) + if(!rst) le <= #1 8'h0; + else + if(!get_hdr) le <= #1 8'h0; + else + if(!(|le)) le <= #1 8'h1; + else + if(fifo_re1 && get_hdr) le <= #1 {le[6:0], 1'b0}; + +always @(posedge clk) + if(le[0]) hdr0 <= #1 ep0_din; + +always @(posedge clk) + if(le[1]) hdr1 <= #1 ep0_din; + +always @(posedge clk) + if(le[2]) hdr2 <= #1 ep0_din; + +always @(posedge clk) + if(le[3]) hdr3 <= #1 ep0_din; + +always @(posedge clk) + if(le[4]) hdr4 <= #1 ep0_din; + +always @(posedge clk) + if(le[5]) hdr5 <= #1 ep0_din; + +always @(posedge clk) + if(le[6]) hdr6 <= #1 ep0_din; + +always @(posedge clk) + if(le[7]) hdr7 <= #1 ep0_din; + +assign hdr_done = le[7] & fifo_re1 & get_hdr; + +/////////////////////////////////////////////////////////////////// +// +// Send Data to Host +// +parameter ZERO_DATA = 6'b000001, + ZERO_ONE_DATA = 6'b000010, + CONFIG_DATA = 6'b000100, + SYNC_FRAME_DATA = 6'b001000, + VEND_DATA = 6'b010000, + REG_RDATA = 6'b100000; + +assign high_sel = write_done; + +always @(posedge clk) + case(data_sel) // synopsys full_case parallel_case + ZERO_DATA: ep0_dout <= #1 rom_sel ? rom_data : 8'h0; + ZERO_ONE_DATA: ep0_dout <= #1 high_sel ? 8'h1 : 8'h0; + CONFIG_DATA: ep0_dout <= #1 {7'h0, configured}; // return configuration + SYNC_FRAME_DATA: ep0_dout <= #1 high_sel ? {5'h0, frame_no[10:8]} : frame_no[7:0]; + VEND_DATA: ep0_dout <= #1 high_sel ? vendor_data[15:8] : vendor_data[7:0]; + REG_RDATA: ep0_dout <= #1 (tx_bcnt==0) ? reg_rdata_r[31:24] : + (tx_bcnt==1) ? reg_rdata_r[23:16] : + (tx_bcnt==2) ? reg_rdata_r[15:8] : reg_rdata_r[7:0]; + endcase + +always @(posedge clk) + ep0_we <= #1 (fifo_we_d & !write_done) | fifo_we_rom; + +always @(posedge clk) + if(in_size_0) ep0_size <= #1 8'h0; + else if(in_size_1) ep0_size <= #1 8'h1; + else if(in_size_2) ep0_size <= #1 8'h2; + else if(in_size_4) ep0_size <= #1 8'h4; + else + if(rom_sel) ep0_size <= #1 {1'b0, rom_size_d}; + + +always @(posedge clk) begin + if(!rst) begin + tx_bcnt <= 0; + write_done <= 0; + end else begin + if(state == IDLE) begin + tx_bcnt <= 0; + write_done <= 0; + end else if((ep0_size == (tx_bcnt+1)) && (!fifo_full && fifo_we_d)) + write_done <= 1; + else if(!fifo_full && fifo_we_d ) + tx_bcnt <= tx_bcnt+1; + else + write_done <= 0; + end +end + +/////////////////////////////////////////////////////////////////// +// +// Decode Header +// + +// Valid bRequest Codes +parameter GET_STATUS = 8'h00, + CLEAR_FEATURE = 8'h01, + SET_FEATURE = 8'h03, + SET_ADDRESS = 8'h05, + GET_DESCRIPTOR = 8'h06, + SET_DESCRIPTOR = 8'h07, + GET_CONFIG = 8'h08, + SET_CONFIG = 8'h09, + GET_INTERFACE = 8'h0a, + SET_INTERFACE = 8'h0b, + SYNCH_FRAME = 8'h0c, + CUSTOM_REG_WADDR= 8'h10, // Added by Dinesh-A, 19th Feb 2013 + CUSTOM_REG_RADDR= 8'h11; // Added by Dinesh-A, 19th Feb 2013 + +parameter V_SET_INT = 8'h0f; + +/************************************************* +* Author: Dinesh-A: 18th Feb 2013 +* Setup Byte Details +Byte Field Description +0 bmRequest Type + Bit 7: Request direction (0=Host to device – Out, 1=Device to host – In). + Bits 5-6: Request type (0=standard, 1=class, 2=vendor, 3=reserved). + Bits 0-4: Recipient (0=device, 1=interface, 2=endpoint,3=other). +1 bRequest The actual request (see the Standard Device Request Codes table [9.2.1.5]. +2 wValueL A word-size value that varies according to the request. For example, + in the CLEAR_FEATURE request the value is used to select the feature, + in the GET_DESCRIPTOR request the value indicates the descriptor type and in the + SET_ADDRESS request the value contains the device address. +3 wValueH The upper byte of the Value word. +4 wIndexL A word-size value that varies according to the request. + The index is generally used to specify an endpoint or an interface. +5 wIndexH The upper byte of the Index word. +6 wLengthL A word-size value that indicates the number of bytes to be transferred if there is a data stage. +7 wLengthH The upper byte of the Length word. +**************************************************/ +/******* +bRequest Value +GET_STATUS 0 +CLEAR_FEATURE 1 +Reserved for future use 2 +SET_FEATURE 3 +Reserved for future use 4 +SET_ADDRESS 5 +GET_DESCRIPTOR 6 +SET_DESCRIPTOR 7 +GET_CONFIGURATION 8 +SET_CONFIGURATION 9 +GET_INTERFACE 10 +SET_INTERFACE 11 +SYNCH_FRAME 12 + +*******************************/ + +assign bmReqType = hdr0; +assign bm_req_dir = bmReqType[7]; // 0-Host to device; 1-device to host +assign bm_req_type = bmReqType[6:5]; // 0-standard; 1-class; 2-vendor; 3-RESERVED +assign bm_req_recp = bmReqType[4:0]; // 0-device; 1-interface; 2-endpoint; 3-other + // 4..31-reserved +assign bRequest = hdr1; +assign wValue = {hdr3, hdr2}; +assign wIndex = {hdr5, hdr4}; +assign wLength = {hdr7, hdr6}; + +always @(posedge clk) + hdr_done_r <= #1 hdr_done; + +// Standard commands that MUST support +always @(posedge clk) + get_status <= #1 hdr_done & (bRequest == GET_STATUS) & (bm_req_type==2'h0); + +always @(posedge clk) + clear_feature <= #1 hdr_done & (bRequest == CLEAR_FEATURE) & (bm_req_type==2'h0); + +always @(posedge clk) + set_feature <= #1 hdr_done & (bRequest == SET_FEATURE) & (bm_req_type==2'h0); + +always @(posedge clk) + set_address <= #1 hdr_done & (bRequest == SET_ADDRESS) & (bm_req_type==2'h0); + +always @(posedge clk) + get_descriptor <= #1 hdr_done & (bRequest == GET_DESCRIPTOR) & (bm_req_type==2'h0); + +always @(posedge clk) + set_descriptor <= #1 hdr_done & (bRequest == SET_DESCRIPTOR) & (bm_req_type==2'h0); + +always @(posedge clk) + get_config <= #1 hdr_done & (bRequest == GET_CONFIG) & (bm_req_type==2'h0); + +always @(posedge clk) + set_config <= #1 hdr_done & (bRequest == SET_CONFIG) & (bm_req_type==2'h0); + +always @(posedge clk) + get_interface <= #1 hdr_done & (bRequest == GET_INTERFACE) & (bm_req_type==2'h0); + +always @(posedge clk) + set_interface <= #1 hdr_done & (bRequest == SET_INTERFACE) & (bm_req_type==2'h0); + +always @(posedge clk) + synch_frame <= #1 hdr_done & (bRequest == SYNCH_FRAME) & (bm_req_type==2'h0); + +always @(posedge clk) + v_set_int <= #1 hdr_done & (bRequest == V_SET_INT) & (bm_req_type==2'h2); + +always @(posedge clk) + v_set_feature <= #1 hdr_done & (bRequest == SET_FEATURE) & (bm_req_type==2'h2); + +always @(posedge clk) + v_get_status <= #1 hdr_done & (bRequest == GET_STATUS) & (bm_req_type==2'h2); +always @(posedge clk) + v_set_reg_waddr <= #1 hdr_done & (bRequest == CUSTOM_REG_WADDR) & (bm_req_type==2'h2); +always @(posedge clk) + v_set_reg_raddr <= #1 hdr_done & (bRequest == CUSTOM_REG_RADDR) & (bm_req_type==2'h2); + +always @(posedge clk) + if(v_set_reg_waddr || v_set_reg_raddr) reg_addr <= {hdr2,hdr3,hdr4,hdr5}; + +reg [1:0] reg_byte_cnt; +always @(posedge clk) begin + if(!rst) begin + reg_byte_cnt <= 2'b0; + end else begin + if(v_set_reg_waddr) begin + reg_wphase <= 1; + reg_byte_cnt <= 0; + end else if(reg_byte_cnt == 2'b11 && fifo_re1) begin + reg_wphase <= 0; + reg_byte_cnt <= 0; + end else if(reg_wphase && fifo_re1) begin + reg_byte_cnt <= reg_byte_cnt+1; + end + end +end + + +always @(posedge clk) + if(reg_wphase && fifo_re1) reg_wdata <= {reg_wdata[23:0],ep0_din[7:0]}; + +always @(posedge clk) + if(reg_rdwrn && reg_ack) reg_rdata_r <= {reg_rdata}; + +always @(posedge clk) begin + if(!rst) begin + reg_req <= 0; + end else begin + if(fifo_re1 && reg_wphase && reg_byte_cnt== 2'b11) reg_req <= 1; + else if(v_set_reg_raddr) reg_req <= 1; + else reg_req <= 0; + end +end + +always @(posedge clk) + if(v_set_reg_raddr) reg_rdwrn <= 1'b1 ; + else if(v_set_reg_waddr) reg_rdwrn <= 1'b0 ; + +// A config err must cause the device to send a STALL for an ACK +always @(posedge clk) + config_err <= #1 hdr_done_r & !(get_status | clear_feature | + set_feature | set_address | get_descriptor | + set_descriptor | get_config | set_config | + get_interface | set_interface | synch_frame | + v_set_int | v_set_feature | v_get_status | v_set_reg_waddr | v_set_reg_raddr); + +always @(posedge clk) + send_stall <= #1 config_err; + +/////////////////////////////////////////////////////////////////// +// +// Set address +// + +always @(posedge clk) + if(!rst) set_adr_pending <= #1 1'b0; + else + if(ctrl_in | ctrl_out | ctrl_setup) set_adr_pending <= #1 1'b0; + else + if(set_address) set_adr_pending <= #1 1'b1; + +always @(posedge clk) + if(!rst) funct_adr_tmp <= #1 7'h0; + else + if(set_address) funct_adr_tmp <= #1 wValue[6:0]; + +always @(posedge clk) + if(!rst) funct_adr <= #1 7'h0; + else + if(set_adr_pending & ctrl_in) funct_adr <= #1 funct_adr_tmp; + +/////////////////////////////////////////////////////////////////// +// +// Main FSM +// + +always @(posedge clk) + if(!rst) state <= #1 IDLE; + else state <= next_state; + +always @(state or ctrl_setup or ctrl_in or ctrl_out or hdr_done or + fifo_full or rom_done or write_done or wValue or bm_req_recp or + get_status or clear_feature or set_feature or set_address or + get_descriptor or set_descriptor or get_config or set_config or + get_interface or set_interface or synch_frame or v_set_int or + v_set_feature or v_get_status or v_set_reg_waddr or v_set_reg_raddr, reg_ack + ) + begin + next_state = state; + get_hdr = 1'b0; + data_sel = ZERO_DATA; + fifo_we_d = 1'b0; + in_size_0 = 1'b0; + in_size_1 = 1'b0; + in_size_2 = 1'b0; + in_size_4 = 1'b0; + rom_sel = 1'b0; + + case(state) // synopsys full_case parallel_case + + // Wait for Setup token + IDLE: + begin + if(ctrl_setup) next_state = GET_HDR; + if(get_status) next_state = GET_STATUS_S; + if(clear_feature) next_state = CLEAR_FEATURE_S; + if(set_feature) next_state = SET_FEATURE_S; + if(set_address) next_state = SET_ADDRESS_S; + if(get_descriptor) next_state = GET_DESCRIPTOR_S; + if(set_descriptor) next_state = SET_DESCRIPTOR_S; + if(get_config) next_state = GET_CONFIG_S; + if(set_config) next_state = SET_CONFIG_S; + if(get_interface) next_state = GET_INTERFACE_S; + if(set_interface) next_state = SET_INTERFACE_S; + if(synch_frame) next_state = SYNCH_FRAME_S; + if(v_set_int) next_state = V_SET_INT_S; + if(v_set_feature) next_state = V_SET_INT_S; + if(v_get_status) next_state = V_GET_STATUS_S; + if(v_set_reg_waddr) next_state = STATUS_IN; + if(v_set_reg_raddr) next_state = V_WAIT_RDATA_DONE_S; + end + + // Retrieve Setup Header + GET_HDR: + begin + get_hdr = 1'b1; + if(hdr_done) next_state = IDLE; + end + + + // Actions for supported commands + GET_STATUS_S: + begin + // Returns to host + // 16'h0001 for device + // 16'h0000 for interface + // 16'h0000 for endpoint + if(bm_req_recp == 5'h00) data_sel = ZERO_ONE_DATA; + else data_sel = ZERO_DATA; + + in_size_2 = 1'b1; + if(!fifo_full) + begin + fifo_we_d = 1'b1; + if(write_done) next_state = WAIT_IN_DATA; + end + + end + V_GET_STATUS_S: + begin + data_sel = VEND_DATA; + in_size_2 = 1'b1; + if(!fifo_full) + begin + fifo_we_d = 1'b1; + if(write_done) next_state = WAIT_IN_DATA; + end + end + + V_WAIT_RDATA_DONE_S: begin // Wait for Register Read Access Completion + if(reg_ack) + next_state = V_GET_REG_RDATA_S; + end + + V_GET_REG_RDATA_S: // Register Access Read Data + begin + data_sel = REG_RDATA; + in_size_4 = 1'b1; + if(!fifo_full) + begin + fifo_we_d = 1'b1; + if(write_done) next_state = WAIT_IN_DATA; + end + end + CLEAR_FEATURE_S: + begin + // just ignore this for now + next_state = STATUS_IN; + end + + SET_FEATURE_S: + begin + // just ignore this for now + next_state = STATUS_IN; + end + + SET_ADDRESS_S: + begin + // done elsewhere .... + next_state = STATUS_IN; + end + + GET_DESCRIPTOR_S: + begin + if( wValue[15:8] == 8'h01 | + wValue[15:8] == 8'h02 | + wValue[15:8] == 8'h03 ) + rom_sel = 1'b1; + else + next_state = IDLE; + + if(rom_done) + next_state = IDLE; + end + + SET_DESCRIPTOR_S: + begin + // This doesn't do anything since we do not support + // setting the descriptor + next_state = IDLE; + end + + GET_CONFIG_S: + begin + // Send one byte back that indicates current status + in_size_1 = 1'b1; + data_sel = CONFIG_DATA; + if(!fifo_full) + begin + fifo_we_d = 1'b1; + next_state = WAIT_IN_DATA; + end + end + + SET_CONFIG_S: + begin + // done elsewhere .... + next_state = STATUS_IN; + end + + GET_INTERFACE_S: + begin + // Return interface '0' + in_size_1 = 1'b1; + if(!fifo_full) + begin + fifo_we_d = 1'b1; + next_state = WAIT_IN_DATA; + end + end + + SET_INTERFACE_S: + begin + // just ignore this for now + next_state = STATUS_IN; + end + + SYNCH_FRAME_S: + begin + // Return Frame current frame number + data_sel = SYNC_FRAME_DATA; + in_size_2 = 1'b1; + if(!fifo_full) + begin + fifo_we_d = 1'b1; + if(write_done) next_state = WAIT_IN_DATA; + end + end + + V_SET_INT_S: + begin + // done elsewhere .... + next_state = STATUS_IN; + end + + WAIT_IN_DATA: + begin + if(ctrl_in) next_state = STATUS_OUT; + end + + STATUS_IN: + begin + in_size_0 = 1'b1; + if(ctrl_in) next_state = IDLE; + end + + STATUS_OUT: + begin + if(ctrl_out) next_state = IDLE; + end + endcase + end + +endmodule +
diff --git a/verilog/dv/bfm/usb_device/core/usb1d_fifo2.v b/verilog/dv/bfm/usb_device/core/usb1d_fifo2.v new file mode 100755 index 0000000..631acb4 --- /dev/null +++ b/verilog/dv/bfm/usb_device/core/usb1d_fifo2.v
@@ -0,0 +1,104 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// Fast FIFO 2 entries deep //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb1_funct///// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// +//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// +//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// +//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// +//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// +//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// +//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// +//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// +//// POSSIBILITY OF SUCH DAMAGE. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usb1_fifo2.v,v 1.1.1.1 2002-09-19 12:07:31 rudi Exp $ +// +// $Date: 2002-09-19 12:07:31 $ +// $Revision: 1.1.1.1 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: not supported by cvs2svn $ +// +// +// +// +// + + +module usb1d_fifo2(clk, rst, clr, din, we, dout, re); + +input clk, rst; +input clr; +input [7:0] din; +input we; +output [7:0] dout; +input re; + + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +reg [7:0] mem[0:1]; +reg wp; +reg rp; + +//////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +always @(posedge clk or negedge rst) + if(!rst) wp <= #1 1'h0; + else + if(clr) wp <= #1 1'h0; + else + if(we) wp <= #1 ~wp; + +always @(posedge clk or negedge rst) + if(!rst) rp <= #1 1'h0; + else + if(clr) rp <= #1 1'h0; + else + if(re) rp <= #1 ~rp; + +// Fifo Output +assign dout = mem[ rp ]; + +// Fifo Input +always @(posedge clk) + if(we) mem[ wp ] <= #1 din; + +endmodule +
diff --git a/verilog/dv/bfm/usb_device/core/usb1d_generic_dpram.v b/verilog/dv/bfm/usb_device/core/usb1d_generic_dpram.v new file mode 100755 index 0000000..431a447 --- /dev/null +++ b/verilog/dv/bfm/usb_device/core/usb1d_generic_dpram.v
@@ -0,0 +1,502 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// Generic Dual-Port Synchronous RAM //// +//// //// +//// This file is part of memory library available from //// +//// http://www.opencores.org/cvsweb.shtml/generic_memories/ //// +//// //// +//// Description //// +//// This block is a wrapper with common dual-port //// +//// synchronous memory interface for different //// +//// types of ASIC and FPGA RAMs. Beside universal memory //// +//// interface it also provides behavioral model of generic //// +//// dual-port synchronous RAM. //// +//// It also contains a fully synthesizeable model for FPGAs. //// +//// It should be used in all OPENCORES designs that want to be //// +//// portable accross different target technologies and //// +//// independent of target memory. //// +//// //// +//// Supported ASIC RAMs are: //// +//// - Artisan Dual-Port Sync RAM //// +//// - Avant! Two-Port Sync RAM (*) //// +//// - Virage 2-port Sync RAM //// +//// //// +//// Supported FPGA RAMs are: //// +//// - Generic FPGA (VENDOR_FPGA) //// +//// Tested RAMs: Altera, Xilinx //// +//// Synthesis tools: LeonardoSpectrum, Synplicity //// +//// - Xilinx (VENDOR_XILINX) //// +//// - Altera (VENDOR_ALTERA) //// +//// //// +//// To Do: //// +//// - fix Avant! //// +//// - add additional RAMs (VS etc) //// +//// //// +//// Author(s): //// +//// - Richard Herveille, richard@asics.ws //// +//// - Damjan Lampret, lampret@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: not supported by cvs2svn $ +// Revision 1.2 2001/11/08 19:11:31 samg +// added valid checks to behvioral model +// +// Revision 1.1.1.1 2001/09/14 09:57:10 rherveille +// Major cleanup. +// Files are now compliant to Altera & Xilinx memories. +// Memories are now compatible, i.e. drop-in replacements. +// Added synthesizeable generic FPGA description. +// Created "generic_memories" cvs entry. +// +// Revision 1.1.1.2 2001/08/21 13:09:27 damjan +// *** empty log message *** +// +// Revision 1.1 2001/08/20 18:23:20 damjan +// Initial revision +// +// Revision 1.1 2001/08/09 13:39:33 lampret +// Major clean-up. +// +// Revision 1.2 2001/07/30 05:38:02 lampret +// Adding empty directories required by HDL coding guidelines +// +// + + +//`define VENDOR_FPGA +//`define VENDOR_XILINX +//`define VENDOR_ALTERA + +module usb1d_generic_dpram( + // Generic synchronous dual-port RAM interface + rclk, rrst, rce, oe, raddr, dout, + wclk, wrst, wce, we, waddr, di +); + + // + // Default address and data buses width + // + parameter aw = 5; // number of bits in address-bus + parameter dw = 16; // number of bits in data-bus + + // + // Generic synchronous double-port RAM interface + // + // read port + input rclk; // read clock, rising edge trigger + input rrst; // read port reset, active high + input rce; // read port chip enable, active high + input oe; // output enable, active high + input [aw-1:0] raddr; // read address + output [dw-1:0] dout; // data output + + // write port + input wclk; // write clock, rising edge trigger + input wrst; // write port reset, active high + input wce; // write port chip enable, active high + input we; // write enable, active high + input [aw-1:0] waddr; // write address + input [dw-1:0] di; // data input + + // + // Module body + // + +`ifdef VENDOR_FPGA + // + // Instantiation synthesizeable FPGA memory + // + // This code has been tested using LeonardoSpectrum and Synplicity. + // The code correctly instantiates Altera EABs and Xilinx BlockRAMs. + // + + reg [dw-1 :0] mem [(1<<aw) -1:0]; // instantiate memory + reg [dw-1:0] dout; // data output registers + + // read operation + + /* + always@(posedge rclk) + if (rce) // clock enable instructs Xilinx tools to use SelectRAM (LUTS) instead of BlockRAM + do <= #1 mem[raddr]; + */ + + always@(posedge rclk) + dout <= #1 mem[raddr]; + + // write operation + always@(posedge wclk) + if (we && wce) + mem[waddr] <= #1 di; + +`else + +`ifdef VENDOR_XILINX + // + // Instantiation of FPGA memory: + // + // Virtex/Spartan2 BlockRAMs + // + xilinx_ram_dp xilinx_ram( + // read port + .CLKA(rclk), + .RSTA(rrst), + .ENA(rce), + .ADDRA(raddr), + .DIA( {dw{1'b0}} ), + .WEA(1'b0), + .DOA(dout), + + // write port + .CLKB(wclk), + .RSTB(wrst), + .ENB(wce), + .ADDRB(waddr), + .DIB(di), + .WEB(we), + .DOB() + ); + + defparam + xilinx_ram.dwidth = dw, + xilinx_ram.awidth = aw; + +`else + +`ifdef VENDOR_ALTERA + // + // Instantiation of FPGA memory: + // + // Altera FLEX/APEX EABs + // + altera_ram_dp altera_ram( + // read port + .rdclock(rclk), + .rdclocken(rce), + .rdaddress(raddr), + .q(dout), + + // write port + .wrclock(wclk), + .wrclocken(wce), + .wren(we), + .wraddress(waddr), + .data(di) + ); + + defparam + altera_ram.dwidth = dw, + altera_ram.awidth = aw; + +`else + +`ifdef VENDOR_ARTISAN + + // + // Instantiation of ASIC memory: + // + // Artisan Synchronous Double-Port RAM (ra2sh) + // + art_hsdp #(dw, 1<<aw, aw) artisan_sdp( + // read port + .qa(dout), + .clka(rclk), + .cena(~rce), + .wena(1'b1), + .aa(raddr), + .da( {dw{1'b0}} ), + .oena(~oe), + + // write port + .qb(), + .clkb(wclk), + .cenb(~wce), + .wenb(~we), + .ab(waddr), + .db(di), + .oenb(1'b1) + ); + +`else + +`ifdef VENDOR_AVANT + + // + // Instantiation of ASIC memory: + // + // Avant! Asynchronous Two-Port RAM + // + avant_atp avant_atp( + .web(~we), + .reb(), + .oeb(~oe), + .rcsb(), + .wcsb(), + .ra(raddr), + .wa(waddr), + .di(di), + .do(dout) + ); + +`else + +`ifdef VENDOR_VIRAGE + + // + // Instantiation of ASIC memory: + // + // Virage Synchronous 2-port R/W RAM + // + virage_stp virage_stp( + // read port + .CLKA(rclk), + .MEA(rce_a), + .ADRA(raddr), + .DA( {dw{1'b0}} ), + .WEA(1'b0), + .OEA(oe), + .QA(dout), + + // write port + .CLKB(wclk), + .MEB(wce), + .ADRB(waddr), + .DB(di), + .WEB(we), + .OEB(1'b1), + .QB() + ); + +`else + + // + // Generic dual-port synchronous RAM model + // + + // + // Generic RAM's registers and wires + // + reg [dw-1:0] mem [(1<<aw)-1:0]; // RAM content + reg [dw-1:0] do_reg; // RAM data output register + + // + // Data output drivers + // + assign dout = (oe & rce) ? do_reg : {dw{1'bz}}; + + // read operation + always @(posedge rclk) + if (rce) + do_reg <= #1 (we && (waddr==raddr)) ? {dw{1'b x}} : mem[raddr]; + + // write operation + always @(posedge wclk) + if (wce && we) + mem[waddr] <= #1 di; + + + // Task prints range of memory + // *** Remember that tasks are non reentrant, don't call this task in parallel for multiple instantiations. + task print_ram; + input [aw-1:0] start; + input [aw-1:0] finish; + integer rnum; + begin + for (rnum=start;rnum<=finish;rnum=rnum+1) + $display("Addr %h = %h",rnum,mem[rnum]); + end + endtask + +`endif // !VENDOR_VIRAGE +`endif // !VENDOR_AVANT +`endif // !VENDOR_ARTISAN +`endif // !VENDOR_ALTERA +`endif // !VENDOR_XILINX +`endif // !VENDOR_FPGA + +endmodule + +// +// Black-box modules +// + +`ifdef VENDOR_ALTERA + module altera_ram_dp( + data, + wraddress, + rdaddress, + wren, + wrclock, + wrclocken, + rdclock, + rdclocken, + q) /* synthesis black_box */; + + parameter awidth = 7; + parameter dwidth = 8; + + input [dwidth -1:0] data; + input [awidth -1:0] wraddress; + input [awidth -1:0] rdaddress; + input wren; + input wrclock; + input wrclocken; + input rdclock; + input rdclocken; + output [dwidth -1:0] q; + + // synopsis translate_off + // exemplar translate_off + + syn_dpram_rowr #( + "UNUSED", + dwidth, + awidth, + 1 << awidth + ) + altera_dpram_model ( + // read port + .RdClock(rdclock), + .RdClken(rdclocken), + .RdAddress(rdaddress), + .RdEn(1'b1), + .Q(q), + + // write port + .WrClock(wrclock), + .WrClken(wrclocken), + .WrAddress(wraddress), + .WrEn(wren), + .Data(data) + ); + + // exemplar translate_on + // synopsis translate_on + + endmodule +`endif // VENDOR_ALTERA + +`ifdef VENDOR_XILINX + module xilinx_ram_dp ( + ADDRA, + CLKA, + ADDRB, + CLKB, + DIA, + WEA, + DIB, + WEB, + ENA, + ENB, + RSTA, + RSTB, + DOA, + DOB) /* synthesis black_box */ ; + + parameter awidth = 7; + parameter dwidth = 8; + + // port_a + input CLKA; + input RSTA; + input ENA; + input [awidth-1:0] ADDRA; + input [dwidth-1:0] DIA; + input WEA; + output [dwidth-1:0] DOA; + + // port_b + input CLKB; + input RSTB; + input ENB; + input [awidth-1:0] ADDRB; + input [dwidth-1:0] DIB; + input WEB; + output [dwidth-1:0] DOB; + + // insert simulation model + + + // synopsys translate_off + // exemplar translate_off + + C_MEM_DP_BLOCK_V1_0 #( + awidth, + awidth, + 1, + 1, + "0", + 1 << awidth, + 1 << awidth, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + "", + 16, + 0, + 0, + 1, + 1, + 1, + 1, + dwidth, + dwidth) + xilinx_dpram_model ( + .ADDRA(ADDRA), + .CLKA(CLKA), + .ADDRB(ADDRB), + .CLKB(CLKB), + .DIA(DIA), + .WEA(WEA), + .DIB(DIB), + .WEB(WEB), + .ENA(ENA), + .ENB(ENB), + .RSTA(RSTA), + .RSTB(RSTB), + .DOA(DOA), + .DOB(DOB)); + + // exemplar translate_on + // synopsys translate_on + + endmodule +`endif // VENDOR_XILINX
diff --git a/verilog/dv/bfm/usb_device/core/usb1d_generic_fifo.v b/verilog/dv/bfm/usb_device/core/usb1d_generic_fifo.v new file mode 100755 index 0000000..89c67e6 --- /dev/null +++ b/verilog/dv/bfm/usb_device/core/usb1d_generic_fifo.v
@@ -0,0 +1,334 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// Universal FIFO Single Clock //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// D/L from: http://www.opencores.org/cores/generic_fifos/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// +//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// +//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// +//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// +//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// +//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// +//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// +//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// +//// POSSIBILITY OF SUCH DAMAGE. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: generic_fifo_sc_a.v,v 1.1.1.1 2002-09-25 05:42:06 rudi Exp $ +// +// $Date: 2002-09-25 05:42:06 $ +// $Revision: 1.1.1.1 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: not supported by cvs2svn $ +// +// +// +// +// +// +// +// +// +// + + +/* + +Description +=========== + +I/Os +---- +rst low active, either sync. or async. master reset (see below how to select) +clr synchronous clear (just like reset but always synchronous), high active +re read enable, synchronous, high active +we read enable, synchronous, high active +din Data Input +dout Data Output + +full Indicates the FIFO is full (combinatorial output) +full_r same as above, but registered output (see note below) +empty Indicates the FIFO is empty +empty_r same as above, but registered output (see note below) + +full_n Indicates if the FIFO has space for N entries (combinatorial output) +full_n_r same as above, but registered output (see note below) +empty_n Indicates the FIFO has at least N entries (combinatorial output) +empty_n_r same as above, but registered output (see note below) + +level indicates the FIFO level: + 2'b00 0-25% full + 2'b01 25-50% full + 2'b10 50-75% full + 2'b11 %75-100% full + +combinatorial vs. registered status outputs +------------------------------------------- +Both the combinatorial and registered status outputs have exactly the same +synchronous timing. Meaning they are being asserted immediately at the clock +edge after the last read or write. The combinatorial outputs however, pass +through several levels of logic before they are output. The registered status +outputs are direct outputs of a flip-flop. The reason both are provided, is +that the registered outputs require quite a bit of additional logic inside +the FIFO. If you can meet timing of your device with the combinatorial +outputs, use them ! The FIFO will be smaller. If the status signals are +in the critical pass, use the registered outputs, they have a much smaller +output delay (actually only Tcq). + +Parameters +---------- +The FIFO takes 3 parameters: +dw Data bus width +aw Address bus width (Determines the FIFO size by evaluating 2^aw) +n N is a second status threshold constant for full_n and empty_n + If you have no need for the second status threshold, do not + connect the outputs and the logic should be removed by your + synthesis tool. + +Synthesis Results +----------------- +In a Spartan 2e a 8 bit wide, 8 entries deep FIFO, takes 85 LUTs and runs +at about 116 MHz (IO insertion disabled). The registered status outputs +are valid after 2.1NS, the combinatorial once take out to 6.5 NS to be +available. + + +Misc +---- +This design assumes you will do appropriate status checking externally. + +IMPORTANT ! writing while the FIFO is full or reading while the FIFO is +empty will place the FIFO in an undefined state. + +*/ + + +// Selecting Sync. or Async Reset +// ------------------------------ +// Uncomment one of the two lines below. The first line for +// synchronous reset, the second for asynchronous reset + +`define SC_FIFO_ASYNC_RESET // Uncomment for Syncr. reset +//`define SC_FIFO_ASYNC_RESET or negedge rst // Uncomment for Async. reset + + +module usb1d_generic_fifo(clk, rst, clr, din, we, dout, re, + full, empty, full_r, empty_r, + full_n, empty_n, full_n_r, empty_n_r, + level); + +parameter dw=8; +parameter aw=8; +parameter n=32; +parameter max_size = 1<<aw; + +input clk, rst, clr; +input [dw-1:0] din; +input we; +output [dw-1:0] dout; +input re; +output full, full_r; +output empty, empty_r; +output full_n, full_n_r; +output empty_n, empty_n_r; +output [1:0] level; + +//////////////////////////////////////////////////////////////////// +// +// Local Wires +// + +reg [aw-1:0] wp; +wire [aw-1:0] wp_pl1; +wire [aw-1:0] wp_pl2; +reg [aw-1:0] rp; +wire [aw-1:0] rp_pl1; +reg full_r; +reg empty_r; +reg gb; +reg gb2; +reg [aw:0] cnt; +wire full_n, empty_n; +reg full_n_r, empty_n_r; + +//////////////////////////////////////////////////////////////////// +// +// Memory Block +// + +usb1d_generic_dpram #(aw,dw) u0( + .rclk( clk ), + .rrst( !rst ), + .rce( 1'b1 ), + .oe( 1'b1 ), + .raddr( rp ), + .dout( dout ), + .wclk( clk ), + .wrst( !rst ), + .wce( 1'b1 ), + .we( we ), + .waddr( wp ), + .di( din ) + ); + +//////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +always @(posedge clk `SC_FIFO_ASYNC_RESET) + if(!rst) wp <= #1 {aw{1'b0}}; + else + if(clr) wp <= #1 {aw{1'b0}}; + else + if(we) wp <= #1 wp_pl1; + +assign wp_pl1 = wp + { {aw-1{1'b0}}, 1'b1}; +assign wp_pl2 = wp + { {aw-2{1'b0}}, 2'b10}; + +always @(posedge clk `SC_FIFO_ASYNC_RESET) + if(!rst) rp <= #1 {aw{1'b0}}; + else + if(clr) rp <= #1 {aw{1'b0}}; + else + if(re) rp <= #1 rp_pl1; + +assign rp_pl1 = rp + { {aw-1{1'b0}}, 1'b1}; + +//////////////////////////////////////////////////////////////////// +// +// Combinatorial Full & Empty Flags +// + +assign empty = ((wp == rp) & !gb); +assign full = ((wp == rp) & gb); + +// Guard Bit ... +always @(posedge clk `SC_FIFO_ASYNC_RESET) + if(!rst) gb <= #1 1'b0; + else + if(clr) gb <= #1 1'b0; + else + if((wp_pl1 == rp) & we) gb <= #1 1'b1; + else + if(re) gb <= #1 1'b0; + +//////////////////////////////////////////////////////////////////// +// +// Registered Full & Empty Flags +// + +// Guard Bit ... +always @(posedge clk `SC_FIFO_ASYNC_RESET) + if(!rst) gb2 <= #1 1'b0; + else + if(clr) gb2 <= #1 1'b0; + else + if((wp_pl2 == rp) & we) gb2 <= #1 1'b1; + else + if((wp != rp) & re) gb2 <= #1 1'b0; + +always @(posedge clk `SC_FIFO_ASYNC_RESET) + if(!rst) full_r <= #1 1'b0; + else + if(clr) full_r <= #1 1'b0; + else + if(we & ((wp_pl1 == rp) & gb2) & !re) full_r <= #1 1'b1; + else + if(re & ((wp_pl1 != rp) | !gb2) & !we) full_r <= #1 1'b0; + +always @(posedge clk `SC_FIFO_ASYNC_RESET) + if(!rst) empty_r <= #1 1'b1; + else + if(clr) empty_r <= #1 1'b1; + else + if(we & ((wp != rp_pl1) | gb2) & !re) empty_r <= #1 1'b0; + else + if(re & ((wp == rp_pl1) & !gb2) & !we) empty_r <= #1 1'b1; + +//////////////////////////////////////////////////////////////////// +// +// Combinatorial Full_n & Empty_n Flags +// + +assign empty_n = cnt < n; +assign full_n = !(cnt < (max_size-n+1)); +assign level = {2{cnt[aw]}} | cnt[aw-1:aw-2]; + +// N entries status +always @(posedge clk `SC_FIFO_ASYNC_RESET) + if(!rst) cnt <= #1 {aw+1{1'b0}}; + else + if(clr) cnt <= #1 {aw+1{1'b0}}; + else + if( re & !we) cnt <= #1 cnt + { {aw{1'b1}}, 1'b1}; + else + if(!re & we) cnt <= #1 cnt + { {aw{1'b0}}, 1'b1}; + +//////////////////////////////////////////////////////////////////// +// +// Registered Full_n & Empty_n Flags +// + +always @(posedge clk `SC_FIFO_ASYNC_RESET) + if(!rst) empty_n_r <= #1 1'b1; + else + if(clr) empty_n_r <= #1 1'b1; + else + if(we & (cnt >= (n-1) ) & !re) empty_n_r <= #1 1'b0; + else + if(re & (cnt <= n ) & !we) empty_n_r <= #1 1'b1; + +always @(posedge clk `SC_FIFO_ASYNC_RESET) + if(!rst) full_n_r <= #1 1'b0; + else + if(clr) full_n_r <= #1 1'b0; + else + if(we & (cnt >= (max_size-n) ) & !re) full_n_r <= #1 1'b1; + else + if(re & (cnt <= (max_size-n+1)) & !we) full_n_r <= #1 1'b0; + +//////////////////////////////////////////////////////////////////// +// +// Sanity Check +// + +// synopsys translate_off +always @(posedge clk) + if(we & full) + $display("%m WARNING: Writing while fifo is FULL (%t)",$time); + +always @(posedge clk) + if(re & empty) + $display("%m WARNING: Reading while fifo is EMPTY (%t)",$time); +// synopsys translate_on + +endmodule
diff --git a/verilog/dv/bfm/usb_device/core/usb1d_idma.v b/verilog/dv/bfm/usb_device/core/usb1d_idma.v new file mode 100755 index 0000000..2a6207c --- /dev/null +++ b/verilog/dv/bfm/usb_device/core/usb1d_idma.v
@@ -0,0 +1,387 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// Internal DMA Engine //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb1_funct///// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// +//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// +//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// +//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// +//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// +//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// +//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// +//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// +//// POSSIBILITY OF SUCH DAMAGE. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usb1_idma.v,v 1.2 2002-09-25 06:06:49 rudi Exp $ +// +// $Date: 2002-09-25 06:06:49 $ +// $Revision: 1.2 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: not supported by cvs2svn $ +// Revision 1.1.1.1 2002/09/19 12:07:38 rudi +// Initial Checkin +// +// +// +// +// +// + +`include "usb1d_defines.v" + +module usb1d_idma( clk, rst, + + // Packet Disassembler/Assembler interface + rx_data_valid, + rx_data_done, + send_data, + rd_next, + + tx_valid, + tx_data_st_i, + tx_data_st_o, + + // Protocol Engine + tx_dma_en, rx_dma_en, idma_done, + ep_sel, + + // Register File Manager Interface + size, + rx_cnt, rx_done, + tx_busy, + + // Block Frames + ep_bf_en, ep_bf_size, + dropped_frame, misaligned_frame, + + // Memory Arb interface + mwe, mre, ep_empty, ep_empty_int, ep_full + ); + + +// Packet Disassembler/Assembler interface +input clk, rst; +input rx_data_valid; +input rx_data_done; +output send_data; +input rd_next; + +input tx_valid; +input [7:0] tx_data_st_i; +output [7:0] tx_data_st_o; + +// Protocol Engine +input tx_dma_en; +input rx_dma_en; +output idma_done; // DMA is done +input [3:0] ep_sel; + +// Register File Manager Interface +input [8:0] size; // MAX PL Size in bytes +output [7:0] rx_cnt; +output rx_done; +output tx_busy; + +input ep_bf_en; +input [6:0] ep_bf_size; +output dropped_frame; +output misaligned_frame; + +// Memory Arb interface +output mwe; +output mre; +input ep_empty; +output ep_empty_int; +input ep_full; + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +reg tx_dma_en_r; +reg [8:0] sizd_c; // Internal size counter +wire adr_incw; +wire adr_incb; +wire siz_dec; +wire mwe; // Memory Write enable +wire mre; // Memory Read enable +reg mwe_r; +reg sizd_is_zero; // Indicates when all bytes have been + // transferred +wire sizd_is_zero_d; +reg idma_done; // DMA transfer is done +wire send_data; // Enable UTMI Transmitter +reg rx_data_done_r; +reg rx_data_valid_r; +wire ff_re, ff_full, ff_empty; +reg ff_we, ff_we1; +reg tx_dma_en_r1; +reg tx_dma_en_r2; +reg tx_dma_en_r3; +reg send_data_r; +wire ff_clr; +reg [7:0] rx_cnt; +reg [7:0] rx_cnt_r; +reg ep_empty_r; +reg ep_empty_latched; +wire ep_empty_int; +reg [6:0] ec; +wire ec_clr; +reg dropped_frame; +reg [6:0] rc_cnt; +wire rc_clr; +reg ep_full_latched; +wire ep_full_int; +reg misaligned_frame; +reg tx_valid_r; +wire tx_valid_e; + +/////////////////////////////////////////////////////////////////// +// +// For IN Block Frames transmit frames in [ep_bf_size] byte quantities +// + +`ifdef USB1_BF_ENABLE + +always @(posedge clk) + if(!rst) ec <= #1 7'h0; + else + if(!ep_bf_en | ec_clr) ec <= #1 7'h0; + else + if(mre) ec <= #1 ec + 7'h1; + +assign ec_clr = (ec == ep_bf_size) | tx_dma_en; + +always @(posedge clk) + if(!rst) ep_empty_latched <= #1 1'b0; + else + if(ec_clr) ep_empty_latched <= #1 ep_empty; + +assign ep_empty_int = ep_bf_en ? ep_empty_latched : ep_empty; +`else +assign ep_empty_int = ep_empty; +`endif +/////////////////////////////////////////////////////////////////// +// +// For OUT Block Frames always store in [ep_bf_size] byte chunks +// if fifo can't accept [ep_bf_size] bytes junk the entire [ep_bf_size] +// byte frame +// + +`ifdef USB1_BF_ENABLE +always @(posedge clk) + if(!rst) rc_cnt <= #1 7'h0; + else + if(!ep_bf_en | rc_clr) rc_cnt <= #1 7'h0; + else + if(mwe_r) rc_cnt <= #1 rc_cnt + 7'h1; + +assign rc_clr = ((rc_cnt == ep_bf_size) & mwe_r) | rx_dma_en; + +always @(posedge clk) + if(!rst) ep_full_latched <= #1 1'b0; + else + if(rc_clr) ep_full_latched <= #1 ep_full; + +assign ep_full_int = ep_bf_en ? ep_full_latched : ep_full; + +always @(posedge clk) + dropped_frame <= #1 rc_clr & ep_full & ep_bf_en; + +always @(posedge clk) + misaligned_frame <= #1 rx_data_done_r & ep_bf_en & (rc_cnt!=7'd00); +`else +assign ep_full_int = ep_full; + +always @(posedge clk) + dropped_frame <= #1 1'b0; + +always @(posedge clk) + misaligned_frame <= #1 1'b0; + +`endif + +// synopsys translate_off +`ifdef USBF_VERBOSE_DEBUG +always @(posedge dropped_frame) + $display("WARNING: BF: Droped one OUT frame (no space in FIFO) (%t)",$time); + +always @(posedge misaligned_frame) + $display("WARNING: BF: Received misaligned frame (%t)",$time); +`endif +// synopsys translate_on + +/////////////////////////////////////////////////////////////////// +// +// FIFO interface +// + +always @(posedge clk) + mwe_r <= #1 rx_data_valid; + +assign mwe = mwe_r & !ep_full_int; + +/////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +always @(posedge clk) + rx_data_valid_r <= #1 rx_data_valid; + +always @(posedge clk) + rx_data_done_r <= #1 rx_data_done; + +// Generate one cycle pulses for tx and rx dma enable +always @(posedge clk) + tx_dma_en_r <= #1 tx_dma_en; + +always @(posedge clk) + tx_dma_en_r1 <= tx_dma_en_r; + +always @(posedge clk) + tx_dma_en_r2 <= tx_dma_en_r1; + +always @(posedge clk) + tx_dma_en_r3 <= tx_dma_en_r2; + +// DMA Done Indicator +always @(posedge clk) + idma_done <= #1 (rx_data_done_r | sizd_is_zero_d | ep_empty_int); + +/////////////////////////////////////////////////////////////////// +// +// RX Size Counter +// + +always @(posedge clk or negedge rst) + if(!rst) rx_cnt_r <= #1 8'h00; + else + if(rx_data_done_r) rx_cnt_r <= #1 8'h00; + else + if(rx_data_valid) rx_cnt_r <= #1 rx_cnt_r + 8'h01; + +always @(posedge clk or negedge rst) + if(!rst) rx_cnt <= #1 8'h00; + else + if(rx_data_done_r) rx_cnt <= #1 rx_cnt_r; + +assign rx_done = rx_data_done_r; + +/////////////////////////////////////////////////////////////////// +// +// Transmit Size Counter (counting backward from input size) +// For MAX packet size +// + +always @(posedge clk or negedge rst) + if(!rst) sizd_c <= #1 9'h1ff; + else + if(tx_dma_en) sizd_c <= #1 size; + else + if(siz_dec) sizd_c <= #1 sizd_c - 9'h1; + +assign siz_dec = (tx_dma_en_r | tx_dma_en_r1 | rd_next) & !sizd_is_zero_d; + +assign sizd_is_zero_d = sizd_c == 9'h0; + +always @(posedge clk) + sizd_is_zero <= #1 sizd_is_zero_d; + +/////////////////////////////////////////////////////////////////// +// +// TX Logic +// + +assign tx_busy = send_data | tx_dma_en_r | tx_dma_en; + +always @(posedge clk) + tx_valid_r <= #1 tx_valid; + +assign tx_valid_e = tx_valid_r & !tx_valid; + +// Since we are prefetching two entries in to our fast fifo, we +// need to know when exactly ep_empty was asserted, as we might +// only need 1 or 2 bytes. This is for ep_empty_r + +always @(posedge clk or negedge rst) + if(!rst) ep_empty_r <= #1 1'b0; + else + if(!tx_valid) ep_empty_r <= #1 1'b0; + else + if(tx_dma_en_r2) ep_empty_r <= #1 ep_empty_int; + +always @(posedge clk or negedge rst) + if(!rst) send_data_r <= #1 1'b0; + else + if((tx_dma_en_r & !ep_empty_int)) send_data_r <= #1 1'b1; + else + if(rd_next & (sizd_is_zero_d | (ep_empty_int & !sizd_is_zero_d)) ) + send_data_r <= #1 1'b0; + +assign send_data = (send_data_r & !ep_empty_r & + !(sizd_is_zero & size==9'h01)) | tx_dma_en_r1; + +assign mre = (tx_dma_en_r1 | tx_dma_en_r | rd_next) & + !sizd_is_zero_d & !ep_empty_int & (send_data | tx_dma_en_r1 | tx_dma_en_r); + +always @(posedge clk) + ff_we1 <= mre; + +always @(posedge clk) + ff_we <= ff_we1; + +assign ff_re = rd_next; + +assign ff_clr = !tx_valid; + +/////////////////////////////////////////////////////////////////// +// +// IDMA fast prefetch fifo +// + +// tx fifo +usb1d_fifo2 ff( + .clk( clk ), + .rst( rst ), + .clr( ff_clr ), + .din( tx_data_st_i ), + .we( ff_we ), + .dout( tx_data_st_o ), + .re( ff_re ) + ); + +endmodule + +
diff --git a/verilog/dv/bfm/usb_device/core/usb1d_pa.v b/verilog/dv/bfm/usb_device/core/usb1d_pa.v new file mode 100755 index 0000000..7bb70de --- /dev/null +++ b/verilog/dv/bfm/usb_device/core/usb1d_pa.v
@@ -0,0 +1,332 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// Packet Assembler //// +//// Assembles Token and Data USB packets //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb1_funct///// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// +//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// +//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// +//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// +//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// +//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// +//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// +//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// +//// POSSIBILITY OF SUCH DAMAGE. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usb1_pa.v,v 1.1.1.1 2002-09-19 12:07:13 rudi Exp $ +// +// $Date: 2002-09-19 12:07:13 $ +// $Revision: 1.1.1.1 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: not supported by cvs2svn $ +// +// +// +// +// +// + +`include "usb1d_defines.v" + +module usb1d_pa( clk, rst, + + // UTMI TX I/F + tx_data, tx_valid, tx_valid_last, tx_ready, + tx_first, + + // Protocol Engine Interface + send_token, token_pid_sel, + send_data, data_pid_sel, + + // IDMA Interface + tx_data_st, rd_next, + + ep_empty + ); + +input clk, rst; + +// UTMI TX Interface +output [7:0] tx_data; +output tx_valid; +output tx_valid_last; +input tx_ready; +output tx_first; + +// Protocol Engine Interface +input send_token; +input [1:0] token_pid_sel; +input send_data; +input [1:0] data_pid_sel; + +// IDMA Interface +input [7:0] tx_data_st; +output rd_next; + +input ep_empty; + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +parameter [3:0] // synopsys enum state + IDLE = 4'b0001, + DATA = 4'b0010, + CRC1 = 4'b0100, + CRC2 = 4'b1000; + +reg [3:0] /* synopsys enum state */ state, next_state; +// synopsys state_vector state + +reg last; +reg rd_next; + +reg [7:0] token_pid, data_pid; // PIDs from selectors +reg [7:0] tx_data_d; +reg [7:0] tx_data_data; +reg dsel; +reg tx_valid_d; +reg send_token_r; +reg [7:0] tx_spec_data; +reg crc_sel1, crc_sel2; +reg tx_first_r; +reg send_data_r; +wire crc16_clr; +reg [15:0] crc16; +wire [15:0] crc16_next; +wire [15:0] crc16_rev; +reg crc16_add; +reg send_data_r2; +reg tx_valid_r; +reg tx_valid_r1; + +wire zero_length; + +/////////////////////////////////////////////////////////////////// +// +// Misc Logic +// +reg zero_length_r; +assign zero_length = ep_empty; + +always @(posedge clk or negedge rst) + if(!rst) zero_length_r <= #1 1'b0; + else + if(last) zero_length_r <= #1 1'b0; + else + if(crc16_clr) zero_length_r <= #1 zero_length; + +always @(posedge clk) + tx_valid_r1 <= #1 tx_valid; + +always @(posedge clk) + tx_valid_r <= #1 tx_valid_r1; + +always @(posedge clk or negedge rst) + if(!rst) send_token_r <= #1 1'b0; + else + if(send_token) send_token_r <= #1 1'b1; + else + if(tx_ready) send_token_r <= #1 1'b0; + +// PID Select +always @(token_pid_sel) + case(token_pid_sel) // synopsys full_case parallel_case + 2'd0: token_pid = { ~`USBF_T_PID_ACK, `USBF_T_PID_ACK}; + 2'd1: token_pid = { ~`USBF_T_PID_NACK, `USBF_T_PID_NACK}; + 2'd2: token_pid = {~`USBF_T_PID_STALL, `USBF_T_PID_STALL}; + 2'd3: token_pid = { ~`USBF_T_PID_NYET, `USBF_T_PID_NYET}; + endcase + +always @(data_pid_sel) + case(data_pid_sel) // synopsys full_case parallel_case + 2'd0: data_pid = { ~`USBF_T_PID_DATA0, `USBF_T_PID_DATA0}; + 2'd1: data_pid = { ~`USBF_T_PID_DATA1, `USBF_T_PID_DATA1}; + 2'd2: data_pid = { ~`USBF_T_PID_DATA2, `USBF_T_PID_DATA2}; + 2'd3: data_pid = { ~`USBF_T_PID_MDATA, `USBF_T_PID_MDATA}; + endcase + +// Data path Muxes + +always @(send_token or send_token_r or token_pid or tx_data_data) + if(send_token | send_token_r) tx_data_d = token_pid; + else tx_data_d = tx_data_data; + +always @(dsel or tx_data_st or tx_spec_data) + if(dsel) tx_data_data = tx_spec_data; + else tx_data_data = tx_data_st; + +always @(crc_sel1 or crc_sel2 or data_pid or crc16_rev) + if(!crc_sel1 & !crc_sel2) tx_spec_data = data_pid; + else + if(crc_sel1) tx_spec_data = crc16_rev[15:8]; // CRC 1 + else tx_spec_data = crc16_rev[7:0]; // CRC 2 + +assign tx_data = tx_data_d; + +// TX Valid assignment +assign tx_valid_last = send_token | last; +assign tx_valid = tx_valid_d; + +always @(posedge clk) + tx_first_r <= #1 send_token | send_data; + +assign tx_first = (send_token | send_data) & ! tx_first_r; + +// CRC Logic +always @(posedge clk) + send_data_r <= #1 send_data; + +always @(posedge clk) + send_data_r2 <= #1 send_data_r; + +assign crc16_clr = send_data & !send_data_r; + +always @(posedge clk) + crc16_add <= #1 !zero_length_r & + ((send_data_r & !send_data_r2) | (rd_next & !crc_sel1)); + +always @(posedge clk) + if(crc16_clr) crc16 <= #1 16'hffff; + else + if(crc16_add) crc16 <= #1 crc16_next; + +usb1d_crc16 u1( + .crc_in( crc16 ), + .din( {tx_data_st[0], tx_data_st[1], + tx_data_st[2], tx_data_st[3], + tx_data_st[4], tx_data_st[5], + tx_data_st[6], tx_data_st[7]} ), + .crc_out( crc16_next ) ); + +assign crc16_rev[15] = ~crc16[8]; +assign crc16_rev[14] = ~crc16[9]; +assign crc16_rev[13] = ~crc16[10]; +assign crc16_rev[12] = ~crc16[11]; +assign crc16_rev[11] = ~crc16[12]; +assign crc16_rev[10] = ~crc16[13]; +assign crc16_rev[9] = ~crc16[14]; +assign crc16_rev[8] = ~crc16[15]; +assign crc16_rev[7] = ~crc16[0]; +assign crc16_rev[6] = ~crc16[1]; +assign crc16_rev[5] = ~crc16[2]; +assign crc16_rev[4] = ~crc16[3]; +assign crc16_rev[3] = ~crc16[4]; +assign crc16_rev[2] = ~crc16[5]; +assign crc16_rev[1] = ~crc16[6]; +assign crc16_rev[0] = ~crc16[7]; + +/////////////////////////////////////////////////////////////////// +// +// Transmit/Encode state machine +// + +always @(posedge clk or negedge rst) + if(!rst) state <= #1 IDLE; + else state <= #1 next_state; + +always @(state or send_data or tx_ready or tx_valid_r or zero_length) + begin + next_state = state; // Default don't change current state + tx_valid_d = 1'b0; + dsel = 1'b0; + rd_next = 1'b0; + last = 1'b0; + crc_sel1 = 1'b0; + crc_sel2 = 1'b0; + case(state) // synopsys full_case parallel_case + IDLE: + begin + if(zero_length & send_data) + begin + tx_valid_d = 1'b1; + dsel = 1'b1; + next_state = CRC1; + end + else + if(send_data) // Send DATA packet + begin + tx_valid_d = 1'b1; + dsel = 1'b1; + next_state = DATA; + end + end + DATA: + begin + if(tx_ready & tx_valid_r) + rd_next = 1'b1; + + tx_valid_d = 1'b1; + if(!send_data & tx_ready & tx_valid_r) + begin + dsel = 1'b1; + crc_sel1 = 1'b1; + next_state = CRC1; + end + end + CRC1: + begin + dsel = 1'b1; + tx_valid_d = 1'b1; + if(tx_ready) + begin + last = 1'b1; + crc_sel2 = 1'b1; + next_state = CRC2; + end + else + begin + tx_valid_d = 1'b1; + crc_sel1 = 1'b1; + end + + end + CRC2: + begin + dsel = 1'b1; + crc_sel2 = 1'b1; + if(tx_ready) + begin + next_state = IDLE; + end + else + begin + last = 1'b1; + end + + end + endcase + end + +endmodule +
diff --git a/verilog/dv/bfm/usb_device/core/usb1d_pd.v b/verilog/dv/bfm/usb_device/core/usb1d_pd.v new file mode 100755 index 0000000..7b2572b --- /dev/null +++ b/verilog/dv/bfm/usb_device/core/usb1d_pd.v
@@ -0,0 +1,398 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// Packet Disassembler //// +//// Disassembles Token and Data USB packets //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb1_funct///// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// +//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// +//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// +//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// +//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// +//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// +//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// +//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// +//// POSSIBILITY OF SUCH DAMAGE. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usb1_pd.v,v 1.2 2002-09-25 06:06:49 rudi Exp $ +// +// $Date: 2002-09-25 06:06:49 $ +// $Revision: 1.2 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: not supported by cvs2svn $ +// Revision 1.1.1.1 2002/09/19 12:07:17 rudi +// Initial Checkin +// +// +// +// +// +// +// +// + +`include "usb1d_defines.v" + +module usb1d_pd( clk, rst, + + // UTMI RX I/F + rx_data, rx_valid, rx_active, rx_err, + + // PID Information + pid_OUT, pid_IN, pid_SOF, pid_SETUP, + pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA, + pid_ACK, pid_NACK, pid_STALL, pid_NYET, + pid_PRE, pid_ERR, pid_SPLIT, pid_PING, + pid_cks_err, + + // Token Information + token_fadr, token_endp, token_valid, crc5_err, + frame_no, + + // Receive Data Output + rx_data_st, rx_data_valid, rx_data_done, crc16_err, + + // Misc. + seq_err, rx_busy + ); + +input clk, rst; + + //UTMI RX Interface +input [7:0] rx_data; +input rx_valid, rx_active, rx_err; + + // Decoded PIDs (used when token_valid is asserted) +output pid_OUT, pid_IN, pid_SOF, pid_SETUP; +output pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA; +output pid_ACK, pid_NACK, pid_STALL, pid_NYET; +output pid_PRE, pid_ERR, pid_SPLIT, pid_PING; +output pid_cks_err; // Indicates a PID checksum error + + +output [6:0] token_fadr; // Function address from token +output [3:0] token_endp; // Endpoint number from token +output token_valid; // Token is valid +output crc5_err; // Token crc5 error +output [10:0] frame_no; // Frame number for SOF tokens + +output [7:0] rx_data_st; // Data to memory store unit +output rx_data_valid; // Data on rx_data_st is valid +output rx_data_done; // Indicates end of a transfer +output crc16_err; // Data packet CRC 16 error + +output seq_err; // State Machine Sequence Error +output rx_busy; // Receivig Data Packet + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +parameter [3:0] // synopsys enum state + IDLE = 4'b0001, + ACTIVE = 4'b0010, + TOKEN = 4'b0100, + DATA = 4'b1000; + +reg [3:0] /* synopsys enum state */ state, next_state; +// synopsys state_vector state + +reg [7:0] pid; // Packet PDI +reg pid_le_sm; // PID Load enable from State Machine +wire pid_ld_en; // Enable loading of PID (all conditions) +wire pid_cks_err; // Indicates a pid checksum err + + // Decoded PID values +wire pid_OUT, pid_IN, pid_SOF, pid_SETUP; +wire pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA; +wire pid_ACK, pid_NACK, pid_STALL, pid_NYET; +wire pid_PRE, pid_ERR, pid_SPLIT, pid_PING, pid_RES; +wire pid_TOKEN; // All TOKEN packet that we recognize +wire pid_DATA; // All DATA packets that we recognize + +reg [7:0] token0, token1; // Token Registers +reg token_le_1, token_le_2; // Latch enables for token storage registers +wire [4:0] token_crc5; + +reg [7:0] d0, d1, d2; // Data path delay line (used to filter out crcs) +reg data_valid_d; // Data Valid output from State Machine +reg data_done; // Data cycle complete output from State Machine +reg data_valid0; // Data valid delay line +reg rxv1; +reg rxv2; + +reg seq_err; // State machine sequence error + +reg pid_ack; + +reg token_valid_r1; +reg token_valid_str1, token_valid_str2; + +reg rx_active_r; + +wire [4:0] crc5_out; +wire [4:0] crc5_out2; +wire crc16_clr; +reg [15:0] crc16_sum; +wire [15:0] crc16_out; + +/////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +reg rx_busy, rx_busy_d; + +always @(posedge clk or negedge rst) + if(!rst) rx_busy_d <= #1 1'b0; + else + if(rx_valid & (state == DATA)) rx_busy_d <= #1 1'b1; + else + if(state != DATA) rx_busy_d <= #1 1'b0; + +always @(posedge clk) + rx_busy <= #1 rx_busy_d; + +// PID Decoding Logic +assign pid_ld_en = pid_le_sm & rx_active & rx_valid; + +always @(posedge clk or negedge rst) + if(!rst) pid <= #1 8'hf0; + else + if(pid_ld_en) pid <= #1 rx_data; + +assign pid_cks_err = (pid[3:0] != ~pid[7:4]); + +assign pid_OUT = pid[3:0] == `USBF_T_PID_OUT; +assign pid_IN = pid[3:0] == `USBF_T_PID_IN; +assign pid_SOF = pid[3:0] == `USBF_T_PID_SOF; +assign pid_SETUP = pid[3:0] == `USBF_T_PID_SETUP; +assign pid_DATA0 = pid[3:0] == `USBF_T_PID_DATA0; +assign pid_DATA1 = pid[3:0] == `USBF_T_PID_DATA1; +assign pid_DATA2 = pid[3:0] == `USBF_T_PID_DATA2; +assign pid_MDATA = pid[3:0] == `USBF_T_PID_MDATA; +assign pid_ACK = pid[3:0] == `USBF_T_PID_ACK; +assign pid_NACK = pid[3:0] == `USBF_T_PID_NACK; +assign pid_STALL = pid[3:0] == `USBF_T_PID_STALL; +assign pid_NYET = pid[3:0] == `USBF_T_PID_NYET; +assign pid_PRE = pid[3:0] == `USBF_T_PID_PRE; +assign pid_ERR = pid[3:0] == `USBF_T_PID_ERR; +assign pid_SPLIT = pid[3:0] == `USBF_T_PID_SPLIT; +assign pid_PING = pid[3:0] == `USBF_T_PID_PING; +assign pid_RES = pid[3:0] == `USBF_T_PID_RES; + +assign pid_TOKEN = pid_OUT | pid_IN | pid_SOF | pid_SETUP | pid_PING; +assign pid_DATA = pid_DATA0 | pid_DATA1 | pid_DATA2 | pid_MDATA; + +// Token Decoding LOGIC +always @(posedge clk) + if(token_le_1) token0 <= #1 rx_data; + +always @(posedge clk) + if(token_le_2) token1 <= #1 rx_data; + +always @(posedge clk) + token_valid_r1 <= #1 token_le_2; + +always @(posedge clk) + token_valid_str1 <= #1 token_valid_r1 | pid_ack; + +always @(posedge clk) + token_valid_str2 <= #1 token_valid_str1; + +assign token_valid = token_valid_str1; + +// CRC 5 should perform the check in one cycle (flow through logic) +// 11 bits and crc5 input, 1 bit output +assign crc5_err = token_valid & (crc5_out2 != token_crc5); + +usb1d_crc5 u0( + .crc_in( 5'h1f ), + .din( { token_fadr[0], + token_fadr[1], + token_fadr[2], + token_fadr[3], + token_fadr[4], + token_fadr[5], + token_fadr[6], + token_endp[0], + token_endp[1], + token_endp[2], + token_endp[3] } ), + .crc_out( crc5_out ) ); + +// Invert and reverse result bits +assign crc5_out2 = ~{crc5_out[0], crc5_out[1], crc5_out[2], crc5_out[3], + crc5_out[4]}; + +assign frame_no = { token1[2:0], token0}; +assign token_fadr = token0[6:0]; +assign token_endp = {token1[2:0], token0[7]}; +assign token_crc5 = token1[7:3]; + +// Data receiving logic +// build a delay line and stop when we are about to get crc +always @(posedge clk or negedge rst) + if(!rst) rxv1 <= #1 1'b0; + else + if(data_valid_d) rxv1 <= #1 1'b1; + else + if(data_done) rxv1 <= #1 1'b0; + +always @(posedge clk or negedge rst) + if(!rst) rxv2 <= #1 1'b0; + else + if(rxv1 & data_valid_d) rxv2 <= #1 1'b1; + else + if(data_done) rxv2 <= #1 1'b0; + +always @(posedge clk) + data_valid0 <= #1 rxv2 & data_valid_d; + +always @(posedge clk) + begin + if(data_valid_d) d0 <= #1 rx_data; + if(data_valid_d) d1 <= #1 d0; + if(data_valid_d) d2 <= #1 d1; + end + +assign rx_data_st = d2; +assign rx_data_valid = data_valid0; +assign rx_data_done = data_done; + +// crc16 accumulates rx_data as long as data_valid_d is asserted. +// when data_done is asserted, crc16 reports status, and resets itself +// next cycle. +always @(posedge clk) + rx_active_r <= #1 rx_active; + +assign crc16_clr = rx_active & !rx_active_r; + +always @(posedge clk) + if(crc16_clr) crc16_sum <= #1 16'hffff; + else + if(data_valid_d) crc16_sum <= #1 crc16_out; + +usb1d_crc16 u1( + .crc_in( crc16_sum ), + .din( {rx_data[0], rx_data[1], rx_data[2], rx_data[3], + rx_data[4], rx_data[5], rx_data[6], rx_data[7]} ), + .crc_out( crc16_out ) ); + +// Verify against polynomial +assign crc16_err = data_done & (crc16_sum != 16'h800d); + +/////////////////////////////////////////////////////////////////// +// +// Receive/Decode State machine +// + +always @(posedge clk or negedge rst) + if(!rst) state <= #1 IDLE; + else state <= #1 next_state; + +always @(state or rx_valid or rx_active or rx_err or pid_ACK or pid_TOKEN + or pid_DATA) + begin + next_state = state; // Default don't change current state + pid_le_sm = 1'b0; + token_le_1 = 1'b0; + token_le_2 = 1'b0; + data_valid_d = 1'b0; + data_done = 1'b0; + seq_err = 1'b0; + pid_ack = 1'b0; + case(state) // synopsys full_case parallel_case + IDLE: + begin + pid_le_sm = 1'b1; + if(rx_valid & rx_active) next_state = ACTIVE; + end + ACTIVE: + begin + // Received a ACK from Host + if(pid_ACK & !rx_err) + begin + pid_ack = 1'b1; + if(!rx_active) next_state = IDLE; + end + else + // Receiving a TOKEN + if(pid_TOKEN & rx_valid & rx_active & !rx_err) + begin + token_le_1 = 1'b1; + next_state = TOKEN; + end + else + // Receiving DATA + if(pid_DATA & rx_valid & rx_active & !rx_err) + begin + data_valid_d = 1'b1; + next_state = DATA; + end + else + if( !rx_active | rx_err | + (rx_valid & !(pid_TOKEN | pid_DATA)) ) // ERROR + begin + seq_err = !rx_err; + if(!rx_active) next_state = IDLE; + end + end + TOKEN: + begin + if(rx_valid & rx_active & !rx_err) + begin + token_le_2 = 1'b1; + next_state = IDLE; + end + else + if(!rx_active | rx_err) // ERROR + begin + seq_err = !rx_err; + if(!rx_active) next_state = IDLE; + end + end + DATA: + begin + if(rx_valid & rx_active & !rx_err) data_valid_d = 1'b1; + if(!rx_active | rx_err) + begin + data_done = 1'b1; + if(!rx_active) next_state = IDLE; + end + end + + endcase + end + +endmodule +
diff --git a/verilog/dv/bfm/usb_device/core/usb1d_pe.v b/verilog/dv/bfm/usb_device/core/usb1d_pe.v new file mode 100755 index 0000000..c0daaff --- /dev/null +++ b/verilog/dv/bfm/usb_device/core/usb1d_pe.v
@@ -0,0 +1,836 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// Protocol Engine //// +//// Performs automatic protocol functions //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb1_funct///// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// +//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// +//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// +//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// +//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// +//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// +//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// +//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// +//// POSSIBILITY OF SUCH DAMAGE. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usb1_pe.v,v 1.1.1.1 2002-09-19 12:07:24 rudi Exp $ +// +// $Date: 2002-09-19 12:07:24 $ +// $Revision: 1.1.1.1 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: not supported by cvs2svn $ +// +// +// +// +// +// + +`include "usb1d_defines.v" + +module usb1d_pe( clk, rst, + + // UTMI Interfaces + tx_valid, rx_active, + + // PID Information + pid_OUT, pid_IN, pid_SOF, pid_SETUP, + pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA, + pid_ACK, pid_PING, + + // Token Information + token_valid, + + // Receive Data Output + rx_data_done, crc16_err, + + // Packet Assembler Interface + send_token, token_pid_sel, + data_pid_sel, + + // IDMA Interface + rx_dma_en, tx_dma_en, + abort, + idma_done, + + // Register File Interface + + fsel, + ep_sel, match, nse_err, + ep_full, ep_empty, + + int_upid_set, int_crc16_set, int_to_set, int_seqerr_set, + csr, + send_stall + + ); + +input clk, rst; +input tx_valid, rx_active; + +// Packet Disassembler Interface + // Decoded PIDs (used when token_valid is asserted) +input pid_OUT, pid_IN, pid_SOF, pid_SETUP; +input pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA; +input pid_ACK, pid_PING; + +input token_valid; // Token is valid + +input rx_data_done; // Indicates end of a transfer +input crc16_err; // Data packet CRC 16 error + +// Packet Assembler Interface +output send_token; +output [1:0] token_pid_sel; +output [1:0] data_pid_sel; + +// IDMA Interface +output rx_dma_en; // Allows the data to be stored +output tx_dma_en; // Allows for data to be retrieved +output abort; // Abort Transfer (time_out, crc_err or rx_error) +input idma_done; // DMA is done indicator + +input ep_full; // Indicates the endpoints fifo is full +input ep_empty; // Indicates the endpoints fifo is empty + +// Register File interface +input fsel; // This function is selected +input [3:0] ep_sel; // Endpoint Number Input +input match; // Endpoint Matched +output nse_err; // no such endpoint error + +output int_upid_set; // Set unsupported PID interrupt +output int_crc16_set; // Set CRC16 error interrupt +output int_to_set; // Set time out interrupt +output int_seqerr_set; // Set PID sequence error interrupt + +input [13:0] csr; // Internal CSR Output + +input send_stall; // Force sending a STALL during setup + + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +// tx token decoding +parameter ACK = 0, + NACK = 1, + STALL = 2, + NYET = 3; + +// State decoding +parameter [9:0] // synopsys enum state + IDLE = 10'b000000_0001, + TOKEN = 10'b000000_0010, + IN = 10'b000000_0100, + IN2 = 10'b000000_1000, + OUT = 10'b000001_0000, + OUT2A = 10'b000010_0000, + OUT2B = 10'b000100_0000, + UPDATEW = 10'b001000_0000, + UPDATE = 10'b010000_0000, + UPDATE2 = 10'b100000_0000; + +reg [1:0] token_pid_sel; +reg [1:0] token_pid_sel_d; +reg send_token; +reg send_token_d; +reg rx_dma_en, tx_dma_en; +reg int_seqerr_set_d; +reg int_seqerr_set; +reg int_upid_set; + +reg match_r; + +// Endpoint Decoding +wire IN_ep, OUT_ep, CTRL_ep; // Endpoint Types +wire txfr_iso, txfr_bulk, txfr_int; // Transfer Types + +reg [1:0] uc_dpd; + +// Buffer checks +reg [9:0] /* synopsys enum state */ state, next_state; +// synopsys state_vector state + +// PID next and current decoders +reg [1:0] next_dpid; +reg [1:0] this_dpid; +reg pid_seq_err; +wire [1:0] tr_fr_d; + +wire [13:0] size_next; +wire buf_smaller; + +// After sending Data in response to an IN token from host, the +// host must reply with an ack. The host has XXXnS to reply. +// "rx_ack_to" indicates when this time has expired. +// rx_ack_to_clr, clears the timer +reg rx_ack_to_clr; +reg rx_ack_to_clr_d; +reg rx_ack_to; +reg [7:0] rx_ack_to_cnt; + +// After sending a OUT token the host must send a data packet. +// The host has XX nS to send the packet. "tx_data_to" indicates +// when this time has expired. +// tx_data_to_clr, clears the timer +wire tx_data_to_clr; +reg tx_data_to; +reg [7:0] tx_data_to_cnt; + +wire [7:0] rx_ack_to_val, tx_data_to_val; + + +wire [1:0] next_bsel; +reg uc_stat_set_d; +reg uc_dpd_set; + +reg in_token; +reg out_token; +reg setup_token; + +wire in_op, out_op; // Indicate a IN or OUT operation + +reg [1:0] allow_pid; + +reg nse_err; +reg abort; + +wire [1:0] ep_type, txfr_type; + +/////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +// Endpoint/CSR Decoding +assign IN_ep = csr[9]; +assign OUT_ep = csr[10]; +assign CTRL_ep = csr[11]; + +assign txfr_iso = csr[12]; +assign txfr_bulk = csr[13]; +assign txfr_int = !csr[12] & !csr[13]; + +assign ep_type = csr[10:9]; +assign txfr_type = csr[13:12]; + +always @(posedge clk) + match_r <= #1 match & fsel; + +// No Such Endpoint Indicator +always @(posedge clk) + nse_err <= #1 token_valid & (pid_OUT | pid_IN | pid_SETUP) & !match; + +always @(posedge clk) + send_token <= #1 send_token_d; + +always @(posedge clk) + token_pid_sel <= #1 token_pid_sel_d; + +/////////////////////////////////////////////////////////////////// +// +// Data Pid Storage +// + +reg [1:0] ep0_dpid, ep1_dpid, ep2_dpid, ep3_dpid; +reg [1:0] ep4_dpid, ep5_dpid, ep6_dpid, ep7_dpid; + +always @(posedge clk or negedge rst) + if(!rst) ep0_dpid <= 2'b00; + else + if(uc_dpd_set & (ep_sel == 4'h0)) ep0_dpid <= next_dpid; + +always @(posedge clk or negedge rst) + if(!rst) ep1_dpid <= 2'b00; + else + if(uc_dpd_set & (ep_sel == 4'h1)) ep1_dpid <= next_dpid; + +always @(posedge clk or negedge rst) + if(!rst) ep2_dpid <= 2'b00; + else + if(uc_dpd_set & (ep_sel == 4'h2)) ep2_dpid <= next_dpid; + +always @(posedge clk or negedge rst) + if(!rst) ep3_dpid <= 2'b00; + else + if(uc_dpd_set & (ep_sel == 4'h3)) ep3_dpid <= next_dpid; + +always @(posedge clk or negedge rst) + if(!rst) ep4_dpid <= 2'b00; + else + if(uc_dpd_set & (ep_sel == 4'h4)) ep4_dpid <= next_dpid; + +always @(posedge clk or negedge rst) + if(!rst) ep5_dpid <= 2'b00; + else + if(uc_dpd_set & (ep_sel == 4'h5)) ep5_dpid <= next_dpid; + +always @(posedge clk or negedge rst) + if(!rst) ep6_dpid <= 2'b00; + else + if(uc_dpd_set & (ep_sel == 4'h6)) ep6_dpid <= next_dpid; + +always @(posedge clk or negedge rst) + if(!rst) ep7_dpid <= 2'b00; + else + if(uc_dpd_set & (ep_sel == 4'h7)) ep7_dpid <= next_dpid; + +always @(posedge clk) + case(ep_sel) + 4'h0: uc_dpd <= ep0_dpid; + 4'h1: uc_dpd <= ep1_dpid; + 4'h2: uc_dpd <= ep2_dpid; + 4'h3: uc_dpd <= ep3_dpid; + 4'h4: uc_dpd <= ep4_dpid; + 4'h5: uc_dpd <= ep5_dpid; + 4'h6: uc_dpd <= ep6_dpid; + 4'h7: uc_dpd <= ep7_dpid; + endcase + +/////////////////////////////////////////////////////////////////// +// +// Data Pid Sequencer +// + +assign tr_fr_d = 2'h0; + +always @(posedge clk) // tr/mf:ep/type:tr/type:last dpd + casex({tr_fr_d,ep_type,txfr_type,uc_dpd}) // synopsys full_case parallel_case + 8'b0?_01_01_??: next_dpid <= #1 2'b00; // ISO txfr. IN, 1 tr/mf + + 8'b10_01_01_?0: next_dpid <= #1 2'b01; // ISO txfr. IN, 2 tr/mf + 8'b10_01_01_?1: next_dpid <= #1 2'b00; // ISO txfr. IN, 2 tr/mf + + 8'b11_01_01_00: next_dpid <= #1 2'b01; // ISO txfr. IN, 3 tr/mf + 8'b11_01_01_01: next_dpid <= #1 2'b10; // ISO txfr. IN, 3 tr/mf + 8'b11_01_01_10: next_dpid <= #1 2'b00; // ISO txfr. IN, 3 tr/mf + + 8'b0?_10_01_??: next_dpid <= #1 2'b00; // ISO txfr. OUT, 1 tr/mf + + 8'b10_10_01_??: // ISO txfr. OUT, 2 tr/mf + begin // Resynchronize in case of PID error + case({pid_MDATA, pid_DATA1}) // synopsys full_case parallel_case + 2'b10: next_dpid <= #1 2'b01; + 2'b01: next_dpid <= #1 2'b00; + endcase + end + + 8'b11_10_01_00: // ISO txfr. OUT, 3 tr/mf + begin // Resynchronize in case of PID error + case({pid_MDATA, pid_DATA2}) // synopsys full_case parallel_case + 2'b10: next_dpid <= #1 2'b01; + 2'b01: next_dpid <= #1 2'b00; + endcase + end + 8'b11_10_01_01: // ISO txfr. OUT, 3 tr/mf + begin // Resynchronize in case of PID error + case({pid_MDATA, pid_DATA2}) // synopsys full_case parallel_case + 2'b10: next_dpid <= #1 2'b10; + 2'b01: next_dpid <= #1 2'b00; + endcase + end + 8'b11_10_01_10: // ISO txfr. OUT, 3 tr/mf + begin // Resynchronize in case of PID error + case({pid_MDATA, pid_DATA2}) // synopsys full_case parallel_case + 2'b10: next_dpid <= #1 2'b01; + 2'b01: next_dpid <= #1 2'b00; + endcase + end + + 8'b??_01_00_?0, // IN/OUT endpoint only + 8'b??_10_00_?0: next_dpid <= #1 2'b01; // INT transfers + + 8'b??_01_00_?1, // IN/OUT endpoint only + 8'b??_10_00_?1: next_dpid <= #1 2'b00; // INT transfers + + 8'b??_01_10_?0, // IN/OUT endpoint only + 8'b??_10_10_?0: next_dpid <= #1 2'b01; // BULK transfers + + 8'b??_01_10_?1, // IN/OUT endpoint only + 8'b??_10_10_?1: next_dpid <= #1 2'b00; // BULK transfers + + 8'b??_00_??_??: // CTRL Endpoint + casex({setup_token, in_op, out_op, uc_dpd}) // synopsys full_case parallel_case + 5'b1_??_??: next_dpid <= #1 2'b11; // SETUP operation + 5'b0_10_0?: next_dpid <= #1 2'b11; // IN operation + 5'b0_10_1?: next_dpid <= #1 2'b01; // IN operation + 5'b0_01_?0: next_dpid <= #1 2'b11; // OUT operation + 5'b0_01_?1: next_dpid <= #1 2'b10; // OUT operation + endcase + + endcase + +// Current PID decoder + +// Allow any PID for ISO. transfers when mode full speed or tr_fr is zero +always @(pid_DATA0 or pid_DATA1 or pid_DATA2 or pid_MDATA) + case({pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA} ) // synopsys full_case parallel_case + 4'b1000: allow_pid = 2'b00; + 4'b0100: allow_pid = 2'b01; + 4'b0010: allow_pid = 2'b10; + 4'b0001: allow_pid = 2'b11; + endcase + +always @(posedge clk) // tf/mf:ep/type:tr/type:last dpd + casex({tr_fr_d,ep_type,txfr_type,uc_dpd}) // synopsys full_case parallel_case + 8'b0?_01_01_??: this_dpid <= #1 2'b00; // ISO txfr. IN, 1 tr/mf + + 8'b10_01_01_?0: this_dpid <= #1 2'b01; // ISO txfr. IN, 2 tr/mf + 8'b10_01_01_?1: this_dpid <= #1 2'b00; // ISO txfr. IN, 2 tr/mf + + 8'b11_01_01_00: this_dpid <= #1 2'b10; // ISO txfr. IN, 3 tr/mf + 8'b11_01_01_01: this_dpid <= #1 2'b01; // ISO txfr. IN, 3 tr/mf + 8'b11_01_01_10: this_dpid <= #1 2'b00; // ISO txfr. IN, 3 tr/mf + + 8'b00_10_01_??: this_dpid <= #1 allow_pid; // ISO txfr. OUT, 0 tr/mf + 8'b01_10_01_??: this_dpid <= #1 2'b00; // ISO txfr. OUT, 1 tr/mf + + 8'b10_10_01_?0: this_dpid <= #1 2'b11; // ISO txfr. OUT, 2 tr/mf + 8'b10_10_01_?1: this_dpid <= #1 2'b01; // ISO txfr. OUT, 2 tr/mf + + 8'b11_10_01_00: this_dpid <= #1 2'b11; // ISO txfr. OUT, 3 tr/mf + 8'b11_10_01_01: this_dpid <= #1 2'b11; // ISO txfr. OUT, 3 tr/mf + 8'b11_10_01_10: this_dpid <= #1 2'b10; // ISO txfr. OUT, 3 tr/mf + + 8'b??_01_00_?0, // IN/OUT endpoint only + 8'b??_10_00_?0: this_dpid <= #1 2'b00; // INT transfers + 8'b??_01_00_?1, // IN/OUT endpoint only + 8'b??_10_00_?1: this_dpid <= #1 2'b01; // INT transfers + + 8'b??_01_10_?0, // IN/OUT endpoint only + 8'b??_10_10_?0: this_dpid <= #1 2'b00; // BULK transfers + 8'b??_01_10_?1, // IN/OUT endpoint only + 8'b??_10_10_?1: this_dpid <= #1 2'b01; // BULK transfers + + 8'b??_00_??_??: // CTRL Endpoint + casex({setup_token,in_op, out_op, uc_dpd}) // synopsys full_case parallel_case + 5'b1_??_??: this_dpid <= #1 2'b00; // SETUP operation + 5'b0_10_0?: this_dpid <= #1 2'b00; // IN operation + 5'b0_10_1?: this_dpid <= #1 2'b01; // IN operation + 5'b0_01_?0: this_dpid <= #1 2'b00; // OUT operation + 5'b0_01_?1: this_dpid <= #1 2'b01; // OUT operation + endcase + endcase + +// Assign PID for outgoing packets +assign data_pid_sel = this_dpid; + +// Verify PID for incoming data packets +always @(posedge clk) + pid_seq_err <= #1 !( (this_dpid==2'b00 & pid_DATA0) | + (this_dpid==2'b01 & pid_DATA1) | + (this_dpid==2'b10 & pid_DATA2) | + (this_dpid==2'b11 & pid_MDATA) ); + +/////////////////////////////////////////////////////////////////// +// +// IDMA Setup & src/dst buffer select +// + +// For Control endpoints things are different: +// buffer0 is used for OUT (incoming) data packets +// buffer1 is used for IN (outgoing) data packets + +// Keep track of last token for control endpoints +always @(posedge clk or negedge rst) + if(!rst) in_token <= #1 1'b0; + else + if(pid_IN) in_token <= #1 1'b1; + else + if(pid_OUT | pid_SETUP) in_token <= #1 1'b0; + +always @(posedge clk or negedge rst) + if(!rst) out_token <= #1 1'b0; + else + if(pid_OUT | pid_SETUP) out_token <= #1 1'b1; + else + if(pid_IN) out_token <= #1 1'b0; + +always @(posedge clk or negedge rst) + if(!rst) setup_token <= #1 1'b0; + else + if(pid_SETUP) setup_token <= #1 1'b1; + else + if(pid_OUT | pid_IN) setup_token <= #1 1'b0; + +// Indicates if we are performing an IN operation +assign in_op = IN_ep | (CTRL_ep & in_token); + +// Indicates if we are performing an OUT operation +assign out_op = OUT_ep | (CTRL_ep & out_token); + + +/////////////////////////////////////////////////////////////////// +// +// Determine if packet is to small or to large +// This is used to NACK and ignore packet for OUT endpoints +// + + +/////////////////////////////////////////////////////////////////// +// +// Register File Update Logic +// + +always @(posedge clk) + uc_dpd_set <= #1 uc_stat_set_d; + +// Abort signal +always @(posedge clk) + abort <= #1 match & fsel & (state != IDLE); + +/////////////////////////////////////////////////////////////////// +// +// TIME OUT TIMERS +// + +// After sending Data in response to an IN token from host, the +// host must reply with an ack. The host has 622nS in Full Speed +// mode and 400nS in High Speed mode to reply. +// "rx_ack_to" indicates when this time has expired. +// rx_ack_to_clr, clears the timer + +always @(posedge clk) + rx_ack_to_clr <= #1 tx_valid | rx_ack_to_clr_d; + +always @(posedge clk) + if(rx_ack_to_clr) rx_ack_to_cnt <= #1 8'h0; + else rx_ack_to_cnt <= #1 rx_ack_to_cnt + 8'h1; + +always @(posedge clk) + rx_ack_to <= #1 (rx_ack_to_cnt == rx_ack_to_val); + +assign rx_ack_to_val = `USBF_RX_ACK_TO_VAL_FS; + +// After sending a OUT token the host must send a data packet. +// The host has 622nS in Full Speed mode and 400nS in High Speed +// mode to send the data packet. +// "tx_data_to" indicates when this time has expired. +// "tx_data_to_clr" clears the timer + +assign tx_data_to_clr = rx_active; + +always @(posedge clk) + if(tx_data_to_clr) tx_data_to_cnt <= #1 8'h0; + else tx_data_to_cnt <= #1 tx_data_to_cnt + 8'h1; + +always @(posedge clk) + tx_data_to <= #1 (tx_data_to_cnt == tx_data_to_val); + +assign tx_data_to_val = `USBF_TX_DATA_TO_VAL_FS; + +/////////////////////////////////////////////////////////////////// +// +// Interrupts +// +reg pid_OUT_r, pid_IN_r, pid_PING_r, pid_SETUP_r; + +always @(posedge clk) + pid_OUT_r <= #1 pid_OUT; + +always @(posedge clk) + pid_IN_r <= #1 pid_IN; + +always @(posedge clk) + pid_PING_r <= #1 pid_PING; + +always @(posedge clk) + pid_SETUP_r <= #1 pid_SETUP; + +always @(posedge clk) + int_upid_set <= #1 match_r & !pid_SOF & ( + ( OUT_ep & !(pid_OUT_r | pid_PING_r)) | + ( IN_ep & !pid_IN_r) | + (CTRL_ep & !(pid_IN_r | pid_OUT_r | pid_PING_r | pid_SETUP_r)) + ); + + +assign int_to_set = ((state == IN2) & rx_ack_to) | ((state == OUT) & tx_data_to); + +assign int_crc16_set = rx_data_done & crc16_err; + +always @(posedge clk) + int_seqerr_set <= #1 int_seqerr_set_d; + +reg send_stall_r; + +always @(posedge clk or negedge rst) + if(!rst) send_stall_r <= #1 1'b0; + else + if(send_stall) send_stall_r <= #1 1'b1; + else + if(send_token) send_stall_r <= #1 1'b0; + +/////////////////////////////////////////////////////////////////// +// +// Main Protocol State Machine +// + +always @(posedge clk or negedge rst) + if(!rst) state <= #1 IDLE; + else + if(match) state <= #1 IDLE; + else state <= #1 next_state; + +always @(state or + pid_seq_err or idma_done or ep_full or ep_empty or + token_valid or pid_ACK or rx_data_done or + tx_data_to or crc16_err or + rx_ack_to or pid_PING or txfr_iso or txfr_int or + CTRL_ep or pid_IN or pid_OUT or IN_ep or OUT_ep or pid_SETUP or pid_SOF + or match_r or abort or send_stall_r + ) + begin + next_state = state; + token_pid_sel_d = ACK; + send_token_d = 1'b0; + rx_dma_en = 1'b0; + tx_dma_en = 1'b0; + uc_stat_set_d = 1'b0; + rx_ack_to_clr_d = 1'b1; + int_seqerr_set_d = 1'b0; + + case(state) // synopsys full_case parallel_case + IDLE: + begin +// synopsys translate_off +`ifdef USBF_VERBOSE_DEBUG + $display("PE: Entered state IDLE (%t)", $time); +`endif +`ifdef USBF_DEBUG + if(rst & match_r & !pid_SOF) + begin + if(match_r === 1'bx) $display("ERROR: IDLE: match_r is unknown. (%t)", $time); + if(pid_SOF === 1'bx) $display("ERROR: IDLE: pid_SOF is unknown. (%t)", $time); + if(CTRL_ep === 1'bx) $display("ERROR: IDLE: CTRL_ep is unknown. (%t)", $time); + if(pid_IN === 1'bx) $display("ERROR: IDLE: pid_IN is unknown. (%t)", $time); + if(pid_OUT === 1'bx) $display("ERROR: IDLE: pid_OUT is unknown. (%t)", $time); + if(pid_SETUP === 1'bx) $display("ERROR: IDLE: pid_SETUP is unknown. (%t)", $time); + if(pid_PING === 1'bx) $display("ERROR: IDLE: pid_PING is unknown. (%t)", $time); + if(IN_ep === 1'bx) $display("ERROR: IDLE: IN_ep is unknown. (%t)", $time); + if(OUT_ep === 1'bx) $display("ERROR: IDLE: OUT_ep is unknown. (%t)", $time); + end +`endif +// synopsys translate_on + + if(match_r & !pid_SOF) + begin +/* + if(ep_stall) // Halt Forced send STALL + begin + token_pid_sel_d = STALL; + send_token_d = 1'b1; + next_state = TOKEN; + end + else +*/ + if(IN_ep | (CTRL_ep & pid_IN)) + begin + if(txfr_int & ep_empty) + begin + token_pid_sel_d = NACK; + send_token_d = 1'b1; + next_state = TOKEN; + end + else + begin + tx_dma_en = 1'b1; + next_state = IN; + end + end + else + if(OUT_ep | (CTRL_ep & (pid_OUT | pid_SETUP))) + begin + rx_dma_en = 1'b1; + next_state = OUT; + end + end + end + + TOKEN: + begin +// synopsys translate_off +`ifdef USBF_VERBOSE_DEBUG + $display("PE: Entered state TOKEN (%t)", $time); +`endif +// synopsys translate_on + next_state = IDLE; + end + + IN: + begin +// synopsys translate_off +`ifdef USBF_VERBOSE_DEBUG + $display("PE: Entered state IN (%t)", $time); +`endif +`ifdef USBF_DEBUG + if(idma_done === 1'bx) $display("ERROR: IN: idma_done is unknown. (%t)", $time); + if(txfr_iso === 1'bx) $display("ERROR: IN: txfr_iso is unknown. (%t)", $time); +`endif +// synopsys translate_on + rx_ack_to_clr_d = 1'b0; + if(idma_done) + begin + if(txfr_iso) next_state = UPDATE; + else next_state = IN2; + end + + end + IN2: + begin +// synopsys translate_off +`ifdef USBF_VERBOSE_DEBUG + $display("PE: Entered state IN2 (%t)", $time); +`endif +`ifdef USBF_DEBUG + if(rx_ack_to === 1'bx) $display("ERROR: IN2: rx_ack_to is unknown. (%t)", $time); + if(token_valid === 1'bx)$display("ERROR: IN2: token_valid is unknown. (%t)", $time); + if(pid_ACK === 1'bx) $display("ERROR: IN2: pid_ACK is unknown. (%t)", $time); +`endif +// synopsys translate_on + rx_ack_to_clr_d = 1'b0; + // Wait for ACK from HOST or Timeout + if(rx_ack_to) next_state = IDLE; + else + if(token_valid & pid_ACK) + begin + next_state = UPDATE; + end + end + + OUT: + begin +// synopsys translate_off +`ifdef USBF_VERBOSE_DEBUG + $display("PE: Entered state OUT (%t)", $time); +`endif +`ifdef USBF_DEBUG + if(tx_data_to === 1'bx) $display("ERROR: OUT: tx_data_to is unknown. (%t)", $time); + if(crc16_err === 1'bx) $display("ERROR: OUT: crc16_err is unknown. (%t)", $time); + if(abort === 1'bx) $display("ERROR: OUT: abort is unknown. (%t)", $time); + if(rx_data_done === 1'bx)$display("ERROR: OUT: rx_data_done is unknown. (%t)", $time); + if(txfr_iso === 1'bx) $display("ERROR: OUT: txfr_iso is unknown. (%t)", $time); + if(pid_seq_err === 1'bx)$display("ERROR: OUT: rx_data_done is unknown. (%t)", $time); +`endif +// synopsys translate_on + if(tx_data_to | crc16_err | abort ) + next_state = IDLE; + else + if(rx_data_done) + begin // Send Ack + if(txfr_iso) + begin + if(pid_seq_err) int_seqerr_set_d = 1'b1; + next_state = UPDATEW; + end + else next_state = OUT2A; + end + end + + OUT2B: + begin // This is a delay State to NACK to small or to + // large packets. this state could be skipped +// synopsys translate_off +`ifdef USBF_VERBOSE_DEBUG + $display("PE: Entered state OUT2B (%t)", $time); +`endif +`ifdef USBF_DEBUG + if(abort === 1'bx) $display("ERROR: OUT2A: abort is unknown. (%t)", $time); +`endif +// synopsys translate_on + if(abort) next_state = IDLE; + else next_state = OUT2B; + end + OUT2A: + begin // Send ACK/NACK/NYET +// synopsys translate_off +`ifdef USBF_VERBOSE_DEBUG + $display("PE: Entered state OUT2A (%t)", $time); +`endif +`ifdef USBF_DEBUG + if(abort === 1'bx) $display("ERROR: OUT2A: abort is unknown. (%t)", $time); + if(pid_seq_err === 1'bx)$display("ERROR: OUT2A: rx_data_done is unknown. (%t)", $time); +`endif +// synopsys translate_on + if(abort) next_state = IDLE; + else + + if(send_stall_r) + begin + token_pid_sel_d = STALL; + send_token_d = 1'b1; + next_state = IDLE; + end + else + if(ep_full) + begin + token_pid_sel_d = NACK; + send_token_d = 1'b1; + next_state = IDLE; + end + else + begin + token_pid_sel_d = ACK; + send_token_d = 1'b1; + if(pid_seq_err) next_state = IDLE; + else next_state = UPDATE; + end + end + + UPDATEW: + begin +// synopsys translate_off +`ifdef USBF_VERBOSE_DEBUG + $display("PE: Entered state UPDATEW (%t)", $time); +`endif +// synopsys translate_on + next_state = UPDATE; + end + + UPDATE: + begin +// synopsys translate_off +`ifdef USBF_VERBOSE_DEBUG + $display("PE: Entered state UPDATE (%t)", $time); +`endif +// synopsys translate_on + uc_stat_set_d = 1'b1; + next_state = IDLE; + end + endcase + end + +endmodule +
diff --git a/verilog/dv/bfm/usb_device/core/usb1d_pl.v b/verilog/dv/bfm/usb_device/core/usb1d_pl.v new file mode 100755 index 0000000..a8a281c --- /dev/null +++ b/verilog/dv/bfm/usb_device/core/usb1d_pl.v
@@ -0,0 +1,419 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// Protocol Layer //// +//// This block is typically referred to as the SEI in USB //// +//// Specification. It encapsulates the Packet Assembler, //// +//// disassembler, protocol engine and internal DMA //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb1_fucnt///// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// +//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// +//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// +//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// +//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// +//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// +//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// +//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// +//// POSSIBILITY OF SUCH DAMAGE. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usb1_pl.v,v 1.2 2002-09-25 06:06:49 rudi Exp $ +// +// $Date: 2002-09-25 06:06:49 $ +// $Revision: 1.2 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: not supported by cvs2svn $ +// Revision 1.1.1.1 2002/09/19 12:07:28 rudi +// Initial Checkin +// +// +// +// +// +// +// +// +// +`include "usb1d_defines.v" + +module usb1d_pl( clk, rst, + + // UTMI Interface + rx_data, rx_valid, rx_active, rx_err, + tx_data, tx_valid, tx_valid_last, tx_ready, + tx_first, tx_valid_out, + + token_valid, + + // Register File Interface + fa, + ep_sel, + x_busy, + int_crc16_set, int_to_set, int_seqerr_set, + + // Misc + frm_nat, + pid_cs_err, nse_err, + crc5_err, + rx_size, rx_done, + ctrl_setup, ctrl_in, ctrl_out, + + // Block Frames + ep_bf_en, ep_bf_size, + dropped_frame, misaligned_frame, + + // EP Interface + csr, + tx_data_st, + rx_ctrl_data, + rx_ctrl_data_d, + rx_ctrl_dvalid, + rx_ctrl_ddone, + idma_re, idma_we, + ep_empty, ep_full, send_stall + + ); + +// UTMI Interface +input clk, rst; +input [7:0] rx_data; +input rx_valid, rx_active, rx_err; +output [7:0] tx_data; +output tx_valid; +output tx_valid_last; +input tx_ready; +output tx_first; +input tx_valid_out; + +output token_valid; + +// Register File interface +input [6:0] fa; // Function Address (as set by the controller) +output [3:0] ep_sel; // Endpoint Number Input +output x_busy; // Indicates USB is busy + +output int_crc16_set; // Set CRC16 error interrupt +output int_to_set; // Set time out interrupt +output int_seqerr_set; // Set PID sequence error interrupt + +// Misc +output pid_cs_err; // pid checksum error +output crc5_err; // crc5 error +output [31:0] frm_nat; +output nse_err; // no such endpoint error +output [7:0] rx_size; +output rx_done; +output ctrl_setup; +output ctrl_in; +output ctrl_out; +input ep_bf_en; +input [6:0] ep_bf_size; +output dropped_frame, misaligned_frame; + +// Endpoint Interfaces +input [13:0] csr; +input [7:0] tx_data_st; +output [7:0] rx_ctrl_data; +output [7:0] rx_ctrl_data_d; +output rx_ctrl_dvalid; +output rx_ctrl_ddone; +output idma_re, idma_we; +input ep_empty; +input ep_full; + +input send_stall; + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +// Packet Disassembler Interface +wire clk, rst; +wire [7:0] rx_data; +wire pid_OUT, pid_IN, pid_SOF, pid_SETUP; +wire pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA; +wire pid_ACK, pid_NACK, pid_STALL, pid_NYET; +wire pid_PRE, pid_ERR, pid_SPLIT, pid_PING; +wire [6:0] token_fadr; +wire token_valid; +wire crc5_err; +wire [10:0] frame_no; +wire [7:0] rx_ctrl_data; +reg [7:0] rx_ctrl_data_d; +wire rx_ctrl_dvalid; +wire rx_ctrl_ddone; +wire crc16_err; +wire rx_seq_err; + +// Packet Assembler Interface +wire send_token; +wire [1:0] token_pid_sel; +wire send_data; +wire [1:0] data_pid_sel; +wire [7:0] tx_data_st; +wire [7:0] tx_data_st_o; +wire rd_next; + +// IDMA Interface +wire rx_dma_en; // Allows the data to be stored +wire tx_dma_en; // Allows for data to be retrieved +wire abort; // Abort Transfer (time_out, crc_err or rx_error) +wire idma_done; // DMA is done + +// Memory Arbiter Interface +wire idma_we; +wire idma_re; + +// Local signals +wire pid_bad; + +reg hms_clk; // 0.5 Micro Second Clock +reg [4:0] hms_cnt; +reg [10:0] frame_no_r; // Current Frame Number register +wire frame_no_we; +reg [11:0] sof_time; // Time since last sof +reg clr_sof_time; +wire fsel; // This Function is selected +wire match_o; + +reg frame_no_we_r; +reg ctrl_setup; +reg ctrl_in; +reg ctrl_out; + +wire idma_we_d; +wire ep_empty_int; +wire rx_busy; +wire tx_busy; + +/////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +assign x_busy = tx_busy | rx_busy; + +// PIDs we should never receive +assign pid_bad = pid_ACK | pid_NACK | pid_STALL | pid_NYET | pid_PRE | + pid_ERR | pid_SPLIT | pid_PING; + +assign match_o = !pid_bad & token_valid & !crc5_err; + +// Receiving Setup +always @(posedge clk) + ctrl_setup <= #1 token_valid & pid_SETUP & (ep_sel==4'h0); + +always @(posedge clk) + ctrl_in <= #1 token_valid & pid_IN & (ep_sel==4'h0); + +always @(posedge clk) + ctrl_out <= #1 token_valid & pid_OUT & (ep_sel==4'h0); + +// Frame Number (from SOF token) +assign frame_no_we = token_valid & !crc5_err & pid_SOF; + +always @(posedge clk) + frame_no_we_r <= #1 frame_no_we; + +always @(posedge clk or negedge rst) + if(!rst) frame_no_r <= #1 11'h0; + else + if(frame_no_we_r) frame_no_r <= #1 frame_no; + +//SOF delay counter +always @(posedge clk) + clr_sof_time <= #1 frame_no_we; + +always @(posedge clk) + if(clr_sof_time) sof_time <= #1 12'h0; + else + if(hms_clk) sof_time <= #1 sof_time + 12'h1; + +assign frm_nat = {4'h0, 1'b0, frame_no_r, 4'h0, sof_time}; + +// 0.5 Micro Seconds Clock Generator +always @(posedge clk or negedge rst) + if(!rst) hms_cnt <= #1 5'h0; + else + if(hms_clk | frame_no_we_r) hms_cnt <= #1 5'h0; + else hms_cnt <= #1 hms_cnt + 5'h1; + +always @(posedge clk) + hms_clk <= #1 (hms_cnt == `USBF_HMS_DEL); + +always @(posedge clk) + rx_ctrl_data_d <= rx_ctrl_data; + +/////////////////////////////////////////////////////////////////// + +// This function is addressed +assign fsel = (token_fadr == fa); + +// Only write when we are addressed !!! +assign idma_we = idma_we_d & fsel; // moved full check to idma ... & !ep_full; + +/////////////////////////////////////////////////////////////////// +// +// Module Instantiations +// + +//Packet Decoder +usb1d_pd u0( .clk( clk ), + .rst( rst ), + + .rx_data( rx_data ), + .rx_valid( rx_valid ), + .rx_active( rx_active ), + .rx_err( rx_err ), + .pid_OUT( pid_OUT ), + .pid_IN( pid_IN ), + .pid_SOF( pid_SOF ), + .pid_SETUP( pid_SETUP ), + .pid_DATA0( pid_DATA0 ), + .pid_DATA1( pid_DATA1 ), + .pid_DATA2( pid_DATA2 ), + .pid_MDATA( pid_MDATA ), + .pid_ACK( pid_ACK ), + .pid_NACK( pid_NACK ), + .pid_STALL( pid_STALL ), + .pid_NYET( pid_NYET ), + .pid_PRE( pid_PRE ), + .pid_ERR( pid_ERR ), + .pid_SPLIT( pid_SPLIT ), + .pid_PING( pid_PING ), + .pid_cks_err( pid_cs_err ), + .token_fadr( token_fadr ), + .token_endp( ep_sel ), + .token_valid( token_valid ), + .crc5_err( crc5_err ), + .frame_no( frame_no ), + .rx_data_st( rx_ctrl_data ), + .rx_data_valid( rx_ctrl_dvalid ), + .rx_data_done( rx_ctrl_ddone ), + .crc16_err( crc16_err ), + .seq_err( rx_seq_err ), + .rx_busy( rx_busy ) + ); + +// Packet Assembler +usb1d_pa u1( .clk( clk ), + .rst( rst ), + .tx_data( tx_data ), + .tx_valid( tx_valid ), + .tx_valid_last( tx_valid_last ), + .tx_ready( tx_ready ), + .tx_first( tx_first ), + .send_token( send_token ), + .token_pid_sel( token_pid_sel ), + .send_data( send_data ), + .data_pid_sel( data_pid_sel ), + .tx_data_st( tx_data_st_o ), + .rd_next( rd_next ), + .ep_empty( ep_empty_int) + ); + +// Internal DMA / Memory Arbiter Interface +usb1d_idma + u2( .clk( clk ), + .rst( rst ), + + .tx_valid( tx_valid ), + .rx_data_valid( rx_ctrl_dvalid ), + .rx_data_done( rx_ctrl_ddone ), + .send_data( send_data ), + .rd_next( rd_next ), + + .tx_data_st_i( tx_data_st ), + .tx_data_st_o( tx_data_st_o ), + .ep_sel( ep_sel ), + + .ep_bf_en( ep_bf_en ), + .ep_bf_size( ep_bf_size ), + .dropped_frame(dropped_frame ), + .misaligned_frame(misaligned_frame), + + .tx_busy( tx_busy ), + + .tx_dma_en( tx_dma_en ), + .rx_dma_en( rx_dma_en ), + .idma_done( idma_done ), + .size( csr[8:0] ), + .rx_cnt( rx_size ), + .rx_done( rx_done ), + .mwe( idma_we_d ), + .mre( idma_re ), + .ep_empty( ep_empty ), + .ep_empty_int( ep_empty_int ), + .ep_full( ep_full ) + ); + +// Protocol Engine +usb1d_pe + u3( .clk( clk ), + .rst( rst ), + + .tx_valid( tx_valid_out ), + .rx_active( rx_active ), + .pid_OUT( pid_OUT ), + .pid_IN( pid_IN ), + .pid_SOF( pid_SOF ), + .pid_SETUP( pid_SETUP ), + .pid_DATA0( pid_DATA0 ), + .pid_DATA1( pid_DATA1 ), + .pid_DATA2( pid_DATA2 ), + .pid_MDATA( pid_MDATA ), + .pid_ACK( pid_ACK ), + .pid_PING( pid_PING ), + .token_valid( token_valid ), + .rx_data_done( rx_ctrl_ddone ), + .crc16_err( crc16_err ), + .send_token( send_token ), + .token_pid_sel( token_pid_sel ), + .data_pid_sel( data_pid_sel ), + .rx_dma_en( rx_dma_en ), + .tx_dma_en( tx_dma_en ), + .abort( abort ), + .idma_done( idma_done ), + .fsel( fsel ), + .ep_sel( ep_sel ), + .ep_full( ep_full ), + .ep_empty( ep_empty ), + .match( match_o ), + .nse_err( nse_err ), + .int_upid_set( ), + .int_crc16_set( int_crc16_set ), + .int_to_set( int_to_set ), + .int_seqerr_set( int_seqerr_set ), + .csr( csr ), + .send_stall( send_stall ) + ); + +endmodule
diff --git a/verilog/dv/bfm/usb_device/core/usb1d_rom1.v b/verilog/dv/bfm/usb_device/core/usb1d_rom1.v new file mode 100755 index 0000000..9e753f6 --- /dev/null +++ b/verilog/dv/bfm/usb_device/core/usb1d_rom1.v
@@ -0,0 +1,243 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// Descriptor ROM //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb1_funct///// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// +//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// +//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// +//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// +//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// +//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// +//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// +//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// +//// POSSIBILITY OF SUCH DAMAGE. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usb1_rom1.v,v 1.1.1.1 2002-09-19 12:07:29 rudi Exp $ +// +// $Date: 2002-09-19 12:07:29 $ +// $Revision: 1.1.1.1 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: not supported by cvs2svn $ +// +// +// +// +// + +`include "usb1d_defines.v" + +module usb1d_rom1(clk, adr, dout); +input clk; +input [6:0] adr; +output [7:0] dout; + +reg [7:0] dout; + +always @(posedge clk) + case(adr) // synopsys full_case parallel_case + + // ==================================== + // ===== DEVICE Descriptor ===== + // ==================================== + + 7'h00: dout <= #1 8'd18; // this descriptor length + 7'h01: dout <= #1 8'h01; // descriptor type + 7'h02: dout <= #1 8'h00; // USB version low byte + 7'h03: dout <= #1 8'h01; // USB version high byte + 7'h04: dout <= #1 8'hff; // device class + 7'h05: dout <= #1 8'h00; // device sub class + 7'h06: dout <= #1 8'hff; // device protocol + 7'h07: dout <= #1 8'd64; // max packet size + 7'h08: dout <= #1 8'h34; // vendor ID low byte + 7'h09: dout <= #1 8'h12; // vendor ID high byte + 7'h0a: dout <= #1 8'h78; // product ID low byte + 7'h0b: dout <= #1 8'h56; // product ID high byte + 7'h0c: dout <= #1 8'h10; // device rel. number low byte + 7'h0d: dout <= #1 8'h00; // device rel. number high byte + 7'h0e: dout <= #1 8'h00; // Manufacturer String Index + 7'h0f: dout <= #1 8'h00; // Product Descr. String Index + 7'h10: dout <= #1 8'h00; // S/N String Index + 7'h11: dout <= #1 8'h01; // Number of possible config. + + // ==================================== + // ===== Configuration Descriptor ===== + // ==================================== + 7'h12: dout <= #1 8'h09; // this descriptor length + 7'h13: dout <= #1 8'h02; // descriptor type + 7'h14: dout <= #1 8'd53; // total data length low byte + 7'h15: dout <= #1 8'd00; // total data length high byte + 7'h16: dout <= #1 8'h01; // number of interfaces + 7'h17: dout <= #1 8'h01; // number of configurations + 7'h18: dout <= #1 8'h00; // Conf. String Index + 7'h19: dout <= #1 8'h40; // Config. Characteristics + 7'h1a: dout <= #1 8'h00; // Max. Power Consumption + + // ==================================== + // ===== Interface Descriptor ===== + // ==================================== + 7'h1b: dout <= #1 8'h09; // this descriptor length + 7'h1c: dout <= #1 8'h04; // descriptor type + 7'h1d: dout <= #1 8'h00; // interface number + 7'h1e: dout <= #1 8'h00; // alternate setting + 7'h1f: dout <= #1 8'h05; // number of endpoints + 7'h20: dout <= #1 8'hff; // interface class + 7'h21: dout <= #1 8'h01; // interface sub class + 7'h22: dout <= #1 8'hff; // interface protocol + 7'h23: dout <= #1 8'h00; // interface string index + + // ==================================== + // ===== Endpoint 1 Descriptor ===== + // ==================================== + 7'h24: dout <= #1 8'h07; // this descriptor length + 7'h25: dout <= #1 8'h05; // descriptor type + 7'h26: dout <= #1 8'h81; // endpoint address + 7'h27: dout <= #1 8'h01; // endpoint attributes + 7'h28: dout <= #1 8'h00; // max packet size low byte + 7'h29: dout <= #1 8'h01; // max packet size high byte + 7'h2a: dout <= #1 8'h01; // polling interval + + // ==================================== + // ===== Endpoint 2 Descriptor ===== + // ==================================== + 7'h2b: dout <= #1 8'h07; // this descriptor length + 7'h2c: dout <= #1 8'h05; // descriptor type + 7'h2d: dout <= #1 8'h02; // endpoint address + 7'h2e: dout <= #1 8'h01; // endpoint attributes + 7'h2f: dout <= #1 8'h00; // max packet size low byte + 7'h30: dout <= #1 8'h01; // max packet size high byte + 7'h31: dout <= #1 8'h01; // polling interval + + // ==================================== + // ===== Endpoint 3 Descriptor ===== + // ==================================== + 7'h32: dout <= #1 8'h07; // this descriptor length + 7'h33: dout <= #1 8'h05; // descriptor type + 7'h34: dout <= #1 8'h83; // endpoint address + 7'h35: dout <= #1 8'h02; // endpoint attributes + 7'h36: dout <= #1 8'd64; // max packet size low byte + 7'h37: dout <= #1 8'd00; // max packet size high byte + 7'h38: dout <= #1 8'h01; // polling interval + + // ==================================== + // ===== Endpoint 4 Descriptor ===== + // ==================================== + 7'h39: dout <= #1 8'h07; // this descriptor length + 7'h3a: dout <= #1 8'h05; // descriptor type + 7'h3b: dout <= #1 8'h04; // endpoint address + 7'h3c: dout <= #1 8'h02; // endpoint attributes + 7'h3d: dout <= #1 8'd64; // max packet size low byte + 7'h3e: dout <= #1 8'd00; // max packet size high byte + 7'h3f: dout <= #1 8'h01; // polling interval + + // ==================================== + // ===== Endpoint 5 Descriptor ===== + // ==================================== + 7'h40: dout <= #1 8'h07; // this descriptor length + 7'h41: dout <= #1 8'h05; // descriptor type + 7'h42: dout <= #1 8'h85; // endpoint address + 7'h43: dout <= #1 8'h03; // endpoint attributes + 7'h44: dout <= #1 8'd64; // max packet size low byte + 7'h45: dout <= #1 8'd00; // max packet size high byte + 7'h46: dout <= #1 8'h01; // polling interval + +/* + // ==================================== + // ===== String Descriptor Lang ID===== + // ==================================== + + 7'h47: dout <= #1 8'd06; // this descriptor length + 7'h48: dout <= #1 8'd03; // descriptor type + + 7'h49: dout <= #1 8'd09; // Language ID 0 low byte + 7'h4a: dout <= #1 8'd04; // Language ID 0 high byte + + 7'h4b: dout <= #1 8'd09; // Language ID 1 low byte + 7'h4c: dout <= #1 8'd04; // Language ID 1 high byte + + 7'h4d: dout <= #1 8'd09; // Language ID 2 low byte + 7'h4e: dout <= #1 8'd04; // Language ID 2 high byte + + // ==================================== + // ===== String Descriptor 0 ===== + // ==================================== + + 7'h50: dout <= #1 8'd010; // this descriptor length + 7'h51: dout <= #1 8'd03; // descriptor type + 7'h52: dout <= #1 "0"; + 7'h53: dout <= #1 " "; + 7'h54: dout <= #1 "g"; + 7'h55: dout <= #1 "n"; + 7'h56: dout <= #1 "i"; + 7'h57: dout <= #1 "r"; + 7'h58: dout <= #1 "t"; + 7'h59: dout <= #1 "S"; + + // ==================================== + // ===== String Descriptor 1 ===== + // ==================================== + + 7'h60: dout <= #1 8'd010; // this descriptor length + 7'h61: dout <= #1 8'd03; // descriptor type + 7'h62: dout <= #1 "1"; + 7'h63: dout <= #1 " "; + 7'h64: dout <= #1 "g"; + 7'h65: dout <= #1 "n"; + 7'h66: dout <= #1 "i"; + 7'h67: dout <= #1 "r"; + 7'h68: dout <= #1 "t"; + 7'h69: dout <= #1 "S"; + + // ==================================== + // ===== String Descriptor 2 ===== + // ==================================== + + 7'h70: dout <= #1 8'd010; // this descriptor length + 7'h71: dout <= #1 8'd03; // descriptor type + 7'h72: dout <= #1 "2"; + 7'h73: dout <= #1 " "; + 7'h74: dout <= #1 "g"; + 7'h75: dout <= #1 "n"; + 7'h76: dout <= #1 "i"; + 7'h77: dout <= #1 "r"; + 7'h78: dout <= #1 "t"; + 7'h79: dout <= #1 "S"; + +*/ + + // ==================================== + // ==================================== + + //default: dout <= #1 8'd00; + endcase + +endmodule
diff --git a/verilog/dv/bfm/usb_device/core/usb1d_sync_fifo.v b/verilog/dv/bfm/usb_device/core/usb1d_sync_fifo.v new file mode 100755 index 0000000..f35e34e --- /dev/null +++ b/verilog/dv/bfm/usb_device/core/usb1d_sync_fifo.v
@@ -0,0 +1,156 @@ +/********************************************************************* + + This file is part of the sdram controller project + http://www.opencores.org/cores/sdr_ctrl/ + + Description: SYNC FIFO + Parameters: + W : Width (integer) + D : Depth (integer, power of 2, 4 to 256) + + To Do: + nothing + + Author(s): Dinesh Annayya, dinesha@opencores.org + + Copyright (C) 2000 Authors and OPENCORES.ORG + + This source file may be used and distributed without + restriction provided that this copyright statement is not + removed from the file and that any derivative work contains + the original copyright notice and the associated disclaimer. + + This source file is free software; you can redistribute it + and/or modify it under the terms of the GNU Lesser General + Public License as published by the Free Software Foundation; + either version 2.1 of the License, or (at your option) any +later version. + + This source 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 Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General + Public License along with this source; if not, download it + from http://www.opencores.org/lgpl.shtml + +*******************************************************************/ + + +module usb1d_sync_fifo (clk, + reset_n, + clr, + wr_en, + wr_data, + full, + empty, + rd_en, + rd_data); + + parameter W = 8; + parameter D = 4; + + parameter AW = (D == 4) ? 2 : + (D == 8) ? 3 : + (D == 16) ? 4 : + (D == 32) ? 5 : + (D == 64) ? 6 : + (D == 128) ? 7 : + (D == 256) ? 8 : 0; + + output [W-1 : 0] rd_data; + input [W-1 : 0] wr_data; + input clk, reset_n, clr,wr_en, rd_en; + output full, empty; + + // synopsys translate_off + + initial begin + if (AW == 0) begin + $display ("%m : ERROR!!! Fifo depth %d not in range 4 to 256", D); + end // if (AW == 0) + end // initial begin + + // synopsys translate_on + + + reg [W-1 : 0] mem[D-1 : 0]; + reg [AW-1 : 0] rd_ptr, wr_ptr; + reg full, empty; + + + wire [W-1 : 0] rd_data; + + always @ (posedge clk or negedge reset_n) + if (reset_n == 1'b0) begin + wr_ptr <= {AW{1'b0}} ; + end + else begin + if(clr) wr_ptr <= {AW{1'b0}} ; + else begin + if (wr_en & !full) begin + wr_ptr <= wr_ptr + 1'b1 ; + end + end + end + + always @ (posedge clk or negedge reset_n) + if (reset_n == 1'b0) begin + rd_ptr <= {AW{1'b0}} ; + end + else begin + if(clr) rd_ptr <= {AW{1'b0}} ; + else begin + if (rd_en & !empty) begin + rd_ptr <= rd_ptr + 1'b1 ; + end + end + end + + + always @ (posedge clk or negedge reset_n) + if (reset_n == 1'b0) begin + empty <= 1'b1 ; + end + else begin + empty <= (((wr_ptr - rd_ptr) == {{(AW-1){1'b0}}, 1'b1}) & rd_en & ~wr_en) ? 1'b1 : + ((wr_ptr == rd_ptr) & ~rd_en & wr_en) ? 1'b0 : empty ; + end + + always @ (posedge clk or negedge reset_n) + if (reset_n == 1'b0) begin + full <= 1'b0 ; + end + else begin + full <= (((wr_ptr - rd_ptr) == {{(AW-1){1'b1}}, 1'b0}) & ~rd_en & wr_en) ? 1'b1 : + (((wr_ptr - rd_ptr) == {AW{1'b1}}) & rd_en & ~wr_en) ? 1'b0 : full ; + end + + always @ (posedge clk) + if (wr_en) + mem[wr_ptr] <= wr_data; + +assign rd_data = mem[rd_ptr]; + + +// synopsys translate_off + always @(posedge clk) begin + if (wr_en && full) begin + $display("%m : Error! sfifo overflow!"); + end + end + + always @(posedge clk) begin + if (rd_en && empty) begin + $display("%m : error! sfifo underflow!"); + end + end + +// synopsys translate_on +//--------------------------------------- + +endmodule + +
diff --git a/verilog/dv/bfm/usb_device/core/usb1d_utmi_if.v b/verilog/dv/bfm/usb_device/core/usb1d_utmi_if.v new file mode 100755 index 0000000..4546906 --- /dev/null +++ b/verilog/dv/bfm/usb_device/core/usb1d_utmi_if.v
@@ -0,0 +1,147 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// UTMI Interface //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb1_funct///// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// +//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// +//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// +//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// +//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// +//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// +//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// +//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// +//// POSSIBILITY OF SUCH DAMAGE. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usb1_utmi_if.v,v 1.1.1.1 2002-09-19 12:07:14 rudi Exp $ +// +// $Date: 2002-09-19 12:07:14 $ +// $Revision: 1.1.1.1 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: not supported by cvs2svn $ +// +// +// +// +// +// +// + +`include "usb1d_defines.v" + +module usb1d_utmi_if( // UTMI Interface (EXTERNAL) + phy_clk, rst, + DataOut, TxValid, TxReady, + RxValid, RxActive, RxError, DataIn, + + // Internal Interface + rx_data, rx_valid, rx_active, rx_err, + tx_data, tx_valid, tx_valid_last, tx_ready, + tx_first + + ); + +input phy_clk; +input rst; + +output [7:0] DataOut; +output TxValid; +input TxReady; + +input [7:0] DataIn; +input RxValid; +input RxActive; +input RxError; + + +output [7:0] rx_data; +output rx_valid, rx_active, rx_err; +input [7:0] tx_data; +input tx_valid; +input tx_valid_last; +output tx_ready; +input tx_first; + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// +reg [7:0] rx_data; +reg rx_valid, rx_active, rx_err; +reg [7:0] DataOut; +reg tx_ready; +reg TxValid; + +/////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + + +/////////////////////////////////////////////////////////////////// +// +// RX Interface Input registers +// + +always @(posedge phy_clk or negedge rst) + if(!rst) rx_valid <= #1 1'b0; + else rx_valid <= #1 RxValid; + +always @(posedge phy_clk or negedge rst) + if(!rst) rx_active <= #1 1'b0; + else rx_active <= #1 RxActive; + +always @(posedge phy_clk or negedge rst) + if(!rst) rx_err <= #1 1'b0; + else rx_err <= #1 RxError; + +always @(posedge phy_clk) + rx_data <= #1 DataIn; + +/////////////////////////////////////////////////////////////////// +// +// TX Interface Output/Input registers +// + +always @(posedge phy_clk) + if(TxReady | tx_first) DataOut <= #1 tx_data; + +always @(posedge phy_clk) + tx_ready <= #1 TxReady; + +always @(posedge phy_clk or negedge rst) + if(!rst) TxValid <= #1 1'b0; + else + TxValid <= #1 tx_valid | tx_valid_last | (TxValid & !TxReady); + +endmodule +
diff --git a/verilog/dv/bfm/usb_device/phy/usb1d_phy.v b/verilog/dv/bfm/usb_device/phy/usb1d_phy.v new file mode 100755 index 0000000..346c523 --- /dev/null +++ b/verilog/dv/bfm/usb_device/phy/usb1d_phy.v
@@ -0,0 +1,190 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// USB 1.1 PHY //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb_phy/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// +//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// +//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// +//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// +//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// +//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// +//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// +//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// +//// POSSIBILITY OF SUCH DAMAGE. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usb_phy.v,v 1.4 2003-10-21 05:58:40 rudi Exp $ +// +// $Date: 2003-10-21 05:58:40 $ +// $Revision: 1.4 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: not supported by cvs2svn $ +// Revision 1.3 2003/10/19 17:40:13 rudi +// - Made core more robust against line noise +// - Added Error Checking and Reporting +// (See README.txt for more info) +// +// Revision 1.2 2002/09/16 16:06:37 rudi +// Changed top level name to be consistent ... +// +// Revision 1.1.1.1 2002/09/16 14:26:59 rudi +// Created Directory Structure +// +// +// +// +// +// +// +// + + +module usb1d_phy(clk, rstn, phy_tx_mode, usb_rst, + + // Transciever Interface + txdp, txdn, txoe, + rxd, rxdp, rxdn, + + // UTMI Interface + DataOut_i, TxValid_i, TxReady_o, RxValid_o, + RxActive_o, RxError_o, DataIn_o, LineState_o + ); + + +/*************************************** +* Comman Signal +* *************************************/ +input clk ; // 48Mhz clock +input rstn ; // Active low async reset + +input phy_tx_mode ; // Used in Tx Path, + // The PHY supports single ended and differential output to the + // transceiver Depending on which device you are using, you have + // to tie the phy_tx_mode high or low. +output usb_rst ; // usb_rst is asserted whenever the host signals reset on the USB bus. + // The USB core will internally reset itself automatically. + // This output is provided for external logic that needs to be + // reset when the USB bus is reset. + +output txdp, txdn, txoe; +input rxd, rxdp, rxdn; +input [7:0] DataOut_i; +input TxValid_i; +output TxReady_o; +output [7:0] DataIn_o; +output RxValid_o; +output RxActive_o; +output RxError_o; +output [1:0] LineState_o; + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +reg [4:0] rst_cnt; +reg usb_rst; +wire fs_ce; +wire rstn; + +/////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +/////////////////////////////////////////////////////////////////// +// +// TX Phy +// + +usb1d_tx_phy i_tx_phy( + .clk( clk ), + .rstn( rstn ), + .fs_ce( fs_ce ), + .phy_mode( phy_tx_mode ), + + // Transciever Interface + .txdp( txdp ), + .txdn( txdn ), + .txoe( txoe ), + + // UTMI Interface + .DataOut_i( DataOut_i ), + .TxValid_i( TxValid_i ), + .TxReady_o( TxReady_o ) + ); + +/////////////////////////////////////////////////////////////////// +// +// RX Phy and DPLL +// + +usb1d_rx_phy i_rx_phy( + .clk( clk ), + .rstn( rstn ), + .fs_ce( fs_ce ), + + // Transciever Interface + .rxd( rxd ), + .rxdp( rxdp ), + .rxdn( rxdn ), + + // UTMI Interface + .DataIn_o( DataIn_o ), + .RxValid_o( RxValid_o ), + .RxActive_o( RxActive_o ), + .RxError_o( RxError_o ), + .RxEn_i( txoe ), + .LineState( LineState_o ) + ); + +/////////////////////////////////////////////////////////////////// +// +// Generate an USB Reset is we see SE0 for at least 2.5uS +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rstn) +`else +always @(posedge clk) +`endif + if(!rstn) rst_cnt <= 5'h0; + else + if(LineState_o != 2'h0) rst_cnt <= 5'h0; + else + if(!usb_rst && fs_ce) rst_cnt <= rst_cnt + 5'h1; + +always @(posedge clk) + usb_rst <= (rst_cnt == 5'h1f); + +endmodule +
diff --git a/verilog/dv/bfm/usb_device/phy/usb1d_rx_phy.v b/verilog/dv/bfm/usb_device/phy/usb1d_rx_phy.v new file mode 100755 index 0000000..6cf42db --- /dev/null +++ b/verilog/dv/bfm/usb_device/phy/usb1d_rx_phy.v
@@ -0,0 +1,455 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// USB 1.1 PHY //// +//// RX & DPLL //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb_phy/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// +//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// +//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// +//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// +//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// +//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// +//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// +//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// +//// POSSIBILITY OF SUCH DAMAGE. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usb_rx_phy.v,v 1.5 2004-10-19 09:29:07 rudi Exp $ +// +// $Date: 2004-10-19 09:29:07 $ +// $Revision: 1.5 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: not supported by cvs2svn $ +// Revision 1.4 2003/12/02 04:56:00 rudi +// Fixed a bug reported by Karl C. Posch from Graz University of Technology. Thanks Karl ! +// +// Revision 1.3 2003/10/19 18:07:45 rudi +// - Fixed Sync Error to be only checked/generated during the sync phase +// +// Revision 1.2 2003/10/19 17:40:13 rudi +// - Made core more robust against line noise +// - Added Error Checking and Reporting +// (See README.txt for more info) +// +// Revision 1.1.1.1 2002/09/16 14:27:01 rudi +// Created Directory Structure +// +// +// +// +// +// +// +// + + +module usb1d_rx_phy( clk, rstn, fs_ce, + + // Transciever Interface + rxd, rxdp, rxdn, + + // UTMI Interface + RxValid_o, RxActive_o, RxError_o, DataIn_o, + RxEn_i, LineState); + +input clk; +input rstn; +output fs_ce; +input rxd, rxdp, rxdn; +output [7:0] DataIn_o; +output RxValid_o; +output RxActive_o; +output RxError_o; +input RxEn_i; +output [1:0] LineState; + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +reg rxd_s0, rxd_s1, rxd_s; +reg rxdp_s0, rxdp_s1, rxdp_s, rxdp_s_r; +reg rxdn_s0, rxdn_s1, rxdn_s, rxdn_s_r; +reg synced_d; +wire k, j, se0; +reg rxd_r; +reg rx_en; +reg rx_active; +reg [2:0] bit_cnt; +reg rx_valid1, rx_valid; +reg shift_en; +reg sd_r; +reg sd_nrzi; +reg [7:0] hold_reg; +wire drop_bit; // Indicates a stuffed bit +reg [2:0] one_cnt; + +reg [1:0] dpll_state, dpll_next_state; +reg fs_ce_d; +reg fs_ce; +wire change; +wire lock_en; +reg [2:0] fs_state, fs_next_state; +reg rx_valid_r; +reg sync_err_d, sync_err; +reg bit_stuff_err; +reg se0_r, byte_err; +reg se0_s; + +/////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +assign RxActive_o = rx_active; +assign RxValid_o = rx_valid; +assign RxError_o = sync_err | bit_stuff_err | byte_err; +assign DataIn_o = hold_reg; +assign LineState = {rxdn_s1, rxdp_s1}; + +always @(posedge clk) rx_en <= RxEn_i; +always @(posedge clk) sync_err <= !rx_active & sync_err_d; + +/////////////////////////////////////////////////////////////////// +// +// Synchronize Inputs +// + +// First synchronize to the local system clock to +// avoid metastability outside the sync block (*_s0). +// Then make sure we see the signal for at least two +// clock cycles stable to avoid glitches and noise + +always @(posedge clk) rxd_s0 <= rxd; +always @(posedge clk) rxd_s1 <= rxd_s0; +always @(posedge clk) // Avoid detecting Line Glitches and noise + if(rxd_s0 && rxd_s1) rxd_s <= 1'b1; + else + if(!rxd_s0 && !rxd_s1) rxd_s <= 1'b0; + +always @(posedge clk) rxdp_s0 <= rxdp; +always @(posedge clk) rxdp_s1 <= rxdp_s0; +always @(posedge clk) rxdp_s_r <= rxdp_s0 & rxdp_s1; +always @(posedge clk) rxdp_s <= (rxdp_s0 & rxdp_s1) | rxdp_s_r; // Avoid detecting Line Glitches and noise + +always @(posedge clk) rxdn_s0 <= rxdn; +always @(posedge clk) rxdn_s1 <= rxdn_s0; +always @(posedge clk) rxdn_s_r <= rxdn_s0 & rxdn_s1; +always @(posedge clk) rxdn_s <= (rxdn_s0 & rxdn_s1) | rxdn_s_r; // Avoid detecting Line Glitches and noise + +assign k = !rxdp_s & rxdn_s; +assign j = rxdp_s & !rxdn_s; +assign se0 = !rxdp_s & !rxdn_s; + +always @(posedge clk) if(fs_ce) se0_s <= se0; + +/////////////////////////////////////////////////////////////////// +// +// DPLL +// + +// This design uses a clock enable to do 12Mhz timing and not a +// real 12Mhz clock. Everything always runs at 48Mhz. We want to +// make sure however, that the clock enable is always exactly in +// the middle between two virtual 12Mhz rising edges. +// We monitor rxdp and rxdn for any changes and do the appropiate +// adjustments. +// In addition to the locking done in the dpll FSM, we adjust the +// final latch enable to compensate for various sync registers ... + +// Allow lockinf only when we are receiving +assign lock_en = rx_en; + +always @(posedge clk) rxd_r <= rxd_s; + +// Edge detector +assign change = rxd_r != rxd_s; + +// DPLL FSM +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rstn) +`else +always @(posedge clk) +`endif + if(!rstn) dpll_state <= 2'h1; + else dpll_state <= dpll_next_state; + +always @(dpll_state or lock_en or change) + begin + fs_ce_d = 1'b0; + case(dpll_state) // synopsys full_case parallel_case + 2'h0: + if(lock_en && change) dpll_next_state = 2'h0; + else dpll_next_state = 2'h1; + 2'h1:begin + fs_ce_d = 1'b1; + if(lock_en && change) dpll_next_state = 2'h3; + else dpll_next_state = 2'h2; + end + 2'h2: + if(lock_en && change) dpll_next_state = 2'h0; + else dpll_next_state = 2'h3; + 2'h3: + if(lock_en && change) dpll_next_state = 2'h0; + else dpll_next_state = 2'h0; + endcase + end + +// Compensate for sync registers at the input - allign full speed +// clock enable to be in the middle between two bit changes ... +reg fs_ce_r1, fs_ce_r2; + +always @(posedge clk) fs_ce_r1 <= fs_ce_d; +always @(posedge clk) fs_ce_r2 <= fs_ce_r1; +always @(posedge clk) fs_ce <= fs_ce_r2; + + +/////////////////////////////////////////////////////////////////// +// +// Find Sync Pattern FSM +// + +parameter FS_IDLE = 3'h0, + K1 = 3'h1, + J1 = 3'h2, + K2 = 3'h3, + J2 = 3'h4, + K3 = 3'h5, + J3 = 3'h6, + K4 = 3'h7; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rstn) +`else +always @(posedge clk) +`endif + if(!rstn) fs_state <= FS_IDLE; + else fs_state <= fs_next_state; + +/*********************************************************** + Dinesh.A, 7th Feb 2013 + Sync Detection, when following pattern detected + k,j,k,j,k,j,k,k + Where k =1; if rxdp == 0 and rxdn == 1 + Where j =1; if rxdp == 1 and rxdn == 0 +************************************************************/ +always @(fs_state or fs_ce or k or j or rx_en or rx_active or se0 or se0_s) + begin + synced_d = 1'b0; + sync_err_d = 1'b0; + fs_next_state = fs_state; + if(fs_ce && !rx_active && !se0 && !se0_s) + case(fs_state) // synopsys full_case parallel_case + FS_IDLE: + begin + if(k && rx_en) fs_next_state = K1; + end + K1: + begin + if(j && rx_en) fs_next_state = J1; + else + begin + sync_err_d = 1'b1; + fs_next_state = FS_IDLE; + end + end + J1: + begin + if(k && rx_en) fs_next_state = K2; + else + begin + sync_err_d = 1'b1; + fs_next_state = FS_IDLE; + end + end + K2: + begin + if(j && rx_en) fs_next_state = J2; + else + begin + sync_err_d = 1'b1; + fs_next_state = FS_IDLE; + end + end + J2: + begin + if(k && rx_en) fs_next_state = K3; + else + begin + sync_err_d = 1'b1; + fs_next_state = FS_IDLE; + end + end + K3: + begin + if(j && rx_en) fs_next_state = J3; + else + if(k && rx_en) + begin + fs_next_state = FS_IDLE; // Allow missing first K-J + synced_d = 1'b1; + end + else + begin + sync_err_d = 1'b1; + fs_next_state = FS_IDLE; + end + end + J3: + begin + if(k && rx_en) fs_next_state = K4; + else + begin + sync_err_d = 1'b1; + fs_next_state = FS_IDLE; + end + end + K4: + begin + if(k) synced_d = 1'b1; + fs_next_state = FS_IDLE; + end + endcase + end + +/////////////////////////////////////////////////////////////////// +// +// Generate RxActive +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rstn) +`else +always @(posedge clk) +`endif + if(!rstn) rx_active <= 1'b0; + else + if(synced_d && rx_en) rx_active <= 1'b1; + else + if(se0 && rx_valid_r) rx_active <= 1'b0; + +always @(posedge clk) + if(rx_valid) rx_valid_r <= 1'b1; + else + if(fs_ce) rx_valid_r <= 1'b0; + +/////////////////////////////////////////////////////////////////// +// +// NRZI Decoder +// + +always @(posedge clk) + if(fs_ce) sd_r <= rxd_s; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rstn) +`else +always @(posedge clk) +`endif + if(!rstn) sd_nrzi <= 1'b0; + else + if(!rx_active) sd_nrzi <= 1'b1; + else + if(rx_active && fs_ce) sd_nrzi <= !(rxd_s ^ sd_r); + +/////////////////////////////////////////////////////////////////// +// +// Bit Stuff Detect +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rstn) +`else +always @(posedge clk) +`endif + if(!rstn) one_cnt <= 3'h0; + else + if(!shift_en) one_cnt <= 3'h0; + else + if(fs_ce) + begin + if(!sd_nrzi || drop_bit) one_cnt <= 3'h0; + else one_cnt <= one_cnt + 3'h1; + end + +assign drop_bit = (one_cnt==3'h6); + +always @(posedge clk) bit_stuff_err <= drop_bit & sd_nrzi & fs_ce & !se0 & rx_active; // Bit Stuff Error + +/////////////////////////////////////////////////////////////////// +// +// Serial => Parallel converter +// + +always @(posedge clk) + if(fs_ce) shift_en <= synced_d | rx_active; + +always @(posedge clk) + if(fs_ce && shift_en && !drop_bit) + hold_reg <= {sd_nrzi, hold_reg[7:1]}; + +/////////////////////////////////////////////////////////////////// +// +// Generate RxValid +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rstn) +`else +always @(posedge clk) +`endif + if(!rstn) bit_cnt <= 3'b0; + else + if(!shift_en) bit_cnt <= 3'h0; + else + if(fs_ce && !drop_bit) bit_cnt <= bit_cnt + 3'h1; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rstn) +`else +always @(posedge clk) +`endif + if(!rstn) rx_valid1 <= 1'b0; + else + if(fs_ce && !drop_bit && (bit_cnt==3'h7)) rx_valid1 <= 1'b1; + else + if(rx_valid1 && fs_ce && !drop_bit) rx_valid1 <= 1'b0; + +always @(posedge clk) rx_valid <= !drop_bit & rx_valid1 & fs_ce; + +always @(posedge clk) se0_r <= se0; + +always @(posedge clk) byte_err <= se0 & !se0_r & (|bit_cnt[2:1]) & rx_active; + +endmodule +
diff --git a/verilog/dv/bfm/usb_device/phy/usb1d_tx_phy.v b/verilog/dv/bfm/usb_device/phy/usb1d_tx_phy.v new file mode 100755 index 0000000..0c0f9fd --- /dev/null +++ b/verilog/dv/bfm/usb_device/phy/usb1d_tx_phy.v
@@ -0,0 +1,461 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// USB 1.1 PHY //// +//// TX //// +//// //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/usb_phy/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// +//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// +//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// +//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// +//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// +//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// +//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// +//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// +//// POSSIBILITY OF SUCH DAMAGE. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: usb_tx_phy.v,v 1.4 2004-10-19 09:29:07 rudi Exp $ +// +// $Date: 2004-10-19 09:29:07 $ +// $Revision: 1.4 $ +// $Author: rudi $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: not supported by cvs2svn $ +// Revision 1.3 2003/10/21 05:58:41 rudi +// usb_rst is no longer or'ed with the incomming reset internally. +// Now usb_rst is simply an output, the application can decide how +// to utilize it. +// +// Revision 1.2 2003/10/19 17:40:13 rudi +// - Made core more robust against line noise +// - Added Error Checking and Reporting +// (See README.txt for more info) +// +// Revision 1.1.1.1 2002/09/16 14:27:02 rudi +// Created Directory Structure +// +// +// +// +// +// +// + + +module usb1d_tx_phy( + clk, rstn, fs_ce, phy_mode, + + // Transciever Interface + txdp, txdn, txoe, + + // UTMI Interface + DataOut_i, TxValid_i, TxReady_o + ); + +input clk; +input rstn; +input fs_ce; +input phy_mode; +output txdp, txdn, txoe; +input [7:0] DataOut_i; +input TxValid_i; +output TxReady_o; + +/////////////////////////////////////////////////////////////////// +// +// Local Wires and Registers +// + +parameter IDLE = 3'd0, + SOP = 3'h1, + DATA = 3'h2, + EOP1 = 3'h3, + EOP2 = 3'h4, + WAIT = 3'h5; + +reg TxReady_o; +reg [2:0] state, next_state; +reg tx_ready_d; +reg ld_sop_d; +reg ld_data_d; +reg ld_eop_d; +reg tx_ip; +reg tx_ip_sync; +reg [2:0] bit_cnt; +reg [7:0] hold_reg; +reg [7:0] hold_reg_d; + +reg sd_raw_o; +wire hold; +reg data_done; +reg sft_done; +reg sft_done_r; +wire sft_done_e; +reg ld_data; +wire eop_done; +reg [2:0] one_cnt; +wire stuff; +reg sd_bs_o; +reg sd_nrzi_o; +reg append_eop; +reg append_eop_sync1; +reg append_eop_sync2; +reg append_eop_sync3; +reg append_eop_sync4; +reg txdp, txdn; +reg txoe_r1, txoe_r2; +reg txoe; + +/////////////////////////////////////////////////////////////////// +// +// Misc Logic +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rstn) +`else +always @(posedge clk) +`endif + if(!rstn) TxReady_o <= 1'b0; + else TxReady_o <= tx_ready_d & TxValid_i; + +always @(posedge clk) ld_data <= ld_data_d; + +/////////////////////////////////////////////////////////////////// +// +// Transmit in progress indicator +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rstn) +`else +always @(posedge clk) +`endif + if(!rstn) tx_ip <= 1'b0; + else + if(ld_sop_d) tx_ip <= 1'b1; + else + if(eop_done) tx_ip <= 1'b0; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rstn) +`else +always @(posedge clk) +`endif + if(!rstn) tx_ip_sync <= 1'b0; + else + if(fs_ce) tx_ip_sync <= tx_ip; + +// data_done helps us to catch cases where TxValid drops due to +// packet end and then gets re-asserted as a new packet starts. +// We might not see this because we are still transmitting. +// data_done should solve those cases ... +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rstn) +`else +always @(posedge clk) +`endif + if(!rstn) data_done <= 1'b0; + else + if(TxValid_i && ! tx_ip) data_done <= 1'b1; + else + if(!TxValid_i) data_done <= 1'b0; + +/////////////////////////////////////////////////////////////////// +// +// Shift Register +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rstn) +`else +always @(posedge clk) +`endif + if(!rstn) bit_cnt <= 3'h0; + else + if(!tx_ip_sync) bit_cnt <= 3'h0; + else + if(fs_ce && !hold) bit_cnt <= bit_cnt + 3'h1; + +assign hold = stuff; + +always @(posedge clk) + if(!tx_ip_sync) sd_raw_o <= 1'b0; + else + case(bit_cnt) // synopsys full_case parallel_case + 3'h0: sd_raw_o <= hold_reg_d[0]; + 3'h1: sd_raw_o <= hold_reg_d[1]; + 3'h2: sd_raw_o <= hold_reg_d[2]; + 3'h3: sd_raw_o <= hold_reg_d[3]; + 3'h4: sd_raw_o <= hold_reg_d[4]; + 3'h5: sd_raw_o <= hold_reg_d[5]; + 3'h6: sd_raw_o <= hold_reg_d[6]; + 3'h7: sd_raw_o <= hold_reg_d[7]; + endcase + +always @(posedge clk) + sft_done <= !hold & (bit_cnt == 3'h7); + +always @(posedge clk) + sft_done_r <= sft_done; + +assign sft_done_e = sft_done & !sft_done_r; + +// Out Data Hold Register +always @(posedge clk) + if(ld_sop_d) hold_reg <= 8'h80; + else + if(ld_data) hold_reg <= DataOut_i; + +always @(posedge clk) hold_reg_d <= hold_reg; + +/////////////////////////////////////////////////////////////////// +// +// Bit Stuffer +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rstn) +`else +always @(posedge clk) +`endif + if(!rstn) one_cnt <= 3'h0; + else + if(!tx_ip_sync) one_cnt <= 3'h0; + else + if(fs_ce) + begin + if(!sd_raw_o || stuff) one_cnt <= 3'h0; + else one_cnt <= one_cnt + 3'h1; + end + +assign stuff = (one_cnt==3'h6); + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rstn) +`else +always @(posedge clk) +`endif + if(!rstn) sd_bs_o <= 1'h0; + else + if(fs_ce) sd_bs_o <= !tx_ip_sync ? 1'b0 : (stuff ? 1'b0 : sd_raw_o); + +/////////////////////////////////////////////////////////////////// +// +// NRZI Encoder +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rstn) +`else +always @(posedge clk) +`endif + if(!rstn) sd_nrzi_o <= 1'b1; + else + if(!tx_ip_sync || !txoe_r1) sd_nrzi_o <= 1'b1; + else + if(fs_ce) sd_nrzi_o <= sd_bs_o ? sd_nrzi_o : ~sd_nrzi_o; + +/////////////////////////////////////////////////////////////////// +// +// EOP append logic +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rstn) +`else +always @(posedge clk) +`endif + if(!rstn) append_eop <= 1'b0; + else + if(ld_eop_d) append_eop <= 1'b1; + else + if(append_eop_sync2) append_eop <= 1'b0; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rstn) +`else +always @(posedge clk) +`endif + if(!rstn) append_eop_sync1 <= 1'b0; + else + if(fs_ce) append_eop_sync1 <= append_eop; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rstn) +`else +always @(posedge clk) +`endif + if(!rstn) append_eop_sync2 <= 1'b0; + else + if(fs_ce) append_eop_sync2 <= append_eop_sync1; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rstn) +`else +always @(posedge clk) +`endif + if(!rstn) append_eop_sync3 <= 1'b0; + else + if(fs_ce) append_eop_sync3 <= append_eop_sync2 | + (append_eop_sync3 & !append_eop_sync4); // Make sure always 2 bit wide + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rstn) +`else +always @(posedge clk) +`endif + if(!rstn) append_eop_sync4 <= 1'b0; + else + if(fs_ce) append_eop_sync4 <= append_eop_sync3; + +assign eop_done = append_eop_sync3; + +/////////////////////////////////////////////////////////////////// +// +// Output Enable Logic +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rstn) +`else +always @(posedge clk) +`endif + if(!rstn) txoe_r1 <= 1'b0; + else + if(fs_ce) txoe_r1 <= tx_ip_sync; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rstn) +`else +always @(posedge clk) +`endif + if(!rstn) txoe_r2 <= 1'b0; + else + if(fs_ce) txoe_r2 <= txoe_r1; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rstn) +`else +always @(posedge clk) +`endif + if(!rstn) txoe <= 1'b1; + else + if(fs_ce) txoe <= !(txoe_r1 | txoe_r2); + +/////////////////////////////////////////////////////////////////// +// +// Output Registers +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rstn) +`else +always @(posedge clk) +`endif + if(!rstn) txdp <= 1'b1; + else + if(fs_ce) txdp <= phy_mode ? + (!append_eop_sync3 & sd_nrzi_o) : + sd_nrzi_o; + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rstn) +`else +always @(posedge clk) +`endif + if(!rstn) txdn <= 1'b0; + else + if(fs_ce) txdn <= phy_mode ? + (!append_eop_sync3 & ~sd_nrzi_o) : + append_eop_sync3; + +/////////////////////////////////////////////////////////////////// +// +// Tx Statemashine +// + +`ifdef USB_ASYNC_REST +always @(posedge clk or negedge rstn) +`else +always @(posedge clk) +`endif + if(!rstn) state <= IDLE; + else state <= next_state; + +always @(state or TxValid_i or data_done or sft_done_e or eop_done or fs_ce) + begin + next_state = state; + tx_ready_d = 1'b0; + + ld_sop_d = 1'b0; + ld_data_d = 1'b0; + ld_eop_d = 1'b0; + + case(state) // synopsys full_case parallel_case + IDLE: + if(TxValid_i) + begin + ld_sop_d = 1'b1; + next_state = SOP; + end + SOP: + if(sft_done_e) + begin + tx_ready_d = 1'b1; + ld_data_d = 1'b1; + next_state = DATA; + end + DATA: + begin + if(!data_done && sft_done_e) + begin + ld_eop_d = 1'b1; + next_state = EOP1; + end + + if(data_done && sft_done_e) + begin + tx_ready_d = 1'b1; + ld_data_d = 1'b1; + end + end + EOP1: + if(eop_done) next_state = EOP2; + EOP2: + if(!eop_done && fs_ce) next_state = WAIT; + WAIT: + if(fs_ce) next_state = IDLE; + endcase + end + +endmodule +
diff --git a/verilog/dv/bfm/usb_device/top/usb1d_top.v b/verilog/dv/bfm/usb_device/top/usb1d_top.v new file mode 100755 index 0000000..f61c1b2 --- /dev/null +++ b/verilog/dv/bfm/usb_device/top/usb1d_top.v
@@ -0,0 +1,411 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// //// +//// Description //// +//// USB Device level integration. //// +//// Following modules are integrated //// +//// 1. usb1_phy //// +//// 2. usb1_core //// +//// Ver 0.1 : 01.Mar.2013 //// +//// //// +//// To Do: //// +//// nothing //// +//// //// +//// Author(s): //// +//// - Dinesh Annayya, dinesha@opencores.org //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// + + +module usb1d_top( + clk_i, + rstn_i, + + // Transciever Interface + usb_dp, + usb_dn, + + // USB Misc + phy_tx_mode , + usb_rst, + + // Interrupts + dropped_frame, + misaligned_frame, + crc16_err, + + // Vendor Features + v_set_int, + v_set_feature, + wValue, + wIndex, + vendor_data, + + // USB Status + usb_busy, + ep_sel, + + // Endpoint Interface + ep1_cfg, + ep1_din, + ep1_we, + ep1_full, + ep1_dout, + ep1_re, + ep1_empty, + ep1_bf_en, + ep1_bf_size, + + ep2_cfg, + ep2_din, + ep2_we, + ep2_full, + ep2_dout, + ep2_re, + ep2_empty, + ep2_bf_en, + ep2_bf_size, + + ep3_cfg, + ep3_din, + ep3_we, + ep3_full, + ep3_dout, + ep3_re, + ep3_empty, + ep3_bf_en, + ep3_bf_size, + + ep4_cfg, + ep4_din, + ep4_we, + ep4_full, + ep4_dout, + ep4_re, + ep4_empty, + ep4_bf_en, + ep4_bf_size, + + ep5_cfg, + ep5_din, + ep5_we, + ep5_full, + ep5_dout, + ep5_re, + ep5_empty, + ep5_bf_en, + ep5_bf_size, + + ep6_cfg, + ep6_din, + ep6_we, ep6_full, + ep6_dout, ep6_re, ep6_empty, + ep6_bf_en, ep6_bf_size, + + ep7_cfg, + ep7_din, ep7_we, ep7_full, + ep7_dout, ep7_re, ep7_empty, + ep7_bf_en, ep7_bf_size, + // Register Interface + reg_addr, + reg_rdwrn, + reg_req, + reg_wdata, + reg_rdata, + reg_ack + + ); + +input clk_i; +input rstn_i; + +inout usb_dp; +inout usb_dn; + +input phy_tx_mode; +output usb_rst; +output dropped_frame, misaligned_frame; +output crc16_err; + +output v_set_int; +output v_set_feature; +output [15:0] wValue; +output [15:0] wIndex; +input [15:0] vendor_data; + +output usb_busy; +output [3:0] ep_sel; + +// Endpoint Interfaces +input [13:0] ep1_cfg; +input [7:0] ep1_din; +output [7:0] ep1_dout; +output ep1_we, ep1_re; +input ep1_empty, ep1_full; +input ep1_bf_en; +input [6:0] ep1_bf_size; + +input [13:0] ep2_cfg; +input [7:0] ep2_din; +output [7:0] ep2_dout; +output ep2_we, ep2_re; +input ep2_empty, ep2_full; +input ep2_bf_en; +input [6:0] ep2_bf_size; + +input [13:0] ep3_cfg; +input [7:0] ep3_din; +output [7:0] ep3_dout; +output ep3_we, ep3_re; +input ep3_empty, ep3_full; +input ep3_bf_en; +input [6:0] ep3_bf_size; + +input [13:0] ep4_cfg; +input [7:0] ep4_din; +output [7:0] ep4_dout; +output ep4_we, ep4_re; +input ep4_empty, ep4_full; +input ep4_bf_en; +input [6:0] ep4_bf_size; + +input [13:0] ep5_cfg; +input [7:0] ep5_din; +output [7:0] ep5_dout; +output ep5_we, ep5_re; +input ep5_empty, ep5_full; +input ep5_bf_en; +input [6:0] ep5_bf_size; + +input [13:0] ep6_cfg; +input [7:0] ep6_din; +output [7:0] ep6_dout; +output ep6_we, ep6_re; +input ep6_empty, ep6_full; +input ep6_bf_en; +input [6:0] ep6_bf_size; + +input [13:0] ep7_cfg; +input [7:0] ep7_din; +output [7:0] ep7_dout; +output ep7_we, ep7_re; +input ep7_empty, ep7_full; +input ep7_bf_en; +input [6:0] ep7_bf_size; + + +//----------------------------------- +// Register Interface +// ---------------------------------- +output [31:0] reg_addr; // Register Address +output reg_rdwrn; // 0 -> write, 1-> read +output reg_req; // Register Req +output [31:0] reg_wdata; // Register write data +input [31:0] reg_rdata; // Register Read Data +input reg_ack; // Register Ack +/////////////////////////////////////////////////////////////////// +// Local Wires and Registers +/////////////////////////////////////////////////////////////////// +//------------------------------------ +// UTMI Interface +// ----------------------------------- +wire [7:0] DataOut; +wire TxValid; +wire TxReady; +wire [7:0] DataIn; +wire RxValid; +wire RxActive; +wire RxError; +wire [1:0] LineState; +wire clk; +wire rst; +wire phy_tx_mode; +wire usb_rst; + +// USB Traceiver interface +wire usb_txdp; // USB TX + +wire usb_txdn; // USB TX - +wire usb_txoe; // USB TX OEN, Output driven at txoe=0 +wire usb_rxd; +wire usb_rxdp; // USB RX+ +wire usb_rxdn; // USB RX- + +assign usb_dp = (usb_txoe == 1'b0) ? usb_txdp : 1'bz; +assign usb_dn = (usb_txoe == 1'b0) ? usb_txdn : 1'bz; + +assign usb_rxd = usb_dp; +assign usb_rxdp = usb_dp; +assign usb_rxdn = usb_dn; + + +usb1d_phy u_usb_phy( + .clk ( clk_i ), + .rstn ( rstn_i ), + .phy_tx_mode ( phy_tx_mode ), + .usb_rst ( usb_rst ), + + // Transceiver Interface + .rxd ( usb_rxd ), + .rxdp ( usb_rxdp ), + .rxdn ( usb_rxdn ), + .txdp ( usb_txdp ), + .txdn ( usb_txdn ), + .txoe ( usb_txoe ), + + // UTMI Interface + .DataIn_o ( DataIn ), + .RxValid_o ( RxValid ), + .RxActive_o ( RxActive ), + .RxError_o ( RxError ), + .DataOut_i ( DataOut ), + .TxValid_i ( TxValid ), + .TxReady_o ( TxReady ), + .LineState_o ( LineState ) + ); + + +usb1d_core u_usb_core( + .clk_i ( clk_i ), + .rst_i ( rstn_i ), + + + // USB Misc + .phy_tx_mode ( phy_tx_mode ), + .usb_rst ( usb_rst ), + + // UTMI Interface + .DataIn ( DataIn ), + .RxValid ( RxValid ), + .RxActive ( RxActive ), + .RxError ( RxError ), + .DataOut ( DataOut ), + .TxValid ( TxValid ), + .TxReady ( TxReady ), + .LineState ( LineState ), + + // Interrupts + .dropped_frame ( dropped_frame ), + .misaligned_frame ( misaligned_frame ), + .crc16_err ( crc16_err ), + + // Vendor Features + .v_set_int ( v_set_int ), + .v_set_feature ( v_set_feature ), + .wValue ( wValue ), + .wIndex ( wIndex ), + .vendor_data ( vendor_data ), + + // USB Status + .usb_busy ( usb_busy ), + .ep_sel ( ep_sel ), + + // Endpoint Interface + .ep1_cfg ( ep1_cfg ), + .ep1_din ( ep1_din ), + .ep1_we ( ep1_we ), + .ep1_full ( ep1_full ), + .ep1_dout ( ep1_dout ), + .ep1_re ( ep1_re ), + .ep1_empty ( ep1_empty ), + .ep1_bf_en ( ep1_bf_en ), + .ep1_bf_size ( ep1_bf_size ), + + .ep2_cfg ( ep2_cfg ), + .ep2_din ( ep2_din ), + .ep2_we ( ep2_we ), + .ep2_full ( ep2_full ), + .ep2_dout ( ep2_dout ), + .ep2_re ( ep2_re ), + .ep2_empty ( ep2_empty ), + .ep2_bf_en ( ep2_bf_en ), + .ep2_bf_size ( ep2_bf_size ), + + .ep3_cfg ( ep3_cfg ), + .ep3_din ( ep3_din ), + .ep3_we ( ep3_we ), + .ep3_full ( ep3_full ), + .ep3_dout ( ep3_dout ), + .ep3_re ( ep3_re ), + .ep3_empty ( ep3_empty ), + .ep3_bf_en ( ep3_bf_en ), + .ep3_bf_size ( ep3_bf_size ), + + .ep4_cfg ( ep4_cfg ), + .ep4_din ( ep4_din ), + .ep4_we ( ep4_we ), + .ep4_full ( ep4_full ), + .ep4_dout ( ep4_dout ), + .ep4_re ( ep4_re ), + .ep4_empty ( ep4_empty ), + .ep4_bf_en ( ep4_bf_en ), + .ep4_bf_size ( ep4_bf_size ), + + .ep5_cfg ( ep5_cfg ), + .ep5_din ( ep5_din ), + .ep5_we ( ep5_we ), + .ep5_full ( ep5_full ), + .ep5_dout ( ep5_dout ), + .ep5_re ( ep5_re ), + .ep5_empty ( ep5_empty ), + .ep5_bf_en ( ep5_bf_en ), + .ep5_bf_size ( ep5_bf_size ), + + .ep6_cfg ( ep6_cfg ), + .ep6_din ( ep6_din ), + .ep6_we ( ep6_we ), + .ep6_full ( ep6_full ), + .ep6_dout ( ep6_dout ), + .ep6_re ( ep6_re ), + .ep6_empty ( ep6_empty ), + .ep6_bf_en ( ep6_bf_en ), + .ep6_bf_size ( ep6_bf_size ), + + .ep7_cfg ( ep7_cfg ), + .ep7_din ( ep7_din ), + .ep7_we ( ep7_we ), + .ep7_full ( ep7_full ), + .ep7_dout ( ep7_dout ), + .ep7_re ( ep7_re ), + .ep7_empty ( ep7_empty ), + .ep7_bf_en ( ep7_bf_en ), + .ep7_bf_size ( ep7_bf_size ), + + // Register Interface + .reg_addr ( reg_addr ), + .reg_rdwrn ( reg_rdwrn ), + .reg_req ( reg_req ), + .reg_wdata ( reg_wdata ), + .reg_rdata ( reg_rdata ), + .reg_ack ( reg_ack ) + + + ); + + + +endmodule
diff --git a/verilog/dv/bfm/usbd_files.v b/verilog/dv/bfm/usbd_files.v new file mode 100644 index 0000000..4087cf0 --- /dev/null +++ b/verilog/dv/bfm/usbd_files.v
@@ -0,0 +1,19 @@ +`include "usb_device/core/usb1d_core.v" +`include "usb_device/core/usb1d_ctrl.v" +`include "usb_device/core/usb1d_generic_dpram.v" +`include "usb_device/core/usb1d_pa.v" +`include "usb_device/core/usb1d_pl.v" +`include "usb_device/core/usb1d_utmi_if.v" +`include "usb_device/core/usb1d_crc16.v" +`include "usb_device/core/usb1d_generic_fifo.v" +`include "usb_device/core/usb1d_pd.v" +`include "usb_device/core/usb1d_rom1.v" +`include "usb_device/core/usb1d_crc5.v" +`include "usb_device/core/usb1d_fifo2.v" +`include "usb_device/core/usb1d_idma.v" +`include "usb_device/core/usb1d_pe.v" +`include "usb_device/core/usb1d_sync_fifo.v" +`include "usb_device/phy/usb1d_rx_phy.v" +`include "usb_device/phy/usb1d_phy.v" +`include "usb_device/phy/usb1d_tx_phy.v" +`include "usb_device/top/usb1d_top.v"
diff --git a/verilog/dv/user_basic/user_basic_tb.v b/verilog/dv/user_basic/user_basic_tb.v index 99e0acb..dedd260 100644 --- a/verilog/dv/user_basic/user_basic_tb.v +++ b/verilog/dv/user_basic/user_basic_tb.v
@@ -179,62 +179,61 @@ // cfg_wb_clk_ctrl = reg_0[11:9]; // cfg_rtc_clk_ctrl = reg_0[19:12]; // cfg_cpu_clk_ctrl = reg_0[23:20]; - // cfg_sdram_clk_ctrl = reg_0[27:24]; - // cfg_usb_clk_ctrl = reg_0[31:28]; + // cfg_usb_clk_ctrl = reg_0[31:24]; $display("Step-1, CPU: CLOCK1, RTC: CLOCK2 *2, USB: CLOCK2, WBS:CLOCK1"); test_step = 1; - wb_user_core_write('h3080_0000,{4'h0,4'h0,4'h0,8'h0,4'h0,8'h00}); + wb_user_core_write('h3080_0000,{8'h0,4'h0,8'h0,4'h0,8'h00}); clock_monitor(CLK1_PERIOD,CLK2_PERIOD*2,CLK2_PERIOD,CLK1_PERIOD); $display("Step-2, CPU: CLOCK2, RTC: CLOCK2/(2+1), USB: CLOCK2/2, WBS:CLOCK2"); test_step = 2; - wb_user_core_write('h3080_0000,{4'h8,4'h0,4'h8,8'h1,4'h8,8'h00}); + wb_user_core_write('h3080_0000,{8'h80,4'h8,8'h1,4'h8,8'h00}); clock_monitor(CLK2_PERIOD,(3)*CLK2_PERIOD,2*CLK2_PERIOD,CLK2_PERIOD); $display("Step-3, CPU: CLOCK1/2, RTC: CLOCK2/(2+2), USB: CLOCK2/(2+1), WBS:CLOCK1/2"); test_step = 3; - wb_user_core_write('h3080_0000,{4'h9,4'h0,4'h4,8'h2,4'h4,8'h00}); + wb_user_core_write('h3080_0000,{8'h81,4'h4,8'h2,4'h4,8'h00}); clock_monitor(2*CLK1_PERIOD,(4)*CLK2_PERIOD,3*CLK2_PERIOD,2*CLK1_PERIOD); $display("Step-4, CPU: CLOCK1/3, RTC: CLOCK2/(2+3), USB: CLOCK2/(2+2), WBS:CLOCK1/3"); test_step = 4; - wb_user_core_write('h3080_0000,{4'hA,4'h0,4'h5,8'h3,4'h5,8'h00}); + wb_user_core_write('h3080_0000,{8'h82,4'h5,8'h3,4'h5,8'h00}); clock_monitor(3*CLK1_PERIOD,5*CLK2_PERIOD,4*CLK2_PERIOD,3*CLK1_PERIOD); $display("Step-5, CPU: CLOCK1/4, RTC: CLOCK2/(2+4), USB: CLOCK2/(2+3), WBS:CLOCK1/4"); test_step = 5; - wb_user_core_write('h3080_0000,{4'hB,4'h0,4'h6,8'h4,4'h6,8'h00}); + wb_user_core_write('h3080_0000,{8'h83,4'h6,8'h4,4'h6,8'h00}); clock_monitor(4*CLK1_PERIOD,6*CLK2_PERIOD,5*CLK2_PERIOD,4*CLK1_PERIOD); $display("Step-6, CPU: CLOCK1/(2+3), RTC: CLOCK2/(2+5), USB: CLOCK2/(2+4), WBS:CLOCK1/(2+3)"); test_step = 6; - wb_user_core_write('h3080_0000,{4'hC,4'h0,4'h7,8'h5,4'h7,8'h00}); + wb_user_core_write('h3080_0000,{8'h84,4'h7,8'h5,4'h7,8'h00}); clock_monitor(5*CLK1_PERIOD,7*CLK2_PERIOD,6*CLK2_PERIOD,5*CLK1_PERIOD); $display("Step-7, CPU: CLOCK2/(2), RTC: CLOCK2/(2+6), USB: CLOCK2/(2+5), WBS:CLOCK2/(2)"); test_step = 7; - wb_user_core_write('h3080_0000,{4'hD,4'h0,4'hC,8'h6,4'hC,8'h00}); + wb_user_core_write('h3080_0000,{8'h85,4'hC,8'h6,4'hC,8'h00}); clock_monitor(2*CLK2_PERIOD,8*CLK2_PERIOD,7*CLK2_PERIOD,2*CLK2_PERIOD); $display("Step-8, CPU: CLOCK2/3, RTC: CLOCK2/(2+7), USB: CLOCK2/(2+6), WBS:CLOCK2/3"); test_step = 8; - wb_user_core_write('h3080_0000,{4'hE,4'h0,4'hD,8'h7,4'hD,8'h00}); + wb_user_core_write('h3080_0000,{8'h86,4'hD,8'h7,4'hD,8'h00}); clock_monitor(3*CLK2_PERIOD,9*CLK2_PERIOD,8*CLK2_PERIOD,3*CLK2_PERIOD); $display("Step-9, CPU: CLOCK2/4, RTC: CLOCK2/(2+8), USB: CLOCK2/(2+7), WBS:CLOCK2/4"); test_step = 9; - wb_user_core_write('h3080_0000,{4'hF,4'h0,4'hE,8'h8,4'hE,8'h00}); + wb_user_core_write('h3080_0000,{8'h87,4'hE,8'h8,4'hE,8'h00}); clock_monitor(4*CLK2_PERIOD,10*CLK2_PERIOD,9*CLK2_PERIOD,4*CLK2_PERIOD); - $display("Step-10, CPU: CLOCK2/(2+3), RTC: CLOCK2/(2+128), USB: CLOCK2/(2+7), WBS:CLOCK1/(2+3)"); + $display("Step-10, CPU: CLOCK2/(2+3), RTC: CLOCK2/(2+128), USB: CLOCK2/(2+8), WBS:CLOCK1/(2+3)"); test_step = 10; - wb_user_core_write('h3080_0000,{4'hF,4'h0,4'hF,8'h80,4'hF,8'h00}); - clock_monitor(5*CLK2_PERIOD,130*CLK2_PERIOD,9*CLK2_PERIOD,5*CLK2_PERIOD); + wb_user_core_write('h3080_0000,{8'h88,4'hF,8'h80,4'hF,8'h00}); + clock_monitor(5*CLK2_PERIOD,130*CLK2_PERIOD,10*CLK2_PERIOD,5*CLK2_PERIOD); - $display("Step-10, CPU: CLOCK2/(2+3), RTC: CLOCK2/(2+255), USB: CLOCK2/(2+7), WBS:CLOCK2/(2+3)"); + $display("Step-10, CPU: CLOCK2/(2+3), RTC: CLOCK2/(2+255), USB: CLOCK2/(2+9), WBS:CLOCK2/(2+3)"); test_step = 10; - wb_user_core_write('h3080_0000,{4'hF,4'h0,4'hF,8'hFF,4'hF,8'h00}); - clock_monitor(5*CLK2_PERIOD,257*CLK2_PERIOD,9*CLK2_PERIOD,5*CLK2_PERIOD); + wb_user_core_write('h3080_0000,{8'h89,4'hF,8'hFF,4'hF,8'h00}); + clock_monitor(5*CLK2_PERIOD,257*CLK2_PERIOD,11*CLK2_PERIOD,5*CLK2_PERIOD); $display("###################################################"); $display("Monitor: Checking the chip signature :"); @@ -242,8 +241,8 @@ wb_user_core_write('h3080_0000,'h1); wb_user_core_read_check(32'h30020058,read_data,32'h8273_8343); - wb_user_core_read_check(32'h3002005C,read_data,32'h0203_2022); - wb_user_core_read_check(32'h30020060,read_data,32'h0003_7000); + wb_user_core_read_check(32'h3002005C,read_data,32'h1003_2022); + wb_user_core_read_check(32'h30020060,read_data,32'h0003_8000); end
diff --git a/verilog/dv/user_sspi/user_sspi_tb.v b/verilog/dv/user_sspi/user_sspi_tb.v index 6dcea02..8330de7 100644 --- a/verilog/dv/user_sspi/user_sspi_tb.v +++ b/verilog/dv/user_sspi/user_sspi_tb.v
@@ -24,20 +24,7 @@ //// //// //// Description //// //// This is a standalone test bench to validate the //// -//// Digital core flash access through External WB i/F. //// -//// 1. Check SPI Read Identification //// -//// 2. Check the Direct Memory Read (Qual/Single/Quad) //// -//// 3. Direct SPI Memory Prefetch - 3DW //// -//// 4. Direct SPI Memory Prefetch - 2DW //// -//// 5. Direct SPI Memory Prefetch - 1DW //// -//// 6. Direct SPI Memory Prefetch - 7DW //// -//// 7. 1DW Indirect Read //// -//// 8. 2DW Indirect Read //// -//// 9. 3DW Indirect Read //// -//// 10. 4DW Indirect Read //// -//// 11. 5DW Indirect Read //// -//// 12. 8DW Indirect Read //// -//// 13. Sector Erase command + Page Write & Read Back //// +//// sspi interfaface through External WB i/F. //// //// //// //// To Do: //// //// nothing ////
diff --git a/verilog/dv/user_usb/.user_usb_tb.v.swp b/verilog/dv/user_usb/.user_usb_tb.v.swp new file mode 100644 index 0000000..13fbb40 --- /dev/null +++ b/verilog/dv/user_usb/.user_usb_tb.v.swp Binary files differ
diff --git a/verilog/dv/user_usb/Makefile b/verilog/dv/user_usb/Makefile new file mode 100644 index 0000000..f72ca56 --- /dev/null +++ b/verilog/dv/user_usb/Makefile
@@ -0,0 +1,100 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +## Caravel Pointers +CARAVEL_ROOT ?= ../../../caravel +CARAVEL_PATH ?= $(CARAVEL_ROOT) +CARAVEL_FIRMWARE_PATH = $(CARAVEL_PATH)/verilog/dv/caravel +CARAVEL_VERILOG_PATH = $(CARAVEL_PATH)/verilog +CARAVEL_RTL_PATH = $(CARAVEL_VERILOG_PATH)/rtl +CARAVEL_BEHAVIOURAL_MODELS = $(CARAVEL_VERILOG_PATH)/dv/caravel + + +## User Project Pointers +UPRJ_VERILOG_PATH ?= ../../../verilog +UPRJ_RTL_PATH = $(UPRJ_VERILOG_PATH)/rtl +UPRJ_GL_PATH = $(UPRJ_VERILOG_PATH)/gl +UPRJ_BEHAVIOURAL_MODELS = ../model +UPRJ_BEHAVIOURAL_AGENTS = ../agents +UPRJ_BEHAVIOURAL_BFM = ../bfm +UPRJ_INCLUDE_PATH1 = $(UPRJ_RTL_PATH)/yifive/ycr1c/src/includes +UPRJ_INCLUDE_PATH2 = $(UPRJ_RTL_PATH)/sdram_ctrl/src/defs +UPRJ_INCLUDE_PATH3 = $(UPRJ_RTL_PATH)/i2cm/src/includes +UPRJ_INCLUDE_PATH4 = $(UPRJ_RTL_PATH)/usb1_host/src/includes +UPRJ_INCLUDE_PATH5 = $(UPRJ_RTL_PATH)/mbist/include + +## YIFIVE FIRMWARE +YIFIVE_FIRMWARE_PATH = $(UPRJ_VERILOG_PATH)/dv/firmware +GCC64_PREFIX?=riscv64-unknown-elf + +## RISCV GCC +GCC_PATH?=/ef/apps/bin +GCC_PREFIX?=riscv32-unknown-elf +PDK_PATH?=/opt/pdk/sky130A + +## Simulation mode: RTL/GL +SIM?=RTL +DUMP?=OFF + +.SUFFIXES: + +PATTERN = user_usb + +all: ${PATTERN:=.vcd} + + +vvp: ${PATTERN:=.vvp} + +%.vvp: %_tb.v +ifeq ($(SIM),RTL) + ifeq ($(DUMP),OFF) + iverilog -g2005-sv -DFUNCTIONAL -DSIM -I $(PDK_PATH) \ + -I $(CARAVEL_BEHAVIOURAL_MODELS) -I $(CARAVEL_RTL_PATH) \ + -I $(UPRJ_BEHAVIOURAL_MODELS) -I $(UPRJ_RTL_PATH) -I $(UPRJ_VERILOG_PATH) \ + -I $(UPRJ_BEHAVIOURAL_AGENTS) -I $(UPRJ_BEHAVIOURAL_BFM) \ + -I $(UPRJ_INCLUDE_PATH1) -I $(UPRJ_INCLUDE_PATH2) -I $(UPRJ_INCLUDE_PATH3) \ + -I $(UPRJ_INCLUDE_PATH4) -I $(UPRJ_INCLUDE_PATH5) \ + $< -o $@ + else + iverilog -g2005-sv -DWFDUMP -DFUNCTIONAL -DSIM -I $(PDK_PATH) \ + -I $(CARAVEL_BEHAVIOURAL_MODELS) -I $(CARAVEL_RTL_PATH) \ + -I $(UPRJ_BEHAVIOURAL_MODELS) -I $(UPRJ_RTL_PATH) -I $(UPRJ_VERILOG_PATH) \ + -I $(UPRJ_BEHAVIOURAL_AGENTS) -I $(UPRJ_BEHAVIOURAL_BFM) \ + -I $(UPRJ_INCLUDE_PATH1) -I $(UPRJ_INCLUDE_PATH2) -I $(UPRJ_INCLUDE_PATH3) \ + -I $(UPRJ_INCLUDE_PATH4) -I $(UPRJ_INCLUDE_PATH5) \ + $< -o $@ + endif +else + iverilog -g2005-sv -DFUNCTIONAL -DSIM -DGL -I $(PDK_PATH) \ + -I $(CARAVEL_BEHAVIOURAL_MODELS) -I $(CARAVEL_RTL_PATH) -I $(CARAVEL_VERILOG_PATH) \ + -I $(UPRJ_BEHAVIOURAL_MODELS) -I $(UPRJ_GL_PATH) \ + -I $(UPRJ_BEHAVIOURAL_AGENTS) \ + $< -o $@ +endif + +%.vcd: %.vvp + vvp $< + +%.hex: + echo @"This is user boot test, noting to compile the mangment core code" + + +# ---- Clean ---- + +clean: + rm -f *.vvp *.vcd *.log *.fst + +.PHONY: clean hex all
diff --git a/verilog/dv/user_usb/tests/.usb_test3.v.swp b/verilog/dv/user_usb/tests/.usb_test3.v.swp new file mode 100644 index 0000000..39e4f3b --- /dev/null +++ b/verilog/dv/user_usb/tests/.usb_test3.v.swp Binary files differ
diff --git a/verilog/dv/user_usb/tests/usb_test1.v b/verilog/dv/user_usb/tests/usb_test1.v new file mode 100755 index 0000000..1522d08 --- /dev/null +++ b/verilog/dv/user_usb/tests/usb_test1.v
@@ -0,0 +1,56 @@ +`define usbbfm u_usb_agent +task usb_test1; + +reg [6:0] address; +reg [3:0] endpt; +reg [3:0] Status; +reg [31:0] ByteCount; + +integer i,j; +reg [7:0] startbyte; +reg [15:0] mask; +integer MaxPktSize; +reg [3:0] PackType; + + +parameter MYACK = 4'b0000, + MYNAK = 4'b0001, + MYSTALL = 4'b0010, + MYTOUT = 4'b0011, + MYIVRES = 4'b0100, + MYCRCER = 4'b0101; + + + + begin + + + $display("%0d: USB Reset -----", $time); + `usbbfm.usbhw_reset; + + address = 1; + endpt = 0; + $display("%0d: Set Address = %x -----", $time,address); + `usbbfm.SetAddress (address); + $display("%0d: Sending Setup Command ", $time); + `usbbfm.setup(7'h00, 4'h0, Status); + `usbbfm.printstatus(Status, MYACK); + $display("%0d: Sending Status Command ", $time); + `usbbfm.status_IN(7'h00, endpt, Status); + `usbbfm.printstatus(Status, MYACK); + #5000; + + $display("%0d: Set configuration -----", $time); + `usbbfm.SetConfiguration(2'b01); + `usbbfm.setup(address, 4'b0000, Status); + `usbbfm.printstatus(Status, MYACK); + `usbbfm.status_IN(address, 4'b0000, Status); + `usbbfm.printstatus(Status, MYACK); + #2000; + + $display("%0d: Configuration done !!!!!!", $time); + test_control.finish_test; + + end + +endtask
diff --git a/verilog/dv/user_usb/tests/usb_test2.v b/verilog/dv/user_usb/tests/usb_test2.v new file mode 100755 index 0000000..fe37549 --- /dev/null +++ b/verilog/dv/user_usb/tests/usb_test2.v
@@ -0,0 +1,91 @@ +`define usbbfm u_usb_agent +task usb_test2; + +reg [6:0] address; +reg [3:0] endpt; +reg [3:0] Status; + + integer i,j; + reg [7:0] startbyte; + reg [15:0] mask; + integer MaxPktSize; + reg [3:0] PackType; + + +parameter MYACK = 4'b0000, + MYNAK = 4'b0001, + MYSTALL = 4'b0010, + MYTOUT = 4'b0011, + MYIVRES = 4'b0100, + MYCRCER = 4'b0101; + + begin + address = 7'b000_0001; + endpt = 4'b0000; + + $display("%0d: USB Reset -----", $time); + `usbbfm.usbhw_reset; + + $display("%0d: Set Address = 1 -----", $time); + `usbbfm.SetAddress (address); + `usbbfm.setup(7'h00, 4'h0, Status); + `usbbfm.printstatus(Status, MYACK); + `usbbfm.status_IN(7'h00, endpt, Status); + `usbbfm.printstatus(Status, MYACK); + #5000; + + $display("%0d: Set configuration -----", $time); + `usbbfm.SetConfiguration(2'b01); + `usbbfm.setup(address, 4'b0000, Status); + `usbbfm.printstatus(Status, MYACK); + `usbbfm.status_IN(address, 4'b0000, Status); + `usbbfm.printstatus(Status, MYACK); + #2000; + + $display("%0d: Configuration done !!!!!!", $time); + + // write UART registers through USB + + ////////////////////////////////////////////////////////////////// + + + // register word write + $display("%0d: Performing Register Word Write------------", $time); + `usbbfm.VenRegWordWr (address, 32'h0, 32'h11223344); + `usbbfm.VenRegWordWr (address, 32'h4, 32'h22334455); + `usbbfm.VenRegWordWr (address, 32'h8, 32'h33445566); + `usbbfm.VenRegWordWr (address, 32'hC, 32'h44556677); + `usbbfm.VenRegWordWr (address, 32'h10, 32'h55667788); + `usbbfm.VenRegWordWr (address, 32'h14, 32'h66778899); + `usbbfm.VenRegWordWr (address, 32'h18, 32'h778899AA); + `usbbfm.VenRegWordWr (address, 32'h1C, 32'h8899AABB); + `usbbfm.VenRegWordWr (address, 32'h20, 32'h99AABBCC); + `usbbfm.VenRegWordWr (address, 32'h24, 32'hAABBCCDD); + `usbbfm.VenRegWordWr (address, 32'h28, 32'hBBCCDDEE); + `usbbfm.VenRegWordWr (address, 32'h2C, 32'hCCDDEEFF); + #500; + + // register word Read + $display("%0d: Performing Register Word Read------------", $time); + `usbbfm.VenRegWordRdCmp (address, 32'h0 , 32'h11223344); + `usbbfm.VenRegWordRdCmp (address, 32'h4 , 32'h22334455); + `usbbfm.VenRegWordRdCmp (address, 32'h8 , 32'h33445566); + `usbbfm.VenRegWordRdCmp (address, 32'hC , 32'h44556677); + `usbbfm.VenRegWordRdCmp (address, 32'h10, 32'h55667788); + `usbbfm.VenRegWordRdCmp (address, 32'h14, 32'h66778899); + `usbbfm.VenRegWordRdCmp (address, 32'h18, 32'h778899AA); + `usbbfm.VenRegWordRdCmp (address, 32'h1C, 32'h8899AABB); + `usbbfm.VenRegWordRdCmp (address, 32'h20, 32'h99AABBCC); + `usbbfm.VenRegWordRdCmp (address, 32'h24, 32'hAABBCCDD); + `usbbfm.VenRegWordRdCmp (address, 32'h28, 32'hBBCCDDEE); + `usbbfm.VenRegWordRdCmp (address, 32'h2C, 32'hCCDDEEFF); + #500 + + + + $display ("USB doing register writes and reads to USB block end \n"); + + test_control.finish_test; + end + +endtask
diff --git a/verilog/dv/user_usb/tests/usb_test3.v b/verilog/dv/user_usb/tests/usb_test3.v new file mode 100755 index 0000000..51d1c69 --- /dev/null +++ b/verilog/dv/user_usb/tests/usb_test3.v
@@ -0,0 +1,182 @@ +`define usbbfm tb_top.u_usb_agent +task usb_test3; + +reg [6:0] address; +reg [3:0] endpt; +reg [3:0] Status; +reg [31:0] ByteCount; +reg [31:0] ReadData; +integer i,j,k; + + +reg [1:0] data_bit ; +reg stop_bits ; // 0: 1 stop bit; 1: 2 stop bit; +reg stick_parity ; // 1: force even parity +reg parity_en ; // parity enable +reg even_odd_parity ; // 0: odd parity; 1: even parity +reg [15:0] divisor ; // divided by (n+1) * 16 +reg [15:0] timeout ;// wait time limit +reg fifo_enable ; // fifo mode disable + +reg [7:0] write_data [0:39]; +reg [15:0] rx_nu; +reg [15:0] tx_nu; + + +parameter MYACK = 4'b0000, + MYNAK = 4'b0001, + MYSTALL = 4'b0010, + MYTOUT = 4'b0011, + MYIVRES = 4'b0100, + MYCRCER = 4'b0101; + + begin + address = 7'b000_0001; + endpt = 4'b0000; + + $display("%0d: USB Reset -----", $time); + `usbbfm.usbhw_reset; + + /********************************************************* + * HOST DEVICE + * 1. 0x2D,0x00, 0x00 + * 2. 0xC3,0x00,0x05,0x01, + * 0x00,0x00,0x00,0x00, + * 0x00,0xEB,0x25 + * 3. 0xD2 + * 4. 0x69,0x00, 0x10 + * 5. 0x4B, 0x00 + * 6. 0xD2 + **********************************************************/ + $display("%0d: Set Address = 1 -----", $time); + `usbbfm.SetAddress (address); + `usbbfm.setup(7'h00, 4'h0, Status); + `usbbfm.printstatus(Status, MYACK); + `usbbfm.status_IN(7'h00, endpt, Status); + `usbbfm.printstatus(Status, MYACK); + + #5000; + /********************************************************* + * HOST DEVICE + * 1. 0x2D,0x01, 0xE8 + * 2. 0xC3,0x00,0x09,0x01, + * 0x00,0x00,0x00,0x00, + * 0x00,0x27,0x25 + * 3. 0xD2 + * 4. 0x69,0x01, 0xE8 + * 5. 0x4B, 0x00 + * 6. 0xD2 + **********************************************************/ + + $display("%0d: Set configuration -----", $time); + `usbbfm.SetConfiguration(2'b01); + `usbbfm.setup(address, 4'b0000, Status); + `usbbfm.printstatus(Status, MYACK); + `usbbfm.status_IN(address, 4'b0000, Status); + `usbbfm.printstatus(Status, MYACK); + #2000; + + $display("%0d: Configuration done !!!!!!", $time); + + // write UART registers through USB + + ////////////////////////////////////////////////////////////////// + data_bit = 2'b11; + stop_bits = 0; // 0: 1 stop bit; 1: 2 stop bit; + stick_parity = 0; // 1: force even parity + parity_en = 1; // parity enable + even_odd_parity = 1; // 0: odd parity; 1: even parity + divisor = 15; // divided by (n+1) * 16 + timeout = 500;// wait time limit + fifo_enable = 0; // fifo mode disable + + tb_top.u_uart_agent.uart_init; + /********************************************************* + * HOST DEVICE + * 1. 0x2D,0x01, 0xE8 + * 2. 0xC3,0x40,0x10,0x00, + * 0x00,0x00,0x00,0x04, + * 0x00,0xA8,0xC5 + * 3. 0xD2 + * 4. 0xE1,0x01, 0xE8 + * 5. 0x4B,0x00,0x00,0x00 + * 0x17,0xBF,0xD5 + * 6 0xD2 + * 7. 0x69,0x01,0xE8 + * 8. 0x4B,0x00 + * 9. 0xD2 + **********************************************************/ + `usbbfm.VenRegWordWr (address, 32'h0, {27'h0,2'b10,1'b1,1'b1,1'b1}); + /********************************************************* + * HOST DEVICE + * 1. 0x2D,0x01, 0xE8 + * 2. 0xC3,0x40,0x10,0x00, + * 0x00,0x00,0x08,0x04, + * 0x00,0x29,0x07 + * 3. 0xD2 + * 4. 0xE1,0x01, 0xE8 + * 5. 0x4B,0x00,0x00,0x00 + * 0x0E,0x7E,0x1F + * 6 0xD2 + * 7. 0x69,0x01,0xE8 + * 8. 0x4B,0x00 + * 9. 0xD2 + **********************************************************/ + // Baud Clock 16x, Master Clock/ (2+cfg_value) + `usbbfm.VenRegWordWr (address, 32'h8, divisor-1); + tb_top.u_uart_agent.control_setup (data_bit, stop_bits, parity_en, even_odd_parity, stick_parity, timeout, divisor, fifo_enable); + + for (i=0; i<40; i=i+1) + write_data[i] = $random; + + fork + begin + for (i=0; i<40; i=i+1) + begin + $display ("\n... Writing char %d ...", write_data[i]); + tb_top.u_uart_agent.write_char (write_data[i]); + #20000; + end + end + + begin + for (j=0; j<40; j=j+1) + begin + tb_top.u_uart_agent.read_char_chk(write_data[j]); + end + end + + // Read through the USB and check the UART RX Fifo Status; + // If Available, then loop it back + begin + for (k=0; k<40; k=k+1) + begin + ReadData[1]= 1'b1; + while(ReadData[1] == 1'b1 ) begin // Check for UART RX fifo not empty + $display ("\n... Reading the UART Status: %x ...", ReadData); + /********************************************************* + * HOST DEVICE + * 1. 0x2D,0x01, 0xE8 + * 2. 0xC3,0xC0,0x11,0x00, + * 0x00,0x00,0x0C,0x04, + * 0x00,0x70,0x66 + * 3. 0xD2 + * 4. 0x69,0x01, 0xE8 + * 5. 0x4B,00 + * 6. 0xD2 + * 7. 0xE1,0x01,0xE8 + * 8. 0x4B,0x00, 0x00 + * 9 0xD2 + **********************************************************/ + `usbbfm.VenRegWordRd (address, 32'hC, ReadData); + end + `usbbfm.VenRegWordRd (address, 32'h14, ReadData); // Read the UART RXD Data + `usbbfm.VenRegWordWr (address, 32'h10, ReadData); // Write Back to UART TXD + end + end + join + + #100 + tb_top.u_uart_agent.report_status(rx_nu, tx_nu); +end +endtask
diff --git a/verilog/dv/user_usb/user_usb_tb.v b/verilog/dv/user_usb/user_usb_tb.v new file mode 100644 index 0000000..73e2b47 --- /dev/null +++ b/verilog/dv/user_usb/user_usb_tb.v
@@ -0,0 +1,561 @@ +//////////////////////////////////////////////////////////////////////////// +// SPDX-FileCopyrightText: 2021 , Dinesh Annayya +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileContributor: Modified by Dinesh Annayya <dinesha@opencores.org> +////////////////////////////////////////////////////////////////////// +//// //// +//// Standalone User validation Test bench //// +//// //// +//// This file is part of the riscduino project //// +//// https://github.com/dineshannayya/riscduino.git //// +//// //// +//// Description //// +//// This is a standalone test bench to validate the //// +//// usb interfaface through External WB i/F. //// +//// //// +//// To Do: //// +//// nothing //// +//// //// +//// Author(s): //// +//// - Dinesh Annayya, dinesha@opencores.org //// +//// //// +//// Revision : //// +//// 0.1 - 09 Mar 2022, Dinesh A //// +//// //// +////////////////////////////////////////////////////////////////////// + +`default_nettype wire + +`timescale 1 ns / 1 ns + +// Note in caravel, 0x30XX_XXXX only come to user interface +// So, using wb_host bank select we have changing MSB address [31:24] = 0x10 +`define ADDR_SPACE_UART 32'h3001_0000 +`define ADDR_SPACE_USB 32'h3001_0080 +`define ADDR_SPACE_SSPI 32'h3001_00C0 +`define ADDR_SPACE_PINMUX 32'h3002_0000 + +`define TB_GLBL user_usb_tb +`define USB_BFM u_usb_agent + +`include "uprj_netlists.v" +`include "usb_agents.v" +`include "test_control.v" +`include "usb1d_defines.v" +`include "usbd_files.v" + +module user_usb_tb; + +parameter USB_HPER = 10.4167; // 48Mhz Half cycle +parameter USER2_HPER = 2.6042; // 192Mhz Half cycle + + reg clock; + reg user_clock2; + reg usb_48mhz_clk; + reg wb_rst_i; + reg power1, power2; + reg power3, power4; + + reg wbd_ext_cyc_i; // strobe/request + reg wbd_ext_stb_i; // strobe/request + reg [31:0] wbd_ext_adr_i; // address + reg wbd_ext_we_i; // write + reg [31:0] wbd_ext_dat_i; // data output + reg [3:0] wbd_ext_sel_i; // byte enable + + wire [31:0] wbd_ext_dat_o; // data input + wire wbd_ext_ack_o; // acknowlegement + wire wbd_ext_err_o; // error + + // User I/O + wire [37:0] io_oeb; + wire [37:0] io_out; + wire [37:0] io_in; + + + reg [1:0] spi_chip_no; + + wire gpio; + wire [37:0] mprj_io; + wire [7:0] mprj_io_0; + reg test_fail; + reg [31:0] read_data; + + //----------------------------------- + // Register Interface + // ---------------------------------- + wire [31:0] usbd_reg_addr; // Register Address + wire usbd_reg_rdwrn; // 0 -> write, 1-> read + wire usbd_reg_req; // Register Req + wire [31:0] usbd_reg_wdata; // Register write data + reg [31:0] usbd_reg_rdata; // Register Read Data + reg usbd_reg_ack = 1'b1; // Register Ack + + reg [31:0] RegBank [0:15]; + + // External clock is used by default. Make this artificially fast for the + // simulation. Normally this would be a slow clock and the digital PLL + // would be the fast clock. + + always #12.5 clock <= (clock === 1'b0); + + // 48Mhz clock generation + always begin + #USB_HPER usb_48mhz_clk = 1'b0; + #USB_HPER usb_48mhz_clk = 1'b1; + end + + // USER Clock generation + always begin + #USER2_HPER user_clock2 = 1'b0; + #USER2_HPER user_clock2 = 1'b1; + end + + initial begin + clock = 0; + wbd_ext_cyc_i ='h0; // strobe/request + wbd_ext_stb_i ='h0; // strobe/request + wbd_ext_adr_i ='h0; // address + wbd_ext_we_i ='h0; // write + wbd_ext_dat_i ='h0; // data output + wbd_ext_sel_i ='h0; // byte enable + end + initial begin + wb_rst_i <= 1'b1; + #100; + wb_rst_i <= 1'b0; // Release reset + end + + `ifdef WFDUMP + initial begin + $dumpfile("simx.vcd"); + $dumpvars(5, user_usb_tb); + end + `endif + + always@(posedge wb_rst_i or posedge usb_48mhz_clk) + begin + if(wb_rst_i == 1'b1) begin + usbd_reg_rdata = 'h0; + usbd_reg_ack = 'h0; + end else begin + if(usbd_reg_req && usbd_reg_rdwrn == 1'b0 && !usbd_reg_ack) begin + usbd_reg_ack = 'h1; + RegBank[usbd_reg_addr[5:2]] = usbd_reg_wdata; + $display("STATUS: Write Access Address : %x Data: %x",usbd_reg_addr[7:0],usbd_reg_wdata); + end else if(usbd_reg_req && usbd_reg_rdwrn == 1'b1 && !usbd_reg_ack) begin + usbd_reg_ack = 'h1; + usbd_reg_rdata = RegBank[usbd_reg_addr[5:2]]; + $display("STATUS: Read Access Address : %x Data: %x",usbd_reg_addr[7:0],usbd_reg_rdata); + end else begin + usbd_reg_ack = 'h0; + end + end + end + + initial begin + $dumpon; + + #200; // Wait for reset removal + repeat (10) @(posedge clock); + $display("Monitor: Standalone User Risc Boot Test Started"); + + // Remove Wb Reset + wb_user_core_write('h3080_0000,'h1); + + // Enable SPI Multi Functional Ports + wb_user_core_write(`ADDR_SPACE_PINMUX+'h0038,'h400); + + repeat (2) @(posedge clock); + #1; + + // Set USB clock : 192/4 = 48Mhz + wb_user_core_write('h3080_0000,{8'h82,4'h0,8'h0,4'h0,8'h01}); + + // Remove the reset + // Remove WB and SPI/UART Reset, Keep CORE under Reset + wb_user_core_write(`ADDR_SPACE_PINMUX+8'h8,'h03F); + + + test_fail = 0; + repeat (200) @(posedge clock); + wb_user_core_write('h3080_0004,'h10); // Change the Bank Sel 10 + + + //usb_test1; + usb_test2; + + + repeat (100) @(posedge clock); + // $display("+1000 cycles"); + + if(test_control.error_count == 0) begin + `ifdef GL + $display("Monitor: USB Mode (GL) Passed"); + `else + $display("Monitor: USB Mode (RTL) Passed"); + `endif + end else begin + `ifdef GL + $display("Monitor: USB Mode (GL) Failed"); + `else + $display("Monitor: USB Mode (RTL) Failed"); + `endif + end + $display("###################################################"); + $finish; + end + +wire USER_VDD1V8 = 1'b1; +wire VSS = 1'b0; + +user_project_wrapper u_top( +`ifdef USE_POWER_PINS + .vccd1(USER_VDD1V8), // User area 1 1.8V supply + .vssd1(VSS), // User area 1 digital ground +`endif + .wb_clk_i (clock ), // System clock + .user_clock2 (user_clock2 ), // Real-time clock + .wb_rst_i (wb_rst_i ), // Regular Reset signal + + .wbs_cyc_i (wbd_ext_cyc_i), // strobe/request + .wbs_stb_i (wbd_ext_stb_i), // strobe/request + .wbs_adr_i (wbd_ext_adr_i), // address + .wbs_we_i (wbd_ext_we_i), // write + .wbs_dat_i (wbd_ext_dat_i), // data output + .wbs_sel_i (wbd_ext_sel_i), // byte enable + + .wbs_dat_o (wbd_ext_dat_o), // data input + .wbs_ack_o (wbd_ext_ack_o), // acknowlegement + + + // Logic Analyzer Signals + .la_data_in ('1) , + .la_data_out (), + .la_oenb ('0), + + + // IOs + .io_in (io_in) , + .io_out (io_out) , + .io_oeb (io_oeb) , + + .user_irq () + +); + usb_agent u_usb_agent(); + test_control test_control(); + +`ifndef GL // Drive Power for Hold Fix Buf + // All standard cell need power hook-up for functionality work + initial begin + + end +`endif + +// Drive USB Pads +// +tri usbd_txdp = (io_oeb[36] == 1'b0) ? io_out[36] : 1'bz; +tri usbd_txdn = (io_oeb[37] == 1'b0) ? io_out[37] : 1'bz; + +assign io_in[36] = usbd_txdp; +assign io_in[37] = usbd_txdn; + +// Full Speed Device Indication + +pullup(usbd_txdp); +//pulldown(usbd_txdn); + +usb1d_top u_usb_top( + + .clk_i (usb_48mhz_clk), + .rstn_i (!wb_rst_i), + + // USB PHY Interface + .usb_dp (usbd_txdp), + .usb_dn (usbd_txdn), + + // USB Misc + .phy_tx_mode (1'b1), + .usb_rst (), + + // Interrupts + .dropped_frame (), + .misaligned_frame(), + .crc16_err (), + + // Vendor Features + .v_set_int (), + .v_set_feature (), + .wValue (), + .wIndex (), + .vendor_data (), + + // USB Status + .usb_busy (), + .ep_sel (), + + // End point 1 configuration + .ep1_cfg ( `ISO | `IN | 14'd0256 ), + // End point 1 'OUT' FIFO i/f + .ep1_dout ( ), + .ep1_we ( ), + .ep1_full ( 1'b0 ), + // End point 1 'IN' FIFO i/f + .ep1_din ( 8'h0 ), + .ep1_re ( ), + .ep1_empty ( 1'b0 ), + .ep1_bf_en ( 1'b0 ), + .ep1_bf_size ( 7'h0 ), + + // End point 2 configuration + .ep2_cfg ( `ISO | `OUT | 14'd0256 ), + // End point 2 'OUT' FIFO i/f + .ep2_dout ( ), + .ep2_we ( ), + .ep2_full ( 1'b0 ), + // End point 2 'IN' FIFO i/f + .ep2_din ( 8'h0 ), + .ep2_re ( ), + .ep2_empty ( 1'b0 ), + .ep2_bf_en ( 1'b0 ), + .ep2_bf_size ( 7'h0 ), + + // End point 3 configuration + .ep3_cfg ( `BULK | `IN | 14'd064 ), + // End point 3 'OUT' FIFO i/f + .ep3_dout ( ), + .ep3_we ( ), + .ep3_full ( 1'b0 ), + // End point 3 'IN' FIFO i/f + .ep3_din ( 8'h0 ), + .ep3_re ( ), + .ep3_empty ( 1'b0 ), + .ep3_bf_en ( 1'b0 ), + .ep3_bf_size ( 7'h0 ), + + // End point 4 configuration + .ep4_cfg ( `BULK | `OUT | 14'd064 ), + // End point 4 'OUT' FIFO i/f + .ep4_dout ( ), + .ep4_we ( ), + .ep4_full ( 1'b0 ), + // End point 4 'IN' FIFO i/f + .ep4_din ( 8'h0 ), + .ep4_re ( ), + .ep4_empty ( 1'b0 ), + .ep4_bf_en ( 1'b0 ), + .ep4_bf_size ( 7'h0 ), + + // End point 5 configuration + .ep5_cfg ( `INT | `IN | 14'd064 ), + // End point 5 'OUT' FIFO i/f + .ep5_dout ( ), + .ep5_we ( ), + .ep5_full ( 1'b0 ), + // End point 5 'IN' FIFO i/f + .ep5_din ( 8'h0 ), + .ep5_re ( ), + .ep5_empty ( 1'b0 ), + .ep5_bf_en ( 1'b0 ), + .ep5_bf_size ( 7'h0 ), + + // End point 6 configuration + .ep6_cfg ( 14'h00 ), + // End point 6 'OUT' FIFO i/f + .ep6_dout ( ), + .ep6_we ( ), + .ep6_full ( 1'b0 ), + // End point 6 'IN' FIFO i/f + .ep6_din ( 8'h0 ), + .ep6_re ( ), + .ep6_empty ( 1'b0 ), + .ep6_bf_en ( 1'b0 ), + .ep6_bf_size ( 7'h0 ), + + // End point 7 configuration + .ep7_cfg ( 14'h00 ), + // End point 7 'OUT' FIFO i/f + .ep7_dout ( ), + .ep7_we ( ), + .ep7_full ( 1'b0 ), + // End point 7 'IN' FIFO i/f + .ep7_din ( 8'h0 ), + .ep7_re ( ), + .ep7_empty ( 1'b0 ), + .ep7_bf_en ( 1'b0 ), + .ep7_bf_size ( 7'h0 ), + + // Register Interface + .reg_addr (usbd_reg_addr), + .reg_rdwrn (usbd_reg_rdwrn), + .reg_req (usbd_reg_req), + .reg_wdata (usbd_reg_wdata), + .reg_rdata (usbd_reg_rdata), + .reg_ack (usbd_reg_ack) + + ); + + +//---------------------------------------------------- +// Task +// -------------------------------------------------- +task test_err; +begin + test_fail = 1; +end +endtask + +task wb_user_core_write; +input [31:0] address; +input [31:0] data; +begin + repeat (1) @(posedge clock); + #1; + wbd_ext_adr_i =address; // address + wbd_ext_we_i ='h1; // write + wbd_ext_dat_i =data; // data output + wbd_ext_sel_i ='hF; // byte enable + wbd_ext_cyc_i ='h1; // strobe/request + wbd_ext_stb_i ='h1; // strobe/request + wait(wbd_ext_ack_o == 1); + repeat (1) @(posedge clock); + #1; + wbd_ext_cyc_i ='h0; // strobe/request + wbd_ext_stb_i ='h0; // strobe/request + wbd_ext_adr_i ='h0; // address + wbd_ext_we_i ='h0; // write + wbd_ext_dat_i ='h0; // data output + wbd_ext_sel_i ='h0; // byte enable + $display("STATUS: WB USER ACCESS WRITE Address : 0x%x, Data : 0x%x",address,data); + repeat (2) @(posedge clock); +end +endtask + +task wb_user_core_read; +input [31:0] address; +output [31:0] data; +reg [31:0] data; +begin + repeat (1) @(posedge clock); + #1; + wbd_ext_adr_i =address; // address + wbd_ext_we_i ='h0; // write + wbd_ext_dat_i ='0; // data output + wbd_ext_sel_i ='hF; // byte enable + wbd_ext_cyc_i ='h1; // strobe/request + wbd_ext_stb_i ='h1; // strobe/request + wait(wbd_ext_ack_o == 1); + data = wbd_ext_dat_o; + repeat (1) @(posedge clock); + #1; + wbd_ext_cyc_i ='h0; // strobe/request + wbd_ext_stb_i ='h0; // strobe/request + wbd_ext_adr_i ='h0; // address + wbd_ext_we_i ='h0; // write + wbd_ext_dat_i ='h0; // data output + wbd_ext_sel_i ='h0; // byte enable + //$display("STATUS: WB USER ACCESS READ Address : 0x%x, Data : 0x%x",address,data); + repeat (2) @(posedge clock); +end +endtask + +task wb_user_core_read_check; +input [31:0] address; +output [31:0] data; +input [31:0] cmp_data; +reg [31:0] data; +begin + repeat (1) @(posedge clock); + #1; + wbd_ext_adr_i =address; // address + wbd_ext_we_i ='h0; // write + wbd_ext_dat_i ='0; // data output + wbd_ext_sel_i ='hF; // byte enable + wbd_ext_cyc_i ='h1; // strobe/request + wbd_ext_stb_i ='h1; // strobe/request + wait(wbd_ext_ack_o == 1); + data = wbd_ext_dat_o; + repeat (1) @(posedge clock); + #1; + wbd_ext_cyc_i ='h0; // strobe/request + wbd_ext_stb_i ='h0; // strobe/request + wbd_ext_adr_i ='h0; // address + wbd_ext_we_i ='h0; // write + wbd_ext_dat_i ='h0; // data output + wbd_ext_sel_i ='h0; // byte enable + if(data !== cmp_data) begin + $display("ERROR : WB USER ACCESS READ Address : 0x%x, Exd: 0x%x Rxd: 0x%x ",address,cmp_data,data); + user_usb_tb.test_fail = 1; + end else begin + $display("STATUS: WB USER ACCESS READ Address : 0x%x, Data : 0x%x",address,data); + end + repeat (2) @(posedge clock); +end +endtask + + +`ifdef GL + +wire wbd_spi_stb_i = u_top.u_spi_master.wbd_stb_i; +wire wbd_spi_ack_o = u_top.u_spi_master.wbd_ack_o; +wire wbd_spi_we_i = u_top.u_spi_master.wbd_we_i; +wire [31:0] wbd_spi_adr_i = u_top.u_spi_master.wbd_adr_i; +wire [31:0] wbd_spi_dat_i = u_top.u_spi_master.wbd_dat_i; +wire [31:0] wbd_spi_dat_o = u_top.u_spi_master.wbd_dat_o; +wire [3:0] wbd_spi_sel_i = u_top.u_spi_master.wbd_sel_i; + +wire wbd_sdram_stb_i = u_top.u_sdram_ctrl.wb_stb_i; +wire wbd_sdram_ack_o = u_top.u_sdram_ctrl.wb_ack_o; +wire wbd_sdram_we_i = u_top.u_sdram_ctrl.wb_we_i; +wire [31:0] wbd_sdram_adr_i = u_top.u_sdram_ctrl.wb_addr_i; +wire [31:0] wbd_sdram_dat_i = u_top.u_sdram_ctrl.wb_dat_i; +wire [31:0] wbd_sdram_dat_o = u_top.u_sdram_ctrl.wb_dat_o; +wire [3:0] wbd_sdram_sel_i = u_top.u_sdram_ctrl.wb_sel_i; + +wire wbd_uart_stb_i = u_top.u_uart_i2c_usb.reg_cs; +wire wbd_uart_ack_o = u_top.u_uart_i2c_usb.reg_ack; +wire wbd_uart_we_i = u_top.u_uart_i2c_usb.reg_wr; +wire [7:0] wbd_uart_adr_i = u_top.u_uart_i2c_usb.reg_addr; +wire [7:0] wbd_uart_dat_i = u_top.u_uart_i2c_usb.reg_wdata; +wire [7:0] wbd_uart_dat_o = u_top.u_uart_i2c_usb.reg_rdata; +wire wbd_uart_sel_i = u_top.u_uart_i2c_usb.reg_be; + +`endif + +/** +`ifdef GL +//----------------------------------------------------------------------------- +// RISC IMEM amd DMEM Monitoring TASK +//----------------------------------------------------------------------------- + +`define RISC_CORE user_uart_tb.u_top.u_core.u_riscv_top + +always@(posedge `RISC_CORE.wb_clk) begin + if(`RISC_CORE.wbd_imem_ack_i) + $display("RISCV-DEBUG => IMEM ADDRESS: %x Read Data : %x", `RISC_CORE.wbd_imem_adr_o,`RISC_CORE.wbd_imem_dat_i); + if(`RISC_CORE.wbd_dmem_ack_i && `RISC_CORE.wbd_dmem_we_o) + $display("RISCV-DEBUG => DMEM ADDRESS: %x Write Data: %x Resonse: %x", `RISC_CORE.wbd_dmem_adr_o,`RISC_CORE.wbd_dmem_dat_o); + if(`RISC_CORE.wbd_dmem_ack_i && !`RISC_CORE.wbd_dmem_we_o) + $display("RISCV-DEBUG => DMEM ADDRESS: %x READ Data : %x Resonse: %x", `RISC_CORE.wbd_dmem_adr_o,`RISC_CORE.wbd_dmem_dat_i); +end + +`endif +**/ +`include "tests/usb_test1.v" +`include "tests/usb_test2.v" + +endmodule +`default_nettype wire
diff --git a/verilog/rtl/pinmux/src/pinmux_reg.sv b/verilog/rtl/pinmux/src/pinmux_reg.sv index 8f900b1..1b0d310 100644 --- a/verilog/rtl/pinmux/src/pinmux_reg.sv +++ b/verilog/rtl/pinmux/src/pinmux_reg.sv
@@ -279,6 +279,12 @@ //----------------------------------------------------------------------- // Chip ID +// chip-id[3:0] mapping +// 0 - YIFIVE (MPW-2) +// 1 - Riscdunio (MPW-3) +// 2 - Riscdunio (MPW-4) +// 3 - Riscdunio (MPW-5) + wire [15:0] manu_id = 16'h8268; // Asci value of RD wire [3:0] total_core = 4'h1; wire [3:0] chip_id = 4'h3; @@ -763,7 +769,7 @@ //----------------------------------------- // Software Reg-2, Release date: <DAY><MONTH><YEAR> // ---------------------------------------- -gen_32b_reg #(32'h0203_2022) u_reg_23 ( +gen_32b_reg #(32'h1003_2022) u_reg_23 ( //List of Inputs .reset_n (h_reset_n ), .clk (mclk ), @@ -776,9 +782,9 @@ ); //----------------------------------------- -// Software Reg-3: Poject Revison 3.7 = 0003700 +// Software Reg-3: Poject Revison 3.8 = 0003800 // ---------------------------------------- -gen_32b_reg #(32'h0003_7000) u_reg_24 ( +gen_32b_reg #(32'h0003_8000) u_reg_24 ( //List of Inputs .reset_n (h_reset_n ), .clk (mclk ),
diff --git a/verilog/rtl/uart_i2c_usb_spi/src/uart_i2c_usb_spi.sv b/verilog/rtl/uart_i2c_usb_spi/src/uart_i2c_usb_spi.sv index d3378e0..028f1d7 100644 --- a/verilog/rtl/uart_i2c_usb_spi/src/uart_i2c_usb_spi.sv +++ b/verilog/rtl/uart_i2c_usb_spi/src/uart_i2c_usb_spi.sv
@@ -168,8 +168,8 @@ wire reg_uart_cs = (reg_addr[7:6] == `SEL_UART) ? reg_cs : 1'b0; wire reg_i2cm_cs = (reg_addr[7:6] == `SEL_I2C) ? reg_cs : 1'b0; -wire reg_usb_cs = (reg_addr[7:6] == `SEL_UART) ? reg_cs : 1'b0; -wire reg_spim_cs = (reg_addr[7:6] == `SEL_SPI) ? reg_cs : 1'b0; +wire reg_usb_cs = (reg_addr[7:6] == `SEL_USB) ? reg_cs : 1'b0; +wire reg_spim_cs = (reg_addr[7:6] == `SEL_SPI) ? reg_cs : 1'b0; uart_core u_uart_core (
diff --git a/verilog/rtl/usb1_host/src/top/usb1_host.sv b/verilog/rtl/usb1_host/src/top/usb1_host.sv index 1de70d4..6ee0ff5 100644 --- a/verilog/rtl/usb1_host/src/top/usb1_host.sv +++ b/verilog/rtl/usb1_host/src/top/usb1_host.sv
@@ -57,8 +57,8 @@ input in_dp , input in_dn , - input out_dp , - input out_dn , + output out_dp , + output out_dn , output out_tx_oen, // Master Port
diff --git a/verilog/rtl/user_project_wrapper.v b/verilog/rtl/user_project_wrapper.v index 68ba561..3688747 100644 --- a/verilog/rtl/user_project_wrapper.v +++ b/verilog/rtl/user_project_wrapper.v
@@ -191,7 +191,10 @@ //// 1. qspi cs# port mapping changed from io 28:25 to 25:28//// //// 2. sspi, bug fix in reg access and endian support added//// //// 3. Wishbone interconnect now support cross-connect //// -//// feature +//// feature //// +//// 3.8 Mar 10 2022, Dinesh A //// +//// 1. usb chip select bug inside uart_* wrapper //// +//// 2. in wb_host, increased usb clk ctrl to 4 to 8 bit //// ////////////////////////////////////////////////////////////////////// //// //// //// Copyright (C) 2000 Authors and OPENCORES.ORG ////
diff --git a/verilog/rtl/wb_host/src/wb_host.sv b/verilog/rtl/wb_host/src/wb_host.sv index 55bf9fb..eef549a 100644 --- a/verilog/rtl/wb_host/src/wb_host.sv +++ b/verilog/rtl/wb_host/src/wb_host.sv
@@ -152,7 +152,7 @@ logic [3:0] cfg_wb_clk_ctrl; logic [3:0] cfg_cpu_clk_ctrl; logic [7:0] cfg_rtc_clk_ctrl; -logic [3:0] cfg_usb_clk_ctrl; +logic [7:0] cfg_usb_clk_ctrl; logic [7:0] cfg_glb_ctrl; // uart Master Port @@ -363,7 +363,7 @@ assign cfg_wb_clk_ctrl = reg_0[11:8]; assign cfg_rtc_clk_ctrl = reg_0[19:12]; assign cfg_cpu_clk_ctrl = reg_0[23:20]; -assign cfg_usb_clk_ctrl = reg_0[31:28]; +assign cfg_usb_clk_ctrl = reg_0[31:24]; always @( *) @@ -544,8 +544,8 @@ wire usb_ref_clk; wire usb_clk_int; -wire cfg_usb_clk_div = cfg_usb_clk_ctrl[3]; -wire [2:0] cfg_usb_clk_ratio = cfg_usb_clk_ctrl[2:0]; +wire cfg_usb_clk_div = cfg_usb_clk_ctrl[7]; +wire [6:0] cfg_usb_clk_ratio = cfg_usb_clk_ctrl[6:0]; assign usb_ref_clk = user_clock2 ; //assign usb_clk_int = (cfg_usb_clk_div) ? usb_clk_div : usb_ref_clk; @@ -554,7 +554,7 @@ ctech_clk_buf u_clkbuf_usb (.A (usb_clk_int), . X(usb_clk)); -clk_ctl #(2) u_usbclk ( +clk_ctl #(6) u_usbclk ( // Outputs .clk_o (usb_clk_div ), // Inputs