Merge pull request #309 from lnis-uofu/micro_benchmarks

Micro benchmarks for dual port BRAMs
This commit is contained in:
tangxifan 2021-04-28 16:23:31 -06:00 committed by GitHub
commit 7ef98a94ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 877 additions and 154 deletions

View File

@ -0,0 +1,58 @@
//-----------------------------------------------------
// Design Name : dual_port_ram_16k
// File Name : dual_port_ram_16k.v
// Function : Dual port RAM 2048x8bit
// Coder : Xifan Tang
//-----------------------------------------------------
module dual_port_ram_16k (
input clk,
input wen,
input ren,
input [10:0] waddr,
input [10:0] raddr,
input [7:0] din,
output [7:0] dout
);
dual_port_sram_16kb memory_0 (
.wclk (clk),
.wen (wen),
.waddr (waddr),
.data_in (din),
.rclk (clk),
.ren (ren),
.raddr (raddr),
.data_out (dout) );
endmodule
module dual_port_sram_16kb (
input wclk,
input wen,
input [10:0] waddr,
input [7:0] data_in,
input rclk,
input ren,
input [10:0] raddr,
output [7:0] data_out
);
reg [7:0] ram[2047:0];
reg [7:0] internal;
assign data_out = internal;
always @(posedge wclk) begin
if(wen) begin
ram[waddr] <= data_in;
end
end
always @(posedge rclk) begin
if(ren) begin
internal <= ram[raddr];
end
end
endmodule

View File

@ -0,0 +1,58 @@
//-----------------------------------------------------
// Design Name : dual_port_ram_1k
// File Name : dual_port_ram_1k.v
// Function : Dual port RAM 128x8bit
// Coder : Xifan Tang
//-----------------------------------------------------
module dual_port_ram_1k (
input clk,
input wen,
input ren,
input [6:0] waddr,
input [6:0] raddr,
input [7:0] din,
output [7:0] dout
);
dual_port_sram_1kb memory_0 (
.wclk (clk),
.wen (wen),
.waddr (waddr),
.data_in (din),
.rclk (clk),
.ren (ren),
.raddr (raddr),
.data_out (dout) );
endmodule
module dual_port_sram_1kb (
input wclk,
input wen,
input [6:0] waddr,
input [7:0] data_in,
input rclk,
input ren,
input [6:0] raddr,
output [7:0] data_out
);
reg [7:0] ram[127:0];
reg [7:0] internal;
assign data_out = internal;
always @(posedge wclk) begin
if(wen) begin
ram[waddr] <= data_in;
end
end
always @(posedge rclk) begin
if(ren) begin
internal <= ram[raddr];
end
end
endmodule

View File

@ -0,0 +1,97 @@
// FIFO buffer implemented with synchronous dual-port block ram
// Reference:
// https://embeddedthoughts.com/2016/07/13/fifo-buffer-using-block-ram-on-a-xilinx-spartan-3-fpga/
module fifo
#( parameter ADDRESS_WIDTH = 4, // number of words in ram
DATA_WIDTH = 4 // number of bits in word
)
// IO ports
(
input wire clk, reset,
input wire read, write,
input wire [DATA_WIDTH-1:0] write_data,
output wire empty, full,
output wire [DATA_WIDTH-1:0] read_data
);
// internal signal declarations
reg [ADDRESS_WIDTH-1:0] write_address_reg, write_address_next, write_address_after;
reg [ADDRESS_WIDTH-1:0] read_address_reg, read_address_next, read_address_after;
reg full_reg, empty_reg, full_next, empty_next;
wire write_en;
// write enable is asserted when write input is asserted and FIFO isn't full
assign write_en = write & ~full_reg;
// instantiate synchronous block ram
sync_dual_port_ram #(.ADDRESS_WIDTH(ADDRESS_WIDTH), .DATA_WIDTH(DATA_WIDTH)) ram
(.clk(clk), .write_en(write_en), .write_address(write_address_reg),
.read_address(read_address_reg), .write_data_in(write_data),
.write_data_out(), .read_data_out(read_data));
// register for address pointers, full/empty status
always @(posedge clk, posedge reset)
if (reset)
begin
write_address_reg <= 0;
read_address_reg <= 0;
full_reg <= 1'b0;
empty_reg <= 1'b1;
end
else
begin
write_address_reg <= write_address_next;
read_address_reg <= read_address_next;
full_reg <= full_next;
empty_reg <= empty_next;
end
// next-state logic for address index values after read/write operations
always @*
begin
write_address_after = write_address_reg + 1;
read_address_after = read_address_reg + 1;
end
// next-state logic for address pointers
always @*
begin
// defaults
write_address_next = write_address_reg;
read_address_next = read_address_reg;
full_next = full_reg;
empty_next = empty_reg;
// if read input asserted and FIFO isn't empty
if(read && ~empty_reg && ~write)
begin
read_address_next = read_address_after; // read address moves forward
full_next = 1'b0; // FIFO isn't full if a read occured
if (read_address_after == write_address_reg) // if read address caught up with write address,
empty_next = 1'b1; // FIFO is empty
end
// if write input asserted and FIFO isn't full
else if(write && ~full_reg && ~read)
begin
write_address_next = write_address_after; // write address moves forward
empty_next = 1'b0; // FIFO isn't empty if write occured
if (write_address_after == read_address_reg) // if write address caught up with read address
full_next = 1'b1; // FIFO is full
end
// if write and read are asserted
else if(write && read)
begin
write_address_next = write_address_after; // write address moves forward
read_address_next = read_address_after; // read address moves forward
end
end
// assign full/empty status to output ports
assign full = full_reg;
assign empty = empty_reg;
endmodule

View File

@ -0,0 +1,35 @@
// Synchronous dual-port block ram
// Reference:
// https://embeddedthoughts.com/2016/07/13/fifo-buffer-using-block-ram-on-a-xilinx-spartan-3-fpga/
module sync_dual_port_ram
#( parameter ADDRESS_WIDTH = 4, // number of words in ram
DATA_WIDTH = 4 // number of bits in word
)
// IO ports
(
input wire clk, // clk for synchronous read/write
input wire write_en, // signal to enable synchronous write
input wire [ADDRESS_WIDTH-1:0] read_address, write_address, // inputs for dual port addresses
input wire [DATA_WIDTH-1:0] write_data_in, // input for data to write to ram
output wire [DATA_WIDTH-1:0] read_data_out, write_data_out // outputs for dual data ports
);
// internal signal declarations
reg [DATA_WIDTH-1:0] ram [2**ADDRESS_WIDTH-1:0]; // ADDRESS_WIDTH x DATA_WIDTH RAM declaration
reg [ADDRESS_WIDTH-1:0] read_address_reg, write_address_reg; // dual port address declarations
// synchronous write and address update
always @(posedge clk)
begin
if (write_en) // if write enabled
ram[write_address] <= write_data_in; // write data to ram and write_address
read_address_reg <= read_address; // store read_address to reg
write_address_reg <= write_address; // store write_address to reg
end
// assignments for two data out ports
assign read_data_out = ram[read_address_reg];
assign write_data_out = ram[write_address_reg];
endmodule

