This commit is contained in:
Polprzewodnikowy 2021-08-21 04:35:40 +02:00
parent 430ecf3e69
commit 90b211c179
19 changed files with 112 additions and 643 deletions

View File

@ -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 btldr/btldr.sv
set_global_assignment -name SYSTEMVERILOG_FILE picorv32/picorv32.v 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_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_gpio.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_i2c.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_i2c.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_ram.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/cpu/cpu_wrapper.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/memory/memory_flash.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/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_bus.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_pi.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_pi.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_sdram.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_sdram.sv

28
fw/rtl/cpu/cpu_dma.sv Normal file
View 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

View File

@ -1,7 +1,7 @@
module cpu_soc ( module cpu_soc (
if_system.sys sys, if_system.sys sys,
if_config cfg, if_config cfg,
if_dma.cpu dma, if_dma dma,
input [7:0] gpio_i, input [7:0] gpio_i,
output [7:0] gpio_o, output [7:0] gpio_o,

View File

@ -8,7 +8,7 @@ module cpu_uart (
output uart_rts 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] { typedef enum bit [1:0] {
S_TRX_IDLE, S_TRX_IDLE,

View File

@ -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 ( module cpu_usb (
if_system sys, if_system sys,
if_cpu_bus bus, if_cpu_bus bus,

View File

@ -1,6 +1,10 @@
module memory_flash ( module memory_flash (
if_system.sys sys, if_system.sys sys,
if_n64_bus bus
input request,
output ack,
input [31:0] address,
output [15:0] rdata
); );
logic flash_enable; logic flash_enable;
@ -12,40 +16,57 @@ module memory_flash (
logic dummy_ack; logic dummy_ack;
always_comb begin 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; rdata = 16'd0;
if (bus.ack && flash_enable) begin if (ack && flash_enable) begin
if (bus.address[1]) bus.rdata = {flash_rdata[23:16], flash_rdata[31:24]}; if (address[1]) rdata = {flash_rdata[23:16], flash_rdata[31:24]};
else bus.rdata = {flash_rdata[7:0], flash_rdata[15:8]}; else rdata = {flash_rdata[7:0], flash_rdata[15:8]};
end end
end end
typedef enum bit [0:0] {
S_IDLE,
S_WAIT
} e_state;
e_state state;
always_ff @(posedge sys.clk) begin always_ff @(posedge sys.clk) begin
dummy_ack <= 1'b0; dummy_ack <= 1'b1;
if (sys.reset) begin if (sys.reset) begin
state <= S_IDLE;
flash_request <= 1'b0; flash_request <= 1'b0;
end else begin end else begin
if (!flash_busy) begin case (state)
flash_request <= 1'b0; S_IDLE: begin
end if (request) begin
if (bus.request) begin state <= S_WAIT;
if (flash_enable) begin flash_request <= flash_enable;
flash_request <= 1'b1; dummy_ack <= !flash_enable;
end else begin end
dummy_ack <= 1'b1;
end end
end
S_WAIT: begin
if (!flash_busy) begin
flash_request <= 1'b0;
end
if (ack) begin
state <= S_IDLE;
end
end
endcase
end end
end end
intel_flash intel_flash_inst ( intel_flash intel_flash_inst (
.clock(sys.clk), .clock(sys.clk),
.reset_n(~sys.reset), .reset_n(~sys.reset),
.avmm_data_addr(bus.address[31:2]), .avmm_data_addr(address[31:2]),
.avmm_data_read(flash_request || (bus.request && flash_enable)), .avmm_data_read(flash_request),
.avmm_data_readdata(flash_rdata), .avmm_data_readdata(flash_rdata),
.avmm_data_waitrequest(flash_busy), .avmm_data_waitrequest(flash_busy),
.avmm_data_readdatavalid(flash_ack), .avmm_data_readdatavalid(flash_ack),

View 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

View File

@ -86,6 +86,8 @@ module n64_pi (
logic n64_pi_ad_output_enable_data; logic n64_pi_ad_output_enable_data;
logic n64_pi_address_valid; logic n64_pi_address_valid;
logic pending_operation;
logic pending_write;
always_comb begin always_comb begin
n64_pi_ad = n64_pi_ad_output_enable ? n64_pi_ad_output : 16'hZZZZ; 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 if (read_op) begin
n64_pi_ad_output_data <= n64_pi_ad_output_data_buffer; n64_pi_ad_output_data <= n64_pi_ad_output_data_buffer;
end end
if (pending_operation && bus.ack) begin
n64_pi_ad_output_data <= bus.rdata;
end
end end
// Internal bus controller // Internal bus controller
@ -110,8 +115,6 @@ module n64_pi (
e_state state; e_state state;
logic first_operation; logic first_operation;
logic pending_operation;
logic pending_write;
sc64::e_n64_id next_id; sc64::e_n64_id next_id;
logic [25:0] next_offset; logic [25:0] next_offset;
@ -157,8 +160,6 @@ module n64_pi (
end end
always_ff @(posedge sys.clk) begin always_ff @(posedge sys.clk) begin
// bus.request <= 1'b0;
if (sys.reset || sys.n64_hard_reset || sys.n64_soft_reset) begin if (sys.reset || sys.n64_hard_reset || sys.n64_soft_reset) begin
state <= S_IDLE; state <= S_IDLE;
bus.request <= 1'b0; bus.request <= 1'b0;
@ -182,6 +183,7 @@ module n64_pi (
end end
bus.wdata <= n64_pi_ad_input; bus.wdata <= n64_pi_ad_input;
first_operation <= alel_op; first_operation <= alel_op;
pending_operation <= 1'b0;
end end
end end
@ -196,12 +198,6 @@ module n64_pi (
pending_write <= write_op; pending_write <= write_op;
end end
end end
default: begin
state <= S_IDLE;
bus.request <= 1'b0;
pending_operation <= 1'b0;
end
endcase endcase
end end
end end

View File

@ -1,7 +1,7 @@
module n64_sdram ( module n64_sdram (
if_system sys, if_system sys,
if_n64_bus bus, if_n64_bus bus,
if_dma.device dma, if_dma.memory dma,
output sdram_cs, output sdram_cs,
output sdram_ras, output sdram_ras,

View File

@ -1,7 +1,7 @@
module n64_soc ( module n64_soc (
if_system sys, if_system sys,
if_config cfg, if_config cfg,
if_dma.device dma, if_dma.memory dma,
input n64_pi_alel, input n64_pi_alel,
input n64_pi_aleh, input n64_pi_aleh,
@ -49,7 +49,7 @@ module n64_soc (
.sdram_dq(sdram_dq) .sdram_dq(sdram_dq)
); );
memory_flash memory_flash_inst ( n64_bootloader n64_bootloader_inst (
.sys(sys), .sys(sys),
.bus(bus.at[sc64::ID_N64_BOOTLOADER].device) .bus(bus.at[sc64::ID_N64_BOOTLOADER].device)
); );

View File

@ -19,8 +19,10 @@ package sc64;
__ID_CPU_END __ID_CPU_END
} e_cpu_id; } 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 endpackage

View File

@ -49,10 +49,14 @@ module system (if_system.internal sys);
.locked(locked) .locked(locked)
); );
// intel_snp intel_snp_inst ( generate
// .source(external_reset), if (sc64::DEBUG_ENABLED) begin
// .source_clk(sys.clk) intel_snp intel_snp_inst (
// ); .source(external_reset),
.source_clk(sys.clk)
);
end
endgenerate
always_ff @(posedge sys.clk) begin always_ff @(posedge sys.clk) begin
n64_reset_ff <= {n64_reset_ff[0], sys.n64_reset}; n64_reset_ff <= {n64_reset_ff[0], sys.n64_reset};

View File

@ -6,14 +6,14 @@
<node_ip_info instance_id="0" mfg_id="110" node_id="0" version="6"/> <node_ip_info instance_id="0" mfg_id="110" node_id="0" version="6"/>
<position_info> <position_info>
<single attribute="active tab" value="0"/> <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="data vertical scroll position" value="0"/>
<single attribute="setup horizontal scroll position" value="0"/> <single attribute="setup horizontal scroll position" value="0"/>
<single attribute="setup vertical scroll position" value="0"/> <single attribute="setup vertical scroll position" value="0"/>
<single attribute="zoom level denominator" value="1"/> <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 denominator" value="1"/>
<single attribute="zoom offset numerator" value="28"/> <single attribute="zoom offset numerator" value="130048"/>
</position_info> </position_info>
<signal_set global_temp="1" name="signal_set: 2021/08/21 02:17:34 #0"> <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"/> <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="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 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>
<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="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="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"/> <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="jtag widget visible" value="1"/>
<single attribute="lock mode" value="0"/> <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="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"/> <multi attribute="jtag widget size" size="2" value="348,135"/>
</global_info> </global_info>
</session> </session>

View File

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

View File

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

View File

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

View File

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