mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-25 15:16:53 +01:00
better
This commit is contained in:
parent
430ecf3e69
commit
90b211c179
@ -55,6 +55,7 @@ set_global_assignment -name SIGNALTAP_FILE stp.stp
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE btldr/btldr.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE picorv32/picorv32.v
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_bus.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_dma.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_gpio.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_i2c.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_ram.sv
|
||||
@ -64,6 +65,7 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_usb.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_wrapper.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/memory/memory_flash.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/memory/memory_sdram.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bootloader.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bus.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_pi.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_sdram.sv
|
||||
|
28
fw/rtl/cpu/cpu_dma.sv
Normal file
28
fw/rtl/cpu/cpu_dma.sv
Normal file
@ -0,0 +1,28 @@
|
||||
interface if_dma ();
|
||||
|
||||
logic request;
|
||||
logic ack;
|
||||
logic write;
|
||||
logic [31:0] address;
|
||||
logic [15:0] rdata;
|
||||
logic [15:0] wdata;
|
||||
|
||||
modport cpu (
|
||||
output request,
|
||||
input ack,
|
||||
output write,
|
||||
output address,
|
||||
input rdata,
|
||||
output wdata
|
||||
);
|
||||
|
||||
modport memory (
|
||||
input request,
|
||||
output ack,
|
||||
input write,
|
||||
input address,
|
||||
output rdata,
|
||||
input wdata
|
||||
);
|
||||
|
||||
endinterface
|
@ -1,7 +1,7 @@
|
||||
module cpu_soc (
|
||||
if_system.sys sys,
|
||||
if_config cfg,
|
||||
if_dma.cpu dma,
|
||||
if_dma dma,
|
||||
|
||||
input [7:0] gpio_i,
|
||||
output [7:0] gpio_o,
|
||||
|
@ -8,7 +8,7 @@ module cpu_uart (
|
||||
output uart_rts
|
||||
);
|
||||
|
||||
localparam BAUD_GEN_VALUE = int'(100_000_000 / sc64::UART_BAUD_RATE) - 1'd1;
|
||||
localparam BAUD_GEN_VALUE = int'(sc64::CLOCK_FREQUENCY / sc64::UART_BAUD_RATE) - 1'd1;
|
||||
|
||||
typedef enum bit [1:0] {
|
||||
S_TRX_IDLE,
|
||||
|
@ -1,32 +1,3 @@
|
||||
interface if_dma ();
|
||||
|
||||
logic request;
|
||||
logic ack;
|
||||
logic write;
|
||||
logic [31:0] address;
|
||||
logic [15:0] rdata;
|
||||
logic [15:0] wdata;
|
||||
|
||||
modport cpu (
|
||||
output request,
|
||||
input ack,
|
||||
output write,
|
||||
output address,
|
||||
input rdata,
|
||||
output wdata
|
||||
);
|
||||
|
||||
modport device (
|
||||
input request,
|
||||
output ack,
|
||||
input write,
|
||||
input address,
|
||||
output rdata,
|
||||
input wdata
|
||||
);
|
||||
|
||||
endinterface
|
||||
|
||||
module cpu_usb (
|
||||
if_system sys,
|
||||
if_cpu_bus bus,
|
||||
|
@ -1,6 +1,10 @@
|
||||
module memory_flash (
|
||||
if_system.sys sys,
|
||||
if_n64_bus bus
|
||||
|
||||
input request,
|
||||
output ack,
|
||||
input [31:0] address,
|
||||
output [15:0] rdata
|
||||
);
|
||||
|
||||
logic flash_enable;
|
||||
@ -12,40 +16,57 @@ module memory_flash (
|
||||
logic dummy_ack;
|
||||
|
||||
always_comb begin
|
||||
flash_enable = bus.address < 32'h10016800;
|
||||
flash_enable = address < 32'h10016800;
|
||||
|
||||
bus.ack = flash_ack | dummy_ack;
|
||||
ack = flash_ack | dummy_ack;
|
||||
|
||||
bus.rdata = 16'd0;
|
||||
if (bus.ack && flash_enable) begin
|
||||
if (bus.address[1]) bus.rdata = {flash_rdata[23:16], flash_rdata[31:24]};
|
||||
else bus.rdata = {flash_rdata[7:0], flash_rdata[15:8]};
|
||||
rdata = 16'd0;
|
||||
if (ack && flash_enable) begin
|
||||
if (address[1]) rdata = {flash_rdata[23:16], flash_rdata[31:24]};
|
||||
else rdata = {flash_rdata[7:0], flash_rdata[15:8]};
|
||||
end
|
||||
end
|
||||
|
||||
typedef enum bit [0:0] {
|
||||
S_IDLE,
|
||||
S_WAIT
|
||||
} e_state;
|
||||
|
||||
e_state state;
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
dummy_ack <= 1'b0;
|
||||
dummy_ack <= 1'b1;
|
||||
|
||||
if (sys.reset) begin
|
||||
state <= S_IDLE;
|
||||
flash_request <= 1'b0;
|
||||
end else begin
|
||||
case (state)
|
||||
S_IDLE: begin
|
||||
if (request) begin
|
||||
state <= S_WAIT;
|
||||
flash_request <= flash_enable;
|
||||
dummy_ack <= !flash_enable;
|
||||
end
|
||||
end
|
||||
|
||||
S_WAIT: begin
|
||||
if (!flash_busy) begin
|
||||
flash_request <= 1'b0;
|
||||
end
|
||||
if (bus.request) begin
|
||||
if (flash_enable) begin
|
||||
flash_request <= 1'b1;
|
||||
end else begin
|
||||
dummy_ack <= 1'b1;
|
||||
if (ack) begin
|
||||
state <= S_IDLE;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
intel_flash intel_flash_inst (
|
||||
.clock(sys.clk),
|
||||
.reset_n(~sys.reset),
|
||||
.avmm_data_addr(bus.address[31:2]),
|
||||
.avmm_data_read(flash_request || (bus.request && flash_enable)),
|
||||
.avmm_data_addr(address[31:2]),
|
||||
.avmm_data_read(flash_request),
|
||||
.avmm_data_readdata(flash_rdata),
|
||||
.avmm_data_waitrequest(flash_busy),
|
||||
.avmm_data_readdatavalid(flash_ack),
|
||||
|
14
fw/rtl/n64/n64_bootloader.sv
Normal file
14
fw/rtl/n64/n64_bootloader.sv
Normal file
@ -0,0 +1,14 @@
|
||||
module n64_bootloader (
|
||||
if_system.sys sys,
|
||||
if_n64_bus bus
|
||||
);
|
||||
|
||||
memory_flash memory_flash_inst (
|
||||
.sys(sys),
|
||||
.request(bus.request),
|
||||
.ack(bus.ack),
|
||||
.address(bus.address),
|
||||
.rdata(bus.rdata)
|
||||
);
|
||||
|
||||
endmodule
|
@ -86,6 +86,8 @@ module n64_pi (
|
||||
logic n64_pi_ad_output_enable_data;
|
||||
|
||||
logic n64_pi_address_valid;
|
||||
logic pending_operation;
|
||||
logic pending_write;
|
||||
|
||||
always_comb begin
|
||||
n64_pi_ad = n64_pi_ad_output_enable ? n64_pi_ad_output : 16'hZZZZ;
|
||||
@ -99,6 +101,9 @@ module n64_pi (
|
||||
if (read_op) begin
|
||||
n64_pi_ad_output_data <= n64_pi_ad_output_data_buffer;
|
||||
end
|
||||
if (pending_operation && bus.ack) begin
|
||||
n64_pi_ad_output_data <= bus.rdata;
|
||||
end
|
||||
end
|
||||
|
||||
// Internal bus controller
|
||||
@ -110,8 +115,6 @@ module n64_pi (
|
||||
|
||||
e_state state;
|
||||
logic first_operation;
|
||||
logic pending_operation;
|
||||
logic pending_write;
|
||||
|
||||
sc64::e_n64_id next_id;
|
||||
logic [25:0] next_offset;
|
||||
@ -157,8 +160,6 @@ module n64_pi (
|
||||
end
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
// bus.request <= 1'b0;
|
||||
|
||||
if (sys.reset || sys.n64_hard_reset || sys.n64_soft_reset) begin
|
||||
state <= S_IDLE;
|
||||
bus.request <= 1'b0;
|
||||
@ -182,6 +183,7 @@ module n64_pi (
|
||||
end
|
||||
bus.wdata <= n64_pi_ad_input;
|
||||
first_operation <= alel_op;
|
||||
pending_operation <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
@ -196,12 +198,6 @@ module n64_pi (
|
||||
pending_write <= write_op;
|
||||
end
|
||||
end
|
||||
|
||||
default: begin
|
||||
state <= S_IDLE;
|
||||
bus.request <= 1'b0;
|
||||
pending_operation <= 1'b0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
@ -1,7 +1,7 @@
|
||||
module n64_sdram (
|
||||
if_system sys,
|
||||
if_n64_bus bus,
|
||||
if_dma.device dma,
|
||||
if_dma.memory dma,
|
||||
|
||||
output sdram_cs,
|
||||
output sdram_ras,
|
||||
|
@ -1,7 +1,7 @@
|
||||
module n64_soc (
|
||||
if_system sys,
|
||||
if_config cfg,
|
||||
if_dma.device dma,
|
||||
if_dma.memory dma,
|
||||
|
||||
input n64_pi_alel,
|
||||
input n64_pi_aleh,
|
||||
@ -49,7 +49,7 @@ module n64_soc (
|
||||
.sdram_dq(sdram_dq)
|
||||
);
|
||||
|
||||
memory_flash memory_flash_inst (
|
||||
n64_bootloader n64_bootloader_inst (
|
||||
.sys(sys),
|
||||
.bus(bus.at[sc64::ID_N64_BOOTLOADER].device)
|
||||
);
|
||||
|
@ -19,8 +19,10 @@ package sc64;
|
||||
__ID_CPU_END
|
||||
} e_cpu_id;
|
||||
|
||||
parameter CLOCK_FREQUENCY = 100_000_000;
|
||||
parameter int CLOCK_FREQUENCY = 32'd100_000_000;
|
||||
|
||||
parameter UART_BAUD_RATE = 1_000_000;
|
||||
parameter int UART_BAUD_RATE = 32'd1_000_000;
|
||||
|
||||
parameter bit DEBUG_ENABLED = 1'b0;
|
||||
|
||||
endpackage
|
||||
|
@ -49,10 +49,14 @@ module system (if_system.internal sys);
|
||||
.locked(locked)
|
||||
);
|
||||
|
||||
// intel_snp intel_snp_inst (
|
||||
// .source(external_reset),
|
||||
// .source_clk(sys.clk)
|
||||
// );
|
||||
generate
|
||||
if (sc64::DEBUG_ENABLED) begin
|
||||
intel_snp intel_snp_inst (
|
||||
.source(external_reset),
|
||||
.source_clk(sys.clk)
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
n64_reset_ff <= {n64_reset_ff[0], sys.n64_reset};
|
||||
|
10
fw/stp.stp
10
fw/stp.stp
@ -6,14 +6,14 @@
|
||||
<node_ip_info instance_id="0" mfg_id="110" node_id="0" version="6"/>
|
||||
<position_info>
|
||||
<single attribute="active tab" value="0"/>
|
||||
<single attribute="data horizontal scroll position" value="757"/>
|
||||
<single attribute="data horizontal scroll position" value="0"/>
|
||||
<single attribute="data vertical scroll position" value="0"/>
|
||||
<single attribute="setup horizontal scroll position" value="0"/>
|
||||
<single attribute="setup vertical scroll position" value="0"/>
|
||||
<single attribute="zoom level denominator" value="1"/>
|
||||
<single attribute="zoom level numerator" value="2048"/>
|
||||
<single attribute="zoom level numerator" value="1"/>
|
||||
<single attribute="zoom offset denominator" value="1"/>
|
||||
<single attribute="zoom offset numerator" value="28"/>
|
||||
<single attribute="zoom offset numerator" value="130048"/>
|
||||
</position_info>
|
||||
<signal_set global_temp="1" name="signal_set: 2021/08/21 02:17:34 #0">
|
||||
<clock name="system:system_inst|intel_pll:intel_pll_inst|altpll:altpll_component|clk[0]" polarity="posedge" tap_mode="classic"/>
|
||||
@ -488,7 +488,7 @@
|
||||
<node data_index="173" duplicate_name_allowed="false" is_data_input="true" is_node_valid="true" is_selected="false" is_storage_input="false" is_trigger_input="true" level-0="dont_care" name="o_sdram_ba[1]" pwr_level-0="dont_care" tap_mode="classic" trigger_index="173" type="unknown"/>
|
||||
<node data_index="172" duplicate_name_allowed="false" is_data_input="true" is_node_valid="true" is_selected="false" is_storage_input="false" is_trigger_input="true" level-0="dont_care" name="o_sdram_ba[0]" pwr_level-0="dont_care" tap_mode="classic" trigger_index="172" type="unknown"/>
|
||||
</node>
|
||||
<node is_selected="true" level-0="alt_or" name="io_sdram_dq[15..0]" order="msb_to_lsb" state="collapse" storage-0="alt_or" storage-1="alt_or" storage-2="alt_or" type="bidir pin">
|
||||
<node is_selected="false" level-0="alt_or" name="io_sdram_dq[15..0]" order="msb_to_lsb" state="collapse" storage-0="alt_or" storage-1="alt_or" storage-2="alt_or" type="bidir pin">
|
||||
<node data_index="6" duplicate_name_allowed="false" is_data_input="true" is_node_valid="true" is_selected="false" is_storage_input="false" is_trigger_input="true" level-0="dont_care" name="io_sdram_dq[15]" pwr_level-0="dont_care" tap_mode="classic" trigger_index="6" type="unknown"/>
|
||||
<node data_index="5" duplicate_name_allowed="false" is_data_input="true" is_node_valid="true" is_selected="false" is_storage_input="false" is_trigger_input="true" level-0="dont_care" name="io_sdram_dq[14]" pwr_level-0="dont_care" tap_mode="classic" trigger_index="5" type="unknown"/>
|
||||
<node data_index="4" duplicate_name_allowed="false" is_data_input="true" is_node_valid="true" is_selected="false" is_storage_input="false" is_trigger_input="true" level-0="dont_care" name="io_sdram_dq[13]" pwr_level-0="dont_care" tap_mode="classic" trigger_index="4" type="unknown"/>
|
||||
@ -1026,7 +1026,7 @@ trigger;]]>
|
||||
<single attribute="jtag widget visible" value="1"/>
|
||||
<single attribute="lock mode" value="0"/>
|
||||
<multi attribute="column width" size="23" value="34,34,452,74,146,78,95,96,98,98,88,88,110,101,101,101,101,101,101,101,101,107,78"/>
|
||||
<multi attribute="frame size" size="2" value="1610,1412"/>
|
||||
<multi attribute="frame size" size="2" value="3378,1417"/>
|
||||
<multi attribute="jtag widget size" size="2" value="348,135"/>
|
||||
</global_info>
|
||||
</session>
|
||||
|
@ -1,26 +0,0 @@
|
||||
module cpu_rom (
|
||||
if_system.sys system_if,
|
||||
if_cpu_bus_out cpu_bus_if,
|
||||
if_cpu_bus_in cpu_rom_if
|
||||
);
|
||||
|
||||
wire request;
|
||||
wire ack;
|
||||
wire [31:0] rdata;
|
||||
|
||||
assign request = (cpu_bus_if.address[31:24] == 8'h03) && cpu_bus_if.req;
|
||||
assign cpu_rom_if.ack = ack & request;
|
||||
assign cpu_rom_if.rdata = cpu_rom_if.ack ? rdata : 32'd0;
|
||||
|
||||
intel_flash intel_flash_inst (
|
||||
.clock(system_if.clk),
|
||||
.avmm_data_addr(cpu_bus_if.address[17:2]),
|
||||
.avmm_data_read(request),
|
||||
.avmm_data_readdata(rdata),
|
||||
.avmm_data_waitrequest(),
|
||||
.avmm_data_readdatavalid(ack),
|
||||
.avmm_data_burstcount(2'd1),
|
||||
.reset_n(~system_if.reset)
|
||||
);
|
||||
|
||||
endmodule
|
@ -1,56 +0,0 @@
|
||||
module memory_embedded_flash (
|
||||
input i_clk,
|
||||
input i_reset,
|
||||
|
||||
input i_request,
|
||||
output reg o_busy,
|
||||
output o_ack,
|
||||
input [18:0] i_address,
|
||||
output reg [31:0] o_data
|
||||
);
|
||||
|
||||
localparam [18:0] ONCHIP_FLASH_END = 19'h059FF;
|
||||
|
||||
wire w_onchip_flash_in_address_range = i_address <= ONCHIP_FLASH_END;
|
||||
|
||||
reg r_dummy_ack;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
r_dummy_ack <= i_request && !w_onchip_flash_in_address_range;
|
||||
end
|
||||
|
||||
reg r_onchip_flash_request;
|
||||
wire w_onchip_flash_busy;
|
||||
wire w_onchip_flash_ack;
|
||||
wire [31:0] w_onchip_flash_o_data;
|
||||
|
||||
assign o_ack = r_dummy_ack || w_onchip_flash_ack;
|
||||
|
||||
always @(*) begin
|
||||
r_onchip_flash_request = 1'b0;
|
||||
o_busy = 1'b0;
|
||||
o_data = 32'h0000_0000;
|
||||
if (w_onchip_flash_in_address_range && !r_dummy_ack) begin
|
||||
r_onchip_flash_request = i_request;
|
||||
o_busy = w_onchip_flash_busy;
|
||||
o_data = {
|
||||
w_onchip_flash_o_data[7:0],
|
||||
w_onchip_flash_o_data[15:8],
|
||||
w_onchip_flash_o_data[23:16],
|
||||
w_onchip_flash_o_data[31:24]
|
||||
};
|
||||
end
|
||||
end
|
||||
|
||||
onchip_flash onchip_flash_inst (
|
||||
.clock(i_clk),
|
||||
.reset_n(~i_reset),
|
||||
.avmm_data_addr(i_address[14:0]),
|
||||
.avmm_data_read(r_onchip_flash_request),
|
||||
.avmm_data_readdata(w_onchip_flash_o_data),
|
||||
.avmm_data_waitrequest(w_onchip_flash_busy),
|
||||
.avmm_data_readdatavalid(w_onchip_flash_ack),
|
||||
.avmm_data_burstcount(2'd1)
|
||||
);
|
||||
|
||||
endmodule
|
@ -1,371 +0,0 @@
|
||||
module memory_sdram (
|
||||
input i_clk,
|
||||
input i_reset,
|
||||
|
||||
output o_sdram_cs,
|
||||
output o_sdram_ras,
|
||||
output o_sdram_cas,
|
||||
output o_sdram_we,
|
||||
output reg [1:0] o_sdram_ba,
|
||||
output reg [12:0] o_sdram_a,
|
||||
inout reg [15:0] io_sdram_dq,
|
||||
|
||||
input i_request,
|
||||
input i_write,
|
||||
output o_busy,
|
||||
output reg o_ack,
|
||||
input [24:0] i_address,
|
||||
output reg [31:0] o_data,
|
||||
input [31:0] i_data
|
||||
);
|
||||
|
||||
// SDRAM timings (in nanoseconds)
|
||||
|
||||
parameter real CLK_FREQ = 100_000_000.0;
|
||||
|
||||
parameter [2:0] CAS_LATENCY = 3'd2;
|
||||
|
||||
parameter real T_INIT = 100_000.0;
|
||||
parameter real T_RC = 60.0;
|
||||
parameter real T_RP = 15.0;
|
||||
parameter real T_RCD = 15.0;
|
||||
parameter real T_RAS = 37.0;
|
||||
parameter real T_WR = T_RAS - T_RCD;
|
||||
parameter real T_MRD = 14.0;
|
||||
parameter real T_REF = 7_800.0;
|
||||
|
||||
localparam real T_CLK = (1.0 / CLK_FREQ) * 1_000_000_000.0;
|
||||
localparam int C_INIT = int'((T_INIT + T_CLK - 1) / T_CLK);
|
||||
localparam int C_RC = int'((T_RC + T_CLK - 1) / T_CLK);
|
||||
localparam int C_RP = int'((T_RP + T_CLK - 1) / T_CLK);
|
||||
localparam int C_RCD = int'((T_RCD + T_CLK - 1) / T_CLK);
|
||||
localparam int C_RAS = int'((T_RAS + T_CLK - 1) / T_CLK);
|
||||
localparam int C_WR = int'((T_WR + T_CLK - 1) / T_CLK);
|
||||
localparam int C_MRD = int'((T_MRD + T_CLK - 1) / T_CLK);
|
||||
localparam int C_REF = int'((T_REF + T_CLK - 1) / T_CLK);
|
||||
|
||||
localparam INIT_PRECHARGE = C_INIT;
|
||||
localparam INIT_REFRESH_1 = C_INIT + C_RP;
|
||||
localparam INIT_REFRESH_2 = C_INIT + C_RP + C_RC;
|
||||
localparam INIT_MODE_REG = C_INIT + C_RP + (2 * C_RC);
|
||||
localparam INIT_DONE = C_INIT + C_RP + (2 * C_RC) + C_MRD;
|
||||
|
||||
|
||||
// SDRAM commands (CS, RAS, CAS, WE) and mode register
|
||||
|
||||
localparam [3:0] CMD_DESL = 4'b1111;
|
||||
localparam [3:0] CMD_NOP = 4'b0111;
|
||||
localparam [3:0] CMD_READ = 4'b0101;
|
||||
localparam [3:0] CMD_WRITE = 4'b0100;
|
||||
localparam [3:0] CMD_ACT = 4'b0011;
|
||||
localparam [3:0] CMD_PRE = 4'b0010;
|
||||
localparam [3:0] CMD_REF = 4'b0001;
|
||||
localparam [3:0] CMD_MRS = 4'b0000;
|
||||
|
||||
localparam MODE_REGISTER = {2'b00, 1'b0, 1'b0, 2'b00, CAS_LATENCY, 1'b0, 3'b000};
|
||||
|
||||
|
||||
// Command signal decoder
|
||||
|
||||
reg [3:0] r_sdram_cmd;
|
||||
|
||||
assign {o_sdram_cs, o_sdram_ras, o_sdram_cas, o_sdram_we} = r_sdram_cmd;
|
||||
|
||||
|
||||
// Address signal decoder
|
||||
|
||||
reg r_sdram_precharge;
|
||||
reg [1:0] r_sdram_bank;
|
||||
reg [12:0] r_sdram_row;
|
||||
reg [9:0] r_sdram_column;
|
||||
reg [14:0] r_active_bank_row;
|
||||
|
||||
always @(*) begin
|
||||
case (r_sdram_cmd)
|
||||
CMD_READ, CMD_WRITE: o_sdram_a = {2'b00, r_sdram_precharge, r_sdram_column};
|
||||
CMD_ACT: o_sdram_a = r_sdram_row;
|
||||
CMD_PRE: o_sdram_a = {2'b00, r_sdram_precharge, 10'b0000000000};
|
||||
CMD_MRS: o_sdram_a = MODE_REGISTER;
|
||||
default: o_sdram_a = 13'b0000000000000;
|
||||
endcase
|
||||
end
|
||||
|
||||
always @(*) begin
|
||||
case (r_sdram_cmd)
|
||||
CMD_READ, CMD_WRITE, CMD_ACT, CMD_PRE: o_sdram_ba = r_sdram_bank;
|
||||
default: o_sdram_ba = 2'b00;
|
||||
endcase
|
||||
end
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_request && !o_busy) begin
|
||||
{r_sdram_bank, r_sdram_row, r_sdram_column} <= i_address;
|
||||
end
|
||||
if (r_sdram_cmd == CMD_ACT) begin
|
||||
r_active_bank_row <= {r_sdram_bank, r_sdram_row};
|
||||
end
|
||||
if (r_sdram_cmd == CMD_READ || r_sdram_cmd == CMD_WRITE) begin
|
||||
{r_sdram_bank, r_sdram_row, r_sdram_column} <= {r_sdram_bank, r_sdram_row, r_sdram_column} + 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
wire w_next_address_in_another_row = (&r_sdram_column);
|
||||
wire w_request_in_another_row = i_address[24:10] != r_active_bank_row;
|
||||
|
||||
|
||||
// Data signal decoder
|
||||
|
||||
reg [31:0] r_sdram_data;
|
||||
reg r_current_write_word;
|
||||
|
||||
always @(*) begin
|
||||
io_sdram_dq = 16'hZZZZ;
|
||||
if (r_sdram_cmd == CMD_WRITE) begin
|
||||
io_sdram_dq = r_current_write_word ? r_sdram_data[15:0] : r_sdram_data[31:16];
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_reset) begin
|
||||
r_current_write_word <= 1'b0;
|
||||
end else if (r_sdram_cmd == CMD_WRITE) begin
|
||||
r_current_write_word <= ~r_current_write_word;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// Read latency timing
|
||||
|
||||
reg [(CAS_LATENCY - 1):0] r_read_latency;
|
||||
reg r_current_read_word;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
o_ack <= 1'b0;
|
||||
if (i_reset) begin
|
||||
r_read_latency <= {CAS_LATENCY{1'b0}};
|
||||
r_current_read_word <= 1'b0;
|
||||
end else begin
|
||||
r_read_latency <= {r_read_latency[(CAS_LATENCY - 2):0], r_sdram_cmd == CMD_READ};
|
||||
if (r_read_latency[CAS_LATENCY - 1]) begin
|
||||
o_data <= {o_data[15:0], io_sdram_dq};
|
||||
if (r_current_read_word) o_ack <= 1'b1;
|
||||
r_current_read_word <= ~r_current_read_word;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
wire w_read_pending = |r_read_latency;
|
||||
|
||||
|
||||
// Init timing and logic
|
||||
|
||||
reg [15:0] r_init_counter;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_reset) begin
|
||||
r_init_counter <= 16'd0;
|
||||
end else if (r_init_counter < INIT_DONE) begin
|
||||
r_init_counter <= r_init_counter + 1'd1;
|
||||
end
|
||||
end
|
||||
|
||||
wire w_init_hold = r_init_counter <= C_INIT - 1;
|
||||
wire w_init_precharge = r_init_counter == INIT_PRECHARGE;
|
||||
wire w_init_refresh_1 = r_init_counter == INIT_REFRESH_1;
|
||||
wire w_init_refresh_2 = r_init_counter == INIT_REFRESH_2;
|
||||
wire w_init_mode_reg = r_init_counter == INIT_MODE_REG;
|
||||
wire w_init_done = r_init_counter == INIT_DONE;
|
||||
|
||||
|
||||
// SDRAM controller FSM
|
||||
|
||||
localparam [2:0] STATE_INIT = 3'd0;
|
||||
localparam [2:0] STATE_IDLE = 3'd1;
|
||||
localparam [2:0] STATE_ACTIVATING = 3'd2;
|
||||
localparam [2:0] STATE_ACTIVE = 3'd3;
|
||||
localparam [2:0] STATE_PRECHARGING = 3'd4;
|
||||
localparam [2:0] STATE_REFRESHING = 3'd5;
|
||||
|
||||
reg [9:0] r_refresh_counter;
|
||||
reg [4:0] r_rcd_ras_rc_counter;
|
||||
reg [1:0] r_wr_counter;
|
||||
reg [2:0] r_rp_counter;
|
||||
|
||||
wire w_refresh_pending = r_refresh_counter >= (C_REF - 1'd1);
|
||||
wire w_rcd_timing_met = r_rcd_ras_rc_counter >= (C_RCD - 1'd1);
|
||||
wire w_ras_timing_met = r_rcd_ras_rc_counter >= (C_RAS - 1'd1);
|
||||
wire w_rc_timing_met = r_rcd_ras_rc_counter >= (C_RC - 1'd1);
|
||||
wire w_wr_timing_met = r_wr_counter >= (C_WR - 1'd1);
|
||||
wire w_rp_timing_met = r_rp_counter >= (C_RP - 1'd1);
|
||||
|
||||
reg [2:0] r_state;
|
||||
reg r_busy;
|
||||
reg r_cross_row_request;
|
||||
reg r_request_pending;
|
||||
reg r_write_pending;
|
||||
reg r_current_word;
|
||||
reg r_wr_wait;
|
||||
|
||||
assign o_busy = i_request && (
|
||||
w_refresh_pending ||
|
||||
r_busy ||
|
||||
r_request_pending ||
|
||||
r_cross_row_request ||
|
||||
w_read_pending ||
|
||||
r_sdram_cmd == CMD_READ ||
|
||||
r_sdram_cmd == CMD_WRITE
|
||||
);
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_reset || w_init_hold) begin
|
||||
r_sdram_cmd <= CMD_DESL;
|
||||
r_state <= STATE_INIT;
|
||||
r_busy <= 1'b1;
|
||||
r_cross_row_request <= 1'b0;
|
||||
r_wr_wait <= 1'b0;
|
||||
end else begin
|
||||
r_sdram_cmd <= CMD_NOP;
|
||||
r_sdram_precharge <= 1'b0;
|
||||
|
||||
if (r_refresh_counter < (C_REF - 1)) r_refresh_counter <= r_refresh_counter + 1'd1;
|
||||
if (r_rcd_ras_rc_counter < (C_RC - 1)) r_rcd_ras_rc_counter <= r_rcd_ras_rc_counter + 1'd1;
|
||||
if (r_wr_counter < (C_WR - 1)) r_wr_counter <= r_wr_counter + 1'd1;
|
||||
if (r_rp_counter < (C_RP - 1)) r_rp_counter <= r_rp_counter + 1'd1;
|
||||
|
||||
case (r_state)
|
||||
STATE_INIT: begin
|
||||
if (w_init_precharge) begin
|
||||
r_sdram_cmd <= CMD_PRE;
|
||||
r_sdram_precharge <= 1'b1;
|
||||
end else if (w_init_refresh_1 || w_init_refresh_2) begin
|
||||
r_sdram_cmd <= CMD_REF;
|
||||
r_refresh_counter <= 10'd0;
|
||||
end else if (w_init_mode_reg) begin
|
||||
r_sdram_cmd <= CMD_MRS;
|
||||
end else if (w_init_done) begin
|
||||
r_state <= STATE_IDLE;
|
||||
r_busy <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
STATE_IDLE: begin
|
||||
if (w_refresh_pending) begin
|
||||
r_sdram_cmd <= CMD_REF;
|
||||
r_refresh_counter <= 10'd0;
|
||||
r_rcd_ras_rc_counter <= 5'd0;
|
||||
r_state <= STATE_REFRESHING;
|
||||
r_busy <= 1'b1;
|
||||
end else if (r_request_pending || r_cross_row_request) begin
|
||||
r_sdram_cmd <= CMD_ACT;
|
||||
r_rcd_ras_rc_counter <= 5'd0;
|
||||
r_state <= STATE_ACTIVATING;
|
||||
r_busy <= 1'b1;
|
||||
end else if (i_request && !o_busy) begin
|
||||
r_sdram_cmd <= CMD_ACT;
|
||||
r_sdram_data <= i_data;
|
||||
r_rcd_ras_rc_counter <= 5'd0;
|
||||
r_state <= STATE_ACTIVATING;
|
||||
r_request_pending <= 1'b1;
|
||||
r_write_pending <= i_write;
|
||||
r_current_word <= 1'b0;
|
||||
r_busy <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
STATE_ACTIVATING: begin
|
||||
if (w_rcd_timing_met) begin
|
||||
r_sdram_cmd <= r_write_pending ? CMD_WRITE : CMD_READ;
|
||||
if (r_write_pending) r_wr_counter <= 2'd0;
|
||||
if (r_cross_row_request) begin
|
||||
r_cross_row_request <= 1'b0;
|
||||
r_busy <= 1'b0;
|
||||
end else if (r_request_pending) begin
|
||||
r_current_word <= 1'b1;
|
||||
end
|
||||
r_state <= STATE_ACTIVE;
|
||||
end
|
||||
end
|
||||
|
||||
STATE_ACTIVE: begin
|
||||
if (r_wr_wait) begin
|
||||
if (w_wr_timing_met) begin
|
||||
r_rp_counter <= 3'd0;
|
||||
r_state <= STATE_PRECHARGING;
|
||||
r_wr_wait <= 1'b0;
|
||||
end
|
||||
end else if (r_request_pending && !(r_write_pending && w_read_pending)) begin
|
||||
r_sdram_cmd <= r_write_pending ? CMD_WRITE : CMD_READ;
|
||||
if (r_write_pending) r_wr_counter <= 2'd0;
|
||||
r_current_word <= 1'b1;
|
||||
if (r_current_word) begin
|
||||
r_busy <= 1'b0;
|
||||
r_request_pending <= 1'b0;
|
||||
end
|
||||
end else if (w_refresh_pending) begin
|
||||
if (w_ras_timing_met && w_wr_timing_met) begin
|
||||
r_sdram_cmd <= CMD_PRE;
|
||||
r_sdram_precharge <= 1'b1;
|
||||
r_rp_counter <= 3'd0;
|
||||
r_state <= STATE_PRECHARGING;
|
||||
end
|
||||
end else if (i_request && !o_busy) begin
|
||||
r_sdram_data <= i_data;
|
||||
r_busy <= 1'b1;
|
||||
r_write_pending <= i_write;
|
||||
|
||||
if (w_request_in_another_row || (i_write && w_read_pending)) begin
|
||||
r_request_pending <= 1'b1;
|
||||
r_current_word <= 1'b0;
|
||||
if (!(i_write && w_read_pending)) begin
|
||||
if (!w_wr_timing_met) begin
|
||||
r_wr_wait <= 1'b1;
|
||||
end else begin
|
||||
r_sdram_cmd <= CMD_PRE;
|
||||
r_sdram_precharge <= 1'b1;
|
||||
r_rp_counter <= 3'd0;
|
||||
r_state <= STATE_PRECHARGING;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
r_sdram_cmd <= i_write ? CMD_WRITE : CMD_READ;
|
||||
if (i_write) r_wr_counter <= 2'd0;
|
||||
r_current_word <= 1'b1;
|
||||
if (w_next_address_in_another_row) begin
|
||||
r_sdram_precharge <= 1'b1;
|
||||
r_cross_row_request <= 1'b1;
|
||||
if (!i_write) begin
|
||||
r_rp_counter <= 3'd0;
|
||||
r_state <= STATE_PRECHARGING;
|
||||
end else begin
|
||||
r_wr_wait <= 1'b1;
|
||||
end
|
||||
end else begin
|
||||
r_request_pending <= 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
STATE_PRECHARGING: begin
|
||||
if (w_rc_timing_met && w_rp_timing_met) begin
|
||||
r_state <= STATE_IDLE;
|
||||
r_busy <= r_request_pending || r_cross_row_request;
|
||||
end
|
||||
end
|
||||
|
||||
STATE_REFRESHING: begin
|
||||
if (w_rc_timing_met) begin
|
||||
r_state <= STATE_IDLE;
|
||||
r_busy <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
default: begin
|
||||
r_state <= STATE_IDLE;
|
||||
r_busy <= 1'b0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
@ -1,116 +0,0 @@
|
||||
module usb_ftdi_fsi (
|
||||
input i_clk,
|
||||
input i_reset,
|
||||
|
||||
output reg o_ftdi_clk,
|
||||
output reg o_ftdi_si,
|
||||
input i_ftdi_so,
|
||||
input i_ftdi_cts,
|
||||
|
||||
input i_rx_ready,
|
||||
output reg o_rx_valid,
|
||||
output reg o_rx_channel,
|
||||
output reg [7:0] o_rx_data,
|
||||
|
||||
output reg o_tx_busy,
|
||||
input i_tx_valid,
|
||||
input i_tx_channel,
|
||||
input [7:0] i_tx_data
|
||||
);
|
||||
|
||||
// Output clock generation and control
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_reset || !i_rx_ready) begin
|
||||
o_ftdi_clk <= 1'b1;
|
||||
end else begin
|
||||
o_ftdi_clk <= ~o_ftdi_clk;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// RX module
|
||||
|
||||
reg r_rx_in_progress;
|
||||
reg [3:0] r_rx_bit_counter;
|
||||
reg r_tx_start_bit;
|
||||
reg r_rx_tx_contention;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
o_rx_valid <= 1'b0;
|
||||
|
||||
if (i_reset) begin
|
||||
r_rx_in_progress <= 1'b0;
|
||||
end else begin
|
||||
if (!o_ftdi_clk) begin
|
||||
if (!r_rx_in_progress) begin
|
||||
r_rx_in_progress <= !i_ftdi_so;
|
||||
r_rx_bit_counter <= 4'd0;
|
||||
r_rx_tx_contention <= r_tx_start_bit;
|
||||
end else begin
|
||||
r_rx_bit_counter <= r_rx_bit_counter + 4'd1;
|
||||
|
||||
if (!r_rx_bit_counter[3]) begin
|
||||
o_rx_data <= {i_ftdi_so, o_rx_data[7:1]};
|
||||
end else begin
|
||||
r_rx_in_progress <= 1'b0;
|
||||
o_rx_valid <= !r_rx_tx_contention;
|
||||
o_rx_channel <= i_ftdi_so;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// TX module
|
||||
|
||||
reg r_tx_pending;
|
||||
reg [3:0] r_tx_bit_counter;
|
||||
reg [7:0] r_tx_data;
|
||||
reg r_tx_channel;
|
||||
|
||||
wire w_tx_request_op = i_tx_valid && !o_tx_busy;
|
||||
wire w_tx_pending_op = !o_ftdi_clk || !i_ftdi_cts || !i_rx_ready || r_rx_in_progress;
|
||||
wire w_tx_reset_output_op = o_ftdi_clk && !o_tx_busy;
|
||||
wire w_tx_start_op = (w_tx_request_op || r_tx_pending) && !w_tx_pending_op;
|
||||
wire w_tx_shift_op = o_ftdi_clk && o_tx_busy && !r_tx_pending;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
r_tx_start_bit <= 1'b0;
|
||||
|
||||
if (i_reset) begin
|
||||
o_ftdi_si <= 1'b1;
|
||||
o_tx_busy <= 1'b0;
|
||||
r_tx_pending <= 1'b0;
|
||||
end else begin
|
||||
if (w_tx_request_op) begin
|
||||
o_tx_busy <= 1'b1;
|
||||
r_tx_data <= i_tx_data;
|
||||
r_tx_channel <= i_tx_channel;
|
||||
r_tx_pending <= w_tx_pending_op;
|
||||
end
|
||||
|
||||
if (w_tx_reset_output_op) begin
|
||||
o_ftdi_si <= 1'b1;
|
||||
end
|
||||
|
||||
if (w_tx_start_op) begin
|
||||
o_ftdi_si <= 1'b0;
|
||||
r_tx_start_bit <= 1'b1;
|
||||
r_tx_pending <= 1'b0;
|
||||
r_tx_bit_counter <= 4'd0;
|
||||
end
|
||||
|
||||
if (w_tx_shift_op) begin
|
||||
r_tx_bit_counter <= r_tx_bit_counter + 4'd1;
|
||||
{r_tx_data[6:0], o_ftdi_si} <= r_tx_data;
|
||||
if (r_tx_bit_counter[3]) begin
|
||||
o_ftdi_si <= r_tx_channel;
|
||||
o_tx_busy <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
Loading…
Reference in New Issue
Block a user