remove lsp

This commit is contained in:
Nitcloud 2024-09-11 13:35:04 +08:00
commit 35d0886e6f
107 changed files with 142953 additions and 1 deletions

6
.gitignore vendored
View File

@ -1,9 +1,15 @@
<<<<<<< HEAD
library
node_modules
out
./*.log
./*.str
dist
=======
out
dist
node_modules
>>>>>>> 199b7a8af3ea01baea4b20c89273a490dc0dc9d2
script/__pycache__
.vscode-test/
*.vsix

View File

@ -42,8 +42,12 @@
```bash
python script/command/make_package.py
<<<<<<< HEAD
```
## library更新
library的更新不会随着Digital-IDE的git一起保存是专门去拉取更新的但是打包要一起打包进插件之中。
=======
```
>>>>>>> 199b7a8af3ea01baea4b20c89273a490dc0dc9d2

View File

@ -0,0 +1,519 @@
{
"design": {
"design_info": {
"boundary_crc": "0xA1D73E4ECA8CEDF5",
"name": "MicroBlaze_default",
"synth_flow_mode": "Hierarchical",
"validated": "true"
},
"design_tree": {
"microblaze_0": "",
"microblaze_0_local_memory": {
"dlmb_v10": "",
"ilmb_v10": "",
"dlmb_bram_if_cntlr": "",
"ilmb_bram_if_cntlr": "",
"lmb_bram": ""
},
"mdm_1": "",
"rst_clk_wiz_1_100M": "",
"axi_gpio_0": "",
"microblaze_0_axi_periph": {
"s00_couplers": {}
}
},
"interface_ports": {
"gpio_rtl_0": {
"mode": "Master",
"vlnv": "xilinx.com:interface:gpio_rtl:1.0"
}
},
"ports": {
"cpu_clk": {
"type": "clk",
"direction": "I",
"parameters": {
"ASSOCIATED_RESET": {
"value": "cpu_rst_n"
},
"CLK_DOMAIN": {
"value": "MicroBlaze_default_Clk_0",
"value_src": "default"
},
"FREQ_HZ": {
"value": "100000000",
"value_src": "default"
},
"INSERT_VIP": {
"value": "0",
"value_src": "default"
},
"PHASE": {
"value": "0.000",
"value_src": "default"
}
}
},
"cpu_rst_n": {
"type": "rst",
"direction": "I",
"parameters": {
"INSERT_VIP": {
"value": "0",
"value_src": "default"
},
"POLARITY": {
"value": "ACTIVE_LOW"
}
}
}
},
"components": {
"microblaze_0": {
"vlnv": "xilinx.com:ip:microblaze:11.0",
"xci_name": "MicroBlaze_default_microblaze_0_0",
"parameters": {
"C_DEBUG_ENABLED": {
"value": "1"
},
"C_D_AXI": {
"value": "1"
},
"C_D_LMB": {
"value": "1"
},
"C_I_LMB": {
"value": "1"
}
},
"hdl_attributes": {
"BMM_INFO_PROCESSOR": {
"value": "microblaze-le > MicroBlaze_default microblaze_0_local_memory/dlmb_bram_if_cntlr",
"value_src": "default"
},
"KEEP_HIERARCHY": {
"value": "yes",
"value_src": "default"
}
}
},
"microblaze_0_local_memory": {
"interface_ports": {
"DLMB": {
"mode": "MirroredMaster",
"vlnv": "xilinx.com:interface:lmb_rtl:1.0"
},
"ILMB": {
"mode": "MirroredMaster",
"vlnv": "xilinx.com:interface:lmb_rtl:1.0"
}
},
"ports": {
"LMB_Clk": {
"type": "clk",
"direction": "I"
},
"SYS_Rst": {
"type": "rst",
"direction": "I"
}
},
"components": {
"dlmb_v10": {
"vlnv": "xilinx.com:ip:lmb_v10:3.0",
"xci_name": "MicroBlaze_default_dlmb_v10_0"
},
"ilmb_v10": {
"vlnv": "xilinx.com:ip:lmb_v10:3.0",
"xci_name": "MicroBlaze_default_ilmb_v10_0"
},
"dlmb_bram_if_cntlr": {
"vlnv": "xilinx.com:ip:lmb_bram_if_cntlr:4.0",
"xci_name": "MicroBlaze_default_dlmb_bram_if_cntlr_0",
"parameters": {
"C_ECC": {
"value": "0"
}
},
"hdl_attributes": {
"BMM_INFO_ADDRESS_SPACE": {
"value": "byte 0x00000000 32 > MicroBlaze_default microblaze_0_local_memory/lmb_bram",
"value_src": "default"
},
"KEEP_HIERARCHY": {
"value": "yes",
"value_src": "default"
}
}
},
"ilmb_bram_if_cntlr": {
"vlnv": "xilinx.com:ip:lmb_bram_if_cntlr:4.0",
"xci_name": "MicroBlaze_default_ilmb_bram_if_cntlr_0",
"parameters": {
"C_ECC": {
"value": "0"
}
}
},
"lmb_bram": {
"vlnv": "xilinx.com:ip:blk_mem_gen:8.4",
"xci_name": "MicroBlaze_default_lmb_bram_0",
"parameters": {
"Memory_Type": {
"value": "True_Dual_Port_RAM"
},
"use_bram_block": {
"value": "BRAM_Controller"
}
}
}
},
"interface_nets": {
"microblaze_0_ilmb_bus": {
"interface_ports": [
"ilmb_v10/LMB_Sl_0",
"ilmb_bram_if_cntlr/SLMB"
]
},
"microblaze_0_dlmb_bus": {
"interface_ports": [
"dlmb_v10/LMB_Sl_0",
"dlmb_bram_if_cntlr/SLMB"
]
},
"microblaze_0_ilmb_cntlr": {
"interface_ports": [
"ilmb_bram_if_cntlr/BRAM_PORT",
"lmb_bram/BRAM_PORTB"
]
},
"microblaze_0_dlmb_cntlr": {
"interface_ports": [
"dlmb_bram_if_cntlr/BRAM_PORT",
"lmb_bram/BRAM_PORTA"
]
},
"microblaze_0_dlmb": {
"interface_ports": [
"DLMB",
"dlmb_v10/LMB_M"
]
},
"microblaze_0_ilmb": {
"interface_ports": [
"ILMB",
"ilmb_v10/LMB_M"
]
}
},
"nets": {
"microblaze_0_Clk": {
"ports": [
"LMB_Clk",
"dlmb_v10/LMB_Clk",
"dlmb_bram_if_cntlr/LMB_Clk",
"ilmb_v10/LMB_Clk",
"ilmb_bram_if_cntlr/LMB_Clk"
]
},
"SYS_Rst_1": {
"ports": [
"SYS_Rst",
"dlmb_v10/SYS_Rst",
"dlmb_bram_if_cntlr/LMB_Rst",
"ilmb_v10/SYS_Rst",
"ilmb_bram_if_cntlr/LMB_Rst"
]
}
}
},
"mdm_1": {
"vlnv": "xilinx.com:ip:mdm:3.2",
"xci_name": "MicroBlaze_default_mdm_1_0"
},
"rst_clk_wiz_1_100M": {
"vlnv": "xilinx.com:ip:proc_sys_reset:5.0",
"xci_name": "MicroBlaze_default_rst_clk_wiz_1_100M_0"
},
"axi_gpio_0": {
"vlnv": "xilinx.com:ip:axi_gpio:2.0",
"xci_name": "MicroBlaze_default_axi_gpio_0_0"
},
"microblaze_0_axi_periph": {
"vlnv": "xilinx.com:ip:axi_interconnect:2.1",
"xci_name": "MicroBlaze_default_microblaze_0_axi_periph_0",
"parameters": {
"NUM_MI": {
"value": "1"
}
},
"interface_ports": {
"S00_AXI": {
"mode": "Slave",
"vlnv": "xilinx.com:interface:aximm_rtl:1.0"
},
"M00_AXI": {
"mode": "Master",
"vlnv": "xilinx.com:interface:aximm_rtl:1.0"
}
},
"ports": {
"ACLK": {
"type": "clk",
"direction": "I",
"parameters": {
"ASSOCIATED_RESET": {
"value": "ARESETN"
}
}
},
"ARESETN": {
"type": "rst",
"direction": "I"
},
"S00_ACLK": {
"type": "clk",
"direction": "I",
"parameters": {
"ASSOCIATED_BUSIF": {
"value": "S00_AXI"
},
"ASSOCIATED_RESET": {
"value": "S00_ARESETN"
}
}
},
"S00_ARESETN": {
"type": "rst",
"direction": "I"
},
"M00_ACLK": {
"type": "clk",
"direction": "I",
"parameters": {
"ASSOCIATED_BUSIF": {
"value": "M00_AXI"
},
"ASSOCIATED_RESET": {
"value": "M00_ARESETN"
}
}
},
"M00_ARESETN": {
"type": "rst",
"direction": "I"
}
},
"components": {
"s00_couplers": {
"interface_ports": {
"M_AXI": {
"mode": "Master",
"vlnv": "xilinx.com:interface:aximm_rtl:1.0"
},
"S_AXI": {
"mode": "Slave",
"vlnv": "xilinx.com:interface:aximm_rtl:1.0"
}
},
"ports": {
"M_ACLK": {
"type": "clk",
"direction": "I",
"parameters": {
"ASSOCIATED_BUSIF": {
"value": "M_AXI"
},
"ASSOCIATED_RESET": {
"value": "M_ARESETN"
}
}
},
"M_ARESETN": {
"type": "rst",
"direction": "I"
},
"S_ACLK": {
"type": "clk",
"direction": "I",
"parameters": {
"ASSOCIATED_BUSIF": {
"value": "S_AXI"
},
"ASSOCIATED_RESET": {
"value": "S_ARESETN"
}
}
},
"S_ARESETN": {
"type": "rst",
"direction": "I"
}
},
"interface_nets": {
"s00_couplers_to_s00_couplers": {
"interface_ports": [
"S_AXI",
"M_AXI"
]
}
}
}
},
"interface_nets": {
"microblaze_0_axi_periph_to_s00_couplers": {
"interface_ports": [
"S00_AXI",
"s00_couplers/S_AXI"
]
},
"s00_couplers_to_microblaze_0_axi_periph": {
"interface_ports": [
"M00_AXI",
"s00_couplers/M_AXI"
]
}
},
"nets": {
"microblaze_0_axi_periph_ACLK_net": {
"ports": [
"M00_ACLK",
"s00_couplers/M_ACLK"
]
},
"microblaze_0_axi_periph_ARESETN_net": {
"ports": [
"M00_ARESETN",
"s00_couplers/M_ARESETN"
]
},
"S00_ACLK_1": {
"ports": [
"S00_ACLK",
"s00_couplers/S_ACLK"
]
},
"S00_ARESETN_1": {
"ports": [
"S00_ARESETN",
"s00_couplers/S_ARESETN"
]
}
}
}
},
"interface_nets": {
"microblaze_0_M_AXI_DP": {
"interface_ports": [
"microblaze_0/M_AXI_DP",
"microblaze_0_axi_periph/S00_AXI"
]
},
"microblaze_0_ilmb_1": {
"interface_ports": [
"microblaze_0/ILMB",
"microblaze_0_local_memory/ILMB"
]
},
"microblaze_0_dlmb_1": {
"interface_ports": [
"microblaze_0/DLMB",
"microblaze_0_local_memory/DLMB"
]
},
"microblaze_0_debug": {
"interface_ports": [
"mdm_1/MBDEBUG_0",
"microblaze_0/DEBUG"
]
},
"microblaze_0_axi_periph_M00_AXI": {
"interface_ports": [
"microblaze_0_axi_periph/M00_AXI",
"axi_gpio_0/S_AXI"
]
},
"axi_gpio_0_GPIO": {
"interface_ports": [
"gpio_rtl_0",
"axi_gpio_0/GPIO"
]
}
},
"nets": {
"rst_clk_wiz_1_100M_mb_reset": {
"ports": [
"rst_clk_wiz_1_100M/mb_reset",
"microblaze_0/Reset"
]
},
"rst_clk_wiz_1_100M_bus_struct_reset": {
"ports": [
"rst_clk_wiz_1_100M/bus_struct_reset",
"microblaze_0_local_memory/SYS_Rst"
]
},
"mdm_1_debug_sys_rst": {
"ports": [
"mdm_1/Debug_SYS_Rst",
"rst_clk_wiz_1_100M/mb_debug_sys_rst"
]
},
"cpu_clk": {
"ports": [
"cpu_clk",
"microblaze_0/Clk",
"rst_clk_wiz_1_100M/slowest_sync_clk",
"microblaze_0_local_memory/LMB_Clk",
"microblaze_0_axi_periph/S00_ACLK",
"axi_gpio_0/s_axi_aclk",
"microblaze_0_axi_periph/M00_ACLK",
"microblaze_0_axi_periph/ACLK"
]
},
"cpu_rst_n": {
"ports": [
"cpu_rst_n",
"rst_clk_wiz_1_100M/ext_reset_in",
"microblaze_0_axi_periph/S00_ARESETN",
"axi_gpio_0/s_axi_aresetn",
"microblaze_0_axi_periph/M00_ARESETN",
"microblaze_0_axi_periph/ARESETN"
]
}
},
"addressing": {
"/microblaze_0": {
"address_spaces": {
"Data": {
"range": "4G",
"width": "32",
"segments": {
"SEG_axi_gpio_0_Reg": {
"address_block": "/axi_gpio_0/S_AXI/Reg",
"offset": "0x40000000",
"range": "64K"
},
"SEG_dlmb_bram_if_cntlr_Mem": {
"address_block": "/microblaze_0_local_memory/dlmb_bram_if_cntlr/SLMB/Mem",
"offset": "0x00000000",
"range": "16K"
}
}
},
"Instruction": {
"range": "4G",
"width": "32",
"segments": {
"SEG_ilmb_bram_if_cntlr_Mem": {
"address_block": "/microblaze_0_local_memory/ilmb_bram_if_cntlr/SLMB/Mem",
"offset": "0x00000000",
"range": "16K"
}
}
}
}
}
}
}
}

2261
lib/bd/xilinx/PCIe_Test.bd Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,832 @@
{
"design": {
"design_info": {
"boundary_crc": "0xCC6CFA5306BD3ECB",
"device": "xc7z020clg400-2",
"name": "zynq_default",
"synth_flow_mode": "Hierarchical",
"tool_version": "2018.3",
"validated": "true"
},
"design_tree": {
"processing_system7_0": ""
},
"interface_ports": {
"DDR": {
"mode": "Master",
"vlnv": "xilinx.com:interface:ddrx_rtl:1.0",
"parameters": {
"AXI_ARBITRATION_SCHEME": {
"value": "TDM",
"value_src": "default"
},
"BURST_LENGTH": {
"value": "8",
"value_src": "default"
},
"CAN_DEBUG": {
"value": "false",
"value_src": "default"
},
"CAS_LATENCY": {
"value": "11",
"value_src": "default"
},
"CAS_WRITE_LATENCY": {
"value": "11",
"value_src": "default"
},
"CS_ENABLED": {
"value": "true",
"value_src": "default"
},
"DATA_MASK_ENABLED": {
"value": "true",
"value_src": "default"
},
"DATA_WIDTH": {
"value": "8",
"value_src": "default"
},
"MEMORY_TYPE": {
"value": "COMPONENTS",
"value_src": "default"
},
"MEM_ADDR_MAP": {
"value": "ROW_COLUMN_BANK",
"value_src": "default"
},
"SLOT": {
"value": "Single",
"value_src": "default"
},
"TIMEPERIOD_PS": {
"value": "1250",
"value_src": "default"
}
}
},
"FIXED_IO": {
"mode": "Master",
"vlnv": "xilinx.com:display_processing_system7:fixedio_rtl:1.0",
"parameters": {
"CAN_DEBUG": {
"value": "false",
"value_src": "default"
}
}
}
},
"components": {
"processing_system7_0": {
"vlnv": "xilinx.com:ip:processing_system7:5.5",
"xci_name": "zynq_default_processing_system7_0_1",
"parameters": {
"PCW_ACT_APU_PERIPHERAL_FREQMHZ": {
"value": "666.666687"
},
"PCW_ACT_CAN_PERIPHERAL_FREQMHZ": {
"value": "10.000000"
},
"PCW_ACT_DCI_PERIPHERAL_FREQMHZ": {
"value": "10.158730"
},
"PCW_ACT_ENET0_PERIPHERAL_FREQMHZ": {
"value": "125.000000"
},
"PCW_ACT_ENET1_PERIPHERAL_FREQMHZ": {
"value": "10.000000"
},
"PCW_ACT_FPGA0_PERIPHERAL_FREQMHZ": {
"value": "10.000000"
},
"PCW_ACT_FPGA1_PERIPHERAL_FREQMHZ": {
"value": "10.000000"
},
"PCW_ACT_FPGA2_PERIPHERAL_FREQMHZ": {
"value": "10.000000"
},
"PCW_ACT_FPGA3_PERIPHERAL_FREQMHZ": {
"value": "10.000000"
},
"PCW_ACT_PCAP_PERIPHERAL_FREQMHZ": {
"value": "200.000000"
},
"PCW_ACT_QSPI_PERIPHERAL_FREQMHZ": {
"value": "200.000000"
},
"PCW_ACT_SDIO_PERIPHERAL_FREQMHZ": {
"value": "100.000000"
},
"PCW_ACT_SMC_PERIPHERAL_FREQMHZ": {
"value": "10.000000"
},
"PCW_ACT_SPI_PERIPHERAL_FREQMHZ": {
"value": "10.000000"
},
"PCW_ACT_TPIU_PERIPHERAL_FREQMHZ": {
"value": "200.000000"
},
"PCW_ACT_TTC0_CLK0_PERIPHERAL_FREQMHZ": {
"value": "111.111115"
},
"PCW_ACT_TTC0_CLK1_PERIPHERAL_FREQMHZ": {
"value": "111.111115"
},
"PCW_ACT_TTC0_CLK2_PERIPHERAL_FREQMHZ": {
"value": "111.111115"
},
"PCW_ACT_TTC1_CLK0_PERIPHERAL_FREQMHZ": {
"value": "111.111115"
},
"PCW_ACT_TTC1_CLK1_PERIPHERAL_FREQMHZ": {
"value": "111.111115"
},
"PCW_ACT_TTC1_CLK2_PERIPHERAL_FREQMHZ": {
"value": "111.111115"
},
"PCW_ACT_UART_PERIPHERAL_FREQMHZ": {
"value": "100.000000"
},
"PCW_ACT_WDT_PERIPHERAL_FREQMHZ": {
"value": "111.111115"
},
"PCW_CLK0_FREQ": {
"value": "10000000"
},
"PCW_CLK1_FREQ": {
"value": "10000000"
},
"PCW_CLK2_FREQ": {
"value": "10000000"
},
"PCW_CLK3_FREQ": {
"value": "10000000"
},
"PCW_DDR_RAM_HIGHADDR": {
"value": "0x3FFFFFFF"
},
"PCW_ENET0_ENET0_IO": {
"value": "MIO 16 .. 27"
},
"PCW_ENET0_GRP_MDIO_ENABLE": {
"value": "1"
},
"PCW_ENET0_GRP_MDIO_IO": {
"value": "MIO 52 .. 53"
},
"PCW_ENET0_PERIPHERAL_CLKSRC": {
"value": "IO PLL"
},
"PCW_ENET0_PERIPHERAL_ENABLE": {
"value": "1"
},
"PCW_ENET0_PERIPHERAL_FREQMHZ": {
"value": "1000 Mbps"
},
"PCW_ENET0_RESET_ENABLE": {
"value": "0"
},
"PCW_ENET_RESET_ENABLE": {
"value": "1"
},
"PCW_ENET_RESET_SELECT": {
"value": "Share reset pin"
},
"PCW_EN_CLK0_PORT": {
"value": "0"
},
"PCW_EN_CLKTRIG0_PORT": {
"value": "0"
},
"PCW_EN_EMIO_ENET0": {
"value": "0"
},
"PCW_EN_EMIO_GPIO": {
"value": "0"
},
"PCW_EN_EMIO_UART0": {
"value": "0"
},
"PCW_EN_ENET0": {
"value": "1"
},
"PCW_EN_GPIO": {
"value": "1"
},
"PCW_EN_QSPI": {
"value": "1"
},
"PCW_EN_RST0_PORT": {
"value": "0"
},
"PCW_EN_SDIO0": {
"value": "1"
},
"PCW_EN_UART0": {
"value": "0"
},
"PCW_EN_UART1": {
"value": "1"
},
"PCW_EN_USB0": {
"value": "1"
},
"PCW_GPIO_EMIO_GPIO_ENABLE": {
"value": "0"
},
"PCW_GPIO_MIO_GPIO_ENABLE": {
"value": "1"
},
"PCW_GPIO_MIO_GPIO_IO": {
"value": "MIO"
},
"PCW_I2C_RESET_ENABLE": {
"value": "1"
},
"PCW_MIO_0_IOTYPE": {
"value": "LVCMOS 3.3V"
},
"PCW_MIO_0_PULLUP": {
"value": "enabled"
},
"PCW_MIO_0_SLEW": {
"value": "slow"
},
"PCW_MIO_10_IOTYPE": {
"value": "LVCMOS 3.3V"
},
"PCW_MIO_10_PULLUP": {
"value": "enabled"
},
"PCW_MIO_10_SLEW": {
"value": "slow"
},
"PCW_MIO_11_IOTYPE": {
"value": "LVCMOS 3.3V"
},
"PCW_MIO_11_PULLUP": {
"value": "enabled"
},
"PCW_MIO_11_SLEW": {
"value": "slow"
},
"PCW_MIO_12_IOTYPE": {
"value": "LVCMOS 3.3V"
},
"PCW_MIO_12_PULLUP": {
"value": "enabled"
},
"PCW_MIO_12_SLEW": {
"value": "slow"
},
"PCW_MIO_13_IOTYPE": {
"value": "LVCMOS 3.3V"
},
"PCW_MIO_13_PULLUP": {
"value": "enabled"
},
"PCW_MIO_13_SLEW": {
"value": "slow"
},
"PCW_MIO_14_IOTYPE": {
"value": "LVCMOS 3.3V"
},
"PCW_MIO_14_PULLUP": {
"value": "enabled"
},
"PCW_MIO_14_SLEW": {
"value": "slow"
},
"PCW_MIO_15_IOTYPE": {
"value": "LVCMOS 3.3V"
},
"PCW_MIO_15_PULLUP": {
"value": "enabled"
},
"PCW_MIO_15_SLEW": {
"value": "slow"
},
"PCW_MIO_16_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_16_PULLUP": {
"value": "enabled"
},
"PCW_MIO_16_SLEW": {
"value": "fast"
},
"PCW_MIO_17_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_17_PULLUP": {
"value": "enabled"
},
"PCW_MIO_17_SLEW": {
"value": "fast"
},
"PCW_MIO_18_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_18_PULLUP": {
"value": "enabled"
},
"PCW_MIO_18_SLEW": {
"value": "fast"
},
"PCW_MIO_19_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_19_PULLUP": {
"value": "enabled"
},
"PCW_MIO_19_SLEW": {
"value": "fast"
},
"PCW_MIO_1_IOTYPE": {
"value": "LVCMOS 3.3V"
},
"PCW_MIO_1_PULLUP": {
"value": "enabled"
},
"PCW_MIO_1_SLEW": {
"value": "fast"
},
"PCW_MIO_20_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_20_PULLUP": {
"value": "enabled"
},
"PCW_MIO_20_SLEW": {
"value": "fast"
},
"PCW_MIO_21_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_21_PULLUP": {
"value": "enabled"
},
"PCW_MIO_21_SLEW": {
"value": "fast"
},
"PCW_MIO_22_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_22_PULLUP": {
"value": "enabled"
},
"PCW_MIO_22_SLEW": {
"value": "fast"
},
"PCW_MIO_23_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_23_PULLUP": {
"value": "enabled"
},
"PCW_MIO_23_SLEW": {
"value": "fast"
},
"PCW_MIO_24_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_24_PULLUP": {
"value": "enabled"
},
"PCW_MIO_24_SLEW": {
"value": "fast"
},
"PCW_MIO_25_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_25_PULLUP": {
"value": "enabled"
},
"PCW_MIO_25_SLEW": {
"value": "fast"
},
"PCW_MIO_26_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_26_PULLUP": {
"value": "enabled"
},
"PCW_MIO_26_SLEW": {
"value": "fast"
},
"PCW_MIO_27_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_27_PULLUP": {
"value": "enabled"
},
"PCW_MIO_27_SLEW": {
"value": "fast"
},
"PCW_MIO_28_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_28_PULLUP": {
"value": "enabled"
},
"PCW_MIO_28_SLEW": {
"value": "fast"
},
"PCW_MIO_29_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_29_PULLUP": {
"value": "enabled"
},
"PCW_MIO_29_SLEW": {
"value": "fast"
},
"PCW_MIO_2_IOTYPE": {
"value": "LVCMOS 3.3V"
},
"PCW_MIO_2_SLEW": {
"value": "fast"
},
"PCW_MIO_30_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_30_PULLUP": {
"value": "enabled"
},
"PCW_MIO_30_SLEW": {
"value": "fast"
},
"PCW_MIO_31_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_31_PULLUP": {
"value": "enabled"
},
"PCW_MIO_31_SLEW": {
"value": "fast"
},
"PCW_MIO_32_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_32_PULLUP": {
"value": "enabled"
},
"PCW_MIO_32_SLEW": {
"value": "fast"
},
"PCW_MIO_33_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_33_PULLUP": {
"value": "enabled"
},
"PCW_MIO_33_SLEW": {
"value": "fast"
},
"PCW_MIO_34_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_34_PULLUP": {
"value": "enabled"
},
"PCW_MIO_34_SLEW": {
"value": "fast"
},
"PCW_MIO_35_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_35_PULLUP": {
"value": "enabled"
},
"PCW_MIO_35_SLEW": {
"value": "fast"
},
"PCW_MIO_36_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_36_PULLUP": {
"value": "enabled"
},
"PCW_MIO_36_SLEW": {
"value": "fast"
},
"PCW_MIO_37_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_37_PULLUP": {
"value": "enabled"
},
"PCW_MIO_37_SLEW": {
"value": "fast"
},
"PCW_MIO_38_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_38_PULLUP": {
"value": "enabled"
},
"PCW_MIO_38_SLEW": {
"value": "fast"
},
"PCW_MIO_39_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_39_PULLUP": {
"value": "enabled"
},
"PCW_MIO_39_SLEW": {
"value": "fast"
},
"PCW_MIO_3_IOTYPE": {
"value": "LVCMOS 3.3V"
},
"PCW_MIO_3_SLEW": {
"value": "fast"
},
"PCW_MIO_40_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_40_PULLUP": {
"value": "enabled"
},
"PCW_MIO_40_SLEW": {
"value": "fast"
},
"PCW_MIO_41_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_41_PULLUP": {
"value": "enabled"
},
"PCW_MIO_41_SLEW": {
"value": "fast"
},
"PCW_MIO_42_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_42_PULLUP": {
"value": "enabled"
},
"PCW_MIO_42_SLEW": {
"value": "fast"
},
"PCW_MIO_43_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_43_PULLUP": {
"value": "enabled"
},
"PCW_MIO_43_SLEW": {
"value": "fast"
},
"PCW_MIO_44_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_44_PULLUP": {
"value": "enabled"
},
"PCW_MIO_44_SLEW": {
"value": "fast"
},
"PCW_MIO_45_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_45_PULLUP": {
"value": "enabled"
},
"PCW_MIO_45_SLEW": {
"value": "fast"
},
"PCW_MIO_46_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_46_PULLUP": {
"value": "enabled"
},
"PCW_MIO_46_SLEW": {
"value": "slow"
},
"PCW_MIO_47_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_47_PULLUP": {
"value": "enabled"
},
"PCW_MIO_47_SLEW": {
"value": "slow"
},
"PCW_MIO_48_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_48_PULLUP": {
"value": "enabled"
},
"PCW_MIO_48_SLEW": {
"value": "slow"
},
"PCW_MIO_49_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_49_PULLUP": {
"value": "enabled"
},
"PCW_MIO_49_SLEW": {
"value": "slow"
},
"PCW_MIO_4_IOTYPE": {
"value": "LVCMOS 3.3V"
},
"PCW_MIO_4_SLEW": {
"value": "fast"
},
"PCW_MIO_50_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_50_PULLUP": {
"value": "enabled"
},
"PCW_MIO_50_SLEW": {
"value": "slow"
},
"PCW_MIO_51_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_51_PULLUP": {
"value": "enabled"
},
"PCW_MIO_51_SLEW": {
"value": "slow"
},
"PCW_MIO_52_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_52_PULLUP": {
"value": "enabled"
},
"PCW_MIO_52_SLEW": {
"value": "fast"
},
"PCW_MIO_53_IOTYPE": {
"value": "LVCMOS 1.8V"
},
"PCW_MIO_53_PULLUP": {
"value": "enabled"
},
"PCW_MIO_53_SLEW": {
"value": "fast"
},
"PCW_MIO_5_IOTYPE": {
"value": "LVCMOS 3.3V"
},
"PCW_MIO_5_SLEW": {
"value": "fast"
},
"PCW_MIO_6_IOTYPE": {
"value": "LVCMOS 3.3V"
},
"PCW_MIO_6_SLEW": {
"value": "fast"
},
"PCW_MIO_7_IOTYPE": {
"value": "LVCMOS 3.3V"
},
"PCW_MIO_7_SLEW": {
"value": "slow"
},
"PCW_MIO_8_IOTYPE": {
"value": "LVCMOS 3.3V"
},
"PCW_MIO_8_SLEW": {
"value": "slow"
},
"PCW_MIO_9_IOTYPE": {
"value": "LVCMOS 3.3V"
},
"PCW_MIO_9_PULLUP": {
"value": "enabled"
},
"PCW_MIO_9_SLEW": {
"value": "slow"
},
"PCW_MIO_TREE_PERIPHERALS": {
"value": "GPIO#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#GPIO#Quad SPI Flash#Quad SPI Flash#GPIO#GPIO#GPIO#GPIO#GPIO#GPIO#GPIO#GPIO#GPIO#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#SD 0#SD 0#SD 0#SD 0#SD 0#SD 0#USB Reset#GPIO#UART 1#UART 1#GPIO#GPIO#Enet 0#Enet 0"
},
"PCW_MIO_TREE_SIGNALS": {
"value": "gpio[0]#qspi0_ss_b#qspi0_io[0]#qspi0_io[1]#gpio[4]#qspi0_io[3]/HOLD_B#qspi0_sclk#gpio[7]#gpio[8]#gpio[9]#gpio[10]#gpio[11]#gpio[12]#gpio[13]#gpio[14]#gpio[15]#tx_clk#txd[0]#txd[1]#txd[2]#txd[3]#tx_ctl#rx_clk#rxd[0]#rxd[1]#rxd[2]#rxd[3]#rx_ctl#data[4]#dir#stp#nxt#data[0]#data[1]#data[2]#data[3]#clk#data[5]#data[6]#data[7]#clk#cmd#data[0]#data[1]#data[2]#data[3]#reset#gpio[47]#tx#rx#gpio[50]#gpio[51]#mdc#mdio"
},
"PCW_PRESET_BANK1_VOLTAGE": {
"value": "LVCMOS 1.8V"
},
"PCW_QSPI_GRP_FBCLK_ENABLE": {
"value": "0"
},
"PCW_QSPI_GRP_IO1_ENABLE": {
"value": "0"
},
"PCW_QSPI_GRP_SINGLE_SS_ENABLE": {
"value": "1"
},
"PCW_QSPI_GRP_SINGLE_SS_IO": {
"value": "MIO 1 .. 6"
},
"PCW_QSPI_GRP_SS1_ENABLE": {
"value": "0"
},
"PCW_QSPI_PERIPHERAL_ENABLE": {
"value": "1"
},
"PCW_QSPI_PERIPHERAL_FREQMHZ": {
"value": "200"
},
"PCW_QSPI_QSPI_IO": {
"value": "MIO 1 .. 6"
},
"PCW_SD0_GRP_CD_ENABLE": {
"value": "0"
},
"PCW_SD0_GRP_POW_ENABLE": {
"value": "0"
},
"PCW_SD0_GRP_WP_ENABLE": {
"value": "0"
},
"PCW_SD0_PERIPHERAL_ENABLE": {
"value": "1"
},
"PCW_SD0_SD0_IO": {
"value": "MIO 40 .. 45"
},
"PCW_SDIO_PERIPHERAL_FREQMHZ": {
"value": "100"
},
"PCW_SDIO_PERIPHERAL_VALID": {
"value": "1"
},
"PCW_SINGLE_QSPI_DATA_MODE": {
"value": "x1"
},
"PCW_UART0_PERIPHERAL_ENABLE": {
"value": "0"
},
"PCW_UART1_GRP_FULL_ENABLE": {
"value": "0"
},
"PCW_UART1_PERIPHERAL_ENABLE": {
"value": "1"
},
"PCW_UART1_UART1_IO": {
"value": "MIO 48 .. 49"
},
"PCW_UART_PERIPHERAL_FREQMHZ": {
"value": "100"
},
"PCW_UART_PERIPHERAL_VALID": {
"value": "1"
},
"PCW_UIPARAM_ACT_DDR_FREQ_MHZ": {
"value": "533.333374"
},
"PCW_UIPARAM_DDR_PARTNO": {
"value": "MT41J256M16 RE-125"
},
"PCW_USB0_PERIPHERAL_ENABLE": {
"value": "1"
},
"PCW_USB0_RESET_ENABLE": {
"value": "1"
},
"PCW_USB0_RESET_IO": {
"value": "MIO 46"
},
"PCW_USB0_USB0_IO": {
"value": "MIO 28 .. 39"
},
"PCW_USB_RESET_ENABLE": {
"value": "1"
},
"PCW_USB_RESET_SELECT": {
"value": "Share reset pin"
},
"PCW_USE_M_AXI_GP0": {
"value": "0"
}
}
}
},
"interface_nets": {
"processing_system7_0_FIXED_IO": {
"interface_ports": [
"FIXED_IO",
"processing_system7_0/FIXED_IO"
]
},
"processing_system7_0_DDR": {
"interface_ports": [
"DDR",
"processing_system7_0/DDR"
]
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

View File

@ -0,0 +1,33 @@
module AGC(
input wire clk,
input wire rst,
input wire [7:0] a_coef,
input wire [15:0] reference,
input wire signed [15:0] x_in,
output wire signed [15:0] y_out
);
wire [31:0] x_mod;
wire [31:0] ref_rms;
wire signed [8:0] a_coef_s;
wire signed [32:0] tmp_level;
wire signed [32:0] feedback_level;
reg signed [32:0] zreg;
assign ref_rms = (reference[15:1] * reference[15:1]);
assign a_coef_s = { 1'b0, a_coef};
assign x_mod = (y_out * y_out);
assign tmp_level = ($signed(ref_rms - x_mod))>>>18;
assign feedback_level = (tmp_level * a_coef_s) >>> 8;
always @(posedge clk or negedge rst) begin
if (!rst)
zreg <= 'h0;
else
zreg <= zreg + feedback_level;
end
assign y_out = (zreg * x_in) >>>16;
endmodule

View File

@ -0,0 +1,72 @@
module Demodulate #(
parameter PHASE_WIDTH = 32,
parameter Fiter_WIDTH = 38,
parameter INPUT_WIDTH = 8,
parameter OUTPUT_WIDTH = 12
) (
input clk,
input RST,
input [15:0] FACTOR,
input [PHASE_WIDTH-1:0] Fre_word,
input [INPUT_WIDTH-1:0] wave_in,
output [OUTPUT_WIDTH-1:0] FM_Demodule_OUT,
output [OUTPUT_WIDTH-1:0] PM_Demodule_OUT,
output [OUTPUT_WIDTH-1:0] AM_Demodule_OUT
);
// IQ_MIXED Outputs
wire clk_out;
wire [OUTPUT_WIDTH - 1 : 0] I_OUT;
wire [OUTPUT_WIDTH - 1 : 0] Q_OUT;
/*
数字下变频处理模块
*/
IQ_MIXED #(
.LO_WIDTH ( 12 ),
.PHASE_WIDTH ( PHASE_WIDTH ),
.Fiter_WIDTH ( Fiter_WIDTH ),
.INPUT_WIDTH ( INPUT_WIDTH ),
.OUTPUT_WIDTH ( OUTPUT_WIDTH ))
u_IQ_MIXED (
.clk ( clk ),
.clk_out ( clk_out ),
.RST ( RST ),
.FACTOR ( FACTOR ),
.Fre_word ( Fre_word ),
.wave_in ( wave_in ),
.I_OUT ( I_OUT ),
.Q_OUT ( Q_OUT )
);
wire [OUTPUT_WIDTH-1:0] Y_diff;
Cordic # (
.XY_BITS(OUTPUT_WIDTH),
.PH_BITS(OUTPUT_WIDTH), //1~32
.ITERATIONS(16), //1~32
.CORDIC_STYLE("VECTOR")) //ROTATE //VECTOR
Demodulate_Gen_u (
.clk(clk_out),
.RST(RST),
.x_i(I_OUT),
.y_i(Q_OUT),
.phase_in(0),
.valid_in(~RST),
.x_o(AM_Demodule_OUT),
.y_o(Y_diff),
.phase_out(PM_Demodule_OUT)
);
reg [OUTPUT_WIDTH-1:0] PM_Demodule_OUT_r = 0;
always @(posedge clk_out) begin
PM_Demodule_OUT_r <= PM_Demodule_OUT;
end
assign FM_Demodule_OUT = $signed(PM_Demodule_OUT) - $signed(PM_Demodule_OUT_r);
endmodule

View File

@ -0,0 +1,92 @@
module IQ_MIXED #(
//LO_OUTPUR_parameter
parameter LO_WIDTH = 12,
parameter PHASE_WIDTH = 32,
//CIC_Filter_parameter
parameter Fiter_WIDTH = 38,
//IQ_MIXED_parameter
parameter INPUT_WIDTH = 12,
parameter OUTPUT_WIDTH = 12
) (
input clk,
output clk_out,
input RST,
input [15:0] FACTOR,
input [PHASE_WIDTH - 1 : 0] Fre_word,
input [INPUT_WIDTH - 1 : 0] wave_in,
output [OUTPUT_WIDTH - 1 : 0] I_OUT,
output [OUTPUT_WIDTH - 1 : 0] Q_OUT
);
wire [LO_WIDTH-1:0] cos_wave;
wire [LO_WIDTH-1:0] sin_wave;
wire [PHASE_WIDTH-1:0] pha_diff;
Cordic # (
.XY_BITS(LO_WIDTH),
.PH_BITS(PHASE_WIDTH), //1~32
.ITERATIONS(16), //1~32
.CORDIC_STYLE("ROTATE"), //ROTATE //VECTOR
.PHASE_ACC("ON") //ON //OFF
) IQ_Gen_u (
.clk(clk),
.RST(RST),
.x_i(0),
.y_i(0),
.phase_in(Fre_word),
.valid_in(~RST),
.x_o(cos_wave),
.y_o(sin_wave),
.phase_out(pha_diff)
);
wire signed [Fiter_WIDTH - 1 : 0] I_SIG;
wire signed [Fiter_WIDTH - 1 : 0] Q_SIG;
reg signed [INPUT_WIDTH + LO_WIDTH - 1 : 0] I_SIG_r = 0;
reg signed [INPUT_WIDTH + LO_WIDTH - 1 : 0] Q_SIG_r = 0;
always @(posedge clk) begin
if (RST) begin
I_SIG_r <= 24'd0;
Q_SIG_r <= 24'd0;
end
else begin
I_SIG_r <= $signed(wave_in) * $signed(cos_wave);
Q_SIG_r <= $signed(wave_in) * $signed(sin_wave);
end
end
assign I_SIG = I_SIG_r[INPUT_WIDTH + LO_WIDTH - 1 : INPUT_WIDTH + LO_WIDTH - 12];
assign Q_SIG = Q_SIG_r[INPUT_WIDTH + LO_WIDTH - 1 : INPUT_WIDTH + LO_WIDTH - 12];
wire [Fiter_WIDTH-1:0] Fiter_wave_I;
CIC_DOWN_S3#(
.INPUT_WIDTH(12),
.OUTPUT_WIDTH(Fiter_WIDTH))
Fiter_I (
.clk(clk),
.clk_enable(1'd1),
.reset(RST),
.FACTOR(FACTOR),
.filter_in(I_SIG),
.filter_out(Fiter_wave_I)
);
assign I_OUT = Fiter_wave_I[Fiter_WIDTH - 1 : Fiter_WIDTH - OUTPUT_WIDTH];
wire [Fiter_WIDTH-1:0] Fiter_wave_Q;
CIC_DOWN_S3#(
.INPUT_WIDTH(12),
.OUTPUT_WIDTH(Fiter_WIDTH)
) Fiter_Q(
.clk(clk),
.clk_enable(1'd1),
.reset(RST),
.FACTOR(FACTOR),
.filter_in(Q_SIG),
.filter_out(Fiter_wave_Q),
.ce_out(clk_out)
);
assign Q_OUT = Fiter_wave_Q[Fiter_WIDTH - 1 : Fiter_WIDTH - OUTPUT_WIDTH];
endmodule

View File

@ -0,0 +1,32 @@
`timescale 1ns / 1ps
module Loop_filter (
input clk_sys,
input rst_n,
input signed [27:0] Xdin,
output signed [27:0] Ydout
);
parameter k1 = 12498;
parameter k2 = 4430400;
reg [2:0] cnt;
reg signed [27:0] Ydin_1;
reg signed [27:0] Ydout_buf;
always@(posedge clk_sys) begin
if(!rst_n)
cnt <= 3'd0;
else
cnt <= cnt + 3'd1;
end
always@(posedge clk_sys) begin
if(!rst_n) begin
Ydin_1 <= 28'd0;
Ydout_buf <= 28'd0;
end
else if(cnt == 3'd3)
Ydin_1 = Ydin_1 + Xdin/k1;
else if(cnt == 3'd4)
Ydout_buf <= Ydin_1 + Xdin/k2;
end
assign Ydout = Ydout_buf;
endmodule

View File

@ -0,0 +1,17 @@
`timescale 1ns / 1ps
module manchester (
input clk,
input sig_in,
output man_sig_out
);
reg ck = 0;
reg ck_r = 0;
always @(posedge clk) begin
ck <= ck_r;
ck <= ~ ck;
end
assign man_sig_out = ck ^ sig_in;
endmodule

View File

@ -0,0 +1,25 @@
`timescale 1ns / 1ps
module mseq #(
parameter W = 4'd4,
parameter POLY = 5'b10011
) (
input clk,
input rst_n,
output mseq_out
);
reg [W-1:0] sreg = 8'b11111111;
assign mseq_out = sreg[0];
always@(posedge clk or posedge rst_n) begin
if(~rst_n)
sreg <= 1'b1;
else begin
if(mseq_out)
sreg <= (sreg >> 1) ^ (POLY >> 1);
else
sreg <= sreg >> 1;
end
end
endmodule

View File

@ -0,0 +1,383 @@
`timescale 1ns / 1ps
module AM_Modulate #(
parameter INPUT_WIDTH = 12,
parameter PHASE_WIDTH = 32,
parameter DEEP_WIDTH = 16,
parameter OUTPUT_WIDTH = 12
) (
input clk,
input RST,
input [INPUT_WIDTH - 1 : 0] wave_in,
input [PHASE_WIDTH - 1 : 0] center_fre, //(fre*2^PHASE_WIDTH)/Fc
input [DEEP_WIDTH - 1 : 0] modulate_deep,//(2^DEEP_WIDTH-1)*percent
output [OUTPUT_WIDTH - 1 : 0] AM_wave
);
localparam [INPUT_WIDTH - 1 : 0] DC_Value = 2**(INPUT_WIDTH-1);
reg [INPUT_WIDTH - 1 : 0] wave_in_r = 0;
always @(posedge clk) begin
if (RST) begin
wave_in_r <= 0;
end
else begin
wave_in_r <= wave_in;
end
end
reg signed [INPUT_WIDTH + DEEP_WIDTH : 0] data_r0 = 0;
always @(posedge clk) begin
if (RST) begin
data_r0 <= 0;
end
else begin
data_r0 <= $signed(wave_in_r) * $signed({1'b0,modulate_deep});
end
end
reg signed [INPUT_WIDTH - 1 : 0] data_r1 = 0;
always @(posedge clk) begin
if (RST) begin
data_r1 <= 0;
end
else begin
data_r1 <= data_r0[INPUT_WIDTH + DEEP_WIDTH - 1 : DEEP_WIDTH];
end
end
reg [INPUT_WIDTH : 0] data_r2 = 0;
always @(posedge clk) begin
if (RST) begin
data_r2 <= 0;
end
else begin
data_r2 <= $signed(data_r1) + $signed({1'b0,DC_Value});
end
end
reg [PHASE_WIDTH - 1 : 0] addr_r0 = 0;
always @(posedge clk) begin
addr_r0 <= addr_r0 + center_fre;
end
reg [9:0] addr_r1 = 0;
always @(posedge clk) begin
addr_r1 <= addr_r0[PHASE_WIDTH - 1 : PHASE_WIDTH - 10];
end
reg [7:0] addr = 0;
always @(*) begin
case (addr_r1[9:8])
2'b00 : begin addr <= addr_r1[7:0]; end
2'b01 : begin addr <= addr_r1[7:0] ^ 8'b1111_1111; end
2'b10 : begin addr <= addr_r1[7:0]; end
2'b11 : begin addr <= addr_r1[7:0] ^ 8'b1111_1111; end
default : begin addr <= 8'd0; end
endcase
end
reg signed [13:0] wave_out_r = 0;
always @(*) begin
case (addr)
8'd0 : begin wave_out_r <= 0; end
8'd1 : begin wave_out_r <= 50; end
8'd2 : begin wave_out_r <= 101; end
8'd3 : begin wave_out_r <= 151; end
8'd4 : begin wave_out_r <= 201; end
8'd5 : begin wave_out_r <= 252; end
8'd6 : begin wave_out_r <= 302; end
8'd7 : begin wave_out_r <= 352; end
8'd8 : begin wave_out_r <= 402; end
8'd9 : begin wave_out_r <= 453; end
8'd10 : begin wave_out_r <= 503; end
8'd11 : begin wave_out_r <= 553; end
8'd12 : begin wave_out_r <= 603; end
8'd13 : begin wave_out_r <= 653; end
8'd14 : begin wave_out_r <= 703; end
8'd15 : begin wave_out_r <= 754; end
8'd16 : begin wave_out_r <= 804; end
8'd17 : begin wave_out_r <= 854; end
8'd18 : begin wave_out_r <= 904; end
8'd19 : begin wave_out_r <= 954; end
8'd20 : begin wave_out_r <= 1004; end
8'd21 : begin wave_out_r <= 1054; end
8'd22 : begin wave_out_r <= 1103; end
8'd23 : begin wave_out_r <= 1153; end
8'd24 : begin wave_out_r <= 1203; end
8'd25 : begin wave_out_r <= 1253; end
8'd26 : begin wave_out_r <= 1302; end
8'd27 : begin wave_out_r <= 1352; end
8'd28 : begin wave_out_r <= 1402; end
8'd29 : begin wave_out_r <= 1451; end
8'd30 : begin wave_out_r <= 1501; end
8'd31 : begin wave_out_r <= 1550; end
8'd32 : begin wave_out_r <= 1600; end
8'd33 : begin wave_out_r <= 1649; end
8'd34 : begin wave_out_r <= 1698; end
8'd35 : begin wave_out_r <= 1747; end
8'd36 : begin wave_out_r <= 1796; end
8'd37 : begin wave_out_r <= 1845; end
8'd38 : begin wave_out_r <= 1894; end
8'd39 : begin wave_out_r <= 1943; end
8'd40 : begin wave_out_r <= 1992; end
8'd41 : begin wave_out_r <= 2041; end
8'd42 : begin wave_out_r <= 2090; end
8'd43 : begin wave_out_r <= 2138; end
8'd44 : begin wave_out_r <= 2187; end
8'd45 : begin wave_out_r <= 2235; end
8'd46 : begin wave_out_r <= 2284; end
8'd47 : begin wave_out_r <= 2332; end
8'd48 : begin wave_out_r <= 2380; end
8'd49 : begin wave_out_r <= 2428; end
8'd50 : begin wave_out_r <= 2476; end
8'd51 : begin wave_out_r <= 2524; end
8'd52 : begin wave_out_r <= 2572; end
8'd53 : begin wave_out_r <= 2620; end
8'd54 : begin wave_out_r <= 2667; end
8'd55 : begin wave_out_r <= 2715; end
8'd56 : begin wave_out_r <= 2762; end
8'd57 : begin wave_out_r <= 2809; end
8'd58 : begin wave_out_r <= 2857; end
8'd59 : begin wave_out_r <= 2904; end
8'd60 : begin wave_out_r <= 2951; end
8'd61 : begin wave_out_r <= 2998; end
8'd62 : begin wave_out_r <= 3044; end
8'd63 : begin wave_out_r <= 3091; end
8'd64 : begin wave_out_r <= 3137; end
8'd65 : begin wave_out_r <= 3184; end
8'd66 : begin wave_out_r <= 3230; end
8'd67 : begin wave_out_r <= 3276; end
8'd68 : begin wave_out_r <= 3322; end
8'd69 : begin wave_out_r <= 3368; end
8'd70 : begin wave_out_r <= 3414; end
8'd71 : begin wave_out_r <= 3460; end
8'd72 : begin wave_out_r <= 3505; end
8'd73 : begin wave_out_r <= 3551; end
8'd74 : begin wave_out_r <= 3596; end
8'd75 : begin wave_out_r <= 3641; end
8'd76 : begin wave_out_r <= 3686; end
8'd77 : begin wave_out_r <= 3731; end
8'd78 : begin wave_out_r <= 3776; end
8'd79 : begin wave_out_r <= 3820; end
8'd80 : begin wave_out_r <= 3865; end
8'd81 : begin wave_out_r <= 3909; end
8'd82 : begin wave_out_r <= 3953; end
8'd83 : begin wave_out_r <= 3997; end
8'd84 : begin wave_out_r <= 4041; end
8'd85 : begin wave_out_r <= 4085; end
8'd86 : begin wave_out_r <= 4128; end
8'd87 : begin wave_out_r <= 4172; end
8'd88 : begin wave_out_r <= 4215; end
8'd89 : begin wave_out_r <= 4258; end
8'd90 : begin wave_out_r <= 4301; end
8'd91 : begin wave_out_r <= 4343; end
8'd92 : begin wave_out_r <= 4386; end
8'd93 : begin wave_out_r <= 4428; end
8'd94 : begin wave_out_r <= 4471; end
8'd95 : begin wave_out_r <= 4513; end
8'd96 : begin wave_out_r <= 4555; end
8'd97 : begin wave_out_r <= 4596; end
8'd98 : begin wave_out_r <= 4638; end
8'd99 : begin wave_out_r <= 4679; end
8'd100 : begin wave_out_r <= 4720; end
8'd101 : begin wave_out_r <= 4761; end
8'd102 : begin wave_out_r <= 4802; end
8'd103 : begin wave_out_r <= 4843; end
8'd104 : begin wave_out_r <= 4883; end
8'd105 : begin wave_out_r <= 4924; end
8'd106 : begin wave_out_r <= 4964; end
8'd107 : begin wave_out_r <= 5004; end
8'd108 : begin wave_out_r <= 5044; end
8'd109 : begin wave_out_r <= 5083; end
8'd110 : begin wave_out_r <= 5122; end
8'd111 : begin wave_out_r <= 5162; end
8'd112 : begin wave_out_r <= 5201; end
8'd113 : begin wave_out_r <= 5239; end
8'd114 : begin wave_out_r <= 5278; end
8'd115 : begin wave_out_r <= 5316; end
8'd116 : begin wave_out_r <= 5354; end
8'd117 : begin wave_out_r <= 5392; end
8'd118 : begin wave_out_r <= 5430; end
8'd119 : begin wave_out_r <= 5468; end
8'd120 : begin wave_out_r <= 5505; end
8'd121 : begin wave_out_r <= 5542; end
8'd122 : begin wave_out_r <= 5579; end
8'd123 : begin wave_out_r <= 5616; end
8'd124 : begin wave_out_r <= 5652; end
8'd125 : begin wave_out_r <= 5689; end
8'd126 : begin wave_out_r <= 5725; end
8'd127 : begin wave_out_r <= 5761; end
8'd128 : begin wave_out_r <= 5796; end
8'd129 : begin wave_out_r <= 5832; end
8'd130 : begin wave_out_r <= 5867; end
8'd131 : begin wave_out_r <= 5902; end
8'd132 : begin wave_out_r <= 5937; end
8'd133 : begin wave_out_r <= 5971; end
8'd134 : begin wave_out_r <= 6006; end
8'd135 : begin wave_out_r <= 6040; end
8'd136 : begin wave_out_r <= 6074; end
8'd137 : begin wave_out_r <= 6107; end
8'd138 : begin wave_out_r <= 6141; end
8'd139 : begin wave_out_r <= 6174; end
8'd140 : begin wave_out_r <= 6207; end
8'd141 : begin wave_out_r <= 6239; end
8'd142 : begin wave_out_r <= 6272; end
8'd143 : begin wave_out_r <= 6304; end
8'd144 : begin wave_out_r <= 6336; end
8'd145 : begin wave_out_r <= 6368; end
8'd146 : begin wave_out_r <= 6399; end
8'd147 : begin wave_out_r <= 6431; end
8'd148 : begin wave_out_r <= 6462; end
8'd149 : begin wave_out_r <= 6493; end
8'd150 : begin wave_out_r <= 6523; end
8'd151 : begin wave_out_r <= 6553; end
8'd152 : begin wave_out_r <= 6584; end
8'd153 : begin wave_out_r <= 6613; end
8'd154 : begin wave_out_r <= 6643; end
8'd155 : begin wave_out_r <= 6672; end
8'd156 : begin wave_out_r <= 6701; end
8'd157 : begin wave_out_r <= 6730; end
8'd158 : begin wave_out_r <= 6759; end
8'd159 : begin wave_out_r <= 6787; end
8'd160 : begin wave_out_r <= 6815; end
8'd161 : begin wave_out_r <= 6843; end
8'd162 : begin wave_out_r <= 6870; end
8'd163 : begin wave_out_r <= 6897; end
8'd164 : begin wave_out_r <= 6925; end
8'd165 : begin wave_out_r <= 6951; end
8'd166 : begin wave_out_r <= 6978; end
8'd167 : begin wave_out_r <= 7004; end
8'd168 : begin wave_out_r <= 7030; end
8'd169 : begin wave_out_r <= 7056; end
8'd170 : begin wave_out_r <= 7081; end
8'd171 : begin wave_out_r <= 7106; end
8'd172 : begin wave_out_r <= 7131; end
8'd173 : begin wave_out_r <= 7156; end
8'd174 : begin wave_out_r <= 7180; end
8'd175 : begin wave_out_r <= 7204; end
8'd176 : begin wave_out_r <= 7228; end
8'd177 : begin wave_out_r <= 7251; end
8'd178 : begin wave_out_r <= 7275; end
8'd179 : begin wave_out_r <= 7298; end
8'd180 : begin wave_out_r <= 7320; end
8'd181 : begin wave_out_r <= 7343; end
8'd182 : begin wave_out_r <= 7365; end
8'd183 : begin wave_out_r <= 7387; end
8'd184 : begin wave_out_r <= 7408; end
8'd185 : begin wave_out_r <= 7430; end
8'd186 : begin wave_out_r <= 7451; end
8'd187 : begin wave_out_r <= 7472; end
8'd188 : begin wave_out_r <= 7492; end
8'd189 : begin wave_out_r <= 7512; end
8'd190 : begin wave_out_r <= 7532; end
8'd191 : begin wave_out_r <= 7552; end
8'd192 : begin wave_out_r <= 7571; end
8'd193 : begin wave_out_r <= 7590; end
8'd194 : begin wave_out_r <= 7609; end
8'd195 : begin wave_out_r <= 7627; end
8'd196 : begin wave_out_r <= 7646; end
8'd197 : begin wave_out_r <= 7664; end
8'd198 : begin wave_out_r <= 7681; end
8'd199 : begin wave_out_r <= 7698; end
8'd200 : begin wave_out_r <= 7715; end
8'd201 : begin wave_out_r <= 7732; end
8'd202 : begin wave_out_r <= 7749; end
8'd203 : begin wave_out_r <= 7765; end
8'd204 : begin wave_out_r <= 7781; end
8'd205 : begin wave_out_r <= 7796; end
8'd206 : begin wave_out_r <= 7812; end
8'd207 : begin wave_out_r <= 7827; end
8'd208 : begin wave_out_r <= 7841; end
8'd209 : begin wave_out_r <= 7856; end
8'd210 : begin wave_out_r <= 7870; end
8'd211 : begin wave_out_r <= 7884; end
8'd212 : begin wave_out_r <= 7897; end
8'd213 : begin wave_out_r <= 7910; end
8'd214 : begin wave_out_r <= 7923; end
8'd215 : begin wave_out_r <= 7936; end
8'd216 : begin wave_out_r <= 7948; end
8'd217 : begin wave_out_r <= 7960; end
8'd218 : begin wave_out_r <= 7972; end
8'd219 : begin wave_out_r <= 7983; end
8'd220 : begin wave_out_r <= 7994; end
8'd221 : begin wave_out_r <= 8005; end
8'd222 : begin wave_out_r <= 8016; end
8'd223 : begin wave_out_r <= 8026; end
8'd224 : begin wave_out_r <= 8036; end
8'd225 : begin wave_out_r <= 8045; end
8'd226 : begin wave_out_r <= 8055; end
8'd227 : begin wave_out_r <= 8064; end
8'd228 : begin wave_out_r <= 8072; end
8'd229 : begin wave_out_r <= 8081; end
8'd230 : begin wave_out_r <= 8089; end
8'd231 : begin wave_out_r <= 8097; end
8'd232 : begin wave_out_r <= 8104; end
8'd233 : begin wave_out_r <= 8111; end
8'd234 : begin wave_out_r <= 8118; end
8'd235 : begin wave_out_r <= 8125; end
8'd236 : begin wave_out_r <= 8131; end
8'd237 : begin wave_out_r <= 8137; end
8'd238 : begin wave_out_r <= 8142; end
8'd239 : begin wave_out_r <= 8148; end
8'd240 : begin wave_out_r <= 8153; end
8'd241 : begin wave_out_r <= 8157; end
8'd242 : begin wave_out_r <= 8162; end
8'd243 : begin wave_out_r <= 8166; end
8'd244 : begin wave_out_r <= 8170; end
8'd245 : begin wave_out_r <= 8173; end
8'd246 : begin wave_out_r <= 8176; end
8'd247 : begin wave_out_r <= 8179; end
8'd248 : begin wave_out_r <= 8182; end
8'd249 : begin wave_out_r <= 8184; end
8'd250 : begin wave_out_r <= 8186; end
8'd251 : begin wave_out_r <= 8188; end
8'd252 : begin wave_out_r <= 8189; end
8'd253 : begin wave_out_r <= 8190; end
8'd254 : begin wave_out_r <= 8191; end
8'd255 : begin wave_out_r <= 8191; end
default : begin wave_out_r <= 0; end
endcase
end
reg signed [13 : 0] AM_Carry_r0 = 0;
always @(*) begin
case (addr_r1[9])
1'b0 : begin AM_Carry_r0 <= wave_out_r[13 : 0]; end
1'b1 : begin AM_Carry_r0 <= - wave_out_r[13 : 0]; end
default : begin AM_Carry_r0 <= 14'd0; end
endcase
end
reg signed [13 : 0] AM_Carry_r1 = 0;
always @(posedge clk) begin
if (RST) begin
AM_Carry_r1 <= 0;
end
else begin
AM_Carry_r1 <= AM_Carry_r0;
end
end
reg signed [INPUT_WIDTH + 14 : 0] AM_wave_r0 = 0;
always @(posedge clk) begin
if (RST) begin
AM_wave_r0 <= 0;
end
else begin
AM_wave_r0 <= $signed(AM_Carry_r1) * $signed({1'b0,data_r2});
end
end
reg signed [OUTPUT_WIDTH - 1 : 0] AM_wave_r1 = 0;
always @(posedge clk) begin
if (RST) begin
AM_wave_r1 <= 0;
end
else begin
AM_wave_r1 <= AM_wave_r0[INPUT_WIDTH + 13 : INPUT_WIDTH + 14 - OUTPUT_WIDTH];
end
end
assign AM_wave = AM_wave_r1;
endmodule

View File

@ -0,0 +1,370 @@
`timescale 1ns / 1ps
module FM_Modulate #(
parameter INPUT_WIDTH = 12,
parameter PHASE_WIDTH = 32,
parameter OUTPUT_WIDTH = 12
) (
input clk,
input RST,
input [INPUT_WIDTH - 1 : 0] wave_in,
input [PHASE_WIDTH - INPUT_WIDTH - 1 : 0] move_fre, //(fre*2^(PHASE_WIDTH-INPUT_WIDTH))/clk/1000000
input [PHASE_WIDTH - 1 : 0] center_fre, //(fre*2^PHASE_WIDTH)/clk/1000000
output [OUTPUT_WIDTH - 1 : 0] FM_wave
);
reg [INPUT_WIDTH - 1 : 0] wave_in_r = 0;
always @(posedge clk) begin
if (RST) begin
wave_in_r <= 0;
end
else begin
wave_in_r <= wave_in;
end
end
reg signed [PHASE_WIDTH : 0] data_r0 = 0;
always @(posedge clk) begin
if (RST) begin
data_r0 <= 0;
end
else begin
data_r0 <= $signed(wave_in_r) * $signed({1'd0,move_fre});
end
end
reg signed [PHASE_WIDTH - 1 : 0] data_r1 = 0;
always @(posedge clk) begin
if (RST) begin
data_r1 <= 0;
end
else begin
data_r1 <= data_r0[PHASE_WIDTH - 1 : 0];
end
end
reg signed [PHASE_WIDTH : 0] data_r2 = 0;
always @(posedge clk) begin
if (RST) begin
data_r2 <= 0;
end
else begin
data_r2 <= $signed(data_r1) + $signed({1'd0,center_fre});
end
end
reg [PHASE_WIDTH - 1 : 0] Fre_word = 0;
always @(posedge clk) begin
if (RST) begin
Fre_word <= 0;
end
else begin
Fre_word <= data_r2[PHASE_WIDTH - 1 : 0];
end
end
reg [PHASE_WIDTH - 1 : 0] addr_r0 = 0;
always @(posedge clk) begin
addr_r0 <= addr_r0 + Fre_word;
end
reg [9:0] addr_r1 = 0;
always @(posedge clk) begin
addr_r1 <= addr_r0[PHASE_WIDTH - 1 : PHASE_WIDTH - 10];
end
reg [7:0] addr = 0;
always @(*) begin
case (addr_r1[9:8])
2'b00 : begin addr <= addr_r1[7:0]; end
2'b01 : begin addr <= addr_r1[7:0] ^ 8'b1111_1111; end
2'b10 : begin addr <= addr_r1[7:0]; end
2'b11 : begin addr <= addr_r1[7:0] ^ 8'b1111_1111; end
default : begin addr <= 8'd0; end
endcase
end
reg signed [13:0] wave_out_r = 0;
always @(*) begin
case (addr)
8'd0 : begin wave_out_r <= 0; end
8'd1 : begin wave_out_r <= 50; end
8'd2 : begin wave_out_r <= 101; end
8'd3 : begin wave_out_r <= 151; end
8'd4 : begin wave_out_r <= 201; end
8'd5 : begin wave_out_r <= 252; end
8'd6 : begin wave_out_r <= 302; end
8'd7 : begin wave_out_r <= 352; end
8'd8 : begin wave_out_r <= 402; end
8'd9 : begin wave_out_r <= 453; end
8'd10 : begin wave_out_r <= 503; end
8'd11 : begin wave_out_r <= 553; end
8'd12 : begin wave_out_r <= 603; end
8'd13 : begin wave_out_r <= 653; end
8'd14 : begin wave_out_r <= 703; end
8'd15 : begin wave_out_r <= 754; end
8'd16 : begin wave_out_r <= 804; end
8'd17 : begin wave_out_r <= 854; end
8'd18 : begin wave_out_r <= 904; end
8'd19 : begin wave_out_r <= 954; end
8'd20 : begin wave_out_r <= 1004; end
8'd21 : begin wave_out_r <= 1054; end
8'd22 : begin wave_out_r <= 1103; end
8'd23 : begin wave_out_r <= 1153; end
8'd24 : begin wave_out_r <= 1203; end
8'd25 : begin wave_out_r <= 1253; end
8'd26 : begin wave_out_r <= 1302; end
8'd27 : begin wave_out_r <= 1352; end
8'd28 : begin wave_out_r <= 1402; end
8'd29 : begin wave_out_r <= 1451; end
8'd30 : begin wave_out_r <= 1501; end
8'd31 : begin wave_out_r <= 1550; end
8'd32 : begin wave_out_r <= 1600; end
8'd33 : begin wave_out_r <= 1649; end
8'd34 : begin wave_out_r <= 1698; end
8'd35 : begin wave_out_r <= 1747; end
8'd36 : begin wave_out_r <= 1796; end
8'd37 : begin wave_out_r <= 1845; end
8'd38 : begin wave_out_r <= 1894; end
8'd39 : begin wave_out_r <= 1943; end
8'd40 : begin wave_out_r <= 1992; end
8'd41 : begin wave_out_r <= 2041; end
8'd42 : begin wave_out_r <= 2090; end
8'd43 : begin wave_out_r <= 2138; end
8'd44 : begin wave_out_r <= 2187; end
8'd45 : begin wave_out_r <= 2235; end
8'd46 : begin wave_out_r <= 2284; end
8'd47 : begin wave_out_r <= 2332; end
8'd48 : begin wave_out_r <= 2380; end
8'd49 : begin wave_out_r <= 2428; end
8'd50 : begin wave_out_r <= 2476; end
8'd51 : begin wave_out_r <= 2524; end
8'd52 : begin wave_out_r <= 2572; end
8'd53 : begin wave_out_r <= 2620; end
8'd54 : begin wave_out_r <= 2667; end
8'd55 : begin wave_out_r <= 2715; end
8'd56 : begin wave_out_r <= 2762; end
8'd57 : begin wave_out_r <= 2809; end
8'd58 : begin wave_out_r <= 2857; end
8'd59 : begin wave_out_r <= 2904; end
8'd60 : begin wave_out_r <= 2951; end
8'd61 : begin wave_out_r <= 2998; end
8'd62 : begin wave_out_r <= 3044; end
8'd63 : begin wave_out_r <= 3091; end
8'd64 : begin wave_out_r <= 3137; end
8'd65 : begin wave_out_r <= 3184; end
8'd66 : begin wave_out_r <= 3230; end
8'd67 : begin wave_out_r <= 3276; end
8'd68 : begin wave_out_r <= 3322; end
8'd69 : begin wave_out_r <= 3368; end
8'd70 : begin wave_out_r <= 3414; end
8'd71 : begin wave_out_r <= 3460; end
8'd72 : begin wave_out_r <= 3505; end
8'd73 : begin wave_out_r <= 3551; end
8'd74 : begin wave_out_r <= 3596; end
8'd75 : begin wave_out_r <= 3641; end
8'd76 : begin wave_out_r <= 3686; end
8'd77 : begin wave_out_r <= 3731; end
8'd78 : begin wave_out_r <= 3776; end
8'd79 : begin wave_out_r <= 3820; end
8'd80 : begin wave_out_r <= 3865; end
8'd81 : begin wave_out_r <= 3909; end
8'd82 : begin wave_out_r <= 3953; end
8'd83 : begin wave_out_r <= 3997; end
8'd84 : begin wave_out_r <= 4041; end
8'd85 : begin wave_out_r <= 4085; end
8'd86 : begin wave_out_r <= 4128; end
8'd87 : begin wave_out_r <= 4172; end
8'd88 : begin wave_out_r <= 4215; end
8'd89 : begin wave_out_r <= 4258; end
8'd90 : begin wave_out_r <= 4301; end
8'd91 : begin wave_out_r <= 4343; end
8'd92 : begin wave_out_r <= 4386; end
8'd93 : begin wave_out_r <= 4428; end
8'd94 : begin wave_out_r <= 4471; end
8'd95 : begin wave_out_r <= 4513; end
8'd96 : begin wave_out_r <= 4555; end
8'd97 : begin wave_out_r <= 4596; end
8'd98 : begin wave_out_r <= 4638; end
8'd99 : begin wave_out_r <= 4679; end
8'd100 : begin wave_out_r <= 4720; end
8'd101 : begin wave_out_r <= 4761; end
8'd102 : begin wave_out_r <= 4802; end
8'd103 : begin wave_out_r <= 4843; end
8'd104 : begin wave_out_r <= 4883; end
8'd105 : begin wave_out_r <= 4924; end
8'd106 : begin wave_out_r <= 4964; end
8'd107 : begin wave_out_r <= 5004; end
8'd108 : begin wave_out_r <= 5044; end
8'd109 : begin wave_out_r <= 5083; end
8'd110 : begin wave_out_r <= 5122; end
8'd111 : begin wave_out_r <= 5162; end
8'd112 : begin wave_out_r <= 5201; end
8'd113 : begin wave_out_r <= 5239; end
8'd114 : begin wave_out_r <= 5278; end
8'd115 : begin wave_out_r <= 5316; end
8'd116 : begin wave_out_r <= 5354; end
8'd117 : begin wave_out_r <= 5392; end
8'd118 : begin wave_out_r <= 5430; end
8'd119 : begin wave_out_r <= 5468; end
8'd120 : begin wave_out_r <= 5505; end
8'd121 : begin wave_out_r <= 5542; end
8'd122 : begin wave_out_r <= 5579; end
8'd123 : begin wave_out_r <= 5616; end
8'd124 : begin wave_out_r <= 5652; end
8'd125 : begin wave_out_r <= 5689; end
8'd126 : begin wave_out_r <= 5725; end
8'd127 : begin wave_out_r <= 5761; end
8'd128 : begin wave_out_r <= 5796; end
8'd129 : begin wave_out_r <= 5832; end
8'd130 : begin wave_out_r <= 5867; end
8'd131 : begin wave_out_r <= 5902; end
8'd132 : begin wave_out_r <= 5937; end
8'd133 : begin wave_out_r <= 5971; end
8'd134 : begin wave_out_r <= 6006; end
8'd135 : begin wave_out_r <= 6040; end
8'd136 : begin wave_out_r <= 6074; end
8'd137 : begin wave_out_r <= 6107; end
8'd138 : begin wave_out_r <= 6141; end
8'd139 : begin wave_out_r <= 6174; end
8'd140 : begin wave_out_r <= 6207; end
8'd141 : begin wave_out_r <= 6239; end
8'd142 : begin wave_out_r <= 6272; end
8'd143 : begin wave_out_r <= 6304; end
8'd144 : begin wave_out_r <= 6336; end
8'd145 : begin wave_out_r <= 6368; end
8'd146 : begin wave_out_r <= 6399; end
8'd147 : begin wave_out_r <= 6431; end
8'd148 : begin wave_out_r <= 6462; end
8'd149 : begin wave_out_r <= 6493; end
8'd150 : begin wave_out_r <= 6523; end
8'd151 : begin wave_out_r <= 6553; end
8'd152 : begin wave_out_r <= 6584; end
8'd153 : begin wave_out_r <= 6613; end
8'd154 : begin wave_out_r <= 6643; end
8'd155 : begin wave_out_r <= 6672; end
8'd156 : begin wave_out_r <= 6701; end
8'd157 : begin wave_out_r <= 6730; end
8'd158 : begin wave_out_r <= 6759; end
8'd159 : begin wave_out_r <= 6787; end
8'd160 : begin wave_out_r <= 6815; end
8'd161 : begin wave_out_r <= 6843; end
8'd162 : begin wave_out_r <= 6870; end
8'd163 : begin wave_out_r <= 6897; end
8'd164 : begin wave_out_r <= 6925; end
8'd165 : begin wave_out_r <= 6951; end
8'd166 : begin wave_out_r <= 6978; end
8'd167 : begin wave_out_r <= 7004; end
8'd168 : begin wave_out_r <= 7030; end
8'd169 : begin wave_out_r <= 7056; end
8'd170 : begin wave_out_r <= 7081; end
8'd171 : begin wave_out_r <= 7106; end
8'd172 : begin wave_out_r <= 7131; end
8'd173 : begin wave_out_r <= 7156; end
8'd174 : begin wave_out_r <= 7180; end
8'd175 : begin wave_out_r <= 7204; end
8'd176 : begin wave_out_r <= 7228; end
8'd177 : begin wave_out_r <= 7251; end
8'd178 : begin wave_out_r <= 7275; end
8'd179 : begin wave_out_r <= 7298; end
8'd180 : begin wave_out_r <= 7320; end
8'd181 : begin wave_out_r <= 7343; end
8'd182 : begin wave_out_r <= 7365; end
8'd183 : begin wave_out_r <= 7387; end
8'd184 : begin wave_out_r <= 7408; end
8'd185 : begin wave_out_r <= 7430; end
8'd186 : begin wave_out_r <= 7451; end
8'd187 : begin wave_out_r <= 7472; end
8'd188 : begin wave_out_r <= 7492; end
8'd189 : begin wave_out_r <= 7512; end
8'd190 : begin wave_out_r <= 7532; end
8'd191 : begin wave_out_r <= 7552; end
8'd192 : begin wave_out_r <= 7571; end
8'd193 : begin wave_out_r <= 7590; end
8'd194 : begin wave_out_r <= 7609; end
8'd195 : begin wave_out_r <= 7627; end
8'd196 : begin wave_out_r <= 7646; end
8'd197 : begin wave_out_r <= 7664; end
8'd198 : begin wave_out_r <= 7681; end
8'd199 : begin wave_out_r <= 7698; end
8'd200 : begin wave_out_r <= 7715; end
8'd201 : begin wave_out_r <= 7732; end
8'd202 : begin wave_out_r <= 7749; end
8'd203 : begin wave_out_r <= 7765; end
8'd204 : begin wave_out_r <= 7781; end
8'd205 : begin wave_out_r <= 7796; end
8'd206 : begin wave_out_r <= 7812; end
8'd207 : begin wave_out_r <= 7827; end
8'd208 : begin wave_out_r <= 7841; end
8'd209 : begin wave_out_r <= 7856; end
8'd210 : begin wave_out_r <= 7870; end
8'd211 : begin wave_out_r <= 7884; end
8'd212 : begin wave_out_r <= 7897; end
8'd213 : begin wave_out_r <= 7910; end
8'd214 : begin wave_out_r <= 7923; end
8'd215 : begin wave_out_r <= 7936; end
8'd216 : begin wave_out_r <= 7948; end
8'd217 : begin wave_out_r <= 7960; end
8'd218 : begin wave_out_r <= 7972; end
8'd219 : begin wave_out_r <= 7983; end
8'd220 : begin wave_out_r <= 7994; end
8'd221 : begin wave_out_r <= 8005; end
8'd222 : begin wave_out_r <= 8016; end
8'd223 : begin wave_out_r <= 8026; end
8'd224 : begin wave_out_r <= 8036; end
8'd225 : begin wave_out_r <= 8045; end
8'd226 : begin wave_out_r <= 8055; end
8'd227 : begin wave_out_r <= 8064; end
8'd228 : begin wave_out_r <= 8072; end
8'd229 : begin wave_out_r <= 8081; end
8'd230 : begin wave_out_r <= 8089; end
8'd231 : begin wave_out_r <= 8097; end
8'd232 : begin wave_out_r <= 8104; end
8'd233 : begin wave_out_r <= 8111; end
8'd234 : begin wave_out_r <= 8118; end
8'd235 : begin wave_out_r <= 8125; end
8'd236 : begin wave_out_r <= 8131; end
8'd237 : begin wave_out_r <= 8137; end
8'd238 : begin wave_out_r <= 8142; end
8'd239 : begin wave_out_r <= 8148; end
8'd240 : begin wave_out_r <= 8153; end
8'd241 : begin wave_out_r <= 8157; end
8'd242 : begin wave_out_r <= 8162; end
8'd243 : begin wave_out_r <= 8166; end
8'd244 : begin wave_out_r <= 8170; end
8'd245 : begin wave_out_r <= 8173; end
8'd246 : begin wave_out_r <= 8176; end
8'd247 : begin wave_out_r <= 8179; end
8'd248 : begin wave_out_r <= 8182; end
8'd249 : begin wave_out_r <= 8184; end
8'd250 : begin wave_out_r <= 8186; end
8'd251 : begin wave_out_r <= 8188; end
8'd252 : begin wave_out_r <= 8189; end
8'd253 : begin wave_out_r <= 8190; end
8'd254 : begin wave_out_r <= 8191; end
8'd255 : begin wave_out_r <= 8191; end
default : begin wave_out_r <= 0; end
endcase
end
reg signed [OUTPUT_WIDTH - 1 : 0] FM_out_r0 = 0;
always @(*) begin
case (addr_r1[9])
1'b0 : begin FM_out_r0 <= wave_out_r[13 : 14 - OUTPUT_WIDTH]; end
1'b1 : begin FM_out_r0 <= - wave_out_r[13 : 14 - OUTPUT_WIDTH]; end
default : begin FM_out_r0 <= 14'd0; end
endcase
end
reg signed [OUTPUT_WIDTH - 1 : 0] FM_out_r1 = 0;
always @(posedge clk) begin
if (RST) begin
FM_out_r1 <= 0;
end
else begin
FM_out_r1 <= FM_out_r0;
end
end
assign FM_wave = FM_out_r1;
endmodule

View File

@ -0,0 +1,20 @@
`timescale 1ns/100ps
module BF_op #(
parameter REAL_WIDTH = 18,
parameter IMGN_WIDTH = 18,
localparam CPLX_WIDTH = REAL_WIDTH + IMGN_WIDTH
) (
input [CPLX_WIDTH - 1 : 0] ia,
input [CPLX_WIDTH - 1 : 0] ib,
output [CPLX_WIDTH - 1 : 0] oa,
output [CPLX_WIDTH - 1 : 0] ob
);
assign oa[CPLX_WIDTH-1:REAL_WIDTH] = $signed(ia[CPLX_WIDTH-1:REAL_WIDTH]) + $signed(ib[CPLX_WIDTH-1:REAL_WIDTH]);
assign oa[IMGN_WIDTH-1:0] = $signed(ia[IMGN_WIDTH-1:0]) + $signed(ib[IMGN_WIDTH-1:0]);
assign ob[CPLX_WIDTH-1:REAL_WIDTH] = $signed(ia[CPLX_WIDTH-1:REAL_WIDTH]) - $signed(ib[CPLX_WIDTH-1:REAL_WIDTH]);
assign ob[IMGN_WIDTH-1:0] = $signed(ia[IMGN_WIDTH-1:0]) - $signed(ib[IMGN_WIDTH-1:0]);
endmodule

View File

@ -0,0 +1,104 @@
`timescale 1ns/100ps
module BF_stg1 #(
parameter FFT_STG = 7,
parameter REAL_WIDTH = 18,
parameter IMGN_WIDTH = 18,
parameter TOTAL_STAGE = 11,
localparam CPLX_WIDTH = REAL_WIDTH + IMGN_WIDTH
) (
input iclk,
input rst_n,
input ien,
input [TOTAL_STAGE-1 : 0] iaddr,
input [CPLX_WIDTH -1 : 0] idata,
output oen,
output [TOTAL_STAGE-1 : 0] oaddr,
output [CPLX_WIDTH -1 : 0] odata
);
localparam TOTAL_ADDR_MAX = { TOTAL_STAGE { 1'b1 } };
localparam STG_MAX = { FFT_STG { 1'b1 } };
localparam STG_HALFMAX = ( STG_MAX >> 1 );
reg [CPLX_WIDTH - 1 : 0] r [STG_HALFMAX:0];
integer i;
initial begin
for (i = 0; i<=STG_HALFMAX; i=i+1) begin
r[i] = 0;
end
end
reg dump = 0;
reg [FFT_STG - 1 : 0] dump_cnt = 0;
always @(posedge iclk) begin
if(iaddr[FFT_STG-1:0] == STG_MAX && ien) begin
dump <= 1'b1;
dump_cnt <= 0;
end
else if(dump) begin
if(dump_cnt == STG_HALFMAX) dump <= 1'b0;
dump_cnt <= dump_cnt + 1'b1;
end
end
wire with_dump;
assign with_dump = dump;
wire [CPLX_WIDTH - 1 : 0] bf_ia;
wire [CPLX_WIDTH - 1 : 0] bf_ib;
wire [CPLX_WIDTH - 1 : 0] bf_oa;
wire [CPLX_WIDTH - 1 : 0] bf_ob;
assign bf_ia = r[STG_HALFMAX];
assign bf_ib = idata;
BF_op #(
.REAL_WIDTH(REAL_WIDTH),
.IMGN_WIDTH(IMGN_WIDTH)
) bf0 (
.ia(bf_ia),
.ib(bf_ib),
.oa(bf_oa),
.ob(bf_ob)
);
wire [CPLX_WIDTH - 1 : 0] wdata_in;
integer index;
always @(posedge iclk) begin
if(ien) r[0] <= wdata_in;
for(index = STG_HALFMAX; index > 0; index=index-1)
r[index] <= r[index-1];
end
reg oen_r = 0;
reg [TOTAL_STAGE-1 : 0] oaddr_r = 0;
reg [CPLX_WIDTH -1 : 0] odata_r = 0;
wire is_load;
wire is_calc;
assign is_load = ~iaddr[FFT_STG-1];
assign is_calc = iaddr[FFT_STG-1];
assign wdata_in = is_load ? idata : bf_ob;
always @(posedge iclk) begin
if(is_calc & ien) begin
odata_r <= bf_oa;
oaddr_r <= oaddr_r + 1'b1;
oen_r <= 1'b1;
end
else if((is_load | ~ien) & with_dump) begin
odata_r <= r[STG_HALFMAX];
oaddr_r <= oaddr_r + 1'b1;
oen_r <= 1'b1;
end
else begin
odata_r <= 0;
oaddr_r <= TOTAL_ADDR_MAX;
oen_r <= 1'b0;
end
end
assign odata = odata_r;
assign oaddr = oaddr_r;
assign oen = oen_r;
endmodule

View File

@ -0,0 +1,110 @@
`timescale 1ns/100ps
module BF_stgX # (
parameter FFT_STG = 7,
parameter REAL_WIDTH = 18,
parameter IMGN_WIDTH = 18,
parameter TOTAL_STAGE = 11,
localparam CPLX_WIDTH = REAL_WIDTH + IMGN_WIDTH
) (
input iclk,
input rst_n,
input ien,
input [TOTAL_STAGE-1 : 0] iaddr,
input [CPLX_WIDTH -1 : 0] idata,
output oen,
output [TOTAL_STAGE-1 : 0] oaddr,
output [CPLX_WIDTH -1 : 0] odata
);
localparam TOTAL_ADDR_MAX = { TOTAL_STAGE { 1'b1 } };
localparam STG_MAX = { FFT_STG { 1'b1 } };
localparam STG_HALFMAX = ( STG_MAX >> 1 );
reg [CPLX_WIDTH - 1 : 0] r [STG_HALFMAX:0];
integer i;
initial begin
for (i = 0; i<=STG_HALFMAX; i=i+1) begin
r[i] = 0;
end
end
reg [CPLX_WIDTH-1 : 0] rdata = 0;
reg [CPLX_WIDTH-1 : 0] rdata_out = 0;
reg dump = 0;
reg [FFT_STG - 2 : 0] dump_cnt = 0;
always @(posedge iclk) begin
if(iaddr[FFT_STG-1:0] == STG_MAX && ien) begin
dump <= 1'b1;
dump_cnt <= 0;
end
else if(dump) begin
if(dump_cnt == STG_HALFMAX) dump <= 1'b0;
dump_cnt <= dump_cnt + 1'b1;
end
end
wire with_dump;
assign with_dump = dump;
wire [FFT_STG-2 : 0] waddr_in;
wire [FFT_STG-2 : 0] raddr_in;
assign raddr_in = (with_dump ? dump_cnt : iaddr[FFT_STG-2:0]) + 2'b10;
assign waddr_in = iaddr[FFT_STG-2:0];
wire [CPLX_WIDTH - 1 : 0] bf_ia;
wire [CPLX_WIDTH - 1 : 0] bf_ib;
wire [CPLX_WIDTH - 1 : 0] bf_oa;
wire [CPLX_WIDTH - 1 : 0] bf_ob;
assign bf_ia = rdata;
assign bf_ib = idata;
BF_op #(
.REAL_WIDTH(REAL_WIDTH),
.IMGN_WIDTH(IMGN_WIDTH)
) bf0 (
.ia(bf_ia),
.ib(bf_ib),
.oa(bf_oa),
.ob(bf_ob)
);
wire [CPLX_WIDTH - 1 : 0] wdata_in;
always @(posedge iclk) begin
if(ien) r[waddr_in] <= wdata_in;
rdata_out <= r[raddr_in];
rdata <= rdata_out;
end
reg oen_r = 0;
reg [TOTAL_STAGE-1 : 0] oaddr_r = 0;
reg [CPLX_WIDTH -1 : 0] odata_r = 0;
wire is_load;
wire is_calc;
assign is_load = ~iaddr[FFT_STG-1];
assign is_calc = iaddr[FFT_STG-1];
assign wdata_in = is_load ? idata : bf_ob;
always @(posedge iclk) begin
if(is_calc & ien) begin
odata_r <= bf_oa;
oaddr_r <= oaddr_r + 1'b1;
oen_r <= 1'b1;
end
else if((is_load | ~ien) & with_dump) begin
odata_r <= rdata;
oaddr_r <= oaddr_r + 1'b1;
oen_r <= 1'b1;
end
else begin
odata_r <= 0;
oaddr_r <= TOTAL_ADDR_MAX;
oen_r <= 1'b0;
end
end
assign odata = odata_r;
assign oaddr = oaddr_r;
assign oen = oen_r;
endmodule

View File

@ -0,0 +1,27 @@
`timescale 1 ps / 1 ps
module cmpl_mult #(
parameter REAL_WIDTH = 18,
parameter IMGN_WIDTH = 18,
localparam CPLX_WIDTH = REAL_WIDTH + IMGN_WIDTH
) (
input clock,
input [REAL_WIDTH-1:0] dataa_real,
input [IMGN_WIDTH-1:0] dataa_imag,
input [REAL_WIDTH-1:0] datab_real,
input [IMGN_WIDTH-1:0] datab_imag,
output [CPLX_WIDTH-1:0] result_real,
output [CPLX_WIDTH-1:0] result_imag
);
reg signed [CPLX_WIDTH-1:0] outr = 0;
reg signed [CPLX_WIDTH-1:0] outi = 0;
always@(posedge clock) begin
outr <= $signed(dataa_real) * $signed(datab_real) - $signed(dataa_imag) * $signed(datab_imag);
outi <= $signed(dataa_real) * $signed(datab_imag) + $signed(dataa_imag) * $signed(datab_real);
end
assign result_imag = outi;
assign result_real = outr;
endmodule

View File

@ -0,0 +1,83 @@
`timescale 1ns/100ps
module fft #(
parameter REAL_WIDTH = 18,
parameter IMGN_WIDTH = 18,
parameter TOTAL_STAGE = 11
) (
input iclk,
input rst_n,
input ien,
input [TOTAL_STAGE-1:0] iaddr,
input [REAL_WIDTH-1:0] iReal,
input [IMGN_WIDTH-1:0] iImag,
output oen,
output [TOTAL_STAGE-1:0] oaddr,
output [REAL_WIDTH-1:0] oReal,
output [IMGN_WIDTH-1:0] oImag
);
localparam INTER_MODU_WIRE_NUM = ((TOTAL_STAGE-1)/2);
localparam CPLX_WIDTH = REAL_WIDTH + IMGN_WIDTH;
wire [CPLX_WIDTH -1:0] data_end;
wire [TOTAL_STAGE-1:0] addr_end;
wire en_w [INTER_MODU_WIRE_NUM:0];
wire [CPLX_WIDTH -1:0] data_w [INTER_MODU_WIRE_NUM:0];
wire [TOTAL_STAGE-1:0] addr_w [INTER_MODU_WIRE_NUM:0];
assign en_w [INTER_MODU_WIRE_NUM] = ien;
assign addr_w[INTER_MODU_WIRE_NUM] = iaddr;
assign data_w[INTER_MODU_WIRE_NUM] = {iReal, iImag};
generate
genvar gv_stg;
for(gv_stg=TOTAL_STAGE; gv_stg>=2; gv_stg=gv_stg-2) begin : stagX
fft_stage #(
.REAL_WIDTH(REAL_WIDTH),
.IMGN_WIDTH(IMGN_WIDTH),
.TOTAL_STAGE(TOTAL_STAGE),
.FFT_STG(gv_stg)
)stgX_inst (
.iclk(iclk),
.rst_n(rst_n),
.iaddr(addr_w[((gv_stg-1)/2)]),
.idata(data_w[((gv_stg-1)/2)]),
.ien(en_w[((gv_stg-1)/2)]),
.oaddr(addr_w[((gv_stg-1)/2)-1]),
.odata(data_w[((gv_stg-1)/2)-1]),
.oen(en_w[((gv_stg-1)/2)-1])
);
end
if(TOTAL_STAGE[0]) begin : BF_stg1
BF_stg1 #(
.REAL_WIDTH(REAL_WIDTH),
.IMGN_WIDTH(IMGN_WIDTH),
.TOTAL_STAGE(TOTAL_STAGE),
.FFT_STG(1)
)stg1_inst (
.iclk(iclk),
.rst_n(rst_n),
.ien(en_w[0]),
.iaddr(addr_w[0]),
.idata(data_w[0]),
.oen(oen),
.oaddr(addr_end),
.odata(data_end)
);
end
endgenerate
generate // bit_reverse
genvar index;
for(index=0; index<TOTAL_STAGE; index=index+1) begin: bit_reverse
assign oaddr[TOTAL_STAGE-index-1] = addr_end[index];
end
endgenerate
assign oReal = data_end[CPLX_WIDTH:REAL_WIDTH];
assign oImag = data_end[IMGN_WIDTH:0];
endmodule

View File

@ -0,0 +1,175 @@
`timescale 1ns/100ps
module fft_stage #(
parameter FFT_STG = 7,
parameter REAL_WIDTH = 18,
parameter IMGN_WIDTH = 18,
parameter TOTAL_STAGE = 11,
localparam CPLX_WIDTH = REAL_WIDTH + IMGN_WIDTH
) (
input iclk,
input rst_n,
input ien,
input [CPLX_WIDTH-1 : 0] idata,
input [TOTAL_STAGE-1 : 0] iaddr,
output oen,
output [CPLX_WIDTH-1 : 0] odata,
output [TOTAL_STAGE-1 : 0] oaddr
);
wire bfX_oen;
wire [CPLX_WIDTH-1:0] bfX_odata;
wire [TOTAL_STAGE-1:0] bfX_oaddr;
wire Trans_I_oen;
wire [CPLX_WIDTH-1:0] Trans_I_odata;
wire [TOTAL_STAGE-1:0] Trans_I_oaddr;
wire bfX_1_oen;
wire [CPLX_WIDTH-1:0] bfX_1_data;
wire [TOTAL_STAGE-1:0] bfX_1_oaddr;
generate
if(FFT_STG == 2) begin : BF_stg_I2
BF_stg1 #(
.REAL_WIDTH(REAL_WIDTH),
.IMGN_WIDTH(IMGN_WIDTH),
.TOTAL_STAGE(TOTAL_STAGE),
.FFT_STG(2)
)BF_instI (
.iclk(iclk),
.rst_n(rst_n),
.ien(ien),
.iaddr(iaddr),
.idata(idata),
.oen(bfX_oen),
.oaddr(bfX_oaddr),
.odata(bfX_odata)
);
end
else begin : BF_stgX_I
BF_stgX #(
.REAL_WIDTH(REAL_WIDTH),
.IMGN_WIDTH(IMGN_WIDTH),
.TOTAL_STAGE(TOTAL_STAGE),
.FFT_STG(FFT_STG)
)BF_instI (
.iclk(iclk),
.rst_n(rst_n),
.ien(ien),
.iaddr(iaddr),
.idata(idata),
.oen(bfX_oen),
.oaddr(bfX_oaddr),
.odata(bfX_odata)
);
end
endgenerate
generate if(FFT_STG > 1) begin : ftrans_conjugate
ftrans #(
.FTRANS_STYLE("conjugate"), //conjugate
.REAL_WIDTH(REAL_WIDTH),
.IMGN_WIDTH(IMGN_WIDTH),
.TOTAL_STAGE(TOTAL_STAGE),
.FFT_STG(FFT_STG)
) ftrans_conjugate_inst (
.iclk(iclk),
.ien(bfX_oen),
.iaddr(bfX_oaddr),
.idata(bfX_odata),
.oen(Trans_I_oen),
.oaddr(Trans_I_oaddr),
.odata(Trans_I_odata)
);
end
else begin
assign oen = bfX_oen;
assign oaddr = bfX_oaddr;
assign odata = bfX_odata;
end
endgenerate
generate
if(FFT_STG == 3) begin : BF_stg_II2
BF_stg1 #(
.REAL_WIDTH(REAL_WIDTH),
.IMGN_WIDTH(IMGN_WIDTH),
.TOTAL_STAGE(TOTAL_STAGE),
.FFT_STG(2)
) BF_instII (
.iclk(iclk),
.rst_n(rst_n),
.ien(Trans_I_oen),
.iaddr(Trans_I_oaddr),
.idata(Trans_I_odata),
.oen(bfX_1_oen),
.oaddr(bfX_1_oaddr),
.odata(bfX_1_data)
);
end
else if(FFT_STG == 2) begin : BF_stg_II1
BF_stg1 #(
.REAL_WIDTH(REAL_WIDTH),
.IMGN_WIDTH(IMGN_WIDTH),
.TOTAL_STAGE(TOTAL_STAGE),
.FFT_STG(1)
) BF_instII (
.iclk(iclk),
.rst_n(rst_n),
.ien(Trans_I_oen),
.iaddr(Trans_I_oaddr),
.idata(Trans_I_odata),
.oen(bfX_1_oen),
.oaddr(bfX_1_oaddr),
.odata(bfX_1_data)
);
end
else begin : BF_stgX_II
BF_stgX #(
.REAL_WIDTH(REAL_WIDTH),
.IMGN_WIDTH(IMGN_WIDTH),
.TOTAL_STAGE(TOTAL_STAGE),
.FFT_STG(FFT_STG-1)
) BF_instII (
.iclk(iclk),
.rst_n(rst_n),
.ien(Trans_I_oen),
.iaddr(Trans_I_oaddr),
.idata(Trans_I_odata),
.oen(bfX_1_oen),
.oaddr(bfX_1_oaddr),
.odata(bfX_1_data)
);
end
endgenerate
generate
if(FFT_STG > 2) begin : ftrans_twiddle
ftrans #(
.FTRANS_STYLE("twiddle"), //conjugate
.REAL_WIDTH(REAL_WIDTH),
.IMGN_WIDTH(IMGN_WIDTH),
.TOTAL_STAGE(TOTAL_STAGE),
.FFT_STG(FFT_STG)
) ftrans_twiddle_inst (
.iclk(iclk),
.ien(bfX_1_oen),
.iaddr(bfX_1_oaddr),
.idata(bfX_1_data),
.oen(oen),
.oaddr(oaddr),
.odata(odata)
);
end
else begin
assign oen = bfX_1_oen;
assign oaddr = bfX_1_oaddr;
assign odata = bfX_1_data;
end
endgenerate
endmodule

View File

@ -0,0 +1,154 @@
`timescale 1ns/100ps
module ftrans #(
parameter FTRANS_STYLE = "twiddle", //conjugate
parameter REAL_WIDTH = 18,
parameter IMGN_WIDTH = 18,
parameter TOTAL_STAGE = 11,
parameter FFT_STG = 7,
localparam CPLX_WIDTH = REAL_WIDTH + IMGN_WIDTH
) (
input iclk,
input ien,
input [CPLX_WIDTH-1:0] idata,
input [TOTAL_STAGE-1:0] iaddr,
output oen,
output [CPLX_WIDTH-1:0] odata,
output [TOTAL_STAGE-1:0] oaddr
);
wire k1 = iaddr[FFT_STG-1];
wire k2 = iaddr[FFT_STG-2];
wire signed [REAL_WIDTH-1:0] data_real = idata[CPLX_WIDTH-1:REAL_WIDTH];
wire signed [IMGN_WIDTH-1:0] data_imag = idata[IMGN_WIDTH-1:0];
reg [CPLX_WIDTH-1:0] idata_r = 0;
reg [CPLX_WIDTH-1:0] odata_r = 0;
generate if(FTRANS_STYLE == "conjugate") begin : conjugate
always @(posedge iclk) begin
if({k1, k2} == 2'b11)begin
idata_r <= {data_real,-data_imag};
odata_r <= idata_r;
end
else begin
idata_r <= idata;
odata_r <= idata_r;
end
end
end
else if(FTRANS_STYLE == "twiddle") begin : twiddle
wire [FFT_STG-3:0] n3 = iaddr[FFT_STG-3:0];
wire [FFT_STG-2:0] addr1 = k1 ? {1'b0, n3} : { (FFT_STG-1) {1'b0} };
wire [FFT_STG-2:0] addr2 = k2 ? {n3, 1'b0} : { (FFT_STG-1) {1'b0} };
wire [FFT_STG-1:0] ROM_addr = addr1 + addr2; // ROM_addr = (k1 + 2*k2) * n3
wire [REAL_WIDTH-1:0] twiddle_ore;
wire [IMGN_WIDTH-1:0] twiddle_oim;
ftwiddle #(
.REAL_WIDTH(REAL_WIDTH),
.IMGN_WIDTH(IMGN_WIDTH),
.TW_STAGE(FFT_STG)
) ftwiddle_inst (
.idx(ROM_addr),
.ore(twiddle_ore),
.oim(twiddle_oim)
);
wire [CPLX_WIDTH-1:0] mul_ore;
wire [CPLX_WIDTH-1:0] mul_oim;
cmpl_mult #(
.REAL_WIDTH(REAL_WIDTH),
.IMGN_WIDTH(IMGN_WIDTH)
) cmpl_mult_inst (
.clock(iclk),
.dataa_real(data_real),
.dataa_imag(data_imag),
.datab_real(twiddle_ore),
.datab_imag(twiddle_oim),
.result_real(mul_ore),
.result_imag(mul_oim)
);
always @(posedge iclk) begin
odata_r <= {mul_ore[CPLX_WIDTH-1:REAL_WIDTH],mul_oim[CPLX_WIDTH-1:IMGN_WIDTH]};
end
end
endgenerate
assign odata = odata_r;
localparam LATENCY = 2;
reg [TOTAL_STAGE-1:0] oaddr_d [LATENCY-1:0];
integer i;
initial begin
for (i = 0; i<LATENCY; i=i+1) begin
oaddr_d[i] = 0;
end
end
integer index;
always @(posedge iclk) begin
oaddr_d[0] <= iaddr;
for(index=0; index<LATENCY-1; index=index+1) begin
oaddr_d[index+1] <= oaddr_d[index];
end
end
assign oaddr = oaddr_d[LATENCY-1];
reg [LATENCY-1:0] oen_d = 0;
always @(posedge iclk) begin
oen_d <= {oen_d[LATENCY-2:0], ien};
end
assign oen = oen_d[LATENCY-1];
// generate if(FTRANS_STYLE == "conjugate") begin
// localparam LATENCY = 2;
// reg [TOTAL_STAGE-1:0] oaddr_d [LATENCY-1:0];
// integer i;
// initial begin
// for (i = 0; i<LATENCY; i=i+1) begin
// oaddr_d[i] = 0;
// end
// end
// integer index;
// always @(posedge iclk) begin
// oaddr_d[0] <= iaddr;
// for(index=0; index<LATENCY-1; index=index+1) begin
// oaddr_d[index+1] <= oaddr_d[index];
// end
// end
// assign oaddr = oaddr_d[LATENCY-1];
// reg [LATENCY-1:0] oen_d = 0;
// always @(posedge iclk) begin
// oen_d <= {oen_d[LATENCY-2:0], ien};
// end
// assign oen = oen_d[LATENCY-1];
// end
// else if(FTRANS_STYLE == "twiddle") begin
// localparam LATENCY = 3;
// reg [TOTAL_STAGE-1:0] oaddr_d [LATENCY-1:0];
// integer i;
// initial begin
// for (i = 0; i<LATENCY; i=i+1) begin
// oaddr_d[i] = 0;
// end
// end
// integer index;
// always @(posedge iclk) begin
// oaddr_d[0] <= iaddr;
// for(index=0; index<LATENCY-1; index=index+1) begin
// oaddr_d[index+1] <= oaddr_d[index];
// end
// end
// assign oaddr = oaddr_d[LATENCY-1];
// reg [LATENCY-1:0] oen_d = 0;
// always @(posedge iclk) begin
// oen_d <= {oen_d[LATENCY-2:0], ien};
// end
// assign oen = oen_d[LATENCY-1];
// end
// endgenerate
endmodule

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,81 @@
`timescale 1ns/100ps
module testbench();
parameter TOTAL_STAGE = 8;
reg clk_100m = 0;
reg sys_rst_n = 0;
reg [TOTAL_STAGE-1:0] addr = 0;
wire valid_out;
always begin
#10 clk_100m = ~clk_100m;
end
always begin
#50 sys_rst_n = 1;
end
always begin
if (valid_out) begin
#10 addr = addr + 1;#10;
end
else begin
#10 addr = 0;#10;
end
end
parameter REAL_WIDTH = 18;
parameter IMGN_WIDTH = 18;
wire [REAL_WIDTH-1:0] cos_wave;
wire [IMGN_WIDTH-1:0] sin_wave;
wire [15:0] pha_diff;
Cordic #
(
.XY_BITS(REAL_WIDTH),
.PH_BITS(16), //1~32
.ITERATIONS(16), //1~32
.CORDIC_STYLE("ROTATE"), //ROTATE //VECTOR
.PHASE_ACC("ON") //ON //OFF
)
IQ_Gen_u
(
.clk_in(clk_100m),
.RST(1'd0),
.x_i(0),
.y_i(0),
.phase_in(16'd2356),//Fre_word = (2^PH_BITS)/fc* f fc时钟频率 f输出频率
.x_o(cos_wave),
.y_o(sin_wave),
.phase_out(pha_diff),
.valid_in(1),
.valid_out(valid_out)
);
wire oen;
wire [REAL_WIDTH-1:0] oReal;
wire [IMGN_WIDTH-1:0] oImag;
wire [TOTAL_STAGE-1:0] oaddr;
fft #(
.REAL_WIDTH(REAL_WIDTH),
.IMGN_WIDTH(REAL_WIDTH),
.TOTAL_STAGE(TOTAL_STAGE)
)
fft_ins
(
.iclk(clk_100m),
.rst_n(sys_rst_n),
.iaddr(addr),
.iReal(cos_wave),
.iImag(0),
.ien(valid_out),
.oReal(oReal),
.oImag(oImag),
.oaddr(oaddr),
.oen(oen)
);
endmodule

View File

@ -0,0 +1,212 @@
`timescale 1 ns / 1 ns
module CIC_DOWN_S2 #(
parameter INPUT_WIDTH = 12,
parameter OUTPUT_WIDTH = 15
) (
input clk,
input clk_enable,
input reset,
input [15:0] FACTOR,
input signed [INPUT_WIDTH-1:0] filter_in,
output signed [OUTPUT_WIDTH-1:0] filter_out,
output ce_out
);
localparam FILTER_WIDTH = OUTPUT_WIDTH;
////////////////////////////////////////////////////////////////
//Module Architecture: CIC_Down_S2
////////////////////////////////////////////////////////////////
// Local Functions
// Type Definitions
// Constants
// Signals
reg [15:0] cur_count = 0; // ufix2
wire phase_1; // boolean
reg ce_out_reg = 0; // boolean
//
reg signed [INPUT_WIDTH-1:0] input_register = 0; // sfix16_En15
// -- Section 1 Signals
wire signed [INPUT_WIDTH-1:0] section_in1; // sfix16_En15
wire signed [FILTER_WIDTH-1:0] section_cast1; // sfix18_En15
wire signed [FILTER_WIDTH-1:0] sum1; // sfix18_En15
reg signed [FILTER_WIDTH-1:0] section_out1 = 0; // sfix18_En15
wire signed [FILTER_WIDTH-1:0] add_cast; // sfix18_En15
wire signed [FILTER_WIDTH-1:0] add_cast_1; // sfix18_En15
wire signed [FILTER_WIDTH:0] add_temp; // sfix19_En15
// -- Section 2 Signals
wire signed [FILTER_WIDTH-1:0] section_in2; // sfix18_En15
wire signed [FILTER_WIDTH-1:0] sum2; // sfix18_En15
reg signed [FILTER_WIDTH-1:0] section_out2 = 0; // sfix18_En15
wire signed [FILTER_WIDTH-1:0] add_cast_2; // sfix18_En15
wire signed [FILTER_WIDTH-1:0] add_cast_3; // sfix18_En15
wire signed [FILTER_WIDTH:0] add_temp_1; // sfix19_En15
// -- Section 3 Signals
wire signed [FILTER_WIDTH-1:0] section_in3; // sfix18_En15
reg signed [FILTER_WIDTH-1:0] diff1 = 0; // sfix18_En15
wire signed [FILTER_WIDTH-1:0] section_out3; // sfix18_En15
wire signed [FILTER_WIDTH-1:0] sub_cast; // sfix18_En15
wire signed [FILTER_WIDTH-1:0] sub_cast_1; // sfix18_En15
wire signed [FILTER_WIDTH:0] sub_temp; // sfix19_En15
// -- Section 4 Signals
wire signed [FILTER_WIDTH-1:0] section_in4; // sfix18_En15
reg signed [FILTER_WIDTH-1:0] diff2 = 0; // sfix18_En15
wire signed [FILTER_WIDTH-1:0] section_out4; // sfix18_En15
wire signed [FILTER_WIDTH-1:0] sub_cast_2; // sfix18_En15
wire signed [FILTER_WIDTH-1:0] sub_cast_3; // sfix18_En15
wire signed [FILTER_WIDTH:0] sub_temp_1; // sfix19_En15
//
reg signed [FILTER_WIDTH-1:0] output_register = 0; // sfix18_En15
// Block Statements
// ------------------ CE Output Generation ------------------
always @ (posedge clk or posedge reset)
begin: ce_output
if (reset == 1'b1) begin
cur_count <= 16'd0;
end
else begin
if (clk_enable == 1'b1) begin
if (cur_count == FACTOR-1) begin
cur_count <= 16'd0;
end
else begin
cur_count <= cur_count + 1;
end
end
end
end // ce_output
assign phase_1 = (cur_count == 16'd1 && clk_enable == 1'b1)? 1 : 0;
// ------------------ CE Output Register ------------------
always @ (posedge clk or posedge reset)
begin: ce_output_register
if (reset == 1'b1) begin
ce_out_reg <= 1'b0;
end
else begin
ce_out_reg <= phase_1;
end
end // ce_output_register
// ------------------ Input Register ------------------
always @ (posedge clk or posedge reset)
begin: input_reg_process
if (reset == 1'b1) begin
input_register <= 0;
end
else begin
if (clk_enable == 1'b1) begin
input_register <= filter_in;
end
end
end // input_reg_process
// ------------------ Section # 1 : Integrator ------------------
assign section_in1 = input_register;
assign section_cast1 = $signed({{(FILTER_WIDTH-INPUT_WIDTH){section_in1[INPUT_WIDTH-1]}}, section_in1});
assign add_cast = section_cast1;
assign add_cast_1 = section_out1;
assign add_temp = add_cast + add_cast_1;
assign sum1 = add_temp[FILTER_WIDTH-1:0];
always @ (posedge clk or posedge reset)
begin: integrator_delay_section1
if (reset == 1'b1) begin
section_out1 <= 0;
end
else begin
if (clk_enable == 1'b1) begin
section_out1 <= sum1;
end
end
end // integrator_delay_section1
// ------------------ Section # 2 : Integrator ------------------
assign section_in2 = section_out1;
assign add_cast_2 = section_in2;
assign add_cast_3 = section_out2;
assign add_temp_1 = add_cast_2 + add_cast_3;
assign sum2 = add_temp_1[FILTER_WIDTH-1:0];
always @ (posedge clk or posedge reset)
begin: integrator_delay_section2
if (reset == 1'b1) begin
section_out2 <= 0;
end
else begin
if (clk_enable == 1'b1) begin
section_out2 <= sum2;
end
end
end // integrator_delay_section2
// ------------------ Section # 3 : Comb ------------------
assign section_in3 = section_out2;
assign sub_cast = section_in3;
assign sub_cast_1 = diff1;
assign sub_temp = sub_cast - sub_cast_1;
assign section_out3 = sub_temp[FILTER_WIDTH-1:0];
always @ (posedge clk or posedge reset)
begin: comb_delay_section3
if (reset == 1'b1) begin
diff1 <= 0;
end
else begin
if (phase_1 == 1'b1) begin
diff1 <= section_in3;
end
end
end // comb_delay_section3
// ------------------ Section # 4 : Comb ------------------
assign section_in4 = section_out3;
assign sub_cast_2 = section_in4;
assign sub_cast_3 = diff2;
assign sub_temp_1 = sub_cast_2 - sub_cast_3;
assign section_out4 = sub_temp_1[FILTER_WIDTH-1:0];
always @ (posedge clk or posedge reset)
begin: comb_delay_section4
if (reset == 1'b1) begin
diff2 <= 0;
end
else begin
if (phase_1 == 1'b1) begin
diff2 <= section_in4;
end
end
end // comb_delay_section4
// ------------------ Output Register ------------------
always @ (posedge clk or posedge reset)
begin: output_reg_process
if (reset == 1'b1) begin
output_register <= 0;
end
else begin
if (phase_1 == 1'b1) begin
output_register <= section_out4;
end
end
end // output_reg_process
// Assignment Statements
assign ce_out = ce_out_reg;
assign filter_out = output_register;
endmodule // CIC_Down_S2

View File

@ -0,0 +1,267 @@
`timescale 1 ns / 1 ns
module CIC_DOWN_S3 #(
parameter INPUT_WIDTH = 12,
parameter OUTPUT_WIDTH = 15
) (
input clk,
input clk_enable,
input reset,
input [15:0] FACTOR,
input signed [INPUT_WIDTH-1:0] filter_in,
output signed [OUTPUT_WIDTH-1:0] filter_out,
output ce_out
);
localparam FILTER_WIDTH = OUTPUT_WIDTH;
////////////////////////////////////////////////////////////////
//Module Architecture: CIC_DOWN_S3
////////////////////////////////////////////////////////////////
// Local Functions
// Type Definitions
// Constants
// Signals
reg [15:0] cur_count = 0; // ufix2
wire phase_1; // boolean
reg ce_out_reg = 0; // boolean
//
reg signed [INPUT_WIDTH-1:0] input_register = 0; // sfix12_En11
// -- Section 1 Signals
wire signed [INPUT_WIDTH-1:0] section_in1; // sfix12_En11
wire signed [FILTER_WIDTH-1:0] section_cast1; // sfix15_En11
wire signed [FILTER_WIDTH-1:0] sum1; // sfix15_En11
reg signed [FILTER_WIDTH-1:0] section_out1 = 0; // sfix15_En11
wire signed [FILTER_WIDTH-1:0] add_cast; // sfix15_En11
wire signed [FILTER_WIDTH-1:0] add_cast_1; // sfix15_En11
wire signed [FILTER_WIDTH:0] add_temp; // sfix16_En11
// -- Section 2 Signals
wire signed [FILTER_WIDTH-1:0] section_in2; // sfix15_En11
wire signed [FILTER_WIDTH-1:0] sum2; // sfix15_En11
reg signed [FILTER_WIDTH-1:0] section_out2 = 0; // sfix15_En11
wire signed [FILTER_WIDTH-1:0] add_cast_2; // sfix15_En11
wire signed [FILTER_WIDTH-1:0] add_cast_3; // sfix15_En11
wire signed [FILTER_WIDTH:0] add_temp_1; // sfix16_En11
// -- Section 3 Signals
wire signed [FILTER_WIDTH-1:0] section_in3; // sfix15_En11
wire signed [FILTER_WIDTH-1:0] sum3; // sfix15_En11
reg signed [FILTER_WIDTH-1:0] section_out3 = 0; // sfix15_En11
wire signed [FILTER_WIDTH-1:0] add_cast_4; // sfix15_En11
wire signed [FILTER_WIDTH-1:0] add_cast_5; // sfix15_En11
wire signed [FILTER_WIDTH:0] add_temp_2; // sfix16_En11
// -- Section 4 Signals
wire signed [FILTER_WIDTH-1:0] section_in4; // sfix15_En11
reg signed [FILTER_WIDTH-1:0] diff1 = 0; // sfix15_En11
wire signed [FILTER_WIDTH-1:0] section_out4; // sfix15_En11
wire signed [FILTER_WIDTH-1:0] sub_cast; // sfix15_En11
wire signed [FILTER_WIDTH-1:0] sub_cast_1; // sfix15_En11
wire signed [FILTER_WIDTH:0] sub_temp; // sfix16_En11
// -- Section 5 Signals
wire signed [FILTER_WIDTH-1:0] section_in5; // sfix15_En11
reg signed [FILTER_WIDTH-1:0] diff2 = 0; // sfix15_En11
wire signed [FILTER_WIDTH-1:0] section_out5; // sfix15_En11
wire signed [FILTER_WIDTH-1:0] sub_cast_2; // sfix15_En11
wire signed [FILTER_WIDTH-1:0] sub_cast_3; // sfix15_En11
wire signed [FILTER_WIDTH:0] sub_temp_1; // sfix16_En11
// -- Section 6 Signals
wire signed [FILTER_WIDTH-1:0] section_in6; // sfix15_En11
reg signed [FILTER_WIDTH-1:0] diff3 = 0; // sfix15_En11
wire signed [FILTER_WIDTH-1:0] section_out6; // sfix15_En11
wire signed [FILTER_WIDTH-1:0] sub_cast_4; // sfix15_En11
wire signed [FILTER_WIDTH-1:0] sub_cast_5; // sfix15_En11
wire signed [FILTER_WIDTH:0] sub_temp_2; // sfix16_En11
//
reg signed [FILTER_WIDTH-1:0] output_register = 0; // sfix15_En11
// Block Statements
// ------------------ CE Output Generation ------------------
always @ (posedge clk or posedge reset)
begin: ce_output
if (reset == 1'b1) begin
cur_count <= 16'd0;
end
else begin
if (clk_enable == 1'b1) begin
if (cur_count == FACTOR-1) begin
cur_count <= 16'd0;
end
else begin
cur_count <= cur_count + 1;
end
end
end
end // ce_output
assign phase_1 = (cur_count == 16'd1 && clk_enable == 1'b1)? 1 : 0;
// ------------------ CE Output Register ------------------
always @ (posedge clk or posedge reset)
begin: ce_output_register
if (reset == 1'b1) begin
ce_out_reg <= 1'b0;
end
else begin
ce_out_reg <= phase_1;
end
end // ce_output_register
// ------------------ Input Register ------------------
always @ (posedge clk or posedge reset)
begin: input_reg_process
if (reset == 1'b1) begin
input_register <= 0;
end
else begin
if (clk_enable == 1'b1) begin
input_register <= filter_in;
end
end
end // input_reg_process
// ------------------ Section # 1 : Integrator ------------------
assign section_in1 = input_register;
assign section_cast1 = $signed({{(FILTER_WIDTH-INPUT_WIDTH){section_in1[INPUT_WIDTH-1]}}, section_in1});
assign add_cast = section_cast1;
assign add_cast_1 = section_out1;
assign add_temp = add_cast + add_cast_1;
assign sum1 = add_temp[FILTER_WIDTH-1:0];
always @ (posedge clk or posedge reset)
begin: integrator_delay_section1
if (reset == 1'b1) begin
section_out1 <= 0;
end
else begin
if (clk_enable == 1'b1) begin
section_out1 <= sum1;
end
end
end // integrator_delay_section1
// ------------------ Section # 2 : Integrator ------------------
assign section_in2 = section_out1;
assign add_cast_2 = section_in2;
assign add_cast_3 = section_out2;
assign add_temp_1 = add_cast_2 + add_cast_3;
assign sum2 = add_temp_1[FILTER_WIDTH-1:0];
always @ (posedge clk or posedge reset)
begin: integrator_delay_section2
if (reset == 1'b1) begin
section_out2 <= 0;
end
else begin
if (clk_enable == 1'b1) begin
section_out2 <= sum2;
end
end
end // integrator_delay_section2
// ------------------ Section # 3 : Integrator ------------------
assign section_in3 = section_out2;
assign add_cast_4 = section_in3;
assign add_cast_5 = section_out3;
assign add_temp_2 = add_cast_4 + add_cast_5;
assign sum3 = add_temp_2[FILTER_WIDTH-1:0];
always @ (posedge clk or posedge reset)
begin: integrator_delay_section3
if (reset == 1'b1) begin
section_out3 <= 0;
end
else begin
if (clk_enable == 1'b1) begin
section_out3 <= sum3;
end
end
end // integrator_delay_section3
// ------------------ Section # 4 : Comb ------------------
assign section_in4 = section_out3;
assign sub_cast = section_in4;
assign sub_cast_1 = diff1;
assign sub_temp = sub_cast - sub_cast_1;
assign section_out4 = sub_temp[FILTER_WIDTH:0];
always @ (posedge clk or posedge reset)
begin: comb_delay_section4
if (reset == 1'b1) begin
diff1 <= 0;
end
else begin
if (phase_1 == 1'b1) begin
diff1 <= section_in4;
end
end
end // comb_delay_section4
// ------------------ Section # 5 : Comb ------------------
assign section_in5 = section_out4;
assign sub_cast_2 = section_in5;
assign sub_cast_3 = diff2;
assign sub_temp_1 = sub_cast_2 - sub_cast_3;
assign section_out5 = sub_temp_1[FILTER_WIDTH-1:0];
always @ (posedge clk or posedge reset)
begin: comb_delay_section5
if (reset == 1'b1) begin
diff2 <= 0;
end
else begin
if (phase_1 == 1'b1) begin
diff2 <= section_in5;
end
end
end // comb_delay_section5
// ------------------ Section # 6 : Comb ------------------
assign section_in6 = section_out5;
assign sub_cast_4 = section_in6;
assign sub_cast_5 = diff3;
assign sub_temp_2 = sub_cast_4 - sub_cast_5;
assign section_out6 = sub_temp_2[FILTER_WIDTH-1:0];
always @ (posedge clk or posedge reset)
begin: comb_delay_section6
if (reset == 1'b1) begin
diff3 <= 0;
end
else begin
if (phase_1 == 1'b1) begin
diff3 <= section_in6;
end
end
end // comb_delay_section6
// ------------------ Output Register ------------------
always @ (posedge clk or posedge reset)
begin: output_reg_process
if (reset == 1'b1) begin
output_register <= 0;
end
else begin
if (phase_1 == 1'b1) begin
output_register <= section_out6;
end
end
end // output_reg_process
// Assignment Statements
assign ce_out = ce_out_reg;
assign filter_out = output_register;
endmodule // CIC_DOWN_S3

View File

@ -0,0 +1,204 @@
`timescale 1 ns / 1 ns
module CIC_DOWN_S4 #(
parameter FACTOR = 10,
parameter INPUT_WIDTH = 12,
parameter OUTPUT_WIDTH = 15
) (
input clk,
input clk_enable,
input reset,
input signed [INPUT_WIDTH-1:0] filter_in,
output signed [OUTPUT_WIDTH-1:0] filter_out,
output ce_out
);
localparam FILTER_WIDTH = OUTPUT_WIDTH;
////////////////////////////////////////////////////////////////
//Module Architecture: CIC_DOWN_S4
////////////////////////////////////////////////////////////////
// Local Functions
// Type Definitions
// Constants
// Signals
reg [15:0] cur_count = 0; // ufix2
wire phase_1; // boolean
reg ce_out_reg = 0; // boolean
//
reg signed [INPUT_WIDTH-1:0] input_register = 0; // sfix16_En15
// -- Section 1 Signals
wire signed [INPUT_WIDTH-1:0] section_in1; // sfix16_En15
wire signed [FILTER_WIDTH-1:0] section_cast1; // sfix20_En15
wire signed [FILTER_WIDTH-1:0] sum1; // sfix20_En15
reg signed [FILTER_WIDTH-1:0] section_out1 = 0; // sfix20_En15
wire signed [FILTER_WIDTH-1:0] add_cast; // sfix20_En15
wire signed [FILTER_WIDTH-1:0] add_cast_1; // sfix20_En15
wire signed [FILTER_WIDTH:0] add_temp; // sfix21_En15
// -- Section 2 Signals
wire signed [FILTER_WIDTH-1:0] section_in2; // sfix20_En15
wire signed [FILTER_WIDTH-1:0] sum2; // sfix20_En15
reg signed [FILTER_WIDTH-1:0] section_out2 = 0; // sfix20_En15
wire signed [FILTER_WIDTH-1:0] add_cast_2; // sfix20_En15
wire signed [FILTER_WIDTH-1:0] add_cast_3; // sfix20_En15
wire signed [FILTER_WIDTH:0] add_temp_1; // sfix21_En15
// -- Section 3 Signals
wire signed [FILTER_WIDTH-1:0] section_in3; // sfix20_En15
reg signed [FILTER_WIDTH-1:0] diff1 = 0; // sfix20_En15
wire signed [FILTER_WIDTH-1:0] section_out3; // sfix20_En15
wire signed [FILTER_WIDTH-1:0] sub_cast; // sfix20_En15
wire signed [FILTER_WIDTH-1:0] sub_cast_1; // sfix20_En15
wire signed [FILTER_WIDTH:0] sub_temp; // sfix21_En15
// -- Section 4 Signals
wire signed [FILTER_WIDTH-1:0] section_in4; // sfix20_En15
reg signed [FILTER_WIDTH-1:0] diff2 = 0; // sfix20_En15
wire signed [FILTER_WIDTH-1:0] section_out4; // sfix20_En15
wire signed [FILTER_WIDTH-1:0] sub_cast_2; // sfix20_En15
wire signed [FILTER_WIDTH-1:0] sub_cast_3; // sfix20_En15
wire signed [FILTER_WIDTH:0] sub_temp_1; // sfix21_En15
//
reg signed [FILTER_WIDTH-1:0] output_register = 0; // sfix20_En15
// Block Statements
// ------------------ CE Output Generation ------------------
always @ (posedge clk or posedge reset) begin: ce_output
if (reset == 1'b1) begin
cur_count <= 16'd0;
end
else begin
if (clk_enable == 1'b1) begin
if (cur_count == FACTOR-1) begin
cur_count <= 16'd0;
end
else begin
cur_count <= cur_count + 1;
end
end
end
end // ce_output
assign phase_1 = (cur_count == 16'd1 && clk_enable == 1'b1)? 1 : 0;
// ------------------ CE Output Register ------------------
always @ (posedge clk or posedge reset) begin: ce_output_register
if (reset == 1'b1) begin
ce_out_reg <= 1'b0;
end
else begin
ce_out_reg <= phase_1;
end
end // ce_output_register
// ------------------ Input Register ------------------
always @ (posedge clk or posedge reset) begin: input_reg_process
if (reset == 1'b1) begin
input_register <= 0;
end
else begin
if (clk_enable == 1'b1) begin
input_register <= filter_in;
end
end
end // input_reg_process
// ------------------ Section # 1 : Integrator ------------------
assign section_in1 = input_register;
assign section_cast1 = $signed({{(FILTER_WIDTH-INPUT_WIDTH){section_in1[INPUT_WIDTH-1]}}, section_in1});
assign add_cast = section_cast1;
assign add_cast_1 = section_out1;
assign add_temp = add_cast + add_cast_1;
assign sum1 = add_temp[FILTER_WIDTH-1:0];
always @ (posedge clk or posedge reset) begin: integrator_delay_section1
if (reset == 1'b1) begin
section_out1 <= 0;
end
else begin
if (clk_enable == 1'b1) begin
section_out1 <= sum1;
end
end
end // integrator_delay_section1
// ------------------ Section # 2 : Integrator ------------------
assign section_in2 = section_out1;
assign add_cast_2 = section_in2;
assign add_cast_3 = section_out2;
assign add_temp_1 = add_cast_2 + add_cast_3;
assign sum2 = add_temp_1[FILTER_WIDTH-1:0];
always @ (posedge clk or posedge reset) begin: integrator_delay_section2
if (reset == 1'b1) begin
section_out2 <= 0;
end
else begin
if (clk_enable == 1'b1) begin
section_out2 <= sum2;
end
end
end // integrator_delay_section2
// ------------------ Section # 3 : Comb ------------------
assign section_in3 = section_out2;
assign sub_cast = section_in3;
assign sub_cast_1 = diff1;
assign sub_temp = sub_cast - sub_cast_1;
assign section_out3 = sub_temp[FILTER_WIDTH-1:0];
always @ (posedge clk or posedge reset) begin: comb_delay_section3
if (reset == 1'b1) begin
diff1 <= 0;
end
else begin
if (phase_1 == 1'b1) begin
diff1 <= section_in3;
end
end
end // comb_delay_section3
// ------------------ Section # 4 : Comb ------------------
assign section_in4 = section_out3;
assign sub_cast_2 = section_in4;
assign sub_cast_3 = diff2;
assign sub_temp_1 = sub_cast_2 - sub_cast_3;
assign section_out4 = sub_temp_1[FILTER_WIDTH-1:0];
always @ (posedge clk or posedge reset) begin: comb_delay_section4
if (reset == 1'b1) begin
diff2 <= 0;
end
else begin
if (phase_1 == 1'b1) begin
diff2 <= section_in4;
end
end
end // comb_delay_section4
// ------------------ Output Register ------------------
always @ (posedge clk or posedge reset) begin: output_reg_process
if (reset == 1'b1) begin
output_register <= 0;
end
else begin
if (phase_1 == 1'b1) begin
output_register <= section_out4;
end
end
end // output_reg_process
// Assignment Statements
assign ce_out = ce_out_reg;
assign filter_out = output_register;
endmodule // CIC_DOWN_S4

Binary file not shown.

View File

@ -0,0 +1,43 @@
module circuit(
input clk,
input reset,
input [7:0] fmin,
output [11:0] dmout
);
wire [11:0] d1;
wire [11:0] d2;
wire [7:0] dout;
wire [7:0] output_xhdl0;
multiplier I1(
.clk(clk),
.reset(reset),
.input1(fmin),
.input2(dout),
.output_xhdl0(output_xhdl0)
);
fir I4(
.clock(clk),
.reset(reset),
.data_in(d1),
.data_out(dmout)
);
loop_filter I3(
.clk(clk),
.reset(reset),
.c(output_xhdl0),
.d1(d1),
.d2(d2)
);
nco I2(
.clk(clk),
.reset(reset),
.din(d2),
.dout(dout)
);
endmodule

View File

@ -0,0 +1,72 @@
module FIR(clock, reset, data_in, data_out);
input clock;
input reset;
input [11:0] data_in;
output [11:0] data_out;
reg [11:0] data_out;
reg [15:0] d0;
reg [15:0] d1;
reg [15:0] d2;
reg [15:0] d3;
reg [15:0] d4;
reg [15:0] d5;
reg [15:0] d6;
reg [15:0] d7;
reg [15:0] d8;
reg [15:0] d9;
reg [15:0] d10;
reg [15:0] d11;
reg [15:0] d12;
reg [15:0] d13;
reg [15:0] d14;
reg [15:0] d15;
reg [15:0] sum;
always @(posedge clock or posedge reset)
if (reset == 1'b1)
begin
d0 <= {16{1'b0}};
d1 <= {16{1'b0}};
d2 <= {16{1'b0}};
d3 <= {16{1'b0}};
d4 <= {16{1'b0}};
d5 <= {16{1'b0}};
d6 <= {16{1'b0}};
d7 <= {16{1'b0}};
d8 <= {16{1'b0}};
d9 <= {16{1'b0}};
d10 <= {16{1'b0}};
d11 <= {16{1'b0}};
d12 <= {16{1'b0}};
d13 <= {16{1'b0}};
d14 <= {16{1'b0}};
d15 <= {16{1'b0}};
sum <= {16{1'b0}};
data_out <= {12{1'b0}};
end
else
begin
d0 <= {data_in[11], data_in[11], data_in[11], data_in[11], data_in};
d1 <= d0;
d2 <= d1;
d3 <= d2;
d4 <= d3;
d5 <= d4;
d6 <= d5;
d7 <= d6;
d8 <= d7;
d9 <= d8;
d10 <= d9;
d11 <= d10;
d12 <= d11;
d13 <= d12;
d14 <= d13;
d15 <= d14;
sum <= (d0 + d1 + d2 + d3 + d4 + d5 + d6 + d7 + d8 + d9 + d10 + d11 + d12 + d13 + d14 + d15) >> 4;
data_out <= (sum[11:0]);
end
endmodule

View File

@ -0,0 +1,29 @@
module loop_filter(CLK, RESET, C, D1, D2);
input CLK;
input RESET;
input [7:0] C;
output [11:0] D1;
output [11:0] D2;
reg [11:0] D1;
reg [11:0] D2;
reg [11:0] E;
reg [11:0] dtemp;
always @(posedge CLK or posedge RESET)
if (RESET == 1'b1) begin
D1 <= {12{1'b0}};
D2 <= {12{1'b0}};
E <= {12{1'b0}};
dtemp <= {12{1'b0}};
end
else begin
dtemp <= ({C[7], C[7], C[7], C, 1'b0}) + dtemp - E;
E <= {dtemp[11], dtemp[11], dtemp[11], dtemp[11], dtemp[11:4]};
D1 <= dtemp;
D2 <= {dtemp[11:4], 4'b0000};
end
endmodule

View File

@ -0,0 +1,148 @@
//--------------------------------------------------------------------------------------------
//
// Generated by X-HDL VHDL Translator - Version 2.0.0 Feb. 1, 2011
// ?? 3? 29 2020 15:44:24
//
// Input file :
// Component name : multiplier
// Author :
// Company :
//
// Description :
//
//
//--------------------------------------------------------------------------------------------
module multiplier(CLK, RESET, input1, input2, output_xhdl0);
input CLK;
input RESET;
input [7:0] input1;
input [7:0] input2;
output [7:0] output_xhdl0;
reg [7:0] output_xhdl0;
reg [15:0] out_temp;
reg [15:0] input1_buf;
reg [15:0] part0;
reg [15:0] part1;
reg [15:0] part2;
reg [15:0] part3;
reg [15:0] part4;
reg [15:0] part5;
reg [15:0] part6;
reg [15:0] part7;
always @(posedge CLK or posedge RESET)
if (RESET == 1'b1)
begin
out_temp <= {16{1'b0}};
output_xhdl0 <= {8{1'b0}};
input1_buf <= {16{1'b0}};
part0 <= {16{1'b0}};
part1 <= {16{1'b0}};
part2 <= {16{1'b0}};
part3 <= {16{1'b0}};
part4 <= {16{1'b0}};
part5 <= {16{1'b0}};
part6 <= {16{1'b0}};
part7 <= {16{1'b0}};
end
else
begin
input1_buf <= {input1[7], input1[7], input1[7], input1[7], input1[7], input1[7], input1[7], input1[7], signed_xhdl1(input1)};
if (input2[0] == 1'b1)
part0 <= -(input1_buf);
else
part0 <= {16{1'b0}};
if (input2[1] == 1'b1)
begin
if (input2[0] == 1'b1)
part1 <= {16{1'b0}};
else
part1 <= -(input1_buf);
end
else
if (input2[0] == 1'b1)
part1 <= input1_buf;
else
part1 <= {16{1'b0}};
if (input2[2] == 1'b1)
begin
if (input2[1] == 1'b1)
part2 <= {16{1'b0}};
else
part2 <= -(input1_buf);
end
else
if (input2[1] == 1'b1)
part2 <= input1_buf;
else
part2 <= {16{1'b0}};
if (input2[3] == 1'b1)
begin
if (input2[2] == 1'b1)
part3 <= {16{1'b0}};
else
part3 <= -(input1_buf);
end
else
if (input2[2] == 1'b1)
part3 <= input1_buf;
else
part3 <= {16{1'b0}};
if (input2[4] == 1'b1)
begin
if (input2[3] == 1'b1)
part4 <= {16{1'b0}};
else
part4 <= -(input1_buf);
end
else
if (input2[3] == 1'b1)
part4 <= input1_buf;
else
part4 <= {16{1'b0}};
if (input2[5] == 1'b1)
begin
if (input2[4] == 1'b1)
part5 <= {16{1'b0}};
else
part5 <= -(input1_buf);
end
else
if (input2[4] == 1'b1)
part5 <= input1_buf;
else
part5 <= {16{1'b0}};
if (input2[6] == 1'b1)
begin
if (input2[5] == 1'b1)
part6 <= {16{1'b0}};
else
part6 <= -(input1_buf);
end
else
if (input2[5] == 1'b1)
part6 <= input1_buf;
else
part6 <= {16{1'b0}};
if (input2[7] == 1'b1)
begin
if (input2[6] == 1'b1)
part7 <= {16{1'b0}};
else
part7 <= -(input1_buf);
end
else
if (input2[6] == 1'b1)
part7 <= input1_buf;
else
part7 <= {16{1'b0}};
out_temp <= part0 + ({part1[14:0], 1'b0}) + ({part2[13:0], 2'b00}) + ({part3[12:0], 3'b000}) + ({part4[11:0], 4'b0000}) + ({part5[10:0], 5'b00000}) + ({part6[9:0], 6'b000000}) + ({part7[8:0], 7'b0000000});
output_xhdl0 <= out_temp[15:8];
end
endmodule

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

View File

@ -0,0 +1,90 @@
/*
奇数倍分频奇数倍分频常常在论坛上有人问起,实际上,奇数倍分频有两种实现方法
首先,完全可以通过计数器来实现,如进行三分频,通过待分频时钟 上升沿触发计数器进行模三计数,
当计数器计数到邻近值进行两次翻转,比如可以在计数器计数到1时,输出时钟进行翻转,计数到2时再次进行翻转
即是在计数 值在邻近的1和2进行了两次翻转这样实现的三分频占空比为1/3或者2/3
如果要实现占空比为50%的三分频时钟,
可以通过待分频时钟下降沿触发计数,和上升沿同样的方法计数进行三分频,
然后下降沿产生的三分频时钟和上升沿产生的时钟进行相或运算,即可得到占空比为50%的三分频时钟
这种方法可以 实现任意的奇数分频
归类为一般的方法为对于实现占空比为50%的N倍奇数分频,
首先进行上升沿触发进行模N计数,计数选定到某一个值进行输出时钟翻 ,然后经过N-1/2再次进行翻转得到一个占空比非50%奇数n分频时钟
再者同时进行下降沿触发的模N计数,到和上升沿触发输出时钟翻转选定值相 同值时,
进行输出时钟时钟翻转,同样经过N-1/2时,输出时钟再次翻转生成占空比非50%的奇数n分频时钟
两个占空比非50%的n分频时钟相或运 ,得到占空比为50%的奇数n分频时钟
另外一种方法对进行奇数倍n分频时钟,首先进行n/2分频带小数,即等于(n-1)/2+0.5,
然后再 进行二分频得到得到占空比为50%的奇数倍分频
*/
/*******************************************************************************/
// wire clk_div;
// CLK_DIV #
// (.WIDTH(8))
// CLK_DIV_u
// (
// .clk_in(clk_sys),
// .rst_n(1'b1),
// .N(2),
// .clk_div(clk_div)
// );
/*******************************************************************************/
`timescale 1ns / 1ps
module CLK_DIV #
(
parameter WIDTH = 8
)
(
input clk_in,
input rst_n,
input [WIDTH - 1:0] N,
output clk_div
);
reg [WIDTH-1:0] cnt_p = 0;// 上升沿计数单位
reg [WIDTH-1:0] cnt_n = 0;// 下降沿计数单位
reg clk_in_p = 0;// 上升沿时钟
reg clk_in_n = 0;// 下降沿时钟
//其中N==1是判断不分频N[0]是判断是奇数还是偶数若为1则是奇数分频若是偶数则是偶数分频
assign clk_div = (N == 1) ? clk_in : (N[0]) ? (clk_in_p | clk_in_n) : (clk_in_p);
always@(posedge clk_in or negedge rst_n) begin
if (!rst_n)
cnt_p <= 0;
else if (cnt_p == (N-1))
cnt_p <= 0;
else
cnt_p <= cnt_p + 1;
end
always@(posedge clk_in or negedge rst_n) begin
if (!rst_n)
clk_in_p <= 1;//此处设置为0也是可以的这个没有硬性的要求不管是取0还是取1结果都是正确的
else if (cnt_p < (N>>1))/*N整体向右移动一位最高位补零其实就是N/2不过在计算奇数的时候有很明显的优越性*/
clk_in_p <= 1;
else
clk_in_p <= 0;
end
always@(negedge clk_in or negedge rst_n) begin
if (!rst_n)
cnt_n <= 0;
else if (cnt_n == (N-1))
cnt_n <= 0;
else
cnt_n <= cnt_n + 1;
end
always@(negedge clk_in or negedge rst_n) begin
if (!rst_n)
clk_in_n <= 1;
else if (cnt_n < (N>>1))
clk_in_n <= 1;
else
clk_in_n <= 0;
end
endmodule

View File

@ -0,0 +1,19 @@
module CLK_Sample # (
parameter PHASE_WIDTH = 32
) (
input clk_in,
input RST,
input [PHASE_WIDTH-1:0] sample_fre,
output clk_sample
);
reg [PHASE_WIDTH-1:0] addr_r = 0;
always @(posedge clk_in) begin
if (RST)
addr_r <= 32'd0;
else
addr_r <= addr_r + sample_fre;
end
assign clk_sample = addr_r[PHASE_WIDTH-1];
endmodule

View File

@ -0,0 +1,327 @@
module DDS_Gen #(
parameter OUTPUT_WIDTH = 12,
parameter PHASE_WIDTH = 32
) (
input clk,
input [PHASE_WIDTH - 1 : 0] Fre_word, // (fre*4294967296)/clk/1000000
input [PHASE_WIDTH - 1 : 0] Pha_word, // (fre*4294967296)/clk/1000000
output [OUTPUT_WIDTH - 1 : 0] wave_out_sin,
output [OUTPUT_WIDTH - 1 : 0] wave_out_tri,
output [OUTPUT_WIDTH - 1 : 0] wave_out_saw
);
localparam [OUTPUT_WIDTH - 1 : 0] DC_SUB = 2**(OUTPUT_WIDTH-1);
reg [OUTPUT_WIDTH - 1 : 0] wave_out_sin_r;
reg [OUTPUT_WIDTH - 1 : 0] wave_out_tri_r;
reg [OUTPUT_WIDTH - 1 : 0] wave_out_saw_r;
reg [PHASE_WIDTH - 1 : 0] addr_r0 = 0;
reg [PHASE_WIDTH - 1 : 0] addr_r1 = 0;
always @(posedge clk) begin
addr_r0 <= addr_r0 + Fre_word;
addr_r1 <= addr_r0 + Pha_word;
end
always @(posedge clk ) begin
wave_out_saw_r <= addr_r1[PHASE_WIDTH - 1 : PHASE_WIDTH - OUTPUT_WIDTH];
end
assign wave_out_saw = wave_out_saw_r;
always @(posedge clk ) begin
if (addr_r1[PHASE_WIDTH - 1])
wave_out_tri_r <= (2**(OUTPUT_WIDTH + 1)-1) - addr_r1[PHASE_WIDTH - 1 : PHASE_WIDTH - OUTPUT_WIDTH - 1];
else
wave_out_tri_r <= addr_r1[PHASE_WIDTH - 1 : PHASE_WIDTH - OUTPUT_WIDTH - 1];
end
assign wave_out_tri = wave_out_tri_r - DC_SUB;
reg [9:0] addr_r = 0;
always @(posedge clk) begin
addr_r <= addr_r1[PHASE_WIDTH - 1 : PHASE_WIDTH - 10];
end
reg [7:0] addr;
always @(*) begin
case (addr_r[9:8])
2'b00 : begin addr <= addr_r[7:0]; end
2'b01 : begin addr <= addr_r[7:0] ^ 8'b1111_1111; end
2'b10 : begin addr <= addr_r[7:0]; end
2'b11 : begin addr <= addr_r[7:0] ^ 8'b1111_1111; end
default : begin addr <= 8'd0; end
endcase
end
reg signed [13:0] wave_sin_buf;
always @(*) begin
case (addr)
8'd0 : begin wave_sin_buf <= 0; end
8'd1 : begin wave_sin_buf <= 50; end
8'd2 : begin wave_sin_buf <= 101; end
8'd3 : begin wave_sin_buf <= 151; end
8'd4 : begin wave_sin_buf <= 201; end
8'd5 : begin wave_sin_buf <= 252; end
8'd6 : begin wave_sin_buf <= 302; end
8'd7 : begin wave_sin_buf <= 352; end
8'd8 : begin wave_sin_buf <= 402; end
8'd9 : begin wave_sin_buf <= 453; end
8'd10 : begin wave_sin_buf <= 503; end
8'd11 : begin wave_sin_buf <= 553; end
8'd12 : begin wave_sin_buf <= 603; end
8'd13 : begin wave_sin_buf <= 653; end
8'd14 : begin wave_sin_buf <= 703; end
8'd15 : begin wave_sin_buf <= 754; end
8'd16 : begin wave_sin_buf <= 804; end
8'd17 : begin wave_sin_buf <= 854; end
8'd18 : begin wave_sin_buf <= 904; end
8'd19 : begin wave_sin_buf <= 954; end
8'd20 : begin wave_sin_buf <= 1004; end
8'd21 : begin wave_sin_buf <= 1054; end
8'd22 : begin wave_sin_buf <= 1103; end
8'd23 : begin wave_sin_buf <= 1153; end
8'd24 : begin wave_sin_buf <= 1203; end
8'd25 : begin wave_sin_buf <= 1253; end
8'd26 : begin wave_sin_buf <= 1302; end
8'd27 : begin wave_sin_buf <= 1352; end
8'd28 : begin wave_sin_buf <= 1402; end
8'd29 : begin wave_sin_buf <= 1451; end
8'd30 : begin wave_sin_buf <= 1501; end
8'd31 : begin wave_sin_buf <= 1550; end
8'd32 : begin wave_sin_buf <= 1600; end
8'd33 : begin wave_sin_buf <= 1649; end
8'd34 : begin wave_sin_buf <= 1698; end
8'd35 : begin wave_sin_buf <= 1747; end
8'd36 : begin wave_sin_buf <= 1796; end
8'd37 : begin wave_sin_buf <= 1845; end
8'd38 : begin wave_sin_buf <= 1894; end
8'd39 : begin wave_sin_buf <= 1943; end
8'd40 : begin wave_sin_buf <= 1992; end
8'd41 : begin wave_sin_buf <= 2041; end
8'd42 : begin wave_sin_buf <= 2090; end
8'd43 : begin wave_sin_buf <= 2138; end
8'd44 : begin wave_sin_buf <= 2187; end
8'd45 : begin wave_sin_buf <= 2235; end
8'd46 : begin wave_sin_buf <= 2284; end
8'd47 : begin wave_sin_buf <= 2332; end
8'd48 : begin wave_sin_buf <= 2380; end
8'd49 : begin wave_sin_buf <= 2428; end
8'd50 : begin wave_sin_buf <= 2476; end
8'd51 : begin wave_sin_buf <= 2524; end
8'd52 : begin wave_sin_buf <= 2572; end
8'd53 : begin wave_sin_buf <= 2620; end
8'd54 : begin wave_sin_buf <= 2667; end
8'd55 : begin wave_sin_buf <= 2715; end
8'd56 : begin wave_sin_buf <= 2762; end
8'd57 : begin wave_sin_buf <= 2809; end
8'd58 : begin wave_sin_buf <= 2857; end
8'd59 : begin wave_sin_buf <= 2904; end
8'd60 : begin wave_sin_buf <= 2951; end
8'd61 : begin wave_sin_buf <= 2998; end
8'd62 : begin wave_sin_buf <= 3044; end
8'd63 : begin wave_sin_buf <= 3091; end
8'd64 : begin wave_sin_buf <= 3137; end
8'd65 : begin wave_sin_buf <= 3184; end
8'd66 : begin wave_sin_buf <= 3230; end
8'd67 : begin wave_sin_buf <= 3276; end
8'd68 : begin wave_sin_buf <= 3322; end
8'd69 : begin wave_sin_buf <= 3368; end
8'd70 : begin wave_sin_buf <= 3414; end
8'd71 : begin wave_sin_buf <= 3460; end
8'd72 : begin wave_sin_buf <= 3505; end
8'd73 : begin wave_sin_buf <= 3551; end
8'd74 : begin wave_sin_buf <= 3596; end
8'd75 : begin wave_sin_buf <= 3641; end
8'd76 : begin wave_sin_buf <= 3686; end
8'd77 : begin wave_sin_buf <= 3731; end
8'd78 : begin wave_sin_buf <= 3776; end
8'd79 : begin wave_sin_buf <= 3820; end
8'd80 : begin wave_sin_buf <= 3865; end
8'd81 : begin wave_sin_buf <= 3909; end
8'd82 : begin wave_sin_buf <= 3953; end
8'd83 : begin wave_sin_buf <= 3997; end
8'd84 : begin wave_sin_buf <= 4041; end
8'd85 : begin wave_sin_buf <= 4085; end
8'd86 : begin wave_sin_buf <= 4128; end
8'd87 : begin wave_sin_buf <= 4172; end
8'd88 : begin wave_sin_buf <= 4215; end
8'd89 : begin wave_sin_buf <= 4258; end
8'd90 : begin wave_sin_buf <= 4301; end
8'd91 : begin wave_sin_buf <= 4343; end
8'd92 : begin wave_sin_buf <= 4386; end
8'd93 : begin wave_sin_buf <= 4428; end
8'd94 : begin wave_sin_buf <= 4471; end
8'd95 : begin wave_sin_buf <= 4513; end
8'd96 : begin wave_sin_buf <= 4555; end
8'd97 : begin wave_sin_buf <= 4596; end
8'd98 : begin wave_sin_buf <= 4638; end
8'd99 : begin wave_sin_buf <= 4679; end
8'd100 : begin wave_sin_buf <= 4720; end
8'd101 : begin wave_sin_buf <= 4761; end
8'd102 : begin wave_sin_buf <= 4802; end
8'd103 : begin wave_sin_buf <= 4843; end
8'd104 : begin wave_sin_buf <= 4883; end
8'd105 : begin wave_sin_buf <= 4924; end
8'd106 : begin wave_sin_buf <= 4964; end
8'd107 : begin wave_sin_buf <= 5004; end
8'd108 : begin wave_sin_buf <= 5044; end
8'd109 : begin wave_sin_buf <= 5083; end
8'd110 : begin wave_sin_buf <= 5122; end
8'd111 : begin wave_sin_buf <= 5162; end
8'd112 : begin wave_sin_buf <= 5201; end
8'd113 : begin wave_sin_buf <= 5239; end
8'd114 : begin wave_sin_buf <= 5278; end
8'd115 : begin wave_sin_buf <= 5316; end
8'd116 : begin wave_sin_buf <= 5354; end
8'd117 : begin wave_sin_buf <= 5392; end
8'd118 : begin wave_sin_buf <= 5430; end
8'd119 : begin wave_sin_buf <= 5468; end
8'd120 : begin wave_sin_buf <= 5505; end
8'd121 : begin wave_sin_buf <= 5542; end
8'd122 : begin wave_sin_buf <= 5579; end
8'd123 : begin wave_sin_buf <= 5616; end
8'd124 : begin wave_sin_buf <= 5652; end
8'd125 : begin wave_sin_buf <= 5689; end
8'd126 : begin wave_sin_buf <= 5725; end
8'd127 : begin wave_sin_buf <= 5761; end
8'd128 : begin wave_sin_buf <= 5796; end
8'd129 : begin wave_sin_buf <= 5832; end
8'd130 : begin wave_sin_buf <= 5867; end
8'd131 : begin wave_sin_buf <= 5902; end
8'd132 : begin wave_sin_buf <= 5937; end
8'd133 : begin wave_sin_buf <= 5971; end
8'd134 : begin wave_sin_buf <= 6006; end
8'd135 : begin wave_sin_buf <= 6040; end
8'd136 : begin wave_sin_buf <= 6074; end
8'd137 : begin wave_sin_buf <= 6107; end
8'd138 : begin wave_sin_buf <= 6141; end
8'd139 : begin wave_sin_buf <= 6174; end
8'd140 : begin wave_sin_buf <= 6207; end
8'd141 : begin wave_sin_buf <= 6239; end
8'd142 : begin wave_sin_buf <= 6272; end
8'd143 : begin wave_sin_buf <= 6304; end
8'd144 : begin wave_sin_buf <= 6336; end
8'd145 : begin wave_sin_buf <= 6368; end
8'd146 : begin wave_sin_buf <= 6399; end
8'd147 : begin wave_sin_buf <= 6431; end
8'd148 : begin wave_sin_buf <= 6462; end
8'd149 : begin wave_sin_buf <= 6493; end
8'd150 : begin wave_sin_buf <= 6523; end
8'd151 : begin wave_sin_buf <= 6553; end
8'd152 : begin wave_sin_buf <= 6584; end
8'd153 : begin wave_sin_buf <= 6613; end
8'd154 : begin wave_sin_buf <= 6643; end
8'd155 : begin wave_sin_buf <= 6672; end
8'd156 : begin wave_sin_buf <= 6701; end
8'd157 : begin wave_sin_buf <= 6730; end
8'd158 : begin wave_sin_buf <= 6759; end
8'd159 : begin wave_sin_buf <= 6787; end
8'd160 : begin wave_sin_buf <= 6815; end
8'd161 : begin wave_sin_buf <= 6843; end
8'd162 : begin wave_sin_buf <= 6870; end
8'd163 : begin wave_sin_buf <= 6897; end
8'd164 : begin wave_sin_buf <= 6925; end
8'd165 : begin wave_sin_buf <= 6951; end
8'd166 : begin wave_sin_buf <= 6978; end
8'd167 : begin wave_sin_buf <= 7004; end
8'd168 : begin wave_sin_buf <= 7030; end
8'd169 : begin wave_sin_buf <= 7056; end
8'd170 : begin wave_sin_buf <= 7081; end
8'd171 : begin wave_sin_buf <= 7106; end
8'd172 : begin wave_sin_buf <= 7131; end
8'd173 : begin wave_sin_buf <= 7156; end
8'd174 : begin wave_sin_buf <= 7180; end
8'd175 : begin wave_sin_buf <= 7204; end
8'd176 : begin wave_sin_buf <= 7228; end
8'd177 : begin wave_sin_buf <= 7251; end
8'd178 : begin wave_sin_buf <= 7275; end
8'd179 : begin wave_sin_buf <= 7298; end
8'd180 : begin wave_sin_buf <= 7320; end
8'd181 : begin wave_sin_buf <= 7343; end
8'd182 : begin wave_sin_buf <= 7365; end
8'd183 : begin wave_sin_buf <= 7387; end
8'd184 : begin wave_sin_buf <= 7408; end
8'd185 : begin wave_sin_buf <= 7430; end
8'd186 : begin wave_sin_buf <= 7451; end
8'd187 : begin wave_sin_buf <= 7472; end
8'd188 : begin wave_sin_buf <= 7492; end
8'd189 : begin wave_sin_buf <= 7512; end
8'd190 : begin wave_sin_buf <= 7532; end
8'd191 : begin wave_sin_buf <= 7552; end
8'd192 : begin wave_sin_buf <= 7571; end
8'd193 : begin wave_sin_buf <= 7590; end
8'd194 : begin wave_sin_buf <= 7609; end
8'd195 : begin wave_sin_buf <= 7627; end
8'd196 : begin wave_sin_buf <= 7646; end
8'd197 : begin wave_sin_buf <= 7664; end
8'd198 : begin wave_sin_buf <= 7681; end
8'd199 : begin wave_sin_buf <= 7698; end
8'd200 : begin wave_sin_buf <= 7715; end
8'd201 : begin wave_sin_buf <= 7732; end
8'd202 : begin wave_sin_buf <= 7749; end
8'd203 : begin wave_sin_buf <= 7765; end
8'd204 : begin wave_sin_buf <= 7781; end
8'd205 : begin wave_sin_buf <= 7796; end
8'd206 : begin wave_sin_buf <= 7812; end
8'd207 : begin wave_sin_buf <= 7827; end
8'd208 : begin wave_sin_buf <= 7841; end
8'd209 : begin wave_sin_buf <= 7856; end
8'd210 : begin wave_sin_buf <= 7870; end
8'd211 : begin wave_sin_buf <= 7884; end
8'd212 : begin wave_sin_buf <= 7897; end
8'd213 : begin wave_sin_buf <= 7910; end
8'd214 : begin wave_sin_buf <= 7923; end
8'd215 : begin wave_sin_buf <= 7936; end
8'd216 : begin wave_sin_buf <= 7948; end
8'd217 : begin wave_sin_buf <= 7960; end
8'd218 : begin wave_sin_buf <= 7972; end
8'd219 : begin wave_sin_buf <= 7983; end
8'd220 : begin wave_sin_buf <= 7994; end
8'd221 : begin wave_sin_buf <= 8005; end
8'd222 : begin wave_sin_buf <= 8016; end
8'd223 : begin wave_sin_buf <= 8026; end
8'd224 : begin wave_sin_buf <= 8036; end
8'd225 : begin wave_sin_buf <= 8045; end
8'd226 : begin wave_sin_buf <= 8055; end
8'd227 : begin wave_sin_buf <= 8064; end
8'd228 : begin wave_sin_buf <= 8072; end
8'd229 : begin wave_sin_buf <= 8081; end
8'd230 : begin wave_sin_buf <= 8089; end
8'd231 : begin wave_sin_buf <= 8097; end
8'd232 : begin wave_sin_buf <= 8104; end
8'd233 : begin wave_sin_buf <= 8111; end
8'd234 : begin wave_sin_buf <= 8118; end
8'd235 : begin wave_sin_buf <= 8125; end
8'd236 : begin wave_sin_buf <= 8131; end
8'd237 : begin wave_sin_buf <= 8137; end
8'd238 : begin wave_sin_buf <= 8142; end
8'd239 : begin wave_sin_buf <= 8148; end
8'd240 : begin wave_sin_buf <= 8153; end
8'd241 : begin wave_sin_buf <= 8157; end
8'd242 : begin wave_sin_buf <= 8162; end
8'd243 : begin wave_sin_buf <= 8166; end
8'd244 : begin wave_sin_buf <= 8170; end
8'd245 : begin wave_sin_buf <= 8173; end
8'd246 : begin wave_sin_buf <= 8176; end
8'd247 : begin wave_sin_buf <= 8179; end
8'd248 : begin wave_sin_buf <= 8182; end
8'd249 : begin wave_sin_buf <= 8184; end
8'd250 : begin wave_sin_buf <= 8186; end
8'd251 : begin wave_sin_buf <= 8188; end
8'd252 : begin wave_sin_buf <= 8189; end
8'd253 : begin wave_sin_buf <= 8190; end
8'd254 : begin wave_sin_buf <= 8191; end
8'd255 : begin wave_sin_buf <= 8191; end
default : begin wave_sin_buf <= 0; end
endcase
end
always @(*) begin
case (addr_r[9])
1'b0 : begin wave_out_sin_r <= wave_sin_buf[13 : 14 - OUTPUT_WIDTH]; end
1'b1 : begin wave_out_sin_r <= -wave_sin_buf[13 : 14 - OUTPUT_WIDTH]; end
default : begin wave_out_sin_r <= 14'd0; end
endcase
end
assign wave_out_sin = wave_out_sin_r;
endmodule

View File

@ -0,0 +1,96 @@
module Fre_meas(
input clk_in,
input square,
input [31:0] GATE_TIME,
output [31:0] CNTCLK, //闸门内系统时钟周期计数
output [31:0] CNTSQU //闸门内待测方波时钟周期计数
);
//parameter GATE_TIME = 28'd49_999_999;//实际闸门计数是99_999_999仿真时设为10ms
reg square_r0 = 1'b0;
reg square_r1 = 1'b0;
reg square_r2 = 1'b0;
reg square_r3 = 1'b0;
reg gate = 1'b0; //闸门信号
reg gatebuf = 1'b0; //与方波同步之后的闸门信号
reg gatebuf1 = 1'b0;//同步闸门信号延时一拍
reg [31:0] cnt1 = 28'd0; //产生 1s 的闸门信号的计数器
reg [31:0] cnt2 = 28'd0;
reg [31:0] cnt2_r = 28'd0;
reg [31:0] cnt3 = 28'd0;
reg [31:0] cnt3_r = 28'd0;
wire square_pose,square_nege;
wire gate_start,gate_end;
//使方波和100MHz时钟同步并捕捉待测方波的边沿
always @ (posedge clk_in)
begin
square_r0 <= square;
square_r1 <= square_r0;//将外部输入的方波打两拍
square_r2 <= square_r1;
square_r3 <= square_r2;
end
assign square_pose = square_r2 & ~square_r3;
assign square_nege = ~square_r2 & square_r3;
always @ (posedge clk_in)
begin
if(cnt1 == GATE_TIME)begin
cnt1 <= 28'd0;
gate <= ~gate;//产生 1s 的闸门信号
end
else begin
cnt1 <= cnt1 + 1'b1;
end
end
always @ (posedge clk_in )
begin
if(square_pose == 1'b1)
begin
gatebuf <= gate;//使闸门信号与待测方波同步保证一个闸门包含整数个方波周期
end
gatebuf1 <= gatebuf;//将同步之后的闸门信号打一拍用于捕捉闸门信号的边沿
end
assign gate_start = gatebuf & ~gatebuf1;//表示闸门开始时刻
assign gate_end = ~gatebuf & gatebuf1;//闸门结束时刻
//计数系统时钟周期
always @ (posedge clk_in)
begin
if(gate_start == 1'b1) begin
cnt2 <= 28'd1;
end
else if(gate_end == 1'b1) begin
cnt2_r <= cnt2;//将所得结果保存在cnt2_r中并将计数器清零
cnt2 <= 28'd0;
end
else if(gatebuf1 == 1'b1) begin//在闸门内计数系统时钟周期
cnt2 <= cnt2 + 1'b1;end
end
//计数待测方波周期数
always @ (posedge clk_in )
begin
if(gate_start == 1'b1) begin
cnt3 <= 28'd0;
end
else if(gate_end == 1'b1) begin
cnt3_r <= cnt3;//将所得结果保存在cnt3_r中并将计数器清零
cnt3 <= 28'd0;
end
else if(gatebuf1 == 1'b1 && square_nege == 1'b1) begin//在闸门内计数待测方波周期数(数闸门内方波的下降沿
cnt3 <= cnt3 + 1'b1;
end
end
assign CNTCLK = cnt2_r;
assign CNTSQU = cnt3_r;
endmodule

View File

@ -0,0 +1,101 @@
module Max_meas #
(
parameter data_width = 4'd12,
parameter range_width = 4'd10
)
(
input clk_in,
input rst_n,
input [range_width-1:0] range,
input signed [data_width - 1:0] data_in,
output signed [data_width - 1:0] data_out
);
localparam state_output = 3'b010;
localparam state_initial = 3'b000;
localparam state_detection = 3'b001;
reg signed [data_width - 1:0] data_out_buf = 0;
reg signed [data_width - 1:0] data_out_buf1 = 0;
reg [2:0] state = 3'b000;
reg test_sig = 1'b0;
reg test_sig_buf = 1'b0;
wire test_done_sig = ~test_sig & test_sig_buf;
wire test_start_sig = test_sig & ~test_sig_buf;
/***************************************************/
//define the time counter
reg [range_width-1:0] cnt0 = 1;
always@(posedge clk_in)
begin
if (range == 0)
begin
test_sig <= 1'b1;
end
else if (cnt0 == range)
begin
cnt0 <= 10'd0; //count done,clearing the time counter
test_sig <= 1'd0;
end
else
test_sig <= 1'd1; //cnt0 counter = cnt0 counter + 1
cnt0 <= cnt0 + 1'b1;
end
/***************************************************/
always@(posedge clk_in)
begin
if (range == 0)
begin
test_sig_buf <= 1'b0;
end
else
begin
test_sig_buf <= test_sig;
end
end
always@(posedge clk_in or negedge rst_n)
begin
if(!rst_n)
begin
data_out_buf <= 0;
data_out_buf1 <= 0;
end
else
begin
case(state)
state_initial:begin
if(test_start_sig)
begin
state <= state_detection;
data_out_buf <= 0;
end
end
state_detection:begin
if(test_done_sig)
state <= state_output;
else
if(data_in > data_out_buf)
begin
data_out_buf <= data_in;
if (range == 0)
begin
data_out_buf1 <= data_out_buf;
end
end
end
state_output:begin
data_out_buf1 <= data_out_buf;
state <= state_initial;
end
endcase
end
end
assign data_out=data_out_buf1;
endmodule

View File

@ -0,0 +1,101 @@
module Min_meas #
(
parameter data_width = 4'd12,
parameter range_width = 4'd10
)
(
input clk_in,
input rst_n,
input [range_width-1:0] range,
input signed [data_width - 1:0] data_in,
output signed [data_width - 1:0] data_out
);
localparam state_output = 3'b010;
localparam state_initial = 3'b000;
localparam state_detection = 3'b001;
reg signed [data_width - 1:0] data_out_buf = 0;
reg signed [data_width - 1:0] data_out_buf1 = 0;
reg [2:0] state = 3'b000;
reg test_sig = 1'b0;
reg test_sig_buf = 1'b0;
wire test_done_sig = ~test_sig & test_sig_buf;
wire test_start_sig = test_sig & ~test_sig_buf;
/***************************************************/
//define the time counter
reg [range_width-1:0] cnt0 = 1;
always@(posedge clk_in)
begin
if (range == 0)
begin
test_sig <= 1'b1;
end
else if (cnt0 == range)
begin
cnt0 <= 10'd0; //count done,clearing the time counter
test_sig <= 1'd0;
end
else
test_sig <= 1'd1; //cnt0 counter = cnt0 counter + 1
cnt0 <= cnt0 + 1'b1;
end
/***************************************************/
always@(posedge clk_in)
begin
if (range == 0)
begin
test_sig_buf <= 1'b0;
end
else
begin
test_sig_buf <= test_sig;
end
end
always@(posedge clk_in or negedge rst_n)
begin
if(!rst_n)
begin
data_out_buf <= 0;
data_out_buf1 <= 0;
end
else
begin
case(state)
state_initial:begin
if(test_start_sig)
begin
state <= state_detection;
data_out_buf <= 0;
end
end
state_detection:begin
if(test_done_sig)
state <= state_output;
else
if(data_in > data_out_buf)
begin
data_out_buf <= data_in;
if (range == 0)
begin
data_out_buf1 <= data_out_buf;
end
end
end
state_output:begin
data_out_buf1 <= data_out_buf;
state <= state_initial;
end
endcase
end
end
assign data_out=data_out_buf1;
endmodule

View File

@ -0,0 +1,76 @@
`timescale 1ns / 1ps
module measure
(
input clk_sys,
input clk_samp,
input rst_n,
input mearsure_start,
input [11:0] AD_data,
output measure_done_q,
output [21:0] data_out
);
parameter cnt_clear = 22'd255;
reg clk_samp_buf0;
reg clk_samp_buf1;
wire clk_samp_impluse = clk_samp_buf0 & ~clk_samp_buf1;//采样脉冲信号
wire [21:0] mult_data;
reg [16:0] cnt;
reg [39:0] sig_energy;
reg [21:0] data_out_buf;
reg measure_en;
wire measure_done = (cnt == cnt_clear) ? 1'b1:1'b0;
assign measure_done_q = measure_done;
always@(posedge clk_sys)
begin
clk_samp_buf0 <= clk_samp;
clk_samp_buf1 <= clk_samp_buf0;
end
always@(posedge clk_sys)
begin
if(!rst_n)
begin
measure_en <= 1'b0;
end
else if(mearsure_start)
measure_en <= 1'b1;
else if(measure_done)
measure_en <= 1'b0;
else
measure_en <= measure_en;
end
always@(posedge clk_sys)
begin
if(!rst_n)
begin
sig_energy <= 40'd0;
cnt <= 17'd0;
data_out_buf <= 22'd0;
end
else if(cnt == cnt_clear)
begin
sig_energy <= 40'd0;
data_out_buf <= sig_energy[39:8];
cnt <= 17'd0;
end
else if(clk_samp_impluse && measure_en)
begin
cnt <= cnt + 17'd1;
sig_energy <= sig_energy + mult_data;
end
else
begin
sig_energy <= sig_energy;
data_out_buf <= data_out_buf;
cnt <= cnt;
end
end
mult1 mult1_inst
(
.A(AD_data),
.B(AD_data),
.P(mult_data),
.CLK(clk_sys),
.CE(clk_samp_impluse)
);
assign data_out = data_out_buf;
endmodule

View File

@ -0,0 +1,69 @@
`timescale 1ns / 1ps
module Image_XYCrop(
input clk,
input rst_n,
//CMOS
input image_in_vsync,
input image_in_href,
input image_in_data,
output image_out_vsync,
output image_out_href_left,
output image_out_data_left,
output image_out_href_right,
output image_out_data_right
);
//-----------------------------------
reg image_in_href_r = 0;
reg image_in_vsync_r = 0;
reg image_in_data_r = 0;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
image_in_vsync_r <= 0;
image_in_href_r <= 0;
image_in_data_r <= 0;
end
else begin
image_in_vsync_r <= image_in_vsync;
image_in_href_r <= image_in_href;
image_in_data_r <= image_in_data;
end
end
//-----------------------------------
//Image Ysize Crop
reg [11:0] image_ypos = 0;
wire image_in_href_negedge = (image_in_href_r & ~image_in_href) ? 1'b1 : 1'b0;
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
image_ypos <= 0;
else if(image_in_vsync == 1'b1) begin
if(image_in_href_negedge == 1'b1) //行同步信号的下降沿一行信号赋值完成后image_ypos累加1
image_ypos <= image_ypos + 1'b1;
else
image_ypos <= image_ypos;
end
else
image_ypos <= 0;
end
assign image_out_vsync = image_in_vsync_r; // image_out_vsync是打一拍后的 image_in_vsync的信号延时了一个时钟周期
//-----------------------------------
//Image Hsize Crop
reg [11:0] image_xpos = 0;
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
image_xpos <= 0;
else if(image_in_href == 1'b1)
image_xpos <= image_xpos + 1'b1;
else
image_xpos <= 0;
end
assign image_out_href_right = ((image_in_href_r == 1'b1) && (image_xpos > 10'd640) && (image_xpos < 12'd1280)) ? 1'b1 : 1'b0;
assign image_out_data_right = (image_out_vsync & image_out_href_right) ? image_in_data_r : 1'd0;
assign image_out_href_left = ((image_in_href_r == 1'b1) && (image_xpos <= 10'd640)) ? 1'b1 : 1'b0;
assign image_out_data_left = (image_out_vsync & image_out_href_left) ? image_in_data_r : 1'd0;
endmodule

View File

@ -0,0 +1,113 @@
module Parallel_Line_Detector #(
parameter IMG_VDISP = 1240,
parameter X_THRESHOLD = 100,
parameter Y_THRESHOLD = 100,
parameter X_Center_Value = 540,
parameter Y_Center_Value = 540
) (
input clk,
input rst_n,
//
input per_img_Bit,
input per_frame_href,
input per_frame_vsync,
//
output X_up_down,
output Y_up_down,
output [15:0] X_distance,
output [15:0] Y_distance
);
//检测行同步信号边沿一行数据的开始和结束
wire href_pos,href_neg,vsync_neg;
reg [1:0] per_frame_href_r,per_frame_vsync_r;
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
per_frame_href_r <= 2'b0;
per_frame_vsync_r <= 2'b0;
end
else begin
per_frame_href_r <= {per_frame_href_r[0],per_frame_href};
per_frame_vsync_r <= {per_frame_vsync_r[0],per_frame_vsync};
end
end
assign href_pos =(~per_frame_href_r[1] & per_frame_href_r[0]) ? 1'b1 : 1'b0; //一行信号的开始
assign href_neg =(~per_frame_href_r[0] & per_frame_href_r[1]) ? 1'b1 : 1'b0; //一行信号的结束
assign vsync_neg =(~per_frame_vsync_r[0] & per_frame_vsync_r[1]) ? 1'b1 : 1'b0; //一帧信号的结束
/**************************************直线检测部分**************************************/
wire IMG_BIT_INPUT = ~per_img_Bit; //输入的边缘数据
reg [15:0] x_coordinate_cnt; //列计数器横坐标 X
reg [15:0] y_coordinate_cnt; //行计数器纵坐标 Y
reg [15:0] X_edge_center; //纵向纤芯坐标
reg [15:0] Y_edge_center; //横向纤芯坐标
//竖线线检测的相关变量
reg [15:0] X_edge_acc = 0; //列边沿坐标的累加
reg [15:0] X_edge_cnt = 0; //列边沿的计数器
reg [15:0] per_row_acc [IMG_VDISP:1]; //每列的累加值
reg [IMG_VDISP:1] per_row_flag; //每列的累加值
//横线检测的相关变量
reg [15:0] Y_edge_acc = 0; //行边沿坐标的累加
reg [15:0] Y_edge_cnt = 0; //行边沿的计数器
reg [15:0] per_href_acc = 0; //每行的累加值
//直线检测处理语句块
integer i;
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
Y_edge_acc <= 16'd0;
Y_edge_cnt <= 16'd0;
X_edge_acc <= 16'd0;
X_edge_cnt <= 16'd0;
per_href_acc <= 16'd0;
x_coordinate_cnt <= 16'd0;
y_coordinate_cnt <= 16'd0;
for (i = 1; i<=IMG_VDISP; i=i+1) begin
per_row_acc[i] <= 16'd0;
per_row_flag[i] <= 1'd0;
end
end
else if (per_frame_href) begin
if (href_pos) y_coordinate_cnt <= y_coordinate_cnt + 1'd1;
else y_coordinate_cnt <= y_coordinate_cnt;
if ((per_row_acc[x_coordinate_cnt] >= X_THRESHOLD) && (~per_row_flag[x_coordinate_cnt])) begin
X_edge_cnt <= X_edge_cnt + 1'd1;
per_row_flag[x_coordinate_cnt] <= 1'b1;
X_edge_acc <= X_edge_acc + x_coordinate_cnt;
end
per_href_acc <= per_href_acc + IMG_BIT_INPUT;
x_coordinate_cnt <= x_coordinate_cnt + 1'd1;
per_row_acc[x_coordinate_cnt] <= per_row_acc[x_coordinate_cnt] + IMG_BIT_INPUT;
end
else if(href_neg) begin //一行数据结束
if(per_href_acc >= Y_THRESHOLD) begin
Y_edge_cnt <= Y_edge_cnt + 1'd1;
Y_edge_acc <= Y_edge_acc + y_coordinate_cnt;
end
per_href_acc <= 16'd0;
x_coordinate_cnt <= 16'd0;
end
else if (vsync_neg) begin
X_edge_center = X_edge_acc / X_edge_cnt;
Y_edge_center = Y_edge_acc / Y_edge_cnt;
X_edge_acc <= 16'd0; X_edge_cnt <= 16'd0;
Y_edge_acc <= 16'd0; Y_edge_cnt <= 16'd0;
for (i = 1; i<=IMG_VDISP; i=i+1) begin
per_row_acc[i] <= 16'd0;
per_row_flag[i] <= 1'd0;
end
y_coordinate_cnt <= 16'd0;
end
end
assign X_distance = $signed(X_edge_center) - $signed(X_Center_Value);
assign Y_distance = $signed(Y_edge_center) - $signed(Y_Center_Value);
assign X_up_down = X_distance[16];
assign Y_up_down = Y_distance[16];
endmodule

View File

@ -0,0 +1,162 @@
`timescale 1ns/1ns
module RAW8_RGB888 #(
parameter [10:0] IMG_HDISP = 11'd640, //640*480
parameter [10:0] IMG_VDISP = 11'd480
) (
//global clock
input clk, //cmos video pixel clock
input rst_n, //global reset
//CMOS YCbCr444 data output
input per_frame_vsync, //Prepared Image data vsync valid signal
input per_frame_href, //Prepared Image data href vaild signal
input [7:0] per_img_RAW, //Prepared Image data 8 Bit RAW Data
//CMOS RGB888 data output
output post_frame_vsync, //Processed Image data vsync valid signal
output post_frame_href, //Processed Image data href vaild signal
output [7:0] post_img_red, //Prepared Image green data to be processed
output [7:0] post_img_green, //Prepared Image green data to be processed
output [7:0] post_img_blue //Prepared Image blue data to be processed
);
//----------------------------------------------------
//Generate 8Bit 3X3 Matrix for Video Image Processor.
//Image data has been processd
wire matrix_frame_vsync; //Prepared Image data vsync valid signal
wire matrix_frame_href; //Prepared Image data href vaild signal
wire [7:0] matrix_p11, matrix_p12, matrix_p13; //3X3 Matrix output
wire [7:0] matrix_p21, matrix_p22, matrix_p23;
wire [7:0] matrix_p31, matrix_p32, matrix_p33;
Matrix_Generate_3X3_Buf # (
.DATA_WIDTH ( 8 ),
.IMG_HDISP (IMG_HDISP), //640*480
.IMG_VDISP (IMG_VDISP)
) Matrix_Generate_3X3_Buf_u (
//global clock
.clk (clk), //cmos video pixel clock
.rst_n (rst_n), //global reset
//Image data prepred to be processd
.per_frame_vsync (per_frame_vsync), //Prepared Image data vsync valid signal
.per_frame_href (per_frame_href), //Prepared Image data href vaild signal
.per_img_Data (per_img_RAW), //Prepared Image brightness input
//Image data has been processd
.matrix_frame_vsync (matrix_frame_vsync), //Processed Image data vsync valid signal
.matrix_frame_href (matrix_frame_href), //Processed Image data href vaild signal
.matrix_p11(matrix_p11), .matrix_p12(matrix_p12), .matrix_p13(matrix_p13), //3X3 Matrix output
.matrix_p21(matrix_p21), .matrix_p22(matrix_p22), .matrix_p23(matrix_p23),
.matrix_p31(matrix_p31), .matrix_p32(matrix_p32), .matrix_p33(matrix_p33)
);
//-------------------------------------------------------------
//sync the frame vsync and href signal and generate frame begin & end signal
reg matrix_frame_href_r;
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
matrix_frame_href_r <= 0;
else
matrix_frame_href_r <= matrix_frame_href;
end
wire matrix_frame_href_end = (matrix_frame_href_r & ~matrix_frame_href) ? 1'b1 : 1'b0; //Line over signal
//----------------------------------------
//Count the frame lines
reg [10:0] line_cnt;
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
line_cnt <= 0;
else if(matrix_frame_vsync == 1'b1) begin
if(matrix_frame_href_end)
line_cnt <= (line_cnt < IMG_VDISP - 1'b1) ? line_cnt + 1'b1 : 10'd0;
else
line_cnt <= line_cnt;
end
else
line_cnt <= 0;
end
//----------------------------------------
//Count the pixels
reg [10:0] point_cnt;
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
point_cnt <= 0;
else if(matrix_frame_href == 1'b1) //Line valid
point_cnt <= (line_cnt < IMG_HDISP - 1'b1) ? point_cnt + 1'b1 : 10'd0;
else
point_cnt <= 0;
end
//--------------------------------------
//Convet RAW 2 RGB888 Format
//
localparam OddLINE_OddPOINT = 2'b10; //odd lines + odd point
localparam OddLINE_Even_POINT = 2'b11; //odd lines + even point
localparam EvenLINE_OddPOINT = 2'b00; //even lines + odd point
localparam EvenLINE_EvenPOINT = 2'b01; //even lines + even point
reg [9:0] post_img_red_r;
reg [9:0] post_img_green_r;
reg [9:0] post_img_blue_r;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
post_img_red_r <= 0;
post_img_green_r<= 0;
post_img_blue_r <= 0;
end
else begin
case({line_cnt[0], point_cnt[0]})
//-------------------------BGBG...BGBG--------------------//
OddLINE_OddPOINT:begin //odd lines + odd point
//Center Blue
post_img_red_r <= (matrix_p11 + matrix_p13 + matrix_p31 + matrix_p33)>>2;
post_img_green_r<= (matrix_p12 + matrix_p21 + matrix_p23 + matrix_p32)>>2;
post_img_blue_r <= matrix_p22;
end
OddLINE_Even_POINT:begin //odd lines + even point
//Center Green
post_img_red_r <= (matrix_p12 + matrix_p32)>>1;
post_img_green_r<= matrix_p22;
post_img_blue_r <= (matrix_p21 + matrix_p23)>>1;
end
//-------------------------GRGR...GRGR--------------------//
EvenLINE_OddPOINT:begin //even lines + odd point
//Center Green
post_img_red_r <= (matrix_p21 + matrix_p23)>>1;
post_img_green_r<= matrix_p22;
post_img_blue_r <= (matrix_p12 + matrix_p32)>>1;
end
EvenLINE_EvenPOINT:begin //even lines + even point
//Center Red
post_img_red_r <= matrix_p22;
post_img_green_r<= (matrix_p12 + matrix_p21 + matrix_p23 + matrix_p32)>>2;
post_img_blue_r <= (matrix_p11 + matrix_p13 + matrix_p31 + matrix_p33)>>2;
end
endcase
end
end
assign post_img_red = post_img_red_r[7:0];
assign post_img_green = post_img_green_r[7:0];
assign post_img_blue = post_img_blue_r[7:0];
//------------------------------------------
//lag n clocks signal sync
reg [1:0] post_frame_vsync_r;
reg [1:0] post_frame_href_r;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
post_frame_vsync_r <= 0;
post_frame_href_r <= 0;
end
else begin
post_frame_vsync_r <= {post_frame_vsync_r[0], matrix_frame_vsync};
post_frame_href_r <= {post_frame_href_r[0], matrix_frame_href};
end
end
assign post_frame_vsync = post_frame_vsync_r[0];
assign post_frame_href = post_frame_href_r[0];
endmodule

View File

@ -0,0 +1,118 @@
`timescale 1ns/1ns
module RGB888_YCbCr444 (
//global clock
input clk, //cmos video pixel clock
input rst_n, //global reset
//Image data prepred to be processd
input per_frame_vsync, //Prepared Image data vsync valid signal
input per_frame_href, //Prepared Image data href vaild signal
input [7:0] per_img_red, //Prepared Image red data to be processed
input [7:0] per_img_green, //Prepared Image green data to be processed
input [7:0] per_img_blue, //Prepared Image blue data to be processed
//Image data has been processd
output post_frame_vsync, //Processed Image data vsync valid signal
output post_frame_href, //Processed Image data href vaild signal
output [7:0] post_img_Y, //Processed Image brightness output
output [7:0] post_img_Cb, //Processed Image blue shading output
output [7:0] post_img_Cr //Processed Image red shading output
);
//--------------------------------------------
/*********************************************
//Refer to <OV7725 Camera Module Software Applicaton Note> page 5
Y = (77 *R + 150*G + 29 *B)>>8
Cb = (-43*R - 85 *G + 128*B)>>8 + 128
Cr = (128*R - 107*G - 21 *B)>>8 + 128
--->
Y = (77 *R + 150*G + 29 *B)>>8
Cb = (-43*R - 85 *G + 128*B + 32768)>>8
Cr = (128*R - 107*G - 21 *B + 32768)>>8
**********************************************/
//Step 1
reg [15:0] img_red_r0, img_red_r1, img_red_r2;
reg [15:0] img_green_r0, img_green_r1, img_green_r2;
reg [15:0] img_blue_r0, img_blue_r1, img_blue_r2;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
img_red_r0 <= 0;
img_red_r1 <= 0;
img_red_r2 <= 0;
img_green_r0 <= 0;
img_green_r1 <= 0;
img_green_r2 <= 0;
img_blue_r0 <= 0;
img_blue_r1 <= 0;
img_blue_r2 <= 0;
end
else begin
img_red_r0 <= per_img_red * 8'd77;
img_red_r1 <= per_img_red * 8'd43;
img_red_r2 <= per_img_red * 8'd128;
img_green_r0 <= per_img_green * 8'd150;
img_green_r1 <= per_img_green * 8'd85;
img_green_r2 <= per_img_green * 8'd107;
img_blue_r0 <= per_img_blue * 8'd29;
img_blue_r1 <= per_img_blue * 8'd128;
img_blue_r2 <= per_img_blue * 8'd21;
end
end
//--------------------------------------------------
//Step 2
reg [15:0] img_Y_r0;
reg [15:0] img_Cb_r0;
reg [15:0] img_Cr_r0;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
img_Y_r0 <= 0;
img_Cb_r0 <= 0;
img_Cr_r0 <= 0;
end
else begin
img_Y_r0 <= img_red_r0 + img_green_r0 + img_blue_r0;
img_Cb_r0 <= img_blue_r1 - img_red_r1 - img_green_r1 + 16'd32768;
img_Cr_r0 <= img_red_r2 + img_green_r2 + img_blue_r2 + 16'd32768;
end
end
//--------------------------------------------------
//Step 3
reg [7:0] img_Y_r1;
reg [7:0] img_Cb_r1;
reg [7:0] img_Cr_r1;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
img_Y_r1 <= 0;
img_Cb_r1 <= 0;
img_Cr_r1 <= 0;
end
else begin
img_Y_r1 <= img_Y_r0[15:8];
img_Cb_r1 <= img_Cb_r0[15:8];
img_Cr_r1 <= img_Cr_r0[15:8];
end
end
//------------------------------------------
//lag 3 clocks signal sync
reg [2:0] per_frame_vsync_r;
reg [2:0] per_frame_href_r;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
per_frame_vsync_r <= 0;
per_frame_href_r <= 0;
end
else begin
per_frame_vsync_r <= {per_frame_vsync_r[1:0], per_frame_vsync};
per_frame_href_r <= {per_frame_href_r[1:0], per_frame_href};
end
end
assign post_frame_vsync = per_frame_vsync_r[2];
assign post_frame_href = per_frame_href_r[2];
assign post_img_Y = post_frame_href ? img_Y_r1 : 8'd0;
assign post_img_Cb = post_frame_href ? img_Cb_r1: 8'd0;
assign post_img_Cr = post_frame_href ? img_Cr_r1: 8'd0;
endmodule

View File

@ -0,0 +1,103 @@
`timescale 1ns/1ns
module Bit_Dilation_Detector #(
parameter [10:0] IMG_HDISP = 11'd640, //640*480
parameter [10:0] IMG_VDISP = 11'd480
) (
//global clock
input clk, //cmos video pixel clock
input rst_n, //global reset
//Image data prepred to be processd
input per_frame_vsync, //Prepared Image data vsync valid signal
input per_frame_href, //Prepared Image data href vaild signal
input per_img_Bit, //Prepared Image Bit flag outout(1: Value, 0:inValid)
//Image data has been processd
output post_frame_vsync, //Processed Image data vsync valid signal
output post_frame_href, //Processed Image data href vaild signal
output post_img_Bit //Processed Image Bit flag outout(1: Value, 0:inValid)
);
//----------------------------------------------------
//Generate 1Bit 3X3 Matrix for Video Image Processor.
//Image data has been processd
wire matrix_frame_vsync; //Prepared Image data vsync valid signal
wire matrix_frame_href; //Prepared Image data href vaild signal
wire matrix_p11, matrix_p12, matrix_p13; //3X3 Matrix output
wire matrix_p21, matrix_p22, matrix_p23;
wire matrix_p31, matrix_p32, matrix_p33;
Matrix_Generate_3X3 #(
.DATA_WIDTH ( 1 ),
.IMG_HDISP (IMG_HDISP), //640*480
.IMG_VDISP (IMG_VDISP)
) Matrix_Generate_3X3_u (
//global clock
.clk (clk), //cmos video pixel clock
.rst_n (rst_n), //global reset
//Image data prepred to be processd
.per_frame_vsync (per_frame_vsync), //Prepared Image data vsync valid signal
.per_frame_href (per_frame_href), //Prepared Image data href vaild signal
.per_img_Data (per_img_Bit), //Prepared Image brightness input
//Image data has been processd
.matrix_frame_vsync (matrix_frame_vsync), //Processed Image data vsync valid signal
.matrix_frame_href (matrix_frame_href), //Processed Image data href vaild signal
.matrix_p11(matrix_p11), .matrix_p12(matrix_p12), .matrix_p13(matrix_p13), //3X3 Matrix output
.matrix_p21(matrix_p21), .matrix_p22(matrix_p22), .matrix_p23(matrix_p23),
.matrix_p31(matrix_p31), .matrix_p32(matrix_p32), .matrix_p33(matrix_p33)
);
//Add you arithmetic here
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//-------------------------------------------
//-------------------------------------------
//Dilation Parameter
// Original Dilation Pixel
// [ 0 0 0 ] [ 1 1 1 ] [ P1 P2 P3 ]
// [ 0 1 0 ] [ 1 1 1 ] [ P4 P5 P6 ]
// [ 0 0 0 ] [ 1 1 1 ] [ P7 P8 P9 ]
//P = P1 | P2 | P3 | P4 | P5 | P6 | P7 | 8 | 9;
//---------------------------------------
//Dilation with or operation,1 : White, 0 : Black
//Step1
reg post_img_Bit1, post_img_Bit2, post_img_Bit3;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
post_img_Bit1 <= 1'b0;
post_img_Bit2 <= 1'b0;
post_img_Bit3 <= 1'b0;
end
else begin
post_img_Bit1 <= matrix_p11 | matrix_p12 | matrix_p13;
post_img_Bit2 <= matrix_p21 | matrix_p22 | matrix_p23;
post_img_Bit3 <= matrix_p21 | matrix_p32 | matrix_p33;
end
end
//Step 2
reg post_img_Bit4;
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
post_img_Bit4 <= 1'b0;
else
post_img_Bit4 <= post_img_Bit1 | post_img_Bit2 | post_img_Bit3;
end
//------------------------------------------
//lag 2 clocks signal sync
reg [1:0] per_frame_vsync_r;
reg [1:0] per_frame_href_r;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
per_frame_vsync_r <= 0;
per_frame_href_r <= 0;
end
else begin
per_frame_vsync_r <= {per_frame_vsync_r[0], matrix_frame_vsync};
per_frame_href_r <= {per_frame_href_r[0], matrix_frame_href};
end
end
assign post_frame_vsync = per_frame_vsync_r[1];
assign post_frame_href = per_frame_href_r[1];
assign post_img_Bit = post_frame_href ? post_img_Bit4 : 1'b0;
endmodule

View File

@ -0,0 +1,105 @@
`timescale 1ns/1ns
module Bit_Erosion_Detector #(
parameter [10:0] IMG_HDISP = 11'd640, //640*480
parameter [10:0] IMG_VDISP = 11'd480
) (
//global clock
input clk, //cmos video pixel clock
input rst_n, //global reset
//Image data prepred to be processd
input per_frame_vsync, //Prepared Image data vsync valid signal
input per_frame_href, //Prepared Image data href vaild signal
input per_img_Bit, //Prepared Image Bit flag outout(1: Value, 0:inValid)
//Image data has been processd
output post_frame_vsync, //Processed Image data vsync valid signal
output post_frame_href, //Processed Image data href vaild signal
output post_img_Bit //Processed Image Bit flag outout(1: Value, 0:inValid)
);
//----------------------------------------------------
//Generate 1Bit 3X3 Matrix for Video Image Processor.
//Image data has been processd
wire matrix_frame_vsync; //Prepared Image data vsync valid signal
wire matrix_frame_href; //Prepared Image data href vaild signal
wire matrix_p11, matrix_p12, matrix_p13; //3X3 Matrix output
wire matrix_p21, matrix_p22, matrix_p23;
wire matrix_p31, matrix_p32, matrix_p33;
Matrix_Generate_3X3 #(
.DATA_WIDTH ( 1 ),
.IMG_HDISP (IMG_HDISP), //640*480
.IMG_VDISP (IMG_VDISP)
) Matrix_Generate_3X3_u (
//global clock
.clk (clk), //cmos video pixel clock
.rst_n (rst_n), //global reset
//Image data prepred to be processd
.per_frame_vsync (per_frame_vsync), //Prepared Image data vsync valid signal
.per_frame_href (per_frame_href), //Prepared Image data href vaild signal
.per_img_Data (per_img_Bit), //Prepared Image brightness input
//Image data has been processd
.matrix_frame_vsync (matrix_frame_vsync), //Processed Image data vsync valid signal
.matrix_frame_href (matrix_frame_href), //Processed Image data href vaild signal
.matrix_p11(matrix_p11), .matrix_p12(matrix_p12), .matrix_p13(matrix_p13), //3X3 Matrix output
.matrix_p21(matrix_p21), .matrix_p22(matrix_p22), .matrix_p23(matrix_p23),
.matrix_p31(matrix_p31), .matrix_p32(matrix_p32), .matrix_p33(matrix_p33)
);
//Add you arithmetic here
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//-------------------------------------------
//-------------------------------------------
//Eronsion Parameter
// Original Dilation Pixel
// [ 0 0 0 ] [ 1 1 1 ] [ P1 P2 P3 ]
// [ 0 1 0 ] [ 1 1 1 ] [ P4 P5 P6 ]
// [ 0 0 0 ] [ 1 1 1 ] [ P7 P8 P9 ]
//P = P1 & P2 & P3 & P4 & P5 & P6 & P7 & 8 & 9;
//---------------------------------------
//Eonsion with or operation
//Step1
reg post_img_Bit1, post_img_Bit2, post_img_Bit3;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
post_img_Bit1 <= 1'b0;
post_img_Bit2 <= 1'b0;
post_img_Bit3 <= 1'b0;
end
else begin
post_img_Bit1 <= matrix_p11 & matrix_p12 & matrix_p13;
post_img_Bit2 <= matrix_p21 & matrix_p22 & matrix_p23;
post_img_Bit3 <= matrix_p21 & matrix_p32 & matrix_p33;
end
end
//Step 2
reg post_img_Bit4;
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
post_img_Bit4 <= 1'b0;
else
post_img_Bit4 <= post_img_Bit1 & post_img_Bit2 & post_img_Bit3;
end
//------------------------------------------
//lag 2 clocks signal sync
reg [1:0] per_frame_vsync_r;
reg [1:0] per_frame_href_r;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
per_frame_vsync_r <= 0;
per_frame_href_r <= 0;
end
else begin
per_frame_vsync_r <= {per_frame_vsync_r[0], matrix_frame_vsync};
per_frame_href_r <= {per_frame_href_r[0], matrix_frame_href};
end
end
assign post_frame_vsync = per_frame_vsync_r[1];
assign post_frame_href = per_frame_href_r[1];
assign post_img_Bit = post_frame_href ? post_img_Bit4 : 1'b0;
endmodule

View File

@ -0,0 +1,155 @@
`timescale 1ns/1ns
module Sobel_Edge_Detector #(
parameter [10:0] IMG_HDISP = 11'd640, //640*480
parameter [10:0] IMG_VDISP = 11'd480
) (
//global clock
input clk, //cmos video pixel clock
input rst_n, //global reset
//Image data prepred to be processd
input per_frame_vsync, //Prepared Image data vsync valid signal
input per_frame_href, //Prepared Image data href vaild signal
input [7:0] per_img_Gray, //Prepared Image brightness input
//Image data has been processd
output post_frame_vsync, //Processed Image data vsync valid signal
output post_frame_href, //Processed Image data href vaild signal
output post_img_Bit, //Processed Image Bit flag outout(1: Value, 0:inValid)
//user interface
input [7:0] Sobel_Threshold //Sobel Threshold for image edge detect
);
//----------------------------------------------------
//Generate 8Bit 3X3 Matrix for Video Image Processor.
//Image data has been processd
wire matrix_frame_vsync; //Prepared Image data vsync valid signal
wire matrix_frame_href; //Prepared Image data href vaild signal
wire [7:0] matrix_p11, matrix_p12, matrix_p13; //3X3 Matrix output
wire [7:0] matrix_p21, matrix_p22, matrix_p23;
wire [7:0] matrix_p31, matrix_p32, matrix_p33;
Matrix_Generate_3X3_Buf # (
.DATA_WIDTH ( 8 ),
.IMG_HDISP (IMG_HDISP), //640*480
.IMG_VDISP (IMG_VDISP)
) Matrix_Generate_3X3_Buf_u (
//global clock
.clk (clk), //cmos video pixel clock
.rst_n (rst_n), //global reset
//Image data prepred to be processd
.per_frame_vsync (per_frame_vsync), //Prepared Image data vsync valid signal
.per_frame_href (per_frame_href), //Prepared Image data href vaild signal
.per_img_Data (per_img_Gray), //Prepared Image brightness input
//Image data has been processd
.matrix_frame_vsync (matrix_frame_vsync), //Processed Image data vsync valid signal
.matrix_frame_href (matrix_frame_href), //Processed Image data href vaild signal
.matrix_p11(matrix_p11), .matrix_p12(matrix_p12), .matrix_p13(matrix_p13), //3X3 Matrix output
.matrix_p21(matrix_p21), .matrix_p22(matrix_p22), .matrix_p23(matrix_p23),
.matrix_p31(matrix_p31), .matrix_p32(matrix_p32), .matrix_p33(matrix_p33)
);
//Add you arithmetic here
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//-------------------------------------------
//Sobel Parameter
// Gx Gy Pixel
// [ -1 0 +1 ] [ +1 +2 +1 ] [ P11 P12 P13 ]
// [ -2 0 +2 ] [ 0 0 0 ] [ P21 P22 P23 ]
// [ -1 0 +1 ] [ -1 -2 -1 ] [ P31 P32 P33 ]
// localparam P11 = 8'd15, P12 = 8'd94, P13 = 8'd136;
// localparam P21 = 8'd31, P22 = 8'd127, P23 = 8'd231;
// localparam P31 = 8'd44, P32 = 8'd181, P33 = 8'd249;
//Caculate horizontal Grade with |abs|
//Step 1-2
reg [9:0] Gx_temp1; //postive result
reg [9:0] Gx_temp2; //negetive result
reg [9:0] Gx_data; //Horizontal grade data
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
Gx_temp1 <= 0;
Gx_temp2 <= 0;
Gx_data <= 0;
end
else begin
Gx_temp1 <= matrix_p13 + (matrix_p23 << 1) + matrix_p33; //postive result
Gx_temp2 <= matrix_p11 + (matrix_p21 << 1) + matrix_p31; //negetive result
Gx_data <= (Gx_temp1 >= Gx_temp2) ? Gx_temp1 - Gx_temp2 : Gx_temp2 - Gx_temp1;
end
end
//---------------------------------------
//Caculate vertical Grade with |abs|
//Step 1-2
reg [9:0] Gy_temp1; //postive result
reg [9:0] Gy_temp2; //negetive result
reg [9:0] Gy_data; //Vertical grade data
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
Gy_temp1 <= 0;
Gy_temp2 <= 0;
Gy_data <= 0;
end
else begin
Gy_temp1 <= matrix_p11 + (matrix_p12 << 1) + matrix_p13; //postive result
Gy_temp2 <= matrix_p31 + (matrix_p32 << 1) + matrix_p33; //negetive result
Gy_data <= (Gy_temp1 >= Gy_temp2) ? Gy_temp1 - Gy_temp2 : Gy_temp2 - Gy_temp1;
end
end
//---------------------------------------
//Caculate the square of distance = (Gx^2 + Gy^2)
//Step 3
reg [20:0] Gxy_square;
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
Gxy_square <= 0;
else
Gxy_square <= Gx_data * Gx_data + Gy_data * Gy_data;
end
//---------------------------------------
//Caculate the distance of P5 = (Gx^2 + Gy^2)^0.5
//Step 4
Sqrt #(
.q_port_width (11),
.r_port_width (12),
.width (21)
) SQRT_u (
.radical (Gxy_square),
.q (Dim),
.remainder ()
);
//---------------------------------------
//Compare and get the Sobel_data
//Step 5
reg post_img_Bit_r;
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
post_img_Bit_r <= 1'b0; //Default None
else if(Dim >= Sobel_Threshold)
post_img_Bit_r <= 1'b1; //Edge Flag
else
post_img_Bit_r <= 1'b0; //Not Edge
end
//------------------------------------------
//lag 5 clocks signal sync
reg [4:0] per_frame_vsync_r;
reg [4:0] per_frame_href_r;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
per_frame_vsync_r <= 0;
per_frame_href_r <= 0;
end
else begin
per_frame_vsync_r <= {per_frame_vsync_r[3:0], matrix_frame_vsync};
per_frame_href_r <= {per_frame_href_r[3:0], matrix_frame_href};
end
end
assign post_frame_vsync = per_frame_vsync_r[4];
assign post_frame_href = per_frame_href_r[4];
assign post_img_Bit = post_frame_href ? post_img_Bit_r : 1'b0;
endmodule

View File

@ -0,0 +1,92 @@
`timescale 1ns/1ns
module Gray_Median_Filter #(
parameter [10:0] IMG_HDISP = 11'd640, //640*480
parameter [10:0] IMG_VDISP = 11'd480
) (
//global clock
input clk, //100MHz
input rst_n, //global reset
//Image data prepred to be processd
input per_frame_vsync, //Prepared Image data vsync valid signal
input per_frame_href, //Prepared Image data href vaild signal
input [7:0] per_img_Gray, //Prepared Image brightness input
//Image data has been processd
output post_frame_vsync, //Processed Image data vsync valid signal
output post_frame_href, //Processed Image data href vaild signal
output [7:0] post_img_Gray //Processed Image brightness input
);
//----------------------------------------------------
//Generate 8Bit 3X3 Matrix for Video Image Processor.
//Image data has been processd
wire matrix_frame_vsync; //Prepared Image data vsync valid signal
wire matrix_frame_href; //Prepared Image data href vaild signal
wire matrix_frame_clken; //Prepared Image data output/capture enable clock
wire [7:0] matrix_p11, matrix_p12, matrix_p13; //3X3 Matrix output
wire [7:0] matrix_p21, matrix_p22, matrix_p23;
wire [7:0] matrix_p31, matrix_p32, matrix_p33;
Matrix_Generate_3X3_Buf # (
.DATA_WIDTH ( 8 ),
.IMG_HDISP (IMG_HDISP), //640*480
.IMG_VDISP (IMG_VDISP)
) Matrix_Generate_3X3_Buf_u (
//global clock
.clk (clk), //cmos video pixel clock
.rst_n (rst_n), //global reset
//Image data prepred to be processd
.per_frame_vsync (per_frame_vsync), //Prepared Image data vsync valid signal
.per_frame_href (per_frame_href), //Prepared Image data href vaild signal
.per_img_Data (per_img_Gray), //Prepared Image brightness input
//Image data has been processd
.matrix_frame_vsync (matrix_frame_vsync), //Processed Image data vsync valid signal
.matrix_frame_href (matrix_frame_href), //Processed Image data href vaild signal
.matrix_p11(matrix_p11), .matrix_p12(matrix_p12), .matrix_p13(matrix_p13), //3X3 Matrix output
.matrix_p21(matrix_p21), .matrix_p22(matrix_p22), .matrix_p23(matrix_p23),
.matrix_p31(matrix_p31), .matrix_p32(matrix_p32), .matrix_p33(matrix_p33)
);
//Add you arithmetic here
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//Median Filter of 3X3 datas, need 3 clock
wire [7:0] mid_value;
Median_Filter_3X3 u_Median_Filter_3X3(
.clk (clk),
.rst_n (rst_n),
//ROW1
.data11 (matrix_p11),
.data12 (matrix_p12),
.data13 (matrix_p13),
//ROW2
.data21 (matrix_p21),
.data22 (matrix_p22),
.data23 (matrix_p23),
//ROW3
.data31 (matrix_p31),
.data32 (matrix_p32),
.data33 (matrix_p33),
.target_data (mid_value)
);
//------------------------------------------
//lag 3 clocks signal sync
reg [2:0] per_frame_vsync_r;
reg [2:0] per_frame_href_r;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
per_frame_vsync_r <= 0;
per_frame_href_r <= 0;
end
else begin
per_frame_vsync_r <= {per_frame_vsync_r[1:0], matrix_frame_vsync};
per_frame_href_r <= {per_frame_href_r[1:0], matrix_frame_href};
end
end
assign post_frame_vsync = per_frame_vsync_r[2];
assign post_frame_href = per_frame_href_r[2];
assign post_img_Gray = post_frame_href ? mid_value : 8'd0;
endmodule

View File

@ -0,0 +1,118 @@
`timescale 1ns/1ns
module Median_Filter_3X3 (
input clk,
input rst_n,
input [7:0] data11, data12, data13,
input [7:0] data21, data22, data23,
input [7:0] data31, data32, data33,
output [7:0] target_data
);
//--------------------------------------------------------------------------------------
//FPGA Median Filter Sort order
// Pixel Sort1 Sort2 Sort3
// [ P1 P2 P3 ] [ Max1 Mid1 Min1 ]
// [ P4 P5 P6 ] [ Max2 Mid2 Min2 ] [Max_min, Mid_mid, Min_max] mid_valid
// [ P7 P8 P9 ] [ Max3 Mid3 Min3 ]
//Step1
wire [7:0] max_data1, mid_data1, min_data1;
Sort3 u_Sort3_1 (
.clk (clk),
.rst_n (rst_n),
.data1 (data11),
.data2 (data12),
.data3 (data13),
.max_data (max_data1),
.mid_data (mid_data1),
.min_data (min_data1)
);
wire [7:0] max_data2, mid_data2, min_data2;
Sort3 u_Sort3_2 (
.clk (clk),
.rst_n (rst_n),
.data1 (data21),
.data2 (data22),
.data3 (data23),
.max_data (max_data2),
.mid_data (mid_data2),
.min_data (min_data2)
);
wire [7:0] max_data3, mid_data3, min_data3;
Sort3 u_Sort3_3 (
.clk (clk),
.rst_n (rst_n),
.data1 (data31),
.data2 (data32),
.data3 (data33),
.max_data (max_data3),
.mid_data (mid_data3),
.min_data (min_data3)
);
//Step2
wire [7:0] max_min_data, mid_mid_data, min_max_data;
Sort3 u_Sort3_4 (
.clk (clk),
.rst_n (rst_n),
.data1 (max_data1),
.data2 (max_data2),
.data3 (max_data3),
.max_data (),
.mid_data (),
.min_data (max_min_data)
);
Sort3 u_Sort3_5 (
.clk (clk),
.rst_n (rst_n),
.data1 (mid_data1),
.data2 (mid_data2),
.data3 (mid_data3),
.max_data (),
.mid_data (mid_mid_data),
.min_data ()
);
Sort3 u_Sort3_6 (
.clk (clk),
.rst_n (rst_n),
.data1 (min_data1),
.data2 (min_data2),
.data3 (min_data3),
.max_data (min_max_data),
.mid_data (),
.min_data ()
);
//step3
Sort3 u_Sort3_7 (
.clk (clk),
.rst_n (rst_n),
.data1 (max_min_data),
.data2 (mid_mid_data),
.data3 (min_max_data),
.max_data (),
.mid_data (target_data),
.min_data ()
);
endmodule

View File

@ -0,0 +1,115 @@
`timescale 1ns/1ns
module Matrix_Generate_3X3 #(
parameter DATA_WIDTH = 8,
parameter IMG_HDISP = 640, //640*480
parameter IMG_VDISP = 480
) (
//global clock
input clk, //cmos video pixel clock
input rst_n, //global reset
//Image data prepred to be processd
input per_frame_vsync, //Prepared Image data vsync valid signal
input per_frame_href, //Prepared Image data href vaild signal
input [DATA_WIDTH-1:0] per_img_Data, //Prepared Image brightness input
//Image data has been processd
output matrix_frame_vsync, //Prepared Image data vsync valid signal
output matrix_frame_href, //Prepared Image data href vaild signal
output reg [DATA_WIDTH-1:0] matrix_p11, matrix_p12, matrix_p13, //3X3 Matrix output
output reg [DATA_WIDTH-1:0] matrix_p21, matrix_p22, matrix_p23,
output reg [DATA_WIDTH-1:0] matrix_p31, matrix_p32, matrix_p33
);
//Generate 3*3 matrix
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
//sync row3_data with per_frame_clken & row1_data & raw2_data
wire [DATA_WIDTH-1:0] row1_data; //frame data of the 1th row
wire [DATA_WIDTH-1:0] row2_data; //frame data of the 2th row
reg [DATA_WIDTH-1:0] row3_data; //frame data of the 3th row
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
row3_data <= 0;
else begin
if(per_frame_href)
row3_data <= per_img_Data;
else
row3_data <= row3_data;
end
end
//---------------------------------------
//module of shift ram for raw data
wire shift_clk_en = per_frame_href;
Line_Shift_RAM #(
.RAM_Length ( IMG_HDISP ),
.DATA_WIDTH ( DATA_WIDTH )
) u_Line_Shift_RAM (
.clock ( clk ),
.clken ( shift_clk_en ),
.shiftin ( row3_data ),
.taps0x ( row2_data ),
.taps1x ( row1_data )
);
//------------------------------------------
//lag 2 clocks signal sync
reg [1:0] per_frame_vsync_r;
reg [1:0] per_frame_href_r;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
per_frame_vsync_r <= 0;
per_frame_href_r <= 0;
end
else begin
per_frame_vsync_r <= {per_frame_vsync_r[0], per_frame_vsync};
per_frame_href_r <= {per_frame_href_r[0], per_frame_href};
end
end
//Give up the 1th and 2th row edge data caculate for simple process
//Give up the 1th and 2th point of 1 line for simple process
wire read_frame_href = per_frame_href_r[0]; //RAM read href sync signal
assign matrix_frame_vsync = per_frame_vsync_r[1];
assign matrix_frame_href = per_frame_href_r[1];
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
/******************************************************************************
---------- Convert Matrix ----------
[ P31 -> P32 -> P33 -> ] ---> [ P11 P12 P13 ]
[ P21 -> P22 -> P23 -> ] ---> [ P21 P22 P23 ]
[ P11 -> P12 -> P11 -> ] ---> [ P31 P32 P33 ]
******************************************************************************/
//---------------------------------------------------------------------------
//---------------------------------------------------
/***********************************************
(1) Read data from Shift_RAM
(2) Caculate the Sobel
(3) Steady data after Sobel generate
************************************************/
//wire [2:0] matrix_row1 = {matrix_p11, matrix_p12, matrix_p13}; //Just for test
//wire [2:0] matrix_row2 = {matrix_p21, matrix_p22, matrix_p23};
//wire [2:0] matrix_row3 = {matrix_p31, matrix_p32, matrix_p33};
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
{matrix_p11, matrix_p12, matrix_p13} <= 0;
{matrix_p21, matrix_p22, matrix_p23} <= 0;
{matrix_p31, matrix_p32, matrix_p33} <= 0;
end
else if(read_frame_href) begin
{matrix_p11, matrix_p12, matrix_p13} <= {matrix_p12, matrix_p13, row1_data}; //1th shift input
{matrix_p21, matrix_p22, matrix_p23} <= {matrix_p22, matrix_p23, row2_data}; //2th shift input
{matrix_p31, matrix_p32, matrix_p33} <= {matrix_p32, matrix_p33, row3_data}; //3th shift input
end
else begin
{matrix_p11, matrix_p12, matrix_p13} <= 0;
{matrix_p21, matrix_p22, matrix_p23} <= 0;
{matrix_p31, matrix_p32, matrix_p33} <= 0;
end
end
endmodule

View File

@ -0,0 +1,148 @@
`timescale 1ns/1ns
module Matrix_Generate_3X3_Buf #(
parameter DATA_WIDTH = 8,
parameter IMG_HDISP = 640, //640*480
parameter IMG_VDISP = 480
) (
//global clock
input clk, //cmos video pixel clock
input rst_n, //global reset
//Image data prepred to be processd
input per_frame_vsync, //Prepared Image data vsync valid signal
input per_frame_href, //Prepared Image data href vaild signal
input [DATA_WIDTH-1:0] per_img_Data, //Prepared Image brightness input
//Image data has been processd
output matrix_frame_vsync, //Prepared Image data vsync valid signal
output matrix_frame_href, //Prepared Image data href vaild signal
output reg [DATA_WIDTH-1:0] matrix_p11, matrix_p12, matrix_p13, //3X3 Matrix output
output reg [DATA_WIDTH-1:0] matrix_p21, matrix_p22, matrix_p23,
output reg [DATA_WIDTH-1:0] matrix_p31, matrix_p32, matrix_p33
);
//Generate 3*3 matrix
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
//sync row3_data with per_frame_clken & row1_data & raw2_data
wire [DATA_WIDTH-1:0] row1_data; //frame data of the 1th row
wire [DATA_WIDTH-1:0] row2_data; //frame data of the 2th row
reg [DATA_WIDTH-1:0] row3_data; //frame data of the 3th row
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
row3_data <= 0;
else begin
if(per_frame_href)
row3_data <= per_img_Data;
else
row3_data <= row3_data;
end
end
//---------------------------------------
//module of shift ram for raw data
wire shift_clk_en = per_frame_href;
Line_Shift_RAM #(
.RAM_Length ( IMG_HDISP ),
.DATA_WIDTH ( DATA_WIDTH )
) u_Line_Shift_RAM (
.clock ( clk ),
.clken ( shift_clk_en ),
.shiftin ( row3_data ),
.taps0x ( row2_data ),
.taps1x ( row1_data )
);
//------------------------------------------
//lag 2 clocks signal sync
reg [2:0] per_frame_vsync_r;
reg [2:0] per_frame_href_r;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
per_frame_vsync_r <= 0;
per_frame_href_r <= 0;
end
else begin
per_frame_vsync_r <= {per_frame_vsync_r[1:0], per_frame_vsync};
per_frame_href_r <= {per_frame_href_r[1:0], per_frame_href};
end
end
//Give up the 1th and 2th row edge data caculate for simple process
//Give up the 1th and 2th point of 1 line for simple process
wire read_frame_href = per_frame_href_r[0]|per_frame_href_r[1]; //RAM read href sync signal
assign matrix_frame_vsync = per_frame_vsync_r[2];
assign matrix_frame_href = per_frame_href_r[2];
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
/******************************************************************************
---------- Convert Matrix ----------
[ P31 -> P32 -> P33 -> ] ---> [ P11 P12 P13 ]
[ P21 -> P22 -> P23 -> ] ---> [ P21 P22 P23 ]
[ P11 -> P12 -> P11 -> ] ---> [ P31 P32 P33 ]
******************************************************************************/
//---------------------------------------------------------------------------
//---------------------------------------------------
/***********************************************
(1) Read data from Shift_RAM
(2) Caculate the Sobel
(3) Steady data after Sobel generate
************************************************/
//wire [23:0] matrix_row1 = {matrix_p11, matrix_p12, matrix_p13}; //Just for test
//wire [23:0] matrix_row2 = {matrix_p21, matrix_p22, matrix_p23};
//wire [23:0] matrix_row3 = {matrix_p31, matrix_p32, matrix_p33};
reg [31:0] pixel_cnt;
reg [DATA_WIDTH-1:0] row1_data0;
reg [DATA_WIDTH-1:0] row2_data0;
reg [DATA_WIDTH-1:0] row3_data0;
reg [DATA_WIDTH-1:0] row1_data1;
reg [DATA_WIDTH-1:0] row2_data1;
reg [DATA_WIDTH-1:0] row3_data1;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
pixel_cnt <= 0;
row1_data0 <= 0; row1_data1 <= 0;
row2_data0 <= 0; row2_data1 <= 0;
row3_data0 <= 0; row3_data1 <= 0;
{matrix_p11, matrix_p12, matrix_p13} <= 0;
{matrix_p21, matrix_p22, matrix_p23} <= 0;
{matrix_p31, matrix_p32, matrix_p33} <= 0;
end
else if(read_frame_href) begin
pixel_cnt <= (pixel_cnt < IMG_HDISP) ? pixel_cnt + 1'b1 : 32'd0; //Point Counter
{row1_data1, row1_data0} <= {row1_data0, row1_data};
{row2_data1, row2_data0} <= {row2_data0, row2_data};
{row3_data1, row3_data0} <= {row3_data0, row3_data};
if(pixel_cnt == 0) begin
{matrix_p11, matrix_p12, matrix_p13} <= 0;
{matrix_p21, matrix_p22, matrix_p23} <= 0;
{matrix_p31, matrix_p32, matrix_p33} <= 0;
end
else if(pixel_cnt == 1) begin
{matrix_p11, matrix_p12, matrix_p13} <= {row1_data, row1_data0, row1_data};
{matrix_p21, matrix_p22, matrix_p23} <= {row2_data, row2_data0, row2_data};
{matrix_p31, matrix_p32, matrix_p33} <= {row3_data, row3_data0, row3_data};
end
else if(pixel_cnt == IMG_HDISP) begin
{matrix_p11, matrix_p12, matrix_p13} <= {row1_data1, row1_data, row1_data1};
{matrix_p21, matrix_p22, matrix_p23} <= {row2_data1, row2_data, row2_data1};
{matrix_p31, matrix_p32, matrix_p33} <= {row3_data1, row3_data, row3_data1};
end
else begin
{matrix_p11, matrix_p12, matrix_p13} <= {row1_data1, row1_data0, row1_data};
{matrix_p21, matrix_p22, matrix_p23} <= {row2_data1, row2_data0, row2_data};
{matrix_p31, matrix_p32, matrix_p33} <= {row3_data1, row3_data0, row3_data};
end
end
else begin
pixel_cnt <= 0;
{matrix_p11, matrix_p12, matrix_p13} <= 0;
{matrix_p21, matrix_p22, matrix_p23} <= 0;
{matrix_p31, matrix_p32, matrix_p33} <= 0;
end
end
endmodule

View File

@ -0,0 +1,228 @@
`timescale 1ns/1ns
module Video_Image_Processor #(
parameter RAW2RG888_YUV444 = "ON",
parameter GRAY_MEDIUM = "ON",
parameter GRAY_SOBEL = "ON",
parameter GRAY_EROSION = "ON",
parameter GRAY_DILATION = "ON",
parameter IMG_HDISP = 11'd640, //640*480
parameter IMG_VDISP = 11'd480
) (
//global clock
input clk, //cmos video pixel clock
input rst_n, //global reset
//Image data prepred to be processd
input per_frame_vsync, //Prepared Image data vsync valid signal
input per_frame_href, //Prepared Image data href vaild signal
input [7:0] per_img_RAW, //Prepared Image data of YCbCr 4:2:2 {CbY} {CrY}
//Image data has been processd
output post_frame_vsync, //Processed Image data vsync valid signal
output post_frame_href, //Processed Image data href vaild signal
output [7:0] post_img_Gray, //Processed Image Gray output
//user interface
input [7:0] Sobel_Threshold //Sobel Threshold for image edge detect
);
//-------------------------------------
//Convert the RAW format to RGB888 format.
wire post1_frame_vsync; //Processed Image data vsync valid signal
wire post1_frame_href; //Processed Image data href vaild signal
wire [7:0] post1_img_red; //Processed Image Red output
wire [7:0] post1_img_green; //Processed Image Green output
wire [7:0] post1_img_blue; //Processed Image Blueoutput
wire post2_frame_vsync; //Processed Image data vsync valid signal
wire post2_frame_href; //Processed Image data href vaild signal
wire [7:0] post2_img_Gray; //Processed Image Gray output
generate if(RAW2RG888_YUV444 == "ON") begin : RAW2RG888_YUV444_ON
RAW8_RGB888 # (
.IMG_HDISP (IMG_HDISP), //640*480
.IMG_VDISP (IMG_VDISP)
) RAW8_RGB888_u (
//global clock
.clk (clk), //cmos video pixel clock
.rst_n (rst_n), //system reset
//Image data prepred to be processd
.per_frame_vsync (per_frame_vsync), //Prepared Image data vsync valid signal
.per_frame_href (per_frame_href), //Prepared Image data href vaild signal
.per_img_RAW (per_img_RAW), //Prepared Image data 8 Bit RAW Data
//Image data has been processd
.post_frame_vsync (post1_frame_vsync), //Processed Image data vsync valid signal
.post_frame_href (post1_frame_href), //Processed Image data href vaild signal
.post_img_red (post1_img_red), //Prepared Image green data to be processed
.post_img_green (post1_img_green), //Prepared Image green data to be processed
.post_img_blue (post1_img_blue) //Prepared Image blue data to be processed
);
//-------------------------------------
//Convert the RGB888 format to YCbCr444 format.
RGB888_YCbCr444 RGB888_YCbCr444_u(
//global clock
.clk (clk), //cmos video pixel clock
.rst_n (rst_n), //system reset
//Image data prepred to be processd
.per_frame_vsync (post1_frame_vsync), //Prepared Image data vsync valid signal
.per_frame_href (post1_frame_href), //Prepared Image data href vaild signal
.per_img_red (post1_img_red), //Prepared Image red data input
.per_img_green (post1_img_green), //Prepared Image green data input
.per_img_blue (post1_img_blue), //Prepared Image blue data input
//Image data has been processd
.post_frame_vsync (post2_frame_vsync), //Processed Image frame data valid signal
.post_frame_href (post2_frame_href), //Processed Image hsync data valid signal
.post_img_Y (post2_img_Gray), //Processed Image brightness output
.post_img_Cb (), //Processed Image blue shading output
.post_img_Cr () //Processed Image red shading output
);
end
else if(RAW2RG888_YUV444 == "OFF") begin : RAW2RG888_YUV444_OFF
assign post2_frame_vsync = per_frame_vsync;
assign post2_frame_href = per_frame_href;
assign post2_img_Gray = per_img_RAW;
end
endgenerate
//--------------------------------------
//Gray Image median filter for better picture quality.
wire post3_frame_vsync; //Processed Image data vsync valid signal
wire post3_frame_href; //Processed Image data href vaild signal
wire [7:0] post3_img_Gray; //Processed Image Gray output
generate if(GRAY_MEDIUM == "ON") begin : GRAY_MEDIUM_ON
Gray_Median_Filter # (
.IMG_HDISP (IMG_HDISP), //640*480
.IMG_VDISP (IMG_VDISP)
) Gray_Median_Filter_u (
//global clock
.clk (clk), //cmos video pixel clock
.rst_n (rst_n), //global reset
//Image data prepred to be processd
.per_frame_vsync (post2_frame_vsync), //Prepared Image data vsync valid signal
.per_frame_href (post2_frame_href), //Prepared Image data href vaild signal
.per_img_Gray (post2_img_Gray), //Prepared Image brightness input
//Image data has been processd
.post_frame_vsync (post3_frame_vsync), //Processed Image data vsync valid signal
.post_frame_href (post3_frame_href), //Processed Image data href vaild signal
.post_img_Gray (post3_img_Gray) //Processed Image brightness output
);
end
else if(GRAY_MEDIUM == "OFF") begin : GRAY_MEDIUM_OFF
assign post3_frame_vsync = post2_frame_vsync;
assign post3_frame_href = post2_frame_href;
assign post3_img_Gray = post2_img_Gray;
end
endgenerate
//--------------------------------------
//Image edge detector with Sobel.
wire post4_frame_vsync; //Processed Image data vsync valid signal
wire post4_frame_href; //Processed Image data href vaild signal
wire post4_img_Bit; //Processed Image Bit flag outout(1: Value, 0:inValid)
wire [7:0] post4_img_Gray;
generate if(GRAY_SOBEL == "ON") begin : GRAY_SOBEL_ON
Sobel_Edge_Detector # (
.IMG_HDISP (IMG_HDISP), //640*480
.IMG_VDISP (IMG_VDISP)
) Sobel_Edge_Detector_u (
//global clock
.clk (clk), //cmos video pixel clock
.rst_n (rst_n), //global reset
//Image data prepred to be processd
.per_frame_vsync (post3_frame_vsync), //Prepared Image data vsync valid signal
.per_frame_href (post3_frame_href), //Prepared Image data href vaild signal
.per_img_Gray (post3_img_Gray), //Prepared Image brightness input
//Image data has been processd
.post_frame_vsync (post4_frame_vsync), //Processed Image data vsync valid signal
.post_frame_href (post4_frame_href), //Processed Image data href vaild signal
.post_img_Bit (post4_img_Bit), //Processed Image Bit flag outout(1: Value, 0:inValid)
//User interface
.Sobel_Threshold (Sobel_Threshold) //Sobel Threshold for image edge detect
);
assign post4_img_Gray = {8{~post4_img_Bit}};
end
else if(GRAY_SOBEL == "OFF") begin : GRAY_SOBEL_OFF
assign post4_frame_vsync = post3_frame_vsync;
assign post4_frame_href = post3_frame_href;
assign post4_img_Gray = post3_img_Gray;
end
endgenerate
//--------------------------------------
//Bit Image Process with Erosion before Dilation Detector.
wire post5_frame_vsync; //Processed Image data vsync valid signal
wire post5_frame_href; //Processed Image data href vaild signal
wire post5_img_Bit; //Processed Image Bit flag outout(1: Value, 0:inValid)
wire [7:0] post5_img_Gray;
generate if(GRAY_EROSION == "ON") begin : GRAY_EROSION_ON
Bit_Erosion_Detector # (
.IMG_HDISP (IMG_HDISP), //640*480
.IMG_VDISP (IMG_VDISP)
) Bit_Erosion_Detector_u (
//global clock
.clk (clk), //cmos video pixel clock
.rst_n (rst_n), //global reset
//Image data prepred to be processd
.per_frame_vsync (post4_frame_vsync), //Prepared Image data vsync valid signal
.per_frame_href (post4_frame_href), //Prepared Image data href vaild signal
.per_img_Bit (post4_img_Gray[0]), //Processed Image Bit flag outout(1: Value, 0:inValid)
//Image data has been processd
.post_frame_vsync (post5_frame_vsync), //Processed Image data vsync valid signal
.post_frame_href (post5_frame_href), //Processed Image data href vaild signal
.post_img_Bit (post5_img_Bit) //Processed Image Bit flag outout(1: Value, 0:inValid)
);
assign post5_img_Gray = {8{post5_img_Bit}};
end
else if(GRAY_EROSION == "OFF") begin : GRAY_EROSION_OFF
assign post5_frame_vsync = post4_frame_vsync;
assign post5_frame_href = post4_frame_href;
assign post5_img_Gray = post4_img_Gray;
end
endgenerate
//--------------------------------------
//Bit Image Process with Dilation after Erosion Detector.
wire post6_frame_vsync; //Processed Image data vsync valid signal
wire post6_frame_href; //Processed Image data href vaild signal
wire post6_img_Bit; //Processed Image Bit flag outout(1: Value, 0:inValid)
wire [7:0] post6_img_Gray;
generate if(GRAY_DILATION == "ON") begin : GRAY_DILATION_ON
Bit_Dilation_Detector # (
.IMG_HDISP (IMG_HDISP), //640*480
.IMG_VDISP (IMG_VDISP)
) Bit_Dilation_Detector_u (
//global clock
.clk (clk), //cmos video pixel clock
.rst_n (rst_n), //global reset
//Image data prepred to be processd
.per_frame_vsync (post5_frame_vsync), //Prepared Image data vsync valid signal
.per_frame_href (post5_frame_href), //Prepared Image data href vaild signal
.per_img_Bit (post5_img_Gray[0]), //Processed Image Bit flag outout(1: Value, 0:inValid)
//Image data has been processd
.post_frame_vsync (post6_frame_vsync), //Processed Image data vsync valid signal
.post_frame_href (post6_frame_href), //Processed Image data href vaild signal
.post_img_Bit (post6_img_Bit) //Processed Image Bit flag outout(1: Value, 0:inValid)
);
assign post6_img_Gray = {8{post6_img_Bit}};
end
else if(GRAY_DILATION == "OFF") begin : GRAY_DILATION_OFF
assign post6_frame_vsync = post5_frame_vsync;
assign post6_frame_href = post5_frame_href;
assign post6_img_Gray = post5_img_Gray;
end
endgenerate
assign post_frame_vsync = post6_frame_vsync; //Processed Image data vsync valid signal
assign post_frame_href = post6_frame_href; //Processed Image data href vaild signal
assign post_img_Gray = post6_img_Gray; //Processed Image Gray output
endmodule

View File

@ -0,0 +1,17 @@
module AD6645
(
input clk_in,
input rst_n,
input [13:0] AD_data,
output [13:0] wave_CH
);
reg [13:0] wave_CH_buf;
always@(posedge clk_in or negedge rst_n)
begin
if(!rst_n)
wave_CH_buf <= 14'd0;
else
wave_CH_buf <= AD_data;
end
assign wave_CH = wave_CH_buf - 14'd1700;
endmodule

View File

@ -0,0 +1,195 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
library UNISIM;
use UNISIM.VComponents.all;
entity ADC_CFG is
Port (
clk : in std_logic;
rstn : in std_logic;
sclk : out std_logic;
sdata : out std_logic;
sen : out std_logic;
adc_rst : out std_logic;
cfg_done : out std_logic
);
end ADC_CFG;
architecture Behavioral of ADC_CFG iimage.pngsimage.png
image.png
component CFG_INT
Port (
CLK : in STD_LOGIC;--100mhz
RSTn : in STD_LOGIC;
TRIG : in STD_LOGIC;
ADDR : in STD_LOGIC_VECTOR (7 downto 0);
DATA : in STD_LOGIC_VECTOR (7 downto 0);
SCLK : out STD_LOGIC;
SDATA : out STD_LOGIC;
SEN : out STD_LOGIC;
BUSY : out STD_LOGIC
);
end component;
type array_reg is array (0 to 25) of std_logic_vector(7 downto 0);
signal addr_reg : array_reg :=( x"42", --
x"00", --bit0 readout ; --bit1 reset
x"01",
x"03",
x"25",
x"29",
x"2b",
x"3d",
x"3f",
x"40",
x"41",
x"42",
x"45",
x"4a",
x"58",
x"bf",
x"c1",
x"cf",
x"ef",
x"f1",
x"f2",
x"02",
x"d5",
x"d7",
x"db",
x"00" --the last byte no meaning
);
constant data_reg : array_reg :=( x"08", --
x"00", --bit0 readout ; --bit1 reset
x"00",
x"03",
x"00",
x"00",
x"00",
x"00",
x"00",
x"00",
x"03",
x"08",
x"00",
x"01",
x"01",
x"00",
x"00",
x"00",
x"00",
x"03",
x"00",
x"40",
x"18",
x"0c",
x"20",
x"00" --the last byte no meaning
);
signal trig : std_logic;
signal busy : std_logic;
signal busy_r : std_logic;
signal busy_rr : std_logic;
signal busy_rrr : std_logic;
signal resetn : std_logic;
signal busy_pulse : std_logic;
signal cfg_done_i : std_logic;
signal byte_count : std_logic_vector(7 downto 0);
signal addr : std_logic_vector(7 downto 0);
signal data : std_logic_vector(7 downto 0);
signal rst_count : std_logic_vector(11 downto 0);
signal clkIbuf : std_logic;
signal clkIbufG : std_logic;
begin
clkIbufG <= clk;
CFG_INT_inst : CFG_INT
Port map(
CLK => clkIbufG ,--: in STD_LOGIC;--100mhz
RSTn => rstn ,--: in STD_LOGIC;
TRIG => trig ,--: in STD_LOGIC;
ADDR => addr ,--: in STD_LOGIC_VECTOR (7 downto 0);
DATA => data ,--: in STD_LOGIC_VECTOR (7 downto 0);
SCLK => sclk ,--: out STD_LOGIC;
SDATA => sdata ,--: out STD_LOGIC;
SEN => sen ,--: out STD_LOGIC;
BUSY => busy --: out STD_LOGIC
);
process(clkIbufG,rstn)
begin
if rstn='0' then
rst_count<=(others=>'0');
elsif rising_edge(clkIbufG) then
if rst_count=x"2ff" then
rst_count<=rst_count;
else
rst_count<=rst_count+1;
end if;
end if;
end process;
adc_rst<=not rst_count(9);
resetn<='1' when rstn='1' and rst_count(9)='1' else '0';
process(clkIbufG,resetn)
begin
if resetn='0' then busy_r<='0';
busy_rr<='0';
busy_rrr<='0';
elsif rising_edge(clkIbufG) then
busy_r<=busy;
busy_rr<=busy_r;
busy_rrr<=busy_rr;
end if;
end process;
busy_pulse<='1' when busy_r='0' and busy_rr='1' else '0';
process(clkIbufG,resetn)
begin
if resetn='0' then byte_count<=(others=>'0');
cfg_done_i<='0';
elsif rising_edge(clkIbufG) then
cfg_done_i<='0';
if byte_count=x"10" then
byte_count<=byte_count;
cfg_done_i<='1';
elsif busy_pulse='1' then
byte_count<=byte_count+1;
else
byte_count<=byte_count;
end if;
end if;
end process;
cfg_done<=cfg_done_i;
addr<=addr_reg(conv_integer(byte_count));
data<=data_reg(conv_integer(byte_count));
process(clkIbufG,resetn)
begin
if resetn='0' then
trig<='0';
elsif rising_edge(clkIbufG) then
if byte_count/=x"10" and busy_rrr='0' then
trig<='1';
else
trig<='0';
end if;
end if;
end process;
end Behavioral;

View File

@ -0,0 +1,51 @@
`timescale 1ns / 1ps
module ADS412x_driver(
// input sys_rst_n,
input user_clk,
output [11:0] user_rd_data,
output adc_sclk, // sclk
output adc_sdata, // sda
output adc_reset,
output adc_sen,
input [11:0] adc_data,
input adc_clk,
output adc_samp_clk
);
wire sys_rst_n;
assign sys_rst_n = 1;
wire adc_config_done;
wire rst_n;
reg [11:0] adc_data_r;
reg [11:0] adc_data_rr;
assign adc_samp_clk=user_clk;
assign rst_n = ((adc_config_done == 1'b1) && (sys_rst_n == 1'b1)) ? 1'b1 : 1'b0;
assign user_rd_data=adc_data_rr;////
ADC_CFG u_ADS4128_CFG(
.clk ( user_clk ),
.rstn ( sys_rst_n ),
.sclk ( adc_sclk ),
.sdata ( adc_sdata ),
.sen ( adc_sen ),
.adc_rst ( adc_reset ),
.cfg_done ( adc_config_done )
);
always @ (posedge adc_clk) begin
if (rst_n == 1'b0) begin
adc_data_r <= 12'h000;
adc_data_rr <= 12'h000;
end
else begin
adc_data_r <= adc_data;
adc_data_rr <= adc_data_r + 12'b1000_0000_0000;
end
end
endmodule

View File

@ -0,0 +1,250 @@
----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 2016/04/06 13:55:20
-- Design Name:
-- Module Name: CFG_INT - Behavioral
-- Project Name:
-- Target Devices:
-- Tool Versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity CFG_INT is
Port (
CLK : in STD_LOGIC;--100mhz
RSTn : in STD_LOGIC;
TRIG : in STD_LOGIC;
ADDR : in STD_LOGIC_VECTOR(7 downto 0);
DATA : in STD_LOGIC_VECTOR(7 downto 0);
SCLK : out STD_LOGIC;
SDATA : out STD_LOGIC;
SEN : out STD_LOGIC;
BUSY : out STD_LOGIC
);
end CFG_INT;
architecture Behavioral of CFG_INT is
type state_type is (idle,start,wr_addr,wr_data,done);
signal state : state_type;
signal freq_div : std_logic_vector(3 downto 0);
signal trig_r : std_logic;
signal trig_rr : std_logic;
signal trigger : std_logic;
signal addr_i : std_logic_vector(7 downto 0);
signal addr_r : std_logic_vector(7 downto 0);
signal data_i : std_logic_vector(7 downto 0);
signal data_r : std_logic_vector(7 downto 0);
signal sen_i : std_logic;
signal bit_count : std_logic_vector(3 downto 0);
signal sclk_r : std_logic;
signal sclk_f : std_logic;
signal sclk_flag : std_logic;
signal sclk_i : std_logic;
signal sdata_i : std_logic;
signal busy_i : std_logic;
begin
process(clk,rstn)
begin
if rstn='0' then
trig_r<='0';
trig_rr<='0';
elsif rising_edge(clk) then
trig_r<=trig;
trig_rr<=trig_r;
end if;
end process;
trigger<='1' when trig_r='1' and trig_rr='0' else '0';
process(clk,rstn)
begin
if rstn='0' then addr_i<=(others=>'0');
data_i<=(others=>'0');
elsif rising_edge(clk) then
if trigger='1' then
addr_i<=addr;
data_i<=data;
end if;
end if;
end process;
process(clk,rstn)
begin
if rstn='0' then state<=idle;
sen_i<='1';
busy_i<='0';
sclk_flag<='0';
elsif rising_edge(clk) then
case state is
when idle =>
if trigger='1' then
state<=start;
busy_i<='1';
else
state<=idle;
end if;
when start =>
state<=wr_addr;
when wr_addr =>
sclk_flag<='1';
sen_i<='0';
if bit_count=x"8" then
state<=wr_data;
else
state<=wr_addr;
end if;
when wr_data =>
if bit_count=x"8" then
state<=done;
else
state<=wr_data;
end if;
when done =>
if sclk_r='1' then state<=idle;
sen_i<='1';
sclk_flag<='0';
busy_i<='0';
else
state<=done;
end if;
when others=> state<=idle;
end case;
end if;
end process;
sen<=sen_i;
busy<=busy_i;
process(clk,rstn)
begin
if rstn='0' then
freq_div<=(others=>'0');
elsif rising_edge(clk) then
if sclk_flag='1' then
if freq_div=x"9" then
freq_div<=(others=>'0');
else
freq_div<=freq_div+'1';
end if;
else
freq_div<=(others=>'0');
end if;
end if;
end process;
process(clk,rstn)
begin
if rstn='0' then
sclk_r<='0';
sclk_f<='0';
elsif rising_edge(clk) then
sclk_r<='0';
sclk_f<='0';
if sclk_flag='1' then
if freq_div=x"0" then
sclk_r<='1';
elsif freq_div=x"5" then
sclk_f<='1';
end if;
end if;
end if;
end process;
process(clk,rstn)
begin
if rstn='0' then
sclk_i<='1';
elsif rising_edge(clk) then
if sclk_flag='1' then
if sclk_r='1' then
sclk_i<='1';
elsif sclk_f='1' then
sclk_i<='0';
else
sclk_i<=sclk_i;
end if;
else
sclk_i<='1';
end if;
end if;
end process;
sclk<=sclk_i;
process(clk,rstn)
begin
if rstn='0' then
bit_count<=(others=>'0');
elsif rising_edge(clk) then
if bit_count=8 then
bit_count<=(others=>'0');
elsif sclk_f='1' then
bit_count<=bit_count+1;
else
bit_count<=bit_count;
end if;
end if;
end process;
process(clk,rstn)
begin
if rstn='0' then
addr_r<=(others=>'0');
data_r<=(others=>'0');
sdata_i<='0';
elsif rising_edge(clk) then
if state=start then
addr_r<=addr_i;
data_r<=data_i;
elsif state=wr_addr then
if sclk_r='1' then
sdata_i<=addr_r(7);
addr_r<=addr_r(6 downto 0) & '0';
else
sdata_i<=sdata_i;
addr_r<=addr_r;
end if;
elsif state=wr_data then
if sclk_r='1' then
sdata_i<=data_r(7);
data_r<=data_r(6 downto 0) & '0';
else
sdata_i<=sdata_i;
data_r<=data_r;
end if;
elsif state=done then
sdata_i<=sdata_i;
else
sdata_i<='0';
end if;
end if;
end process;
sdata<=sdata_i;
end Behavioral;

View File

@ -0,0 +1,37 @@
module AD9226_driver #
(
parameter signed CH_offset = 27
)
(
input clk_in,
input rst_n,
input [11:0] AD_data,
output AD_clk,
output [11:0] wave_CH
);
reg signed [11:0] wave_CH_buf;
always@(posedge clk_in or negedge rst_n) begin
if(!rst_n)
wave_CH_buf <= 12'd0;
else begin
wave_CH_buf[11] <= AD_data[0];
wave_CH_buf[10] <= AD_data[1];
wave_CH_buf[9] <= AD_data[2];
wave_CH_buf[8] <= AD_data[3];
wave_CH_buf[7] <= AD_data[4];
wave_CH_buf[6] <= AD_data[5];
wave_CH_buf[5] <= AD_data[6];
wave_CH_buf[4] <= AD_data[7];
wave_CH_buf[3] <= AD_data[8];
wave_CH_buf[2] <= AD_data[9];
wave_CH_buf[1] <= AD_data[10];
wave_CH_buf[0] <= AD_data[11];
end
end
assign wave_CH = $signed(wave_CH_buf) + $signed(CH_offset);
assign AD_clk = clk_in;
endmodule

View File

@ -0,0 +1,65 @@
`timescale 1ns / 1ps
module DAC3162_driver (
input clk_in,
input clk_div,
input [11:0] DA3162_CH1,
input [11:0] DA3162_CH2,
/*DAC*/
output [11:0] dac_data_p,
output [11:0] dac_data_n,
output dac_clk_p,
output dac_clk_n,
output dac_sleep
);
assign dac_sleep = 1'd1;
reg [11:0] dac_a_int = 0;
reg [11:0] dac_b_int = 0;
reg [11:0] dac_a_intt = 0;
reg [11:0] dac_b_intt = 0;
reg [1:0] cnt_clk = 0;
reg [3:0] power_on_rst_cnt = 4'h0;
reg power_on_rst = 1;
always @ (posedge clk_in) begin
dac_a_int<=DA3162_CH1 + 12'b100000000000;
dac_b_int<=DA3162_CH2 + 12'b100000000000;
dac_a_intt<=dac_a_int;
dac_b_intt<=dac_b_int;
end
always @ (posedge clk_div) begin
if (power_on_rst_cnt == 4'hf) begin
power_on_rst_cnt <= power_on_rst_cnt;
power_on_rst <= 0;
end
else begin
power_on_rst_cnt <= power_on_rst_cnt + 1;
power_on_rst <= 1;
end
end
LVDS_DDR_clk DAC3162_clk_u (
.data_out_from_device ( 4'b0101 ), // input [3:0] data_out_from_device
.data_out_to_pins_p ( dac_clk_p ), // output [0:0] data_out_to_pins_p
.data_out_to_pins_n ( dac_clk_n ), // output [0:0] data_out_to_pins_n
.clk_in ( clk_in ), // input clk_in
.clk_div_in ( clk_div ), // input clk_div_in
.io_reset ( power_on_rst ) // input io_reset
);
// input [47:0] data_out_from_device
LVDS_DDR_data DAC3162_data_u (
.clk_in ( clk_in ), // input clk_in
.clk_div_in ( clk_div ), // input clk_div_in
.data_out_from_device ({dac_a_int,dac_b_int,dac_a_intt,dac_b_intt} ),
.data_out_to_pins_p ( dac_data_p ), // output [11:0] data_out_to_pins_p
.data_out_to_pins_n ( dac_data_n ), // output [11:0] data_out_to_pins_n
.io_reset ( power_on_rst ) // input io_reset
);
endmodule

View File

@ -0,0 +1,108 @@
`timescale 1ps/1ps
(* CORE_GENERATION_INFO = "LVDS_DDR_clk,selectio_wiz_v5_1_12,{component_name=LVDS_DDR_clk,bus_dir=OUTPUTS,bus_sig_type=DIFF,bus_io_std=DIFF_HSTL_I_18,use_serialization=true,use_phase_detector=false,serialization_factor=4,enable_bitslip=false,enable_train=false,system_data_width=1,bus_in_delay=NONE,bus_out_delay=NONE,clk_sig_type=SINGLE,clk_io_std=LVCMOS18,clk_buf=BUFIO2,active_edge=RISING,clk_delay=NONE,selio_bus_in_delay=NONE,selio_bus_out_delay=NONE,selio_clk_buf=MMCM,selio_active_edge=DDR,selio_ddr_alignment=SAME_EDGE_PIPELINED,selio_oddr_alignment=SAME_EDGE,ddr_alignment=C0,selio_interface_type=NETWORKING,interface_type=NETWORKING,selio_bus_in_tap=0,selio_bus_out_tap=0,selio_clk_io_std=DIFF_HSTL_I_18,selio_clk_sig_type=DIFF}" *)
module LVDS_DDR_clk
// width of the data for the system
#(parameter SYS_W = 1,
// width of the data for the device
parameter DEV_W = 4)
(
// From the device out to the system
input [DEV_W-1:0] data_out_from_device,
output [SYS_W-1:0] data_out_to_pins_p,
output [SYS_W-1:0] data_out_to_pins_n,
input clk_in, // Fast clock input from PLL/MMCM
input clk_div_in, // Slow clock input from PLL/MMCM
input io_reset);
localparam num_serial_bits = DEV_W/SYS_W;
wire clock_enable = 1'b1;
// Signal declarations
////------------------------------
// Before the buffer
wire [SYS_W-1:0] data_out_to_pins_int;
// Between the delay and serdes
wire [SYS_W-1:0] data_out_to_pins_predelay;
// Array to use intermediately from the serdes to the internal
// devices. bus "0" is the leftmost bus
wire [SYS_W-1:0] oserdes_d[0:13]; // fills in starting with 13
// Create the clock logic
// We have multiple bits- step over every bit, instantiating the required elements
genvar pin_count;
genvar slice_count;
generate for (pin_count = 0; pin_count < SYS_W; pin_count = pin_count + 1) begin: pins
// Instantiate the buffers
////------------------------------
// Instantiate a buffer for every bit of the data bus
OBUFDS
#(.IOSTANDARD ("DIFF_HSTL_I_18"))
obufds_inst
(.O (data_out_to_pins_p [pin_count]),
.OB (data_out_to_pins_n [pin_count]),
.I (data_out_to_pins_int[pin_count]));
// Pass through the delay
////-------------------------------
assign data_out_to_pins_int[pin_count] = data_out_to_pins_predelay[pin_count];
// Instantiate the serdes primitive
////------------------------------
// declare the oserdes
OSERDESE2
# (
.DATA_RATE_OQ ("DDR"),
.DATA_RATE_TQ ("DDR"),
.DATA_WIDTH (4),
.TRISTATE_WIDTH (4),
.SERDES_MODE ("MASTER"))
oserdese2_master (
.D1 (oserdes_d[13][pin_count]),
.D2 (oserdes_d[12][pin_count]),
.D3 (oserdes_d[11][pin_count]),
.D4 (oserdes_d[10][pin_count]),
.D5 (oserdes_d[9][pin_count]),
.D6 (oserdes_d[8][pin_count]),
.D7 (oserdes_d[7][pin_count]),
.D8 (oserdes_d[6][pin_count]),
.T1 (1'b0),
.T2 (1'b0),
.T3 (1'b0),
.T4 (1'b0),
.SHIFTIN1 (1'b0),
.SHIFTIN2 (1'b0),
.SHIFTOUT1 (),
.SHIFTOUT2 (),
.OCE (clock_enable),
.CLK (clk_in),
.CLKDIV (clk_div_in),
.OQ (data_out_to_pins_predelay[pin_count]),
.TQ (),
.OFB (),
.TFB (),
.TBYTEIN (1'b0),
.TBYTEOUT (),
.TCE (1'b0),
.RST (io_reset));
// Concatenate the serdes outputs together. Keep the timesliced
// bits together, and placing the earliest bits on the right
// ie, if data comes in 0, 1, 2, 3, 4, 5, 6, 7, ...
// the output will be 3210, 7654, ...
////---------------------------------------------------------
for (slice_count = 0; slice_count < num_serial_bits; slice_count = slice_count + 1) begin: out_slices
// This places the first data in time on the right
assign oserdes_d[14-slice_count-1] =
data_out_from_device[slice_count];
// To place the first data in time on the left, use the
// following code, instead
// assign oserdes_d[slice_count] =
// data_out_from_device[slice_count];
end
end
endgenerate
endmodule

View File

@ -0,0 +1,106 @@
`timescale 1ps/1ps
(* CORE_GENERATION_INFO = "LVDS_DDR_data,selectio_wiz_v5_1_12,{component_name=LVDS_DDR_data,bus_dir=OUTPUTS,bus_sig_type=DIFF,bus_io_std=DIFF_HSTL_I_18,use_serialization=true,use_phase_detector=false,serialization_factor=4,enable_bitslip=false,enable_train=false,system_data_width=12,bus_in_delay=NONE,bus_out_delay=NONE,clk_sig_type=SINGLE,clk_io_std=LVCMOS18,clk_buf=BUFIO2,active_edge=RISING,clk_delay=NONE,selio_bus_in_delay=NONE,selio_bus_out_delay=NONE,selio_clk_buf=MMCM,selio_active_edge=DDR,selio_ddr_alignment=SAME_EDGE_PIPELINED,selio_oddr_alignment=SAME_EDGE,ddr_alignment=C0,selio_interface_type=NETWORKING,interface_type=NETWORKING,selio_bus_in_tap=0,selio_bus_out_tap=0,selio_clk_io_std=DIFF_HSTL_I_18,selio_clk_sig_type=DIFF}" *)
module LVDS_DDR_data
// width of the data for the system
#(parameter SYS_W = 12,
// width of the data for the device
parameter DEV_W = 48)
(
// From the device out to the system
input [DEV_W-1:0] data_out_from_device,
output [SYS_W-1:0] data_out_to_pins_p,
output [SYS_W-1:0] data_out_to_pins_n,
input clk_in, // Fast clock input from PLL/MMCM
input clk_div_in, // Slow clock input from PLL/MMCM
input io_reset);
localparam num_serial_bits = DEV_W/SYS_W;
wire clock_enable = 1'b1;
// Signal declarations
////------------------------------
// Before the buffer
wire [SYS_W-1:0] data_out_to_pins_int;
// Between the delay and serdes
wire [SYS_W-1:0] data_out_to_pins_predelay;
// Array to use intermediately from the serdes to the internal
// devices. bus "0" is the leftmost bus
wire [SYS_W-1:0] oserdes_d[0:13]; // fills in starting with 13
// Create the clock logic
// We have multiple bits- step over every bit, instantiating the required elements
genvar pin_count;
genvar slice_count;
generate for (pin_count = 0; pin_count < SYS_W; pin_count = pin_count + 1) begin: pins
// Instantiate the buffers
////------------------------------
// Instantiate a buffer for every bit of the data bus
OBUFDS
#(.IOSTANDARD ("DIFF_HSTL_I_18"))
obufds_inst
(.O (data_out_to_pins_p [pin_count]),
.OB (data_out_to_pins_n [pin_count]),
.I (data_out_to_pins_int[pin_count]));
// Pass through the delay
////-------------------------------
assign data_out_to_pins_int[pin_count] = data_out_to_pins_predelay[pin_count];
// Instantiate the serdes primitive
////------------------------------
// declare the oserdes
OSERDESE2 # (
.DATA_RATE_OQ ("DDR"),
.DATA_RATE_TQ ("DDR"),
.DATA_WIDTH (4),
.TRISTATE_WIDTH (4),
.SERDES_MODE ("MASTER"))
oserdese2_master (
.D1 (oserdes_d[13][pin_count]),
.D2 (oserdes_d[12][pin_count]),
.D3 (oserdes_d[11][pin_count]),
.D4 (oserdes_d[10][pin_count]),
.D5 (oserdes_d[9][pin_count]),
.D6 (oserdes_d[8][pin_count]),
.D7 (oserdes_d[7][pin_count]),
.D8 (oserdes_d[6][pin_count]),
.T1 (1'b0),
.T2 (1'b0),
.T3 (1'b0),
.T4 (1'b0),
.SHIFTIN1 (1'b0),
.SHIFTIN2 (1'b0),
.SHIFTOUT1 (),
.SHIFTOUT2 (),
.OCE (clock_enable),
.CLK (clk_in),
.CLKDIV (clk_div_in),
.OQ (data_out_to_pins_predelay[pin_count]),
.TQ (),
.OFB (),
.TFB (),
.TBYTEIN (1'b0),
.TBYTEOUT (),
.TCE (1'b0),
.RST (io_reset));
// Concatenate the serdes outputs together. Keep the timesliced
// bits together, and placing the earliest bits on the right
// ie, if data comes in 0, 1, 2, 3, 4, 5, 6, 7, ...
// the output will be 3210, 7654, ...
////---------------------------------------------------------
for (slice_count = 0; slice_count < num_serial_bits; slice_count = slice_count + 1) begin: out_slices
// This places the first data in time on the right
assign oserdes_d[14-slice_count-1] =
data_out_from_device[slice_count*SYS_W+:SYS_W];
// To place the first data in time on the left, use the
// following code, instead
// assign oserdes_d[slice_count] =
// data_out_from_device[slice_count*SYS_W+:SYS_W];
end
end
endgenerate
endmodule

View File

@ -0,0 +1,62 @@
//============================================================================================
/*
* #Author : sterben(Duan)
* #LastAuthor : sterben(Duan)
* #Date : 2019-09-27 00:00:34
* #lastTime : 2020-01-22 23:54:59
* #FilePath : src\Driver\DAC_driver\DAC9767_driver\DA9767.v
* #Description : port:
*/
//============================================================================================
module DA9767 #
(
parameter INPUT_WIDTH = 14,
parameter INPUT_STYLE = "signed",
parameter ALIGNED_STYLE = "LSB"
)
(
input clk_in,
input [INPUT_WIDTH - 1 : 0] DA_data,
output DA_clk,
output DA_wrt,
output [13:0] DA_out
);
generate if(INPUT_STYLE == "signed") begin : OUTPUT
if (INPUT_WIDTH < 14) begin
localparam DATA_WIDTH = 14 - INPUT_WIDTH;
if (ALIGNED_STYLE == "LSB") begin
assign DA_out = $signed({{DATA_WIDTH{DA_data[INPUT_WIDTH-1]}},DA_data})
+ $signed(14'd8192);
end
else if(ALIGNED_STYLE == "MSB") begin
reg [DATA_WIDTH - 1 : 0 ] data_buf = 0;
assign DA_out = $signed({DA_data,data_buf}) + $signed(14'd8192);
end
end
else begin
assign DA_out = $signed(DA_data[INPUT_WIDTH - 1 : INPUT_WIDTH - 14]) + $signed(14'd8192);
end
end
else if(INPUT_STYLE == "unsigned") begin
if (INPUT_WIDTH < 14) begin
localparam DATA_WIDTH = 14 - INPUT_WIDTH;
if (ALIGNED_STYLE == "LSB") begin
assign DA_out = {{DATA_WIDTH{DA_data[INPUT_WIDTH-1]}},DA_data};
end
else if(ALIGNED_STYLE == "MSB") begin
reg [DATA_WIDTH - 1 : 0 ] data_buf = 0;
assign DA_out = {DA_data,data_buf};
end
end
else begin
assign DA_out = DA_data[INPUT_WIDTH - 1 : INPUT_WIDTH - 14];
end
end
endgenerate
assign DA_clk = clk_in;
assign DA_wrt = clk_in;
endmodule

View File

@ -0,0 +1,35 @@
module DAC_PWM #
(
parameter MAIN_FRE = 500,
parameter PWM_FRE = 1000,
parameter PHASE_WIDTH = 32
)
(
input clk_in,
input RST,
output DAC_PWM,
input [PHASE_WIDTH-1:0] data_in
);
localparam [PHASE_WIDTH-1:0] DC_ADD = (2**(PHASE_WIDTH-1)) - 1;
localparam [PHASE_WIDTH-1:0] FRE_WORD = (2**PHASE_WIDTH)*PWM_FRE/(MAIN_FRE*1000);
reg [PHASE_WIDTH-1:0] addr_r = 0;
always @(posedge clk_in) begin
if (RST)
addr_r <= 0;
else
addr_r <= addr_r + FRE_WORD;
end
reg [PHASE_WIDTH-1:0] duty_r = 0;
always @(posedge clk_in) begin
if (RST)
duty_r <= 32'd0;
else
duty_r <= $signed(data_in) + DC_ADD;
end
assign DAC_PWM = (addr_r <= duty_r) ? 1'b1 : 1'b0;
endmodule

View File

@ -0,0 +1,124 @@
module ADF_driver
(
input clk, //系统时钟
input wrsig, //发送命令上升沿有效
input [8:0] datain, //需要发送的数据
output reg tx_idle, //线路状态指示高为线路忙低为线路空闲
output reg tx, //发送数据信号
output reg clkout,
output reg LE
);
reg tx_send=0;
reg tx_wrsigbuf=0, tx_wrsigrise=0;
reg[7:0] tx_cnt=0; //计数器
//检测发送命令是否有效
reg [15:0] clk_cnt=0;
reg [31:0]dataint=0;
reg [10:0]cnt_init=0;
reg init=0;
reg [4:0] cnt_wei=0;
reg [15:0]int_v=0;
reg [11:0]frac_v=0;
parameter [31:0]R5=32'b00000000_00011_0000000000000000_101;
parameter [31:0]R4=32'b00000000_1101_01100100_000000_111100;
parameter [31:0]R3=32'b00000000_100000010_111111111111_011;
parameter [31:0]R2=32'b00000000_0000000001_00000_001000010;
parameter [31:0]R1=32'b00000_000000000000_000001100100_001;
reg [31:0]R0=32'b0_00000000_10100000_000000000000_000;
always @(posedge clk) begin//分频进程 CLK/(1000000)
if(clk_cnt == 16'd24) begin
clkout <= 1'b1;
clk_cnt <= clk_cnt + 16'd1;
end
else if(clk_cnt == 16'd49) begin
clkout <= 1'b0;
clk_cnt <= 16'd0;
end
else begin
clk_cnt <= clk_cnt + 16'd1;
end
end
always @(negedge clkout) begin
int_v<=datain/7'd100;
frac_v<=datain%7'd100;
if(!init) begin
cnt_init<=cnt_init+1'b1;
case(cnt_init)
11'd5: begin R0<=32'b0_00000000_10100000_000000000000_000; end
11'd1010: begin tx_send <= 1'b1; dataint<=R5; end
11'd1046: begin tx_send <= 1'b0; end
11'd1110: begin tx_send <= 1'b1; dataint<=R4; end
11'd1146: begin tx_send <= 1'b0; end
11'd1210: begin tx_send <= 1'b1; dataint<=R3; end
11'd1246: begin tx_send <= 1'b0; end
11'd1310: begin tx_send <= 1'b1; dataint<=R2; end
11'd1346: begin tx_send <= 1'b0; end
11'd1410: begin tx_send <= 1'b1; dataint<=R1; end
11'd1446: begin tx_send <= 1'b0; end
11'd1510: begin tx_send <= 1'b1; dataint<=R0; end
11'd1546: begin tx_send <= 1'b0; end
11'd1610: begin tx_send <= 1'b1; dataint<=R3; end
11'd1646: begin tx_send <= 1'b0; end
11'd1650: begin init<=1'b1; end
endcase
end
else begin
tx_wrsigbuf <= wrsig;
tx_wrsigrise <= (~tx_wrsigbuf) & wrsig;
if (tx_wrsigrise && (~tx_idle)) begin
tx_send <= 1'b1;
R0[30:15]<=int_v;
R0[14:3]<=frac_v;
end
else if(tx_cnt == 8'd36) begin
tx_send <= 1'b0;
end
end
end
always @(negedge clkout) begin
if(tx_send == 1'b1) begin
case(tx_cnt) //产生起始位
8'd1: begin
LE<=1'b0;
tx <= dataint[31];
cnt_wei<=5'd31;
tx_idle <= 1'b1;
tx_cnt <= tx_cnt + 8'd1;
end
8'd2,8'd3,8'd4,8'd5,8'd6,8'd7,8'd8,8'd9,8'd10,8'd11,8'd12,8'd13,8'd14,8'd15
,8'd16,8'd17,8'd18,8'd19,8'd20,8'd21,8'd22,8'd23,8'd24,8'd25,8'd26,8'd27,
8'd28,8'd29,8'd30,8'd31,8'd32,8'd33: begin
tx <= dataint[cnt_wei]; //发送数据0
cnt_wei<=cnt_wei-1'b1;
tx_idle <= 1'b1;
tx_cnt <= tx_cnt + 8'd1;
end
8'd34: begin
tx <= 1'b1;
LE<=1'b1;
tx_idle <= 1'b0;
tx_cnt <= tx_cnt + 8'd1;
end
default: begin
tx_cnt <= tx_cnt + 8'd1;
end
endcase
end
else begin
tx <= 1'b1;
LE<=1'b1;
cnt_wei<=5'd31;
tx_cnt <= 8'd0;
tx_idle <= 1'b0;
end
end
endmodule

View File

@ -0,0 +1,11 @@
module HDMI_in #(
parameter INPUT_WIDTH = 12,
parameter OUTPUT_WIDTH = 12
) (
input clk_in,
input rst_n,
input [INPUT_WIDTH - 1 : 0] data_in,
output [OUTPUT_WIDTH - 1 : 0] data_out
);
endmodule //HDMI_in

View File

@ -0,0 +1,11 @@
module HDMI_out #(
parameter INPUT_WIDTH = 12,
parameter OUTPUT_WIDTH = 12
) (
input clk_in,
input rst_n,
input [INPUT_WIDTH - 1 : 0] data_in,
output [OUTPUT_WIDTH - 1 : 0] data_out
);
endmodule //HDMI_out

View File

@ -0,0 +1,80 @@
`timescale 1 ns / 100 ps
module key_driver
(
input clk,
input rst,
input button_in,
output reg button_posedge,
output reg button_negedge,
output reg button_out
);
//// ---------------- internal constants --------------
parameter N = 32 ; // debounce timer bitwidth
parameter FREQ = 60; //model clock :Mhz
parameter MAX_TIME = 20; //ms
localparam TIMER_MAX_VAL = MAX_TIME * 1000 * FREQ;
////---------------- internal variables ---------------
reg [N-1 : 0] q_reg; // timing regs
reg [N-1 : 0] q_next;
reg DFF1, DFF2; // input flip-flops
wire q_add; // control flags
wire q_reset;
reg button_out_d0;
//// ------------------------------------------------------
////contenious assignment for counter control
assign q_reset = (DFF1 ^ DFF2); // xor input flip flops to look for level chage to reset counter
assign q_add = ~(q_reg == TIMER_MAX_VAL); // add to counter when q_reg msb is equal to 0
//// combo counter to manage q_next
always @ ( q_reset, q_add, q_reg) begin
case( {q_reset , q_add})
2'b00 :
q_next <= q_reg;
2'b01 :
q_next <= q_reg + 1;
default :
q_next <= { N {1'b0} };
endcase
end
//// Flip flop inputs and q_reg update
always @ ( posedge clk or posedge rst) begin
if(rst == 1'b1) begin
DFF1 <= 1'b0;
DFF2 <= 1'b0;
q_reg <= { N {1'b0} };
end
else begin
DFF1 <= button_in;
DFF2 <= DFF1;
q_reg <= q_next;
end
end
//// counter control
always @ ( posedge clk or posedge rst) begin
if(rst == 1'b1)
button_out <= 1'b1;
else if(q_reg == TIMER_MAX_VAL)
button_out <= DFF2;
else
button_out <= button_out;
end
always @ ( posedge clk or posedge rst) begin
if(rst == 1'b1) begin
button_out_d0 <= 1'b1;
button_posedge <= 1'b0;
button_negedge <= 1'b0;
end
else begin
button_out_d0 <= button_out;
button_posedge <= ~button_out_d0 & button_out;
button_negedge <= button_out_d0 & ~button_out;
end
end
endmodule

View File

@ -0,0 +1,112 @@
/********************************************
wire Motor_Control;
Motor_driver Motor_driver_u(
.clk_in(clk_50m),
.rst_n(1'd1),
.Trig(Trig),
.Meter(16'd4),
.Motor_Control(Motor_Control)
);
********************************************/
module Motor_driver (
input clk_in,
input rst_n,
input Trig,
input [15:0] Meter,
output reg Motor_Control
);
parameter MAIN_FRE = 50000000;
parameter MOTOR_FRE = 1000;
parameter SET_TIME = MAIN_FRE/MOTOR_FRE/2;
/***************************************************/
//define the data lock
reg Trig_SIG = 0;
reg Trig_SIG_buf = 0;
wire Trig_SIG_pose = Trig_SIG & ~Trig_SIG_buf;
wire Trig_SIG_nege = ~Trig_SIG & Trig_SIG_buf;
always@(posedge clk_in) begin
Trig_SIG <= Trig;
Trig_SIG_buf <= Trig_SIG;
end
/***************************************************/
/***************************************************/
//define the time counter
reg [15:0] cnt0 = 0;
reg Motor_Control_r = 0;
always@(posedge clk_in) begin
if (cnt0 == SET_TIME) begin
cnt0 <= 15'd0;
Motor_Control_r <= ~Motor_Control_r;
end
else
cnt0 <= cnt0 + 1'd1;
end
/***************************************************/
/***************************************************/
//define the data lock
reg motor_sig = 0;
reg motor_sig_buf = 0;
wire motor_sig_pose = motor_sig & ~motor_sig_buf;
wire motor_sig_nege = ~motor_sig & motor_sig_buf;
always@(posedge clk_in) begin
motor_sig <= Motor_Control_r;
motor_sig_buf <= motor_sig;
end
/***************************************************/
/***************************************************/
//define the time counter
reg [15:0] cnt1 = 0;
reg CNT_CE = 0;
always@(posedge clk_in) begin
if (Trig_SIG_pose) begin
CNT_CE <= 1'd1;
end
else if(cnt1 == Meter) begin
if (motor_sig_nege) begin
CNT_CE <= 1'd0;
end
else begin
CNT_CE <= CNT_CE;
end
end
else begin
CNT_CE <= CNT_CE;
end
end
/***************************************************/
reg MOTOR_CE = 0;
always @(posedge clk_in) begin
if (CNT_CE) begin
if (motor_sig_pose) begin
cnt1 <= cnt1 + 1'd1; //cnt1 counter = cnt1 counter + 1
MOTOR_CE <= 1'd1;
end
else begin
MOTOR_CE <= MOTOR_CE;
end
end
else begin
cnt1 <= 16'd0;
MOTOR_CE <= 1'd0;
end
end
always @(*) begin
case (MOTOR_CE)
1'b0 : begin Motor_Control <= 1'b0; end
1'b1 : begin Motor_Control <= Motor_Control_r; end
default : begin Motor_Control <= 1'b0; end
endcase
end
endmodule

View File

@ -0,0 +1,571 @@
/*********************************************************************
SDRAM Controller Bank Controller
This file is part of the sdram controller project
http://www.opencores.org/cores/sdr_ctrl/
Description:
This module takes requests from sdrc_req_gen, checks for page hit/miss and
issues precharge/activate commands and then passes the request to sdrc_xfr_ctl.
To Do:
nothing
Author(s):
- Dinesh Annayya, dinesha@opencores.org
Version : 1.0 - 8th Jan 2012
Copyright (C) 2000 Authors and OPENCORES.ORG
This source file may be used and distributed without
restriction provided that this copyright statement is not
removed from the file and that any derivative work contains
the original copyright notice and the associated disclaimer.
This source file is free software; you can redistribute it
and/or modify it under the terms of the GNU Lesser General
Public License as published by the Free Software Foundation;
either version 2.1 of the License, or (at your option) any
later version.
This source is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General
Public License along with this source; if not, download it
from http://www.opencores.org/lgpl.shtml
*******************************************************************/
`include "sdrc_define.v"
module sdrc_bank_ctl (clk,
reset_n,
a2b_req_depth, // Number of requests we can buffer
/* Req from req_gen */
r2b_req, // request
r2b_req_id, // ID
r2b_start, // First chunk of burst
r2b_last, // Last chunk of burst
r2b_wrap,
r2b_ba, // bank address
r2b_raddr, // row address
r2b_caddr, // col address
r2b_len, // length
r2b_write, // write request
b2r_arb_ok, // OK to arbitrate for next xfr
b2r_ack,
/* Transfer request to xfr_ctl */
b2x_idle, // All banks are idle
b2x_req, // Request to xfr_ctl
b2x_start, // first chunk of transfer
b2x_last, // last chunk of transfer
b2x_wrap,
b2x_id, // Transfer ID
b2x_ba, // bank address
b2x_addr, // row/col address
b2x_len, // transfer length
b2x_cmd, // transfer command
x2b_ack, // command accepted
/* Status to/from xfr_ctl */
b2x_tras_ok, // TRAS OK for all banks
x2b_refresh, // We did a refresh
x2b_pre_ok, // OK to do a precharge (per bank)
x2b_act_ok, // OK to do an activate
x2b_rdok, // OK to do a read
x2b_wrok, // OK to do a write
/* xfr msb address */
xfr_bank_sel,
sdr_req_norm_dma_last,
/* SDRAM Timing */
tras_delay, // Active to precharge delay
trp_delay, // Precharge to active delay
trcd_delay); // Active to R/W delay
parameter SDR_DW = 16; // SDR Data Width
parameter SDR_BW = 2; // SDR Byte Width
input clk, reset_n;
input [1:0] a2b_req_depth;
/* Req from bank_ctl */
input r2b_req, r2b_start, r2b_last,
r2b_write, r2b_wrap;
input [`SDR_REQ_ID_W-1:0] r2b_req_id;
input [1:0] r2b_ba;
input [12:0] r2b_raddr;
input [12:0] r2b_caddr;
input [`REQ_BW-1:0] r2b_len;
output b2r_arb_ok, b2r_ack;
input sdr_req_norm_dma_last;
/* Req to xfr_ctl */
output b2x_idle, b2x_req, b2x_start, b2x_last,
b2x_tras_ok, b2x_wrap;
output [`SDR_REQ_ID_W-1:0] b2x_id;
output [1:0] b2x_ba;
output [12:0] b2x_addr;
output [`REQ_BW-1:0] b2x_len;
output [1:0] b2x_cmd;
input x2b_ack;
/* Status from xfr_ctl */
input [3:0] x2b_pre_ok;
input x2b_refresh, x2b_act_ok, x2b_rdok,
x2b_wrok;
input [3:0] tras_delay, trp_delay, trcd_delay;
input [1:0] xfr_bank_sel;
/****************************************************************************/
// Internal Nets
wire [3:0] r2i_req, i2r_ack, i2x_req,
i2x_start, i2x_last, i2x_wrap, tras_ok;
wire [12:0] i2x_addr0, i2x_addr1, i2x_addr2, i2x_addr3;
wire [`REQ_BW-1:0] i2x_len0, i2x_len1, i2x_len2, i2x_len3;
wire [1:0] i2x_cmd0, i2x_cmd1, i2x_cmd2, i2x_cmd3;
wire [`SDR_REQ_ID_W-1:0] i2x_id0, i2x_id1, i2x_id2, i2x_id3;
reg b2x_req;
wire b2x_idle, b2x_start, b2x_last, b2x_wrap;
wire [`SDR_REQ_ID_W-1:0] b2x_id;
wire [12:0] b2x_addr;
wire [`REQ_BW-1:0] b2x_len;
wire [1:0] b2x_cmd;
wire [3:0] x2i_ack;
reg [1:0] b2x_ba;
reg [`SDR_REQ_ID_W-1:0] curr_id;
wire [1:0] xfr_ba;
wire xfr_ba_last;
wire [3:0] xfr_ok;
// This 8 bit register stores the bank addresses for upto 4 requests.
reg [7:0] rank_ba;
reg [3:0] rank_ba_last;
// This 3 bit counter counts the number of requests we have
// buffered so far, legal values are 0, 1, 2, 3, or 4.
reg [2:0] rank_cnt;
wire [3:0] rank_req, rank_wr_sel;
wire rank_fifo_wr, rank_fifo_rd;
wire rank_fifo_full, rank_fifo_mt;
wire [12:0] bank0_row, bank1_row, bank2_row, bank3_row;
assign b2x_tras_ok = &tras_ok;
// Distribute the request from req_gen
assign r2i_req[0] = (r2b_ba == 2'b00) ? r2b_req & ~rank_fifo_full : 1'b0;
assign r2i_req[1] = (r2b_ba == 2'b01) ? r2b_req & ~rank_fifo_full : 1'b0;
assign r2i_req[2] = (r2b_ba == 2'b10) ? r2b_req & ~rank_fifo_full : 1'b0;
assign r2i_req[3] = (r2b_ba == 2'b11) ? r2b_req & ~rank_fifo_full : 1'b0;
/******************
Modified the Better FPGA Timing Purpose
assign b2r_ack = (r2b_ba == 2'b00) ? i2r_ack[0] :
(r2b_ba == 2'b01) ? i2r_ack[1] :
(r2b_ba == 2'b10) ? i2r_ack[2] :
(r2b_ba == 2'b11) ? i2r_ack[3] : 1'b0;
********************/
// Assumption: Only one Ack Will be asserted at a time.
assign b2r_ack =|i2r_ack;
assign b2r_arb_ok = ~rank_fifo_full;
// Put the requests from the 4 bank_fsms into a 4 deep shift
// register file. The earliest request is prioritized over the
// later requests. Also the number of requests we are allowed to
// buffer is limited by a 2 bit external input
// Mux the req/cmd to xfr_ctl. Allow RD/WR commands from the request in
// rank0, allow only PR/ACT commands from the requests in other ranks
// If the rank_fifo is empty, send the request from the bank addressed by
// r2b_ba
// In FPGA Mode, to improve the timing, also send the rank_ba
assign xfr_ba = (`TARGET_DESIGN == `FPGA) ? rank_ba[1:0]:
((rank_fifo_mt) ? r2b_ba : rank_ba[1:0]);
assign xfr_ba_last = (`TARGET_DESIGN == `FPGA) ? rank_ba_last[0]:
((rank_fifo_mt) ? sdr_req_norm_dma_last : rank_ba_last[0]);
assign rank_req[0] = i2x_req[xfr_ba]; // each rank generates requests
assign rank_req[1] = (rank_cnt < 3'h2) ? 1'b0 :
(rank_ba[3:2] == 2'b00) ? i2x_req[0] & ~i2x_cmd0[1] :
(rank_ba[3:2] == 2'b01) ? i2x_req[1] & ~i2x_cmd1[1] :
(rank_ba[3:2] == 2'b10) ? i2x_req[2] & ~i2x_cmd2[1] :
i2x_req[3] & ~i2x_cmd3[1];
assign rank_req[2] = (rank_cnt < 3'h3) ? 1'b0 :
(rank_ba[5:4] == 2'b00) ? i2x_req[0] & ~i2x_cmd0[1] :
(rank_ba[5:4] == 2'b01) ? i2x_req[1] & ~i2x_cmd1[1] :
(rank_ba[5:4] == 2'b10) ? i2x_req[2] & ~i2x_cmd2[1] :
i2x_req[3] & ~i2x_cmd3[1];
assign rank_req[3] = (rank_cnt < 3'h4) ? 1'b0 :
(rank_ba[7:6] == 2'b00) ? i2x_req[0] & ~i2x_cmd0[1] :
(rank_ba[7:6] == 2'b01) ? i2x_req[1] & ~i2x_cmd1[1] :
(rank_ba[7:6] == 2'b10) ? i2x_req[2] & ~i2x_cmd2[1] :
i2x_req[3] & ~i2x_cmd3[1];
always @ (*) begin
b2x_req = 1'b0;
b2x_ba = xfr_ba;
if(`TARGET_DESIGN == `ASIC) begin // Support Multiple Rank request only on ASIC
if (rank_req[0]) begin
b2x_req = 1'b1;
b2x_ba = xfr_ba;
end // if (rank_req[0])
else if (rank_req[1]) begin
b2x_req = 1'b1;
b2x_ba = rank_ba[3:2];
end // if (rank_req[1])
else if (rank_req[2]) begin
b2x_req = 1'b1;
b2x_ba = rank_ba[5:4];
end // if (rank_req[2])
else if (rank_req[3]) begin
b2x_req = 1'b1;
b2x_ba = rank_ba[7:6];
end // if (rank_req[3])
end else begin // If FPGA
if (rank_req[0]) begin
b2x_req = 1'b1;
end
end
end // always @ (rank_req or rank_fifo_mt or r2b_ba or rank_ba)
assign b2x_idle = rank_fifo_mt;
assign b2x_start = i2x_start[b2x_ba];
assign b2x_last = i2x_last[b2x_ba];
assign b2x_wrap = i2x_wrap[b2x_ba];
assign b2x_addr = (b2x_ba == 2'b11) ? i2x_addr3 :
(b2x_ba == 2'b10) ? i2x_addr2 :
(b2x_ba == 2'b01) ? i2x_addr1 : i2x_addr0;
assign b2x_len = (b2x_ba == 2'b11) ? i2x_len3 :
(b2x_ba == 2'b10) ? i2x_len2 :
(b2x_ba == 2'b01) ? i2x_len1 : i2x_len0;
assign b2x_cmd = (b2x_ba == 2'b11) ? i2x_cmd3 :
(b2x_ba == 2'b10) ? i2x_cmd2 :
(b2x_ba == 2'b01) ? i2x_cmd1 : i2x_cmd0;
assign b2x_id = (b2x_ba == 2'b11) ? i2x_id3 :
(b2x_ba == 2'b10) ? i2x_id2 :
(b2x_ba == 2'b01) ? i2x_id1 : i2x_id0;
assign x2i_ack[0] = (b2x_ba == 2'b00) ? x2b_ack : 1'b0;
assign x2i_ack[1] = (b2x_ba == 2'b01) ? x2b_ack : 1'b0;
assign x2i_ack[2] = (b2x_ba == 2'b10) ? x2b_ack : 1'b0;
assign x2i_ack[3] = (b2x_ba == 2'b11) ? x2b_ack : 1'b0;
// Rank Fifo
// On a write write to selected rank and increment rank_cnt
// On a read shift rank_ba right 2 bits and decrement rank_cnt
assign rank_fifo_wr = b2r_ack;
assign rank_fifo_rd = b2x_req & b2x_cmd[1] & x2b_ack;
assign rank_wr_sel[0] = (rank_cnt == 3'h0) ? rank_fifo_wr :
(rank_cnt == 3'h1) ? rank_fifo_wr & rank_fifo_rd :
1'b0;
assign rank_wr_sel[1] = (rank_cnt == 3'h1) ? rank_fifo_wr & ~rank_fifo_rd :
(rank_cnt == 3'h2) ? rank_fifo_wr & rank_fifo_rd :
1'b0;
assign rank_wr_sel[2] = (rank_cnt == 3'h2) ? rank_fifo_wr & ~rank_fifo_rd :
(rank_cnt == 3'h3) ? rank_fifo_wr & rank_fifo_rd :
1'b0;
assign rank_wr_sel[3] = (rank_cnt == 3'h3) ? rank_fifo_wr & ~rank_fifo_rd :
(rank_cnt == 3'h4) ? rank_fifo_wr & rank_fifo_rd :
1'b0;
assign rank_fifo_mt = (rank_cnt == 3'b0) ? 1'b1 : 1'b0;
assign rank_fifo_full = (rank_cnt[2]) ? 1'b1 :
(rank_cnt[1:0] == a2b_req_depth) ? 1'b1 : 1'b0;
// FIFO Check
// synopsys translate_off
always @ (posedge clk) begin
if (~rank_fifo_wr & rank_fifo_rd && rank_cnt == 3'h0) begin
$display ("%t: %m: ERROR!!! Read from empty Fifo", $time);
$stop;
end // if (rank_fifo_rd && rank_cnt == 3'h0)
if (rank_fifo_wr && ~rank_fifo_rd && rank_cnt == 3'h4) begin
$display ("%t: %m: ERROR!!! Write to full Fifo", $time);
$stop;
end // if (rank_fifo_wr && ~rank_fifo_rd && rank_cnt == 3'h4)
end // always @ (posedge clk)
// synopsys translate_on
always @ (posedge clk)
if (~reset_n) begin
rank_cnt <= 3'b0;
rank_ba <= 8'b0;
rank_ba_last <= 4'b0;
end // if (~reset_n)
else begin
rank_cnt <= (rank_fifo_wr & ~rank_fifo_rd) ? rank_cnt + 3'b1 :
(~rank_fifo_wr & rank_fifo_rd) ? rank_cnt - 3'b1 :
rank_cnt;
rank_ba[1:0] <= (rank_wr_sel[0]) ? r2b_ba :
(rank_fifo_rd) ? rank_ba[3:2] : rank_ba[1:0];
rank_ba[3:2] <= (rank_wr_sel[1]) ? r2b_ba :
(rank_fifo_rd) ? rank_ba[5:4] : rank_ba[3:2];
rank_ba[5:4] <= (rank_wr_sel[2]) ? r2b_ba :
(rank_fifo_rd) ? rank_ba[7:6] : rank_ba[5:4];
rank_ba[7:6] <= (rank_wr_sel[3]) ? r2b_ba :
(rank_fifo_rd) ? 2'b00 : rank_ba[7:6];
if(`TARGET_DESIGN == `ASIC) begin // This Logic is implemented for ASIC Only
// Note: Currenly top-level does not generate the
// sdr_req_norm_dma_last signal and can be tied zero at top-level
rank_ba_last[0] <= (rank_wr_sel[0]) ? sdr_req_norm_dma_last :
(rank_fifo_rd) ? rank_ba_last[1] : rank_ba_last[0];
rank_ba_last[1] <= (rank_wr_sel[1]) ? sdr_req_norm_dma_last :
(rank_fifo_rd) ? rank_ba_last[2] : rank_ba_last[1];
rank_ba_last[2] <= (rank_wr_sel[2]) ? sdr_req_norm_dma_last :
(rank_fifo_rd) ? rank_ba_last[3] : rank_ba_last[2];
rank_ba_last[3] <= (rank_wr_sel[3]) ? sdr_req_norm_dma_last :
(rank_fifo_rd) ? 1'b0 : rank_ba_last[3];
end
end // else: !if(~reset_n)
assign xfr_ok[0] = (xfr_ba == 2'b00) ? 1'b1 : 1'b0;
assign xfr_ok[1] = (xfr_ba == 2'b01) ? 1'b1 : 1'b0;
assign xfr_ok[2] = (xfr_ba == 2'b10) ? 1'b1 : 1'b0;
assign xfr_ok[3] = (xfr_ba == 2'b11) ? 1'b1 : 1'b0;
/****************************************************************************/
// Instantiate Bank Ctl FSM 0
sdrc_bank_fsm bank0_fsm (.clk (clk),
.reset_n (reset_n),
/* Req from req_gen */
.r2b_req (r2i_req[0]),
.r2b_req_id (r2b_req_id),
.r2b_start (r2b_start),
.r2b_last (r2b_last),
.r2b_wrap (r2b_wrap),
.r2b_raddr (r2b_raddr),
.r2b_caddr (r2b_caddr),
.r2b_len (r2b_len),
.r2b_write (r2b_write),
.b2r_ack (i2r_ack[0]),
.sdr_dma_last(rank_ba_last[0]),
/* Transfer request to xfr_ctl */
.b2x_req (i2x_req[0]),
.b2x_start (i2x_start[0]),
.b2x_last (i2x_last[0]),
.b2x_wrap (i2x_wrap[0]),
.b2x_id (i2x_id0),
.b2x_addr (i2x_addr0),
.b2x_len (i2x_len0),
.b2x_cmd (i2x_cmd0),
.x2b_ack (x2i_ack[0]),
/* Status to/from xfr_ctl */
.tras_ok (tras_ok[0]),
.xfr_ok (xfr_ok[0]),
.x2b_refresh (x2b_refresh),
.x2b_pre_ok (x2b_pre_ok[0]),
.x2b_act_ok (x2b_act_ok),
.x2b_rdok (x2b_rdok),
.x2b_wrok (x2b_wrok),
.bank_row(bank0_row),
/* SDRAM Timing */
.tras_delay (tras_delay),
.trp_delay (trp_delay),
.trcd_delay (trcd_delay));
/****************************************************************************/
// Instantiate Bank Ctl FSM 1
sdrc_bank_fsm bank1_fsm (.clk (clk),
.reset_n (reset_n),
/* Req from req_gen */
.r2b_req (r2i_req[1]),
.r2b_req_id (r2b_req_id),
.r2b_start (r2b_start),
.r2b_last (r2b_last),
.r2b_wrap (r2b_wrap),
.r2b_raddr (r2b_raddr),
.r2b_caddr (r2b_caddr),
.r2b_len (r2b_len),
.r2b_write (r2b_write),
.b2r_ack (i2r_ack[1]),
.sdr_dma_last(rank_ba_last[1]),
/* Transfer request to xfr_ctl */
.b2x_req (i2x_req[1]),
.b2x_start (i2x_start[1]),
.b2x_last (i2x_last[1]),
.b2x_wrap (i2x_wrap[1]),
.b2x_id (i2x_id1),
.b2x_addr (i2x_addr1),
.b2x_len (i2x_len1),
.b2x_cmd (i2x_cmd1),
.x2b_ack (x2i_ack[1]),
/* Status to/from xfr_ctl */
.tras_ok (tras_ok[1]),
.xfr_ok (xfr_ok[1]),
.x2b_refresh (x2b_refresh),
.x2b_pre_ok (x2b_pre_ok[1]),
.x2b_act_ok (x2b_act_ok),
.x2b_rdok (x2b_rdok),
.x2b_wrok (x2b_wrok),
.bank_row(bank1_row),
/* SDRAM Timing */
.tras_delay (tras_delay),
.trp_delay (trp_delay),
.trcd_delay (trcd_delay));
/****************************************************************************/
// Instantiate Bank Ctl FSM 2
sdrc_bank_fsm bank2_fsm (.clk (clk),
.reset_n (reset_n),
/* Req from req_gen */
.r2b_req (r2i_req[2]),
.r2b_req_id (r2b_req_id),
.r2b_start (r2b_start),
.r2b_last (r2b_last),
.r2b_wrap (r2b_wrap),
.r2b_raddr (r2b_raddr),
.r2b_caddr (r2b_caddr),
.r2b_len (r2b_len),
.r2b_write (r2b_write),
.b2r_ack (i2r_ack[2]),
.sdr_dma_last(rank_ba_last[2]),
/* Transfer request to xfr_ctl */
.b2x_req (i2x_req[2]),
.b2x_start (i2x_start[2]),
.b2x_last (i2x_last[2]),
.b2x_wrap (i2x_wrap[2]),
.b2x_id (i2x_id2),
.b2x_addr (i2x_addr2),
.b2x_len (i2x_len2),
.b2x_cmd (i2x_cmd2),
.x2b_ack (x2i_ack[2]),
/* Status to/from xfr_ctl */
.tras_ok (tras_ok[2]),
.xfr_ok (xfr_ok[2]),
.x2b_refresh (x2b_refresh),
.x2b_pre_ok (x2b_pre_ok[2]),
.x2b_act_ok (x2b_act_ok),
.x2b_rdok (x2b_rdok),
.x2b_wrok (x2b_wrok),
.bank_row(bank2_row),
/* SDRAM Timing */
.tras_delay (tras_delay),
.trp_delay (trp_delay),
.trcd_delay (trcd_delay));
/****************************************************************************/
// Instantiate Bank Ctl FSM 3
sdrc_bank_fsm bank3_fsm (.clk (clk),
.reset_n (reset_n),
/* Req from req_gen */
.r2b_req (r2i_req[3]),
.r2b_req_id (r2b_req_id),
.r2b_start (r2b_start),
.r2b_last (r2b_last),
.r2b_wrap (r2b_wrap),
.r2b_raddr (r2b_raddr),
.r2b_caddr (r2b_caddr),
.r2b_len (r2b_len),
.r2b_write (r2b_write),
.b2r_ack (i2r_ack[3]),
.sdr_dma_last(rank_ba_last[3]),
/* Transfer request to xfr_ctl */
.b2x_req (i2x_req[3]),
.b2x_start (i2x_start[3]),
.b2x_last (i2x_last[3]),
.b2x_wrap (i2x_wrap[3]),
.b2x_id (i2x_id3),
.b2x_addr (i2x_addr3),
.b2x_len (i2x_len3),
.b2x_cmd (i2x_cmd3),
.x2b_ack (x2i_ack[3]),
/* Status to/from xfr_ctl */
.tras_ok (tras_ok[3]),
.xfr_ok (xfr_ok[3]),
.x2b_refresh (x2b_refresh),
.x2b_pre_ok (x2b_pre_ok[3]),
.x2b_act_ok (x2b_act_ok),
.x2b_rdok (x2b_rdok),
.x2b_wrok (x2b_wrok),
.bank_row(bank3_row),
/* SDRAM Timing */
.tras_delay (tras_delay),
.trp_delay (trp_delay),
.trcd_delay (trcd_delay));
/* address for current xfr, debug only */
wire [12:0] cur_row = (xfr_bank_sel==3) ? bank3_row:
(xfr_bank_sel==2) ? bank2_row:
(xfr_bank_sel==1) ? bank1_row: bank0_row;
endmodule // sdr_bank_ctl

View File

@ -0,0 +1,371 @@
/*********************************************************************
SDRAM Controller Bank Controller
This file is part of the sdram controller project
http://www.opencores.org/cores/sdr_ctrl/
Description:
This module takes requests from sdrc_req_gen, checks for page hit/miss and
issues precharge/activate commands and then passes the request to sdrc_xfr_ctl.
To Do:
nothing
Author(s):
- Dinesh Annayya, dinesha@opencores.org
Version : 1.0 - 8th Jan 2012
Copyright (C) 2000 Authors and OPENCORES.ORG
This source file may be used and distributed without
restriction provided that this copyright statement is not
removed from the file and that any derivative work contains
the original copyright notice and the associated disclaimer.
This source file is free software; you can redistribute it
and/or modify it under the terms of the GNU Lesser General
Public License as published by the Free Software Foundation;
either version 2.1 of the License, or (at your option) any
later version.
This source is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General
Public License along with this source; if not, download it
from http://www.opencores.org/lgpl.shtml
*******************************************************************/
`include "sdrc_define.v"
module sdrc_bank_fsm (clk,
reset_n,
/* Req from req_gen */
r2b_req, // request
r2b_req_id, // ID
r2b_start, // First chunk of burst
r2b_last, // Last chunk of burst
r2b_wrap,
r2b_raddr, // row address
r2b_caddr, // col address
r2b_len, // length
r2b_write, // write request
b2r_ack,
sdr_dma_last,
/* Transfer request to xfr_ctl */
b2x_req, // Request to xfr_ctl
b2x_start, // first chunk of transfer
b2x_last, // last chunk of transfer
b2x_wrap,
b2x_id, // Transfer ID
b2x_addr, // row/col address
b2x_len, // transfer length
b2x_cmd, // transfer command
x2b_ack, // command accepted
/* Status to/from xfr_ctl */
tras_ok, // TRAS OK for this bank
xfr_ok,
x2b_refresh, // We did a refresh
x2b_pre_ok, // OK to do a precharge (per bank)
x2b_act_ok, // OK to do an activate
x2b_rdok, // OK to do a read
x2b_wrok, // OK to do a write
/* current xfr row address of the bank */
bank_row,
/* SDRAM Timing */
tras_delay, // Active to precharge delay
trp_delay, // Precharge to active delay
trcd_delay); // Active to R/W delay
parameter SDR_DW = 16; // SDR Data Width
parameter SDR_BW = 2; // SDR Byte Width
input clk, reset_n;
/* Req from bank_ctl */
input r2b_req, r2b_start, r2b_last,
r2b_write, r2b_wrap;
input [`SDR_REQ_ID_W-1:0] r2b_req_id;
input [12:0] r2b_raddr;
input [12:0] r2b_caddr;
input [`REQ_BW-1:0] r2b_len;
output b2r_ack;
input sdr_dma_last;
/* Req to xfr_ctl */
output b2x_req, b2x_start, b2x_last,
tras_ok, b2x_wrap;
output [`SDR_REQ_ID_W-1:0] b2x_id;
output [12:0] b2x_addr;
output [`REQ_BW-1:0] b2x_len;
output [1:0] b2x_cmd;
input x2b_ack;
/* Status from xfr_ctl */
input x2b_refresh, x2b_act_ok, x2b_rdok,
x2b_wrok, x2b_pre_ok, xfr_ok;
input [3:0] tras_delay, trp_delay, trcd_delay;
output [12:0] bank_row;
/****************************************************************************/
// Internal Nets
`define BANK_IDLE 3'b000
`define BANK_PRE 3'b001
`define BANK_ACT 3'b010
`define BANK_XFR 3'b011
`define BANK_DMA_LAST_PRE 3'b100
reg [2:0] bank_st, next_bank_st;
wire b2x_start, b2x_last;
reg l_start, l_last;
reg b2x_req, b2r_ack;
wire [`SDR_REQ_ID_W-1:0] b2x_id;
reg [`SDR_REQ_ID_W-1:0] l_id;
reg [12:0] b2x_addr;
reg [`REQ_BW-1:0] l_len;
wire [`REQ_BW-1:0] b2x_len;
reg [1:0] b2x_cmd_t;
reg bank_valid;
reg [12:0] bank_row;
reg [3:0] tras_cntr, timer0;
reg l_wrap, l_write;
wire b2x_wrap;
reg [12:0] l_raddr;
reg [12:0] l_caddr;
reg l_sdr_dma_last;
reg bank_prech_page_closed;
wire tras_ok_internal, tras_ok, activate_bank;
wire page_hit, timer0_tc_t, ld_trp, ld_trcd;
/*** Timing Break Logic Added for FPGA - Start ****/
reg x2b_wrok_r, xfr_ok_r , x2b_rdok_r;
reg [1:0] b2x_cmd_r,timer0_tc_r,tras_ok_r,x2b_pre_ok_r,x2b_act_ok_r;
always @ (posedge clk)
if (~reset_n) begin
x2b_wrok_r <= 1'b0;
xfr_ok_r <= 1'b0;
x2b_rdok_r <= 1'b0;
b2x_cmd_r <= 2'b0;
timer0_tc_r <= 1'b0;
tras_ok_r <= 1'b0;
x2b_pre_ok_r <= 1'b0;
x2b_act_ok_r <= 1'b0;
end
else begin
x2b_wrok_r <= x2b_wrok;
xfr_ok_r <= xfr_ok;
x2b_rdok_r <= x2b_rdok;
b2x_cmd_r <= b2x_cmd_t;
timer0_tc_r <= (ld_trp | ld_trcd) ? 1'b0 : timer0_tc_t;
tras_ok_r <= tras_ok_internal;
x2b_pre_ok_r <= x2b_pre_ok;
x2b_act_ok_r <= x2b_act_ok;
end
wire x2b_wrok_t = (`TARGET_DESIGN == `FPGA) ? x2b_wrok_r : x2b_wrok;
wire xfr_ok_t = (`TARGET_DESIGN == `FPGA) ? xfr_ok_r : xfr_ok;
wire x2b_rdok_t = (`TARGET_DESIGN == `FPGA) ? x2b_rdok_r : x2b_rdok;
wire [1:0] b2x_cmd = (`TARGET_DESIGN == `FPGA) ? b2x_cmd_r : b2x_cmd_t;
wire timer0_tc = (`TARGET_DESIGN == `FPGA) ? timer0_tc_r : timer0_tc_t;
assign tras_ok = (`TARGET_DESIGN == `FPGA) ? tras_ok_r : tras_ok_internal;
wire x2b_pre_ok_t = (`TARGET_DESIGN == `FPGA) ? x2b_pre_ok_r : x2b_pre_ok;
wire x2b_act_ok_t = (`TARGET_DESIGN == `FPGA) ? x2b_act_ok_r : x2b_act_ok;
/*** Timing Break Logic Added for FPGA - End****/
always @ (posedge clk)
if (~reset_n) begin
bank_valid <= 1'b0;
tras_cntr <= 4'b0;
timer0 <= 4'b0;
bank_st <= `BANK_IDLE;
end // if (~reset_n)
else begin
bank_valid <= (x2b_refresh || bank_prech_page_closed) ? 1'b0 : // force the bank status to be invalid
(activate_bank) ? 1'b1 : bank_valid;
tras_cntr <= (activate_bank) ? tras_delay :
(~tras_ok_internal) ? tras_cntr - 4'b1 : 4'b0;
timer0 <= (ld_trp) ? trp_delay :
(ld_trcd) ? trcd_delay :
(timer0 != 'h0) ? timer0 - 4'b1 : timer0;
bank_st <= next_bank_st;
end // else: !if(~reset_n)
always @ (posedge clk) begin
bank_row <= (bank_st == `BANK_ACT) ? b2x_addr : bank_row;
if (~reset_n) begin
l_start <= 1'b0;
l_last <= 1'b0;
l_id <= 1'b0;
l_len <= 1'b0;
l_wrap <= 1'b0;
l_write <= 1'b0;
l_raddr <= 1'b0;
l_caddr <= 1'b0;
l_sdr_dma_last <= 1'b0;
end
else begin
if (b2r_ack) begin
l_start <= r2b_start;
l_last <= r2b_last;
l_id <= r2b_req_id;
l_len <= r2b_len;
l_wrap <= r2b_wrap;
l_write <= r2b_write;
l_raddr <= r2b_raddr;
l_caddr <= r2b_caddr;
l_sdr_dma_last <= sdr_dma_last;
end // if (b2r_ack)
end
end // always @ (posedge clk)
assign tras_ok_internal = ~|tras_cntr;
assign activate_bank = (b2x_cmd == `OP_ACT) & x2b_ack;
assign page_hit = (r2b_raddr == bank_row) ? bank_valid : 1'b0; // its a hit only if bank is valid
assign timer0_tc_t = ~|timer0;
assign ld_trp = (b2x_cmd == `OP_PRE) ? x2b_ack : 1'b0;
assign ld_trcd = (b2x_cmd == `OP_ACT) ? x2b_ack : 1'b0;
always @ (*) begin
bank_prech_page_closed = 1'b0;
b2x_req = 1'b0;
b2x_cmd_t = 2'bx;
b2r_ack = 1'b0;
b2x_addr = 13'bx;
next_bank_st = bank_st;
case (bank_st)
`BANK_IDLE : begin
if(`TARGET_DESIGN == `FPGA) begin // To break the timing, b2x request are generated delayed
if (~r2b_req) begin
next_bank_st = `BANK_IDLE;
end // if (~r2b_req)
else if (page_hit) begin
b2r_ack = 1'b1;
b2x_cmd_t = (r2b_write) ? `OP_WR : `OP_RD;
next_bank_st = `BANK_XFR;
end // if (page_hit)
else begin // page_miss
b2r_ack = 1'b1;
b2x_cmd_t = `OP_PRE;
next_bank_st = `BANK_PRE; // bank was precharged on l_sdr_dma_last
end // else: !if(page_hit)
end else begin // ASIC
if (~r2b_req) begin
bank_prech_page_closed = 1'b0;
b2x_req = 1'b0;
b2x_cmd_t = 2'bx;
b2r_ack = 1'b0;
b2x_addr = 13'bx;
next_bank_st = `BANK_IDLE;
end // if (~r2b_req)
else if (page_hit) begin
b2x_req = (r2b_write) ? x2b_wrok_t & xfr_ok_t :
x2b_rdok_t & xfr_ok_t;
b2x_cmd_t = (r2b_write) ? `OP_WR : `OP_RD;
b2r_ack = 1'b1;
b2x_addr = r2b_caddr;
next_bank_st = (x2b_ack) ? `BANK_IDLE : `BANK_XFR; // in case of hit, stay here till xfr sm acks
end // if (page_hit)
else begin // page_miss
b2x_req = tras_ok & x2b_pre_ok_t;
b2x_cmd_t = `OP_PRE;
b2r_ack = 1'b1;
b2x_addr = r2b_raddr & 13'hBFF; // Dont want to pre all banks!
next_bank_st = (l_sdr_dma_last) ? `BANK_PRE : (x2b_ack) ? `BANK_ACT : `BANK_PRE; // bank was precharged on l_sdr_dma_last
end // else: !if(page_hit)
end
end // case: `BANK_IDLE
`BANK_PRE : begin
b2x_req = tras_ok & x2b_pre_ok_t;
b2x_cmd_t = `OP_PRE;
b2r_ack = 1'b0;
b2x_addr = l_raddr & 13'hBFF; // Dont want to pre all banks!
bank_prech_page_closed = 1'b0;
next_bank_st = (x2b_ack) ? `BANK_ACT : `BANK_PRE;
end // case: `BANK_PRE
`BANK_ACT : begin
b2x_req = timer0_tc & x2b_act_ok_t;
b2x_cmd_t = `OP_ACT;
b2r_ack = 1'b0;
b2x_addr = l_raddr;
bank_prech_page_closed = 1'b0;
next_bank_st = (x2b_ack) ? `BANK_XFR : `BANK_ACT;
end // case: `BANK_ACT
`BANK_XFR : begin
b2x_req = (l_write) ? timer0_tc & x2b_wrok_t & xfr_ok_t :
timer0_tc & x2b_rdok_t & xfr_ok_t;
b2x_cmd_t = (l_write) ? `OP_WR : `OP_RD;
b2r_ack = 1'b0;
b2x_addr = l_caddr;
bank_prech_page_closed = 1'b0;
next_bank_st = (x2b_refresh) ? `BANK_ACT :
(x2b_ack & l_sdr_dma_last) ? `BANK_DMA_LAST_PRE :
(x2b_ack) ? `BANK_IDLE : `BANK_XFR;
end // case: `BANK_XFR
`BANK_DMA_LAST_PRE : begin
b2x_req = tras_ok & x2b_pre_ok_t;
b2x_cmd_t = `OP_PRE;
b2r_ack = 1'b0;
b2x_addr = l_raddr & 13'hBFF; // Dont want to pre all banks!
bank_prech_page_closed = 1'b1;
next_bank_st = (x2b_ack) ? `BANK_IDLE : `BANK_DMA_LAST_PRE;
end // case: `BANK_DMA_LAST_PRE
endcase // case(bank_st)
end // always @ (bank_st or ...)
assign b2x_start = (bank_st == `BANK_IDLE) ? r2b_start : l_start;
assign b2x_last = (bank_st == `BANK_IDLE) ? r2b_last : l_last;
assign b2x_id = (bank_st == `BANK_IDLE) ? r2b_req_id : l_id;
assign b2x_len = (bank_st == `BANK_IDLE) ? r2b_len : l_len;
assign b2x_wrap = (bank_st == `BANK_IDLE) ? r2b_wrap : l_wrap;
endmodule // sdr_bank_fsm

View File

@ -0,0 +1,228 @@
/*********************************************************************
SDRAM Controller buswidth converter
This file is part of the sdram controller project
http://www.opencores.org/cores/sdr_ctrl/
Description: SDRAM Controller Buswidth converter
This module does write/read data transalation between
application data to SDRAM bus width
To Do:
nothing
Author(s):
- Dinesh Annayya, dinesha@opencores.org
Version : 0.0 - 8th Jan 2012 - Initial structure
0.2 - 2nd Feb 2012
Improved the command pipe structure to accept up-to 4 command of different bank.
0.3 - 6th Feb 2012
Bug fix on read valid generation
Copyright (C) 2000 Authors and OPENCORES.ORG
This source file may be used and distributed without
restriction provided that this copyright statement is not
removed from the file and that any derivative work contains
the original copyright notice and the associated disclaimer.
This source file is free software; you can redistribute it
and/or modify it under the terms of the GNU Lesser General
Public License as published by the Free Software Foundation;
either version 2.1 of the License, or (at your option) any
later version.
This source is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General
Public License along with this source; if not, download it
from http://www.opencores.org/lgpl.shtml
*******************************************************************/
`include "sdrc_define.v"
module sdrc_bs_convert (
clk ,
reset_n ,
sdr_width ,
/* Control Signal from xfr ctrl */
x2a_rdstart ,
x2a_wrstart ,
x2a_rdlast ,
x2a_wrlast ,
x2a_rddt ,
x2a_rdok ,
a2x_wrdt ,
a2x_wren_n ,
x2a_wrnext ,
/* Control Signal from/to to application i/f */
app_wr_data ,
app_wr_en_n ,
app_wr_next ,
app_last_wr ,
app_rd_data ,
app_rd_valid ,
app_last_rd
);
parameter APP_AW = 30; // Application Address Width
parameter APP_DW = 32; // Application Data Width
parameter APP_BW = 4; // Application Byte Width
parameter SDR_DW = 16; // SDR Data Width
parameter SDR_BW = 2; // SDR Byte Width
input clk ;
input reset_n ;
input [1:0] sdr_width ; // 2'b00 - 32 Bit SDR, 2'b01 - 16 Bit SDR, 2'b1x - 8 Bit
/* Control Signal from xfr ctrl Read Transaction*/
input x2a_rdstart ; // read start indication
input x2a_rdlast ; // read last burst access
input [SDR_DW-1:0] x2a_rddt ;
input x2a_rdok ;
/* Control Signal from xfr ctrl Write Transaction*/
input x2a_wrstart ; // writ start indication
input x2a_wrlast ; // write last transfer
input x2a_wrnext ;
output [SDR_DW-1:0] a2x_wrdt ;
output [SDR_BW-1:0] a2x_wren_n ;
// Application Write Transaction
input [APP_DW-1:0] app_wr_data ;
input [APP_BW-1:0] app_wr_en_n ;
output app_wr_next ;
output app_last_wr ; // Indicate last Write Transfer for a given burst size
// Application Read Transaction
output [APP_DW-1:0] app_rd_data ;
output app_rd_valid ;
output app_last_rd ; // Indicate last Read Transfer for a given burst size
//----------------------------------------------
// Local Decleration
// ----------------------------------------
reg [APP_DW-1:0] app_rd_data ;
reg app_rd_valid ;
reg [SDR_DW-1:0] a2x_wrdt ;
reg [SDR_BW-1:0] a2x_wren_n ;
reg app_wr_next ;
reg [23:0] saved_rd_data ;
reg [1:0] rd_xfr_count ;
reg [1:0] wr_xfr_count ;
assign app_last_wr = x2a_wrlast;
assign app_last_rd = x2a_rdlast;
always @(*) begin
if(sdr_width == 2'b00) // 32 Bit SDR Mode
begin
a2x_wrdt = app_wr_data;
a2x_wren_n = app_wr_en_n;
app_wr_next = x2a_wrnext;
app_rd_data = x2a_rddt;
app_rd_valid = x2a_rdok;
end
else if(sdr_width == 2'b01) // 16 Bit SDR Mode
begin
// Changed the address and length to match the 16 bit SDR Mode
app_wr_next = (x2a_wrnext & wr_xfr_count[0]);
app_rd_valid = (x2a_rdok & rd_xfr_count[0]);
if(wr_xfr_count[0] == 1'b1)
begin
a2x_wren_n = app_wr_en_n[3:2];
a2x_wrdt = app_wr_data[31:16];
end
else
begin
a2x_wren_n = app_wr_en_n[1:0];
a2x_wrdt = app_wr_data[15:0];
end
app_rd_data = {x2a_rddt,saved_rd_data[15:0]};
end else // 8 Bit SDR Mode
begin
// Changed the address and length to match the 16 bit SDR Mode
app_wr_next = (x2a_wrnext & (wr_xfr_count[1:0]== 2'b11));
app_rd_valid = (x2a_rdok & (rd_xfr_count[1:0]== 2'b11));
if(wr_xfr_count[1:0] == 2'b11)
begin
a2x_wren_n = app_wr_en_n[3];
a2x_wrdt = app_wr_data[31:24];
end
else if(wr_xfr_count[1:0] == 2'b10)
begin
a2x_wren_n = app_wr_en_n[2];
a2x_wrdt = app_wr_data[23:16];
end
else if(wr_xfr_count[1:0] == 2'b01)
begin
a2x_wren_n = app_wr_en_n[1];
a2x_wrdt = app_wr_data[15:8];
end
else begin
a2x_wren_n = app_wr_en_n[0];
a2x_wrdt = app_wr_data[7:0];
end
app_rd_data = {x2a_rddt,saved_rd_data[23:0]};
end
end
always @(posedge clk)
begin
if(!reset_n)
begin
rd_xfr_count <= 8'b0;
wr_xfr_count <= 8'b0;
saved_rd_data <= 24'h0;
end
else begin
// During Write Phase
if(x2a_wrlast) begin
wr_xfr_count <= 0;
end
else if(x2a_wrnext) begin
wr_xfr_count <= wr_xfr_count + 1'b1;
end
// During Read Phase
if(x2a_rdlast) begin
rd_xfr_count <= 0;
end
else if(x2a_rdok) begin
rd_xfr_count <= rd_xfr_count + 1'b1;
end
// Save Previous Data
if(x2a_rdok) begin
if(sdr_width == 2'b01) // 16 Bit SDR Mode
saved_rd_data[15:0] <= x2a_rddt;
else begin// 8 bit SDR Mode -
if(rd_xfr_count[1:0] == 2'b00) saved_rd_data[7:0] <= x2a_rddt[7:0];
else if(rd_xfr_count[1:0] == 2'b01) saved_rd_data[15:8] <= x2a_rddt[7:0];
else if(rd_xfr_count[1:0] == 2'b10) saved_rd_data[23:16] <= x2a_rddt[7:0];
end
end
end
end
endmodule // sdr_bs_convert

View File

@ -0,0 +1,477 @@
/*********************************************************************
SDRAM Controller Core File
This file is part of the sdram controller project
http://www.opencores.org/cores/sdr_ctrl/
Description: SDRAM Controller Core Module
2 types of SDRAMs are supported, 1Mx16 2 bank, or 4Mx16 4 bank.
This block integrate following sub modules
sdrc_bs_convert
convert the system side 32 bit into equvailent 8/16/32 SDR format
sdrc_req_gen
This module takes requests from the app, chops them to burst booundaries
if wrap=0, decodes the bank and passe the request to bank_ctl
sdrc_xfr_ctl
This module takes requests from sdr_bank_ctl, runs the transfer and
controls data flow to/from the app. At the end of the transfer it issues a
burst terminate if not at the end of a burst and another command to this
bank is not available.
sdrc_bank_ctl
This module takes requests from sdr_req_gen, checks for page hit/miss and
issues precharge/activate commands and then passes the request to
sdr_xfr_ctl.
Assumption: SDRAM Pads should be placed near to this module. else
user should add a FF near the pads
To Do:
nothing
Author(s):
- Dinesh Annayya, dinesha@opencores.org
Version : 0.0 - 8th Jan 2012
Initial version with 16/32 Bit SDRAM Support
: 0.1 - 24th Jan 2012
8 Bit SDRAM Support is added
0.2 - 2nd Feb 2012
Improved the command pipe structure to accept up-to
4 command of different bank.
0.3 - 7th Feb 2012
Bug fix for parameter defination for request length has changed from 9 to 12
0.4 - 26th April 2013
SDRAM Address Bit is Extended by 12 bit to 13 bit to support higher SDRAM
Copyright (C) 2000 Authors and OPENCORES.ORG
This source file may be used and distributed without
restriction provided that this copyright statement is not
removed from the file and that any derivative work contains
the original copyright notice and the associated disclaimer.
This source file is free software; you can redistribute it
and/or modify it under the terms of the GNU Lesser General
Public License as published by the Free Software Foundation;
either version 2.1 of the License, or (at your option) any
later version.
This source is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General
Public License along with this source; if not, download it
from http://www.opencores.org/lgpl.shtml
*******************************************************************/
`include "sdrc_define.v"
module sdrc_core
(
clk,
pad_clk,
reset_n,
sdr_width,
cfg_colbits,
/* Request from app */
app_req, // Transfer Request
app_req_addr, // SDRAM Address
app_req_len, // Burst Length (in 16 bit words)
app_req_wrap, // Wrap mode request (xfr_len = 4)
app_req_wr_n, // 0 => Write request, 1 => read req
app_req_ack, // Request has been accepted
cfg_req_depth, //how many req. buffer should hold
app_wr_data,
app_wr_en_n,
app_last_wr,
app_rd_data,
app_rd_valid,
app_last_rd,
app_wr_next_req,
sdr_init_done,
app_req_dma_last,
/* Interface to SDRAMs */
sdr_cs_n,
sdr_cke,
sdr_ras_n,
sdr_cas_n,
sdr_we_n,
sdr_dqm,
sdr_ba,
sdr_addr,
pad_sdr_din,
sdr_dout,
sdr_den_n,
/* Parameters */
cfg_sdr_en,
cfg_sdr_mode_reg,
cfg_sdr_tras_d,
cfg_sdr_trp_d,
cfg_sdr_trcd_d,
cfg_sdr_cas,
cfg_sdr_trcar_d,
cfg_sdr_twr_d,
cfg_sdr_rfsh,
cfg_sdr_rfmax);
parameter APP_AW = 26; // Application Address Width
parameter APP_DW = 32; // Application Data Width
parameter APP_BW = 4; // Application Byte Width
parameter APP_RW = 9; // Application Request Width
parameter SDR_DW = 16; // SDR Data Width
parameter SDR_BW = 2; // SDR Byte Width
//-----------------------------------------------
// Global Variable
// ----------------------------------------------
input clk ; // SDRAM Clock
input pad_clk ; // SDRAM Clock from Pad, used for registering Read Data
input reset_n ; // Reset Signal
input [1:0] sdr_width ; // 2'b00 - 32 Bit SDR, 2'b01 - 16 Bit SDR, 2'b1x - 8 Bit
input [1:0] cfg_colbits ; // 2'b00 - 8 Bit column address, 2'b01 - 9 Bit, 10 - 10 bit, 11 - 11Bits
//------------------------------------------------
// Request from app
//------------------------------------------------
input app_req ; // Application Request
input [APP_AW-1:0] app_req_addr ; // Address
input app_req_wr_n ; // 0 - Write, 1 - Read
input app_req_wrap ; // Address Wrap
output app_req_ack ; // Application Request Ack
input [APP_DW-1:0] app_wr_data ; // Write Data
output app_wr_next_req ; // Next Write Data Request
input [APP_BW-1:0] app_wr_en_n ; // Byte wise Write Enable
output app_last_wr ; // Last Write trannsfer of a given Burst
output [APP_DW-1:0] app_rd_data ; // Read Data
output app_rd_valid ; // Read Valid
output app_last_rd ; // Last Read Transfer of a given Burst
//------------------------------------------------
// Interface to SDRAMs
//------------------------------------------------
output sdr_cke ; // SDRAM CKE
output sdr_cs_n ; // SDRAM Chip Select
output sdr_ras_n ; // SDRAM ras
output sdr_cas_n ; // SDRAM cas
output sdr_we_n ; // SDRAM write enable
output [SDR_BW-1:0] sdr_dqm ; // SDRAM Data Mask
output [1:0] sdr_ba ; // SDRAM Bank Enable
output [12:0] sdr_addr ; // SDRAM Address
input [SDR_DW-1:0] pad_sdr_din ; // SDRA Data Input
output [SDR_DW-1:0] sdr_dout ; // SDRAM Data Output
output [SDR_BW-1:0] sdr_den_n ; // SDRAM Data Output enable
//------------------------------------------------
// Configuration Parameter
//------------------------------------------------
output sdr_init_done ; // Indicate SDRAM Initialisation Done
input [3:0] cfg_sdr_tras_d ; // Active to precharge delay
input [3:0] cfg_sdr_trp_d ; // Precharge to active delay
input [3:0] cfg_sdr_trcd_d ; // Active to R/W delay
input cfg_sdr_en ; // Enable SDRAM controller
input [1:0] cfg_req_depth ; // Maximum Request accepted by SDRAM controller
input [APP_RW-1:0] app_req_len ; // Application Burst Request length in 32 bit
input [12:0] cfg_sdr_mode_reg ;
input [2:0] cfg_sdr_cas ; // SDRAM CAS Latency
input [3:0] cfg_sdr_trcar_d ; // Auto-refresh period
input [3:0] cfg_sdr_twr_d ; // Write recovery delay
input [`SDR_RFSH_TIMER_W-1 : 0] cfg_sdr_rfsh;
input [`SDR_RFSH_ROW_CNT_W -1 : 0] cfg_sdr_rfmax;
input app_req_dma_last; // this signal should close the bank
/****************************************************************************/
// Internal Nets
// SDR_REQ_GEN
wire [`SDR_REQ_ID_W-1:0]r2b_req_id;
wire [1:0] r2b_ba;
wire [12:0] r2b_raddr;
wire [12:0] r2b_caddr;
wire [`REQ_BW-1:0] r2b_len;
// SDR BANK CTL
wire [`SDR_REQ_ID_W-1:0]b2x_id;
wire [1:0] b2x_ba;
wire [12:0] b2x_addr;
wire [`REQ_BW-1:0] b2x_len;
wire [1:0] b2x_cmd;
// SDR_XFR_CTL
wire [3:0] x2b_pre_ok;
wire [`SDR_REQ_ID_W-1:0]xfr_id;
wire [APP_DW-1:0] app_rd_data;
wire sdr_cs_n, sdr_cke, sdr_ras_n, sdr_cas_n, sdr_we_n;
wire [SDR_BW-1:0] sdr_dqm;
wire [1:0] sdr_ba;
wire [12:0] sdr_addr;
wire [SDR_DW-1:0] sdr_dout;
wire [SDR_DW-1:0] sdr_dout_int;
wire [SDR_BW-1:0] sdr_den_n;
wire [SDR_BW-1:0] sdr_den_n_int;
wire [1:0] xfr_bank_sel;
wire [APP_AW-1:0] app_req_addr;
wire [APP_RW-1:0] app_req_len;
wire [APP_DW-1:0] app_wr_data;
wire [SDR_DW-1:0] a2x_wrdt ;
wire [APP_BW-1:0] app_wr_en_n;
wire [SDR_BW-1:0] a2x_wren_n;
//wire [31:0] app_rd_data;
wire [SDR_DW-1:0] x2a_rddt;
// synopsys translate_off
wire [3:0] sdr_cmd;
assign sdr_cmd = {sdr_cs_n, sdr_ras_n, sdr_cas_n, sdr_we_n};
// synopsys translate_on
assign sdr_den_n = sdr_den_n_int ;
assign sdr_dout = sdr_dout_int ;
// To meet the timing at read path, read data is registered w.r.t pad_sdram_clock and register back to sdram_clk
// assumption, pad_sdram_clk is synhronous and delayed clock of sdram_clk.
// register w.r.t pad sdram clk
reg [SDR_DW-1:0] pad_sdr_din1;
reg [SDR_DW-1:0] pad_sdr_din2;
always@(posedge pad_clk) begin
pad_sdr_din1 <= pad_sdr_din;
end
always@(posedge clk) begin
pad_sdr_din2 <= pad_sdr_din1;
end
/****************************************************************************/
// Instantiate sdr_req_gen
// This module takes requests from the app, chops them to burst booundaries
// if wrap=0, decodes the bank and passe the request to bank_ctl
sdrc_req_gen #(.SDR_DW(SDR_DW) , .SDR_BW(SDR_BW)) u_req_gen (
.clk (clk ),
.reset_n (reset_n ),
.cfg_colbits (cfg_colbits ),
.sdr_width (sdr_width ),
/* Req to xfr_ctl */
.r2x_idle (r2x_idle ),
/* Request from app */
.req (app_req ),
.req_id (4'b0 ),
.req_addr (app_req_addr ),
.req_len (app_req_len ),
.req_wrap (app_req_wrap ),
.req_wr_n (app_req_wr_n ),
.req_ack (app_req_ack ),
/* Req to bank_ctl */
.r2b_req (r2b_req ),
.r2b_req_id (r2b_req_id ),
.r2b_start (r2b_start ),
.r2b_last (r2b_last ),
.r2b_wrap (r2b_wrap ),
.r2b_ba (r2b_ba ),
.r2b_raddr (r2b_raddr ),
.r2b_caddr (r2b_caddr ),
.r2b_len (r2b_len ),
.r2b_write (r2b_write ),
.b2r_ack (b2r_ack ),
.b2r_arb_ok (b2r_arb_ok )
);
/****************************************************************************/
// Instantiate sdr_bank_ctl
// This module takes requests from sdr_req_gen, checks for page hit/miss and
// issues precharge/activate commands and then passes the request to
// sdr_xfr_ctl.
sdrc_bank_ctl #(.SDR_DW(SDR_DW) , .SDR_BW(SDR_BW)) u_bank_ctl (
.clk (clk ),
.reset_n (reset_n ),
.a2b_req_depth (cfg_req_depth ),
/* Req from req_gen */
.r2b_req (r2b_req ),
.r2b_req_id (r2b_req_id ),
.r2b_start (r2b_start ),
.r2b_last (r2b_last ),
.r2b_wrap (r2b_wrap ),
.r2b_ba (r2b_ba ),
.r2b_raddr (r2b_raddr ),
.r2b_caddr (r2b_caddr ),
.r2b_len (r2b_len ),
.r2b_write (r2b_write ),
.b2r_arb_ok (b2r_arb_ok ),
.b2r_ack (b2r_ack ),
/* Transfer request to xfr_ctl */
.b2x_idle (b2x_idle ),
.b2x_req (b2x_req ),
.b2x_start (b2x_start ),
.b2x_last (b2x_last ),
.b2x_wrap (b2x_wrap ),
.b2x_id (b2x_id ),
.b2x_ba (b2x_ba ),
.b2x_addr (b2x_addr ),
.b2x_len (b2x_len ),
.b2x_cmd (b2x_cmd ),
.x2b_ack (x2b_ack ),
/* Status from xfr_ctl */
.b2x_tras_ok (b2x_tras_ok ),
.x2b_refresh (x2b_refresh ),
.x2b_pre_ok (x2b_pre_ok ),
.x2b_act_ok (x2b_act_ok ),
.x2b_rdok (x2b_rdok ),
.x2b_wrok (x2b_wrok ),
/* for generate cuurent xfr address msb */
.sdr_req_norm_dma_last(app_req_dma_last),
.xfr_bank_sel (xfr_bank_sel ),
/* SDRAM Timing */
.tras_delay (cfg_sdr_tras_d ),
.trp_delay (cfg_sdr_trp_d ),
.trcd_delay (cfg_sdr_trcd_d )
);
/****************************************************************************/
// Instantiate sdr_xfr_ctl
// This module takes requests from sdr_bank_ctl, runs the transfer and
// controls data flow to/from the app. At the end of the transfer it issues a
// burst terminate if not at the end of a burst and another command to this
// bank is not available.
sdrc_xfr_ctl #(.SDR_DW(SDR_DW) , .SDR_BW(SDR_BW)) u_xfr_ctl (
.clk (clk ),
.reset_n (reset_n ),
/* Transfer request from bank_ctl */
.r2x_idle (r2x_idle ),
.b2x_idle (b2x_idle ),
.b2x_req (b2x_req ),
.b2x_start (b2x_start ),
.b2x_last (b2x_last ),
.b2x_wrap (b2x_wrap ),
.b2x_id (b2x_id ),
.b2x_ba (b2x_ba ),
.b2x_addr (b2x_addr ),
.b2x_len (b2x_len ),
.b2x_cmd (b2x_cmd ),
.x2b_ack (x2b_ack ),
/* Status to bank_ctl, req_gen */
.b2x_tras_ok (b2x_tras_ok ),
.x2b_refresh (x2b_refresh ),
.x2b_pre_ok (x2b_pre_ok ),
.x2b_act_ok (x2b_act_ok ),
.x2b_rdok (x2b_rdok ),
.x2b_wrok (x2b_wrok ),
/* SDRAM I/O */
.sdr_cs_n (sdr_cs_n ),
.sdr_cke (sdr_cke ),
.sdr_ras_n (sdr_ras_n ),
.sdr_cas_n (sdr_cas_n ),
.sdr_we_n (sdr_we_n ),
.sdr_dqm (sdr_dqm ),
.sdr_ba (sdr_ba ),
.sdr_addr (sdr_addr ),
.sdr_din (pad_sdr_din2 ),
.sdr_dout (sdr_dout_int ),
.sdr_den_n (sdr_den_n_int ),
/* Data Flow to the app */
.x2a_rdstart (x2a_rdstart ),
.x2a_wrstart (x2a_wrstart ),
.x2a_id (xfr_id ),
.x2a_rdlast (x2a_rdlast ),
.x2a_wrlast (x2a_wrlast ),
.a2x_wrdt (a2x_wrdt ),
.a2x_wren_n (a2x_wren_n ),
.x2a_wrnext (x2a_wrnext ),
.x2a_rddt (x2a_rddt ),
.x2a_rdok (x2a_rdok ),
.sdr_init_done (sdr_init_done ),
/* SDRAM Parameters */
.sdram_enable (cfg_sdr_en ),
.sdram_mode_reg (cfg_sdr_mode_reg ),
/* current xfr bank */
.xfr_bank_sel (xfr_bank_sel ),
/* SDRAM Timing */
.cas_latency (cfg_sdr_cas ),
.trp_delay (cfg_sdr_trp_d ),
.trcar_delay (cfg_sdr_trcar_d ),
.twr_delay (cfg_sdr_twr_d ),
.rfsh_time (cfg_sdr_rfsh ),
.rfsh_rmax (cfg_sdr_rfmax )
);
/****************************************************************************/
// Instantiate sdr_bs_convert
// This model handle the bus with transaltion from application layer to
// 8/16/32 SDRAM Memory format
// During Write Phase, this block split the data as per SDRAM Width
// During Read Phase, This block does the re-packing based on SDRAM
// Width
//---------------------------------------------------------------------------
sdrc_bs_convert #(.SDR_DW(SDR_DW) , .SDR_BW(SDR_BW)) u_bs_convert (
.clk (clk ),
.reset_n (reset_n ),
.sdr_width (sdr_width ),
/* Control Signal from xfr ctrl */
// Read Interface Inputs
.x2a_rdstart (x2a_rdstart ),
.x2a_rdlast (x2a_rdlast ),
.x2a_rdok (x2a_rdok ),
// Read Interface outputs
.x2a_rddt (x2a_rddt ),
// Write Interface, Inputs
.x2a_wrstart (x2a_wrstart ),
.x2a_wrlast (x2a_wrlast ),
.x2a_wrnext (x2a_wrnext ),
// Write Interface, Outputs
.a2x_wrdt (a2x_wrdt ),
.a2x_wren_n (a2x_wren_n ),
/* Control Signal from sdrc_bank_ctl */
/* Control Signal from/to to application i/f */
.app_wr_data (app_wr_data ),
.app_wr_en_n (app_wr_en_n ),
.app_wr_next (app_wr_next_req ),
.app_last_wr (app_last_wr ),
.app_rd_data (app_rd_data ),
.app_rd_valid (app_rd_valid ),
.app_last_rd (app_last_rd )
);
endmodule // sdrc_core

View File

@ -0,0 +1,31 @@
`define SDR_REQ_ID_W 4
`define SDR_RFSH_TIMER_W 12
`define SDR_RFSH_ROW_CNT_W 3
// B2X Command
`define OP_PRE 2'b00
`define OP_ACT 2'b01
`define OP_RD 2'b10
`define OP_WR 2'b11
// SDRAM Commands (CS_N, RAS_N, CAS_N, WE_N)
`define SDR_DESEL 4'b1111
`define SDR_NOOP 4'b0111
`define SDR_ACTIVATE 4'b0011
`define SDR_READ 4'b0101
`define SDR_WRITE 4'b0100
`define SDR_BT 4'b0110
`define SDR_PRECHARGE 4'b0010
`define SDR_REFRESH 4'b0001
`define SDR_MODE 4'b0000
`define ASIC 1'b1
`define FPGA 1'b0
`define TARGET_DESIGN `FPGA
// 12 bit subtractor is not feasibile for FPGA, so changed to 6 bits
`define REQ_BW (`TARGET_DESIGN == `FPGA) ? 6 : 12 // Request Width

View File

@ -0,0 +1,340 @@
/*********************************************************************
SDRAM Controller Request Generation
This file is part of the sdram controller project
http://www.opencores.org/cores/sdr_ctrl/
Description: SDRAM Controller Reguest Generation
Address Generation Based on cfg_colbits
cfg_colbits= 2'b00
Address[7:0] - Column Address
Address[9:8] - Bank Address
Address[22:10] - Row Address
cfg_colbits= 2'b01
Address[8:0] - Column Address
Address[10:9] - Bank Address
Address[23:11] - Row Address
cfg_colbits= 2'b10
Address[9:0] - Column Address
Address[11:10] - Bank Address
Address[24:12] - Row Address
cfg_colbits= 2'b11
Address[10:0] - Column Address
Address[12:11] - Bank Address
Address[25:13] - Row Address
The SDRAMs are operated in 4 beat burst mode.
If Wrap = 0;
If the current burst cross the page boundary, then this block split the request
into two coressponding change in address and request length
if the current burst cross the page boundar.
This module takes requests from the memory controller,
chops them to page boundaries if wrap=0,
and passes the request to bank_ctl
Note: With Wrap = 0, each request from Application layer will be splited into two request,
if the current burst cross the page boundary.
To Do:
nothing
Author(s):
- Dinesh Annayya, dinesha@opencores.org
Version : 0.0 - 8th Jan 2012
0.1 - 5th Feb 2012, column/row/bank address are register to improve the timing issue in FPGA synthesis
Copyright (C) 2000 Authors and OPENCORES.ORG
This source file may be used and distributed without
restriction provided that this copyright statement is not
removed from the file and that any derivative work contains
the original copyright notice and the associated disclaimer.
This source file is free software; you can redistribute it
and/or modify it under the terms of the GNU Lesser General
Public License as published by the Free Software Foundation;
either version 2.1 of the License, or (at your option) any
later version.
This source is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General
Public License along with this source; if not, download it
from http://www.opencores.org/lgpl.shtml
*******************************************************************/
`include "sdrc_define.v"
module sdrc_req_gen (clk,
reset_n,
cfg_colbits,
sdr_width,
/* Request from app */
req, // Transfer Request
req_id, // ID for this transfer
req_addr, // SDRAM Address
req_len, // Burst Length (in 32 bit words)
req_wrap, // Wrap mode request (xfr_len = 4)
req_wr_n, // 0 => Write request, 1 => read req
req_ack, // Request has been accepted
/* Req to xfr_ctl */
r2x_idle,
/* Req to bank_ctl */
r2b_req, // request
r2b_req_id, // ID
r2b_start, // First chunk of burst
r2b_last, // Last chunk of burst
r2b_wrap, // Wrap Mode
r2b_ba, // bank address
r2b_raddr, // row address
r2b_caddr, // col address
r2b_len, // length
r2b_write, // write request
b2r_ack,
b2r_arb_ok
);
parameter APP_AW = 26; // Application Address Width
parameter APP_DW = 32; // Application Data Width
parameter APP_BW = 4; // Application Byte Width
parameter APP_RW = 9; // Application Request Width
parameter SDR_DW = 16; // SDR Data Width
parameter SDR_BW = 2; // SDR Byte Width
input clk ;
input reset_n ;
input [1:0] cfg_colbits ; // 2'b00 - 8 Bit column address, 2'b01 - 9 Bit, 10 - 10 bit, 11 - 11Bits
/* Request from app */
input req ; // Request
input [`SDR_REQ_ID_W-1:0] req_id ; // Request ID
input [APP_AW-1:0] req_addr ; // Request Address
input [APP_RW-1:0] req_len ; // Request length
input req_wr_n ; // 0 -Write, 1 - Read
input req_wrap ; // 1 - Wrap the Address on page boundary
output req_ack ; // Request Ack
/* Req to bank_ctl */
output r2x_idle ;
output r2b_req ; // Request
output r2b_start ; // First Junk of the Burst Access
output r2b_last ; // Last Junk of the Burst Access
output r2b_write ; // 1 - Write, 0 - Read
output r2b_wrap ; // 1 - Wrap the Address at the page boundary.
output [`SDR_REQ_ID_W-1:0] r2b_req_id;
output [1:0] r2b_ba ; // Bank Address
output [12:0] r2b_raddr ; // Row Address
output [12:0] r2b_caddr ; // Column Address
output [`REQ_BW-1:0] r2b_len ; // Burst Length
input b2r_ack ; // Request Ack
input b2r_arb_ok ; // Bank controller fifo is not full and ready to accept the command
//
input [1:0] sdr_width; // 2'b00 - 32 Bit, 2'b01 - 16 Bit, 2'b1x - 8Bit
/****************************************************************************/
// Internal Nets
`define REQ_IDLE 2'b00
`define REQ_ACTIVE 2'b01
`define REQ_PAGE_WRAP 2'b10
reg [1:0] req_st, next_req_st;
reg r2x_idle, req_ack, r2b_req, r2b_start,
r2b_write, req_idle, req_ld, lcl_wrap;
reg [`SDR_REQ_ID_W-1:0] r2b_req_id;
reg [`REQ_BW-1:0] lcl_req_len;
wire r2b_last, page_ovflw;
reg page_ovflw_r;
wire [`REQ_BW-1:0] r2b_len, next_req_len;
wire [12:0] max_r2b_len;
reg [12:0] max_r2b_len_r;
reg [1:0] r2b_ba;
reg [12:0] r2b_raddr;
reg [12:0] r2b_caddr;
reg [APP_AW-1:0] curr_sdr_addr ;
wire [APP_AW-1:0] next_sdr_addr ;
//--------------------------------------------------------------------
// Generate the internal Adress and Burst length Based on sdram width
//--------------------------------------------------------------------
reg [APP_AW:0] req_addr_int;
reg [APP_RW-1:0] req_len_int;
always @(*) begin
if(sdr_width == 2'b00) begin // 32 Bit SDR Mode
req_addr_int = {1'b0,req_addr};
req_len_int = req_len;
end else if(sdr_width == 2'b01) begin // 16 Bit SDR Mode
// Changed the address and length to match the 16 bit SDR Mode
req_addr_int = {req_addr,1'b0};
req_len_int = {req_len,1'b0};
end else begin // 8 Bit SDR Mode
// Changed the address and length to match the 16 bit SDR Mode
req_addr_int = {req_addr,2'b0};
req_len_int = {req_len,2'b0};
end
end
//
// Identify the page over flow.
// Find the Maximum Burst length allowed from the selected column
// address, If the requested burst length is more than the allowed Maximum
// burst length, then we need to handle the bank cross over case and we
// need to split the reuest.
//
assign max_r2b_len = (cfg_colbits == 2'b00) ? (12'h100 - {4'b0, req_addr_int[7:0]}) :
(cfg_colbits == 2'b01) ? (12'h200 - {3'b0, req_addr_int[8:0]}) :
(cfg_colbits == 2'b10) ? (12'h400 - {2'b0, req_addr_int[9:0]}) : (12'h800 - {1'b0, req_addr_int[10:0]});
// If the wrap = 0 and current application burst length is crossing the page boundary,
// then request will be split into two with corresponding change in request address and request length.
//
// If the wrap = 0 and current burst length is not crossing the page boundary,
// then request from application layer will be transparently passed on the bank control block.
//
// if the wrap = 1, then this block will not modify the request address and length.
// The wrapping functionality will be handle by the bank control module and
// column address will rewind back as follows XX -> FF ? 00 ? 1
//
// Note: With Wrap = 0, each request from Application layer will be spilited into two request,
// if the current burst cross the page boundary.
assign page_ovflw = ({1'b0, req_len_int} > max_r2b_len) ? ~r2b_wrap : 1'b0;
assign r2b_len = r2b_start ? ((page_ovflw_r) ? max_r2b_len_r : lcl_req_len) :
lcl_req_len;
assign next_req_len = lcl_req_len - r2b_len;
assign next_sdr_addr = curr_sdr_addr + r2b_len;
assign r2b_wrap = lcl_wrap;
assign r2b_last = (r2b_start & !page_ovflw_r) | (req_st == `REQ_PAGE_WRAP);
//
//
//
always @ (posedge clk) begin
page_ovflw_r <= (req_ack) ? page_ovflw: 'h0;
max_r2b_len_r <= (req_ack) ? max_r2b_len: 'h0;
r2b_start <= (req_ack) ? 1'b1 :
(b2r_ack) ? 1'b0 : r2b_start;
r2b_write <= (req_ack) ? ~req_wr_n : r2b_write;
r2b_req_id <= (req_ack) ? req_id : r2b_req_id;
lcl_wrap <= (req_ack) ? req_wrap : lcl_wrap;
lcl_req_len <= (req_ack) ? req_len_int :
(req_ld) ? next_req_len : lcl_req_len;
curr_sdr_addr <= (req_ack) ? req_addr_int :
(req_ld) ? next_sdr_addr : curr_sdr_addr;
end // always @ (posedge clk)
always @ (*) begin
r2x_idle = 1'b0;
req_idle = 1'b0;
req_ack = 1'b0;
req_ld = 1'b0;
r2b_req = 1'b0;
next_req_st = `REQ_IDLE;
case (req_st) // synopsys full_case parallel_case
`REQ_IDLE : begin
r2x_idle = ~req;
req_idle = 1'b1;
req_ack = req & b2r_arb_ok;
req_ld = 1'b0;
r2b_req = 1'b0;
next_req_st = (req & b2r_arb_ok) ? `REQ_ACTIVE : `REQ_IDLE;
end // case: `REQ_IDLE
`REQ_ACTIVE : begin
r2x_idle = 1'b0;
req_idle = 1'b0;
req_ack = 1'b0;
req_ld = b2r_ack;
r2b_req = 1'b1; // req_gen to bank_req
next_req_st = (b2r_ack ) ? ((page_ovflw_r) ? `REQ_PAGE_WRAP :`REQ_IDLE) : `REQ_ACTIVE;
end // case: `REQ_ACTIVE
`REQ_PAGE_WRAP : begin
r2x_idle = 1'b0;
req_idle = 1'b0;
req_ack = 1'b0;
req_ld = b2r_ack;
r2b_req = 1'b1; // req_gen to bank_req
next_req_st = (b2r_ack) ? `REQ_IDLE : `REQ_PAGE_WRAP;
end // case: `REQ_ACTIVE
endcase // case(req_st)
end // always @ (req_st or ....)
always @ (posedge clk)
if (~reset_n) begin
req_st <= `REQ_IDLE;
end // if (~reset_n)
else begin
req_st <= next_req_st;
end // else: !if(~reset_n)
//
// addrs bits for the bank, row and column
//
// Register row/column/bank to improve fpga timing issue
wire [APP_AW-1:0] map_address ;
assign map_address = (req_ack) ? req_addr_int :
(req_ld) ? next_sdr_addr : curr_sdr_addr;
always @ (posedge clk) begin
// Bank Bits are always - 2 Bits
r2b_ba <= (cfg_colbits == 2'b00) ? {map_address[9:8]} :
(cfg_colbits == 2'b01) ? {map_address[10:9]} :
(cfg_colbits == 2'b10) ? {map_address[11:10]} : map_address[12:11];
/********************
* Colbits Mapping:
* 2'b00 - 8 Bit
* 2'b01 - 16 Bit
* 2'b10 - 10 Bit
* 2'b11 - 11 Bits
************************/
r2b_caddr <= (cfg_colbits == 2'b00) ? {5'b0, map_address[7:0]} :
(cfg_colbits == 2'b01) ? {4'b0, map_address[8:0]} :
(cfg_colbits == 2'b10) ? {3'b0, map_address[9:0]} : {2'b0, map_address[10:0]};
r2b_raddr <= (cfg_colbits == 2'b00) ? map_address[22:10] :
(cfg_colbits == 2'b01) ? map_address[23:11] :
(cfg_colbits == 2'b10) ? map_address[24:12] : map_address[25:13];
end
endmodule // sdr_req_gen

View File

@ -0,0 +1,772 @@
/*********************************************************************
SDRAM Controller Transfer control
This file is part of the sdram controller project
http://www.opencores.org/cores/sdr_ctrl/
Description: SDRAM Controller Transfer control
This module takes requests from sdrc_bank_ctl and runs the
transfer. The input request is guaranteed to be in a bank that is
precharged and activated. This block runs the transfer until a
burst boundary is reached, then issues another read/write command
to sequentially step thru memory if wrap=0, until the transfer is
completed.
if a read transfer finishes and the caddr is not at a burst boundary
a burst terminate command is issued unless another read/write or
precharge to the same bank is pending.
if a write transfer finishes and the caddr is not at a burst boundary
a burst terminate command is issued unless a read/write is pending.
If a refresh request is made, the bank_ctl will be held off until
the number of refreshes requested are completed.
This block also handles SDRAM initialization.
To Do:
nothing
Author(s):
- Dinesh Annayya, dinesha@opencores.org
Version : 1.0 - 8th Jan 2012
Copyright (C) 2000 Authors and OPENCORES.ORG
This source file may be used and distributed without
restriction provided that this copyright statement is not
removed from the file and that any derivative work contains
the original copyright notice and the associated disclaimer.
This source file is free software; you can redistribute it
and/or modify it under the terms of the GNU Lesser General
Public License as published by the Free Software Foundation;
either version 2.1 of the License, or (at your option) any
later version.
This source is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General
Public License along with this source; if not, download it
from http://www.opencores.org/lgpl.shtml
*******************************************************************/
`include "sdrc_define.v"
module sdrc_xfr_ctl (clk,
reset_n,
/* Transfer request from bank_ctl */
r2x_idle, // Req is idle
b2x_idle, // All banks are idle
b2x_req, // Req from bank_ctl
b2x_start, // first chunk of transfer
b2x_last, // last chunk of transfer
b2x_id, // Transfer ID
b2x_ba, // bank address
b2x_addr, // row/col address
b2x_len, // transfer length
b2x_cmd, // transfer command
b2x_wrap, // Wrap mode transfer
x2b_ack, // command accepted
/* Status to bank_ctl, req_gen */
b2x_tras_ok, // Tras for all banks expired
x2b_refresh, // We did a refresh
x2b_pre_ok, // OK to do a precharge (per bank)
x2b_act_ok, // OK to do an activate
x2b_rdok, // OK to do a read
x2b_wrok, // OK to do a write
/* SDRAM I/O */
sdr_cs_n,
sdr_cke,
sdr_ras_n,
sdr_cas_n,
sdr_we_n,
sdr_dqm,
sdr_ba,
sdr_addr,
sdr_din,
sdr_dout,
sdr_den_n,
/* Data Flow to the app */
x2a_rdstart,
x2a_wrstart,
x2a_rdlast,
x2a_wrlast,
x2a_id,
a2x_wrdt,
a2x_wren_n,
x2a_wrnext,
x2a_rddt,
x2a_rdok,
sdr_init_done,
/* SDRAM Parameters */
sdram_enable,
sdram_mode_reg,
/* output for generate row address of the transfer */
xfr_bank_sel,
/* SDRAM Timing */
cas_latency,
trp_delay, // Precharge to refresh delay
trcar_delay, // Auto-refresh period
twr_delay, // Write recovery delay
rfsh_time, // time per row (31.25 or 15.6125 uS)
rfsh_rmax); // Number of rows to rfsh at a time (<120uS)
parameter SDR_DW = 16; // SDR Data Width
parameter SDR_BW = 2; // SDR Byte Width
input clk, reset_n;
/* Req from bank_ctl */
input b2x_req, b2x_start, b2x_last, b2x_tras_ok,
b2x_wrap, r2x_idle, b2x_idle;
input [`SDR_REQ_ID_W-1:0] b2x_id;
input [1:0] b2x_ba;
input [12:0] b2x_addr;
input [`REQ_BW-1:0] b2x_len;
input [1:0] b2x_cmd;
output x2b_ack;
/* Status to bank_ctl */
output [3:0] x2b_pre_ok;
output x2b_refresh, x2b_act_ok, x2b_rdok,
x2b_wrok;
/* Data Flow to the app */
output x2a_rdstart, x2a_wrstart, x2a_rdlast, x2a_wrlast;
output [`SDR_REQ_ID_W-1:0] x2a_id;
input [SDR_DW-1:0] a2x_wrdt;
input [SDR_BW-1:0] a2x_wren_n;
output [SDR_DW-1:0] x2a_rddt;
output x2a_wrnext, x2a_rdok, sdr_init_done;
/* Interface to SDRAMs */
output sdr_cs_n, sdr_cke, sdr_ras_n, sdr_cas_n,
sdr_we_n;
output [SDR_BW-1:0] sdr_dqm;
output [1:0] sdr_ba;
output [12:0] sdr_addr;
input [SDR_DW-1:0] sdr_din;
output [SDR_DW-1:0] sdr_dout;
output [SDR_BW-1:0] sdr_den_n;
output [1:0] xfr_bank_sel;
input sdram_enable;
input [12:0] sdram_mode_reg;
input [2:0] cas_latency;
input [3:0] trp_delay, trcar_delay, twr_delay;
input [`SDR_RFSH_TIMER_W-1 : 0] rfsh_time;
input [`SDR_RFSH_ROW_CNT_W-1:0] rfsh_rmax;
/************************************************************************/
// Internal Nets
`define XFR_IDLE 2'b00
`define XFR_WRITE 2'b01
`define XFR_READ 2'b10
`define XFR_RDWT 2'b11
reg [1:0] xfr_st, next_xfr_st;
reg [12:0] xfr_caddr;
wire last_burst;
wire x2a_rdstart, x2a_wrstart, x2a_rdlast, x2a_wrlast;
reg l_start, l_last, l_wrap;
wire [`SDR_REQ_ID_W-1:0] x2a_id;
reg [`SDR_REQ_ID_W-1:0] l_id;
wire [1:0] xfr_ba;
reg [1:0] l_ba;
wire [12:0] xfr_addr;
wire [`REQ_BW-1:0] xfr_len, next_xfr_len;
reg [`REQ_BW-1:0] l_len;
reg mgmt_idle, mgmt_req;
reg [3:0] mgmt_cmd;
reg [12:0] mgmt_addr;
reg [1:0] mgmt_ba;
reg sel_mgmt, sel_b2x;
reg cb_pre_ok, rdok, wrok, wr_next,
rd_next, sdr_init_done, act_cmd, d_act_cmd;
wire [3:0] b2x_sdr_cmd, xfr_cmd;
reg [3:0] i_xfr_cmd;
wire mgmt_ack, x2b_ack, b2x_read, b2x_write,
b2x_prechg, d_rd_next, dt_next, xfr_end,
rd_pipe_mt, ld_xfr, rd_last, d_rd_last,
wr_last, l_xfr_end, rd_start, d_rd_start,
wr_start, page_hit, burst_bdry, xfr_wrap,
b2x_prechg_hit;
reg [6:0] l_rd_next, l_rd_start, l_rd_last;
assign b2x_read = (b2x_cmd == `OP_RD) ? 1'b1 : 1'b0;
assign b2x_write = (b2x_cmd == `OP_WR) ? 1'b1 : 1'b0;
assign b2x_prechg = (b2x_cmd == `OP_PRE) ? 1'b1 : 1'b0;
assign b2x_sdr_cmd = (b2x_cmd == `OP_PRE) ? `SDR_PRECHARGE :
(b2x_cmd == `OP_ACT) ? `SDR_ACTIVATE :
(b2x_cmd == `OP_RD) ? `SDR_READ :
(b2x_cmd == `OP_WR) ? `SDR_WRITE : `SDR_DESEL;
assign page_hit = (b2x_ba == l_ba) ? 1'b1 : 1'b0;
assign b2x_prechg_hit = b2x_prechg & page_hit;
assign xfr_cmd = (sel_mgmt) ? mgmt_cmd :
(sel_b2x) ? b2x_sdr_cmd : i_xfr_cmd;
assign xfr_addr = (sel_mgmt) ? mgmt_addr :
(sel_b2x) ? b2x_addr : xfr_caddr+1;
assign mgmt_ack = sel_mgmt;
assign x2b_ack = sel_b2x;
assign ld_xfr = sel_b2x & (b2x_read | b2x_write);
assign xfr_len = (ld_xfr) ? b2x_len : l_len;
//assign next_xfr_len = (l_xfr_end && !ld_xfr) ? l_len : xfr_len - 1;
assign next_xfr_len = (ld_xfr) ? b2x_len :
(l_xfr_end) ? l_len: l_len - 1;
assign d_rd_next = (cas_latency == 3'b001) ? l_rd_next[2] :
(cas_latency == 3'b010) ? l_rd_next[3] :
(cas_latency == 3'b011) ? l_rd_next[4] :
(cas_latency == 3'b100) ? l_rd_next[5] :
l_rd_next[6];
assign d_rd_last = (cas_latency == 3'b001) ? l_rd_last[2] :
(cas_latency == 3'b010) ? l_rd_last[3] :
(cas_latency == 3'b011) ? l_rd_last[4] :
(cas_latency == 3'b100) ? l_rd_last[5] :
l_rd_last[6];
assign d_rd_start = (cas_latency == 3'b001) ? l_rd_start[2] :
(cas_latency == 3'b010) ? l_rd_start[3] :
(cas_latency == 3'b011) ? l_rd_start[4] :
(cas_latency == 3'b100) ? l_rd_start[5] :
l_rd_start[6];
assign rd_pipe_mt = (cas_latency == 3'b001) ? ~|l_rd_next[1:0] :
(cas_latency == 3'b010) ? ~|l_rd_next[2:0] :
(cas_latency == 3'b011) ? ~|l_rd_next[3:0] :
(cas_latency == 3'b100) ? ~|l_rd_next[4:0] :
~|l_rd_next[5:0];
assign dt_next = wr_next | d_rd_next;
assign xfr_end = ~|xfr_len;
assign l_xfr_end = ~|(l_len-1);
assign rd_start = ld_xfr & b2x_read & b2x_start;
assign wr_start = ld_xfr & b2x_write & b2x_start;
assign rd_last = rd_next & last_burst & ~|xfr_len[`REQ_BW-1:1];
//assign wr_last = wr_next & last_burst & ~|xfr_len[APP_RW-1:1];
assign wr_last = last_burst & ~|xfr_len[`REQ_BW-1:1];
//assign xfr_ba = (ld_xfr) ? b2x_ba : l_ba;
assign xfr_ba = (sel_mgmt) ? mgmt_ba :
(sel_b2x) ? b2x_ba : l_ba;
assign xfr_wrap = (ld_xfr) ? b2x_wrap : l_wrap;
// assign burst_bdry = ~|xfr_caddr[2:0];
wire [1:0] xfr_caddr_lsb = (xfr_caddr[1:0]+1);
assign burst_bdry = ~|(xfr_caddr_lsb[1:0]);
always @ (posedge clk) begin
if (~reset_n) begin
xfr_caddr <= 13'b0;
l_start <= 1'b0;
l_last <= 1'b0;
l_wrap <= 1'b0;
l_id <= 0;
l_ba <= 0;
l_len <= 0;
l_rd_next <= 7'b0;
l_rd_start <= 7'b0;
l_rd_last <= 7'b0;
act_cmd <= 1'b0;
d_act_cmd <= 1'b0;
xfr_st <= `XFR_IDLE;
end // if (~reset_n)
else begin
xfr_caddr <= (ld_xfr) ? b2x_addr :
(rd_next | wr_next) ? xfr_caddr + 1 : xfr_caddr;
l_start <= (dt_next) ? 1'b0 :
(ld_xfr) ? b2x_start : l_start;
l_last <= (ld_xfr) ? b2x_last : l_last;
l_wrap <= (ld_xfr) ? b2x_wrap : l_wrap;
l_id <= (ld_xfr) ? b2x_id : l_id;
l_ba <= (ld_xfr) ? b2x_ba : l_ba;
l_len <= next_xfr_len;
l_rd_next <= {l_rd_next[5:0], rd_next};
l_rd_start <= {l_rd_start[5:0], rd_start};
l_rd_last <= {l_rd_last[5:0], rd_last};
act_cmd <= (xfr_cmd == `SDR_ACTIVATE) ? 1'b1 : 1'b0;
d_act_cmd <= act_cmd;
xfr_st <= next_xfr_st;
end // else: !if(~reset_n)
end // always @ (posedge clk)
always @ (*) begin
case (xfr_st)
`XFR_IDLE : begin
sel_mgmt = mgmt_req;
sel_b2x = ~mgmt_req & sdr_init_done & b2x_req;
i_xfr_cmd = `SDR_DESEL;
rd_next = ~mgmt_req & sdr_init_done & b2x_req & b2x_read;
wr_next = ~mgmt_req & sdr_init_done & b2x_req & b2x_write;
rdok = ~mgmt_req;
cb_pre_ok = 1'b1;
wrok = ~mgmt_req;
next_xfr_st = (mgmt_req | ~sdr_init_done) ? `XFR_IDLE :
(~b2x_req) ? `XFR_IDLE :
(b2x_read) ? `XFR_READ :
(b2x_write) ? `XFR_WRITE : `XFR_IDLE;
end // case: `XFR_IDLE
`XFR_READ : begin
rd_next = ~l_xfr_end |
l_xfr_end & ~mgmt_req & b2x_req & b2x_read;
wr_next = 1'b0;
rdok = l_xfr_end & ~mgmt_req;
// Break the timing path for FPGA Based Design
cb_pre_ok = (`TARGET_DESIGN == `FPGA) ? 1'b0 : l_xfr_end;
wrok = 1'b0;
sel_mgmt = 1'b0;
if (l_xfr_end) begin // end of transfer
if (~l_wrap) begin
// Current transfer was not wrap mode, may need BT
// If next cmd is a R or W or PRE to same bank allow
// it else issue BT
// This is a little pessimistic since BT is issued
// for non-wrap mode transfers even if the transfer
// ends on a burst boundary, but is felt to be of
// minimal performance impact.
i_xfr_cmd = `SDR_BT;
sel_b2x = b2x_req & ~mgmt_req & (b2x_read | b2x_prechg_hit);
end // if (~l_wrap)
else begin
// Wrap mode transfer, by definition is end of burst
// boundary
i_xfr_cmd = `SDR_DESEL;
sel_b2x = b2x_req & ~mgmt_req & ~b2x_write;
end // else: !if(~l_wrap)
next_xfr_st = (sdr_init_done) ? ((b2x_req & ~mgmt_req & b2x_read) ? `XFR_READ : `XFR_RDWT) : `XFR_IDLE;
end // if (l_xfr_end)
else begin
// Not end of transfer
// If current transfer was not wrap mode and we are at
// the start of a burst boundary issue another R cmd to
// step sequemtially thru memory, ELSE,
// issue precharge/activate commands from the bank control
i_xfr_cmd = (burst_bdry & ~l_wrap) ? `SDR_READ : `SDR_DESEL;
sel_b2x = ~(burst_bdry & ~l_wrap) & b2x_req;
next_xfr_st = `XFR_READ;
end // else: !if(l_xfr_end)
end // case: `XFR_READ
`XFR_RDWT : begin
rd_next = ~mgmt_req & b2x_req & b2x_read;
wr_next = rd_pipe_mt & ~mgmt_req & b2x_req & b2x_write;
rdok = ~mgmt_req;
cb_pre_ok = 1'b1;
wrok = rd_pipe_mt & ~mgmt_req;
sel_mgmt = mgmt_req;
sel_b2x = ~mgmt_req & b2x_req;
i_xfr_cmd = `SDR_DESEL;
next_xfr_st = (~mgmt_req & b2x_req & b2x_read) ? `XFR_READ :
(~rd_pipe_mt) ? `XFR_RDWT :
(~mgmt_req & b2x_req & b2x_write) ? `XFR_WRITE :
`XFR_IDLE;
end // case: `XFR_RDWT
`XFR_WRITE : begin
rd_next = l_xfr_end & ~mgmt_req & b2x_req & b2x_read;
wr_next = ~l_xfr_end |
l_xfr_end & ~mgmt_req & b2x_req & b2x_write;
rdok = l_xfr_end & ~mgmt_req;
cb_pre_ok = 1'b0;
wrok = l_xfr_end & ~mgmt_req;
sel_mgmt = 1'b0;
if (l_xfr_end) begin // End of transfer
if (~l_wrap) begin
// Current transfer was not wrap mode, may need BT
// If next cmd is a R or W allow it else issue BT
// This is a little pessimistic since BT is issued
// for non-wrap mode transfers even if the transfer
// ends on a burst boundary, but is felt to be of
// minimal performance impact.
sel_b2x = b2x_req & ~mgmt_req & (b2x_read | b2x_write);
i_xfr_cmd = `SDR_BT;
end // if (~l_wrap)
else begin
// Wrap mode transfer, by definition is end of burst
// boundary
sel_b2x = b2x_req & ~mgmt_req & ~b2x_prechg_hit;
i_xfr_cmd = `SDR_DESEL;
end // else: !if(~l_wrap)
next_xfr_st = (~mgmt_req & b2x_req & b2x_read) ? `XFR_READ :
(~mgmt_req & b2x_req & b2x_write) ? `XFR_WRITE :
`XFR_IDLE;
end // if (l_xfr_end)
else begin
// Not end of transfer
// If current transfer was not wrap mode and we are at
// the start of a burst boundary issue another R cmd to
// step sequemtially thru memory, ELSE,
// issue precharge/activate commands from the bank control
if (burst_bdry & ~l_wrap) begin
sel_b2x = 1'b0;
i_xfr_cmd = `SDR_WRITE;
end // if (burst_bdry & ~l_wrap)
else begin
sel_b2x = b2x_req & ~mgmt_req;
i_xfr_cmd = `SDR_DESEL;
end // else: !if(burst_bdry & ~l_wrap)
next_xfr_st = `XFR_WRITE;
end // else: !if(l_xfr_end)
end // case: `XFR_WRITE
endcase // case(xfr_st)
end // always @ (xfr_st or ...)
// signals to bank_ctl (x2b_refresh, x2b_act_ok, x2b_rdok, x2b_wrok,
// x2b_pre_ok[3:0]
assign x2b_refresh = (xfr_cmd == `SDR_REFRESH) ? 1'b1 : 1'b0;
assign x2b_act_ok = ~act_cmd & ~d_act_cmd;
assign x2b_rdok = rdok;
assign x2b_wrok = wrok;
//assign x2b_pre_ok[0] = (l_ba == 2'b00) ? cb_pre_ok : 1'b1;
//assign x2b_pre_ok[1] = (l_ba == 2'b01) ? cb_pre_ok : 1'b1;
//assign x2b_pre_ok[2] = (l_ba == 2'b10) ? cb_pre_ok : 1'b1;
//assign x2b_pre_ok[3] = (l_ba == 2'b11) ? cb_pre_ok : 1'b1;
assign x2b_pre_ok[0] = cb_pre_ok;
assign x2b_pre_ok[1] = cb_pre_ok;
assign x2b_pre_ok[2] = cb_pre_ok;
assign x2b_pre_ok[3] = cb_pre_ok;
assign last_burst = (ld_xfr) ? b2x_last : l_last;
/************************************************************************/
// APP Data I/F
wire [SDR_DW-1:0] x2a_rddt;
//assign x2a_start = (ld_xfr) ? b2x_start : l_start;
assign x2a_rdstart = d_rd_start;
assign x2a_wrstart = wr_start;
assign x2a_rdlast = d_rd_last;
assign x2a_wrlast = wr_last;
assign x2a_id = (ld_xfr) ? b2x_id : l_id;
assign x2a_rddt = sdr_din;
assign x2a_wrnext = wr_next;
assign x2a_rdok = d_rd_next;
/************************************************************************/
// SDRAM I/F
reg sdr_cs_n, sdr_cke, sdr_ras_n, sdr_cas_n,
sdr_we_n;
reg [SDR_BW-1:0] sdr_dqm;
reg [1:0] sdr_ba;
reg [12:0] sdr_addr;
reg [SDR_DW-1:0] sdr_dout;
reg [SDR_BW-1:0] sdr_den_n;
always @ (posedge clk)
if (~reset_n) begin
sdr_cs_n <= 1'b1;
sdr_cke <= 1'b1;
sdr_ras_n <= 1'b1;
sdr_cas_n <= 1'b1;
sdr_we_n <= 1'b1;
sdr_dqm <= {SDR_BW{1'b1}};
sdr_den_n <= {SDR_BW{1'b1}};
end // if (~reset_n)
else begin
sdr_cs_n <= xfr_cmd[3];
sdr_ras_n <= xfr_cmd[2];
sdr_cas_n <= xfr_cmd[1];
sdr_we_n <= xfr_cmd[0];
sdr_cke <= (xfr_st != `XFR_IDLE) ? 1'b1 :
~(mgmt_idle & b2x_idle & r2x_idle);
sdr_dqm <= (wr_next) ? a2x_wren_n : {SDR_BW{1'b0}};
sdr_den_n <= (wr_next) ? {SDR_BW{1'b0}} : {SDR_BW{1'b1}};
end // else: !if(~reset_n)
always @ (posedge clk) begin
if (~xfr_cmd[3]) begin
sdr_addr <= xfr_addr;
sdr_ba <= xfr_ba;
end // if (~xfr_cmd[3])
sdr_dout <= (wr_next) ? a2x_wrdt : sdr_dout;
end // always @ (posedge clk)
/************************************************************************/
// Refresh and Initialization
`define MGM_POWERUP 3'b000
`define MGM_PRECHARGE 3'b001
`define MGM_PCHWT 3'b010
`define MGM_REFRESH 3'b011
`define MGM_REFWT 3'b100
`define MGM_MODE_REG 3'b101
`define MGM_MODE_WT 3'b110
`define MGM_ACTIVE 3'b111
reg [2:0] mgmt_st, next_mgmt_st;
reg [3:0] tmr0, tmr0_d;
reg [3:0] cntr1, cntr1_d;
wire tmr0_tc, cntr1_tc, rfsh_timer_tc, ref_req, precharge_ok;
reg ld_tmr0, ld_cntr1, dec_cntr1, set_sdr_init_done;
reg [`SDR_RFSH_TIMER_W-1 : 0] rfsh_timer;
reg [`SDR_RFSH_ROW_CNT_W-1:0] rfsh_row_cnt;
always @ (posedge clk)
if (~reset_n) begin
mgmt_st <= `MGM_POWERUP;
tmr0 <= 4'b0;
cntr1 <= 4'h7;
rfsh_timer <= 0;
rfsh_row_cnt <= 0;
sdr_init_done <= 1'b0;
end // if (~reset_n)
else begin
mgmt_st <= next_mgmt_st;
tmr0 <= (ld_tmr0) ? tmr0_d :
(~tmr0_tc) ? tmr0 - 1 : tmr0;
cntr1 <= (ld_cntr1) ? cntr1_d :
(dec_cntr1) ? cntr1 - 1 : cntr1;
sdr_init_done <= (set_sdr_init_done | sdr_init_done) & sdram_enable;
rfsh_timer <= (rfsh_timer_tc) ? 0 : rfsh_timer + 1;
rfsh_row_cnt <= (~set_sdr_init_done) ? 0 :
(rfsh_timer_tc) ? rfsh_row_cnt + 1 : rfsh_row_cnt;
end // else: !if(~reset_n)
assign tmr0_tc = ~|tmr0;
assign cntr1_tc = ~|cntr1;
assign rfsh_timer_tc = (rfsh_timer == rfsh_time) ? 1'b1 : 1'b0;
assign ref_req = (rfsh_row_cnt >= rfsh_rmax) ? 1'b1 : 1'b0;
assign precharge_ok = cb_pre_ok & b2x_tras_ok;
assign xfr_bank_sel = l_ba;
always @ (mgmt_st or sdram_enable or mgmt_ack or trp_delay or tmr0_tc or
cntr1_tc or trcar_delay or rfsh_row_cnt or ref_req or sdr_init_done
or precharge_ok or sdram_mode_reg) begin
case (mgmt_st) // synopsys full_case parallel_case
`MGM_POWERUP : begin
mgmt_idle = 1'b0;
mgmt_req = 1'b0;
mgmt_cmd = `SDR_DESEL;
mgmt_ba = 2'b0;
mgmt_addr = 13'h400; // A10 = 1 => all banks
ld_tmr0 = 1'b0;
tmr0_d = 4'b0;
dec_cntr1 = 1'b0;
ld_cntr1 = 1'b1;
cntr1_d = 4'hf; // changed for sdrams with higher refresh cycles during initialization
set_sdr_init_done = 1'b0;
next_mgmt_st = (sdram_enable) ? `MGM_PRECHARGE : `MGM_POWERUP;
end // case: `MGM_POWERUP
`MGM_PRECHARGE : begin // Precharge all banks
mgmt_idle = 1'b0;
mgmt_req = 1'b1;
mgmt_cmd = (precharge_ok) ? `SDR_PRECHARGE : `SDR_DESEL;
mgmt_ba = 2'b0;
mgmt_addr = 13'h400; // A10 = 1 => all banks
ld_tmr0 = mgmt_ack;
tmr0_d = trp_delay;
ld_cntr1 = 1'b0;
cntr1_d = 4'h7;
dec_cntr1 = 1'b0;
set_sdr_init_done = 1'b0;
next_mgmt_st = (precharge_ok & mgmt_ack) ? `MGM_PCHWT : `MGM_PRECHARGE;
end // case: `MGM_PRECHARGE
`MGM_PCHWT : begin // Wait for Trp
mgmt_idle = 1'b0;
mgmt_req = 1'b1;
mgmt_cmd = `SDR_DESEL;
mgmt_ba = 2'b0;
mgmt_addr = 13'h400; // A10 = 1 => all banks
ld_tmr0 = 1'b0;
tmr0_d = trp_delay;
ld_cntr1 = 1'b0;
cntr1_d = 4'b0;
dec_cntr1 = 1'b0;
set_sdr_init_done = 1'b0;
next_mgmt_st = (tmr0_tc) ? `MGM_REFRESH : `MGM_PCHWT;
end // case: `MGM_PRECHARGE
`MGM_REFRESH : begin // Refresh
mgmt_idle = 1'b0;
mgmt_req = 1'b1;
mgmt_cmd = `SDR_REFRESH;
mgmt_ba = 2'b0;
mgmt_addr = 13'h400; // A10 = 1 => all banks
ld_tmr0 = mgmt_ack;
tmr0_d = trcar_delay;
dec_cntr1 = mgmt_ack;
ld_cntr1 = 1'b0;
cntr1_d = 4'h7;
set_sdr_init_done = 1'b0;
next_mgmt_st = (mgmt_ack) ? `MGM_REFWT : `MGM_REFRESH;
end // case: `MGM_REFRESH
`MGM_REFWT : begin // Wait for trcar
mgmt_idle = 1'b0;
mgmt_req = 1'b1;
mgmt_cmd = `SDR_DESEL;
mgmt_ba = 2'b0;
mgmt_addr = 13'h400; // A10 = 1 => all banks
ld_tmr0 = 1'b0;
tmr0_d = trcar_delay;
dec_cntr1 = 1'b0;
ld_cntr1 = 1'b0;
cntr1_d = 4'h7;
set_sdr_init_done = 1'b0;
next_mgmt_st = (~tmr0_tc) ? `MGM_REFWT :
(~cntr1_tc) ? `MGM_REFRESH :
(sdr_init_done) ? `MGM_ACTIVE : `MGM_MODE_REG;
end // case: `MGM_REFWT
`MGM_MODE_REG : begin // Program mode Register & wait for
mgmt_idle = 1'b0;
mgmt_req = 1'b1;
mgmt_cmd = `SDR_MODE;
mgmt_ba = {1'b0, sdram_mode_reg[11]};
mgmt_addr = sdram_mode_reg;
ld_tmr0 = mgmt_ack;
tmr0_d = 4'h7;
dec_cntr1 = 1'b0;
ld_cntr1 = 1'b0;
cntr1_d = 4'h7;
set_sdr_init_done = 1'b0;
next_mgmt_st = (mgmt_ack) ? `MGM_MODE_WT : `MGM_MODE_REG;
end // case: `MGM_MODE_REG
`MGM_MODE_WT : begin // Wait for tMRD
mgmt_idle = 1'b0;
mgmt_req = 1'b1;
mgmt_cmd = `SDR_DESEL;
mgmt_ba = 2'bx;
mgmt_addr = 13'bx;
ld_tmr0 = 1'b0;
tmr0_d = 4'h7;
dec_cntr1 = 1'b0;
ld_cntr1 = 1'b0;
cntr1_d = 4'h7;
set_sdr_init_done = 1'b0;
next_mgmt_st = (~tmr0_tc) ? `MGM_MODE_WT : `MGM_ACTIVE;
end // case: `MGM_MODE_WT
`MGM_ACTIVE : begin // Wait for ref_req
mgmt_idle = ~ref_req;
mgmt_req = 1'b0;
mgmt_cmd = `SDR_DESEL;
mgmt_ba = 2'bx;
mgmt_addr = 13'bx;
ld_tmr0 = 1'b0;
tmr0_d = 4'h7;
dec_cntr1 = 1'b0;
ld_cntr1 = ref_req;
cntr1_d = rfsh_row_cnt;
set_sdr_init_done = 1'b1;
next_mgmt_st = (~sdram_enable) ? `MGM_POWERUP :
(ref_req) ? `MGM_PRECHARGE : `MGM_ACTIVE;
end // case: `MGM_MODE_WT
endcase // case(mgmt_st)
end // always @ (mgmt_st or ....)
endmodule // sdr_xfr_ctl

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,963 @@
/****************************************************************************************
*
* File Name: MT48LC8M16A2.V
* Version: 0.0f
* Date: July 8th, 1999
* Model: BUS Functional
* Simulator: Model Technology (PC version 5.2e PE)
*
* Dependencies: None
*
* Author: Son P. Huynh
* Email: sphuynh@micron.com
* Phone: (208) 368-3825
* Company: Micron Technology, Inc.
* Model: MT48LC8M16A2 (2Meg x 16 x 4 Banks)
*
* Description: Micron 128Mb SDRAM Verilog model
*
* Limitation: - Doesn't check for 4096 cycle refresh
*
* Note: - Set simulator resolution to "ps" accuracy
* - Set Debug = 0 to disable $display messages
*
* Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY
* WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
* A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT.
*
* Copyright © 1998 Micron Semiconductor Products, Inc.
* All rights researved
*
* Rev Author Phone Date Changes
* ---- ---------------------------- ---------- ---------------------------------------
* 0.0f Son Huynh 208-368-3825 07/08/1999 - Fix tWR = 1 Clk + 7.5 ns (Auto)
* Micron Technology Inc. - Fix tWR = 15 ns (Manual)
* - Fix tRP (Autoprecharge to AutoRefresh)
*
* 0.0a Son Huynh 208-368-3825 05/13/1998 - First Release (from 64Mb rev 0.0e)
* Micron Technology Inc.
****************************************************************************************/
`timescale 1ns / 100ps
module mt48lc8m16a2 (Dq, Addr, Ba, Clk, Cke, Cs_n, Ras_n, Cas_n, We_n, Dqm);
parameter addr_bits = 12;
parameter data_bits = 16;
parameter col_bits = 9;
parameter mem_sizes = 2097151; // 2 Meg
inout [data_bits - 1 : 0] Dq;
input [addr_bits - 1 : 0] Addr;
input [1 : 0] Ba;
input Clk;
input Cke;
input Cs_n;
input Ras_n;
input Cas_n;
input We_n;
input [1 : 0] Dqm;
reg [data_bits - 1 : 0] Bank0 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank1 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank2 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank3 [0 : mem_sizes];
reg [1 : 0] Bank_addr [0 : 3]; // Bank Address Pipeline
reg [col_bits - 1 : 0] Col_addr [0 : 3]; // Column Address Pipeline
reg [3 : 0] Command [0 : 3]; // Command Operation Pipeline
reg [1 : 0] Dqm_reg0, Dqm_reg1; // DQM Operation Pipeline
reg [addr_bits - 1 : 0] B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr;
reg [addr_bits - 1 : 0] Mode_reg;
reg [data_bits - 1 : 0] Dq_reg, Dq_dqm;
reg [col_bits - 1 : 0] Col_temp, Burst_counter;
reg Act_b0, Act_b1, Act_b2, Act_b3; // Bank Activate
reg Pc_b0, Pc_b1, Pc_b2, Pc_b3; // Bank Precharge
reg [1 : 0] Bank_precharge [0 : 3]; // Precharge Command
reg A10_precharge [0 : 3]; // Addr[10] = 1 (All banks)
reg Auto_precharge [0 : 3]; // RW AutoPrecharge (Bank)
reg Read_precharge [0 : 3]; // R AutoPrecharge
reg Write_precharge [0 : 3]; // W AutoPrecharge
integer Count_precharge [0 : 3]; // RW AutoPrecharge (Counter)
reg RW_interrupt_read [0 : 3]; // RW Interrupt Read with Auto Precharge
reg RW_interrupt_write [0 : 3]; // RW Interrupt Write with Auto Precharge
reg Data_in_enable;
reg Data_out_enable;
reg [1 : 0] Bank, Previous_bank;
reg [addr_bits - 1 : 0] Row;
reg [col_bits - 1 : 0] Col, Col_brst;
// Internal system clock
reg CkeZ, Sys_clk;
// Commands Decode
wire Active_enable = ~Cs_n & ~Ras_n & Cas_n & We_n;
wire Aref_enable = ~Cs_n & ~Ras_n & ~Cas_n & We_n;
wire Burst_term = ~Cs_n & Ras_n & Cas_n & ~We_n;
wire Mode_reg_enable = ~Cs_n & ~Ras_n & ~Cas_n & ~We_n;
wire Prech_enable = ~Cs_n & ~Ras_n & Cas_n & ~We_n;
wire Read_enable = ~Cs_n & Ras_n & ~Cas_n & We_n;
wire Write_enable = ~Cs_n & Ras_n & ~Cas_n & ~We_n;
// Burst Length Decode
wire Burst_length_1 = ~Mode_reg[2] & ~Mode_reg[1] & ~Mode_reg[0];
wire Burst_length_2 = ~Mode_reg[2] & ~Mode_reg[1] & Mode_reg[0];
wire Burst_length_4 = ~Mode_reg[2] & Mode_reg[1] & ~Mode_reg[0];
wire Burst_length_8 = ~Mode_reg[2] & Mode_reg[1] & Mode_reg[0];
// CAS Latency Decode
wire Cas_latency_2 = ~Mode_reg[6] & Mode_reg[5] & ~Mode_reg[4];
wire Cas_latency_3 = ~Mode_reg[6] & Mode_reg[5] & Mode_reg[4];
// Write Burst Mode
wire Write_burst_mode = Mode_reg[9];
reg Debug; // Debug messages : 1 = On
wire Dq_chk = Sys_clk & Data_in_enable; // Check setup/hold time for DQ
assign Dq = Dq_reg; // DQ buffer
// Commands Operation
`define ACT 0
`define NOP 1
`define READ 2
`define READ_A 3
`define WRITE 4
`define WRITE_A 5
`define PRECH 6
`define A_REF 7
`define BST 8
`define LMR 9
// Timing Parameters for -75 (PC133) and CAS Latency = 2
parameter tAC = 6.0;
parameter tHZ = 7.0;
parameter tOH = 2.7;
parameter tMRD = 2.0; // 2 Clk Cycles
parameter tRAS = 44.0;
parameter tRC = 66.0;
parameter tRCD = 20.0;
parameter tRP = 20.0;
parameter tRRD = 15.0;
parameter tWRa = 7.5; // A2 Version - Auto precharge mode only (1 Clk + 7.5 ns)
parameter tWRp = 15.0; // A2 Version - Precharge mode only (15 ns)
// Timing Check variable
integer MRD_chk;
integer WR_counter [0 : 3];
time WR_chk [0 : 3];
time RC_chk, RRD_chk;
time RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3;
time RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3;
time RP_chk0, RP_chk1, RP_chk2, RP_chk3;
initial begin
Debug = 1'b0;
Dq_reg = {data_bits{1'bz}};
{Data_in_enable, Data_out_enable} = 0;
{Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000;
{Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b0000;
{WR_chk[0], WR_chk[1], WR_chk[2], WR_chk[3]} = 0;
{WR_counter[0], WR_counter[1], WR_counter[2], WR_counter[3]} = 0;
{RW_interrupt_read[0], RW_interrupt_read[1], RW_interrupt_read[2], RW_interrupt_read[3]} = 0;
{RW_interrupt_write[0], RW_interrupt_write[1], RW_interrupt_write[2], RW_interrupt_write[3]} = 0;
{MRD_chk, RC_chk, RRD_chk} = 0;
{RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3} = 0;
{RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3} = 0;
{RP_chk0, RP_chk1, RP_chk2, RP_chk3} = 0;
$timeformat (-9, 0, " ns", 12);
//$readmemh("bank0.txt", Bank0);
//$readmemh("bank1.txt", Bank1);
//$readmemh("bank2.txt", Bank2);
//$readmemh("bank3.txt", Bank3);
end
// System clock generator
always begin
@ (posedge Clk) begin
Sys_clk = CkeZ;
CkeZ = Cke;
end
@ (negedge Clk) begin
Sys_clk = 1'b0;
end
end
always @ (posedge Sys_clk) begin
// Internal Commamd Pipelined
Command[0] = Command[1];
Command[1] = Command[2];
Command[2] = Command[3];
Command[3] = `NOP;
Col_addr[0] = Col_addr[1];
Col_addr[1] = Col_addr[2];
Col_addr[2] = Col_addr[3];
Col_addr[3] = {col_bits{1'b0}};
Bank_addr[0] = Bank_addr[1];
Bank_addr[1] = Bank_addr[2];
Bank_addr[2] = Bank_addr[3];
Bank_addr[3] = 2'b0;
Bank_precharge[0] = Bank_precharge[1];
Bank_precharge[1] = Bank_precharge[2];
Bank_precharge[2] = Bank_precharge[3];
Bank_precharge[3] = 2'b0;
A10_precharge[0] = A10_precharge[1];
A10_precharge[1] = A10_precharge[2];
A10_precharge[2] = A10_precharge[3];
A10_precharge[3] = 1'b0;
// Dqm pipeline for Read
Dqm_reg0 = Dqm_reg1;
Dqm_reg1 = Dqm;
// Read or Write with Auto Precharge Counter
if (Auto_precharge[0] == 1'b1) begin
Count_precharge[0] = Count_precharge[0] + 1;
end
if (Auto_precharge[1] == 1'b1) begin
Count_precharge[1] = Count_precharge[1] + 1;
end
if (Auto_precharge[2] == 1'b1) begin
Count_precharge[2] = Count_precharge[2] + 1;
end
if (Auto_precharge[3] == 1'b1) begin
Count_precharge[3] = Count_precharge[3] + 1;
end
// tMRD Counter
MRD_chk = MRD_chk + 1;
// tWR Counter for Write
WR_counter[0] = WR_counter[0] + 1;
WR_counter[1] = WR_counter[1] + 1;
WR_counter[2] = WR_counter[2] + 1;
WR_counter[3] = WR_counter[3] + 1;
// Auto Refresh
if (Aref_enable == 1'b1) begin
if (Debug) $display ("at time %t AREF : Auto Refresh", $time);
// Auto Refresh to Auto Refresh
if ($time - RC_chk < tRC) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRC violation during Auto Refresh", $time);
end
// Precharge to Auto Refresh
if ($time - RP_chk0 < tRP || $time - RP_chk1 < tRP || $time - RP_chk2 < tRP || $time - RP_chk3 < tRP) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRP violation during Auto Refresh", $time);
end
// Precharge to Refresh
if (Pc_b0 == 1'b0 || Pc_b1 == 1'b0 || Pc_b2 == 1'b0 || Pc_b3 == 1'b0) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: All banks must be Precharge before Auto Refresh", $time);
end
// Record Current tRC time
RC_chk = $time;
end
// Load Mode Register
if (Mode_reg_enable == 1'b1) begin
// Decode CAS Latency, Burst Length, Burst Type, and Write Burst Mode
if (Pc_b0 == 1'b1 && Pc_b1 == 1'b1 && Pc_b2 == 1'b1 && Pc_b3 == 1'b1) begin
Mode_reg = Addr;
if (Debug) begin
$display ("at time %t LMR : Load Mode Register", $time);
// CAS Latency
if (Addr[6 : 4] == 3'b010)
$display (" CAS Latency = 2");
else if (Addr[6 : 4] == 3'b011)
$display (" CAS Latency = 3");
else
$display (" CAS Latency = Reserved");
// Burst Length
if (Addr[2 : 0] == 3'b000)
$display (" Burst Length = 1");
else if (Addr[2 : 0] == 3'b001)
$display (" Burst Length = 2");
else if (Addr[2 : 0] == 3'b010)
$display (" Burst Length = 4");
else if (Addr[2 : 0] == 3'b011)
$display (" Burst Length = 8");
else if (Addr[3 : 0] == 4'b0111)
$display (" Burst Length = Full");
else
$display (" Burst Length = Reserved");
// Burst Type
if (Addr[3] == 1'b0)
$display (" Burst Type = Sequential");
else if (Addr[3] == 1'b1)
$display (" Burst Type = Interleaved");
else
$display (" Burst Type = Reserved");
// Write Burst Mode
if (Addr[9] == 1'b0)
$display (" Write Burst Mode = Programmed Burst Length");
else if (Addr[9] == 1'b1)
$display (" Write Burst Mode = Single Location Access");
else
$display (" Write Burst Mode = Reserved");
end
end else begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: all banks must be Precharge before Load Mode Register", $time);
end
// REF to LMR
if ($time - RC_chk < tRC) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRC violation during Load Mode Register", $time);
end
// LMR to LMR
if (MRD_chk < tMRD) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tMRD violation during Load Mode Register", $time);
end
MRD_chk = 0;
end
// Active Block (Latch Bank Address and Row Address)
if (Active_enable == 1'b1) begin
if (Ba == 2'b00 && Pc_b0 == 1'b1) begin
{Act_b0, Pc_b0} = 2'b10;
B0_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk0 = $time;
RAS_chk0 = $time;
if (Debug) $display ("at time %t ACT : Bank = 0 Row = %d", $time, Addr);
// Precharge to Activate Bank 0
if ($time - RP_chk0 < tRP) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRP violation during Activate bank 0", $time);
end
end else if (Ba == 2'b01 && Pc_b1 == 1'b1) begin
{Act_b1, Pc_b1} = 2'b10;
B1_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk1 = $time;
RAS_chk1 = $time;
if (Debug) $display ("at time %t ACT : Bank = 1 Row = %d", $time, Addr);
// Precharge to Activate Bank 1
if ($time - RP_chk1 < tRP) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRP violation during Activate bank 1", $time);
end
end else if (Ba == 2'b10 && Pc_b2 == 1'b1) begin
{Act_b2, Pc_b2} = 2'b10;
B2_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk2 = $time;
RAS_chk2 = $time;
if (Debug) $display ("at time %t ACT : Bank = 2 Row = %d", $time, Addr);
// Precharge to Activate Bank 2
if ($time - RP_chk2 < tRP) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRP violation during Activate bank 2", $time);
end
end else if (Ba == 2'b11 && Pc_b3 == 1'b1) begin
{Act_b3, Pc_b3} = 2'b10;
B3_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk3 = $time;
RAS_chk3 = $time;
if (Debug) $display ("at time %t ACT : Bank = 3 Row = %d", $time, Addr);
// Precharge to Activate Bank 3
if ($time - RP_chk3 < tRP) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRP violation during Activate bank 3", $time);
end
end else if (Ba == 2'b00 && Pc_b0 == 1'b0) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: Bank 0 is not Precharged.", $time);
end else if (Ba == 2'b01 && Pc_b1 == 1'b0) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: Bank 1 is not Precharged.", $time);
end else if (Ba == 2'b10 && Pc_b2 == 1'b0) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: Bank 2 is not Precharged.", $time);
end else if (Ba == 2'b11 && Pc_b3 == 1'b0) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: Bank 3 is not Precharged.", $time);
end
// Active Bank A to Active Bank B
if ((Previous_bank != Ba) && ($time - RRD_chk < tRRD)) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRRD violation during Activate bank = %d", $time, Ba);
end
// Load Mode Register to Active
if (MRD_chk < tMRD ) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tMRD violation during Activate bank = %d", $time, Ba);
end
// Auto Refresh to Activate
if ($time - RC_chk < tRC) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRC violation during Activate bank = %d", $time, Ba);
end
// Record variables for checking violation
RRD_chk = $time;
Previous_bank = Ba;
end
// Precharge Block
if (Prech_enable == 1'b1) begin
if (Addr[10] == 1'b1) begin
{Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b1111;
{Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000;
RP_chk0 = $time;
RP_chk1 = $time;
RP_chk2 = $time;
RP_chk3 = $time;
if (Debug) $display ("at time %t PRE : Bank = ALL",$time);
// Activate to Precharge all banks
if (($time - RAS_chk0 < tRAS) || ($time - RAS_chk1 < tRAS) ||
($time - RAS_chk2 < tRAS) || ($time - RAS_chk3 < tRAS)) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRAS violation during Precharge all bank", $time);
end
// tWR violation check for write
if (($time - WR_chk[0] < tWRp) || ($time - WR_chk[1] < tWRp) ||
($time - WR_chk[2] < tWRp) || ($time - WR_chk[3] < tWRp)) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tWR violation during Precharge all bank", $time);
end
end else if (Addr[10] == 1'b0) begin
if (Ba == 2'b00) begin
{Pc_b0, Act_b0} = 2'b10;
RP_chk0 = $time;
if (Debug) $display ("at time %t PRE : Bank = 0",$time);
// Activate to Precharge Bank 0
if ($time - RAS_chk0 < tRAS) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRAS violation during Precharge bank 0", $time);
end
end else if (Ba == 2'b01) begin
{Pc_b1, Act_b1} = 2'b10;
RP_chk1 = $time;
if (Debug) $display ("at time %t PRE : Bank = 1",$time);
// Activate to Precharge Bank 1
if ($time - RAS_chk1 < tRAS) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRAS violation during Precharge bank 1", $time);
end
end else if (Ba == 2'b10) begin
{Pc_b2, Act_b2} = 2'b10;
RP_chk2 = $time;
if (Debug) $display ("at time %t PRE : Bank = 2",$time);
// Activate to Precharge Bank 2
if ($time - RAS_chk2 < tRAS) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRAS violation during Precharge bank 2", $time);
end
end else if (Ba == 2'b11) begin
{Pc_b3, Act_b3} = 2'b10;
RP_chk3 = $time;
if (Debug) $display ("at time %t PRE : Bank = 3",$time);
// Activate to Precharge Bank 3
if ($time - RAS_chk3 < tRAS) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRAS violation during Precharge bank 3", $time);
end
end
// tWR violation check for write
if ($time - WR_chk[Ba] < tWRp) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tWR violation during Precharge bank %d", $time, Ba);
end
end
// Terminate a Write Immediately (if same bank or all banks)
if (Data_in_enable == 1'b1 && (Bank == Ba || Addr[10] == 1'b1)) begin
Data_in_enable = 1'b0;
end
// Precharge Command Pipeline for Read
if (Cas_latency_3 == 1'b1) begin
Command[2] = `PRECH;
Bank_precharge[2] = Ba;
A10_precharge[2] = Addr[10];
end else if (Cas_latency_2 == 1'b1) begin
Command[1] = `PRECH;
Bank_precharge[1] = Ba;
A10_precharge[1] = Addr[10];
end
end
// Burst terminate
if (Burst_term == 1'b1) begin
// Terminate a Write Immediately
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
end
// Terminate a Read Depend on CAS Latency
if (Cas_latency_3 == 1'b1) begin
Command[2] = `BST;
end else if (Cas_latency_2 == 1'b1) begin
Command[1] = `BST;
end
if (Debug) $display ("at time %t BST : Burst Terminate",$time);
end
// Read, Write, Column Latch
if (Read_enable == 1'b1 || Write_enable == 1'b1) begin
// Check to see if bank is open (ACT)
if ((Ba == 2'b00 && Pc_b0 == 1'b1) || (Ba == 2'b01 && Pc_b1 == 1'b1) ||
(Ba == 2'b10 && Pc_b2 == 1'b1) || (Ba == 2'b11 && Pc_b3 == 1'b1)) begin
//->tb.test_control.error_detected;
$display("at time %t ERROR: Cannot Read or Write - Bank %d is not Activated", $time, Ba);
end
// Activate to Read or Write
if ((Ba == 2'b00) && ($time - RCD_chk0 < tRCD))
begin
//->tb.test_control.error_detected;
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 0", $time);
end
if ((Ba == 2'b01) && ($time - RCD_chk1 < tRCD))
begin
//->tb.test_control.error_detected;
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 1", $time);
end
if ((Ba == 2'b10) && ($time - RCD_chk2 < tRCD))
begin
//->tb.test_control.error_detected;
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 2", $time);
end
if ((Ba == 2'b11) && ($time - RCD_chk3 < tRCD))
begin
//->tb.test_control.error_detected;
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 3", $time);
end
// Read Command
if (Read_enable == 1'b1) begin
// CAS Latency pipeline
if (Cas_latency_3 == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[2] = `READ_A;
end else begin
Command[2] = `READ;
end
Col_addr[2] = Addr;
Bank_addr[2] = Ba;
end else if (Cas_latency_2 == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[1] = `READ_A;
end else begin
Command[1] = `READ;
end
Col_addr[1] = Addr;
Bank_addr[1] = Ba;
end
// Read interrupt Write (terminate Write immediately)
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
end
// Write Command
end else if (Write_enable == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[0] = `WRITE_A;
end else begin
Command[0] = `WRITE;
end
Col_addr[0] = Addr;
Bank_addr[0] = Ba;
// Write interrupt Write (terminate Write immediately)
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
end
// Write interrupt Read (terminate Read immediately)
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
// Interrupting a Write with Autoprecharge
if (Auto_precharge[Bank] == 1'b1 && Write_precharge[Bank] == 1'b1) begin
RW_interrupt_write[Bank] = 1'b1;
if (Debug) $display ("at time %t NOTE : Read/Write Bank %d interrupt Write Bank %d with Autoprecharge", $time, Ba, Bank);
end
// Interrupting a Read with Autoprecharge
if (Auto_precharge[Bank] == 1'b1 && Read_precharge[Bank] == 1'b1) begin
RW_interrupt_read[Bank] = 1'b1;
if (Debug) $display ("at time %t NOTE : Read/Write Bank %d interrupt Read Bank %d with Autoprecharge", $time, Ba, Bank);
end
// Read or Write with Auto Precharge
if (Addr[10] == 1'b1) begin
Auto_precharge[Ba] = 1'b1;
Count_precharge[Ba] = 0;
if (Read_enable == 1'b1) begin
Read_precharge[Ba] = 1'b1;
end else if (Write_enable == 1'b1) begin
Write_precharge[Ba] = 1'b1;
end
end
end
// Read with Auto Precharge Calculation
// The device start internal precharge:
// 1. CAS Latency - 1 cycles before last burst
// and 2. Meet minimum tRAS requirement
// or 3. Interrupt by a Read or Write (with or without AutoPrecharge)
if ((Auto_precharge[0] == 1'b1) && (Read_precharge[0] == 1'b1)) begin
if ((($time - RAS_chk0 >= tRAS) && // Case 2
((Burst_length_1 == 1'b1 && Count_precharge[0] >= 1) || // Case 1
(Burst_length_2 == 1'b1 && Count_precharge[0] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[0] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[0] >= 8))) ||
(RW_interrupt_read[0] == 1'b1)) begin // Case 3
Pc_b0 = 1'b1;
Act_b0 = 1'b0;
RP_chk0 = $time;
Auto_precharge[0] = 1'b0;
Read_precharge[0] = 1'b0;
RW_interrupt_read[0] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time);
end
end
if ((Auto_precharge[1] == 1'b1) && (Read_precharge[1] == 1'b1)) begin
if ((($time - RAS_chk1 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[1] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[1] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[1] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[1] >= 8))) ||
(RW_interrupt_read[1] == 1'b1)) begin
Pc_b1 = 1'b1;
Act_b1 = 1'b0;
RP_chk1 = $time;
Auto_precharge[1] = 1'b0;
Read_precharge[1] = 1'b0;
RW_interrupt_read[1] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time);
end
end
if ((Auto_precharge[2] == 1'b1) && (Read_precharge[2] == 1'b1)) begin
if ((($time - RAS_chk2 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[2] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[2] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[2] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[2] >= 8))) ||
(RW_interrupt_read[2] == 1'b1)) begin
Pc_b2 = 1'b1;
Act_b2 = 1'b0;
RP_chk2 = $time;
Auto_precharge[2] = 1'b0;
Read_precharge[2] = 1'b0;
RW_interrupt_read[2] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time);
end
end
if ((Auto_precharge[3] == 1'b1) && (Read_precharge[3] == 1'b1)) begin
if ((($time - RAS_chk3 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[3] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[3] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[3] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[3] >= 8))) ||
(RW_interrupt_read[3] == 1'b1)) begin
Pc_b3 = 1'b1;
Act_b3 = 1'b0;
RP_chk3 = $time;
Auto_precharge[3] = 1'b0;
Read_precharge[3] = 1'b0;
RW_interrupt_read[3] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time);
end
end
// Internal Precharge or Bst
if (Command[0] == `PRECH) begin // Precharge terminate a read with same bank or all banks
if (Bank_precharge[0] == Bank || A10_precharge[0] == 1'b1) begin
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
end else if (Command[0] == `BST) begin // BST terminate a read to current bank
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
if (Data_out_enable == 1'b0) begin
Dq_reg <= #tOH {data_bits{1'bz}};
end
// Detect Read or Write command
if (Command[0] == `READ || Command[0] == `READ_A) begin
Bank = Bank_addr[0];
Col = Col_addr[0];
Col_brst = Col_addr[0];
if (Bank_addr[0] == 2'b00) begin
Row = B0_row_addr;
end else if (Bank_addr[0] == 2'b01) begin
Row = B1_row_addr;
end else if (Bank_addr[0] == 2'b10) begin
Row = B2_row_addr;
end else if (Bank_addr[0] == 2'b11) begin
Row = B3_row_addr;
end
Burst_counter = 0;
Data_in_enable = 1'b0;
Data_out_enable = 1'b1;
end else if (Command[0] == `WRITE || Command[0] == `WRITE_A) begin
Bank = Bank_addr[0];
Col = Col_addr[0];
Col_brst = Col_addr[0];
if (Bank_addr[0] == 2'b00) begin
Row = B0_row_addr;
end else if (Bank_addr[0] == 2'b01) begin
Row = B1_row_addr;
end else if (Bank_addr[0] == 2'b10) begin
Row = B2_row_addr;
end else if (Bank_addr[0] == 2'b11) begin
Row = B3_row_addr;
end
Burst_counter = 0;
Data_in_enable = 1'b1;
Data_out_enable = 1'b0;
end
// DQ buffer (Driver/Receiver)
if (Data_in_enable == 1'b1) begin // Writing Data to Memory
// Array buffer
if (Bank == 2'b00) Dq_dqm [15 : 0] = Bank0 [{Row, Col}];
if (Bank == 2'b01) Dq_dqm [15 : 0] = Bank1 [{Row, Col}];
if (Bank == 2'b10) Dq_dqm [15 : 0] = Bank2 [{Row, Col}];
if (Bank == 2'b11) Dq_dqm [15 : 0] = Bank3 [{Row, Col}];
// Dqm operation
if (Dqm[0] == 1'b0) Dq_dqm [ 7 : 0] = Dq [ 7 : 0];
if (Dqm[1] == 1'b0) Dq_dqm [15 : 8] = Dq [15 : 8];
// Write to memory
if (Bank == 2'b00) Bank0 [{Row, Col}] = Dq_dqm [15 : 0];
if (Bank == 2'b01) Bank1 [{Row, Col}] = Dq_dqm [15 : 0];
if (Bank == 2'b10) Bank2 [{Row, Col}] = Dq_dqm [15 : 0];
if (Bank == 2'b11) Bank3 [{Row, Col}] = Dq_dqm [15 : 0];
// Output result
if (Dqm == 2'b11) begin
if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col);
end else begin
if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = %h, Dqm = %b", $time, Bank, Row, Col, Dq_dqm, Dqm);
// Record tWR time and reset counter
WR_chk [Bank] = $time;
WR_counter [Bank] = 0;
end
// Advance burst counter subroutine
#tHZ Burst;
end else if (Data_out_enable == 1'b1) begin // Reading Data from Memory
// Array buffer
if (Bank == 2'b00) Dq_dqm [15 : 0] = Bank0 [{Row, Col}];
if (Bank == 2'b01) Dq_dqm [15 : 0] = Bank1 [{Row, Col}];
if (Bank == 2'b10) Dq_dqm [15 : 0] = Bank2 [{Row, Col}];
if (Bank == 2'b11) Dq_dqm [15 : 0] = Bank3 [{Row, Col}];
// Dqm operation
if (Dqm_reg0[0] == 1'b1) Dq_dqm [ 7 : 0] = 8'bz;
if (Dqm_reg0[1] == 1'b1) Dq_dqm [15 : 8] = 8'bz;
// Display result
Dq_reg [15 : 0] = #tAC Dq_dqm [15 : 0];
if (Dqm_reg0 == 2'b11) begin
if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col);
end else begin
if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = %h, Dqm = %b", $time, Bank, Row, Col, Dq_reg, Dqm_reg0);
end
// Advance burst counter subroutine
Burst;
end
end
// Write with Auto Precharge Calculation
// The device start internal precharge:
// 1. tWR Clock after last burst
// and 2. Meet minimum tRAS requirement
// or 3. Interrupt by a Read or Write (with or without AutoPrecharge)
always @ (WR_counter[0]) begin
if ((Auto_precharge[0] == 1'b1) && (Write_precharge[0] == 1'b1)) begin
if ((($time - RAS_chk0 >= tRAS) && // Case 2
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [0] >= 1) || // Case 1
(Burst_length_2 == 1'b1 && Count_precharge [0] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge [0] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge [0] >= 8))) ||
(RW_interrupt_write[0] == 1'b1 && WR_counter[0] >= 2)) begin // Case 3 (stop count when interrupt)
Auto_precharge[0] = 1'b0;
Write_precharge[0] = 1'b0;
RW_interrupt_write[0] = 1'b0;
#tWRa; // Wait for tWR
Pc_b0 = 1'b1;
Act_b0 = 1'b0;
RP_chk0 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time);
end
end
end
always @ (WR_counter[1]) begin
if ((Auto_precharge[1] == 1'b1) && (Write_precharge[1] == 1'b1)) begin
if ((($time - RAS_chk1 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [1] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge [1] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge [1] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge [1] >= 8))) ||
(RW_interrupt_write[1] == 1'b1 && WR_counter[1] >= 2)) begin
Auto_precharge[1] = 1'b0;
Write_precharge[1] = 1'b0;
RW_interrupt_write[1] = 1'b0;
#tWRa; // Wait for tWR
Pc_b1 = 1'b1;
Act_b1 = 1'b0;
RP_chk1 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time);
end
end
end
always @ (WR_counter[2]) begin
if ((Auto_precharge[2] == 1'b1) && (Write_precharge[2] == 1'b1)) begin
if ((($time - RAS_chk2 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [2] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge [2] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge [2] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge [2] >= 8))) ||
(RW_interrupt_write[2] == 1'b1 && WR_counter[2] >= 2)) begin
Auto_precharge[2] = 1'b0;
Write_precharge[2] = 1'b0;
RW_interrupt_write[2] = 1'b0;
#tWRa; // Wait for tWR
Pc_b2 = 1'b1;
Act_b2 = 1'b0;
RP_chk2 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time);
end
end
end
always @ (WR_counter[3]) begin
if ((Auto_precharge[3] == 1'b1) && (Write_precharge[3] == 1'b1)) begin
if ((($time - RAS_chk3 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [3] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge [3] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge [3] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge [3] >= 8))) ||
(RW_interrupt_write[3] == 1'b1 && WR_counter[3] >= 2)) begin
Auto_precharge[3] = 1'b0;
Write_precharge[3] = 1'b0;
RW_interrupt_write[3] = 1'b0;
#tWRa; // Wait for tWR
Pc_b3 = 1'b1;
Act_b3 = 1'b0;
RP_chk3 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time);
end
end
end
task Burst;
begin
// Advance Burst Counter
Burst_counter = Burst_counter + 1;
// Burst Type
if (Mode_reg[3] == 1'b0) begin // Sequential Burst
Col_temp = Col + 1;
end else if (Mode_reg[3] == 1'b1) begin // Interleaved Burst
Col_temp[2] = Burst_counter[2] ^ Col_brst[2];
Col_temp[1] = Burst_counter[1] ^ Col_brst[1];
Col_temp[0] = Burst_counter[0] ^ Col_brst[0];
end
// Burst Length
if (Burst_length_2) begin // Burst Length = 2
Col [0] = Col_temp [0];
end else if (Burst_length_4) begin // Burst Length = 4
Col [1 : 0] = Col_temp [1 : 0];
end else if (Burst_length_8) begin // Burst Length = 8
Col [2 : 0] = Col_temp [2 : 0];
end else begin // Burst Length = FULL
Col = Col_temp;
end
// Burst Read Single Write
if (Write_burst_mode == 1'b1) begin
Data_in_enable = 1'b0;
end
// Data Counter
if (Burst_length_1 == 1'b1) begin
if (Burst_counter >= 1) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_2 == 1'b1) begin
if (Burst_counter >= 2) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_4 == 1'b1) begin
if (Burst_counter >= 4) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_8 == 1'b1) begin
if (Burst_counter >= 8) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end
end
endtask
// Timing Parameters for -75 (PC133) and CAS Latency = 2
specify
specparam
tAH = 0.8, // Addr, Ba Hold Time
tAS = 1.5, // Addr, Ba Setup Time
tCH = 2.5, // Clock High-Level Width
tCL = 2.5, // Clock Low-Level Width
tCK = 10, // Clock Cycle Time
tDH = 0.8, // Data-in Hold Time
tDS = 1.5, // Data-in Setup Time
tCKH = 0.8, // CKE Hold Time
tCKS = 1.5, // CKE Setup Time
tCMH = 0.8, // CS#, RAS#, CAS#, WE#, DQM# Hold Time
tCMS = 1.5; // CS#, RAS#, CAS#, WE#, DQM# Setup Time
$width (posedge Clk, tCH);
$width (negedge Clk, tCL);
$period (negedge Clk, tCK);
$period (posedge Clk, tCK);
$setuphold(posedge Clk, Cke, tCKS, tCKH);
$setuphold(posedge Clk, Cs_n, tCMS, tCMH);
$setuphold(posedge Clk, Cas_n, tCMS, tCMH);
$setuphold(posedge Clk, Ras_n, tCMS, tCMH);
$setuphold(posedge Clk, We_n, tCMS, tCMH);
$setuphold(posedge Clk, Addr, tAS, tAH);
$setuphold(posedge Clk, Ba, tAS, tAH);
$setuphold(posedge Clk, Dqm, tCMS, tCMH);
$setuphold(posedge Dq_chk, Dq, tDS, tDH);
endspecify
endmodule

View File

@ -0,0 +1,964 @@
/****************************************************************************************
*
* File Name: MT48LC8M8A2.V
* Version: 0.0f
* Date: July 8th, 1999
* Model: BUS Functional
* Simulator: Model Technology (PC version 5.2e PE)
*
* Dependencies: None
*
* Author: Son P. Huynh
* Email: sphuynh@micron.com
* Phone: (208) 368-3825
* Company: Micron Technology, Inc.
* Model: MT48LC8M16A2 (2Meg x 8 x 4 Banks)
*
* Description: Micron 128Mb SDRAM Verilog model
*
* Limitation: - Doesn't check for 4096 cycle refresh
*
* Note: - Set simulator resolution to "ps" accuracy
* - Set Debug = 0 to disable $display messages
*
* Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY
* WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
* A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT.
*
* Copyright © 1998 Micron Semiconductor Products, Inc.
* All rights researved
*
* Rev Author Phone Date Changes
* ---- ---------------------------- ---------- ---------------------------------------
* 0.0f Son Huynh 208-368-3825 07/08/1999 - Fix tWR = 1 Clk + 7.5 ns (Auto)
* Micron Technology Inc. - Fix tWR = 15 ns (Manual)
* - Fix tRP (Autoprecharge to AutoRefresh)
*
* 0.0a Son Huynh 208-368-3825 05/13/1998 - First Release (from 64Mb rev 0.0e)
* Micron Technology Inc.
****************************************************************************************/
`timescale 1ns / 100ps
module mt48lc8m8a2 (Dq, Addr, Ba, Clk, Cke, Cs_n, Ras_n, Cas_n, We_n, Dqm);
parameter addr_bits = 12;
parameter data_bits = 8;
parameter col_bits = 9;
parameter mem_sizes = 2097151; // 2 Meg
inout [data_bits - 1 : 0] Dq;
input [addr_bits - 1 : 0] Addr;
input [1 : 0] Ba;
input Clk;
input Cke;
input Cs_n;
input Ras_n;
input Cas_n;
input We_n;
input [0 : 0] Dqm;
reg [data_bits - 1 : 0] Bank0 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank1 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank2 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank3 [0 : mem_sizes];
reg [1 : 0] Bank_addr [0 : 3]; // Bank Address Pipeline
reg [col_bits - 1 : 0] Col_addr [0 : 3]; // Column Address Pipeline
reg [3 : 0] Command [0 : 3]; // Command Operation Pipeline
reg [0 : 0] Dqm_reg0, Dqm_reg1; // DQM Operation Pipeline
reg [addr_bits - 1 : 0] B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr;
reg [addr_bits - 1 : 0] Mode_reg;
reg [data_bits - 1 : 0] Dq_reg, Dq_dqm;
reg [col_bits - 1 : 0] Col_temp, Burst_counter;
reg Act_b0, Act_b1, Act_b2, Act_b3; // Bank Activate
reg Pc_b0, Pc_b1, Pc_b2, Pc_b3; // Bank Precharge
reg [1 : 0] Bank_precharge [0 : 3]; // Precharge Command
reg A10_precharge [0 : 3]; // Addr[10] = 1 (All banks)
reg Auto_precharge [0 : 3]; // RW AutoPrecharge (Bank)
reg Read_precharge [0 : 3]; // R AutoPrecharge
reg Write_precharge [0 : 3]; // W AutoPrecharge
integer Count_precharge [0 : 3]; // RW AutoPrecharge (Counter)
reg RW_interrupt_read [0 : 3]; // RW Interrupt Read with Auto Precharge
reg RW_interrupt_write [0 : 3]; // RW Interrupt Write with Auto Precharge
reg Data_in_enable;
reg Data_out_enable;
reg [1 : 0] Bank, Previous_bank;
reg [addr_bits - 1 : 0] Row;
reg [col_bits - 1 : 0] Col, Col_brst;
// Internal system clock
reg CkeZ, Sys_clk;
// Commands Decode
wire Active_enable = ~Cs_n & ~Ras_n & Cas_n & We_n;
wire Aref_enable = ~Cs_n & ~Ras_n & ~Cas_n & We_n;
wire Burst_term = ~Cs_n & Ras_n & Cas_n & ~We_n;
wire Mode_reg_enable = ~Cs_n & ~Ras_n & ~Cas_n & ~We_n;
wire Prech_enable = ~Cs_n & ~Ras_n & Cas_n & ~We_n;
wire Read_enable = ~Cs_n & Ras_n & ~Cas_n & We_n;
wire Write_enable = ~Cs_n & Ras_n & ~Cas_n & ~We_n;
// Burst Length Decode
wire Burst_length_1 = ~Mode_reg[2] & ~Mode_reg[1] & ~Mode_reg[0];
wire Burst_length_2 = ~Mode_reg[2] & ~Mode_reg[1] & Mode_reg[0];
wire Burst_length_4 = ~Mode_reg[2] & Mode_reg[1] & ~Mode_reg[0];
wire Burst_length_8 = ~Mode_reg[2] & Mode_reg[1] & Mode_reg[0];
// CAS Latency Decode
wire Cas_latency_2 = ~Mode_reg[6] & Mode_reg[5] & ~Mode_reg[4];
wire Cas_latency_3 = ~Mode_reg[6] & Mode_reg[5] & Mode_reg[4];
`ifdef VERBOSE
wire Debug = 1'b1; // Debug messages : 1 = On
`else
wire Debug = 1'b0; // Debug messages : 1 = On
`endif
// Write Burst Mode
wire Write_burst_mode = Mode_reg[9];
wire Dq_chk = Sys_clk & Data_in_enable; // Check setup/hold time for DQ
assign Dq = Dq_reg; // DQ buffer
// Commands Operation
`define ACT 0
`define NOP 1
`define READ 2
`define READ_A 3
`define SDRAM_WRITE 4
`define WRITE_A 5
`define SDRAM_PRECH 6
`define SDRAM_A_REF 7
`define SDRAM_BST 8
`define SDRAM_LMR 9
// Timing Parameters for -75 (PC133) and CAS Latency = 2
parameter tAC = 6.0;
parameter tHZ = 7.0;
parameter tOH = 2.7;
parameter tMRD = 2.0; // 2 Clk Cycles
parameter tRAS = 44.0;
parameter tRC = 66.0;
parameter tRCD = 20.0;
parameter tRP = 20.0;
parameter tRRD = 15.0;
parameter tWRa = 7.5; // A2 Version - Auto precharge mode only (1 Clk + 7.5 ns)
parameter tWRp = 15.0; // A2 Version - Precharge mode only (15 ns)
// Timing Check variable
integer MRD_chk;
integer WR_counter [0 : 3];
time WR_chk [0 : 3];
time RC_chk, RRD_chk;
time RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3;
time RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3;
time RP_chk0, RP_chk1, RP_chk2, RP_chk3;
initial begin
Dq_reg = {data_bits{1'bz}};
{Data_in_enable, Data_out_enable} = 0;
{Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000;
{Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b0000;
{WR_chk[0], WR_chk[1], WR_chk[2], WR_chk[3]} = 0;
{WR_counter[0], WR_counter[1], WR_counter[2], WR_counter[3]} = 0;
{RW_interrupt_read[0], RW_interrupt_read[1], RW_interrupt_read[2], RW_interrupt_read[3]} = 0;
{RW_interrupt_write[0], RW_interrupt_write[1], RW_interrupt_write[2], RW_interrupt_write[3]} = 0;
{MRD_chk, RC_chk, RRD_chk} = 0;
{RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3} = 0;
{RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3} = 0;
{RP_chk0, RP_chk1, RP_chk2, RP_chk3} = 0;
$timeformat (-9, 0, " ns", 12);
//$readmemh("bank0.txt", Bank0);
//$readmemh("bank1.txt", Bank1);
//$readmemh("bank2.txt", Bank2);
//$readmemh("bank3.txt", Bank3);
end
// System clock generator
always begin
@ (posedge Clk) begin
Sys_clk = CkeZ;
CkeZ = Cke;
end
@ (negedge Clk) begin
Sys_clk = 1'b0;
end
end
always @ (posedge Sys_clk) begin
// Internal Commamd Pipelined
Command[0] = Command[1];
Command[1] = Command[2];
Command[2] = Command[3];
Command[3] = `NOP;
Col_addr[0] = Col_addr[1];
Col_addr[1] = Col_addr[2];
Col_addr[2] = Col_addr[3];
Col_addr[3] = {col_bits{1'b0}};
Bank_addr[0] = Bank_addr[1];
Bank_addr[1] = Bank_addr[2];
Bank_addr[2] = Bank_addr[3];
Bank_addr[3] = 2'b0;
Bank_precharge[0] = Bank_precharge[1];
Bank_precharge[1] = Bank_precharge[2];
Bank_precharge[2] = Bank_precharge[3];
Bank_precharge[3] = 2'b0;
A10_precharge[0] = A10_precharge[1];
A10_precharge[1] = A10_precharge[2];
A10_precharge[2] = A10_precharge[3];
A10_precharge[3] = 1'b0;
// Dqm pipeline for Read
Dqm_reg0 = Dqm_reg1;
Dqm_reg1 = Dqm;
// Read or Write with Auto Precharge Counter
if (Auto_precharge[0] == 1'b1) begin
Count_precharge[0] = Count_precharge[0] + 1;
end
if (Auto_precharge[1] == 1'b1) begin
Count_precharge[1] = Count_precharge[1] + 1;
end
if (Auto_precharge[2] == 1'b1) begin
Count_precharge[2] = Count_precharge[2] + 1;
end
if (Auto_precharge[3] == 1'b1) begin
Count_precharge[3] = Count_precharge[3] + 1;
end
// tMRD Counter
MRD_chk = MRD_chk + 1;
// tWR Counter for Write
WR_counter[0] = WR_counter[0] + 1;
WR_counter[1] = WR_counter[1] + 1;
WR_counter[2] = WR_counter[2] + 1;
WR_counter[3] = WR_counter[3] + 1;
// Auto Refresh
if (Aref_enable == 1'b1) begin
if (Debug) $display ("at time %t AREF : Auto Refresh", $time);
// Auto Refresh to Auto Refresh
if ($time - RC_chk < tRC) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRC violation during Auto Refresh", $time);
end
// Precharge to Auto Refresh
if ($time - RP_chk0 < tRP || $time - RP_chk1 < tRP || $time - RP_chk2 < tRP || $time - RP_chk3 < tRP) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRP violation during Auto Refresh", $time);
end
// Precharge to Refresh
if (Pc_b0 == 1'b0 || Pc_b1 == 1'b0 || Pc_b2 == 1'b0 || Pc_b3 == 1'b0) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: All banks must be Precharge before Auto Refresh", $time);
end
// Record Current tRC time
RC_chk = $time;
end
// Load Mode Register
if (Mode_reg_enable == 1'b1) begin
// Decode CAS Latency, Burst Length, Burst Type, and Write Burst Mode
if (Pc_b0 == 1'b1 && Pc_b1 == 1'b1 && Pc_b2 == 1'b1 && Pc_b3 == 1'b1) begin
Mode_reg = Addr;
if (Debug) begin
$display ("at time %t LMR : Load Mode Register", $time);
// CAS Latency
if (Addr[6 : 4] == 3'b010)
$display (" CAS Latency = 2");
else if (Addr[6 : 4] == 3'b011)
$display (" CAS Latency = 3");
else
$display (" CAS Latency = Reserved");
// Burst Length
if (Addr[2 : 0] == 3'b000)
$display (" Burst Length = 1");
else if (Addr[2 : 0] == 3'b001)
$display (" Burst Length = 2");
else if (Addr[2 : 0] == 3'b010)
$display (" Burst Length = 4");
else if (Addr[2 : 0] == 3'b011)
$display (" Burst Length = 8");
else if (Addr[3 : 0] == 4'b0111)
$display (" Burst Length = Full");
else
$display (" Burst Length = Reserved");
// Burst Type
if (Addr[3] == 1'b0)
$display (" Burst Type = Sequential");
else if (Addr[3] == 1'b1)
$display (" Burst Type = Interleaved");
else
$display (" Burst Type = Reserved");
// Write Burst Mode
if (Addr[9] == 1'b0)
$display (" Write Burst Mode = Programmed Burst Length");
else if (Addr[9] == 1'b1)
$display (" Write Burst Mode = Single Location Access");
else
$display (" Write Burst Mode = Reserved");
end
end else begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: all banks must be Precharge before Load Mode Register", $time);
end
// REF to LMR
if ($time - RC_chk < tRC) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRC violation during Load Mode Register", $time);
end
// LMR to LMR
if (MRD_chk < tMRD) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tMRD violation during Load Mode Register", $time);
end
MRD_chk = 0;
end
// Active Block (Latch Bank Address and Row Address)
if (Active_enable == 1'b1) begin
if (Ba == 2'b00 && Pc_b0 == 1'b1) begin
{Act_b0, Pc_b0} = 2'b10;
B0_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk0 = $time;
RAS_chk0 = $time;
if (Debug) $display ("at time %t ACT : Bank = 0 Row = %d", $time, Addr);
// Precharge to Activate Bank 0
if ($time - RP_chk0 < tRP) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRP violation during Activate bank 0", $time);
end
end else if (Ba == 2'b01 && Pc_b1 == 1'b1) begin
{Act_b1, Pc_b1} = 2'b10;
B1_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk1 = $time;
RAS_chk1 = $time;
if (Debug) $display ("at time %t ACT : Bank = 1 Row = %d", $time, Addr);
// Precharge to Activate Bank 1
if ($time - RP_chk1 < tRP) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRP violation during Activate bank 1", $time);
end
end else if (Ba == 2'b10 && Pc_b2 == 1'b1) begin
{Act_b2, Pc_b2} = 2'b10;
B2_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk2 = $time;
RAS_chk2 = $time;
if (Debug) $display ("at time %t ACT : Bank = 2 Row = %d", $time, Addr);
// Precharge to Activate Bank 2
if ($time - RP_chk2 < tRP) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRP violation during Activate bank 2", $time);
end
end else if (Ba == 2'b11 && Pc_b3 == 1'b1) begin
{Act_b3, Pc_b3} = 2'b10;
B3_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk3 = $time;
RAS_chk3 = $time;
if (Debug) $display ("at time %t ACT : Bank = 3 Row = %d", $time, Addr);
// Precharge to Activate Bank 3
if ($time - RP_chk3 < tRP) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRP violation during Activate bank 3", $time);
end
end else if (Ba == 2'b00 && Pc_b0 == 1'b0) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: Bank 0 is not Precharged.", $time);
end else if (Ba == 2'b01 && Pc_b1 == 1'b0) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: Bank 1 is not Precharged.", $time);
end else if (Ba == 2'b10 && Pc_b2 == 1'b0) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: Bank 2 is not Precharged.", $time);
end else if (Ba == 2'b11 && Pc_b3 == 1'b0) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: Bank 3 is not Precharged.", $time);
end
// Active Bank A to Active Bank B
if ((Previous_bank != Ba) && ($time - RRD_chk < tRRD)) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRRD violation during Activate bank = %d", $time, Ba);
end
// Load Mode Register to Active
if (MRD_chk < tMRD ) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tMRD violation during Activate bank = %d", $time, Ba);
end
// Auto Refresh to Activate
if ($time - RC_chk < tRC) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRC violation during Activate bank = %d", $time, Ba);
end
// Record variables for checking violation
RRD_chk = $time;
Previous_bank = Ba;
end
// Precharge Block
if (Prech_enable == 1'b1) begin
if (Addr[10] == 1'b1) begin
{Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b1111;
{Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000;
RP_chk0 = $time;
RP_chk1 = $time;
RP_chk2 = $time;
RP_chk3 = $time;
if (Debug) $display ("at time %t PRE : Bank = ALL",$time);
// Activate to Precharge all banks
if (($time - RAS_chk0 < tRAS) || ($time - RAS_chk1 < tRAS) ||
($time - RAS_chk2 < tRAS) || ($time - RAS_chk3 < tRAS)) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRAS violation during Precharge all bank", $time);
end
// tWR violation check for write
if (($time - WR_chk[0] < tWRp) || ($time - WR_chk[1] < tWRp) ||
($time - WR_chk[2] < tWRp) || ($time - WR_chk[3] < tWRp)) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tWR violation during Precharge all bank", $time);
end
end else if (Addr[10] == 1'b0) begin
if (Ba == 2'b00) begin
{Pc_b0, Act_b0} = 2'b10;
RP_chk0 = $time;
if (Debug) $display ("at time %t PRE : Bank = 0",$time);
// Activate to Precharge Bank 0
if ($time - RAS_chk0 < tRAS) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRAS violation during Precharge bank 0", $time);
end
end else if (Ba == 2'b01) begin
{Pc_b1, Act_b1} = 2'b10;
RP_chk1 = $time;
if (Debug) $display ("at time %t PRE : Bank = 1",$time);
// Activate to Precharge Bank 1
if ($time - RAS_chk1 < tRAS) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRAS violation during Precharge bank 1", $time);
end
end else if (Ba == 2'b10) begin
{Pc_b2, Act_b2} = 2'b10;
RP_chk2 = $time;
if (Debug) $display ("at time %t PRE : Bank = 2",$time);
// Activate to Precharge Bank 2
if ($time - RAS_chk2 < tRAS) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRAS violation during Precharge bank 2", $time);
end
end else if (Ba == 2'b11) begin
{Pc_b3, Act_b3} = 2'b10;
RP_chk3 = $time;
if (Debug) $display ("at time %t PRE : Bank = 3",$time);
// Activate to Precharge Bank 3
if ($time - RAS_chk3 < tRAS) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRAS violation during Precharge bank 3", $time);
end
end
// tWR violation check for write
if ($time - WR_chk[Ba] < tWRp) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tWR violation during Precharge bank %d", $time, Ba);
end
end
// Terminate a Write Immediately (if same bank or all banks)
if (Data_in_enable == 1'b1 && (Bank == Ba || Addr[10] == 1'b1)) begin
Data_in_enable = 1'b0;
end
// Precharge Command Pipeline for Read
if (Cas_latency_3 == 1'b1) begin
Command[2] = `SDRAM_PRECH;
Bank_precharge[2] = Ba;
A10_precharge[2] = Addr[10];
end else if (Cas_latency_2 == 1'b1) begin
Command[1] = `SDRAM_PRECH;
Bank_precharge[1] = Ba;
A10_precharge[1] = Addr[10];
end
end
// Burst terminate
if (Burst_term == 1'b1) begin
// Terminate a Write Immediately
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
end
// Terminate a Read Depend on CAS Latency
if (Cas_latency_3 == 1'b1) begin
Command[2] = `SDRAM_BST;
end else if (Cas_latency_2 == 1'b1) begin
Command[1] = `SDRAM_BST;
end
if (Debug) $display ("at time %t BST : Burst Terminate",$time);
end
// Read, Write, Column Latch
if (Read_enable == 1'b1 || Write_enable == 1'b1) begin
// Check to see if bank is open (ACT)
if ((Ba == 2'b00 && Pc_b0 == 1'b1) || (Ba == 2'b01 && Pc_b1 == 1'b1) ||
(Ba == 2'b10 && Pc_b2 == 1'b1) || (Ba == 2'b11 && Pc_b3 == 1'b1)) begin
//->tb.test_control.error_detected;
$display("at time %t ERROR: Cannot Read or Write - Bank %d is not Activated", $time, Ba);
end
// Activate to Read or Write
if ((Ba == 2'b00) && ($time - RCD_chk0 < tRCD))
begin
//->tb.test_control.error_detected;
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 0", $time);
end
if ((Ba == 2'b01) && ($time - RCD_chk1 < tRCD))
begin
//->tb.test_control.error_detected;
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 1", $time);
end
if ((Ba == 2'b10) && ($time - RCD_chk2 < tRCD))
begin
//->tb.test_control.error_detected;
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 2", $time);
end
if ((Ba == 2'b11) && ($time - RCD_chk3 < tRCD))
begin
//->tb.test_control.error_detected;
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 3", $time);
end
// Read Command
if (Read_enable == 1'b1) begin
// CAS Latency pipeline
if (Cas_latency_3 == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[2] = `READ_A;
end else begin
Command[2] = `READ;
end
Col_addr[2] = Addr;
Bank_addr[2] = Ba;
end else if (Cas_latency_2 == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[1] = `READ_A;
end else begin
Command[1] = `READ;
end
Col_addr[1] = Addr;
Bank_addr[1] = Ba;
end
// Read interrupt Write (terminate Write immediately)
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
end
// Write Command
end else if (Write_enable == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[0] = `WRITE_A;
end else begin
Command[0] = `SDRAM_WRITE;
end
Col_addr[0] = Addr;
Bank_addr[0] = Ba;
// Write interrupt Write (terminate Write immediately)
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
end
// Write interrupt Read (terminate Read immediately)
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
// Interrupting a Write with Autoprecharge
if (Auto_precharge[Bank] == 1'b1 && Write_precharge[Bank] == 1'b1) begin
RW_interrupt_write[Bank] = 1'b1;
if (Debug) $display ("at time %t NOTE : Read/Write Bank %d interrupt Write Bank %d with Autoprecharge", $time, Ba, Bank);
end
// Interrupting a Read with Autoprecharge
if (Auto_precharge[Bank] == 1'b1 && Read_precharge[Bank] == 1'b1) begin
RW_interrupt_read[Bank] = 1'b1;
if (Debug) $display ("at time %t NOTE : Read/Write Bank %d interrupt Read Bank %d with Autoprecharge", $time, Ba, Bank);
end
// Read or Write with Auto Precharge
if (Addr[10] == 1'b1) begin
Auto_precharge[Ba] = 1'b1;
Count_precharge[Ba] = 0;
if (Read_enable == 1'b1) begin
Read_precharge[Ba] = 1'b1;
end else if (Write_enable == 1'b1) begin
Write_precharge[Ba] = 1'b1;
end
end
end
// Read with Auto Precharge Calculation
// The device start internal precharge:
// 1. CAS Latency - 1 cycles before last burst
// and 2. Meet minimum tRAS requirement
// or 3. Interrupt by a Read or Write (with or without AutoPrecharge)
if ((Auto_precharge[0] == 1'b1) && (Read_precharge[0] == 1'b1)) begin
if ((($time - RAS_chk0 >= tRAS) && // Case 2
((Burst_length_1 == 1'b1 && Count_precharge[0] >= 1) || // Case 1
(Burst_length_2 == 1'b1 && Count_precharge[0] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[0] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[0] >= 8))) ||
(RW_interrupt_read[0] == 1'b1)) begin // Case 3
Pc_b0 = 1'b1;
Act_b0 = 1'b0;
RP_chk0 = $time;
Auto_precharge[0] = 1'b0;
Read_precharge[0] = 1'b0;
RW_interrupt_read[0] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time);
end
end
if ((Auto_precharge[1] == 1'b1) && (Read_precharge[1] == 1'b1)) begin
if ((($time - RAS_chk1 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[1] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[1] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[1] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[1] >= 8))) ||
(RW_interrupt_read[1] == 1'b1)) begin
Pc_b1 = 1'b1;
Act_b1 = 1'b0;
RP_chk1 = $time;
Auto_precharge[1] = 1'b0;
Read_precharge[1] = 1'b0;
RW_interrupt_read[1] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time);
end
end
if ((Auto_precharge[2] == 1'b1) && (Read_precharge[2] == 1'b1)) begin
if ((($time - RAS_chk2 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[2] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[2] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[2] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[2] >= 8))) ||
(RW_interrupt_read[2] == 1'b1)) begin
Pc_b2 = 1'b1;
Act_b2 = 1'b0;
RP_chk2 = $time;
Auto_precharge[2] = 1'b0;
Read_precharge[2] = 1'b0;
RW_interrupt_read[2] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time);
end
end
if ((Auto_precharge[3] == 1'b1) && (Read_precharge[3] == 1'b1)) begin
if ((($time - RAS_chk3 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[3] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[3] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[3] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[3] >= 8))) ||
(RW_interrupt_read[3] == 1'b1)) begin
Pc_b3 = 1'b1;
Act_b3 = 1'b0;
RP_chk3 = $time;
Auto_precharge[3] = 1'b0;
Read_precharge[3] = 1'b0;
RW_interrupt_read[3] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time);
end
end
// Internal Precharge or Bst
if (Command[0] == `SDRAM_PRECH) begin // Precharge terminate a read with same bank or all banks
if (Bank_precharge[0] == Bank || A10_precharge[0] == 1'b1) begin
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
end else if (Command[0] == `SDRAM_BST) begin // BST terminate a read to current bank
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
if (Data_out_enable == 1'b0) begin
Dq_reg <= #tOH {data_bits{1'bz}};
end
// Detect Read or Write command
if (Command[0] == `READ || Command[0] == `READ_A) begin
Bank = Bank_addr[0];
Col = Col_addr[0];
Col_brst = Col_addr[0];
if (Bank_addr[0] == 2'b00) begin
Row = B0_row_addr;
end else if (Bank_addr[0] == 2'b01) begin
Row = B1_row_addr;
end else if (Bank_addr[0] == 2'b10) begin
Row = B2_row_addr;
end else if (Bank_addr[0] == 2'b11) begin
Row = B3_row_addr;
end
Burst_counter = 0;
Data_in_enable = 1'b0;
Data_out_enable = 1'b1;
end else if (Command[0] == `SDRAM_WRITE || Command[0] == `WRITE_A) begin
Bank = Bank_addr[0];
Col = Col_addr[0];
Col_brst = Col_addr[0];
if (Bank_addr[0] == 2'b00) begin
Row = B0_row_addr;
end else if (Bank_addr[0] == 2'b01) begin
Row = B1_row_addr;
end else if (Bank_addr[0] == 2'b10) begin
Row = B2_row_addr;
end else if (Bank_addr[0] == 2'b11) begin
Row = B3_row_addr;
end
Burst_counter = 0;
Data_in_enable = 1'b1;
Data_out_enable = 1'b0;
end
// DQ buffer (Driver/Receiver)
if (Data_in_enable == 1'b1) begin // Writing Data to Memory
// Array buffer
if (Bank == 2'b00) Dq_dqm [15 : 0] = Bank0 [{Row, Col}];
if (Bank == 2'b01) Dq_dqm [15 : 0] = Bank1 [{Row, Col}];
if (Bank == 2'b10) Dq_dqm [15 : 0] = Bank2 [{Row, Col}];
if (Bank == 2'b11) Dq_dqm [15 : 0] = Bank3 [{Row, Col}];
// Dqm operation
if (Dqm[0] == 1'b0) Dq_dqm [ 7 : 0] = Dq [ 7 : 0];
// Write to memory
if (Bank == 2'b00) Bank0 [{Row, Col}] = Dq_dqm [15 : 0];
if (Bank == 2'b01) Bank1 [{Row, Col}] = Dq_dqm [15 : 0];
if (Bank == 2'b10) Bank2 [{Row, Col}] = Dq_dqm [15 : 0];
if (Bank == 2'b11) Bank3 [{Row, Col}] = Dq_dqm [15 : 0];
// Output result
if (Dqm == 1'b1) begin
if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col);
end else begin
if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = %h, Dqm = %b", $time, Bank, Row, Col, Dq_dqm, Dqm);
// Record tWR time and reset counter
WR_chk [Bank] = $time;
WR_counter [Bank] = 0;
end
// Advance burst counter subroutine
#tHZ Burst;
end else if (Data_out_enable == 1'b1) begin // Reading Data from Memory
// Array buffer
if (Bank == 2'b00) Dq_dqm [15 : 0] = Bank0 [{Row, Col}];
if (Bank == 2'b01) Dq_dqm [15 : 0] = Bank1 [{Row, Col}];
if (Bank == 2'b10) Dq_dqm [15 : 0] = Bank2 [{Row, Col}];
if (Bank == 2'b11) Dq_dqm [15 : 0] = Bank3 [{Row, Col}];
// Dqm operation
if (Dqm_reg0[0] == 1'b1) Dq_dqm [ 7 : 0] = 8'bz;
// Display result
Dq_reg [15 : 0] = #tAC Dq_dqm [15 : 0];
if (Dqm_reg0 == 1'b1) begin
if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col);
end else begin
if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = %h, Dqm = %b", $time, Bank, Row, Col, Dq_reg, Dqm_reg0);
end
// Advance burst counter subroutine
Burst;
end
end
// Write with Auto Precharge Calculation
// The device start internal precharge:
// 1. tWR Clock after last burst
// and 2. Meet minimum tRAS requirement
// or 3. Interrupt by a Read or Write (with or without AutoPrecharge)
always @ (WR_counter[0]) begin
if ((Auto_precharge[0] == 1'b1) && (Write_precharge[0] == 1'b1)) begin
if ((($time - RAS_chk0 >= tRAS) && // Case 2
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [0] >= 1) || // Case 1
(Burst_length_2 == 1'b1 && Count_precharge [0] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge [0] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge [0] >= 8))) ||
(RW_interrupt_write[0] == 1'b1 && WR_counter[0] >= 2)) begin // Case 3 (stop count when interrupt)
Auto_precharge[0] = 1'b0;
Write_precharge[0] = 1'b0;
RW_interrupt_write[0] = 1'b0;
#tWRa; // Wait for tWR
Pc_b0 = 1'b1;
Act_b0 = 1'b0;
RP_chk0 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time);
end
end
end
always @ (WR_counter[1]) begin
if ((Auto_precharge[1] == 1'b1) && (Write_precharge[1] == 1'b1)) begin
if ((($time - RAS_chk1 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [1] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge [1] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge [1] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge [1] >= 8))) ||
(RW_interrupt_write[1] == 1'b1 && WR_counter[1] >= 2)) begin
Auto_precharge[1] = 1'b0;
Write_precharge[1] = 1'b0;
RW_interrupt_write[1] = 1'b0;
#tWRa; // Wait for tWR
Pc_b1 = 1'b1;
Act_b1 = 1'b0;
RP_chk1 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time);
end
end
end
always @ (WR_counter[2]) begin
if ((Auto_precharge[2] == 1'b1) && (Write_precharge[2] == 1'b1)) begin
if ((($time - RAS_chk2 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [2] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge [2] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge [2] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge [2] >= 8))) ||
(RW_interrupt_write[2] == 1'b1 && WR_counter[2] >= 2)) begin
Auto_precharge[2] = 1'b0;
Write_precharge[2] = 1'b0;
RW_interrupt_write[2] = 1'b0;
#tWRa; // Wait for tWR
Pc_b2 = 1'b1;
Act_b2 = 1'b0;
RP_chk2 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time);
end
end
end
always @ (WR_counter[3]) begin
if ((Auto_precharge[3] == 1'b1) && (Write_precharge[3] == 1'b1)) begin
if ((($time - RAS_chk3 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [3] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge [3] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge [3] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge [3] >= 8))) ||
(RW_interrupt_write[3] == 1'b1 && WR_counter[3] >= 2)) begin
Auto_precharge[3] = 1'b0;
Write_precharge[3] = 1'b0;
RW_interrupt_write[3] = 1'b0;
#tWRa; // Wait for tWR
Pc_b3 = 1'b1;
Act_b3 = 1'b0;
RP_chk3 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time);
end
end
end
task Burst;
begin
// Advance Burst Counter
Burst_counter = Burst_counter + 1;
// Burst Type
if (Mode_reg[3] == 1'b0) begin // Sequential Burst
Col_temp = Col + 1;
end else if (Mode_reg[3] == 1'b1) begin // Interleaved Burst
Col_temp[2] = Burst_counter[2] ^ Col_brst[2];
Col_temp[1] = Burst_counter[1] ^ Col_brst[1];
Col_temp[0] = Burst_counter[0] ^ Col_brst[0];
end
// Burst Length
if (Burst_length_2) begin // Burst Length = 2
Col [0] = Col_temp [0];
end else if (Burst_length_4) begin // Burst Length = 4
Col [1 : 0] = Col_temp [1 : 0];
end else if (Burst_length_8) begin // Burst Length = 8
Col [2 : 0] = Col_temp [2 : 0];
end else begin // Burst Length = FULL
Col = Col_temp;
end
// Burst Read Single Write
if (Write_burst_mode == 1'b1) begin
Data_in_enable = 1'b0;
end
// Data Counter
if (Burst_length_1 == 1'b1) begin
if (Burst_counter >= 1) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_2 == 1'b1) begin
if (Burst_counter >= 2) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_4 == 1'b1) begin
if (Burst_counter >= 4) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_8 == 1'b1) begin
if (Burst_counter >= 8) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end
end
endtask
// Timing Parameters for -75 (PC133) and CAS Latency = 2
specify
specparam
tAH = 0.8, // Addr, Ba Hold Time
tAS = 1.5, // Addr, Ba Setup Time
tCH = 2.5, // Clock High-Level Width
tCL = 2.5, // Clock Low-Level Width
tCK = 10, // Clock Cycle Time
tDH = 0.8, // Data-in Hold Time
tDS = 1.5, // Data-in Setup Time
tCKH = 0.8, // CKE Hold Time
tCKS = 1.5, // CKE Setup Time
tCMH = 0.8, // CS#, RAS#, CAS#, WE#, DQM# Hold Time
tCMS = 1.5; // CS#, RAS#, CAS#, WE#, DQM# Setup Time
$width (posedge Clk, tCH);
$width (negedge Clk, tCL);
$period (negedge Clk, tCK);
$period (posedge Clk, tCK);
$setuphold(posedge Clk, Cke, tCKS, tCKH);
$setuphold(posedge Clk, Cs_n, tCMS, tCMH);
$setuphold(posedge Clk, Cas_n, tCMS, tCMH);
$setuphold(posedge Clk, Ras_n, tCMS, tCMH);
$setuphold(posedge Clk, We_n, tCMS, tCMH);
$setuphold(posedge Clk, Addr, tAS, tAH);
$setuphold(posedge Clk, Ba, tAS, tAH);
$setuphold(posedge Clk, Dqm, tCMS, tCMH);
$setuphold(posedge Dq_chk, Dq, tDS, tDH);
endspecify
endmodule

View File

@ -0,0 +1,107 @@
# Syntheis command format
#"-from" objects must be of type clock (c:), port (p:), inst (i:), or pin (t:)
#
#166MHz - Application CLOCK
#set APP_CLK_PER 6.0
#set APP_CLK_HALF_PER [expr APP_CLK_PER]
#100MHz - SDRAM Clock
#set SDR_CLK_PER 10.0
#set SDI_CLK_HALF_PER [expr $SDR_CLK_PERR/2]
####################################
# Clear Application Clock : 200Mhz
####################################
create_clock -name wb_clk_i -period 6 -waveform {0 3} p:wb_clk_i
#set_clock_uncertainty -max 0.2 [get_clocks wb_clk_i]
#set_clock_uncertainty -min 0.1 [get_clocks wb_clk_i]
#set_clock_latency 2.0 [get_clocks wb_clk_i]
########################################
# Create SDRAM Clock to 100Mhz
########################################
create_clock -name sdram_clk -period 10 -waveform {0 5} p:sdram_clk
#set_clock_uncertainty -max 0.2 [get_clocks sdram_clk]
#set_clock_uncertainty -min 0.1 [get_clocks sdram_clk]
#set_clock_latency 2.0 [get_clocks sdram_clk]
###########################################
# Set false path between application and SDRAM Clock
##########################################
set_false_path -from c:wb_clk_i -to c:sdram_clk
set_false_path -to c:wb_clk_i -from c:sdram_clk
########################################
# Set false path through reset
########################################
set_false_path -from p:wb_rst_i
set_false_path -from p:sdram_resetn
########################################
# Set False path to all the configuration input
########################################
#set_false_path -from p:{cfg_colbits[*] cfg_req_depth[*] cfg_sdr_cas[*]}
#set_false_path -from p:{cfg_sdr_en cfg_sdr_mode_reg[*] cfg_sdr_rfmax[*]]
#set_false_path -from p:{cfg_sdr_rfsh[*] cfg_sdr_tras_d[*] cfg_sdr_trcar_d[*]}
#set_false_path -from p:{cfg_sdr_trcd_d[*] cfg_sdr_trp_d[*] cfg_sdr_twr_d[*]}
#set_false_path -from p:cfg_sdr_width[*]
########################################
# Application Port Input Contraints
# Since Application Signal will be internally terminated and
# there is will not be any additional FPGA pad delay of 3ns.
# So input delay constraint changed form 3ns to 0ns
#
#######################################
#set_input_delay 3 -max [ wb_stb_i wb_addr_i wb_we_i wb_dat_i wb_sel_i wb_cyc_i wb_cti_i] -clock wb_clk_i
set_input_delay 0 -max { wb_stb_i wb_addr_i[*] wb_we_i wb_dat_i[*] wb_sel_i[*] wb_cyc_i wb_cti_i[*]} -clock wb_clk_i
set_input_delay 0.5 -min { wb_stb_i wb_addr_i[*] wb_we_i wb_dat_i[*] wb_sel_i[*] wb_cyc_i wb_cti_i[*]} -clock wb_clk_i
########################################
# Application Port Output Contraints
# Since Application Signal will be internally terminstated and
# there will not be addiitional FPGA pad delay of 3ns.
# So output delat contraints are changed from 3ns to 0ns
#######################################
#set_output_delay 3 -max [ wb_ack_o wb_dat_o ] -clock wb_clk_i
set_output_delay 0 -max wb_ack_o -clock wb_clk_i
set_output_delay 3 -max {wb_dat_o[*]} -clock wb_clk_i
set_output_delay 0.5 -min wb_ack_o -clock wb_clk_i
set_output_delay 0.5 -min {wb_dat_o[*]} -clock wb_clk_i
#######################################
# SDRAM Input Contraints
# 10 - 2 = 8ns
#######################################
set_input_delay 5 -max {sdr_dq[*]} -clock sdram_clk
set_input_delay 0.5 -min {sdr_dq[*]} -clock sdram_clk
#######################################
# Set the SDRAM Output delay constraints
#######################################
set_output_delay 5 -max { sdr_cs_n sdr_cke sdr_ras_n sdr_cas_n sdr_we_n sdr_dqm[*] sdr_ba[*] sdr_addr[*] sdr_dq[*] } -clock sdram_clk
set_output_delay -2 -min { sdr_cs_n sdr_cke sdr_ras_n sdr_cas_n sdr_we_n sdr_dqm[*] sdr_ba[*] sdr_addr[*] sdr_dq[*] } -clock sdram_clk
########################################
# Misc
#########################################
set_output_delay 5 -max { sdr_init_done } -clock sdram_clk
set_output_delay -2 -min { sdr_init_done } -clock sdram_clk

View File

@ -0,0 +1,187 @@
# Top Level Design Parameters
# Clocks
create_clock -period 6.000000 -waveform {0.000000 3.000000} wb_clk_i
create_clock -period 10.000000 -waveform {0.000000 5.000000} sdram_clk
# False Paths Between Clocks
# False Path Constraints
set_false_path -from {wb_rst_i} -to {*}
set_false_path -from {sdram_resetn} -to {*}
# Maximum Delay Constraints
# Multicycle Constraints
# Virtual Clocks
# Output Load Constraints
# Driving Cell Constraints
# Wire Loads
# set_wire_load_mode top
# Other Constraints
set_input_delay 0.000 -clock {wb_clk_i} {wb_stb_i}
set_output_delay 0.000 -clock {wb_clk_i} {wb_ack_o}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[0]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[1]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[2]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[3]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[4]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[5]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[6]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[7]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[8]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[9]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[10]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[11]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[12]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[13]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[14]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[15]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[16]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[17]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[18]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[19]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[20]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[21]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[22]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[23]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[24]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[25]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[26]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[27]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[28]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_addr_i[29]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_we_i}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[0]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[1]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[2]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[3]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[4]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[5]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[6]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[7]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[8]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[9]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[10]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[11]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[12]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[13]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[14]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[15]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[16]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[17]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[18]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[19]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[20]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[21]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[22]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[23]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[24]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[25]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[26]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[27]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[28]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[29]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[30]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_dat_i[31]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_sel_i[0]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_sel_i[1]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_sel_i[2]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_sel_i[3]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[0]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[1]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[2]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[3]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[4]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[5]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[6]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[7]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[8]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[9]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[10]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[11]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[12]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[13]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[14]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[15]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[16]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[17]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[18]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[19]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[20]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[21]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[22]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[23]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[24]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[25]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[26]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[27]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[28]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[29]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[30]}
set_output_delay 3.000 -clock {wb_clk_i} {wb_dat_o[31]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_cyc_i}
set_input_delay 0.000 -clock {wb_clk_i} {wb_cti_i[0]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_cti_i[1]}
set_input_delay 0.000 -clock {wb_clk_i} {wb_cti_i[2]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_cs_n}
set_output_delay 5.000 -clock {sdram_clk} {sdr_cke}
set_output_delay 5.000 -clock {sdram_clk} {sdr_ras_n}
set_output_delay 5.000 -clock {sdram_clk} {sdr_cas_n}
set_output_delay 5.000 -clock {sdram_clk} {sdr_we_n}
set_output_delay 5.000 -clock {sdram_clk} {sdr_dqm[0]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_dqm[1]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_ba[0]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_ba[1]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_addr[0]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_addr[1]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_addr[2]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_addr[3]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_addr[4]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_addr[5]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_addr[6]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_addr[7]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_addr[8]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_addr[9]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_addr[10]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_addr[11]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_dq[0]}
set_input_delay 5.000 -clock {sdram_clk} {sdr_dq[0]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_dq[1]}
set_input_delay 5.000 -clock {sdram_clk} {sdr_dq[1]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_dq[2]}
set_input_delay 5.000 -clock {sdram_clk} {sdr_dq[2]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_dq[3]}
set_input_delay 5.000 -clock {sdram_clk} {sdr_dq[3]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_dq[4]}
set_input_delay 5.000 -clock {sdram_clk} {sdr_dq[4]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_dq[5]}
set_input_delay 5.000 -clock {sdram_clk} {sdr_dq[5]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_dq[6]}
set_input_delay 5.000 -clock {sdram_clk} {sdr_dq[6]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_dq[7]}
set_input_delay 5.000 -clock {sdram_clk} {sdr_dq[7]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_dq[8]}
set_input_delay 5.000 -clock {sdram_clk} {sdr_dq[8]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_dq[9]}
set_input_delay 5.000 -clock {sdram_clk} {sdr_dq[9]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_dq[10]}
set_input_delay 5.000 -clock {sdram_clk} {sdr_dq[10]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_dq[11]}
set_input_delay 5.000 -clock {sdram_clk} {sdr_dq[11]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_dq[12]}
set_input_delay 5.000 -clock {sdram_clk} {sdr_dq[12]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_dq[13]}
set_input_delay 5.000 -clock {sdram_clk} {sdr_dq[13]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_dq[14]}
set_input_delay 5.000 -clock {sdram_clk} {sdr_dq[14]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_dq[15]}
set_input_delay 5.000 -clock {sdram_clk} {sdr_dq[15]}
set_output_delay 5.000 -clock {sdram_clk} {sdr_init_done}

View File

@ -0,0 +1,535 @@
//////////////////////////////////////////////////////////////////////
//// ////
//// ////
//// This file is part of the SDRAM Controller project ////
//// http://www.opencores.org/cores/sdr_ctrl/ ////
//// ////
//// Description ////
//// SDRAM CTRL definitions. ////
//// ////
//// To Do: ////
//// nothing ////
// Version :0.1 - Test Bench automation is improvised with ////
// seperate data,address,burst length fifo. ////
// Now user can create different write and ////
// read sequence ////
//// ////
//// Author(s): ////
//// - Dinesh Annayya, dinesha@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
// This testbench stand-alone verify the sdram core
`timescale 1ns/1ps
module tb_core;
parameter P_SYS = 10; // 100MHz
// General
reg RESETN;
reg sdram_clk;
initial sdram_clk = 0;
always #(P_SYS/2) sdram_clk = !sdram_clk;
parameter dw = 32; // data width
parameter tw = 8; // tag id width
parameter bl = 5; // burst_lenght_width
//-------------------------------------------
// Application Interface bus
//-------------------------------------------
reg app_req ; // Application Request
reg [8:0] app_req_len ; // Burst Request length
wire app_req_ack ; // Application Request Ack
reg [25:0] app_req_addr ; // Application Address
reg app_req_wr_n ; // 1 -> Read, 0 -> Write
reg [dw-1:0] app_wr_data ; // Write Data
reg [dw/8-1:0] app_wr_en_n ; // Write Enable, Active Low
wire app_rd_valid ; // Read Valid
wire app_last_rd ; // Last Read Valid
wire app_last_wr ; // Last Write Valid
wire [dw-1:0] app_rd_data ; // Read Data
//--------------------------------------------
// SDRAM I/F
//--------------------------------------------
`ifdef SDR_32BIT
wire [31:0] Dq ; // SDRAM Read/Write Data Bus
wire [31:0] sdr_dout ; // SDRAM Data Out
wire [31:0] pad_sdr_din ; // SDRAM Data Input
wire [3:0] sdr_den_n ; // SDRAM Data Enable
wire [3:0] sdr_dqm ; // SDRAM DATA Mask
`elsif SDR_16BIT
wire [15:0] Dq ; // SDRAM Read/Write Data Bus
wire [15:0] sdr_dout ; // SDRAM Data Out
wire [15:0] pad_sdr_din ; // SDRAM Data Input
wire [1:0] sdr_den_n ; // SDRAM Data Enable
wire [1:0] sdr_dqm ; // SDRAM DATA Mask
`else
wire [7:0] Dq ; // SDRAM Read/Write Data Bus
wire [7:0] sdr_dout ; // SDRAM Data Out
wire [7:0] pad_sdr_din ; // SDRAM Data Input
wire [0:0] sdr_den_n ; // SDRAM Data Enable
wire [0:0] sdr_dqm ; // SDRAM DATA Mask
`endif
wire [1:0] sdr_ba ; // SDRAM Bank Select
wire [12:0] sdr_addr ; // SDRAM ADRESS
wire sdr_init_done ; // SDRAM Init Done
// to fix the sdram interface timing issue
wire #(2.0) sdram_clk_d = sdram_clk;
wire #(1.0) pad_clk = sdram_clk_d;
`ifdef SDR_32BIT
sdrc_core #(.SDR_DW(32),.SDR_BW(4)) u_dut(
`elsif SDR_16BIT
sdrc_core #(.SDR_DW(16),.SDR_BW(2)) u_dut(
`else // 8 BIT SDRAM
sdrc_core #(.SDR_DW(8),.SDR_BW(1)) u_dut(
`endif
// System
.clk (sdram_clk ),
.reset_n (RESETN ),
.pad_clk (pad_clk ),
`ifdef SDR_32BIT
.sdr_width (2'b00 ), // 32 BIT SDRAM
`elsif SDR_16BIT
.sdr_width (2'b01 ), // 16 BIT SDRAM
`else
.sdr_width (2'b10 ), // 8 BIT SDRAM
`endif
.cfg_colbits (2'b00 ), // 8 Bit Column Address
/* Request from app */
.app_req (app_req ), // Transfer Request
.app_req_addr (app_req_addr ), // SDRAM Address
.app_req_len (app_req_len ), // Burst Length (in 16 bit words)
.app_req_wrap (1'b0 ), // Wrap mode request (xfr_len = 4)
.app_req_wr_n (app_req_wr_n ), // 0 => Write request, 1 => read req
.app_req_ack (app_req_ack ), // Request has been accepted
.app_wr_data (app_wr_data ),
.app_wr_en_n (app_wr_en_n ),
.app_rd_data (app_rd_data ),
.app_last_rd (app_last_rd ),
.app_last_wr (app_last_wr ),
.app_rd_valid (app_rd_valid ),
.app_wr_next_req (app_wr_next_req ),
.app_req_dma_last (app_req ),
/* Interface to SDRAMs */
.sdr_cs_n (sdr_cs_n ),
.sdr_cke (sdr_cke ),
.sdr_ras_n (sdr_ras_n ),
.sdr_cas_n (sdr_cas_n ),
.sdr_we_n (sdr_we_n ),
.sdr_dqm (sdr_dqm ),
.sdr_ba (sdr_ba ),
.sdr_addr (sdr_addr ),
.pad_sdr_din (Dq ),
.sdr_dout (sdr_dout ),
.sdr_den_n (sdr_den_n ),
/* Parameters */
.sdr_init_done (sdr_init_done ),
.cfg_req_depth (2'h3 ), //how many req. buffer should hold
.cfg_sdr_en (1'b1 ),
.cfg_sdr_mode_reg (13'h033 ),
.cfg_sdr_tras_d (4'h4 ),
.cfg_sdr_trp_d (4'h2 ),
.cfg_sdr_trcd_d (4'h2 ),
.cfg_sdr_cas (3'h3 ),
.cfg_sdr_trcar_d (4'h7 ),
.cfg_sdr_twr_d (4'h1 ),
.cfg_sdr_rfsh (12'h100 ), // reduced from 12'hC35
.cfg_sdr_rfmax (3'h6 )
);
`ifdef SDR_32BIT
assign Dq[7:0] = (sdr_den_n[0] == 1'b0) ? sdr_dout[7:0] : 8'hZZ;
assign Dq[15:8] = (sdr_den_n[1] == 1'b0) ? sdr_dout[15:8] : 8'hZZ;
assign Dq[23:16] = (sdr_den_n[2] == 1'b0) ? sdr_dout[23:16] : 8'hZZ;
assign Dq[31:24] = (sdr_den_n[3] == 1'b0) ? sdr_dout[31:24] : 8'hZZ;
mt48lc2m32b2 #(.data_bits(32)) u_sdram32 (
.Dq (Dq ) ,
.Addr (sdr_addr[10:0] ),
.Ba (sdr_ba ),
.Clk (sdram_clk_d ),
.Cke (sdr_cke ),
.Cs_n (sdr_cs_n ),
.Ras_n (sdr_ras_n ),
.Cas_n (sdr_cas_n ),
.We_n (sdr_we_n ),
.Dqm (sdr_dqm )
);
`elsif SDR_16BIT
assign Dq[7:0] = (sdr_den_n[0] == 1'b0) ? sdr_dout[7:0] : 8'hZZ;
assign Dq[15:8] = (sdr_den_n[1] == 1'b0) ? sdr_dout[15:8] : 8'hZZ;
IS42VM16400K u_sdram16 (
.dq (Dq ),
.addr (sdr_addr[11:0] ),
.ba (sdr_ba ),
.clk (sdram_clk_d ),
.cke (sdr_cke ),
.csb (sdr_cs_n ),
.rasb (sdr_ras_n ),
.casb (sdr_cas_n ),
.web (sdr_we_n ),
.dqm (sdr_dqm )
);
`else
assign Dq[7:0] = (sdr_den_n[0] == 1'b0) ? sdr_dout[7:0] : 8'hZZ;
mt48lc8m8a2 #(.data_bits(8)) u_sdram8 (
.Dq (Dq ) ,
.Addr (sdr_addr[11:0] ),
.Ba (sdr_ba ),
.Clk (sdram_clk_d ),
.Cke (sdr_cke ),
.Cs_n (sdr_cs_n ),
.Ras_n (sdr_ras_n ),
.Cas_n (sdr_cas_n ),
.We_n (sdr_we_n ),
.Dqm (sdr_dqm )
);
`endif
//--------------------
// data/address/burst length FIFO
//--------------------
int dfifo[$]; // data fifo
int afifo[$]; // address fifo
int bfifo[$]; // Burst Length fifo
reg [31:0] read_data;
reg [31:0] ErrCnt;
int k;
reg [31:0] StartAddr;
/////////////////////////////////////////////////////////////////////////
// Test Case
/////////////////////////////////////////////////////////////////////////
initial begin //{
ErrCnt = 0;
app_req_addr = 0;
app_wr_data = 0;
app_wr_en_n = 4'hF;
app_req_wr_n = 0;
app_req = 0;
app_req_len = 0;
RESETN = 1'h1;
#100
// Applying reset
RESETN = 1'h0;
#10000;
// Releasing reset
RESETN = 1'h1;
#1000;
wait(u_dut.sdr_init_done == 1);
#1000;
$display("-------------------------------------- ");
$display(" Case-1: Single Write/Read Case ");
$display("-------------------------------------- ");
burst_write(32'h4_0000,8'h4);
#1000;
burst_read();
// Repeat one more time to analysis the
// SDRAM state change for same col/row address
$display("-------------------------------------- ");
$display(" Case-2: Repeat same transfer once again ");
$display("----------------------------------------");
burst_write(32'h4_0000,8'h4);
burst_read();
burst_write(32'h0040_0000,8'h5);
burst_read();
$display("----------------------------------------");
$display(" Case-3 Create a Page Cross Over ");
$display("----------------------------------------");
burst_write(32'h0000_0FF0,8'h8);
burst_write(32'h0001_0FF4,8'hF);
burst_write(32'h0002_0FF8,8'hF);
burst_write(32'h0003_0FFC,8'hF);
burst_write(32'h0004_0FE0,8'hF);
burst_write(32'h0005_0FE4,8'hF);
burst_write(32'h0006_0FE8,8'hF);
burst_write(32'h0007_0FEC,8'hF);
burst_write(32'h0008_0FD0,8'hF);
burst_write(32'h0009_0FD4,8'hF);
burst_write(32'h000A_0FD8,8'hF);
burst_write(32'h000B_0FDC,8'hF);
burst_write(32'h000C_0FC0,8'hF);
burst_write(32'h000D_0FC4,8'hF);
burst_write(32'h000E_0FC8,8'hF);
burst_write(32'h000F_0FCC,8'hF);
burst_write(32'h0010_0FB0,8'hF);
burst_write(32'h0011_0FB4,8'hF);
burst_write(32'h0012_0FB8,8'hF);
burst_write(32'h0013_0FBC,8'hF);
burst_write(32'h0014_0FA0,8'hF);
burst_write(32'h0015_0FA4,8'hF);
burst_write(32'h0016_0FA8,8'hF);
burst_write(32'h0017_0FAC,8'hF);
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
$display("----------------------------------------");
$display(" Case:4 4 Write & 4 Read ");
$display("----------------------------------------");
burst_write(32'h4_0000,8'h4);
burst_write(32'h5_0000,8'h5);
burst_write(32'h6_0000,8'h6);
burst_write(32'h7_0000,8'h7);
burst_read();
burst_read();
burst_read();
burst_read();
$display("---------------------------------------");
$display(" Case:5 24 Write & 24 Read With Different Bank and Row ");
$display("---------------------------------------");
//----------------------------------------
// Address Decodeing:
// with cfg_col bit configured as: 00
// <12 Bit Row> <2 Bit Bank> <8 Bit Column> <2'b00>
//
burst_write({12'h000,2'b00,8'h00,2'b00},8'h4); // Row: 0 Bank : 0
burst_write({12'h000,2'b01,8'h00,2'b00},8'h5); // Row: 0 Bank : 1
burst_write({12'h000,2'b10,8'h00,2'b00},8'h6); // Row: 0 Bank : 2
burst_write({12'h000,2'b11,8'h00,2'b00},8'h7); // Row: 0 Bank : 3
burst_write({12'h001,2'b00,8'h00,2'b00},8'h4); // Row: 1 Bank : 0
burst_write({12'h001,2'b01,8'h00,2'b00},8'h5); // Row: 1 Bank : 1
burst_write({12'h001,2'b10,8'h00,2'b00},8'h6); // Row: 1 Bank : 2
burst_write({12'h001,2'b11,8'h00,2'b00},8'h7); // Row: 1 Bank : 3
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_write({12'h002,2'b00,8'h00,2'b00},8'h4); // Row: 2 Bank : 0
burst_write({12'h002,2'b01,8'h00,2'b00},8'h5); // Row: 2 Bank : 1
burst_write({12'h002,2'b10,8'h00,2'b00},8'h6); // Row: 2 Bank : 2
burst_write({12'h002,2'b11,8'h00,2'b00},8'h7); // Row: 2 Bank : 3
burst_write({12'h003,2'b00,8'h00,2'b00},8'h4); // Row: 3 Bank : 0
burst_write({12'h003,2'b01,8'h00,2'b00},8'h5); // Row: 3 Bank : 1
burst_write({12'h003,2'b10,8'h00,2'b00},8'h6); // Row: 3 Bank : 2
burst_write({12'h003,2'b11,8'h00,2'b00},8'h7); // Row: 3 Bank : 3
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_write({12'h002,2'b00,8'h00,2'b00},8'h4); // Row: 2 Bank : 0
burst_write({12'h002,2'b01,8'h01,2'b00},8'h5); // Row: 2 Bank : 1
burst_write({12'h002,2'b10,8'h02,2'b00},8'h6); // Row: 2 Bank : 2
burst_write({12'h002,2'b11,8'h03,2'b00},8'h7); // Row: 2 Bank : 3
burst_write({12'h003,2'b00,8'h04,2'b00},8'h4); // Row: 3 Bank : 0
burst_write({12'h003,2'b01,8'h05,2'b00},8'h5); // Row: 3 Bank : 1
burst_write({12'h003,2'b10,8'h06,2'b00},8'h6); // Row: 3 Bank : 2
burst_write({12'h003,2'b11,8'h07,2'b00},8'h7); // Row: 3 Bank : 3
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
$display("---------------------------------------------------");
$display(" Case: 6 Random 2 write and 2 read random");
$display("---------------------------------------------------");
for(k=0; k < 20; k++) begin
StartAddr = $random & 32'h003FFFFF;
burst_write(StartAddr,($random & 8'h0f)+1);
#100;
StartAddr = $random & 32'h003FFFFF;
burst_write(StartAddr,($random & 8'h0f)+1);
#100;
burst_read();
#100;
burst_read();
#100;
end
#10000;
$display("###############################");
if(ErrCnt == 0)
$display("STATUS: SDRAM Write/Read TEST PASSED");
else
$display("ERROR: SDRAM Write/Read TEST FAILED");
$display("###############################");
$finish;
end
task burst_write;
input [31:0] Address;
input [7:0] bl;
int i;
begin
afifo.push_back(Address);
bfifo.push_back(bl);
@ (negedge sdram_clk);
app_req = 1;
app_wr_en_n = 0;
app_req_wr_n = 1'b0;
app_req_addr = Address[31:2];
app_req_len = bl;
$display("Write Address: %x, Burst Size: %d",Address,bl);
// wait for app_req_ack == 1
do begin
@ (posedge sdram_clk);
end while(app_req_ack == 1'b0);
@ (negedge sdram_clk);
app_req = 0;
for(i=0; i < bl; i++) begin
app_wr_data = $random & 32'hFFFFFFFF;
dfifo.push_back(app_wr_data);
do begin
@ (posedge sdram_clk);
end while(app_wr_next_req == 1'b0);
@ (negedge sdram_clk);
$display("Status: Burst-No: %d Write Address: %x WriteData: %x ",i,Address,app_wr_data);
end
app_req = 0;
app_wr_en_n = 'hx;
app_req_wr_n = 'hx;
app_req_addr = 'hx;
app_req_len = 'hx;
end
endtask
task burst_read;
reg [31:0] Address;
reg [7:0] bl;
int i,j;
reg [31:0] exp_data;
begin
Address = afifo.pop_front();
bl = bfifo.pop_front();
@ (negedge sdram_clk);
app_req = 1;
app_wr_en_n = 0;
app_req_wr_n = 1;
app_req_addr = Address[29:2];
app_req_len = bl;
// wait for app_req_ack == 1
do begin
@ (posedge sdram_clk);
end while(app_req_ack == 1'b0);
@ (negedge sdram_clk);
app_req = 0;
app_wr_en_n = 'hx;
app_req_wr_n = 'hx;
app_req_addr = 'hx;
app_req_len = 'hx;
for(j=0; j < bl; j++) begin
wait(app_rd_valid == 1);
exp_data = dfifo.pop_front(); // Exptected Read Data
if(app_rd_data !== exp_data) begin
$display("READ ERROR: Burst-No: %d Addr: %x Rxp: %x Exd: %x",j,Address+(j*2),app_rd_data,exp_data);
ErrCnt = ErrCnt+1;
end else begin
$display("READ STATUS: Burst-No: %d Addr: %x Rxd: %x",j,Address+(j*2),app_rd_data);
end
@ (posedge sdram_clk);
@ (negedge sdram_clk);
end
end
endtask
endmodule

View File

@ -0,0 +1,500 @@
//////////////////////////////////////////////////////////////////////
//// ////
//// ////
//// This file is part of the SDRAM Controller project ////
//// http://www.opencores.org/cores/sdr_ctrl/ ////
//// ////
//// Description ////
//// SDRAM CTRL definitions. ////
//// ////
//// To Do: ////
//// nothing ////
//// ////
// Version :0.1 - Test Bench automation is improvised with ////
// seperate data,address,burst length fifo. ////
// Now user can create different write and ////
// read sequence ////
// ////
//// Author(s): ////
//// - Dinesh Annayya, dinesha@opencores.org ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000 Authors and OPENCORES.ORG ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file is free software; you can redistribute it ////
//// and/or modify it under the terms of the GNU Lesser General ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
`timescale 1ns/1ps
// This testbench verify with SDRAM TOP
module tb_top;
parameter P_SYS = 10; // 200MHz
parameter P_SDR = 20; // 100MHz
// General
reg RESETN;
reg sdram_clk;
reg sys_clk;
initial sys_clk = 0;
initial sdram_clk = 0;
always #(P_SYS/2) sys_clk = !sys_clk;
always #(P_SDR/2) sdram_clk = !sdram_clk;
parameter dw = 32; // data width
parameter tw = 8; // tag id width
parameter bl = 5; // burst_lenght_width
//-------------------------------------------
// WISH BONE Interface
//-------------------------------------------
//--------------------------------------
// Wish Bone Interface
// -------------------------------------
reg wb_stb_i ;
wire wb_ack_o ;
reg [25:0] wb_addr_i ;
reg wb_we_i ; // 1 - Write, 0 - Read
reg [dw-1:0] wb_dat_i ;
reg [dw/8-1:0] wb_sel_i ; // Byte enable
wire [dw-1:0] wb_dat_o ;
reg wb_cyc_i ;
reg [2:0] wb_cti_i ;
//--------------------------------------------
// SDRAM I/F
//--------------------------------------------
`ifdef SDR_32BIT
wire [31:0] Dq ; // SDRAM Read/Write Data Bus
wire [3:0] sdr_dqm ; // SDRAM DATA Mask
`elsif SDR_16BIT
wire [15:0] Dq ; // SDRAM Read/Write Data Bus
wire [1:0] sdr_dqm ; // SDRAM DATA Mask
`else
wire [7:0] Dq ; // SDRAM Read/Write Data Bus
wire [0:0] sdr_dqm ; // SDRAM DATA Mask
`endif
wire [1:0] sdr_ba ; // SDRAM Bank Select
wire [12:0] sdr_addr ; // SDRAM ADRESS
wire sdr_init_done ; // SDRAM Init Done
// to fix the sdram interface timing issue
wire #(2.0) sdram_clk_d = sdram_clk;
`ifdef SDR_32BIT
sdrc_top #(.SDR_DW(32),.SDR_BW(4)) u_dut(
`elsif SDR_16BIT
sdrc_top #(.SDR_DW(16),.SDR_BW(2)) u_dut(
`else // 8 BIT SDRAM
sdrc_top #(.SDR_DW(8),.SDR_BW(1)) u_dut(
`endif
// System
`ifdef SDR_32BIT
.cfg_sdr_width (2'b00 ), // 32 BIT SDRAM
`elsif SDR_16BIT
.cfg_sdr_width (2'b01 ), // 16 BIT SDRAM
`else
.cfg_sdr_width (2'b10 ), // 8 BIT SDRAM
`endif
.cfg_colbits (2'b00 ), // 8 Bit Column Address
/* WISH BONE */
.wb_rst_i (!RESETN ),
.wb_clk_i (sys_clk ),
.wb_stb_i (wb_stb_i ),
.wb_ack_o (wb_ack_o ),
.wb_addr_i (wb_addr_i ),
.wb_we_i (wb_we_i ),
.wb_dat_i (wb_dat_i ),
.wb_sel_i (wb_sel_i ),
.wb_dat_o (wb_dat_o ),
.wb_cyc_i (wb_cyc_i ),
.wb_cti_i (wb_cti_i ),
/* Interface to SDRAMs */
.sdram_clk (sdram_clk ),
.sdram_resetn (RESETN ),
.sdr_cs_n (sdr_cs_n ),
.sdr_cke (sdr_cke ),
.sdr_ras_n (sdr_ras_n ),
.sdr_cas_n (sdr_cas_n ),
.sdr_we_n (sdr_we_n ),
.sdr_dqm (sdr_dqm ),
.sdr_ba (sdr_ba ),
.sdr_addr (sdr_addr ),
.sdr_dq (Dq ),
/* Parameters */
.sdr_init_done (sdr_init_done ),
.cfg_req_depth (2'h3 ), //how many req. buffer should hold
.cfg_sdr_en (1'b1 ),
.cfg_sdr_mode_reg (13'h033 ),
.cfg_sdr_tras_d (4'h4 ),
.cfg_sdr_trp_d (4'h2 ),
.cfg_sdr_trcd_d (4'h2 ),
.cfg_sdr_cas (3'h3 ),
.cfg_sdr_trcar_d (4'h7 ),
.cfg_sdr_twr_d (4'h1 ),
.cfg_sdr_rfsh (12'h100 ), // reduced from 12'hC35
.cfg_sdr_rfmax (3'h6 )
);
`ifdef SDR_32BIT
mt48lc2m32b2 #(.data_bits(32)) u_sdram32 (
.Dq (Dq ) ,
.Addr (sdr_addr[10:0] ),
.Ba (sdr_ba ),
.Clk (sdram_clk_d ),
.Cke (sdr_cke ),
.Cs_n (sdr_cs_n ),
.Ras_n (sdr_ras_n ),
.Cas_n (sdr_cas_n ),
.We_n (sdr_we_n ),
.Dqm (sdr_dqm )
);
`elsif SDR_16BIT
IS42VM16400K u_sdram16 (
.dq (Dq ),
.addr (sdr_addr[11:0] ),
.ba (sdr_ba ),
.clk (sdram_clk_d ),
.cke (sdr_cke ),
.csb (sdr_cs_n ),
.rasb (sdr_ras_n ),
.casb (sdr_cas_n ),
.web (sdr_we_n ),
.dqm (sdr_dqm )
);
`else
mt48lc8m8a2 #(.data_bits(8)) u_sdram8 (
.Dq (Dq ) ,
.Addr (sdr_addr[11:0] ),
.Ba (sdr_ba ),
.Clk (sdram_clk_d ),
.Cke (sdr_cke ),
.Cs_n (sdr_cs_n ),
.Ras_n (sdr_ras_n ),
.Cas_n (sdr_cas_n ),
.We_n (sdr_we_n ),
.Dqm (sdr_dqm )
);
`endif
//--------------------
// data/address/burst length FIFO
//--------------------
int dfifo[$]; // data fifo
int afifo[$]; // address fifo
int bfifo[$]; // Burst Length fifo
reg [31:0] read_data;
reg [31:0] ErrCnt;
int k;
reg [31:0] StartAddr;
/////////////////////////////////////////////////////////////////////////
// Test Case
/////////////////////////////////////////////////////////////////////////
initial begin //{
ErrCnt = 0;
wb_addr_i = 0;
wb_dat_i = 0;
wb_sel_i = 4'h0;
wb_we_i = 0;
wb_stb_i = 0;
wb_cyc_i = 0;
RESETN = 1'h1;
#100
// Applying reset
RESETN = 1'h0;
#10000;
// Releasing reset
RESETN = 1'h1;
#1000;
wait(u_dut.sdr_init_done == 1);
#1000;
$display("-------------------------------------- ");
$display(" Case-1: Single Write/Read Case ");
$display("-------------------------------------- ");
burst_write(32'h4_0000,8'h4);
#1000;
burst_read();
// Repeat one more time to analysis the
// SDRAM state change for same col/row address
$display("-------------------------------------- ");
$display(" Case-2: Repeat same transfer once again ");
$display("----------------------------------------");
burst_write(32'h4_0000,8'h4);
burst_read();
burst_write(32'h0040_0000,8'h5);
burst_read();
$display("----------------------------------------");
$display(" Case-3 Create a Page Cross Over ");
$display("----------------------------------------");
burst_write(32'h0000_0FF0,8'h8);
burst_write(32'h0001_0FF4,8'hF);
burst_write(32'h0002_0FF8,8'hF);
burst_write(32'h0003_0FFC,8'hF);
burst_write(32'h0004_0FE0,8'hF);
burst_write(32'h0005_0FE4,8'hF);
burst_write(32'h0006_0FE8,8'hF);
burst_write(32'h0007_0FEC,8'hF);
burst_write(32'h0008_0FD0,8'hF);
burst_write(32'h0009_0FD4,8'hF);
burst_write(32'h000A_0FD8,8'hF);
burst_write(32'h000B_0FDC,8'hF);
burst_write(32'h000C_0FC0,8'hF);
burst_write(32'h000D_0FC4,8'hF);
burst_write(32'h000E_0FC8,8'hF);
burst_write(32'h000F_0FCC,8'hF);
burst_write(32'h0010_0FB0,8'hF);
burst_write(32'h0011_0FB4,8'hF);
burst_write(32'h0012_0FB8,8'hF);
burst_write(32'h0013_0FBC,8'hF);
burst_write(32'h0014_0FA0,8'hF);
burst_write(32'h0015_0FA4,8'hF);
burst_write(32'h0016_0FA8,8'hF);
burst_write(32'h0017_0FAC,8'hF);
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
$display("----------------------------------------");
$display(" Case:4 4 Write & 4 Read ");
$display("----------------------------------------");
burst_write(32'h4_0000,8'h4);
burst_write(32'h5_0000,8'h5);
burst_write(32'h6_0000,8'h6);
burst_write(32'h7_0000,8'h7);
burst_read();
burst_read();
burst_read();
burst_read();
$display("---------------------------------------");
$display(" Case:5 24 Write & 24 Read With Different Bank and Row ");
$display("---------------------------------------");
//----------------------------------------
// Address Decodeing:
// with cfg_col bit configured as: 00
// <12 Bit Row> <2 Bit Bank> <8 Bit Column> <2'b00>
//
burst_write({12'h000,2'b00,8'h00,2'b00},8'h4); // Row: 0 Bank : 0
burst_write({12'h000,2'b01,8'h00,2'b00},8'h5); // Row: 0 Bank : 1
burst_write({12'h000,2'b10,8'h00,2'b00},8'h6); // Row: 0 Bank : 2
burst_write({12'h000,2'b11,8'h00,2'b00},8'h7); // Row: 0 Bank : 3
burst_write({12'h001,2'b00,8'h00,2'b00},8'h4); // Row: 1 Bank : 0
burst_write({12'h001,2'b01,8'h00,2'b00},8'h5); // Row: 1 Bank : 1
burst_write({12'h001,2'b10,8'h00,2'b00},8'h6); // Row: 1 Bank : 2
burst_write({12'h001,2'b11,8'h00,2'b00},8'h7); // Row: 1 Bank : 3
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_write({12'h002,2'b00,8'h00,2'b00},8'h4); // Row: 2 Bank : 0
burst_write({12'h002,2'b01,8'h00,2'b00},8'h5); // Row: 2 Bank : 1
burst_write({12'h002,2'b10,8'h00,2'b00},8'h6); // Row: 2 Bank : 2
burst_write({12'h002,2'b11,8'h00,2'b00},8'h7); // Row: 2 Bank : 3
burst_write({12'h003,2'b00,8'h00,2'b00},8'h4); // Row: 3 Bank : 0
burst_write({12'h003,2'b01,8'h00,2'b00},8'h5); // Row: 3 Bank : 1
burst_write({12'h003,2'b10,8'h00,2'b00},8'h6); // Row: 3 Bank : 2
burst_write({12'h003,2'b11,8'h00,2'b00},8'h7); // Row: 3 Bank : 3
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_write({12'h002,2'b00,8'h00,2'b00},8'h4); // Row: 2 Bank : 0
burst_write({12'h002,2'b01,8'h01,2'b00},8'h5); // Row: 2 Bank : 1
burst_write({12'h002,2'b10,8'h02,2'b00},8'h6); // Row: 2 Bank : 2
burst_write({12'h002,2'b11,8'h03,2'b00},8'h7); // Row: 2 Bank : 3
burst_write({12'h003,2'b00,8'h04,2'b00},8'h4); // Row: 3 Bank : 0
burst_write({12'h003,2'b01,8'h05,2'b00},8'h5); // Row: 3 Bank : 1
burst_write({12'h003,2'b10,8'h06,2'b00},8'h6); // Row: 3 Bank : 2
burst_write({12'h003,2'b11,8'h07,2'b00},8'h7); // Row: 3 Bank : 3
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
burst_read();
$display("---------------------------------------------------");
$display(" Case: 6 Random 2 write and 2 read random");
$display("---------------------------------------------------");
for(k=0; k < 20; k++) begin
StartAddr = $random & 32'h003FFFFF;
burst_write(StartAddr,($random & 8'h0f)+1);
#100;
StartAddr = $random & 32'h003FFFFF;
burst_write(StartAddr,($random & 8'h0f)+1);
#100;
burst_read();
#100;
burst_read();
#100;
end
#10000;
$display("###############################");
if(ErrCnt == 0)
$display("STATUS: SDRAM Write/Read TEST PASSED");
else
$display("ERROR: SDRAM Write/Read TEST FAILED");
$display("###############################");
$finish;
end
task burst_write;
input [31:0] Address;
input [7:0] bl;
int i;
begin
afifo.push_back(Address);
bfifo.push_back(bl);
@ (negedge sys_clk);
$display("Write Address: %x, Burst Size: %d",Address,bl);
for(i=0; i < bl; i++) begin
wb_stb_i = 1;
wb_cyc_i = 1;
wb_we_i = 1;
wb_sel_i = 4'b1111;
wb_addr_i = Address[31:2]+i;
wb_dat_i = $random & 32'hFFFFFFFF;
dfifo.push_back(wb_dat_i);
do begin
@ (posedge sys_clk);
end while(wb_ack_o == 1'b0);
@ (negedge sys_clk);
$display("Status: Burst-No: %d Write Address: %x WriteData: %x ",i,wb_addr_i,wb_dat_i);
end
wb_stb_i = 0;
wb_cyc_i = 0;
wb_we_i = 'hx;
wb_sel_i = 'hx;
wb_addr_i = 'hx;
wb_dat_i = 'hx;
end
endtask
task burst_read;
reg [31:0] Address;
reg [7:0] bl;
int i,j;
reg [31:0] exp_data;
begin
Address = afifo.pop_front();
bl = bfifo.pop_front();
@ (negedge sys_clk);
for(j=0; j < bl; j++) begin
wb_stb_i = 1;
wb_cyc_i = 1;
wb_we_i = 0;
wb_addr_i = Address[31:2]+j;
exp_data = dfifo.pop_front(); // Exptected Read Data
do begin
@ (posedge sys_clk);
end while(wb_ack_o == 1'b0);
if(wb_dat_o !== exp_data) begin
$display("READ ERROR: Burst-No: %d Addr: %x Rxp: %x Exd: %x",j,wb_addr_i,wb_dat_o,exp_data);
ErrCnt = ErrCnt+1;
end else begin
$display("READ STATUS: Burst-No: %d Addr: %x Rxd: %x",j,wb_addr_i,wb_dat_o);
end
@ (negedge sdram_clk);
end
wb_stb_i = 0;
wb_cyc_i = 0;
wb_we_i = 'hx;
wb_addr_i = 'hx;
end
endtask
endmodule

View File

@ -0,0 +1,297 @@
/*********************************************************************
SDRAM Controller top File
This file is part of the sdram controller project
http://www.opencores.org/cores/sdr_ctrl/
Description: SDRAM Controller Top Module.
Support 81/6/32 Bit SDRAM.
Column Address is Programmable
Bank Bit are 2 Bit
Row Bits are 12 Bits
This block integrate following sub modules
sdrc_core
SDRAM Controller file
wb2sdrc
This module transalate the bus protocl from wishbone to custome
sdram controller
To Do:
nothing
Author(s): Dinesh Annayya, dinesha@opencores.org
Version : 0.0 - 8th Jan 2012
Initial version with 16/32 Bit SDRAM Support
: 0.1 - 24th Jan 2012
8 Bit SDRAM Support is added
0.2 - 31st Jan 2012
sdram_dq and sdram_pad_clk are internally generated
0.3 - 26th April 2013
Sdram Address witdh is increased from 12 to 13bits
Copyright (C) 2000 Authors and OPENCORES.ORG
This source file may be used and distributed without
restriction provided that this copyright statement is not
removed from the file and that any derivative work contains
the original copyright notice and the associated disclaimer.
This source file is free software; you can redistribute it
and/or modify it under the terms of the GNU Lesser General
Public License as published by the Free Software Foundation;
either version 2.1 of the License, or (at your option) any
later version.
This source is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General
Public License along with this source; if not, download it
from http://www.opencores.org/lgpl.shtml
*******************************************************************/
`include "sdrc_define.v"
module sdrc_top
(
cfg_sdr_width ,
cfg_colbits ,
// WB bus
wb_rst_i ,
wb_clk_i ,
wb_stb_i ,
wb_ack_o ,
wb_addr_i ,
wb_we_i ,
wb_dat_i ,
wb_sel_i ,
wb_dat_o ,
wb_cyc_i ,
wb_cti_i ,
/* Interface to SDRAMs */
sdram_clk ,
sdram_resetn ,
sdr_cs_n ,
sdr_cke ,
sdr_ras_n ,
sdr_cas_n ,
sdr_we_n ,
sdr_dqm ,
sdr_ba ,
sdr_addr ,
sdr_dq ,
/* Parameters */
sdr_init_done ,
cfg_req_depth , //how many req. buffer should hold
cfg_sdr_en ,
cfg_sdr_mode_reg ,
cfg_sdr_tras_d ,
cfg_sdr_trp_d ,
cfg_sdr_trcd_d ,
cfg_sdr_cas ,
cfg_sdr_trcar_d ,
cfg_sdr_twr_d ,
cfg_sdr_rfsh ,
cfg_sdr_rfmax
);
parameter APP_AW = 26; // Application Address Width
parameter APP_DW = 32; // Application Data Width
parameter APP_BW = 4; // Application Byte Width
parameter APP_RW = 9; // Application Request Width
parameter SDR_DW = 16; // SDR Data Width
parameter SDR_BW = 2; // SDR Byte Width
parameter dw = 32; // data width
parameter tw = 8; // tag id width
parameter bl = 9; // burst_lenght_width
//-----------------------------------------------
// Global Variable
// ----------------------------------------------
input sdram_clk ; // SDRAM Clock
input sdram_resetn ; // Reset Signal
input [1:0] cfg_sdr_width ; // 2'b00 - 32 Bit SDR, 2'b01 - 16 Bit SDR, 2'b1x - 8 Bit
input [1:0] cfg_colbits ; // 2'b00 - 8 Bit column address,
// 2'b01 - 9 Bit, 10 - 10 bit, 11 - 11Bits
//--------------------------------------
// Wish Bone Interface
// -------------------------------------
input wb_rst_i ;
input wb_clk_i ;
input wb_stb_i ;
output wb_ack_o ;
input [APP_AW-1:0] wb_addr_i ;
input wb_we_i ; // 1 - Write, 0 - Read
input [dw-1:0] wb_dat_i ;
input [dw/8-1:0] wb_sel_i ; // Byte enable
output [dw-1:0] wb_dat_o ;
input wb_cyc_i ;
input [2:0] wb_cti_i ;
//------------------------------------------------
// Interface to SDRAMs
//------------------------------------------------
output sdr_cke ; // SDRAM CKE
output sdr_cs_n ; // SDRAM Chip Select
output sdr_ras_n ; // SDRAM ras
output sdr_cas_n ; // SDRAM cas
output sdr_we_n ; // SDRAM write enable
output [SDR_BW-1:0] sdr_dqm ; // SDRAM Data Mask
output [1:0] sdr_ba ; // SDRAM Bank Enable
output [12:0] sdr_addr ; // SDRAM Address
inout [SDR_DW-1:0] sdr_dq ; // SDRA Data Input/output
//------------------------------------------------
// Configuration Parameter
//------------------------------------------------
output sdr_init_done ; // Indicate SDRAM Initialisation Done
input [3:0] cfg_sdr_tras_d ; // Active to precharge delay
input [3:0] cfg_sdr_trp_d ; // Precharge to active delay
input [3:0] cfg_sdr_trcd_d ; // Active to R/W delay
input cfg_sdr_en ; // Enable SDRAM controller
input [1:0] cfg_req_depth ; // Maximum Request accepted by SDRAM controller
input [12:0] cfg_sdr_mode_reg ;
input [2:0] cfg_sdr_cas ; // SDRAM CAS Latency
input [3:0] cfg_sdr_trcar_d ; // Auto-refresh period
input [3:0] cfg_sdr_twr_d ; // Write recovery delay
input [`SDR_RFSH_TIMER_W-1 : 0] cfg_sdr_rfsh;
input [`SDR_RFSH_ROW_CNT_W -1 : 0] cfg_sdr_rfmax;
//--------------------------------------------
// SDRAM controller Interface
//--------------------------------------------
wire app_req ; // SDRAM request
wire [APP_AW-1:0] app_req_addr ; // SDRAM Request Address
wire [bl-1:0] app_req_len ;
wire app_req_wr_n ; // 0 - Write, 1 -> Read
wire app_req_ack ; // SDRAM request Accepted
wire app_busy_n ; // 0 -> sdr busy
wire [dw/8-1:0] app_wr_en_n ; // Active low sdr byte-wise write data valid
wire app_wr_next_req ; // Ready to accept the next write
wire app_rd_valid ; // sdr read valid
wire app_last_rd ; // Indicate last Read of Burst Transfer
wire app_last_wr ; // Indicate last Write of Burst Transfer
wire [dw-1:0] app_wr_data ; // sdr write data
wire [dw-1:0] app_rd_data ; // sdr read data
/****************************************
* These logic has to be implemented using Pads
* **************************************/
wire [SDR_DW-1:0] pad_sdr_din ; // SDRA Data Input
wire [SDR_DW-1:0] sdr_dout ; // SDRAM Data Output
wire [SDR_BW-1:0] sdr_den_n ; // SDRAM Data Output enable
assign sdr_dq = (&sdr_den_n == 1'b0) ? sdr_dout : {SDR_DW{1'bz}};
assign pad_sdr_din = sdr_dq;
// sdram pad clock is routed back through pad
// SDRAM Clock from Pad, used for registering Read Data
wire #(1.0) sdram_pad_clk = sdram_clk;
/************** Ends Here **************************/
wb2sdrc #(.dw(dw),.tw(tw),.bl(bl)) u_wb2sdrc (
// WB bus
.wb_rst_i (wb_rst_i ) ,
.wb_clk_i (wb_clk_i ) ,
.wb_stb_i (wb_stb_i ) ,
.wb_ack_o (wb_ack_o ) ,
.wb_addr_i (wb_addr_i ) ,
.wb_we_i (wb_we_i ) ,
.wb_dat_i (wb_dat_i ) ,
.wb_sel_i (wb_sel_i ) ,
.wb_dat_o (wb_dat_o ) ,
.wb_cyc_i (wb_cyc_i ) ,
.wb_cti_i (wb_cti_i ) ,
//SDRAM Controller Hand-Shake Signal
.sdram_clk (sdram_clk ) ,
.sdram_resetn (sdram_resetn ) ,
.sdr_req (app_req ) ,
.sdr_req_addr (app_req_addr ) ,
.sdr_req_len (app_req_len ) ,
.sdr_req_wr_n (app_req_wr_n ) ,
.sdr_req_ack (app_req_ack ) ,
.sdr_busy_n (app_busy_n ) ,
.sdr_wr_en_n (app_wr_en_n ) ,
.sdr_wr_next (app_wr_next_req ) ,
.sdr_rd_valid (app_rd_valid ) ,
.sdr_last_rd (app_last_rd ) ,
.sdr_wr_data (app_wr_data ) ,
.sdr_rd_data (app_rd_data )
);
sdrc_core #(.SDR_DW(SDR_DW) , .SDR_BW(SDR_BW)) u_sdrc_core (
.clk (sdram_clk ) ,
.pad_clk (sdram_pad_clk ) ,
.reset_n (sdram_resetn ) ,
.sdr_width (cfg_sdr_width ) ,
.cfg_colbits (cfg_colbits ) ,
/* Request from app */
.app_req (app_req ) ,// Transfer Request
.app_req_addr (app_req_addr ) ,// SDRAM Address
.app_req_len (app_req_len ) ,// Burst Length (in 16 bit words)
.app_req_wrap (1'b0 ) ,// Wrap mode request
.app_req_wr_n (app_req_wr_n ) ,// 0 => Write request, 1 => read req
.app_req_ack (app_req_ack ) ,// Request has been accepted
.cfg_req_depth (cfg_req_depth ) ,//how many req. buffer should hold
.app_wr_data (app_wr_data ) ,
.app_wr_en_n (app_wr_en_n ) ,
.app_rd_data (app_rd_data ) ,
.app_rd_valid (app_rd_valid ) ,
.app_last_rd (app_last_rd ) ,
.app_last_wr (app_last_wr ) ,
.app_wr_next_req (app_wr_next_req ) ,
.sdr_init_done (sdr_init_done ) ,
.app_req_dma_last (app_req ) ,
/* Interface to SDRAMs */
.sdr_cs_n (sdr_cs_n ) ,
.sdr_cke (sdr_cke ) ,
.sdr_ras_n (sdr_ras_n ) ,
.sdr_cas_n (sdr_cas_n ) ,
.sdr_we_n (sdr_we_n ) ,
.sdr_dqm (sdr_dqm ) ,
.sdr_ba (sdr_ba ) ,
.sdr_addr (sdr_addr ) ,
.pad_sdr_din (pad_sdr_din ) ,
.sdr_dout (sdr_dout ) ,
.sdr_den_n (sdr_den_n ) ,
/* Parameters */
.cfg_sdr_en (cfg_sdr_en ) ,
.cfg_sdr_mode_reg (cfg_sdr_mode_reg ) ,
.cfg_sdr_tras_d (cfg_sdr_tras_d ) ,
.cfg_sdr_trp_d (cfg_sdr_trp_d ) ,
.cfg_sdr_trcd_d (cfg_sdr_trcd_d ) ,
.cfg_sdr_cas (cfg_sdr_cas ) ,
.cfg_sdr_trcar_d (cfg_sdr_trcar_d ) ,
.cfg_sdr_twr_d (cfg_sdr_twr_d ) ,
.cfg_sdr_rfsh (cfg_sdr_rfsh ) ,
.cfg_sdr_rfmax (cfg_sdr_rfmax )
);
endmodule // sdrc_core

View File

@ -0,0 +1,371 @@
/*********************************************************************
This file is part of the sdram controller project
http://www.opencores.org/cores/sdr_ctrl/
Description: WISHBONE to SDRAM Controller Bus Transalator
1. This module translate the WISHBONE protocol to custom sdram controller i/f
2. Also Handle the clock domain change from Application layer to Sdram layer
To Do:
nothing
Author(s): Dinesh Annayya, dinesha@opencores.org
Version : 0.0 - Initial Release
0.1 - 2nd Feb 2012
Async Fifo towards the application layer is selected
with Registered Full Generation
0.2 - 2nd Feb 2012
Pending Read generation bug fix done to handle backto back write
followed by read request
Copyright (C) 2000 Authors and OPENCORES.ORG
This source file may be used and distributed without
restriction provided that this copyright statement is not
removed from the file and that any derivative work contains
the original copyright notice and the associated disclaimer.
This source file is free software; you can redistribute it
and/or modify it under the terms of the GNU Lesser General
Public License as published by the Free Software Foundation;
either version 2.1 of the License, or (at your option) any
later version.
This source is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General
Public License along with this source; if not, download it
from http://www.opencores.org/lgpl.shtml
*******************************************************************/
module wb2sdrc (
// WB bus
wb_rst_i ,
wb_clk_i ,
wb_stb_i ,
wb_ack_o ,
wb_addr_i ,
wb_we_i ,
wb_dat_i ,
wb_sel_i ,
wb_dat_o ,
wb_cyc_i ,
wb_cti_i ,
//SDRAM Controller Hand-Shake Signal
sdram_clk ,
sdram_resetn ,
sdr_req ,
sdr_req_addr ,
sdr_req_len ,
sdr_req_wr_n ,
sdr_req_ack ,
sdr_busy_n ,
sdr_wr_en_n ,
sdr_wr_next ,
sdr_rd_valid ,
sdr_last_rd ,
sdr_wr_data ,
sdr_rd_data
);
parameter dw = 32; // data width
parameter tw = 8; // tag id width
parameter bl = 9; // burst_lenght_width
parameter APP_AW = 26; // Application Address Width
//--------------------------------------
// Wish Bone Interface
// -------------------------------------
input wb_rst_i ;
input wb_clk_i ;
input wb_stb_i ;
output wb_ack_o ;
input [APP_AW-1:0] wb_addr_i ;
input wb_we_i ; // 1 - Write , 0 - Read
input [dw-1:0] wb_dat_i ;
input [dw/8-1:0] wb_sel_i ; // Byte enable
output [dw-1:0] wb_dat_o ;
input wb_cyc_i ;
input [2:0] wb_cti_i ;
/***************************************************
The Cycle Type Idenfier [CTI_IO()] Address Tag provides
additional information about the current cycle.
The MASTER sends this information to the SLAVE. The SLAVE can use this
information to prepare the response for the next cycle.
Table 4-2 Cycle Type Identifiers
CTI_O(2:0) Description
000 Classic cycle.
001 Constant address burst cycle
010 Incrementing burst cycle
011 Reserved
100 Reserved
101 Reserved
110 Reserved
111 End-of-Burst
****************************************************/
//--------------------------------------------
// SDRAM controller Interface
//--------------------------------------------
input sdram_clk ; // sdram clock
input sdram_resetn ; // sdram reset
output sdr_req ; // SDRAM request
output [APP_AW-1:0] sdr_req_addr ; // SDRAM Request Address
output [bl-1:0] sdr_req_len ;
output sdr_req_wr_n ; // 0 - Write, 1 -> Read
input sdr_req_ack ; // SDRAM request Accepted
input sdr_busy_n ; // 0 -> sdr busy
output [dw/8-1:0] sdr_wr_en_n ; // Active low sdr byte-wise write data valid
input sdr_wr_next ; // Ready to accept the next write
input sdr_rd_valid ; // sdr read valid
input sdr_last_rd ; // Indicate last Read of Burst Transfer
output [dw-1:0] sdr_wr_data ; // sdr write data
input [dw-1:0] sdr_rd_data ; // sdr read data
//----------------------------------------------------
// Wire Decleration
// ---------------------------------------------------
wire cmdfifo_full ;
wire cmdfifo_empty ;
wire wrdatafifo_full ;
wire wrdatafifo_empty ;
wire tagfifo_full ;
wire tagfifo_empty ;
wire rddatafifo_empty ;
wire rddatafifo_full ;
reg pending_read ;
//-----------------------------------------------------------------------------
// Ack Generaltion Logic
// If Write Request - Acknowledge if the command and write FIFO are not full
// If Read Request - Generate the Acknowledgment once read fifo has data
// available
//-----------------------------------------------------------------------------
assign wb_ack_o = (wb_stb_i && wb_cyc_i && wb_we_i) ? // Write Phase
((!cmdfifo_full) && (!wrdatafifo_full)) :
(wb_stb_i && wb_cyc_i && !wb_we_i) ? // Read Phase
!rddatafifo_empty : 1'b0;
//---------------------------------------------------------------------------
// Command FIFO Write Generation
// If Write Request - Generate write, when Write fifo and command fifo is
// not full
// If Read Request - Generate write, when command fifo not full and there
// is no pending read request.
//---------------------------------------------------------------------------
wire cmdfifo_wr = (wb_stb_i && wb_cyc_i && wb_we_i && (!cmdfifo_full) ) ? wb_ack_o :
(wb_stb_i && wb_cyc_i && !wb_we_i && (!cmdfifo_full)) ? !pending_read: 1'b0 ;
//---------------------------------------------------------------------------
// command fifo read generation
// Command FIFo read will be generated, whenever SDRAM Controller
// Acknowldge the Request
//----------------------------------------------------------------------------
wire cmdfifo_rd = sdr_req_ack;
//---------------------------------------------------------------------------
// Application layer request is generated towards the controller, whenever
// Command FIFO is not full
// --------------------------------------------------------------------------
assign sdr_req = !cmdfifo_empty;
//----------------------------------------------------------------------------
// Since Burst length is not known at the start of the Burst, It's assumed as
// Single Cycle Burst. We need to improvise this ...
// --------------------------------------------------------------------------
wire [bl-1:0] burst_length = 1; // 0 Mean 1 Transfer
//-----------------------------------------------------------------------------
// In Wish Bone Spec, For Read Request has to be acked along with data.
// We need to identify the pending read request.
// Once we accept the read request, we should not accept one more read
// request, untill we have transmitted the read data.
// Pending Read will
// set - with Read Request
// reset - with Read Request + Ack
// ----------------------------------------------------------------------------
always @(posedge wb_rst_i or posedge wb_clk_i) begin
if(wb_rst_i) begin
pending_read <= 1'b0;
end else begin
//pending_read <= wb_stb_i & wb_cyc_i & !wb_we_i & !wb_ack_o;
pending_read <= (cmdfifo_wr && !wb_we_i) ? 1'b1:
(wb_stb_i & wb_cyc_i & !wb_we_i & wb_ack_o) ? 1'b0: pending_read;
end
end
//---------------------------------------------------------------------
// Async Command FIFO. This block handle the clock domain change from
// Application layer to SDRAM Controller
// ------------------------------------------------------------------
// Address + Burst Length + W/R Request
async_fifo #(.W(APP_AW+bl+1),.DP(4),.WR_FAST(1'b0), .RD_FAST(1'b0)) u_cmdfifo (
// Write Path Sys CLock Domain
.wr_clk (wb_clk_i ),
.wr_reset_n (!wb_rst_i ),
.wr_en (cmdfifo_wr ),
.wr_data ({burst_length,
!wb_we_i,
wb_addr_i} ),
.afull ( ),
.full (cmdfifo_full ),
// Read Path, SDRAM clock domain
.rd_clk (sdram_clk ),
.rd_reset_n (sdram_resetn ),
.aempty ( ),
.empty (cmdfifo_empty ),
.rd_en (cmdfifo_rd ),
.rd_data ({sdr_req_len,
sdr_req_wr_n,
sdr_req_addr} )
);
// synopsys translate_off
always @(posedge wb_clk_i) begin
if (cmdfifo_full == 1'b1 && cmdfifo_wr == 1'b1) begin
$display("ERROR:%m COMMAND FIFO WRITE OVERFLOW");
end
end
// synopsys translate_on
// synopsys translate_off
always @(posedge sdram_clk) begin
if (cmdfifo_empty == 1'b1 && cmdfifo_rd == 1'b1) begin
$display("ERROR:%m COMMAND FIFO READ OVERFLOW");
end
end
// synopsys translate_on
//---------------------------------------------------------------------
// Write Data FIFO Write Generation, when ever Acked + Write Request
// Note: Ack signal generation already taking account of FIFO full condition
// ---------------------------------------------------------------------
wire wrdatafifo_wr = wb_ack_o & wb_we_i ;
//------------------------------------------------------------------------
// Write Data FIFO Read Generation, When ever Next Write request generated
// from SDRAM Controller
// ------------------------------------------------------------------------
wire wrdatafifo_rd = sdr_wr_next;
//------------------------------------------------------------------------
// Async Write Data FIFO
// This block handle the clock domain change over + Write Data + Byte mask
// From Application layer to SDRAM controller layer
//------------------------------------------------------------------------
// Write DATA + Data Mask FIFO
async_fifo #(.W(dw+(dw/8)), .DP(8), .WR_FAST(1'b0), .RD_FAST(1'b1)) u_wrdatafifo (
// Write Path , System clock domain
.wr_clk (wb_clk_i ),
.wr_reset_n (!wb_rst_i ),
.wr_en (wrdatafifo_wr ),
.wr_data ({~wb_sel_i,
wb_dat_i} ),
.afull ( ),
.full (wrdatafifo_full ),
// Read Path , SDRAM clock domain
.rd_clk (sdram_clk ),
.rd_reset_n (sdram_resetn ),
.aempty ( ),
.empty (wrdatafifo_empty ),
.rd_en (wrdatafifo_rd ),
.rd_data ({sdr_wr_en_n,
sdr_wr_data} )
);
// synopsys translate_off
always @(posedge wb_clk_i) begin
if (wrdatafifo_full == 1'b1 && wrdatafifo_wr == 1'b1) begin
$display("ERROR:%m WRITE DATA FIFO WRITE OVERFLOW");
end
end
always @(posedge sdram_clk) begin
if (wrdatafifo_empty == 1'b1 && wrdatafifo_rd == 1'b1) begin
$display("ERROR:%m WRITE DATA FIFO READ OVERFLOW");
end
end
// synopsys translate_on
// -------------------------------------------------------------------
// READ DATA FIFO
// ------------------------------------------------------------------
wire rd_eop; // last read indication
// Read FIFO write generation, when ever SDRAM controller issues the read
// valid signal
wire rddatafifo_wr = sdr_rd_valid;
// Read FIFO read generation, when ever ack is generated along with read
// request.
// Note: Ack generation is already accounted the write FIFO Not Empty
// condition
wire rddatafifo_rd = wb_ack_o & !wb_we_i;
//-------------------------------------------------------------------------
// Async Read FIFO
// This block handles the clock domain change over + Read data from SDRAM
// controller to Application layer.
// Note:
// 1. READ DATA FIFO depth is kept small, assuming that Sys-CLock > SDRAM Clock
// READ DATA + EOP
// 2. EOP indicate, last transfer of Burst Read Access. use-full for future
// Tag handling per burst
//
// ------------------------------------------------------------------------
async_fifo #(.W(dw+1), .DP(4), .WR_FAST(1'b0), .RD_FAST(1'b1) ) u_rddatafifo (
// Write Path , SDRAM clock domain
.wr_clk (sdram_clk ),
.wr_reset_n (sdram_resetn ),
.wr_en (rddatafifo_wr ),
.wr_data ({sdr_last_rd,
sdr_rd_data} ),
.afull ( ),
.full (rddatafifo_full ),
// Read Path , SYS clock domain
.rd_clk (wb_clk_i ),
.rd_reset_n (!wb_rst_i ),
.empty (rddatafifo_empty ),
.aempty ( ),
.rd_en (rddatafifo_rd ),
.rd_data ({rd_eop,
wb_dat_o} )
);
// synopsys translate_off
always @(posedge sdram_clk) begin
if (rddatafifo_full == 1'b1 && rddatafifo_wr == 1'b1) begin
$display("ERROR:%m READ DATA FIFO WRITE OVERFLOW");
end
end
always @(posedge wb_clk_i) begin
if (rddatafifo_empty == 1'b1 && rddatafifo_rd == 1'b1) begin
$display("ERROR:%m READ DATA FIFO READ OVERFLOW");
end
end
// synopsys translate_on
endmodule

View File

@ -0,0 +1,78 @@
`timescale 1ns / 1ps
module uart_rx(
input clk_50m,
input uart_rx,
output [7:0] uart_rx_data,
output uart_rx_done
);
parameter [12:0] BAUD_DIV = 13'd87;//bps115200 每位数据传输时间为t=1/115200 s,周期T=1/100000000计数值为t/T=868
parameter [12:0] BAUD_DIV_CAP = 13'd43;
reg [12:0] baud_div=0;
reg baud_bps=0;
reg bps_start=0;
always@(posedge clk_50m)
begin
if(baud_div==BAUD_DIV_CAP)
begin
baud_bps<=1'b1;
baud_div<=baud_div+1'b1;
end
else if(baud_div<BAUD_DIV && bps_start)
begin
baud_div<=baud_div+1'b1;
baud_bps<=0;
end
else
begin
baud_bps<=0;
baud_div<=0;
end
end
reg [4:0] uart_rx_r=5'b11111;
always@(posedge clk_50m)
begin
uart_rx_r<={uart_rx_r[3:0],uart_rx};
end
wire uart_rxnt=uart_rx_r[4]|uart_rx_r[3]|uart_rx_r[2]|uart_rx_r[1]|uart_rx_r[0];
reg [3:0] bit_num=0;
reg state=1'b0;
reg [7:0] uart_rx_data_r0=0;
reg [7:0] uart_rx_data_r1=0;
reg uart_rx_dong_r=0;
always@(posedge clk_50m)
begin
uart_rx_dong_r <= 0;
case(state)
1'b0 :
if(!uart_rxnt)
begin
bps_start<=1'b1;
state<=1'b1;
end
1'b1 :
if(baud_bps)
begin
bit_num<=bit_num+1'b1;
if(bit_num<4'd9)
uart_rx_data_r0[bit_num-1]<=uart_rx;
end
else if(bit_num==4'd10)
begin
bit_num<=0;
uart_rx_dong_r <= 1;
uart_rx_data_r1<=uart_rx_data_r0;
state<=1'b0;
bps_start<=0;
end
default:;
endcase
end
assign uart_rx_data=uart_rx_data_r1;
assign uart_rx_done= uart_rx_dong_r;
endmodule

View File

@ -0,0 +1,74 @@
module uart_tx(
input clk_50m,
input [7:0] uart_tx_data,
input uart_tx_en,
output uart_tx,
output uart_tx_done
);
parameter BAUD_DIV = 13'd87;
parameter BAUD_DIV_CAP = 13'd43;
reg [12:0] baud_div=0;
reg baud_bps=0;
reg [9:0] send_data=10'b1111111111;
reg [3:0] bit_num=0;
reg uart_send_flag=0;
reg uart_tx_r=1;
always@(posedge clk_50m)
begin
if(baud_div==BAUD_DIV_CAP)
begin
baud_bps<=1'b1;
baud_div<=baud_div+1'b1;
end
else if(baud_div<BAUD_DIV && uart_send_flag)
begin
baud_div<=baud_div+1'b1;
baud_bps<=0;
end
else
begin
baud_bps<=0;
baud_div<=0;
end
end
always@(posedge clk_50m)
begin
if(uart_tx_en)
begin
uart_send_flag<=1'b1;
send_data<={1'b1,uart_tx_data,1'b0};
end
else if(bit_num==4'd10)
begin
uart_send_flag<=1'b0;
send_data<=10'b1111_1111_11;
end
end
always@(posedge clk_50m)
begin
if(uart_send_flag)
begin
if(baud_bps)
begin
if(bit_num<=4'd9)
begin
uart_tx_r<=send_data[bit_num];
bit_num<=bit_num+1'b1;
end
end
else if(bit_num==4'd10)
bit_num<=4'd0;
end
else
begin
uart_tx_r<=1'b1;
bit_num<=0;
end
end
assign uart_tx=uart_tx_r;
assign uart_tx_done = (bit_num == 10) ? 1:0;
endmodule

View File

@ -0,0 +1,61 @@
module uart_rx_control
(
input clk_50m,
input rst_n,
input uart_rx_done,
input [7:0] uart_rx_data,
output [31:0] data_out_0,
output [15:0] data_out_1,
output [15:0] data_out_2,
output uart_done
);
reg [31:0] uart_data_buf_0;
reg [31:0] data_out_r_0;
reg [15:0] uart_data_buf_1;
reg [15:0] data_out_r_1;
reg [15:0] uart_data_buf_2;
reg [15:0] data_out_r_2;
reg [4:0] state;
reg uart_done_buf;
always@(posedge clk_50m or negedge rst_n)
begin
if(!rst_n)
begin
state <= 4'd0;
uart_data_buf_0 <= 32'd0;
uart_data_buf_1 <= 15'd0;
uart_data_buf_2 <= 15'd0;
uart_done_buf <= 1'd0;
end
else
begin
case(state)
5'd0:begin uart_done_buf<=1'd0; state<=state+1; end
5'd1:if((uart_rx_data == 8'h99)&&uart_rx_done)begin state<=state+1; end
5'd2:if((uart_rx_data == 8'h50)&&uart_rx_done)begin state<=state+1; end
5'd3:if(uart_rx_done)begin uart_data_buf_0[7:0]<=uart_rx_data; state<=state+1; end
5'd4:if(uart_rx_done)begin uart_data_buf_0[15:8]<=uart_rx_data; state<=state+1; end
5'd5:if(uart_rx_done)begin uart_data_buf_0[23:16]<=uart_rx_data; state<=state+1; end
5'd6:if(uart_rx_done)begin uart_data_buf_0[31:24]<=uart_rx_data; state<=state+1; end
5'd7:if(uart_rx_done)begin uart_data_buf_1[7:0]<=uart_rx_data; state<=state+1; end
5'd8:if(uart_rx_done)begin uart_data_buf_1[15:8]<=uart_rx_data; state<=state+1; end
5'd9:if(uart_rx_done)begin uart_data_buf_2[7:0]<=uart_rx_data; state<=state+1; end
5'd10:if(uart_rx_done)begin uart_data_buf_2[15:8]<=uart_rx_data; state<=state+1; end
5'd11:begin data_out_r_0<=uart_data_buf_0;
data_out_r_1<=uart_data_buf_1;
data_out_r_2<=uart_data_buf_2;
uart_done_buf<=1'd1; state<=4'd0;
end
endcase
end
end
assign data_out_0 = data_out_r_0;
assign data_out_1 = data_out_r_1;
assign data_out_2 = data_out_r_2;
assign uart_done = uart_done_buf;
endmodule

View File

@ -0,0 +1,110 @@
module uart_tx_control
(
input clk_50m,
input rst_n,
input uart_tx_done,
input start_sig,
input [31:0] uart_data_a,
input [31:0] uart_data_b,
input [1:0] mod,
output [7:0] uart_tx_data,
output tx_sig_q,
output uart_tx_en
);
parameter clk_pw_div_1 = 16'd44999;
parameter clk_pw_div_2 = 16'd249999;
reg [4:0] state;
reg [7:0] uart_tx_data_r;
reg tx_en_r;
reg tx_sig;
reg [31:0] uart_data_a_buf;
reg [31:0] uart_data_b_buf;
reg start_sig_buf;
reg [2:0] state_sweep;
reg [2:0] state_piont;
reg [22:0] clk_cnt;
always@(posedge clk_50m or negedge rst_n)
begin
if(!rst_n)
begin
start_sig_buf <= 1'd0;
state_sweep <= 3'd0;
state_piont <= 3'd0;
clk_cnt <= 23'd0;
end
else if(mod == 2'b01)//扫频
begin
state_piont <= 3'd0;
case(state_sweep)
3'd0:begin start_sig_buf<=1'd0; clk_cnt<=15'd0; state_sweep<=3'd1;end
3'd1:begin if(start_sig) state_sweep<=2'd2;end
3'd2:begin if(clk_cnt==clk_pw_div_1) state_sweep<=3'd3; else clk_cnt<=clk_cnt+23'd1;end
3'd3:begin start_sig_buf<=1'd1; state_sweep<=3'd0; end
endcase
end
else if(mod == 2'b10)//点频
begin
state_sweep <= 3'd0;
case(state_piont)
3'd0:begin start_sig_buf<=1'd0; clk_cnt<=15'd0; state_piont<=3'd1;end
3'd1:begin if(start_sig) state_piont<=2'd2;end
3'd2:begin start_sig_buf<=1'd0; if(clk_cnt==clk_pw_div_2) state_piont<=3'd3; else clk_cnt<=clk_cnt+23'd1;end
3'd3:begin start_sig_buf<=1'd1; clk_cnt<=15'd0; state_piont<=3'd2; end
endcase
end
else
begin
start_sig_buf <= 1'd0;
state_sweep <= 3'd0;
state_piont <= 3'd0;
clk_cnt <= 15'd0;
end
end
always@(posedge clk_50m or negedge rst_n)
begin
if(!rst_n)
begin
uart_data_a_buf <= 28'd0;
uart_data_b_buf <= 28'd0;
end
else if(start_sig_buf)
begin
uart_data_a_buf <= uart_data_a;
uart_data_b_buf <= uart_data_b;
end
end
always@(posedge clk_50m or negedge rst_n)
begin
if(!rst_n)
begin
state <= 5'd0;
tx_sig <= 1'd0;
uart_tx_data_r <= 8'd0;
tx_en_r <= 1'd0;
end
else
begin
case(state)
5'd0:begin if(start_sig_buf)begin state<=state+1; tx_sig<=0; tx_en_r<=1; end end
5'd1:begin uart_tx_data_r<=8'h99; tx_en_r<=1; state<=state+1; end
5'd2:begin if(uart_tx_done) begin uart_tx_data_r<=8'h24; tx_en_r<=1; state<=state+1; end end
5'd3:begin if(uart_tx_done) begin uart_tx_data_r<=uart_data_a_buf[7:0]; tx_en_r<=1; state<=state+1; end end
5'd4:begin if(uart_tx_done) begin uart_tx_data_r<=uart_data_a_buf[15:8]; tx_en_r<=1; state<=state+1; end end
5'd5:begin if(uart_tx_done) begin uart_tx_data_r<=uart_data_a_buf[23:16]; tx_en_r<=1; state<=state+1; end end
5'd6:begin if(uart_tx_done) begin uart_tx_data_r<=uart_data_a_buf[31:24]; tx_en_r<=1; state<=state+1; end end
5'd7:begin if(uart_tx_done) begin uart_tx_data_r<=uart_data_b_buf[7:0]; tx_en_r<=1; state<=state+1; end end
5'd8:begin if(uart_tx_done) begin uart_tx_data_r<=uart_data_b_buf[15:8]; tx_en_r<=1; state<=state+1; end end
5'd9:begin if(uart_tx_done) begin uart_tx_data_r<=uart_data_b_buf[23:16]; tx_en_r<=1; state<=state+1; end end
5'd10:begin if(uart_tx_done) begin uart_tx_data_r<=uart_data_b_buf[31:24]; tx_en_r<=1; state<=state+1; end end
5'd11:begin tx_en_r<=0; state<=state+1; end
5'd12:begin if(uart_tx_done) begin tx_sig<=1; state<=5'd0;end end
default:begin state <= 0; end
endcase
end
end
assign uart_tx_data = uart_tx_data_r;
assign uart_tx_en = tx_en_r;
assign tx_sig_q = tx_sig;
endmodule

View File

@ -0,0 +1,277 @@
//-------------------------------------------
// async FIFO
//-----------------------------------------------
`timescale 1ns/1ps
module async_fifo #(
parameter W = 4'd8
) (
//timing for wr
input wr_clk,
input wr_reset_n,
input wr_en,
output full,
output afull,
input [W-1 : 0] wr_data,
//timing for rd
input rd_clk,
input rd_reset_n,
input rd_en,
output empty,
output aempty,
output [W-1 : 0] rd_data
);
parameter DP = 3'd4;
parameter WR_FAST = 1'b1;
parameter RD_FAST = 1'b1;
parameter EMPTY_DP = 1'b0;
parameter FULL_DP = DP;
parameter AW = (DP == 2) ? 1 :
(DP == 4) ? 2 :
(DP == 8) ? 3 :
(DP == 16) ? 4 :
(DP == 32) ? 5 :
(DP == 64) ? 6 :
(DP == 128) ? 7 :
(DP == 256) ? 8 : 0;
// synopsys translate_off
initial begin
if (AW == 0) begin
$display ("%m : ERROR!!! Fifo depth %d not in range 2 to 256", DP);
end // if (AW == 0)
end // initial begin
// synopsys translate_on
reg [W-1 : 0] mem[DP-1 : 0];
/*********************** write side ************************/
reg [AW:0] sync_rd_ptr_0, sync_rd_ptr_1;
wire [AW:0] sync_rd_ptr;
reg [AW:0] wr_ptr, grey_wr_ptr;
reg [AW:0] grey_rd_ptr;
reg full_q;
wire full_c;
wire afull_c;
wire [AW:0] wr_ptr_inc = wr_ptr + 1'b1;
wire [AW:0] wr_cnt = get_cnt(wr_ptr, sync_rd_ptr);
assign full_c = (wr_cnt == FULL_DP) ? 1'b1 : 1'b0;
assign afull_c = (wr_cnt == FULL_DP-1) ? 1'b1 : 1'b0;
always @(posedge wr_clk or negedge wr_reset_n) begin
if (!wr_reset_n) begin
wr_ptr <= 0;
grey_wr_ptr <= 0;
full_q <= 0;
end
else if (wr_en) begin
wr_ptr <= wr_ptr_inc;
grey_wr_ptr <= bin2grey(wr_ptr_inc);
if (wr_cnt == (FULL_DP-1)) begin
full_q <= 1'b1;
end
end
else begin
if (full_q && (wr_cnt<FULL_DP)) begin
full_q <= 1'b0;
end
end
end
assign full = (WR_FAST == 1) ? full_c : full_q;
assign afull = afull_c;
always @(posedge wr_clk) begin
if (wr_en) begin
mem[wr_ptr[AW-1:0]] <= wr_data;
end
end
wire [AW:0] grey_rd_ptr_dly ;
assign #1 grey_rd_ptr_dly = grey_rd_ptr;
// read pointer synchronizer
always @(posedge wr_clk or negedge wr_reset_n) begin
if (!wr_reset_n) begin
sync_rd_ptr_0 <= 0;
sync_rd_ptr_1 <= 0;
end
else begin
sync_rd_ptr_0 <= grey_rd_ptr_dly;
sync_rd_ptr_1 <= sync_rd_ptr_0;
end
end
assign sync_rd_ptr = grey2bin(sync_rd_ptr_1);
/************************ read side *****************************/
reg [AW:0] sync_wr_ptr_0, sync_wr_ptr_1;
wire [AW:0] sync_wr_ptr;
reg [AW:0] rd_ptr;
reg empty_q;
wire empty_c;
wire aempty_c;
wire [AW:0] rd_ptr_inc = rd_ptr + 1'b1;
wire [AW:0] sync_wr_ptr_dec = sync_wr_ptr - 1'b1;
wire [AW:0] rd_cnt = get_cnt(sync_wr_ptr, rd_ptr);
assign empty_c = (rd_cnt == 0) ? 1'b1 : 1'b0;
assign aempty_c = (rd_cnt == 1) ? 1'b1 : 1'b0;
always @(posedge rd_clk or negedge rd_reset_n) begin
if (!rd_reset_n) begin
rd_ptr <= 0;
grey_rd_ptr <= 0;
empty_q <= 1'b1;
end
else begin
if (rd_en) begin
rd_ptr <= rd_ptr_inc;
grey_rd_ptr <= bin2grey(rd_ptr_inc);
if (rd_cnt==(EMPTY_DP+1)) begin
empty_q <= 1'b1;
end
end
else begin
if (empty_q && (rd_cnt!=EMPTY_DP)) begin
empty_q <= 1'b0;
end
end
end
end
assign empty = (RD_FAST == 1) ? empty_c : empty_q;
assign aempty = aempty_c;
reg [W-1 : 0] rd_data_q;
wire [W-1 : 0] rd_data_c = mem[rd_ptr[AW-1:0]];
always @(posedge rd_clk) begin
rd_data_q <= rd_data_c;
end
assign rd_data = (RD_FAST == 1) ? rd_data_c : rd_data_q;
wire [AW:0] grey_wr_ptr_dly ;
assign #1 grey_wr_ptr_dly = grey_wr_ptr;
// write pointer synchronizer
always @(posedge rd_clk or negedge rd_reset_n) begin
if (!rd_reset_n) begin
sync_wr_ptr_0 <= 0;
sync_wr_ptr_1 <= 0;
end
else begin
sync_wr_ptr_0 <= grey_wr_ptr_dly;
sync_wr_ptr_1 <= sync_wr_ptr_0;
end
end
assign sync_wr_ptr = grey2bin(sync_wr_ptr_1);
/************************ functions ******************************/
function [AW:0] bin2grey;
input [AW:0] bin;
reg [8:0] bin_8;
reg [8:0] grey_8;
begin
bin_8 = bin;
grey_8[1:0] = do_grey(bin_8[2:0]);
grey_8[3:2] = do_grey(bin_8[4:2]);
grey_8[5:4] = do_grey(bin_8[6:4]);
grey_8[7:6] = do_grey(bin_8[8:6]);
grey_8[8] = bin_8[8];
bin2grey = grey_8;
end
endfunction
function [AW:0] grey2bin;
input [AW:0] grey;
reg [8:0] grey_8;
reg [8:0] bin_8;
begin
grey_8 = grey;
bin_8[8] = grey_8[8];
bin_8[7:6] = do_bin({bin_8[8], grey_8[7:6]});
bin_8[5:4] = do_bin({bin_8[6], grey_8[5:4]});
bin_8[3:2] = do_bin({bin_8[4], grey_8[3:2]});
bin_8[1:0] = do_bin({bin_8[2], grey_8[1:0]});
grey2bin = bin_8;
end
endfunction
function [1:0] do_grey;
input [2:0] bin;
begin
if (bin[2]) begin // do reverse grey
case (bin[1:0])
2'b00: do_grey = 2'b10;
2'b01: do_grey = 2'b11;
2'b10: do_grey = 2'b01;
2'b11: do_grey = 2'b00;
endcase
end
else begin
case (bin[1:0])
2'b00: do_grey = 2'b00;
2'b01: do_grey = 2'b01;
2'b10: do_grey = 2'b11;
2'b11: do_grey = 2'b10;
endcase
end
end
endfunction
function [1:0] do_bin;
input [2:0] grey;
begin
if (grey[2]) begin // actually bin[2]
case (grey[1:0])
2'b10: do_bin = 2'b00;
2'b11: do_bin = 2'b01;
2'b01: do_bin = 2'b10;
2'b00: do_bin = 2'b11;
endcase
end
else begin
case (grey[1:0])
2'b00: do_bin = 2'b00;
2'b01: do_bin = 2'b01;
2'b11: do_bin = 2'b10;
2'b10: do_bin = 2'b11;
endcase
end
end
endfunction
function [AW:0] get_cnt;
input [AW:0] wr_ptr, rd_ptr;
begin
if (wr_ptr >= rd_ptr) begin
get_cnt = (wr_ptr - rd_ptr);
end
else begin
get_cnt = DP*2 - (rd_ptr - wr_ptr);
end
end
endfunction
// synopsys translate_off
always @(posedge wr_clk) begin
if (wr_en && full) begin
$display($time, "%m Error! afifo overflow!");
$stop;
end
end
always @(posedge rd_clk) begin
if (rd_en && empty) begin
$display($time, "%m error! afifo underflow!");
$stop;
end
end
// synopsys translate_on
endmodule

View File

@ -0,0 +1,101 @@
`timescale 1ns/1ps
module sync_fifo #(
parameter W = 8
)
(
input clk,
input reset_n,
input rd_en,
output [W-1 : 0] rd_data,
input wr_en,
input [W-1 : 0] wr_data,
output reg full,
output reg empty
);
parameter D = 4;
parameter AW = (D == 4) ? 2 :
(D == 8) ? 3 :
(D == 16) ? 4 :
(D == 32) ? 5 :
(D == 64) ? 6 :
(D == 128) ? 7 :
(D == 256) ? 8 : 0;
// synopsys translate_off
initial begin
if (AW == 0) begin
$display ("%m : ERROR!!! Fifo depth %d not in range 4 to 256", D);
end // if (AW == 0)
end // initial begin
// synopsys translate_on
reg [W-1 : 0] mem[D-1 : 0];
reg [AW-1 : 0] rd_ptr, wr_ptr;
always @ (posedge clk or negedge reset_n)
if (reset_n == 1'b0) begin
wr_ptr <= {AW{1'b0}} ;
end
else begin
if (wr_en & !full) begin
wr_ptr <= wr_ptr + 1'b1 ;
end
end
always @ (posedge clk or negedge reset_n)
if (reset_n == 1'b0) begin
rd_ptr <= {AW{1'b0}} ;
end
else begin
if (rd_en & !empty) begin
rd_ptr <= rd_ptr + 1'b1 ;
end
end
always @ (posedge clk or negedge reset_n)
if (reset_n == 1'b0) begin
empty <= 1'b1 ;
end
else begin
empty <= (((wr_ptr - rd_ptr) == {{(AW-1){1'b0}}, 1'b1}) & rd_en & ~wr_en) ? 1'b1 :
((wr_ptr == rd_ptr) & ~rd_en & wr_en) ? 1'b0 : empty ;
end
always @ (posedge clk or negedge reset_n)
if (reset_n == 1'b0) begin
full <= 1'b0 ;
end
else begin
full <= (((wr_ptr - rd_ptr) == {{(AW-1){1'b1}}, 1'b0}) & ~rd_en & wr_en) ? 1'b1 :
(((wr_ptr - rd_ptr) == {AW{1'b1}}) & rd_en & ~wr_en) ? 1'b0 : full ;
end
always @ (posedge clk)
if (wr_en)
mem[wr_ptr] <= wr_data;
assign rd_data = mem[rd_ptr];
// synopsys translate_off
always @(posedge clk) begin
if (wr_en && full) begin
$display("%m : Error! sfifo overflow!");
end
end
always @(posedge clk) begin
if (rd_en && empty) begin
$display("%m : error! sfifo underflow!");
end
end
// synopsys translate_on
//---------------------------------------
endmodule

View File

@ -0,0 +1,33 @@
module Line_Shift_RAM #(
parameter RAM_Length = 640, //640*480
parameter DATA_WIDTH = 8
) (
input clken,
input clock,
input [DATA_WIDTH-1:0] shiftin,
output [DATA_WIDTH-1:0] taps0x,
output [DATA_WIDTH-1:0] taps1x
);
RAMshift_taps #(
.TOTAL_RAM_Length (RAM_Length),
.DATA_WIDTH (DATA_WIDTH)
) RAMshfit_taps_u1 (
.clken(clken),
.clock(clock),
.Delay_Length(RAM_Length),
.shiftin(shiftin),
.shiftout(taps0x)
);
RAMshift_taps #(
.TOTAL_RAM_Length (RAM_Length),
.DATA_WIDTH (DATA_WIDTH)
) RAMshfit_taps_u2 (
.clken(clken),
.clock(clock),
.Delay_Length(RAM_Length),
.shiftin(taps0x),
.shiftout(taps1x)
);
endmodule

View File

@ -0,0 +1,46 @@
`timescale 1 ns / 1 ns
module RAMshift_taps #(
parameter TOTAL_RAM_Length = 640,
parameter DATA_WIDTH = 8
) (
input clken,
input clock,
input [31:0] Delay_Length,
input [DATA_WIDTH - 1 : 0] shiftin,
output [DATA_WIDTH - 1 : 0] shiftout
);
reg [31:0] RAM_CNT = 0;
reg [DATA_WIDTH - 1 : 0] ram_buf = 0;
reg [DATA_WIDTH - 1 : 0] shift_ram [TOTAL_RAM_Length - 1 : 0];
integer m;
initial begin
for (m = 0; m<=TOTAL_RAM_Length; m=m+1) begin
shift_ram[m] = 0;
end
end
always @(posedge clock) begin
if (RAM_CNT == (Delay_Length - 1))
RAM_CNT <= 0;
else if (clken)
RAM_CNT <= RAM_CNT + 1;
else
RAM_CNT <= RAM_CNT;
end
always @(posedge clock) begin
if (clken) begin
shift_ram[RAM_CNT] <= shiftin;
end
else begin
shift_ram[RAM_CNT] <= shift_ram[RAM_CNT];
end
end
assign shiftout = shift_ram[RAM_CNT];
endmodule

258
lib/common/Math/Cordic.v Normal file
View File

@ -0,0 +1,258 @@
`timescale 1ns / 1ps
module Cordic #(
parameter XY_BITS = 12,
parameter PH_BITS = 32,
parameter ITERATIONS = 32,
parameter CORDIC_STYLE = "ROTATE",
parameter PHASE_ACC = "ON"
)(
input clk,
input RST,
input signed [XY_BITS-1:0] x_i,
input signed [XY_BITS-1:0] y_i,
input signed [PH_BITS-1:0] phase_in,
output signed [XY_BITS-1:0] x_o,
output signed [XY_BITS-1:0] y_o,
output signed [PH_BITS-1:0] phase_out,
input valid_in,
output valid_out
);
localparam [XY_BITS-1:0] K_COS = (0.607252935 * 2**(XY_BITS-1))-2;
/*
//360°--2^16,phase_in = 16bits (input [15:0] phase_in)
//1°--2^16/360
*/
function [PH_BITS-1:0] tanangle;
input [4:0] i;
begin
case (i)
5'b00000: tanangle = (32'h20000000 >> (32 - PH_BITS)); //tan = 1/2^1 = 1/2
5'b00001: tanangle = (32'h12e4051e >> (32 - PH_BITS)); //tan = 1/2^2 = 1/4
5'b00010: tanangle = (32'h09fb385b >> (32 - PH_BITS)); //tan = 1/2^3 = 1/8
5'b00011: tanangle = (32'h051111d4 >> (32 - PH_BITS)); //tan = 1/2^4 = 1/16
5'b00100: tanangle = (32'h028b0d43 >> (32 - PH_BITS)); //tan = 1/2^5 = 1/32
5'b00101: tanangle = (32'h0145d7e1 >> (32 - PH_BITS)); //tan = 1/2^6 = 1/64
5'b00110: tanangle = (32'h00a2f61e >> (32 - PH_BITS)); //tan = 1/2^7 = 1/128
5'b00111: tanangle = (32'h00517c55 >> (32 - PH_BITS)); //tan = 1/2^8 = 1/256
5'b01000: tanangle = (32'h0028be53 >> (32 - PH_BITS)); //tan = 1/2^9 = 1/512
5'b01001: tanangle = (32'h00145f2f >> (32 - PH_BITS)); //tan = 1/2^10 = 1/1024
5'b01010: tanangle = (32'h000a2f98 >> (32 - PH_BITS)); //tan = 1/2^11 = 1/2048
5'b01011: tanangle = (32'h000517cc >> (32 - PH_BITS)); //tan = 1/2^12 = 1/4096
5'b01100: tanangle = (32'h00028be6 >> (32 - PH_BITS)); //tan = 1/2^13 = 1/8192
5'b01101: tanangle = (32'h000145f3 >> (32 - PH_BITS)); //tan = 1/2^14 = 1/16384
5'b01110: tanangle = (32'h0000a2fa >> (32 - PH_BITS)); //tan = 1/2^15 = 1/32768
5'b01111: tanangle = (32'h0000517d >> (32 - PH_BITS)); //tan = 1/2^16 = 1/65536
5'b10000: tanangle = (32'h000028be >> (32 - PH_BITS)); //tan = 1/2^17 = 1/131072
5'b10001: tanangle = (32'h0000145f >> (32 - PH_BITS)); //tan = 1/2^18 = 1/262144
5'b10010: tanangle = (32'h00000a30 >> (32 - PH_BITS)); //tan = 1/2^19 = 1/524288
5'b10011: tanangle = (32'h00000518 >> (32 - PH_BITS)); //tan = 1/2^20 = 1/1048576
5'b10100: tanangle = (32'h0000028c >> (32 - PH_BITS)); //tan = 1/2^21 = 1/2097152
5'b10101: tanangle = (32'h00000146 >> (32 - PH_BITS)); //tan = 1/2^22 = 1/4194304
5'b10110: tanangle = (32'h000000a3 >> (32 - PH_BITS)); //tan = 1/2^23 = 1/8388608
5'b10111: tanangle = (32'h00000051 >> (32 - PH_BITS)); //tan = 1/2^24 = 1/16777216
5'b11000: tanangle = (32'h00000029 >> (32 - PH_BITS)); //tan = 1/2^25 = 1/33554432
5'b11001: tanangle = (32'h00000014 >> (32 - PH_BITS)); //tan = 1/2^26 = 1/67108864
5'b11010: tanangle = (32'h0000000a >> (32 - PH_BITS)); //tan = 1/2^27 = 1/134217728
5'b11011: tanangle = (32'h00000005 >> (32 - PH_BITS)); //tan = 1/2^28 = 1/268435456
5'b11100: tanangle = (32'h00000003 >> (32 - PH_BITS)); //tan = 1/2^29 = 1/536870912
5'b11101: tanangle = (32'h00000001 >> (32 - PH_BITS)); //tan = 1/2^30 = 1/1073741824
5'b11110: tanangle = (32'h00000001 >> (32 - PH_BITS)); //tan = 1/2^31 = 1/2147483648
5'b11111: tanangle = (32'h00000000 >> (32 - PH_BITS)); //tan = 1/2^32 = 1/4294967296
endcase
end
endfunction
reg [1:0] data_in_buff [ITERATIONS:0];
reg signed [XY_BITS-1:0] x [ITERATIONS:0];
reg signed [XY_BITS-1:0] y [ITERATIONS:0];
reg signed [PH_BITS-1:0] z [ITERATIONS:0];
integer m;
initial begin
for (m = 0; m<=ITERATIONS; m=m+1) begin
x[m] = 0;
end
end
integer n;
initial begin
for (n = 0; n<=ITERATIONS; n=n+1) begin
y[n] = 0;
end
end
integer s;
initial begin
for (s = 0; s<=ITERATIONS; s=s+1) begin
z[s] = 0;
end
end
integer k;
initial begin
for (k = 0; k<=ITERATIONS; k=k+1) begin
data_in_buff[k] = 0;
end
end
genvar i;
generate for(i=0;i<ITERATIONS;i=i+1) begin : CORDIC
always @ (posedge clk) begin
if (RST) begin
x[i+1] <= 0;
y[i+1] <= 0;
z[i+1] <= 0;
end
else begin
if (CORDIC_STYLE == "ROTATE") begin
if (z[i] < 0) begin
x[i+1] <= x[i] + (y[i]>>>i);
y[i+1] <= y[i] - (x[i]>>>i);
z[i+1] <= z[i] + tanangle(i);
end
else begin
x[i+1] <= x[i] - (y[i]>>>i);
y[i+1] <= y[i] + (x[i]>>>i);
z[i+1] <= z[i] - tanangle(i);
end
end
else if(CORDIC_STYLE == "VECTOR") begin
if (y[i] > 0) begin
x[i+1] <= x[i] + (y[i]>>>i);
y[i+1] <= y[i] - (x[i]>>>i);
z[i+1] <= z[i] + tanangle(i);
end else begin
x[i+1] <= x[i] - (y[i]>>>i);
y[i+1] <= y[i] + (x[i]>>>i);
z[i+1] <= z[i] - tanangle(i);
end
end
end
end
always @ (posedge clk) begin
data_in_buff[i+1] <= data_in_buff[i];
end
end
endgenerate
generate if (CORDIC_STYLE == "ROTATE") begin : IQ_Gen
reg [PH_BITS - 1 : 0] Phase_input = 0;
if (PHASE_ACC == "ON") begin
reg [PH_BITS - 1 : 0] addr_r0 = 0;
always @(posedge clk) begin
addr_r0 <= addr_r0 + phase_in;
end
always @(posedge clk) begin
Phase_input <= addr_r0;
end
end
else if (PHASE_ACC == "OFF") begin
always @(posedge clk) begin
Phase_input <= phase_in;
end
end
always @(posedge clk) begin
if(valid_in & (~RST)) begin
x[0] <= K_COS;
y[0] <= 0;
z[0] <= Phase_input[PH_BITS - 3 : 0];
data_in_buff[0] <= Phase_input[PH_BITS - 1 : PH_BITS - 2];
end
else begin
x[0] <= 0;
y[0] <= 0;
z[0] <= 0;
data_in_buff[0] <= 0;
end
end
reg signed [XY_BITS-1:0] cos = 0;
reg signed [XY_BITS-1:0] sin = 0;
always @ (posedge clk) begin
case(data_in_buff[ITERATIONS])
2'b00:begin //if the phase is in first quadrant,the sin(X)=sin(A),cos(X)=cos(A)
cos <= x[ITERATIONS];
sin <= y[ITERATIONS];
end
2'b01:begin //if the phase is in second quadrant,the sin(X)=sin(A+90)=cosA,cos(X)=cos(A+90)=-sinA
cos <= ~(y[ITERATIONS]) + 1'b1;//-sin
sin <= x[ITERATIONS];//cos
end
2'b10:begin //if the phase is in third quadrant,the sin(X)=sin(A+180)=-sinA,cos(X)=cos(A+180)=-cosA
cos <= ~(x[ITERATIONS]) + 1'b1;//-cos
sin <= ~(y[ITERATIONS]) + 1'b1;//-sin
end
2'b11:begin //if the phase is in forth quadrant,the sin(X)=sin(A+270)=-cosA,cos(X)=cos(A+270)=sinA
cos <= y[ITERATIONS];//sin
sin <= ~(x[ITERATIONS]) + 1'b1;//-cos
end
endcase
end
assign x_o = cos;
assign y_o = sin;
assign phase_out = z[ITERATIONS];
end
endgenerate
generate if (CORDIC_STYLE == "VECTOR") begin : Demodule_Gen
localparam signed [PH_BITS-1:0] PHASE_COE = (2**(PH_BITS-2)) - 1;
//localparam MODUIUS_COE = ;
always @(posedge clk) begin
if(valid_in & (~RST)) begin
case ({x_i[XY_BITS-1],y_i[XY_BITS-1]})
2'b00 : begin x[0] <= {x_i[XY_BITS-1],x_i[XY_BITS-1:1]};
y[0] <= {y_i[XY_BITS-1],y_i[XY_BITS-1:1]}; end
2'b01 : begin x[0] <= {x_i[XY_BITS-1],x_i[XY_BITS-1:1]};
y[0] <= {y_i[XY_BITS-1],y_i[XY_BITS-1:1]}; end
2'b10 : begin x[0] <= {y_i[XY_BITS-1],y_i[XY_BITS-1:1]};
y[0] <= -{x_i[XY_BITS-1],x_i[XY_BITS-1:1]}; end
2'b11 : begin x[0] <= -{y_i[XY_BITS-1],y_i[XY_BITS-1:1]};
y[0] <= {x_i[XY_BITS-1],x_i[XY_BITS-1:1]}; end
default : begin x[0] <= {x_i[XY_BITS-1],x_i[XY_BITS-1:1]};
y[0] <= {y_i[XY_BITS-1],y_i[XY_BITS-1:1]}; end
endcase
z[0] <= phase_in;
data_in_buff[0] <= {x_i[XY_BITS-1],y_i[XY_BITS-1]};
end
else begin
x[0] <= 0;
y[0] <= 0;
z[0] <= 0;
data_in_buff[0] <= 0;
end
end
reg [XY_BITS*2-1:0] Modulus = 0;
wire [XY_BITS*2-1:0] Modulus_buf;
reg signed [PH_BITS - 1:0] phase_r = 0;
always @ (posedge clk) begin
case(data_in_buff[ITERATIONS])
2'b00:begin phase_r <= $signed(z[ITERATIONS]); end
2'b01:begin phase_r <= $signed(z[ITERATIONS]); end
2'b10:begin phase_r <= $signed(z[ITERATIONS]) + $signed(PHASE_COE); end
2'b11:begin phase_r <= $signed(z[ITERATIONS]) - $signed(PHASE_COE); end
endcase
Modulus[XY_BITS:0] <= x[ITERATIONS];
end
assign Modulus_buf = (Modulus * 32'd39797)>>15;
assign x_o = Modulus_buf[XY_BITS-1:0];
assign y_o = y[ITERATIONS];
assign phase_out = phase_r;
end
endgenerate
reg [ITERATIONS+1:0] v = 0;
always @ (posedge clk) begin
if (RST)
v <= 0;
else begin
v <= v << 1;
v[0] <= valid_in;
end
end
assign valid_out = v[ITERATIONS+1];
endmodule

45
lib/common/Math/Sort3.v Normal file
View File

@ -0,0 +1,45 @@
`timescale 1ns/1ns
module Sort3 (
input clk,
input rst_n,
input [7:0] data1, data2, data3,
output reg [7:0] max_data, mid_data, min_data
);
//-----------------------------------
//Sort of 3 datas
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
max_data <= 0;
mid_data <= 0;
min_data <= 0;
end
else begin
//get the max value
if(data1 >= data2 && data1 >= data3)
max_data <= data1;
else if(data2 >= data1 && data2 >= data3)
max_data <= data2;
else//(data3 >= data1 && data3 >= data2)
max_data <= data3;
//get the mid value
if((data1 >= data2 && data1 <= data3) || (data1 >= data3 && data1 <= data2))
mid_data <= data1;
else if((data2 >= data1 && data2 <= data3) || (data2 >= data3 && data2 <= data1))
mid_data <= data2;
else//((data3 >= data1 && data3 <= data2) || (data3 >= data2 && data3 <= data1))
mid_data <= data3;
//ge the min value
if(data1 <= data2 && data1 <= data3)
min_data <= data1;
else if(data2 <= data1 && data2 <= data3)
min_data <= data2;
else//(data3 <= data1 && data3 <= data2)
min_data <= data3;
end
end
endmodule

View File

@ -0,0 +1,63 @@
module phase_acc(clr,en,rst,valid_out1,clk,add_sub,sel,D,Q);
parameter DATASIZE=16;
input clr,en,rst,clk,add_sub,sel,valid_out1;
input [DATASIZE-1:0] D;
output [DATASIZE:0] Q;
reg count0,count1,count2,count3;
reg [DATASIZE:0] b_tmp,b_tmp0,b_tmp1,b_tmp2;
reg [3:0] sum0;
reg [7:0] sum1;
reg [11:0] sum2;
reg [16:0] sum3;
reg add_sub0,add_sub1,add_sub2;
reg clr0,clr1,clr2;
always @(posedge clk) begin
case({clr,add_sub})
2'b00:{count0,sum0}<={1'b0,sum0}+{1'b0,D[3:0]};
2'b01:{count0,sum0}<={1'b0,sum0}-{1'b0,D[3:0]};
2'b10:{count0,sum0}<=5'b0+{1'b0,D[3:0]};
default:{count0,sum0}<=5'b0-{1'b0,D[3:0]};
endcase
b_tmp0<=D;
clr0<=clr;
add_sub0<=add_sub;
end
always @(posedge clk)
begin
case({clr0,add_sub0})
2'b00:{count1,sum1}<={{1'b0,sum1[7:4]}+{1'b0,b_tmp0[7:4]}+count0,sum0};
2'b01:{count1,sum1}<={{1'b0,sum1[7:4]}-{1'b0,b_tmp0[7:4]}-count0,sum0};
2'b10:{count1,sum1}<=5'b0+{1'b0,b_tmp0[7:4]};
default:{count1,sum1}<=5'b0-{1'b0,b_tmp0[7:4]};
endcase
b_tmp1<=b_tmp0;
clr1<=clr0;
add_sub1<=add_sub0;
end
always @(posedge clk)
begin
case({clr1,add_sub1})
2'b00:{count2,sum2}<={{1'b0,sum2[11:8]}+{1'b0,b_tmp1[11:8]}+count1,sum1};
2'b01:{count2,sum2}<={{1'b0,sum2[11:8]}-{1'b0,b_tmp1[11:8]}-count1,sum1};
2'b10:{count2,sum2}<=5'b0+{1'b0,b_tmp1[11:8]};
default:{count2,sum2}<=5'b0-{1'b0,b_tmp1[11:8]};
endcase
b_tmp2<=b_tmp1;
clr2<=clr1;
add_sub2<=add_sub1;
end
always @(posedge clk) begin
case({clr2,add_sub2})
2'b00:sum3<={sum3[16:12]+{1'b0,b_tmp2[15:12]}+count2,sum2};
2'b01:sum3<={sum3[16:12]-{1'b0,b_tmp2[15:12]}-count2,sum2};
2'b10:sum3<=5'b0+{1'b0,b_tmp2[15:12]};
default:sum3<=5'b0-{1'b0,b_tmp2[15:12]};
endcase
end
assign Q=sum3;
endmodule

View File

@ -0,0 +1,299 @@
`timescale 1 ns / 1 ps
module AXI #(
parameter integer OUTPUT_WIDTH = 12,
parameter integer PHASE_WIDTH = 32,
parameter integer C_S_AXI_DATA_WIDTH = 32,
parameter integer C_S_AXI_ADDR_WIDTH = 4
) (
// Users to add ports here
// User ports ends
// Do not modify the ports beyond this line
input wire S_AXI_ACLK,
input wire S_AXI_ARESETN,
input wire S_AXI_WVALID,
output wire S_AXI_RVALID,
output wire S_AXI_WREADY,
input wire S_AXI_RREADY,
input wire S_AXI_AWVALID,
input wire S_AXI_ARVALID,
output wire S_AXI_AWREADY,
output wire S_AXI_ARREADY,
input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR,
input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR,
input wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA,
output wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA,
input wire [2 : 0] S_AXI_AWPROT,
input wire [2 : 0] S_AXI_ARPROT,
output wire [1 : 0] S_AXI_BRESP,
output wire [1 : 0] S_AXI_RRESP,
output wire S_AXI_BVALID,
input wire S_AXI_BREADY,
input wire [(C_S_AXI_DATA_WIDTH/8)-1 : 0] S_AXI_WSTRB
);
// AXI4LITE signals
reg axi_awready;
reg axi_arready;
reg axi_bvalid;
reg axi_rvalid;
reg axi_wready;
reg [1 : 0] axi_bresp;
reg [1 : 0] axi_rresp;
reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_awaddr;
reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_araddr;
reg [C_S_AXI_DATA_WIDTH-1 : 0] axi_rdata;
// Example-specific design signals
// local parameter for addressing 32 bit / 64 bit C_S_AXI_DATA_WIDTH
// ADDR_LSB is used for addressing 32/64 bit registers/memories
// ADDR_LSB = 2 for 32 bits (n downto 2)
// ADDR_LSB = 3 for 64 bits (n downto 3)
localparam integer ADDR_LSB = (C_S_AXI_DATA_WIDTH/32) + 1;
localparam integer OPT_MEM_ADDR_BITS = 1;
//----------------------------------------------
//-- Signals for user logic register space example
//------------------------------------------------
//-- Number of Slave Registers 4
reg aw_en;
wire slv_reg_rden;
wire slv_reg_wren;
reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg0;
reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg1;
reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg2;
reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg3;
reg [C_S_AXI_DATA_WIDTH-1:0] reg_data_out;
integer byte_index;
// I/O Connections assignments
assign S_AXI_AWREADY = axi_awready;
assign S_AXI_WREADY = axi_wready;
assign S_AXI_BRESP = axi_bresp;
assign S_AXI_BVALID = axi_bvalid;
assign S_AXI_ARREADY = axi_arready;
assign S_AXI_RDATA = axi_rdata;
assign S_AXI_RRESP = axi_rresp;
assign S_AXI_RVALID = axi_rvalid;
// Implement axi_awready generation
// axi_awready is asserted for one S_AXI_ACLK clock cycle when both
// S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_awready is
// de-asserted when reset is low.
always @( posedge S_AXI_ACLK ) begin
if ( S_AXI_ARESETN == 1'b0 ) begin
axi_awready <= 1'b0;
aw_en <= 1'b1;
end
else begin
if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en) begin
axi_awready <= 1'b1;
aw_en <= 1'b0;
end
else if (S_AXI_BREADY && axi_bvalid) begin
aw_en <= 1'b1;
axi_awready <= 1'b0;
end
else begin
axi_awready <= 1'b0;
end
end
end
// Implement axi_awaddr latching
// This process is used to latch the address when both
// S_AXI_AWVALID and S_AXI_WVALID are valid.
always @( posedge S_AXI_ACLK ) begin
if ( S_AXI_ARESETN == 1'b0 ) begin
axi_awaddr <= 0;
end
else begin
if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en) begin
// Write Address latching
axi_awaddr <= S_AXI_AWADDR;
end
end
end
// Implement axi_wready generation
// axi_wready is asserted for one S_AXI_ACLK clock cycle when both
// S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_wready is
// de-asserted when reset is low.
always @( posedge S_AXI_ACLK ) begin
if ( S_AXI_ARESETN == 1'b0 ) begin
axi_wready <= 1'b0;
end
else begin
if (~axi_wready && S_AXI_WVALID && S_AXI_AWVALID && aw_en ) begin
axi_wready <= 1'b1;
end
else begin
axi_wready <= 1'b0;
end
end
end
// Implement write response logic generation
// The write response and response valid signals are asserted by the slave
// when axi_wready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted.
// This marks the acceptance of address and indicates the status of
// write transaction.
always @( posedge S_AXI_ACLK ) begin
if ( S_AXI_ARESETN == 1'b0 ) begin
axi_bvalid <= 0;
axi_bresp <= 2'b0;
end
else begin
if (axi_awready && S_AXI_AWVALID && ~axi_bvalid && axi_wready && S_AXI_WVALID) begin
// indicates a valid write response is available
axi_bvalid <= 1'b1;
axi_bresp <= 2'b0; // 'OKAY' response
end // work error responses in future
else begin
if (S_AXI_BREADY && axi_bvalid) begin
axi_bvalid <= 1'b0;
end
end
end
end
// Implement axi_arready generation
// axi_arready is asserted for one S_AXI_ACLK clock cycle when
// S_AXI_ARVALID is asserted. axi_awready is
// de-asserted when reset (active low) is asserted.
// The read address is also latched when S_AXI_ARVALID is
// asserted. axi_araddr is reset to zero on reset assertion.
always @( posedge S_AXI_ACLK ) begin
if ( S_AXI_ARESETN == 1'b0 ) begin
axi_arready <= 1'b0;
axi_araddr <= 32'b0;
end
else begin
if (~axi_arready && S_AXI_ARVALID) begin
// indicates that the slave has acceped the valid read address
axi_arready <= 1'b1;
// Read address latching
axi_araddr <= S_AXI_ARADDR;
end
else begin
axi_arready <= 1'b0;
end
end
end
// Implement axi_arvalid generation
// axi_rvalid is asserted for one S_AXI_ACLK clock cycle when both
// S_AXI_ARVALID and axi_arready are asserted. The slave registers
// data are available on the axi_rdata bus at this instance. The
// assertion of axi_rvalid marks the validity of read data on the
// bus and axi_rresp indicates the status of read transaction.axi_rvalid
// is deasserted on reset (active low). axi_rresp and axi_rdata are
// cleared to zero on reset (active low).
always @( posedge S_AXI_ACLK ) begin
if ( S_AXI_ARESETN == 1'b0 ) begin
axi_rvalid <= 0;
axi_rresp <= 0;
end
else begin
if (axi_arready && S_AXI_ARVALID && ~axi_rvalid) begin
// Valid read data is available at the read data bus
axi_rvalid <= 1'b1;
axi_rresp <= 2'b0; // 'OKAY' response
end
else if (axi_rvalid && S_AXI_RREADY) begin
// Read data is accepted by the master
axi_rvalid <= 1'b0;
end
end
end
// Output register or memory read data
always @( posedge S_AXI_ACLK ) begin
if ( S_AXI_ARESETN == 1'b0 ) begin
axi_rdata <= 0;
end
else begin
if (slv_reg_rden) begin
axi_rdata <= reg_data_out; // register read data
end
end
end
// Implement memory mapped register select and write logic generation
// The write data is accepted and written to memory mapped registers when
// axi_awready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. Write strobes are used to
// select byte enables of slave registers while writing.
// These registers are cleared when reset (active low) is applied.
// Slave register write enable is asserted when valid address and data are available
// and the slave is ready to accept the write address and write data.
assign slv_reg_wren = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID;
always @( posedge S_AXI_ACLK ) begin
if ( S_AXI_ARESETN == 1'b0 ) begin
slv_reg0 <= 0;
slv_reg1 <= 0;
slv_reg2 <= 0;
slv_reg3 <= 0;
end
else begin
if (slv_reg_wren) begin
case ( axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
4'd0:for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
if ( S_AXI_WSTRB[byte_index] == 1 ) begin
slv_reg0[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
end
4'd1:for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
if ( S_AXI_WSTRB[byte_index] == 1 ) begin
slv_reg1[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
end
4'd2:for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
if ( S_AXI_WSTRB[byte_index] == 1 ) begin
slv_reg2[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
end
4'd3:for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
if ( S_AXI_WSTRB[byte_index] == 1 ) begin
slv_reg3[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
end
default :
begin
slv_reg0 <= slv_reg0;
slv_reg1 <= slv_reg1;
slv_reg2 <= slv_reg2;
slv_reg3 <= slv_reg3;
end
endcase
end
end
end
// Implement memory mapped register select and read logic generation
// Slave register read enable is asserted when valid address is available
// and the slave is ready to accept the read address.
assign slv_reg_rden = axi_arready & S_AXI_ARVALID & ~axi_rvalid;
always @(*) begin
case ( axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
4'd0 : reg_data_out <= slv_reg0;
4'd1 : reg_data_out <= slv_reg1;
4'd2 : reg_data_out <= slv_reg2;
4'd3 : reg_data_out <= slv_reg3;
default : reg_data_out <= 0;
endcase
end
// Add user logic here
// User logic ends
endmodule

Some files were not shown because too many files have changed in this diff Show More