View File

@ -27,9 +27,6 @@ opt_clean
deminout
opt
#########################
# Run coarse synthesis
#########################
opt_expr
opt_clean
check
@ -38,8 +35,13 @@ wreduce -keepdc
peepopt
pmuxtree
opt_clean
#########################
# Run coarse synthesis
#########################
# Extract arithmetic functions
alumacc
share
opt
fsm
# Run a quick follow-up optimization to sweep out unused nets/signals

View File

@ -0,0 +1,279 @@
<!-- Architecture annotation for OpenFPGA framework
This annotation supports the k6_N10_40nm.xml
- General purpose logic block
- K = 6, N = 10, I = 40
- Single mode
- Routing architecture
- L = 4, fc_in = 0.15, fc_out = 0.1
-->
<openfpga_architecture>
<technology_library>
<device_library>
<device_model name="logic" type="transistor">
<lib type="industry" corner="TOP_TT" ref="M" path="${OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.pm"/>
<design vdd="0.9" pn_ratio="2"/>
<pmos name="pch" chan_length="40e-9" min_width="140e-9" variation="logic_transistor_var"/>
<nmos name="nch" chan_length="40e-9" min_width="140e-9" variation="logic_transistor_var"/>
</device_model>
<device_model name="io" type="transistor">
<lib type="academia" ref="M" path="${OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.pm"/>
<design vdd="2.5" pn_ratio="3"/>
<pmos name="pch_25" chan_length="270e-9" min_width="320e-9" variation="io_transistor_var"/>
<nmos name="nch_25" chan_length="270e-9" min_width="320e-9" variation="io_transistor_var"/>
</device_model>
</device_library>
<variation_library>
<variation name="logic_transistor_var" abs_deviation="0.1" num_sigma="3"/>
<variation name="io_transistor_var" abs_deviation="0.1" num_sigma="3"/>
</variation_library>
</technology_library>
<circuit_library>
<circuit_model type="inv_buf" name="INVTX1" prefix="INVTX1" is_default="true">
<design_technology type="cmos" topology="inverter" size="1"/>
<device_technology device_model_name="logic"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<delay_matrix type="rise" in_port="in" out_port="out">
10e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in" out_port="out">
10e-12
</delay_matrix>
</circuit_model>
<circuit_model type="inv_buf" name="buf4" prefix="buf4" is_default="false">
<design_technology type="cmos" topology="buffer" size="1" num_level="2" f_per_stage="4"/>
<device_technology device_model_name="logic"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<delay_matrix type="rise" in_port="in" out_port="out">
10e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in" out_port="out">
10e-12
</delay_matrix>
</circuit_model>
<circuit_model type="inv_buf" name="tap_buf4" prefix="tap_buf4" is_default="false">
<design_technology type="cmos" topology="buffer" size="1" num_level="3" f_per_stage="4"/>
<device_technology device_model_name="logic"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<delay_matrix type="rise" in_port="in" out_port="out">
10e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in" out_port="out">
10e-12
</delay_matrix>
</circuit_model>
<circuit_model type="gate" name="OR2" prefix="OR2" is_default="true">
<design_technology type="cmos" topology="OR"/>
<device_technology device_model_name="logic"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="a" size="1"/>
<port type="input" prefix="b" size="1"/>
<port type="output" prefix="out" size="1"/>
<delay_matrix type="rise" in_port="a b" out_port="out">
10e-12 5e-12
</delay_matrix>
<delay_matrix type="fall" in_port="a b" out_port="out">
10e-12 5e-12
</delay_matrix>
</circuit_model>
<circuit_model type="pass_gate" name="TGATE" prefix="TGATE" is_default="true">
<design_technology type="cmos" topology="transmission_gate" nmos_size="1" pmos_size="2"/>
<device_technology device_model_name="logic"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="in" size="1"/>
<port type="input" prefix="sel" size="1"/>
<port type="input" prefix="selb" size="1"/>
<port type="output" prefix="out" size="1"/>
<delay_matrix type="rise" in_port="in sel selb" out_port="out">
10e-12 5e-12 5e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in sel selb" out_port="out">
10e-12 5e-12 5e-12
</delay_matrix>
</circuit_model>
<circuit_model type="chan_wire" name="chan_segment" prefix="track_seg" is_default="true">
<design_technology type="cmos"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<wire_param model_type="pi" R="101" C="22.5e-15" num_level="1"/> <!-- model_type could be T, res_val and cap_val DON'T CARE -->
</circuit_model>
<circuit_model type="wire" name="direct_interc" prefix="direct_interc" is_default="true">
<design_technology type="cmos"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<wire_param model_type="pi" R="0" C="0" num_level="1"/> <!-- model_type could be T, res_val cap_val should be defined -->
</circuit_model>
<circuit_model type="mux" name="mux_2level" prefix="mux_2level" dump_structural_verilog="true">
<design_technology type="cmos" structure="multi_level" num_level="2" add_const_input="true" const_input_val="1"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<pass_gate_logic circuit_model_name="TGATE"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<port type="sram" prefix="sram" size="1"/>
</circuit_model>
<circuit_model type="mux" name="mux_2level_tapbuf" prefix="mux_2level_tapbuf" dump_structural_verilog="true">
<design_technology type="cmos" structure="multi_level" num_level="2" add_const_input="true" const_input_val="1"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="tap_buf4"/>
<pass_gate_logic circuit_model_name="TGATE"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<port type="sram" prefix="sram" size="1"/>
</circuit_model>
<circuit_model type="mux" name="mux_1level_tapbuf" prefix="mux_1level_tapbuf" is_default="true" dump_structural_verilog="true">
<design_technology type="cmos" structure="one_level" add_const_input="true" const_input_val="1"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="tap_buf4"/>
<pass_gate_logic circuit_model_name="TGATE"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<port type="sram" prefix="sram" size="1"/>
</circuit_model>
<!--DFF subckt ports should be defined as <D> <Q> <CLK> <RESET> <SET> -->
<circuit_model type="ff" name="DFFSRQ" prefix="DFFSRQ" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/spice/dff.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/dff.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<port type="input" prefix="D" size="1"/>
<port type="input" prefix="set" lib_name="SET" size="1" is_global="true" default_val="0" is_set="true"/>
<port type="input" prefix="reset" lib_name="RST" size="1" is_global="true" default_val="0" is_reset="true"/>
<port type="output" prefix="Q" size="1"/>
<port type="clock" prefix="clk" lib_name="CK" size="1"/>
</circuit_model>
<circuit_model type="lut" name="frac_lut6" prefix="frac_lut6" dump_structural_verilog="true">
<design_technology type="cmos" fracturable_lut="true"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<lut_input_inverter exist="true" circuit_model_name="INVTX1"/>
<lut_input_buffer exist="true" circuit_model_name="buf4"/>
<lut_intermediate_buffer exist="true" circuit_model_name="buf4" location_map="-1-1-"/>
<pass_gate_logic circuit_model_name="TGATE"/>
<port type="input" prefix="in" size="6" tri_state_map="----11" circuit_model_name="OR2"/>
<port type="output" prefix="lut4_out" size="4" lut_frac_level="4" lut_output_mask="0,1,2,3"/>
<port type="output" prefix="lut5_out" size="2" lut_frac_level="5" lut_output_mask="0,1"/>
<port type="output" prefix="lut6_out" size="1" lut_output_mask="0"/>
<port type="sram" prefix="sram" size="64"/>
<port type="sram" prefix="mode" size="2" mode_select="true" circuit_model_name="DFFR" default_val="1"/>
</circuit_model>
<!--Scan-chain DFF subckt ports should be defined as <D> <Q> <Qb> <CLK> <RESET> <SET> -->
<circuit_model type="ccff" name="DFFR" prefix="DFFR" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/spice/dff.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/dff.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<port type="input" prefix="pReset" lib_name="RST" size="1" is_global="true" default_val="0" is_reset="true" is_prog="true"/>
<port type="input" prefix="D" size="1"/>
<port type="output" prefix="Q" size="1"/>
<port type="output" prefix="QN" size="1"/>
<port type="clock" prefix="prog_clk" lib_name="CK" size="1" is_global="true" default_val="0" is_prog="true"/>
</circuit_model>
<circuit_model type="iopad" name="GPIO" prefix="GPIO" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/spice/gpio.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/gpio.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<port type="inout" prefix="PAD" size="1" is_global="true" is_io="true" is_data_io="true"/>
<port type="sram" prefix="DIR" size="1" mode_select="true" circuit_model_name="DFFR" default_val="1"/>
<port type="input" prefix="outpad" lib_name="A" size="1"/>
<port type="output" prefix="inpad" lib_name="Y" size="1"/>
</circuit_model>
<circuit_model type="hard_logic" name="ADDF" prefix="ADDF" is_default="true" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/spice/adder.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/adder.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<port type="input" prefix="a" lib_name="A" size="1"/>
<port type="input" prefix="b" lib_name="B" size="1"/>
<port type="input" prefix="cin" lib_name="CI" size="1"/>
<port type="output" prefix="sumout" lib_name="SUM" size="1"/>
<port type="output" prefix="cout" lib_name="CO" size="1"/>
</circuit_model>
<circuit_model type="hard_logic" name="dpram_128x8" prefix="dpram_128x8" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/spice/dpram.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/dpram1k.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<port type="input" prefix="waddr" size="7"/>
<port type="input" prefix="raddr" size="7"/>
<port type="input" prefix="data_in" lib_name="d_in" size="8"/>
<port type="input" prefix="wen" size="1"/>
<port type="input" prefix="ren" size="1"/>
<port type="output" prefix="data_out" lib_name="d_out" size="8"/>
<port type="clock" prefix="clk" size="1"/>
</circuit_model>
</circuit_library>
<configuration_protocol>
<organization type="scan_chain" circuit_model_name="DFFR"/>
</configuration_protocol>
<connection_block>
<switch name="ipin_cblock" circuit_model_name="mux_2level_tapbuf"/>
</connection_block>
<switch_block>
<switch name="0" circuit_model_name="mux_2level_tapbuf"/>
</switch_block>
<routing_segment>
<segment name="L4" circuit_model_name="chan_segment"/>
</routing_segment>
<direct_connection>
<direct name="adder_carry" circuit_model_name="direct_interc" type="column" x_dir="positive" y_dir="positive"/>
</direct_connection>
<tile_annotations>
<global_port name="clk" is_clock="true" default_val="0">
<tile name="clb" port="clk"/>
<tile name="memory" port="clk"/>
</global_port>
</tile_annotations>
<pb_type_annotations>
<!-- physical pb_type binding in complex block IO -->
<pb_type name="io" physical_mode_name="physical" idle_mode_name="inpad"/>
<pb_type name="io[physical].iopad" circuit_model_name="GPIO" mode_bits="1"/>
<pb_type name="io[inpad].inpad" physical_pb_type_name="io[physical].iopad" mode_bits="1"/>
<pb_type name="io[outpad].outpad" physical_pb_type_name="io[physical].iopad" mode_bits="0"/>
<!-- End physical pb_type binding in complex block IO -->
<!-- physical pb_type binding in complex block CLB -->
<!-- physical mode will be the default mode if not specified -->
<pb_type name="clb">
<!-- Binding interconnect to circuit models as their physical implementation, if not defined, we use the default model -->
<interconnect name="crossbar" circuit_model_name="mux_2level"/>
</pb_type>
<pb_type name="clb.fle" physical_mode_name="physical"/>
<pb_type name="clb.fle[physical].fabric.frac_logic.frac_lut6" circuit_model_name="frac_lut6" mode_bits="11"/>
<pb_type name="clb.fle[physical].fabric.ff" circuit_model_name="DFFSRQ"/>
<pb_type name="clb.fle[physical].fabric.adder" circuit_model_name="ADDF"/>
<!-- Binding operating pb_type to physical pb_type -->
<!-- Binding operating pb_types in mode 'n2_lut5' -->
<pb_type name="clb.fle[n2_lut5].ble5.lut5" physical_pb_type_name="clb.fle[physical].fabric.frac_logic.frac_lut6" mode_bits="01" physical_pb_type_index_factor="0.5">
<!-- Binding the lut5 to the first 5 inputs of fracturable lut6 -->
<port name="in" physical_mode_port="in[0:4]"/>
<port name="out" physical_mode_port="lut5_out[0:0]" physical_mode_pin_rotate_offset="1"/>
</pb_type>
<pb_type name="clb.fle[n2_lut5].ble5.ff" physical_pb_type_name="clb.fle[physical].fabric.ff"/>
<!-- Binding operating pb_types in mode 'arithmetic' -->
<pb_type name="clb.fle[arithmetic].arithmetic.lut4" physical_pb_type_name="clb.fle[physical].fabric.frac_logic.frac_lut6" mode_bits="11" physical_pb_type_index_factor="0.25">
<!-- Binding the lut4 to the first 4 inputs of fracturable lut6 -->
<port name="in" physical_mode_port="in[0:3]"/>
<port name="out" physical_mode_port="lut4_out[0:0]" physical_mode_pin_rotate_offset="1"/>
</pb_type>
<pb_type name="clb.fle[arithmetic].arithmetic.adder" physical_pb_type_name="clb.fle[physical].fabric.adder"/>
<pb_type name="clb.fle[arithmetic].arithmetic.ff" physical_pb_type_name="clb.fle[physical].fabric.ff"/>
<!-- Binding operating pb_types in mode 'ble6' -->
<pb_type name="clb.fle[n1_lut6].ble6.lut6" physical_pb_type_name="clb.fle[physical].fabric.frac_logic.frac_lut6" mode_bits="00">
<!-- Binding the lut6 to the first 6 inputs of fracturable lut6 -->
<port name="in" physical_mode_port="in[0:5]"/>
<port name="out" physical_mode_port="lut6_out"/>
</pb_type>
<pb_type name="clb.fle[n1_lut6].ble6.ff" physical_pb_type_name="clb.fle[physical].fabric.ff" physical_pb_type_index_factor="2" physical_pb_type_index_offset="0"/>
<!-- End physical pb_type binding in complex block clb -->
<!-- physical pb_type binding in complex block memory -->
<pb_type name="memory[mem_128x8_dp].mem_128x8_dp" circuit_model_name="dpram_128x8"/>
<!-- END physical pb_type binding in complex block memory -->
</pb_type_annotations>
</openfpga_architecture>

