本练习主要研究FPGA片内/外存储器。实现32X8-bit的RAM。
LPM的用法参阅<Using Library Module in Verilog Design>。
1. Tools / MegaWizard Plug-in Manger /…/ memory compiles创建一个名为ramlpm.v的RAM。
2. 编译,并查看编译报告。RAM占用1个M4K块,256B。
3. 仿真。
仿真结果:
代码part 1:
1 // part 1 用altsyncram LPM构建一个32*8bit RAM
2
3 module part1(
4 input [ 4 : 0 ] Address,
5 input [ 7 : 0 ] DataIn,
6 input Write,Clock,
7 output [ 7 : 0 ] DataOut
8 );
9
10 ramlpm u0(
11 .address(Address),
12 .clock(Clock),
13 .data(DataIn),
14 .wren(Write),
15 .q(DataOut)
16 );
17
18 endmodule
19
20
21
22 // megafunction wizard: %RAM: 1-PORT%
23 // GENERATION: STANDARD
24 // VERSION: WM1.0
25 // MODULE: altsyncram
26
27 // ============================================================
28 // File Name: ramlpm.v
29 // Megafunction Name(s):
30 // altsyncram
31 //
32 // Simulation Library Files(s):
33 // altera_mf
34 // ============================================================
35 // ************************************************************
36 // THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
37 //
38 // 9.1 Build 222 10/21/2009 SJ Full Version
39 // ************************************************************
40
41
42 // Copyright (C) 1991-2009 Altera Corporation
43 // Your use of Altera Corporation's design tools, logic functions
44 // and other software and tools, and its AMPP partner logic
45 // functions, and any output files from any of the foregoing
46 // (including device programming or simulation files), and any
47 // associated documentation or information are expressly subject
48 // to the terms and conditions of the Altera Program License
49 // Subscription Agreement, Altera MegaCore Function License
50 // Agreement, or other applicable license agreement, including,
51 // without limitation, that your use is for the sole purpose of
52 // programming logic devices manufactured by Altera and sold by
53 // Altera or its authorized distributors. Please refer to the
54 // applicable agreement for further details.
55
56
57 // synopsys translate_off
58 `timescale 1 ps / 1 ps
59 // synopsys translate_on
60 module ramlpm (
61 address,
62 clock,
63 data,
64 wren,
65 q);
66
67 input [ 4 : 0 ] address;
68 input clock;
69 input [ 7 : 0 ] data;
70 input wren;
71 output [ 7 : 0 ] q;
72
73 wire [ 7 : 0 ] sub_wire0;
74 wire [ 7 : 0 ] q = sub_wire0[ 7 : 0 ];
75
76 altsyncram altsyncram_component (
77 .wren_a (wren),
78 .clock0 (clock),
79 .address_a (address),
80 .data_a (data),
81 .q_a (sub_wire0),
82 .aclr0 ( 1 ' b0),
83 .aclr1 ( 1 ' b0),
84 .address_b ( 1 ' b1),
85 .addressstall_a ( 1 ' b0),
86 .addressstall_b ( 1 ' b0),
87 .byteena_a ( 1 ' b1),
88 .byteena_b ( 1 ' b1),
89 .clock1 ( 1 ' b1),
90 .clocken0 ( 1 ' b1),
91 .clocken1 ( 1 ' b1),
92 .clocken2 ( 1 ' b1),
93 .clocken3 ( 1 ' b1),
94 .data_b ( 1 ' b1),
95 .eccstatus (),
96 .q_b (),
97 .rden_a ( 1 ' b1),
98 .rden_b ( 1 ' b1),
99 .wren_b ( 1 ' b0));
100 defparam
101 altsyncram_component.clock_enable_input_a = " BYPASS " ,
102 altsyncram_component.clock_enable_output_a = " BYPASS " ,
103 altsyncram_component.intended_device_family = " Cyclone II " ,
104 altsyncram_component.lpm_hint = " ENABLE_RUNTIME_MOD=NO " ,
105 altsyncram_component.lpm_type = " altsyncram " ,
106 altsyncram_component.numwords_a = 32 ,
107 altsyncram_component.operation_mode = " SINGLE_PORT " ,
108 altsyncram_component.outdata_aclr_a = " NONE " ,
109 altsyncram_component.outdata_reg_a = " UNREGISTERED " ,
110 altsyncram_component.power_up_uninitialized = " FALSE " ,
111 altsyncram_component.ram_block_type = " M4K " ,
112 altsyncram_component.widthad_a = 5 ,
113 altsyncram_component.width_a = 8 ,
114 altsyncram_component.width_byteena_a = 1 ;
115
116
117 endmodule
118
119 // ============================================================
120 // CNX file retrieval info
121 // ============================================================
122 // Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0"
123 // Retrieval info: PRIVATE: AclrAddr NUMERIC "0"
124 // Retrieval info: PRIVATE: AclrByte NUMERIC "0"
125 // Retrieval info: PRIVATE: AclrData NUMERIC "0"
126 // Retrieval info: PRIVATE: AclrOutput NUMERIC "0"
127 // Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0"
128 // Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8"
129 // Retrieval info: PRIVATE: BlankMemory NUMERIC "1"
130 // Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0"
131 // Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0"
132 // Retrieval info: PRIVATE: Clken NUMERIC "0"
133 // Retrieval info: PRIVATE: DataBusSeparated NUMERIC "1"
134 // Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0"
135 // Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A"
136 // Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0"
137 // Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II"
138 // Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0"
139 // Retrieval info: PRIVATE: JTAG_ID STRING "NONE"
140 // Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"
141 // Retrieval info: PRIVATE: MIFfilename STRING ""
142 // Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "32"
143 // Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "2"
144 // Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3"
145 // Retrieval info: PRIVATE: RegAddr NUMERIC "1"
146 // Retrieval info: PRIVATE: RegData NUMERIC "1"
147 // Retrieval info: PRIVATE: RegOutput NUMERIC "0"
148 // Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
149 // Retrieval info: PRIVATE: SingleClock NUMERIC "1"
150 // Retrieval info: PRIVATE: UseDQRAM NUMERIC "1"
151 // Retrieval info: PRIVATE: WRCONTROL_ACLR_A NUMERIC "0"
152 // Retrieval info: PRIVATE: WidthAddr NUMERIC "5"
153 // Retrieval info: PRIVATE: WidthData NUMERIC "8"
154 // Retrieval info: PRIVATE: rden NUMERIC "0"
155 // Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS"
156 // Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS"
157 // Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II"
158 // Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO"
159 // Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"
160 // Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "32"
161 // Retrieval info: CONSTANT: OPERATION_MODE STRING "SINGLE_PORT"
162 // Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE"
163 // Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED"
164 // Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE"
165 // Retrieval info: CONSTANT: RAM_BLOCK_TYPE STRING "M4K"
166 // Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "5"
167 // Retrieval info: CONSTANT: WIDTH_A NUMERIC "8"
168 // Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
169 // Retrieval info: USED_PORT: address 0 0 5 0 INPUT NODEFVAL address[4..0]
170 // Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL clock
171 // Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL data[7..0]
172 // Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL q[7..0]
173 // Retrieval info: USED_PORT: wren 0 0 0 0 INPUT NODEFVAL wren
174 // Retrieval info: CONNECT: @address_a 0 0 5 0 address 0 0 5 0
175 // Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0
176 // Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0
177 // Retrieval info: CONNECT: @data_a 0 0 8 0 data 0 0 8 0
178 // Retrieval info: CONNECT: @wren_a 0 0 0 0 wren 0 0 0 0
179 // Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
180 // Retrieval info: GEN_FILE: TYPE_NORMAL ramlpm.v TRUE
181 // Retrieval info: GEN_FILE: TYPE_NORMAL ramlpm.inc FALSE
182 // Retrieval info: GEN_FILE: TYPE_NORMAL ramlpm.cmp FALSE
183 // Retrieval info: GEN_FILE: TYPE_NORMAL ramlpm.bsf FALSE
184 // Retrieval info: GEN_FILE: TYPE_NORMAL ramlpm_inst.v FALSE
185 // Retrieval info: GEN_FILE: TYPE_NORMAL ramlpm_bb.v FALSE
186 // Retrieval info: GEN_FILE: TYPE_NORMAL ramlpm_waveforms.html TRUE
187 // Retrieval info: GEN_FILE: TYPE_NORMAL ramlpm_wave*.jpg FALSE
188 // Retrieval info: LIB_FILE: altera_mf
本练习验证part I的RAM,即在DE2上用拨动开关写一部分数据到RAM,并读出,显示在数码管上。
代码part II:
1 // part 2 在DE2上验证Part的设计
2 // 引脚说明:
3 // input: SW7-0 --DataIn SW15-11--Address SW17--Write KEY0--Clock
4 // output : HEX7-6--Address HEX5-4--DataIn HEX1-0--DataOut LEDG0--Write
5
6 module part2(
7 input [ 17 : 0 ] SW,
8 input [ 0 : 0 ] KEY,
9 output [ 0 : 0 ] LEDG,
10 output [ 0 : 6 ] HEX7,HEX6,HEX5,HEX4,HEX1,HEX0
11 );
12
13 wire [ 7 : 0 ] DataOut;
14
15 ramlpm u0(
16 .address(SW[ 15 : 11 ]),
17 .clock(KEY),
18 .data(SW[ 7 : 0 ]),
19 .wren(SW[ 17 ]),
20 .q(DataOut[ 7 : 0 ])
21 );
22
23 assign LEDG = SW[ 17 ]; // Write的标记
24
25 // 调用7-seg显示模块
26 seg_lut h5(HEX5,SW[ 7 : 4 ]);
27 seg_lut h4(HEX4,SW[ 3 : 0 ]);
28
29 seg_lut h7(HEX7,{{ 3 { 1 ' b0}},SW[15]});
30 seg_lut h6(HEX6,SW[ 14 : 11 ]);
31
32 seg_lut h1(HEX1,DataOut[ 7 : 4 ]);
33 seg_lut h0(HEX0,DataOut[ 3 : 0 ]);
34
35 endmodule
36
37 // 7-seg
38
39 module seg_lut(oseg,idig);
40 input [ 3 : 0 ] idig;
41 output reg [ 0 : 6 ] oseg;
42
43 always @(idig)
44 case (idig)
45 4 ' h1: oseg=7 ' b100_1111; // --------0--------
46 4 ' h2: oseg=7 ' b001_0010; // | |
47 4 ' h3: oseg=7 ' b000_0110; // | | 1
48 4 ' h4: oseg=7 ' b100_1100; // | 5 |
49 4 ' h5: oseg=7 ' b010_0100; // | |
50 4 ' h6: oseg=7 ' b010_0000; // --------6--------
51 4 ' h7: oseg=7 ' b000_1111; // | |
52 4 ' h8: oseg=7 ' b000_0000; // | |
53 4 ' h9: oseg=7 ' b000_1100; // | 4 | 2
54 4 ' hA: oseg=7 ' b000_1000; // | |
55 4 ' hb: oseg=7 ' b110_0000; // --------3---------
56 4 ' hC: oseg=7 ' b011_0001;
57 4 ' hd: oseg=7 ' b100_0010;
58 4 ' hE: oseg=7 ' b011_0000;
59 4 ' hF: oseg=7 ' b011_1000;
60 default : oseg = 7 ' b111_1111;
61 endcase
62
63 endmodule
64
用多维数组定义存储器。32X8-bit的RAM可以定义为32X8的数组,如:
reg [7:0] memory_array [31:0];
对于Cyclone II系列的FPGA,实现这种数组可用触发器或M4K存储器块。确保使用M4K实现有两种方法:一是调用LPM库,二是用适当形式的Verilog代码定义RAM,这部分可查阅Quartus II 的帮助,搜索“Inferred memory”。
代码part 3:
1 module part3(
2 input [ 17 : 0 ] SW,
3 input [ 0 : 0 ] KEY,
4 output [ 0 : 0 ] LEDG,
5 output [ 0 : 6 ] HEX7,HEX6,HEX5,HEX4,HEX1,HEX0
6 );
7
8 wire [ 7 : 0 ] DataOut;
9
10 ram_single u0(
11 .a(SW[ 15 : 11 ]),
12 .clk(KEY),
13 .d(SW[ 7 : 0 ]),
14 .we(SW[ 17 ]),
15 .q(DataOut[ 7 : 0 ])
16 );
17
18 assign LEDG = SW[ 17 ]; // Write的标记
19
20 // 调用7-seg显示模块
21 seg_lut h5(HEX5,SW[ 7 : 4 ]);
22 seg_lut h4(HEX4,SW[ 3 : 0 ]);
23
24 seg_lut h7(HEX7,{{ 3 { 1 ' b0}},SW[15]});
25 seg_lut h6(HEX6,SW[ 14 : 11 ]);
26
27 seg_lut h1(HEX1,DataOut[ 7 : 4 ]);
28 seg_lut h0(HEX0,DataOut[ 3 : 0 ]);
29
30 endmodule
31
32 // 7-seg
33
34 module seg_lut(oseg,idig);
35 input [ 3 : 0 ] idig;
36 output reg [ 0 : 6 ] oseg;
37
38 always @(idig)
39 case (idig)
40 4 ' h1: oseg=7 ' b100_1111; // --------0--------
41 4 ' h2: oseg=7 ' b001_0010; // | |
42 4 ' h3: oseg=7 ' b000_0110; // | | 1
43 4 ' h4: oseg=7 ' b100_1100; // | 5 |
44 4 ' h5: oseg=7 ' b010_0100; // | |
45 4 ' h6: oseg=7 ' b010_0000; // --------6--------
46 4 ' h7: oseg=7 ' b000_1111; // | |
47 4 ' h8: oseg=7 ' b000_0000; // | |
48 4 ' h9: oseg=7 ' b000_1100; // | 4 | 2
49 4 ' hA: oseg=7 ' b000_1000; // | |
50 4 ' hb: oseg=7 ' b110_0000; // --------3---------
51 4 ' hC: oseg=7 ' b011_0001;
52 4 ' hd: oseg=7 ' b100_0010;
53 4 ' hE: oseg=7 ' b011_0000;
54 4 ' hF: oseg=7 ' b011_1000;
55 default : oseg = 7 ' b111_1111;
56 endcase
57
58 endmodule
59
60 // 32*8 bit RAM
61
62 module ram_single(q,a,d,we,clk);
63 output reg [ 7 : 0 ] q;
64 input [ 7 : 0 ] d;
65 input [ 4 : 0 ] a;
66 input we,clk;
67
68 reg [ 7 : 0 ] mem [ 31 : 0 ] ;
69
70 always @( posedge clk)
71 begin
72 if (we)
73 mem[a] <= d;
74 q <= mem[a];
75 end
76
77 endmodule
RAM Summary
与part 2的区别,读出RAM的数据慢一个时钟。
本练习使用DE2上的SRAM—IS61LV25616AL-10.其参数可查看数据手册。为简化设计,控制端口除WE外,都缺省有效,即赋0值。
代码part 4:
1 // 练习SRAM的读/写功能,通过FPGA控制SRAM
2 // 引脚说明:
3 // ---------------------------------------------------------
4 // SW[17] write
5 // SW[15:11] address
6 // SW[7:0] datain
7 // KEY[1] rst_n
8 // KEY[0] clk
9
10 module part4(
11 input [ 17 : 0 ] SW,
12 input [ 1 : 0 ] KEY, // rst_n,clk
13 output [ 0 : 0 ] LEDG,
14 output [ 0 : 6 ] HEX7,HEX6,HEX5,HEX4,HEX1,HEX0,
15
16 // SRAM pors
17 output [ 17 : 0 ] SRAM_ADDR, // address
18 inout [ 15 : 0 ] SRAM_DQ, // datain , dataout
19 output SRAM_CE_N, // chip enable
20 SRAM_OE_N, // output enable
21 SRAM_WE_N, // write enable
22 SRAM_UB_N, // upper byte
23 SRAM_LB_N // lower byte
24 );
25
26 wire [ 7 : 0 ] DataOut,DataIn;
27 wire [ 4 : 0 ] address;
28 wire [ 15 : 0 ] DataIn_reg;
29 wire clk,rst_n,write,ce_n;
30
31 assign clk = KEY[ 0 ];
32 assign rst_n = KEY[ 1 ];
33
34 assign write = SW[ 17 ];
35 regne #(.n( 1 ) ) r0(write,clk,rst_n, 1 ' b1,SRAM_WE_N); //同步write
36
37 assign address = SW[ 15 : 11 ];
38 regne #(.n( 5 )) r1(address,clk,rst_n, 1 ' b1,SRAM_ADDR[4:0]); //同步address
39 assign SRAM_ADDR[ 17 : 5 ] = 13 ' b0;
40
41 assign DataIn = SW[ 7 : 0 ];
42 regne #(.n( 8 )) r2(DataIn,clk,rst_n, 1 ' b1,DataIn_reg[7:0]); //同步DataIn
43 assign DataIn_reg[ 15 : 8 ] = 8 ' b0;
44
45 assign SRAM_DQ = (SRAM_WE_N == 0 ) ? DataIn_reg: 16 ' bz;
46
47 assign DataOut = SRAM_DQ[ 7 : 0 ];
48
49 regne #(.n( 1 )) r3( 1 ' b1,clk,rst_n,1 ' b1,ce_n); // CE初始化,上电为无效,避免写入
50 assign SRAM_CE_N =~ ce_n;
51
52 assign
53 SRAM_OE_N = 1 ' b0,
54 SRAM_UB_N = 1 ' b0,
55 SRAM_LB_N = 1 ' b0;
56
57 assign LEDG = SW[ 17 ]; // Write的标记
58
59 // 调用7-seg显示模块
60 seg_lut h5(HEX5,DataIn[ 7 : 4 ]); // DataIn
61 seg_lut h4(HEX4,DataIn[ 3 : 0 ]);
62
63 seg_lut h7(HEX7,{{ 3 { 1 ' b0}},address[4]}); //address
64 seg_lut h6(HEX6,address[ 3 : 0 ]);
65
66 seg_lut h1(HEX1,DataOut[ 7 : 4 ]); // DataOut
67 seg_lut h0(HEX0,DataOut[ 3 : 0 ]);
68
69 endmodule
70
71 // 7-seg
72
73 module seg_lut(oseg,idig);
74 input [ 3 : 0 ] idig;
75 output reg [ 0 : 6 ] oseg;
76
77 always @(idig)
78 case (idig)
79 4 ' h0: oseg=7 ' b000_0001;
80 4 ' h1: oseg=7 ' b100_1111; // --------0--------
81 4 ' h2: oseg=7 ' b001_0010; // | |
82 4 ' h3: oseg=7 ' b000_0110; // | | 1
83 4 ' h4: oseg=7 ' b100_1100; // | 5 |
84 4 ' h5: oseg=7 ' b010_0100; // | |
85 4 ' h6: oseg=7 ' b010_0000; // --------6--------
86 4 ' h7: oseg=7 ' b000_1111; // | |
87 4 ' h8: oseg=7 ' b000_0000; // | |
88 4 ' h9: oseg=7 ' b000_1100; // | 4 | 2
89 4 ' hA: oseg=7 ' b000_1000; // | |
90 4 ' hb: oseg=7 ' b110_0000; // --------3---------
91 4 ' hC: oseg=7 ' b011_0001;
92 4 ' hd: oseg=7 ' b100_0010;
93 4 ' hE: oseg=7 ' b011_0000;
94 4 ' hF: oseg=7 ' b011_1000;
95 default : oseg = 7 ' b111_1111;
96 endcase
97
98 endmodule
99
100 // register 用来同步输入信号
101
102 module regne(r,clk,rst_n,e,q);
103 parameter n = 7 ;
104 input [n - 1 : 0 ] r;
105 input clk,rst_n,e;
106 output reg [n - 1 : 0 ] q;
107
108 always @( posedge clk)
109 begin
110 if (rst_n == 0 )
111 q <= {n{ 1 ' b0}};
112 else if (e)
113 q <= r;
114 end
115
116 endmodule
117
所谓双口,即读/写的地址端口分开,即选择Simple dual-port mode。本练习可对存储器初始化,建立一个mif文件。最终在数码管上实现循环显示RAM的数据和地址,间隔为1s。
代码part 5:
1 // part 5
2 // 创建一个读写分开控制的RAM,要求上电后,读地址和其对应的数据以1s的间隔
3 // 循环显示在HEX3-2和HEX1-0上,通过写地址和写控制,可以随时修改对应地址
4 // 的内容。RAM用mif文件初始化。
5
6 // 引脚说明:
7 // -------------------------------------------------------------------
8 // SW[17] write_en
9 // SW[15:11] address
10 // SW[7:0] datain
11 // LEDG0 write
12 // HEX7-6 address
13 // HEX5-4 datain
14 // HEX3-2 read_address
15 // HEX1-0 dataout
16 // KEY0 rst_n
17 // CLOCK_50 clk
18
19 module part5(
20 input CLOCK_50,
21 input [ 0 : 0 ] KEY,
22 input [ 17 : 0 ] SW,
23 output [ 0 : 6 ] HEX7,HEX6,HEX5,HEX4,HEX3,HEX2,HEX1,HEX0,
24 output [ 0 : 0 ] LEDG
25 );
26
27 wire clk,rst_n,write,write_sync;
28 wire [ 4 : 0 ] write_address,write_address_sync;
29 wire [ 7 : 0 ] datain,datain_sync,dataout;
30
31 assign rst_n = KEY[ 0 ];
32 assign clk = CLOCK_50;
33
34 // 同步输入信号
35
36 regne #(.n( 1 )) r0(SW[ 17 ],clk,rst_n, 1 ' b1,write_sync);
37 regne #(.n( 1 )) r1(write_sync,clk,rst_n, 1 ' b1,write);
38
39 regne #(.n( 5 )) r2(SW[ 15 : 11 ],clk,rst_n, 1 ' b1,write_address_sync);
40 regne #(.n( 5 )) r3(write_address_sync,clk,rst_n, 1 ' b1,write_address);
41
42 regne #(.n( 8 )) r4(SW[ 7 : 0 ],clk,rst_n, 1 ' b1,datain_sync);
43 regne #(.n( 8 )) r5(datain_sync,clk,rst_n, 1 ' b1,datain);
44
45 // 分频,产生约1s的时钟
46
47 parameter m = 26 ; // (2^26-1)*20*10^(-9)=1.3s
48 reg [m - 1 : 0 ] div_count;
49 reg [ 4 : 0 ] read_address; // 0-31
50
51 // 寻址计数
52
53 always @( posedge clk)
54 div_count <= div_count + 1 ' b1;
55 always @( posedge clk)
56 if ( ! rst_n)
57 read_address <= 5 ' b0;
58 else if (div_count == 0 ) // 每过约1s
59 read_address <= read_address + 1 ' b1;
60
61 // 引用LPM
62 ramlpm u0(
63 .clock(clk),
64 .data(datain),
65 .rdaddress(read_address),
66 .wraddress(write_address),
67 .wren(write),
68 .q(dataout)
69 );
70
71
72 assign LEDG = write; // Write的标记
73
74 // 调用7-seg显示模块
75 seg_lut h5(HEX5,datain[ 7 : 4 ]); // DataIn
76 seg_lut h4(HEX4,datain[ 3 : 0 ]);
77
78 seg_lut h7(HEX7,{{ 3 { 1 ' b0}},write_address[4]}); //address
79 seg_lut h6(HEX6,write_address[ 3 : 0 ]);
80
81 seg_lut h1(HEX1,dataout[ 7 : 4 ]); // DataOut
82 seg_lut h0(HEX0,dataout[ 3 : 0 ]);
83
84 seg_lut h3(HEX3,{{ 3 { 1 ' b0}},read_address[4]}); //address
85 seg_lut h2(HEX2,read_address[ 3 : 0 ]);
86
87 endmodule
88
89 // 7-seg
90
91 module seg_lut(oseg,idig);
92 input [ 3 : 0 ] idig;
93 output reg [ 0 : 6 ] oseg;
94
95 always @(idig)
96 case (idig)
97 4 ' h0: oseg=7 ' b000_0001;
98 4 ' h1: oseg=7 ' b100_1111; // --------0--------
99 4 ' h2: oseg=7 ' b001_0010; // | |
100 4 ' h3: oseg=7 ' b000_0110; // | | 1
101 4 ' h4: oseg=7 ' b100_1100; // | 5 |
102 4 ' h5: oseg=7 ' b010_0100; // | |
103 4 ' h6: oseg=7 ' b010_0000; // --------6--------
104 4 ' h7: oseg=7 ' b000_1111; // | |
105 4 ' h8: oseg=7 ' b000_0000; // | |
106 4 ' h9: oseg=7 ' b000_1100; // | 4 | 2
107 4 ' hA: oseg=7 ' b000_1000; // | |
108 4 ' hb: oseg=7 ' b110_0000; // --------3---------
109 4 ' hC: oseg=7 ' b011_0001;
110 4 ' hd: oseg=7 ' b100_0010;
111 4 ' hE: oseg=7 ' b011_0000;
112 4 ' hF: oseg=7 ' b011_1000;
113 default : oseg = 7 ' b111_1111;
114 endcase
115
116 endmodule
117
118 // register 用来同步输入信号
119
120 module regne(r,clk,rst_n,e,q);
121 parameter n = 7 ;
122 input [n - 1 : 0 ] r;
123 input clk,rst_n,e;
124 output reg [n - 1 : 0 ] q;
125
126 always @( posedge clk)
127 begin
128 if (rst_n == 0 )
129 q <= {n{ 1 ' b0}};
130 else if (e)
131 q <= r;
132 end
133
134 endmodule
135
136
137
1 // megafunction wizard: %RAM: 2-PORT%
2 // GENERATION: STANDARD
3 // VERSION: WM1.0
4 // MODULE: altsyncram
5
6 // ============================================================
7 // File Name: ramlpm.v
8 // Megafunction Name(s):
9 // altsyncram
10 //
11 // Simulation Library Files(s):
12 // altera_mf
13 // ============================================================
14 // ************************************************************
15 // THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
16 //
17 // 9.1 Build 222 10/21/2009 SJ Full Version
18 // ************************************************************
19
20
21 // Copyright (C) 1991-2009 Altera Corporation
22 // Your use of Altera Corporation's design tools, logic functions
23 // and other software and tools, and its AMPP partner logic
24 // functions, and any output files from any of the foregoing
25 // (including device programming or simulation files), and any
26 // associated documentation or information are expressly subject
27 // to the terms and conditions of the Altera Program License
28 // Subscription Agreement, Altera MegaCore Function License
29 // Agreement, or other applicable license agreement, including,
30 // without limitation, that your use is for the sole purpose of
31 // programming logic devices manufactured by Altera and sold by
32 // Altera or its authorized distributors. Please refer to the
33 // applicable agreement for further details.
34
35
36 // synopsys translate_off
37 `timescale 1 ps / 1 ps
38 // synopsys translate_on
39 module ramlpm (
40 clock,
41 data,
42 rdaddress,
43 wraddress,
44 wren,
45 q);
46
47 input clock;
48 input [ 7 : 0 ] data;
49 input [ 4 : 0 ] rdaddress;
50 input [ 4 : 0 ] wraddress;
51 input wren;
52 output [ 7 : 0 ] q;
53 `ifndef ALTERA_RESERVED_QIS
54 // synopsys translate_off
55 `endif
56 tri1 wren;
57 `ifndef ALTERA_RESERVED_QIS
58 // synopsys translate_on
59 `endif
60
61 wire [ 7 : 0 ] sub_wire0;
62 wire [ 7 : 0 ] q = sub_wire0[ 7 : 0 ];
63
64 altsyncram altsyncram_component (
65 .wren_a (wren),
66 .clock0 (clock),
67 .address_a (wraddress),
68 .address_b (rdaddress),
69 .data_a (data),
70 .q_b (sub_wire0),
71 .aclr0 ( 1 ' b0),
72 .aclr1 ( 1 ' b0),
73 .addressstall_a ( 1 ' b0),
74 .addressstall_b ( 1 ' b0),
75 .byteena_a ( 1 ' b1),
76 .byteena_b ( 1 ' b1),
77 .clock1 ( 1 ' b1),
78 .clocken0 ( 1 ' b1),
79 .clocken1 ( 1 ' b1),
80 .clocken2 ( 1 ' b1),
81 .clocken3 ( 1 ' b1),
82 .data_b ({ 8 { 1 ' b1}}),
83 .eccstatus (),
84 .q_a (),
85 .rden_a ( 1 ' b1),
86 .rden_b ( 1 ' b1),
87 .wren_b ( 1 ' b0));
88 defparam
89 altsyncram_component.address_reg_b = " CLOCK0 " ,
90 altsyncram_component.clock_enable_input_a = " BYPASS " ,
91 altsyncram_component.clock_enable_input_b = " BYPASS " ,
92 altsyncram_component.clock_enable_output_a = " BYPASS " ,
93 altsyncram_component.clock_enable_output_b = " BYPASS " ,
94 altsyncram_component.init_file = " ramlpm.mif " ,
95 altsyncram_component.intended_device_family = " Cyclone II " ,
96 altsyncram_component.lpm_type = " altsyncram " ,
97 altsyncram_component.numwords_a = 32 ,
98 altsyncram_component.numwords_b = 32 ,
99 altsyncram_component.operation_mode = " DUAL_PORT " ,
100 altsyncram_component.outdata_aclr_b = " NONE " ,
101 altsyncram_component.outdata_reg_b = " UNREGISTERED " ,
102 altsyncram_component.power_up_uninitialized = " FALSE " ,
103 altsyncram_component.read_during_write_mode_mixed_ports = " DONT_CARE " ,
104 altsyncram_component.widthad_a = 5 ,
105 altsyncram_component.widthad_b = 5 ,
106 altsyncram_component.width_a = 8 ,
107 altsyncram_component.width_b = 8 ,
108 altsyncram_component.width_byteena_a = 1 ;
109
110
111 endmodule
112
113 // ============================================================
114 // CNX file retrieval info
115 // ============================================================
116 // Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0"
117 // Retrieval info: PRIVATE: ADDRESSSTALL_B NUMERIC "0"
118 // Retrieval info: PRIVATE: BYTEENA_ACLR_A NUMERIC "0"
119 // Retrieval info: PRIVATE: BYTEENA_ACLR_B NUMERIC "0"
120 // Retrieval info: PRIVATE: BYTE_ENABLE_A NUMERIC "0"
121 // Retrieval info: PRIVATE: BYTE_ENABLE_B NUMERIC "0"
122 // Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8"
123 // Retrieval info: PRIVATE: BlankMemory NUMERIC "0"
124 // Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0"
125 // Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_B NUMERIC "0"
126 // Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0"
127 // Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_B NUMERIC "0"
128 // Retrieval info: PRIVATE: CLRdata NUMERIC "0"
129 // Retrieval info: PRIVATE: CLRq NUMERIC "0"
130 // Retrieval info: PRIVATE: CLRrdaddress NUMERIC "0"
131 // Retrieval info: PRIVATE: CLRrren NUMERIC "0"
132 // Retrieval info: PRIVATE: CLRwraddress NUMERIC "0"
133 // Retrieval info: PRIVATE: CLRwren NUMERIC "0"
134 // Retrieval info: PRIVATE: Clock NUMERIC "0"
135 // Retrieval info: PRIVATE: Clock_A NUMERIC "0"
136 // Retrieval info: PRIVATE: Clock_B NUMERIC "0"
137 // Retrieval info: PRIVATE: ECC NUMERIC "0"
138 // Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0"
139 // Retrieval info: PRIVATE: INDATA_ACLR_B NUMERIC "0"
140 // Retrieval info: PRIVATE: INDATA_REG_B NUMERIC "0"
141 // Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_B"
142 // Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0"
143 // Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II"
144 // Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0"
145 // Retrieval info: PRIVATE: JTAG_ID STRING "NONE"
146 // Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"
147 // Retrieval info: PRIVATE: MEMSIZE NUMERIC "256"
148 // Retrieval info: PRIVATE: MEM_IN_BITS NUMERIC "0"
149 // Retrieval info: PRIVATE: MIFfilename STRING "ramlpm.mif"
150 // Retrieval info: PRIVATE: OPERATION_MODE NUMERIC "2"
151 // Retrieval info: PRIVATE: OUTDATA_ACLR_B NUMERIC "0"
152 // Retrieval info: PRIVATE: OUTDATA_REG_B NUMERIC "0"
153 // Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
154 // Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_MIXED_PORTS NUMERIC "2"
155 // Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "4"
156 // Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_B NUMERIC "4"
157 // Retrieval info: PRIVATE: REGdata NUMERIC "1"
158 // Retrieval info: PRIVATE: REGq NUMERIC "1"
159 // Retrieval info: PRIVATE: REGrdaddress NUMERIC "1"
160 // Retrieval info: PRIVATE: REGrren NUMERIC "1"
161 // Retrieval info: PRIVATE: REGwraddress NUMERIC "1"
162 // Retrieval info: PRIVATE: REGwren NUMERIC "1"
163 // Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
164 // Retrieval info: PRIVATE: USE_DIFF_CLKEN NUMERIC "0"
165 // Retrieval info: PRIVATE: UseDPRAM NUMERIC "1"
166 // Retrieval info: PRIVATE: VarWidth NUMERIC "0"
167 // Retrieval info: PRIVATE: WIDTH_READ_A NUMERIC "8"
168 // Retrieval info: PRIVATE: WIDTH_READ_B NUMERIC "8"
169 // Retrieval info: PRIVATE: WIDTH_WRITE_A NUMERIC "8"
170 // Retrieval info: PRIVATE: WIDTH_WRITE_B NUMERIC "8"
171 // Retrieval info: PRIVATE: WRADDR_ACLR_B NUMERIC "0"
172 // Retrieval info: PRIVATE: WRADDR_REG_B NUMERIC "0"
173 // Retrieval info: PRIVATE: WRCTRL_ACLR_B NUMERIC "0"
174 // Retrieval info: PRIVATE: enable NUMERIC "0"
175 // Retrieval info: PRIVATE: rden NUMERIC "0"
176 // Retrieval info: CONSTANT: ADDRESS_REG_B STRING "CLOCK0"
177 // Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS"
178 // Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_B STRING "BYPASS"
179 // Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS"
180 // Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_B STRING "BYPASS"
181 // Retrieval info: CONSTANT: INIT_FILE STRING "ramlpm.mif"
182 // Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II"
183 // Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"
184 // Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "32"
185 // Retrieval info: CONSTANT: NUMWORDS_B NUMERIC "32"
186 // Retrieval info: CONSTANT: OPERATION_MODE STRING "DUAL_PORT"
187 // Retrieval info: CONSTANT: OUTDATA_ACLR_B STRING "NONE"
188 // Retrieval info: CONSTANT: OUTDATA_REG_B STRING "UNREGISTERED"
189 // Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE"
190 // Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_MIXED_PORTS STRING "DONT_CARE"
191 // Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "5"
192 // Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "5"
193 // Retrieval info: CONSTANT: WIDTH_A NUMERIC "8"
194 // Retrieval info: CONSTANT: WIDTH_B NUMERIC "8"
195 // Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
196 // Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL clock
197 // Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL data[7..0]
198 // Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL q[7..0]
199 // Retrieval info: USED_PORT: rdaddress 0 0 5 0 INPUT NODEFVAL rdaddress[4..0]
200 // Retrieval info: USED_PORT: wraddress 0 0 5 0 INPUT NODEFVAL wraddress[4..0]
201 // Retrieval info: USED_PORT: wren 0 0 0 0 INPUT VCC wren
202 // Retrieval info: CONNECT: @data_a 0 0 8 0 data 0 0 8 0
203 // Retrieval info: CONNECT: @wren_a 0 0 0 0 wren 0 0 0 0
204 // Retrieval info: CONNECT: q 0 0 8 0 @q_b 0 0 8 0
205 // Retrieval info: CONNECT: @address_a 0 0 5 0 wraddress 0 0 5 0
206 // Retrieval info: CONNECT: @address_b 0 0 5 0 rdaddress 0 0 5 0
207 // Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0
208 // Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
209 // Retrieval info: GEN_FILE: TYPE_NORMAL ramlpm.v TRUE
210 // Retrieval info: GEN_FILE: TYPE_NORMAL ramlpm.inc FALSE
211 // Retrieval info: GEN_FILE: TYPE_NORMAL ramlpm.cmp FALSE
212 // Retrieval info: GEN_FILE: TYPE_NORMAL ramlpm.bsf FALSE
213 // Retrieval info: GEN_FILE: TYPE_NORMAL ramlpm_inst.v FALSE
214 // Retrieval info: GEN_FILE: TYPE_NORMAL ramlpm_bb.v FALSE
215 // Retrieval info: GEN_FILE: TYPE_NORMAL ramlpm_waveforms.html TRUE
216 // Retrieval info: GEN_FILE: TYPE_NORMAL ramlpm_wave*.jpg FALSE
217 // Retrieval info: LIB_FILE: altera_mf
修改Part V的RAM,用多路器实现一个地址端口复用。在LPM里选择Allow In-system Memory Content Editor to capture and update content independently of the system clock。存储器ID设为32X8.
调用这个RAM模块,实现与Part 5同样的功能。
在使用In-System Memory Content Editor之前,需要设置参数。Assignment / setting / Analysis & Synthesis Setting / Defualt Parameters 添加一个参数CYCLONEII_SAFE_WRITE, 值为RESTRUCTURE。
编译、测试。与Part 5的结果比较。
Tools / In-System Memory Content Editor读取和修改RAM的内容,并与数码管的显示比较。
代码part 6;
1 // part 6 单端口的RAM,读写共用地址总线。练习In-system memory content editor
2 /// 引脚说明:
3 // -------------------------------------------------------------------
4 // SW[17] write_en
5 // SW[15:11] address
6 // SW[7:0] datain
7 // LEDG0 write
8 // HEX7-6 address
9 // HEX5-4 datain
10 // HEX3-2 read_address
11 // HEX1-0 dataout
12 // KEY0 rst_n
13 // CLOCK_50 clk
14
15 module part6(
16 input CLOCK_50,
17 input [ 0 : 0 ] KEY,
18 input [ 17 : 0 ] SW,
19 output [ 0 : 6 ] HEX7,HEX6,HEX5,HEX4,HEX3,HEX2,HEX1,HEX0,
20 output [ 0 : 0 ] LEDG
21 );
22
23 wire clk,rst_n,write,write_sync;
24 wire [ 4 : 0 ] write_address,write_address_sync;
25 wire [ 7 : 0 ] datain,datain_sync,dataout;
26
27 assign rst_n = KEY[ 0 ];
28 assign clk = CLOCK_50;
29
30 // 同步输入信号
31
32 regne #(.n( 1 )) r0(SW[ 17 ],clk,rst_n, 1 ' b1,write_sync);
33 regne #(.n( 1 )) r1(write_sync,clk,rst_n, 1 ' b1,write);
34
35 regne #(.n( 5 )) r2(SW[ 15 : 11 ],clk,rst_n, 1 ' b1,write_address_sync);
36 regne #(.n( 5 )) r3(write_address_sync,clk,rst_n, 1 ' b1,write_address);
37
38 regne #(.n( 8 )) r4(SW[ 7 : 0 ],clk,rst_n, 1 ' b1,datain_sync);
39 regne #(.n( 8 )) r5(datain_sync,clk,rst_n, 1 ' b1,datain);
40
41 // 分频,产生约1s的时钟
42
43 parameter m = 26 ; // (2^26-1)*20*10^(-9)=1.3s
44 reg [m - 1 : 0 ] div_count;
45 reg [ 4 : 0 ] read_address; // 0-31
46
47 // 寻址计数
48
49 always @( posedge clk)
50 div_count <= div_count + 1 ' b1;
51 always @( posedge clk)
52 if ( ! rst_n)
53 read_address <= 5 ' b0;
54 else if (div_count == 0 ) // 每过约1s
55 read_address <= read_address + 1 ' b1;
56
57 // 用multiplexer决定地址
58 wire [ 4 : 0 ] address;
59 assign address = (write == 1 ' b1)?write_address:read_address;
60
61 // 引用LPM
62 ramlpm u0(
63 .clock(clk),
64 .data(datain),
65 .address(address),
66 .wren(write),
67 .q(dataout)
68 );
69
70
71 assign LEDG = write; // Write的标记
72
73 // 调用7-seg显示模块
74 seg_lut h5(HEX5,datain[ 7 : 4 ]); // DataIn
75 seg_lut h4(HEX4,datain[ 3 : 0 ]);
76
77 seg_lut h7(HEX7,{{ 3 { 1 ' b0}},write_address[4]}); //address
78 seg_lut h6(HEX6,write_address[ 3 : 0 ]);
79
80 seg_lut h1(HEX1,dataout[ 7 : 4 ]); // DataOut
81 seg_lut h0(HEX0,dataout[ 3 : 0 ]);
82
83 seg_lut h3(HEX3,{{ 3 { 1 ' b0}},read_address[4]}); //address
84 seg_lut h2(HEX2,read_address[ 3 : 0 ]);
85
86 endmodule
87
88 // 7-seg
89
90 module seg_lut(oseg,idig);
91 input [ 3 : 0 ] idig;
92 output reg [ 0 : 6 ] oseg;
93
94 always @(idig)
95 case (idig)
96 4 ' h0: oseg=7 ' b000_0001;
97 4 ' h1: oseg=7 ' b100_1111; // --------0--------
98 4 ' h2: oseg=7 ' b001_0010; // | |
99 4 ' h3: oseg=7 ' b000_0110; // | | 1
100 4 ' h4: oseg=7 ' b100_1100; // | 5 |
101 4 ' h5: oseg=7 ' b010_0100; // | |
102 4 ' h6: oseg=7 ' b010_0000; // --------6--------
103 4 ' h7: oseg=7 ' b000_1111; // | |
104 4 ' h8: oseg=7 ' b000_0000; // | |
105 4 ' h9: oseg=7 ' b000_1100; // | 4 | 2
106 4 ' hA: oseg=7 ' b000_1000; // | |
107 4 ' hb: oseg=7 ' b110_0000; // --------3---------
108 4 ' hC: oseg=7 ' b011_0001;
109 4 ' hd: oseg=7 ' b100_0010;
110 4 ' hE: oseg=7 ' b011_0000;
111 4 ' hF: oseg=7 ' b011_1000;
112 default : oseg = 7 ' b111_1111;
113 endcase
114
115 endmodule
116
117 // register 用来同步输入信号
118
119 module regne(r,clk,rst_n,e,q);
120 parameter n = 7 ;
121 input [n - 1 : 0 ] r;
122 input clk,rst_n,e;
123 output reg [n - 1 : 0 ] q;
124
125 always @( posedge clk)
126 begin
127 if (rst_n == 0 )
128 q <= {n{ 1 ' b0}};
129 else if (e)
130 q <= r;
131 end
132
133 endmodule
1 // megafunction wizard: %RAM: 1-PORT%
2 // GENERATION: STANDARD
3 // VERSION: WM1.0
4 // MODULE: altsyncram
5
6 // ============================================================
7 // File Name: ramlpm.v
8 // Megafunction Name(s):
9 // altsyncram
10 //
11 // Simulation Library Files(s):
12 // altera_mf
13 // ============================================================
14 // ************************************************************
15 // THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
16 //
17 // 9.1 Build 222 10/21/2009 SJ Full Version
18 // ************************************************************
19
20
21 // Copyright (C) 1991-2009 Altera Corporation
22 // Your use of Altera Corporation's design tools, logic functions
23 // and other software and tools, and its AMPP partner logic
24 // functions, and any output files from any of the foregoing
25 // (including device programming or simulation files), and any
26 // associated documentation or information are expressly subject
27 // to the terms and conditions of the Altera Program License
28 // Subscription Agreement, Altera MegaCore Function License
29 // Agreement, or other applicable license agreement, including,
30 // without limitation, that your use is for the sole purpose of
31 // programming logic devices manufactured by Altera and sold by
32 // Altera or its authorized distributors. Please refer to the
33 // applicable agreement for further details.
34
35
36 // synopsys translate_off
37 `timescale 1 ps / 1 ps
38 // synopsys translate_on
39 module ramlpm (
40 address,
41 clock,
42 data,
43 wren,
44 q);
45
46 input [ 4 : 0 ] address;
47 input clock;
48 input [ 7 : 0 ] data;
49 input wren;
50 output [ 7 : 0 ] q;
51
52 wire [ 7 : 0 ] sub_wire0;
53 wire [ 7 : 0 ] q = sub_wire0[ 7 : 0 ];
54
55 altsyncram altsyncram_component (
56 .wren_a (wren),
57 .clock0 (clock),
58 .address_a (address),
59 .data_a (data),
60 .q_a (sub_wire0),
61 .aclr0 ( 1 ' b0),
62 .aclr1 ( 1 ' b0),
63 .address_b ( 1 ' b1),
64 .addressstall_a ( 1 ' b0),
65 .addressstall_b ( 1 ' b0),
66 .byteena_a ( 1 ' b1),
67 .byteena_b ( 1 ' b1),
68 .clock1 ( 1 ' b1),
69 .clocken0 ( 1 ' b1),
70 .clocken1 ( 1 ' b1),
71 .clocken2 ( 1 ' b1),
72 .clocken3 ( 1 ' b1),
73 .data_b ( 1 ' b1),
74 .eccstatus (),
75 .q_b (),
76 .rden_a ( 1 ' b1),
77 .rden_b ( 1 ' b1),
78 .wren_b ( 1 ' b0));
79 defparam
80 altsyncram_component.clock_enable_input_a = " BYPASS " ,
81 altsyncram_component.clock_enable_output_a = " BYPASS " ,
82 altsyncram_component.init_file = " ../part5/ramlpm.mif " ,
83 altsyncram_component.intended_device_family = " Cyclone II " ,
84 altsyncram_component.lpm_hint = " ENABLE_RUNTIME_MOD=YES,INSTANCE_NAME=32x8 " ,
85 altsyncram_component.lpm_type = " altsyncram " ,
86 altsyncram_component.numwords_a = 32 ,
87 altsyncram_component.operation_mode = " SINGLE_PORT " ,
88 altsyncram_component.outdata_aclr_a = " NONE " ,
89 altsyncram_component.outdata_reg_a = " UNREGISTERED " ,
90 altsyncram_component.power_up_uninitialized = " FALSE " ,
91 altsyncram_component.ram_block_type = " M4K " ,
92 altsyncram_component.widthad_a = 5 ,
93 altsyncram_component.width_a = 8 ,
94 altsyncram_component.width_byteena_a = 1 ;
95
96
97 endmodule
98
99 // ============================================================
100 // CNX file retrieval info
101 // ============================================================
102 // Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0"
103 // Retrieval info: PRIVATE: AclrAddr NUMERIC "0"
104 // Retrieval info: PRIVATE: AclrByte NUMERIC "0"
105 // Retrieval info: PRIVATE: AclrData NUMERIC "0"
106 // Retrieval info: PRIVATE: AclrOutput NUMERIC "0"
107 // Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0"
108 // Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8"
109 // Retrieval info: PRIVATE: BlankMemory NUMERIC "0"
110 // Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0"
111 // Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0"
112 // Retrieval info: PRIVATE: Clken NUMERIC "0"
113 // Retrieval info: PRIVATE: DataBusSeparated NUMERIC "1"
114 // Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0"
115 // Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A"
116 // Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0"
117 // Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II"
118 // Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "1"
119 // Retrieval info: PRIVATE: JTAG_ID STRING "32x8"
120 // Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"
121 // Retrieval info: PRIVATE: MIFfilename STRING "../part5/ramlpm.mif"
122 // Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "32"
123 // Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "2"
124 // Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3"
125 // Retrieval info: PRIVATE: RegAddr NUMERIC "1"
126 // Retrieval info: PRIVATE: RegData NUMERIC "1"
127 // Retrieval info: PRIVATE: RegOutput NUMERIC "0"
128 // Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
129 // Retrieval info: PRIVATE: SingleClock NUMERIC "1"
130 // Retrieval info: PRIVATE: UseDQRAM NUMERIC "1"
131 // Retrieval info: PRIVATE: WRCONTROL_ACLR_A NUMERIC "0"
132 // Retrieval info: PRIVATE: WidthAddr NUMERIC "5"
133 // Retrieval info: PRIVATE: WidthData NUMERIC "8"
134 // Retrieval info: PRIVATE: rden NUMERIC "0"
135 // Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS"
136 // Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS"
137 // Retrieval info: CONSTANT: INIT_FILE STRING "../part5/ramlpm.mif"
138 // Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II"
139 // Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=YES,INSTANCE_NAME=32x8"
140 // Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"
141 // Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "32"
142 // Retrieval info: CONSTANT: OPERATION_MODE STRING "SINGLE_PORT"
143 // Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE"
144 // Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED"
145 // Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE"
146 // Retrieval info: CONSTANT: RAM_BLOCK_TYPE STRING "M4K"
147 // Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "5"
148 // Retrieval info: CONSTANT: WIDTH_A NUMERIC "8"
149 // Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
150 // Retrieval info: USED_PORT: address 0 0 5 0 INPUT NODEFVAL address[4..0]
151 // Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL clock
152 // Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL data[7..0]
153 // Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL q[7..0]
154 // Retrieval info: USED_PORT: wren 0 0 0 0 INPUT NODEFVAL wren
155 // Retrieval info: CONNECT: @address_a 0 0 5 0 address 0 0 5 0
156 // Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0
157 // Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0
158 // Retrieval info: CONNECT: @data_a 0 0 8 0 data 0 0 8 0
159 // Retrieval info: CONNECT: @wren_a 0 0 0 0 wren 0 0 0 0
160 // Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
161 // Retrieval info: GEN_FILE: TYPE_NORMAL ramlpm.v TRUE
162 // Retrieval info: GEN_FILE: TYPE_NORMAL ramlpm.inc FALSE
163 // Retrieval info: GEN_FILE: TYPE_NORMAL ramlpm.cmp FALSE
164 // Retrieval info: GEN_FILE: TYPE_NORMAL ramlpm.bsf FALSE
165 // Retrieval info: GEN_FILE: TYPE_NORMAL ramlpm_inst.v FALSE
166 // Retrieval info: GEN_FILE: TYPE_NORMAL ramlpm_bb.v FALSE
167 // Retrieval info: GEN_FILE: TYPE_NORMAL ramlpm_waveforms.html TRUE
168 // Retrieval info: GEN_FILE: TYPE_NORMAL ramlpm_wave*.jpg FALSE
169 // Retrieval info: LIB_FILE: altera_mf
本练习借助DE2 控制面板这个工具来对片外存储器初始化和查看、修改。
DE2 control panel的使用方法可查阅用户手册。下载相应的电路,打开应用程序,启动接口,即可实现对SRAM的控制。
代码part 7:
1 // 练习SRAM的读/写功能,通过FPGA控制SRAM和通过DE2 control pannel控制SRAM
2
3 /// 引脚说明:
4 // -------------------------------------------------------------------
5 // SW[17] write_en
6 // SW[15:11] address
7 // SW[7:0] datain
8 // LEDG0 write
9 // HEX7-6 address
10 // HEX5-4 datain
11 // HEX3-2 read_address
12 // HEX1-0 dataout
13 // KEY0 rst_n
14 // CLOCK_50 clk
15
16 module part7(
17 input CLOCK_50,
18 input [ 17 : 0 ] SW,
19 input [ 0 : 0 ] KEY, // rst_n
20 output [ 0 : 0 ] LEDG,
21 output [ 0 : 6 ] HEX7,HEX6,HEX5,HEX4,HEX3,HEX2,HEX1,HEX0,
22
23 // SRAM pors
24 output [ 17 : 0 ] SRAM_ADDR, // address
25 inout [ 15 : 0 ] SRAM_DQ, // datain , dataout
26 output SRAM_CE_N, // chip enable
27 SRAM_OE_N, // output enable
28 SRAM_WE_N, // write enable
29 SRAM_UB_N, // upper byte
30 SRAM_LB_N // lower byte
31 );
32
33
34 wire rst_n,clk,writen_sync,ce,ce1,ce2;
35 wire [ 7 : 0 ] datain,datain_sync,dataout;
36 wire [ 4 : 0 ] write_address,write_address_sync;
37
38 assign clk = CLOCK_50;
39 assign rst_n = KEY[ 0 ];
40
41 // 同步输入信号
42
43 regne #(.n( 1 )) r0( ! SW[ 17 ],clk,rst_n, 1 ' b1,writen_sync);
44 regne #(.n( 1 ) ) r1(writen_sync,clk,rst_n, 1 ' b1,SRAM_WE_N); //同步write
45
46 regne #(.n( 5 )) r2(SW[ 15 : 11 ],clk,rst_n, 1 ' b1,write_address_sync);
47 regne #(.n( 5 )) r3(write_address_sync,clk,rst_n, 1 ' b1,write_address); //同步address
48
49 regne #(.n( 8 )) r4(SW[ 7 : 0 ],clk,rst_n, 1 ' b1,datain_sync);
50 regne #(.n( 8 )) r5(datain_sync,clk,rst_n, 1 ' b1,datain); //同步DataIn
51
52 // 分频,产生约1s的时钟
53 parameter m = 26 ;
54 reg [m - 1 : 0 ] div_count;
55 reg [ 4 : 0 ] read_address;
56
57 // 寻址
58 always @( posedge clk)
59 div_count <= div_count + 1 ;
60
61 always @( posedge clk)
62 if ( ! rst_n)
63 read_address <= 5 ' b0;
64 else if (div_count == 0 )
65 read_address <= read_address + 1 ' b1;
66
67 // 读/写选择
68 assign SRAM_ADDR = (SRAM_WE_N == 1 ' b0)?{13 ' b0,write_address}:{ 13 ' b0,read_address};
69
70 assign SRAM_DQ = (SRAM_WE_N == 1 ' b0)?{8 ' b0,datain}: 16 ' bz;
71
72 assign dataout = SRAM_DQ[ 7 : 0 ];
73
74 regne #(.n( 1 )) r6( 1 ' b1,clk,rst_n,1 ' b1,ce1); // CE初始化,上电后2个时钟,避免写入
75 regne #(.n( 1 )) r7(ce1,clk,rst_n, 1 ' b1,ce2);
76 regne #(.n( 1 )) r8(ce2,clk,rst_n, 1 ' b1,ce);
77 assign SRAM_CE_N =~ ce;
78
79 assign
80 SRAM_OE_N = 1 ' b0,
81 SRAM_UB_N = 1 ' b0,
82 SRAM_LB_N = 1 ' b0;
83
84 assign LEDG = SRAM_WE_N; // Write的标记
85
86 // 调用7-seg显示模块
87 seg_lut h5(HEX5,datain[ 7 : 4 ]); // DataIn
88 seg_lut h4(HEX4,datain[ 3 : 0 ]);
89
90 seg_lut h7(HEX7,{{ 3 { 1 ' b0}},write_address[4]}); //address
91 seg_lut h6(HEX6,write_address[ 3 : 0 ]);
92
93 seg_lut h1(HEX1,dataout[ 7 : 4 ]); // DataOut
94 seg_lut h0(HEX0,dataout[ 3 : 0 ]);
95
96 seg_lut h3(HEX3,{ 3 ' b0,read_address[4]}); //read_address
97 seg_lut h2(HEX2,read_address[ 3 : 0 ]);
98
99 endmodule
100
101 // 7-seg
102
103 module seg_lut(oseg,idig);
104 input [ 3 : 0 ] idig;
105 output reg [ 0 : 6 ] oseg;
106
107 always @(idig)
108 case (idig)
109 4 ' h0: oseg=7 ' b000_0001;
110 4 ' h1: oseg=7 ' b100_1111; // --------0--------
111 4 ' h2: oseg=7 ' b001_0010; // | |
112 4 ' h3: oseg=7 ' b000_0110; // | | 1
113 4 ' h4: oseg=7 ' b100_1100; // | 5 |
114 4 ' h5: oseg=7 ' b010_0100; // | |
115 4 ' h6: oseg=7 ' b010_0000; // --------6--------
116 4 ' h7: oseg=7 ' b000_1111; // | |
117 4 ' h8: oseg=7 ' b000_0000; // | |
118 4 ' h9: oseg=7 ' b000_1100; // | 4 | 2
119 4 ' hA: oseg=7 ' b000_1000; // | |
120 4 ' hb: oseg=7 ' b110_0000; // --------3---------
121 4 ' hC: oseg=7 ' b011_0001;
122 4 ' hd: oseg=7 ' b100_0010;
123 4 ' hE: oseg=7 ' b011_0000;
124 4 ' hF: oseg=7 ' b011_1000;
125 default : oseg = 7 ' b111_1111;
126 endcase
127
128 endmodule
129
130 // register 用来同步输入信号
131
132 module regne(r,clk,rst_n,e,q);
133 parameter n = 7 ;
134 input [n - 1 : 0 ] r;
135 input clk,rst_n,e;
136 output reg [n - 1 : 0 ] q;
137
138 always @( posedge clk)
139 begin
140 if (rst_n == 0 )
141 q <= {n{ 1 ' b0}};
142 else if (e)
143 q <= r;
144 end
145
146 endmodule
147
以上7个小练习逐步熟悉对RAM的操作。有意思的是part 7的控制面板。有UI,有驱动电路。