mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-25 23:24:15 +01:00
added fpga flash update access
This commit is contained in:
parent
0b18c55d1c
commit
9c710a2019
@ -78,12 +78,21 @@
|
|||||||
<Source name="../../rtl/usb/usb_ft1248.sv" type="Verilog" type_short="Verilog">
|
<Source name="../../rtl/usb/usb_ft1248.sv" type="Verilog" type_short="Verilog">
|
||||||
<Options VerilogStandard="System Verilog"/>
|
<Options VerilogStandard="System Verilog"/>
|
||||||
</Source>
|
</Source>
|
||||||
|
<Source name="../../rtl/vendor/vendor_scb.sv" type="Verilog" type_short="Verilog">
|
||||||
|
<Options VerilogStandard="System Verilog"/>
|
||||||
|
</Source>
|
||||||
<Source name="../../rtl/vendor/lcmxo2/fifo_8kb.sv" type="Verilog" type_short="Verilog">
|
<Source name="../../rtl/vendor/lcmxo2/fifo_8kb.sv" type="Verilog" type_short="Verilog">
|
||||||
<Options VerilogStandard="System Verilog"/>
|
<Options VerilogStandard="System Verilog"/>
|
||||||
</Source>
|
</Source>
|
||||||
<Source name="../../rtl/vendor/lcmxo2/pll.sv" type="Verilog" type_short="Verilog">
|
<Source name="../../rtl/vendor/lcmxo2/pll.sv" type="Verilog" type_short="Verilog">
|
||||||
<Options VerilogStandard="System Verilog"/>
|
<Options VerilogStandard="System Verilog"/>
|
||||||
</Source>
|
</Source>
|
||||||
|
<Source name="../../rtl/vendor/lcmxo2/vendor.sv" type="Verilog" type_short="Verilog">
|
||||||
|
<Options VerilogStandard="System Verilog"/>
|
||||||
|
</Source>
|
||||||
|
<Source name="../../rtl/vendor/lcmxo2/generated/efb_lattice_generated.v" type="Verilog" type_short="Verilog">
|
||||||
|
<Options/>
|
||||||
|
</Source>
|
||||||
<Source name="../../rtl/vendor/lcmxo2/generated/fifo_8kb_lattice_generated.v" type="Verilog" type_short="Verilog">
|
<Source name="../../rtl/vendor/lcmxo2/generated/fifo_8kb_lattice_generated.v" type="Verilog" type_short="Verilog">
|
||||||
<Options/>
|
<Options/>
|
||||||
</Source>
|
</Source>
|
||||||
|
@ -92,7 +92,7 @@
|
|||||||
<Property name="PROP_MAP_MAPInferGSR" value="True" time="0"/>
|
<Property name="PROP_MAP_MAPInferGSR" value="True" time="0"/>
|
||||||
<Property name="PROP_MAP_MapModArgs" value="" time="0"/>
|
<Property name="PROP_MAP_MapModArgs" value="" time="0"/>
|
||||||
<Property name="PROP_MAP_OvermapDevice" value="False" time="0"/>
|
<Property name="PROP_MAP_OvermapDevice" value="False" time="0"/>
|
||||||
<Property name="PROP_MAP_PackLogMapDes" value="" time="0"/>
|
<Property name="PROP_MAP_PackLogMapDes" value="0" time="0"/>
|
||||||
<Property name="PROP_MAP_RegRetiming" value="False" time="0"/>
|
<Property name="PROP_MAP_RegRetiming" value="False" time="0"/>
|
||||||
<Property name="PROP_MAP_SigCrossRef" value="False" time="0"/>
|
<Property name="PROP_MAP_SigCrossRef" value="False" time="0"/>
|
||||||
<Property name="PROP_MAP_SymCrossRef" value="False" time="0"/>
|
<Property name="PROP_MAP_SymCrossRef" value="False" time="0"/>
|
||||||
@ -119,7 +119,7 @@
|
|||||||
<Property name="PROP_PAR_PARModArgs" value="" time="0"/>
|
<Property name="PROP_PAR_PARModArgs" value="" time="0"/>
|
||||||
<Property name="PROP_PAR_ParMultiNodeList" value="" time="0"/>
|
<Property name="PROP_PAR_ParMultiNodeList" value="" time="0"/>
|
||||||
<Property name="PROP_PAR_ParRunPlaceOnly" value="False" time="0"/>
|
<Property name="PROP_PAR_ParRunPlaceOnly" value="False" time="0"/>
|
||||||
<Property name="PROP_PAR_PlcIterParDes" value="1" time="0"/>
|
<Property name="PROP_PAR_PlcIterParDes" value="3" time="0"/>
|
||||||
<Property name="PROP_PAR_PlcStCostTblParDes" value="1" time="0"/>
|
<Property name="PROP_PAR_PlcStCostTblParDes" value="1" time="0"/>
|
||||||
<Property name="PROP_PAR_PrefErrorOut" value="True" time="0"/>
|
<Property name="PROP_PAR_PrefErrorOut" value="True" time="0"/>
|
||||||
<Property name="PROP_PAR_RemoveDir" value="True" time="0"/>
|
<Property name="PROP_PAR_RemoveDir" value="True" time="0"/>
|
||||||
|
@ -9,6 +9,7 @@ module mcu_top (
|
|||||||
sd_scb.controller sd_scb,
|
sd_scb.controller sd_scb,
|
||||||
dma_scb.controller sd_dma_scb,
|
dma_scb.controller sd_dma_scb,
|
||||||
flash_scb.controller flash_scb,
|
flash_scb.controller flash_scb,
|
||||||
|
vendor_scb.controller vendor_scb,
|
||||||
|
|
||||||
fifo_bus.controller fifo_bus,
|
fifo_bus.controller fifo_bus,
|
||||||
mem_bus.controller mem_bus,
|
mem_bus.controller mem_bus,
|
||||||
@ -353,7 +354,9 @@ module mcu_top (
|
|||||||
REG_DD_CMD_DATA,
|
REG_DD_CMD_DATA,
|
||||||
REG_DD_HEAD_TRACK,
|
REG_DD_HEAD_TRACK,
|
||||||
REG_DD_SECTOR_INFO,
|
REG_DD_SECTOR_INFO,
|
||||||
REG_DD_DRIVE_ID
|
REG_DD_DRIVE_ID,
|
||||||
|
REG_VENDOR_SCR,
|
||||||
|
REG_VENDOR_DATA
|
||||||
} reg_address_e;
|
} reg_address_e;
|
||||||
|
|
||||||
logic bootloader_skip;
|
logic bootloader_skip;
|
||||||
@ -579,6 +582,14 @@ module mcu_top (
|
|||||||
dd_scb.sector_num
|
dd_scb.sector_num
|
||||||
};
|
};
|
||||||
end
|
end
|
||||||
|
|
||||||
|
REG_VENDOR_SCR: begin
|
||||||
|
reg_rdata <= vendor_scb.control_rdata;
|
||||||
|
end
|
||||||
|
|
||||||
|
REG_VENDOR_DATA: begin
|
||||||
|
reg_rdata <= vendor_scb.data_rdata;
|
||||||
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -614,6 +625,8 @@ module mcu_top (
|
|||||||
dd_scb.bm_clear <= 1'b0;
|
dd_scb.bm_clear <= 1'b0;
|
||||||
dd_scb.bm_ready <= 1'b0;
|
dd_scb.bm_ready <= 1'b0;
|
||||||
|
|
||||||
|
vendor_scb.control_valid <= 1'b0;
|
||||||
|
|
||||||
if (n64_scb.n64_nmi) begin
|
if (n64_scb.n64_nmi) begin
|
||||||
n64_scb.bootloader_enabled <= !bootloader_skip;
|
n64_scb.bootloader_enabled <= !bootloader_skip;
|
||||||
end
|
end
|
||||||
@ -792,6 +805,15 @@ module mcu_top (
|
|||||||
REG_DD_DRIVE_ID: begin
|
REG_DD_DRIVE_ID: begin
|
||||||
dd_scb.drive_id <= reg_wdata[15:0];
|
dd_scb.drive_id <= reg_wdata[15:0];
|
||||||
end
|
end
|
||||||
|
|
||||||
|
REG_VENDOR_SCR: begin
|
||||||
|
vendor_scb.control_valid <= 1'b1;
|
||||||
|
vendor_scb.control_wdata <= reg_wdata;
|
||||||
|
end
|
||||||
|
|
||||||
|
REG_VENDOR_DATA: begin
|
||||||
|
vendor_scb.data_wdata <= reg_wdata;
|
||||||
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -58,6 +58,7 @@ module top (
|
|||||||
sd_scb sd_scb ();
|
sd_scb sd_scb ();
|
||||||
dma_scb sd_dma_scb ();
|
dma_scb sd_dma_scb ();
|
||||||
flash_scb flash_scb ();
|
flash_scb flash_scb ();
|
||||||
|
vendor_scb vendor_scb ();
|
||||||
|
|
||||||
fifo_bus usb_cfg_fifo_bus ();
|
fifo_bus usb_cfg_fifo_bus ();
|
||||||
fifo_bus usb_dma_fifo_bus ();
|
fifo_bus usb_dma_fifo_bus ();
|
||||||
@ -93,6 +94,7 @@ module top (
|
|||||||
.sd_scb(sd_scb),
|
.sd_scb(sd_scb),
|
||||||
.sd_dma_scb(sd_dma_scb),
|
.sd_dma_scb(sd_dma_scb),
|
||||||
.flash_scb(flash_scb),
|
.flash_scb(flash_scb),
|
||||||
|
.vendor_scb(vendor_scb),
|
||||||
|
|
||||||
.fifo_bus(usb_cfg_fifo_bus),
|
.fifo_bus(usb_cfg_fifo_bus),
|
||||||
.mem_bus(cfg_mem_bus),
|
.mem_bus(cfg_mem_bus),
|
||||||
@ -250,4 +252,14 @@ module top (
|
|||||||
.mem_bus(bram_mem_bus)
|
.mem_bus(bram_mem_bus)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Vendor specific control
|
||||||
|
|
||||||
|
vendor vendor_inst (
|
||||||
|
.clk(clk),
|
||||||
|
.reset(reset),
|
||||||
|
|
||||||
|
.vendor_scb(vendor_scb)
|
||||||
|
);
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
113
fw/rtl/vendor/lcmxo2/generated/efb_lattice_generated.v
vendored
Normal file
113
fw/rtl/vendor/lcmxo2/generated/efb_lattice_generated.v
vendored
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
/* Verilog netlist generated by SCUBA Diamond (64-bit) 3.12.1.454 */
|
||||||
|
/* Module Version: 1.2 */
|
||||||
|
/* C:\lscc\diamond\3.12\ispfpga\bin\nt64\scuba.exe -w -n efb_lattice_generated -lang verilog -synth synplify -bus_exp 7 -bb -type efb -arch xo2c00 -freq 100 -ufm -ufm_ebr 2038 -mem_size 8 -ufm_0 -wb -dev 7000 */
|
||||||
|
/* Sun Jul 31 17:59:17 2022 */
|
||||||
|
|
||||||
|
|
||||||
|
`timescale 1 ns / 1 ps
|
||||||
|
module efb_lattice_generated (wb_clk_i, wb_rst_i, wb_cyc_i, wb_stb_i,
|
||||||
|
wb_we_i, wb_adr_i, wb_dat_i, wb_dat_o, wb_ack_o, wbc_ufm_irq)/* synthesis NGD_DRC_MASK=1 */;
|
||||||
|
input wire wb_clk_i;
|
||||||
|
input wire wb_rst_i;
|
||||||
|
input wire wb_cyc_i;
|
||||||
|
input wire wb_stb_i;
|
||||||
|
input wire wb_we_i;
|
||||||
|
input wire [7:0] wb_adr_i;
|
||||||
|
input wire [7:0] wb_dat_i;
|
||||||
|
output wire [7:0] wb_dat_o;
|
||||||
|
output wire wb_ack_o;
|
||||||
|
output wire wbc_ufm_irq;
|
||||||
|
|
||||||
|
wire scuba_vhi;
|
||||||
|
wire scuba_vlo;
|
||||||
|
|
||||||
|
VHI scuba_vhi_inst (.Z(scuba_vhi));
|
||||||
|
|
||||||
|
VLO scuba_vlo_inst (.Z(scuba_vlo));
|
||||||
|
|
||||||
|
defparam EFBInst_0.UFM_INIT_FILE_FORMAT = "HEX" ;
|
||||||
|
defparam EFBInst_0.UFM_INIT_FILE_NAME = "NONE" ;
|
||||||
|
defparam EFBInst_0.UFM_INIT_ALL_ZEROS = "ENABLED" ;
|
||||||
|
defparam EFBInst_0.UFM_INIT_START_PAGE = 2038 ;
|
||||||
|
defparam EFBInst_0.UFM_INIT_PAGES = 8 ;
|
||||||
|
defparam EFBInst_0.DEV_DENSITY = "7000L" ;
|
||||||
|
defparam EFBInst_0.EFB_UFM = "ENABLED" ;
|
||||||
|
defparam EFBInst_0.TC_ICAPTURE = "DISABLED" ;
|
||||||
|
defparam EFBInst_0.TC_OVERFLOW = "DISABLED" ;
|
||||||
|
defparam EFBInst_0.TC_ICR_INT = "OFF" ;
|
||||||
|
defparam EFBInst_0.TC_OCR_INT = "OFF" ;
|
||||||
|
defparam EFBInst_0.TC_OV_INT = "OFF" ;
|
||||||
|
defparam EFBInst_0.TC_TOP_SEL = "OFF" ;
|
||||||
|
defparam EFBInst_0.TC_RESETN = "ENABLED" ;
|
||||||
|
defparam EFBInst_0.TC_OC_MODE = "TOGGLE" ;
|
||||||
|
defparam EFBInst_0.TC_OCR_SET = 32767 ;
|
||||||
|
defparam EFBInst_0.TC_TOP_SET = 65535 ;
|
||||||
|
defparam EFBInst_0.GSR = "ENABLED" ;
|
||||||
|
defparam EFBInst_0.TC_CCLK_SEL = 1 ;
|
||||||
|
defparam EFBInst_0.TC_MODE = "CTCM" ;
|
||||||
|
defparam EFBInst_0.TC_SCLK_SEL = "PCLOCK" ;
|
||||||
|
defparam EFBInst_0.EFB_TC_PORTMODE = "WB" ;
|
||||||
|
defparam EFBInst_0.EFB_TC = "DISABLED" ;
|
||||||
|
defparam EFBInst_0.SPI_WAKEUP = "DISABLED" ;
|
||||||
|
defparam EFBInst_0.SPI_INTR_RXOVR = "DISABLED" ;
|
||||||
|
defparam EFBInst_0.SPI_INTR_TXOVR = "DISABLED" ;
|
||||||
|
defparam EFBInst_0.SPI_INTR_RXRDY = "DISABLED" ;
|
||||||
|
defparam EFBInst_0.SPI_INTR_TXRDY = "DISABLED" ;
|
||||||
|
defparam EFBInst_0.SPI_SLAVE_HANDSHAKE = "DISABLED" ;
|
||||||
|
defparam EFBInst_0.SPI_PHASE_ADJ = "DISABLED" ;
|
||||||
|
defparam EFBInst_0.SPI_CLK_INV = "DISABLED" ;
|
||||||
|
defparam EFBInst_0.SPI_LSB_FIRST = "DISABLED" ;
|
||||||
|
defparam EFBInst_0.SPI_CLK_DIVIDER = 2 ;
|
||||||
|
defparam EFBInst_0.SPI_MODE = "MASTER" ;
|
||||||
|
defparam EFBInst_0.EFB_SPI = "DISABLED" ;
|
||||||
|
defparam EFBInst_0.I2C2_WAKEUP = "DISABLED" ;
|
||||||
|
defparam EFBInst_0.I2C2_GEN_CALL = "DISABLED" ;
|
||||||
|
defparam EFBInst_0.I2C2_CLK_DIVIDER = 1 ;
|
||||||
|
defparam EFBInst_0.I2C2_BUS_PERF = "100kHz" ;
|
||||||
|
defparam EFBInst_0.I2C2_SLAVE_ADDR = "0b1000010" ;
|
||||||
|
defparam EFBInst_0.I2C2_ADDRESSING = "7BIT" ;
|
||||||
|
defparam EFBInst_0.EFB_I2C2 = "DISABLED" ;
|
||||||
|
defparam EFBInst_0.I2C1_WAKEUP = "DISABLED" ;
|
||||||
|
defparam EFBInst_0.I2C1_GEN_CALL = "DISABLED" ;
|
||||||
|
defparam EFBInst_0.I2C1_CLK_DIVIDER = 1 ;
|
||||||
|
defparam EFBInst_0.I2C1_BUS_PERF = "100kHz" ;
|
||||||
|
defparam EFBInst_0.I2C1_SLAVE_ADDR = "0b1000001" ;
|
||||||
|
defparam EFBInst_0.I2C1_ADDRESSING = "7BIT" ;
|
||||||
|
defparam EFBInst_0.EFB_I2C1 = "DISABLED" ;
|
||||||
|
defparam EFBInst_0.EFB_WB_CLK_FREQ = "100.0" ;
|
||||||
|
EFB EFBInst_0 (.WBCLKI(wb_clk_i), .WBRSTI(wb_rst_i), .WBCYCI(wb_cyc_i),
|
||||||
|
.WBSTBI(wb_stb_i), .WBWEI(wb_we_i), .WBADRI7(wb_adr_i[7]), .WBADRI6(wb_adr_i[6]),
|
||||||
|
.WBADRI5(wb_adr_i[5]), .WBADRI4(wb_adr_i[4]), .WBADRI3(wb_adr_i[3]),
|
||||||
|
.WBADRI2(wb_adr_i[2]), .WBADRI1(wb_adr_i[1]), .WBADRI0(wb_adr_i[0]),
|
||||||
|
.WBDATI7(wb_dat_i[7]), .WBDATI6(wb_dat_i[6]), .WBDATI5(wb_dat_i[5]),
|
||||||
|
.WBDATI4(wb_dat_i[4]), .WBDATI3(wb_dat_i[3]), .WBDATI2(wb_dat_i[2]),
|
||||||
|
.WBDATI1(wb_dat_i[1]), .WBDATI0(wb_dat_i[0]), .PLL0DATI7(scuba_vlo),
|
||||||
|
.PLL0DATI6(scuba_vlo), .PLL0DATI5(scuba_vlo), .PLL0DATI4(scuba_vlo),
|
||||||
|
.PLL0DATI3(scuba_vlo), .PLL0DATI2(scuba_vlo), .PLL0DATI1(scuba_vlo),
|
||||||
|
.PLL0DATI0(scuba_vlo), .PLL0ACKI(scuba_vlo), .PLL1DATI7(scuba_vlo),
|
||||||
|
.PLL1DATI6(scuba_vlo), .PLL1DATI5(scuba_vlo), .PLL1DATI4(scuba_vlo),
|
||||||
|
.PLL1DATI3(scuba_vlo), .PLL1DATI2(scuba_vlo), .PLL1DATI1(scuba_vlo),
|
||||||
|
.PLL1DATI0(scuba_vlo), .PLL1ACKI(scuba_vlo), .I2C1SCLI(scuba_vlo),
|
||||||
|
.I2C1SDAI(scuba_vlo), .I2C2SCLI(scuba_vlo), .I2C2SDAI(scuba_vlo),
|
||||||
|
.SPISCKI(scuba_vlo), .SPIMISOI(scuba_vlo), .SPIMOSII(scuba_vlo),
|
||||||
|
.SPISCSN(scuba_vlo), .TCCLKI(scuba_vlo), .TCRSTN(scuba_vlo), .TCIC(scuba_vlo),
|
||||||
|
.UFMSN(scuba_vhi), .WBDATO7(wb_dat_o[7]), .WBDATO6(wb_dat_o[6]),
|
||||||
|
.WBDATO5(wb_dat_o[5]), .WBDATO4(wb_dat_o[4]), .WBDATO3(wb_dat_o[3]),
|
||||||
|
.WBDATO2(wb_dat_o[2]), .WBDATO1(wb_dat_o[1]), .WBDATO0(wb_dat_o[0]),
|
||||||
|
.WBACKO(wb_ack_o), .PLLCLKO(), .PLLRSTO(), .PLL0STBO(), .PLL1STBO(),
|
||||||
|
.PLLWEO(), .PLLADRO4(), .PLLADRO3(), .PLLADRO2(), .PLLADRO1(), .PLLADRO0(),
|
||||||
|
.PLLDATO7(), .PLLDATO6(), .PLLDATO5(), .PLLDATO4(), .PLLDATO3(),
|
||||||
|
.PLLDATO2(), .PLLDATO1(), .PLLDATO0(), .I2C1SCLO(), .I2C1SCLOEN(),
|
||||||
|
.I2C1SDAO(), .I2C1SDAOEN(), .I2C2SCLO(), .I2C2SCLOEN(), .I2C2SDAO(),
|
||||||
|
.I2C2SDAOEN(), .I2C1IRQO(), .I2C2IRQO(), .SPISCKO(), .SPISCKEN(),
|
||||||
|
.SPIMISOO(), .SPIMISOEN(), .SPIMOSIO(), .SPIMOSIEN(), .SPIMCSN7(),
|
||||||
|
.SPIMCSN6(), .SPIMCSN5(), .SPIMCSN4(), .SPIMCSN3(), .SPIMCSN2(),
|
||||||
|
.SPIMCSN1(), .SPIMCSN0(), .SPICSNEN(), .SPIIRQO(), .TCINT(), .TCOC(),
|
||||||
|
.WBCUFMIRQ(wbc_ufm_irq), .CFGWAKE(), .CFGSTDBY());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// exemplar begin
|
||||||
|
// exemplar end
|
||||||
|
|
||||||
|
endmodule
|
127
fw/rtl/vendor/lcmxo2/vendor.sv
vendored
Normal file
127
fw/rtl/vendor/lcmxo2/vendor.sv
vendored
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
module vendor (
|
||||||
|
input clk,
|
||||||
|
input reset,
|
||||||
|
|
||||||
|
vendor_scb.vendor vendor_scb
|
||||||
|
);
|
||||||
|
|
||||||
|
logic start;
|
||||||
|
logic busy;
|
||||||
|
logic [1:0] length;
|
||||||
|
logic [5:0] delay;
|
||||||
|
|
||||||
|
logic request;
|
||||||
|
logic write;
|
||||||
|
logic ack;
|
||||||
|
logic [7:0] address;
|
||||||
|
logic [7:0] rdata;
|
||||||
|
logic [7:0] wdata;
|
||||||
|
|
||||||
|
logic [23:0] wdata_buffer;
|
||||||
|
|
||||||
|
logic ufm_irq;
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
start = vendor_scb.control_valid && vendor_scb.control_wdata[0] && !busy;
|
||||||
|
vendor_scb.control_rdata = {
|
||||||
|
16'd0,
|
||||||
|
address,
|
||||||
|
4'b0000,
|
||||||
|
length,
|
||||||
|
write,
|
||||||
|
busy
|
||||||
|
};
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (reset) begin
|
||||||
|
busy <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
if (start) begin
|
||||||
|
busy <= 1'b1;
|
||||||
|
end
|
||||||
|
if (length == 2'd0 && ack) begin
|
||||||
|
busy <= 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (start) begin
|
||||||
|
length <= vendor_scb.control_wdata[3:2];
|
||||||
|
end
|
||||||
|
if (ack && length > 2'd0) begin
|
||||||
|
length <= length - 1'd1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (reset) begin
|
||||||
|
delay <= 6'd0;
|
||||||
|
end else begin
|
||||||
|
if (start && vendor_scb.control_wdata[4]) begin
|
||||||
|
delay <= 6'd35;
|
||||||
|
end
|
||||||
|
if (delay > 6'd0) begin
|
||||||
|
delay <= delay - 1'd1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (reset) begin
|
||||||
|
request <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
if (start) begin
|
||||||
|
request <= 1'b1;
|
||||||
|
end
|
||||||
|
if (busy && !request && delay == 6'd0) begin
|
||||||
|
request <= 1'b1;
|
||||||
|
end
|
||||||
|
if (ack) begin
|
||||||
|
request <= 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (start) begin
|
||||||
|
write <= vendor_scb.control_wdata[1];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (start) begin
|
||||||
|
address <= vendor_scb.control_wdata[15:8];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (ack) begin
|
||||||
|
vendor_scb.data_rdata <= {vendor_scb.data_rdata[23:0], rdata};
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (start) begin
|
||||||
|
{wdata, wdata_buffer} <= vendor_scb.data_wdata;
|
||||||
|
end
|
||||||
|
if (ack) begin
|
||||||
|
{wdata, wdata_buffer} <= {wdata_buffer, 8'h00};
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
efb_lattice_generated efb_lattice_generated_inst (
|
||||||
|
.wb_clk_i(clk),
|
||||||
|
.wb_rst_i(reset),
|
||||||
|
.wb_cyc_i(request),
|
||||||
|
.wb_stb_i(request),
|
||||||
|
.wb_we_i(write),
|
||||||
|
.wb_adr_i(address),
|
||||||
|
.wb_dat_i(wdata),
|
||||||
|
.wb_dat_o(rdata),
|
||||||
|
.wb_ack_o(ack),
|
||||||
|
.wbc_ufm_irq(ufm_irq)
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule
|
25
fw/rtl/vendor/vendor_scb.sv
vendored
Normal file
25
fw/rtl/vendor/vendor_scb.sv
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
interface vendor_scb ();
|
||||||
|
|
||||||
|
logic control_valid;
|
||||||
|
logic [31:0] control_rdata;
|
||||||
|
logic [31:0] control_wdata;
|
||||||
|
logic [31:0] data_rdata;
|
||||||
|
logic [31:0] data_wdata;
|
||||||
|
|
||||||
|
modport controller (
|
||||||
|
output control_valid,
|
||||||
|
input control_rdata,
|
||||||
|
output control_wdata,
|
||||||
|
input data_rdata,
|
||||||
|
output data_wdata
|
||||||
|
);
|
||||||
|
|
||||||
|
modport vendor (
|
||||||
|
input control_valid,
|
||||||
|
output control_rdata,
|
||||||
|
input control_wdata,
|
||||||
|
output data_rdata,
|
||||||
|
input data_wdata
|
||||||
|
);
|
||||||
|
|
||||||
|
endinterface
|
@ -93,7 +93,7 @@ bool sc64_usb_write_ready (void) {
|
|||||||
return result[0];
|
return result[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void sc64_usb_write (uint32_t *address, uint32_t length) {
|
bool sc64_usb_write (uint32_t *address, uint32_t length) {
|
||||||
while (!sc64_usb_write_ready());
|
while (!sc64_usb_write_ready());
|
||||||
uint32_t args[2] = { (uint32_t) (address), length };
|
uint32_t args[2] = { (uint32_t) (address), length };
|
||||||
return sc64_execute_cmd(SC64_CMD_USB_WRITE, args, NULL);
|
return sc64_execute_cmd(SC64_CMD_USB_WRITE, args, NULL);
|
||||||
|
@ -24,6 +24,7 @@ SRC_FILES = \
|
|||||||
gvr.c \
|
gvr.c \
|
||||||
hw.c \
|
hw.c \
|
||||||
isv.c \
|
isv.c \
|
||||||
|
lcmxo2.c \
|
||||||
main.c \
|
main.c \
|
||||||
rtc.c \
|
rtc.c \
|
||||||
task.c \
|
task.c \
|
||||||
|
@ -50,7 +50,9 @@ typedef enum {
|
|||||||
REG_DD_CMD_DATA,
|
REG_DD_CMD_DATA,
|
||||||
REG_DD_HEAD_TRACK,
|
REG_DD_HEAD_TRACK,
|
||||||
REG_DD_SECTOR_INFO,
|
REG_DD_SECTOR_INFO,
|
||||||
REG_DD_DRIVE_ID
|
REG_DD_DRIVE_ID,
|
||||||
|
REG_VENDOR_SCR,
|
||||||
|
REG_VENDOR_DATA
|
||||||
} fpga_reg_t;
|
} fpga_reg_t;
|
||||||
|
|
||||||
|
|
||||||
|
232
sw/controller/src/lcmxo2.c
Normal file
232
sw/controller/src/lcmxo2.c
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
#include "fpga.h"
|
||||||
|
#include "vendor.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define VENDOR_SCR_START (1 << 0)
|
||||||
|
#define VENDOR_SCR_BUSY (1 << 0)
|
||||||
|
#define VENDOR_SCR_WRITE (1 << 1)
|
||||||
|
#define VENDOR_SCR_LENGTH_BIT (2)
|
||||||
|
#define VENDOR_SCR_DELAY (1 << 4)
|
||||||
|
#define VENDOR_SCR_ADDRESS_BIT (8)
|
||||||
|
|
||||||
|
#define LCMXO2_CFGCR (0x70)
|
||||||
|
#define LCMXO2_CFGTXDR (0x71)
|
||||||
|
#define LCMXO2_CFGRXDR (0x73)
|
||||||
|
|
||||||
|
#define CFGCR_RSTE (1 << 6)
|
||||||
|
#define CFGCR_WBCE (1 << 7)
|
||||||
|
|
||||||
|
#define ISC_ERASE (0x0E)
|
||||||
|
#define ISC_DISABLE (0x26)
|
||||||
|
#define LSC_READ_STATUS (0x3C)
|
||||||
|
#define LSC_INIT_ADDRESS (0x46)
|
||||||
|
#define ISC_PROGRAM_DONE (0x5E)
|
||||||
|
#define LSC_PROG_INCR_NV (0x70)
|
||||||
|
#define LSC_READ_INCR_NV (0x73)
|
||||||
|
#define ISC_ENABLE_X (0x74)
|
||||||
|
#define LSC_REFRESH (0x79)
|
||||||
|
#define ISC_NOOP (0xFF)
|
||||||
|
|
||||||
|
#define ISC_ERASE_CFG (1 << 18)
|
||||||
|
#define ISC_ERASE_UFM (1 << 19)
|
||||||
|
|
||||||
|
#define LSC_STATUS_1_BUSY (1 << 4)
|
||||||
|
#define LSC_STATUS_1_FAIL (1 << 5)
|
||||||
|
|
||||||
|
#define FLASH_PAGE_SIZE (16)
|
||||||
|
#define FLASH_NUM_PAGES (11260)
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CMD_NORMAL,
|
||||||
|
CMD_DELAYED,
|
||||||
|
CMD_TWO_OP,
|
||||||
|
} cmd_type_t;
|
||||||
|
|
||||||
|
|
||||||
|
static void lcmxo2_reg_set (uint8_t reg, uint8_t value) {
|
||||||
|
fpga_reg_set(REG_VENDOR_DATA, value << 24);
|
||||||
|
fpga_reg_set(REG_VENDOR_SCR,
|
||||||
|
(reg << VENDOR_SCR_ADDRESS_BIT) |
|
||||||
|
(0 << VENDOR_SCR_LENGTH_BIT) |
|
||||||
|
VENDOR_SCR_WRITE |
|
||||||
|
VENDOR_SCR_START
|
||||||
|
);
|
||||||
|
while (fpga_reg_get(REG_VENDOR_SCR) & VENDOR_SCR_BUSY);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t lcmxo2_reg_get (uint8_t reg) {
|
||||||
|
fpga_reg_set(REG_VENDOR_SCR,
|
||||||
|
(reg << VENDOR_SCR_ADDRESS_BIT) |
|
||||||
|
(0 << VENDOR_SCR_LENGTH_BIT) |
|
||||||
|
VENDOR_SCR_START
|
||||||
|
);
|
||||||
|
while (fpga_reg_get(REG_VENDOR_SCR) & VENDOR_SCR_BUSY);
|
||||||
|
return fpga_reg_get(REG_VENDOR_DATA) & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lcmxo2_reset_bus (void) {
|
||||||
|
lcmxo2_reg_set(LCMXO2_CFGCR, CFGCR_RSTE);
|
||||||
|
lcmxo2_reg_set(LCMXO2_CFGCR, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lcmxo2_execute_cmd (uint8_t cmd, uint32_t arg, cmd_type_t type) {
|
||||||
|
lcmxo2_reg_set(LCMXO2_CFGCR, 0);
|
||||||
|
uint32_t data = (cmd << 24) | (arg & 0x00FFFFFF);
|
||||||
|
lcmxo2_reg_set(LCMXO2_CFGCR, CFGCR_WBCE);
|
||||||
|
fpga_reg_set(REG_VENDOR_DATA, data);
|
||||||
|
fpga_reg_set(REG_VENDOR_SCR,
|
||||||
|
(LCMXO2_CFGTXDR << VENDOR_SCR_ADDRESS_BIT) |
|
||||||
|
(type == CMD_DELAYED ? VENDOR_SCR_DELAY : 0) |
|
||||||
|
((type == CMD_TWO_OP ? 2 : 3) << VENDOR_SCR_LENGTH_BIT) |
|
||||||
|
VENDOR_SCR_WRITE |
|
||||||
|
VENDOR_SCR_START
|
||||||
|
);
|
||||||
|
while (fpga_reg_get(REG_VENDOR_SCR) & VENDOR_SCR_BUSY);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lcmxo2_cleanup (void) {
|
||||||
|
lcmxo2_reg_set(LCMXO2_CFGCR, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lcmxo2_read_data (uint8_t *buffer, uint32_t length) {
|
||||||
|
for (uint32_t i = 0; i < length; i++) {
|
||||||
|
*buffer++ = lcmxo2_reg_get(LCMXO2_CFGRXDR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lcmxo2_write_data (uint8_t *buffer, uint32_t length) {
|
||||||
|
for (uint32_t i = 0; i < length; i++) {
|
||||||
|
lcmxo2_reg_set(LCMXO2_CFGTXDR, *buffer++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool lcmxo2_wait_busy (void) {
|
||||||
|
uint8_t status[4];
|
||||||
|
do {
|
||||||
|
lcmxo2_execute_cmd(LSC_READ_STATUS, 0, CMD_NORMAL);
|
||||||
|
lcmxo2_read_data(status, 4);
|
||||||
|
} while(status[2] & LSC_STATUS_1_BUSY);
|
||||||
|
return status[2] & LSC_STATUS_1_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool lcmxo2_enable_flash (void) {
|
||||||
|
lcmxo2_execute_cmd(ISC_ENABLE_X, 0x080000, CMD_NORMAL);
|
||||||
|
return lcmxo2_wait_busy();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lcmxo2_disable_flash (void) {
|
||||||
|
lcmxo2_wait_busy();
|
||||||
|
lcmxo2_execute_cmd(ISC_DISABLE, 0, CMD_TWO_OP);
|
||||||
|
lcmxo2_execute_cmd(ISC_NOOP, 0xFFFFFF, CMD_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool lcmxo2_erase_flash (void) {
|
||||||
|
lcmxo2_execute_cmd(ISC_ERASE, ISC_ERASE_UFM | ISC_ERASE_CFG, CMD_NORMAL);
|
||||||
|
return lcmxo2_wait_busy();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lcmxo2_reset_flash_address (void) {
|
||||||
|
lcmxo2_execute_cmd(LSC_INIT_ADDRESS, 0, CMD_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool lcmxo2_write_flash_page (uint8_t *buffer) {
|
||||||
|
lcmxo2_execute_cmd(LSC_PROG_INCR_NV, 1, CMD_NORMAL);
|
||||||
|
lcmxo2_write_data(buffer, FLASH_PAGE_SIZE);
|
||||||
|
return lcmxo2_wait_busy();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lcmxo2_read_flash_page (uint8_t *buffer) {
|
||||||
|
lcmxo2_execute_cmd(LSC_READ_INCR_NV, 1, CMD_DELAYED);
|
||||||
|
lcmxo2_read_data(buffer, FLASH_PAGE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lcmxo2_program_done (void) {
|
||||||
|
lcmxo2_execute_cmd(ISC_PROGRAM_DONE, 0, CMD_NORMAL);
|
||||||
|
lcmxo2_wait_busy();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lcmxo2_refresh (void) {
|
||||||
|
lcmxo2_execute_cmd(LSC_REFRESH, 0, CMD_TWO_OP);
|
||||||
|
}
|
||||||
|
|
||||||
|
static vendor_error_t lcmxo2_fail (vendor_error_t error) {
|
||||||
|
lcmxo2_disable_flash();
|
||||||
|
lcmxo2_cleanup();
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
vendor_error_t vendor_update (uint32_t address, uint32_t length) {
|
||||||
|
uint8_t buffer[FLASH_PAGE_SIZE];
|
||||||
|
uint8_t verify_buffer[FLASH_PAGE_SIZE];
|
||||||
|
|
||||||
|
if (length == 0) {
|
||||||
|
return VENDOR_ERROR_ARGS;
|
||||||
|
}
|
||||||
|
if ((length % FLASH_PAGE_SIZE) != 0) {
|
||||||
|
return VENDOR_ERROR_ARGS;
|
||||||
|
}
|
||||||
|
if (length > (FLASH_PAGE_SIZE * FLASH_NUM_PAGES)) {
|
||||||
|
return VENDOR_ERROR_ARGS;
|
||||||
|
}
|
||||||
|
|
||||||
|
lcmxo2_reset_bus();
|
||||||
|
if (lcmxo2_enable_flash()) {
|
||||||
|
return lcmxo2_fail(VENDOR_ERROR_INIT);
|
||||||
|
}
|
||||||
|
if (lcmxo2_erase_flash()) {
|
||||||
|
return lcmxo2_fail(VENDOR_ERROR_ERASE);
|
||||||
|
}
|
||||||
|
lcmxo2_reset_flash_address();
|
||||||
|
for (int i = 0; i < length; i += FLASH_PAGE_SIZE) {
|
||||||
|
fpga_mem_read(address + i, FLASH_PAGE_SIZE, buffer);
|
||||||
|
if (lcmxo2_write_flash_page(buffer)) {
|
||||||
|
return lcmxo2_fail(VENDOR_ERROR_PROGRAM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lcmxo2_program_done();
|
||||||
|
lcmxo2_reset_flash_address();
|
||||||
|
for (int i = 0; i < length; i += FLASH_PAGE_SIZE) {
|
||||||
|
lcmxo2_read_flash_page(buffer);
|
||||||
|
fpga_mem_read(address + i, FLASH_PAGE_SIZE, verify_buffer);
|
||||||
|
for (int x = 0; x < FLASH_PAGE_SIZE; x++) {
|
||||||
|
if (buffer[x] != verify_buffer[x]) {
|
||||||
|
return lcmxo2_fail(VENDOR_ERROR_VERIFY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lcmxo2_disable_flash();
|
||||||
|
lcmxo2_cleanup();
|
||||||
|
|
||||||
|
return VENDOR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
vendor_error_t vendor_backup (uint32_t address, uint32_t *length) {
|
||||||
|
uint8_t buffer[FLASH_PAGE_SIZE];
|
||||||
|
|
||||||
|
*length = 0;
|
||||||
|
|
||||||
|
lcmxo2_reset_bus();
|
||||||
|
if (lcmxo2_enable_flash()) {
|
||||||
|
return lcmxo2_fail(VENDOR_ERROR_INIT);
|
||||||
|
}
|
||||||
|
lcmxo2_reset_flash_address();
|
||||||
|
for (int i = 0; i < (FLASH_PAGE_SIZE * FLASH_NUM_PAGES); i += FLASH_PAGE_SIZE) {
|
||||||
|
lcmxo2_read_flash_page(buffer);
|
||||||
|
fpga_mem_write(address + i, FLASH_PAGE_SIZE, buffer);
|
||||||
|
*length += FLASH_PAGE_SIZE;
|
||||||
|
}
|
||||||
|
lcmxo2_disable_flash();
|
||||||
|
lcmxo2_cleanup();
|
||||||
|
|
||||||
|
return VENDOR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
vendor_error_t vendor_reconfigure (void) {
|
||||||
|
lcmxo2_reset_bus();
|
||||||
|
lcmxo2_refresh();
|
||||||
|
lcmxo2_cleanup();
|
||||||
|
|
||||||
|
return VENDOR_OK;
|
||||||
|
}
|
@ -1,12 +1,13 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "cfg.h"
|
||||||
#include "cic.h"
|
#include "cic.h"
|
||||||
#include "dd.h"
|
#include "dd.h"
|
||||||
#include "cfg.h"
|
#include "flash.h"
|
||||||
#include "fpga.h"
|
#include "fpga.h"
|
||||||
#include "rtc.h"
|
#include "rtc.h"
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
#include "flash.h"
|
#include "vendor.h"
|
||||||
|
|
||||||
|
|
||||||
enum rx_state {
|
enum rx_state {
|
||||||
@ -249,12 +250,33 @@ static void usb_rx_process (void) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'f':
|
||||||
|
p.response_info.data[0] = vendor_backup(p.rx_args[0], &p.response_info.data[1]);
|
||||||
|
p.rx_state = RX_STATE_IDLE;
|
||||||
|
p.response_pending = true;
|
||||||
|
p.response_info.data_length = 8;
|
||||||
|
if (p.response_info.data[0] != VENDOR_OK) {
|
||||||
|
p.response_error = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'F':
|
||||||
|
p.response_info.data[0] = vendor_update(p.rx_args[0], p.rx_args[1]);
|
||||||
|
p.rx_state = RX_STATE_IDLE;
|
||||||
|
p.response_pending = true;
|
||||||
|
p.response_info.data_length = 4;
|
||||||
|
if (p.response_info.data[0] != VENDOR_OK) {
|
||||||
|
p.response_error = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
p.rx_state = RX_STATE_IDLE;
|
p.rx_state = RX_STATE_IDLE;
|
||||||
p.response_pending = true;
|
p.response_pending = true;
|
||||||
p.response_error = true;
|
p.response_error = true;
|
||||||
p.response_info.data_length = 4;
|
p.response_info.data_length = 4;
|
||||||
p.response_info.data[0] = 0xFF;
|
p.response_info.data[0] = 0xFF;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
23
sw/controller/src/vendor.h
Normal file
23
sw/controller/src/vendor.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#ifndef VENDOR_H__
|
||||||
|
#define VENDOR_H__
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
VENDOR_OK,
|
||||||
|
VENDOR_ERROR_ARGS,
|
||||||
|
VENDOR_ERROR_INIT,
|
||||||
|
VENDOR_ERROR_ERASE,
|
||||||
|
VENDOR_ERROR_PROGRAM,
|
||||||
|
VENDOR_ERROR_VERIFY,
|
||||||
|
} vendor_error_t;
|
||||||
|
|
||||||
|
|
||||||
|
vendor_error_t vendor_update (uint32_t address, uint32_t length);
|
||||||
|
vendor_error_t vendor_backup (uint32_t address, uint32_t *length);
|
||||||
|
vendor_error_t vendor_reconfigure (void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user