View File

@ -0,0 +1,62 @@
//-----------------------------------------------------
// Design Name : dpram_2048x8
// File Name : dpram_2048x8.v
// Function : Dual port RAM 2048 x 8bit
// Coder : Xifan Tang
//-----------------------------------------------------
module dpram_2048x8 (
input clk,
input wen,
input ren,
input[0:10] waddr,
input[0:10] raddr,
input[0:7] data_in,
output[0:7] data_out );
dual_port_sram memory_0 (
.wclk (clk),
.wen (wen),
.waddr (waddr),
.data_in (data_in),
.rclk (clk),
.ren (ren),
.raddr (raddr),
.data_out (data_out) );
endmodule
//-----------------------------------------------------
// Design Name : dpram_2048x8_core
// File Name : dpram_2048x8.v
// Function : Core module of dual port RAM 2048 addresses x 8 bit
// Coder : Xifan tang
//-----------------------------------------------------
module dual_port_sram (
input wclk,
input wen,
input[0:10] waddr,
input[0:7] data_in,
input rclk,
input ren,
input[0:10] raddr,
output[0:7] data_out );
reg[0:7] ram[0:2047];
reg[0:7] internal;
assign data_out = internal;
always @(posedge wclk) begin
if(wen) begin
ram[waddr] <= data_in;
end
end
always @(posedge rclk) begin
if(ren) begin
internal <= ram[raddr];
end
end
endmodule

