mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-25 23:24:15 +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 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
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 (
|
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,
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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),
|
||||||
|
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_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
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
||||||
);
|
);
|
||||||
|
@ -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
|
||||||
|
@ -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};
|
||||||
|
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"/>
|
<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>
|
||||||
|
@ -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