View File

@ -0,0 +1,18 @@
bram $__MY_DPRAM_128x8
init 0
abits 7
dbits 8
groups 2
ports 1 1
wrmode 1 0
enable 1 1
transp 0 0
clocks 1 1
clkpol 1 1
endbram
match $__MY_DPRAM_128x8
min efficiency 0
make_transp
endmatch

View File

@ -0,0 +1,21 @@
module $__MY_DPRAM_128x8 (
output [0:7] B1DATA,
input CLK1,
input [0:6] B1ADDR,
input [0:6] A1ADDR,
input [0:7] A1DATA,
input A1EN,
input B1EN );
generate
dpram_128x8 #() _TECHMAP_REPLACE_ (
.clk (CLK1),
.wen (A1EN),
.waddr (A1ADDR),
.data_in (A1DATA),
.ren (B1EN),
.raddr (B1ADDR),
.data_out (B1DATA) );
endgenerate
endmodule

View File

@ -0,0 +1,58 @@
//-----------------------------
// Dual-port RAM 128x8 bit (1Kbit)
// Core logic
//-----------------------------
module dpram_128x8_core (
input wclk,
input wen,
input [0:6] waddr,
input [0:7] data_in,
input rclk,
input ren,
input [0:6] raddr,
output [0:7] data_out );
reg [0:7] ram[0:127];
reg [0:7] internal;
assign data_out = internal;
always @(posedge wclk) begin
if(wen) begin
ram[waddr] <= data_in;
end
end
always @(posedge rclk) begin
if(ren) begin
internal <= ram[raddr];
end
end
endmodule
//-----------------------------
// Dual-port RAM 128x8 bit (1Kbit) wrapper
// where the read clock and write clock
// are combined to a unified clock
//-----------------------------
module dpram_128x8 (
input clk,
input wen,
input ren,
input [0:6] waddr,
input [0:6] raddr,
input [0:7] data_in,
output [0:7] data_out );
dpram_128x8_core memory_0 (
.wclk (clk),
.wen (wen),
.waddr (waddr),
.data_in (data_in),
.rclk (clk),
.ren (ren),
.raddr (raddr),
.data_out (data_out) );
endmodule

View File

@ -38,11 +38,11 @@ run-task fpga_verilog/adder/hard_adder --debug --show_thread_logs
echo -e "Testing Verilog generation with soft adder chain in CLBs ";
run-task fpga_verilog/adder/soft_adder --debug --show_thread_logs
echo -e "Testing Verilog generation with 16k block RAMs ";
run-task fpga_verilog/bram/dpram16k --debug --show_thread_logs
echo -e "Testing Verilog generation with 1k block RAMs ";
run-task fpga_verilog/bram/dpram1k --debug --show_thread_logs
echo -e "Testing Verilog generation with 16k block RAMs spanning two columns ";
run-task fpga_verilog/bram/wide_dpram16k --debug --show_thread_logs
echo -e "Testing Verilog generation with 1k block RAMs spanning two columns ";
run-task fpga_verilog/bram/wide_dpram1k --debug --show_thread_logs
echo -e "Testing Verilog generation with heterogeneous fabric using 8-bit single-mode multipliers ";
run-task fpga_verilog/dsp/single_mode_mult_8x8 --debug --show_thread_logs

View File

@ -9,29 +9,33 @@
[GENERAL]
run_engine=openfpga_shell
power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml
power_analysis = true
power_analysis = false
spice_output=false
verilog_output=true
timeout_each_job = 20*60
fpga_flow=vpr_blif
fpga_flow=yosys_vpr
[OpenFPGA_SHELL]
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fix_device_example_script.openfpga
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fix_heterogeneous_device_example_script.openfpga
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem1K_40nm_openfpga.xml
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml
# Yosys script parameters
yosys_cell_sim_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem1K_40nm_cell_sim.v
yosys_bram_map_rules=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem1K_40nm_bram.txt
yosys_bram_map_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem1K_40nm_bram_map.v
# VPR parameter
openfpga_vpr_device_layout=3x2
[ARCHITECTURES]
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_40nm.xml
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_mem1K_40nm.xml
[BENCHMARKS]
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/dual_port_ram_1k/dual_port_ram_1k.v
[SYNTHESIS_PARAM]
bench0_top = and2
bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act
bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v
bench0_chan_width = 300
bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_bram_flow.ys
bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys;${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_rewrite_flow.ys
bench0_top = dual_port_ram_1k
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
end_flow_with_test=

View File

@ -9,29 +9,33 @@
[GENERAL]
run_engine=openfpga_shell
power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml
power_analysis = true
power_analysis = false
spice_output=false
verilog_output=true
timeout_each_job = 20*60
fpga_flow=vpr_blif
fpga_flow=yosys_vpr
[OpenFPGA_SHELL]
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fix_device_example_script.openfpga
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml
openfpga_vpr_device_layout=4x4
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fix_heterogeneous_device_example_script.openfpga
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_mem1K_40nm_openfpga.xml
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml
# Yosys script parameters
yosys_cell_sim_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem1K_40nm_cell_sim.v
yosys_bram_map_rules=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem1K_40nm_bram.txt
yosys_bram_map_verilog=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_mem1K_40nm_bram_map.v
# VPR parameter
openfpga_vpr_device_layout=4x2
[ARCHITECTURES]
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem1K_40nm.xml
[BENCHMARKS]
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/dual_port_ram_1k/dual_port_ram_1k.v
[SYNTHESIS_PARAM]
bench0_top = and2
bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act
bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v
bench0_chan_width = 300
bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_bram_flow.ys
bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys;${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_rewrite_flow.ys
bench0_top = dual_port_ram_1k
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
end_flow_with_test=

View File

@ -118,14 +118,14 @@
<port name="lut6_out"/>
</output_ports>
</model>
<model name="dual_port_ram">
<model name="dpram_2048x8">
<input_ports>
<!-- write address lines -->
<port name="waddr" clock="clk"/>
<!-- read address lines -->
<port name="raddr" clock="clk"/>
<!-- data lines can be broken down into smaller bit widths minimum size 1 -->
<port name="d_in" clock="clk"/>
<port name="data_in" clock="clk"/>
<!-- write enable -->
<port name="wen" clock="clk"/>
<!-- read enable -->
@ -135,7 +135,7 @@
</input_ports>
<output_ports>
<!-- output can be broken down into smaller bit widths minimum size 1 -->
<port name="d_out" clock="clk"/>
<port name="data_out" clock="clk"/>
</output_ports>
</model>
</models>
@ -180,15 +180,21 @@
<equivalent_sites>
<site pb_type="memory"/>
</equivalent_sites>
<input name="waddr" num_pins="10"/>
<input name="raddr" num_pins="10"/>
<input name="d_in" num_pins="32"/>
<input name="waddr" num_pins="12"/>
<input name="raddr" num_pins="12"/>
<input name="data_in" num_pins="8"/>
<input name="wen" num_pins="1"/>
<input name="ren" num_pins="1"/>
<output name="d_out" num_pins="32"/>
<output name="data_out" num_pins="8"/>
<clock name="clk" num_pins="1"/>
<fc in_type="frac" in_val="0.15" out_type="frac" out_val="0.10"/>
<pinlocations pattern="spread"/>
<pinlocations pattern="custom">
<loc side="left" yoffset="0">memory.clk</loc>
<loc side="top" yoffset="1"></loc>
<loc side="right" yoffset="0">memory.wen memory.waddr[0:3] memory.raddr[0:3] memory.data_in[0:2] memory.data_out[0:2]</loc>
<loc side="right" yoffset="1">memory.ren memory.waddr[4:7] memory.raddr[4:7] memory.data_in[3:5] memory.data_out[3:5]</loc>
<loc side="bottom" yoffset="0">memory.waddr[8:11] memory.raddr[8:11] memory.data_in[6:7] memory.data_out[6:7]</loc>
</pinlocations>
</tile>
</tiles>
<!-- ODIN II specific config ends -->
@ -682,57 +688,57 @@
<!-- Define general purpose logic block (CLB) ends -->
<!-- Define single-mode dual-port memory begin -->
<pb_type name="memory">
<input name="waddr" num_pins="10"/>
<input name="raddr" num_pins="10"/>
<input name="d_in" num_pins="32"/>
<input name="waddr" num_pins="12"/>
<input name="raddr" num_pins="12"/>
<input name="data_in" num_pins="8"/>
<input name="wen" num_pins="1"/>
<input name="ren" num_pins="1"/>
<output name="d_out" num_pins="32"/>
<output name="data_out" num_pins="8"/>
<clock name="clk" num_pins="1"/>
<!-- Specify the 512x32=16Kbit memory block
<!-- Specify the 2048x8=16Kbit memory block
Note: the delay numbers are extracted from VPR flagship XML without modification
Should align to the process technology we using to create the 16K dual-port RAM
-->
<mode name="mem_512x32_dp">
<pb_type name="mem_512x32_dp" blif_model=".subckt dual_port_ram" class="memory" num_pb="1">
<input name="waddr" num_pins="10" port_class="address"/>
<input name="raddr" num_pins="10" port_class="address"/>
<input name="d_in" num_pins="32" port_class="data_in"/>
<input name="wen" num_pins="1" port_class="write_en"/>
<input name="ren" num_pins="1" port_class="write_en"/>
<output name="d_out" num_pins="32" port_class="data_out"/>
<mode name="mem_2048x8_dp">
<pb_type name="mem_2048x8_dp" blif_model=".subckt dpram_2048x8" num_pb="1">
<input name="waddr" num_pins="12" port_class="address1"/>
<input name="raddr" num_pins="12" port_class="address2"/>
<input name="data_in" num_pins="8" port_class="data_in1"/>
<input name="wen" num_pins="1" port_class="write_en1"/>
<input name="ren" num_pins="1" port_class="write_en2"/>
<output name="data_out" num_pins="8" port_class="data_out1"/>
<clock name="clk" num_pins="1" port_class="clock"/>
<T_setup value="509e-12" port="mem_512x32_dp.waddr" clock="clk"/>
<T_setup value="509e-12" port="mem_512x32_dp.raddr" clock="clk"/>
<T_setup value="509e-12" port="mem_512x32_dp.d_in" clock="clk"/>
<T_setup value="509e-12" port="mem_512x32_dp.wen" clock="clk"/>
<T_setup value="509e-12" port="mem_512x32_dp.ren" clock="clk"/>
<T_clock_to_Q max="1.234e-9" port="mem_512x32_dp.d_out" clock="clk"/>
<T_setup value="509e-12" port="mem_2048x8_dp.waddr" clock="clk"/>
<T_setup value="509e-12" port="mem_2048x8_dp.raddr" clock="clk"/>
<T_setup value="509e-12" port="mem_2048x8_dp.data_in" clock="clk"/>
<T_setup value="509e-12" port="mem_2048x8_dp.wen" clock="clk"/>
<T_setup value="509e-12" port="mem_2048x8_dp.ren" clock="clk"/>
<T_clock_to_Q max="1.234e-9" port="mem_2048x8_dp.data_out" clock="clk"/>
<power method="pin-toggle">
<port name="clk" energy_per_toggle="17.9e-12"/>
<static_power power_per_instance="0.0"/>
</power>
</pb_type>
<interconnect>
<direct name="waddress" input="memory.waddr" output="mem_512x32_dp.waddr">
<delay_constant max="132e-12" in_port="memory.waddr" out_port="mem_512x32_dp.waddr"/>
<direct name="waddress" input="memory.waddr" output="mem_2048x8_dp.waddr">
<delay_constant max="132e-12" in_port="memory.waddr" out_port="mem_2048x8_dp.waddr"/>
</direct>
<direct name="raddress" input="memory.raddr" output="mem_512x32_dp.raddr">
<delay_constant max="132e-12" in_port="memory.raddr" out_port="mem_512x32_dp.raddr"/>
<direct name="raddress" input="memory.raddr" output="mem_2048x8_dp.raddr">
<delay_constant max="132e-12" in_port="memory.raddr" out_port="mem_2048x8_dp.raddr"/>
</direct>
<direct name="data_input" input="memory.d_in" output="mem_512x32_dp.d_in">
<delay_constant max="132e-12" in_port="memory.d_in" out_port="mem_512x32_dp.d_in"/>
<direct name="data_input" input="memory.data_in" output="mem_2048x8_dp.data_in">
<delay_constant max="132e-12" in_port="memory.data_in" out_port="mem_2048x8_dp.data_in"/>
</direct>
<direct name="writeen" input="memory.wen" output="mem_512x32_dp.wen">
<delay_constant max="132e-12" in_port="memory.wen" out_port="mem_512x32_dp.wen"/>
<direct name="writeen" input="memory.wen" output="mem_2048x8_dp.wen">
<delay_constant max="132e-12" in_port="memory.wen" out_port="mem_2048x8_dp.wen"/>
</direct>
<direct name="readen" input="memory.ren" output="mem_512x32_dp.ren">
<delay_constant max="132e-12" in_port="memory.ren" out_port="mem_512x32_dp.ren"/>
<direct name="readen" input="memory.ren" output="mem_2048x8_dp.ren">
<delay_constant max="132e-12" in_port="memory.ren" out_port="mem_2048x8_dp.ren"/>
</direct>
<direct name="dataout" input="mem_512x32_dp.d_out" output="memory.d_out">
<delay_constant max="40e-12" in_port="mem_512x32_dp.d_out" out_port="memory.d_out"/>
<direct name="dataout" input="mem_2048x8_dp.data_out" output="memory.data_out">
<delay_constant max="40e-12" in_port="mem_2048x8_dp.data_out" out_port="memory.data_out"/>
</direct>
<direct name="clk" input="memory.clk" output="mem_512x32_dp.clk">
<direct name="clk" input="memory.clk" output="mem_2048x8_dp.clk">
</direct>
</interconnect>
</mode>

View File

@ -118,14 +118,14 @@
<port name="lut6_out"/>
</output_ports>
</model>
<model name="dual_port_ram">
<model name="dpram_128x8">
<input_ports>
<!-- write address lines -->
<port name="waddr" clock="clk"/>
<!-- read address lines -->
<port name="raddr" clock="clk"/>
<!-- data lines can be broken down into smaller bit widths minimum size 1 -->
<port name="d_in" clock="clk"/>
<port name="data_in" clock="clk"/>
<!-- write enable -->
<port name="wen" clock="clk"/>
<!-- read enable -->
@ -135,7 +135,7 @@
</input_ports>
<output_ports>
<!-- output can be broken down into smaller bit widths minimum size 1 -->
<port name="d_out" clock="clk"/>
<port name="data_out" clock="clk"/>
</output_ports>
</model>
</models>
@ -164,6 +164,7 @@
<output name="cout" num_pins="1"/>
<clock name="clk" num_pins="1"/>
<fc in_type="frac" in_val="0.15" out_type="frac" out_val="0.10">
<fc_override port_name="clk" fc_type="frac" fc_val="0"/>
<fc_override port_name="cin" fc_type="frac" fc_val="0"/>
<fc_override port_name="cout" fc_type="frac" fc_val="0"/>
</fc>
@ -180,15 +181,23 @@
<equivalent_sites>
<site pb_type="memory"/>
</equivalent_sites>
<input name="waddr" num_pins="10"/>
<input name="raddr" num_pins="10"/>
<input name="d_in" num_pins="32"/>
<input name="waddr" num_pins="7"/>
<input name="raddr" num_pins="7"/>
<input name="data_in" num_pins="8"/>
<input name="wen" num_pins="1"/>
<input name="ren" num_pins="1"/>
<output name="d_out" num_pins="32"/>
<output name="data_out" num_pins="8"/>
<clock name="clk" num_pins="1"/>
<fc in_type="frac" in_val="0.15" out_type="frac" out_val="0.10"/>
<pinlocations pattern="spread"/>
<fc in_type="frac" in_val="0.15" out_type="frac" out_val="0.10">
<fc_override port_name="clk" fc_type="frac" fc_val="0"/>
</fc>
<pinlocations pattern="custom">
<loc side="left" yoffset="0">memory.clk</loc>
<loc side="top" yoffset="1"></loc>
<loc side="right" yoffset="0">memory.wen memory.waddr[0:2] memory.raddr[0:2] memory.data_in[0:2] memory.data_out[0:2]</loc>
<loc side="right" yoffset="1">memory.ren memory.waddr[3:5] memory.raddr[3:5] memory.data_in[3:5] memory.data_out[3:5]</loc>
<loc side="bottom" yoffset="0">memory.waddr[6:6] memory.raddr[6:6] memory.data_in[6:7] memory.data_out[6:7]</loc>
</pinlocations>
</tile>
</tiles>
<!-- ODIN II specific config ends -->
@ -682,57 +691,57 @@
<!-- Define general purpose logic block (CLB) ends -->
<!-- Define single-mode dual-port memory begin -->
<pb_type name="memory">
<input name="waddr" num_pins="10"/>
<input name="raddr" num_pins="10"/>
<input name="d_in" num_pins="32"/>
<input name="waddr" num_pins="7"/>
<input name="raddr" num_pins="7"/>
<input name="data_in" num_pins="8"/>
<input name="wen" num_pins="1"/>
<input name="ren" num_pins="1"/>
<output name="d_out" num_pins="32"/>
<output name="data_out" num_pins="8"/>
<clock name="clk" num_pins="1"/>
<!-- Specify the 512x32=16Kbit memory block
<!-- Specify the 128x8=16Kbit memory block
Note: the delay numbers are extracted from VPR flagship XML without modification
Should align to the process technology we using to create the 16K dual-port RAM
-->
<mode name="mem_512x32_dp">
<pb_type name="mem_512x32_dp" blif_model=".subckt dual_port_ram" class="memory" num_pb="1">
<input name="waddr" num_pins="10" port_class="address"/>
<input name="raddr" num_pins="10" port_class="address"/>
<input name="d_in" num_pins="32" port_class="data_in"/>
<input name="wen" num_pins="1" port_class="write_en"/>
<input name="ren" num_pins="1" port_class="write_en"/>
<output name="d_out" num_pins="32" port_class="data_out"/>
<mode name="mem_128x8_dp">
<pb_type name="mem_128x8_dp" blif_model=".subckt dpram_128x8" num_pb="1">
<input name="waddr" num_pins="7" port_class="address1"/>
<input name="raddr" num_pins="7" port_class="address2"/>
<input name="data_in" num_pins="8" port_class="data_in1"/>
<input name="wen" num_pins="1" port_class="write_en1"/>
<input name="ren" num_pins="1" port_class="write_en2"/>
<output name="data_out" num_pins="8" port_class="data_out1"/>
<clock name="clk" num_pins="1" port_class="clock"/>
<T_setup value="509e-12" port="mem_512x32_dp.waddr" clock="clk"/>
<T_setup value="509e-12" port="mem_512x32_dp.raddr" clock="clk"/>
<T_setup value="509e-12" port="mem_512x32_dp.d_in" clock="clk"/>
<T_setup value="509e-12" port="mem_512x32_dp.wen" clock="clk"/>
<T_setup value="509e-12" port="mem_512x32_dp.ren" clock="clk"/>
<T_clock_to_Q max="1.234e-9" port="mem_512x32_dp.d_out" clock="clk"/>
<T_setup value="509e-12" port="mem_128x8_dp.waddr" clock="clk"/>
<T_setup value="509e-12" port="mem_128x8_dp.raddr" clock="clk"/>
<T_setup value="509e-12" port="mem_128x8_dp.data_in" clock="clk"/>
<T_setup value="509e-12" port="mem_128x8_dp.wen" clock="clk"/>
<T_setup value="509e-12" port="mem_128x8_dp.ren" clock="clk"/>
<T_clock_to_Q max="1.234e-9" port="mem_128x8_dp.data_out" clock="clk"/>
<power method="pin-toggle">
<port name="clk" energy_per_toggle="17.9e-12"/>
<static_power power_per_instance="0.0"/>
</power>
</pb_type>
<interconnect>
<direct name="waddress" input="memory.waddr" output="mem_512x32_dp.waddr">
<delay_constant max="132e-12" in_port="memory.waddr" out_port="mem_512x32_dp.waddr"/>
<direct name="waddress" input="memory.waddr" output="mem_128x8_dp.waddr">
<delay_constant max="132e-12" in_port="memory.waddr" out_port="mem_128x8_dp.waddr"/>
</direct>
<direct name="raddress" input="memory.raddr" output="mem_512x32_dp.raddr">
<delay_constant max="132e-12" in_port="memory.raddr" out_port="mem_512x32_dp.raddr"/>
<direct name="raddress" input="memory.raddr" output="mem_128x8_dp.raddr">
<delay_constant max="132e-12" in_port="memory.raddr" out_port="mem_128x8_dp.raddr"/>
</direct>
<direct name="data_input" input="memory.d_in" output="mem_512x32_dp.d_in">
<delay_constant max="132e-12" in_port="memory.d_in" out_port="mem_512x32_dp.d_in"/>
<direct name="data_input" input="memory.data_in" output="mem_128x8_dp.data_in">
<delay_constant max="132e-12" in_port="memory.data_in" out_port="mem_128x8_dp.data_in"/>
</direct>
<direct name="writeen" input="memory.wen" output="mem_512x32_dp.wen">
<delay_constant max="132e-12" in_port="memory.wen" out_port="mem_512x32_dp.wen"/>
<direct name="writeen" input="memory.wen" output="mem_128x8_dp.wen">
<delay_constant max="132e-12" in_port="memory.wen" out_port="mem_128x8_dp.wen"/>
</direct>
<direct name="readen" input="memory.ren" output="mem_512x32_dp.ren">
<delay_constant max="132e-12" in_port="memory.ren" out_port="mem_512x32_dp.ren"/>
<direct name="readen" input="memory.ren" output="mem_128x8_dp.ren">
<delay_constant max="132e-12" in_port="memory.ren" out_port="mem_128x8_dp.ren"/>
</direct>
<direct name="dataout" input="mem_512x32_dp.d_out" output="memory.d_out">
<delay_constant max="40e-12" in_port="mem_512x32_dp.d_out" out_port="memory.d_out"/>
<direct name="dataout" input="mem_128x8_dp.data_out" output="memory.data_out">
<delay_constant max="40e-12" in_port="mem_128x8_dp.data_out" out_port="memory.data_out"/>
</direct>
<direct name="clk" input="memory.clk" output="mem_512x32_dp.clk">
<direct name="clk" input="memory.clk" output="mem_128x8_dp.clk">
</direct>
</interconnect>
</mode>

View File

@ -118,14 +118,14 @@
<port name="lut6_out"/>
</output_ports>
</model>
<model name="dual_port_ram">
<model name="dpram_128x8">
<input_ports>
<!-- write address lines -->
<port name="waddr" clock="clk"/>
<!-- read address lines -->
<port name="raddr" clock="clk"/>
<!-- data lines can be broken down into smaller bit widths minimum size 1 -->
<port name="d_in" clock="clk"/>
<port name="data_in" clock="clk"/>
<!-- write enable -->
<port name="wen" clock="clk"/>
<!-- read enable -->
@ -135,7 +135,7 @@
</input_ports>
<output_ports>
<!-- output can be broken down into smaller bit widths minimum size 1 -->
<port name="d_out" clock="clk"/>
<port name="data_out" clock="clk"/>
</output_ports>
</model>
</models>
@ -164,6 +164,7 @@
<output name="cout" num_pins="1"/>
<clock name="clk" num_pins="1"/>
<fc in_type="frac" in_val="0.15" out_type="frac" out_val="0.10">
<fc_override port_name="clk" fc_type="frac" fc_val="0"/>
<fc_override port_name="cin" fc_type="frac" fc_val="0"/>
<fc_override port_name="cout" fc_type="frac" fc_val="0"/>
</fc>
@ -176,19 +177,30 @@
<loc side="bottom">clb.cout clb.O[19:10] clb.I[39:20]</loc>
</pinlocations>
</tile>
<tile name="memory" width="2" height="2" area="548000">
<tile name="memory" height="2" width="2" area="548000">
<equivalent_sites>
<site pb_type="memory"/>
</equivalent_sites>
<input name="waddr" num_pins="10"/>
<input name="raddr" num_pins="10"/>
<input name="d_in" num_pins="32"/>
<input name="waddr" num_pins="7"/>
<input name="raddr" num_pins="7"/>
<input name="data_in" num_pins="8"/>
<input name="wen" num_pins="1"/>
<input name="ren" num_pins="1"/>
<output name="d_out" num_pins="32"/>
<output name="data_out" num_pins="8"/>
<clock name="clk" num_pins="1"/>
<fc in_type="frac" in_val="0.15" out_type="frac" out_val="0.10"/>
<pinlocations pattern="perimeter"/>
<fc in_type="frac" in_val="0.15" out_type="frac" out_val="0.10">
<fc_override port_name="clk" fc_type="frac" fc_val="0"/>
</fc>
<pinlocations pattern="custom">
<loc side="left" yoffset="0">memory.clk memory.waddr[0:0] memory.raddr[0:0] memory.data_in[0:0] memory.data_out[0:0]</loc>
<loc side="left" yoffset="1">memory.waddr[1:1] memory.raddr[1:1] memory.data_in[1:1] memory.data_out[1:1]</loc>
<loc side="top" xoffset="0" yoffset="1">memory.waddr[2:2] memory.raddr[2:2] memory.data_in[2:2] memory.data_out[2:2]</loc>
<loc side="top" xoffset="1" yoffset="1">memory.waddr[3:3] memory.raddr[3:3] memory.data_in[3:3] memory.data_out[3:3]</loc>
<loc side="right" xoffset="1" yoffset="0">memory.waddr[4:4] memory.raddr[4:4] memory.data_in[4:4] memory.data_out[4:4]</loc>
<loc side="right" xoffset="1" yoffset="1">memory.waddr[5:5] memory.raddr[5:5] memory.data_in[5:5] memory.data_out[5:5]</loc>
<loc side="bottom" xoffset="0">memory.wen memory.waddr[6:6] memory.raddr[6:6] memory.data_in[6:6] memory.data_out[6:6]</loc>
<loc side="bottom" xoffset="1">memory.ren memory.data_in[7:7] memory.data_out[7:7]</loc>
</pinlocations>
</tile>
</tiles>
<!-- ODIN II specific config ends -->
@ -204,7 +216,7 @@
<col type="memory" startx="2" starty="1" repeatx="8" priority="20"/>
<col type="EMPTY" startx="2" repeatx="8" starty="1" priority="19"/>
</auto_layout>
<fixed_layout name="4x4" width="6" height="6">
<fixed_layout name="4x2" width="6" height="4">
<!--Perimeter of 'io' blocks with 'EMPTY' blocks at corners-->
<perimeter type="io" priority="100"/>
<corners type="EMPTY" priority="101"/>
@ -682,57 +694,57 @@
<!-- Define general purpose logic block (CLB) ends -->
<!-- Define single-mode dual-port memory begin -->
<pb_type name="memory">
<input name="waddr" num_pins="10"/>
<input name="raddr" num_pins="10"/>
<input name="d_in" num_pins="32"/>
<input name="waddr" num_pins="7"/>
<input name="raddr" num_pins="7"/>
<input name="data_in" num_pins="8"/>
<input name="wen" num_pins="1"/>
<input name="ren" num_pins="1"/>
<output name="d_out" num_pins="32"/>
<output name="data_out" num_pins="8"/>
<clock name="clk" num_pins="1"/>
<!-- Specify the 512x32=16Kbit memory block
<!-- Specify the 128x8=16Kbit memory block
Note: the delay numbers are extracted from VPR flagship XML without modification
Should align to the process technology we using to create the 16K dual-port RAM
-->
<mode name="mem_512x32_dp">
<pb_type name="mem_512x32_dp" blif_model=".subckt dual_port_ram" class="memory" num_pb="1">
<input name="waddr" num_pins="10" port_class="address"/>
<input name="raddr" num_pins="10" port_class="address"/>
<input name="d_in" num_pins="32" port_class="data_in"/>
<input name="wen" num_pins="1" port_class="write_en"/>
<input name="ren" num_pins="1" port_class="write_en"/>
<output name="d_out" num_pins="32" port_class="data_out"/>
<mode name="mem_128x8_dp">
<pb_type name="mem_128x8_dp" blif_model=".subckt dpram_128x8" num_pb="1">
<input name="waddr" num_pins="7" port_class="address1"/>
<input name="raddr" num_pins="7" port_class="address2"/>
<input name="data_in" num_pins="8" port_class="data_in1"/>
<input name="wen" num_pins="1" port_class="write_en1"/>
<input name="ren" num_pins="1" port_class="write_en2"/>
<output name="data_out" num_pins="8" port_class="data_out1"/>
<clock name="clk" num_pins="1" port_class="clock"/>
<T_setup value="509e-12" port="mem_512x32_dp.waddr" clock="clk"/>
<T_setup value="509e-12" port="mem_512x32_dp.raddr" clock="clk"/>
<T_setup value="509e-12" port="mem_512x32_dp.d_in" clock="clk"/>
<T_setup value="509e-12" port="mem_512x32_dp.wen" clock="clk"/>
<T_setup value="509e-12" port="mem_512x32_dp.ren" clock="clk"/>
<T_clock_to_Q max="1.234e-9" port="mem_512x32_dp.d_out" clock="clk"/>
<T_setup value="509e-12" port="mem_128x8_dp.waddr" clock="clk"/>
<T_setup value="509e-12" port="mem_128x8_dp.raddr" clock="clk"/>
<T_setup value="509e-12" port="mem_128x8_dp.data_in" clock="clk"/>
<T_setup value="509e-12" port="mem_128x8_dp.wen" clock="clk"/>
<T_setup value="509e-12" port="mem_128x8_dp.ren" clock="clk"/>
<T_clock_to_Q max="1.234e-9" port="mem_128x8_dp.data_out" clock="clk"/>
<power method="pin-toggle">
<port name="clk" energy_per_toggle="17.9e-12"/>
<static_power power_per_instance="0.0"/>
</power>
</pb_type>
<interconnect>
<direct name="waddress" input="memory.waddr" output="mem_512x32_dp.waddr">
<delay_constant max="132e-12" in_port="memory.waddr" out_port="mem_512x32_dp.waddr"/>
<direct name="waddress" input="memory.waddr" output="mem_128x8_dp.waddr">
<delay_constant max="132e-12" in_port="memory.waddr" out_port="mem_128x8_dp.waddr"/>
</direct>
<direct name="raddress" input="memory.raddr" output="mem_512x32_dp.raddr">
<delay_constant max="132e-12" in_port="memory.raddr" out_port="mem_512x32_dp.raddr"/>
<direct name="raddress" input="memory.raddr" output="mem_128x8_dp.raddr">
<delay_constant max="132e-12" in_port="memory.raddr" out_port="mem_128x8_dp.raddr"/>
</direct>
<direct name="data_input" input="memory.d_in" output="mem_512x32_dp.d_in">
<delay_constant max="132e-12" in_port="memory.d_in" out_port="mem_512x32_dp.d_in"/>
<direct name="data_input" input="memory.data_in" output="mem_128x8_dp.data_in">
<delay_constant max="132e-12" in_port="memory.data_in" out_port="mem_128x8_dp.data_in"/>
</direct>
<direct name="writeen" input="memory.wen" output="mem_512x32_dp.wen">
<delay_constant max="132e-12" in_port="memory.wen" out_port="mem_512x32_dp.wen"/>
<direct name="writeen" input="memory.wen" output="mem_128x8_dp.wen">
<delay_constant max="132e-12" in_port="memory.wen" out_port="mem_128x8_dp.wen"/>
</direct>
<direct name="readen" input="memory.ren" output="mem_512x32_dp.ren">
<delay_constant max="132e-12" in_port="memory.ren" out_port="mem_512x32_dp.ren"/>
<direct name="readen" input="memory.ren" output="mem_128x8_dp.ren">
<delay_constant max="132e-12" in_port="memory.ren" out_port="mem_128x8_dp.ren"/>
</direct>
<direct name="dataout" input="mem_512x32_dp.d_out" output="memory.d_out">
<delay_constant max="40e-12" in_port="mem_512x32_dp.d_out" out_port="memory.d_out"/>
<direct name="dataout" input="mem_128x8_dp.data_out" output="memory.data_out">
<delay_constant max="40e-12" in_port="mem_128x8_dp.data_out" out_port="memory.data_out"/>
</direct>
<direct name="clk" input="memory.clk" output="mem_512x32_dp.clk">
<direct name="clk" input="memory.clk" output="mem_128x8_dp.clk">
</direct>
</interconnect>
</mode>