1 //要求:对于74HC595芯片,该芯片在SH_CP(SCLK)的上升沿将DS(DIO)上的数据移入内部的寄存器。
2 //目的:因此我们需要保证DS上的数据在SH_CP的上升沿前后一段时间,保持稳定。
3 //手段:FPGA要在SH_CP的下降沿改变DS的值
4 //先移入的数据,在高位输出。
5 //SH_CP = 12.5Mhz
6 //产生12.5Mhz的时钟有两种思路,第一种使用计数器,计数分频。(存在一个问题DS如何与SH_CP的上升沿和下降沿建立起关系)
7 //不要将SH_CP当成一个时钟信号,而是当成一个普通信号,一个和DS、ST_CP一样的普通信号。
8 //第二种将SH_CP和当成一个普通信号。
9 //顶层hex8_test文件
10
11 module hex8_test(
12 clk,
13 reset_n,
14 sel,
15 seg,
16 SH_CP,
17 ST_CP,
18 DS
19 );
20 input clk;
21 input reset_n;
22
23 output [7:0] sel;
24 output [7:0] seg;
25
26 output SH_CP;
27 output ST_CP;
28 output DS;
29 wire [31:0] disp_data;
30
31 hex8_2 hex8_2_inst0(
32 clk,
33 reset_n,
34 disp_data,
35 sel,
36 seg
37 );
38
39 wire [15:0] data;
40 //先传seg,再传sel,怎么看出来的?
41 assign data= {seg,sel};
42
43 wire s_en;
44 assign s_en = 1;
45 hc595_driver hc595_driver_inst0(
46 clk,
47 reset_n,
48 data,
49 s_en,
50 SH_CP,
51 ST_CP,
52 DS
53 );
54 assign disp_data = 32'h05211314;
55
56 endmodule
57
58 //底层hex8_2源文件
59
60 module hex8_2(
61 clk,
62 reset_n,
63 disp_data,
64 sel,
65 seg
66 );
67 input clk;
68 input reset_n;
69 input [31:0] disp_data;
70 output reg [7:0] sel;
71 output reg [7:0] seg;
72
73
74 reg clk_1k;
75 reg [15:0]div_cnt;
76 //设置分频计数时钟
77 always@(posedge clk or negedge reset_n)
78 if(!reset_n)
79 div_cnt <= 0;
80 else if(div_cnt >= 49999)
81 div_cnt <= 0;
82 else
83 div_cnt <= div_cnt + 1'b1;
84 //这种门控时钟在绝大多数场合不允许使用
85 //定义1ms的时钟(1khz)
86 // always@(posedge clk or negedge reset_n)
87 // if(!reset_n)
88 // clk_1k <= 0;
89 // else if(div_cnt >= 24999)
90 // clk_1k <= !clk_1k;
91
92 //使能时钟
93 always@(posedge clk or negedge reset_n)
94 if(!reset_n)
95 clk_1k <= 0;
96 else if(div_cnt >= 49999)
97 clk_1k <= 1;
98 else
99 clk_1k <= 0;
100
101 reg [2:0] num_cnt;
102 always@(posedge clk or negedge reset_n)
103 if(!reset_n)
104 num_cnt <= 0;
105 else if(clk_1k)//这里面使用的就是使能时钟
106 num_cnt <= num_cnt + 1'b1;
107
108 //书写3—8译码器
109 always@(posedge clk)begin//将组合逻辑用时序的时钟,结果更加精确。
110 case(num_cnt)
111 0:sel <= 8'b0000_0001;
112 1:sel <= 8'b0000_0010;
113 2:sel <= 8'b0000_0100;
114 3:sel <= 8'b0000_1000;
115 4:sel <= 8'b0001_0000;
116 5:sel <= 8'b0010_0000;
117 6:sel <= 8'b0100_0000;
118 7:sel <= 8'b1000_0000;
119 endcase
120 end
121
122 reg [3:0] dis_tmp;
123 always@(posedge clk)begin
124 case(num_cnt)
125 7:dis_tmp <= disp_data[31:28];
126 6:dis_tmp <= disp_data[27:24];
127 5:dis_tmp <= disp_data[23:20];
128 4:dis_tmp <= disp_data[19:16];
129 3:dis_tmp <= disp_data[15:12];
130 2:dis_tmp <= disp_data[11:8];
131 1:dis_tmp <= disp_data[7:4];
132 0:dis_tmp <= disp_data[3:0];
133 endcase
134 end
135
136 always@(posedge clk)begin
137 case(dis_tmp)
138 0:seg <= 8'hc0;
139 1:seg <= 8'hf9;
140 2:seg <= 8'ha4;
141 3:seg <= 8'hb0;
142 4:seg <= 8'h99;
143 5:seg <= 8'h92;
144 6:seg <= 8'h82;
145 7:seg <= 8'hf8;
146 8:seg <= 8'h80;
147 9:seg <= 8'h90;
148 4'ha:seg <= 8'h88;
149 4'hb:seg <= 8'h83;
150 4'hc:seg <= 8'hc6;
151 4'hd:seg <= 8'ha1;
152 4'he:seg <= 8'h86;
153 4'hf:seg <= 8'h8e;
154 endcase
155 end
156 endmodule
157
158 //底层hc595_driver文件
159
160 module hc595_driver(
161 clk,
162 reset_n,
163 data,
164 s_en,
165 SH_CP,
166 ST_CP,
167 DS
168 );
169 input clk;
170 input reset_n;
171 input [15:0]data;
172 input s_en;
173 output reg SH_CP;
174 output reg ST_CP;
175 output reg DS;
176 parameter CNT_MAX = 2;
177 //这样就可以使用瞬时的数据,因为data随时可能会变化,来一个send_go(s_en)信号,就把数据寄存到r_data中。
178 reg[15:0]r_data;
179 always@(posedge clk )
180 if(s_en)
181 r_data <= data;
182
183 //分频计数器得到
184 reg [7:0] divider_cnt;
185 always@(posedge clk or negedge reset_n)
186 if(!reset_n)
187 divider_cnt <= 0;
188 else if(divider_cnt == CNT_MAX - 1)
189 divider_cnt <=0;
190 else
191 divider_cnt <= divider_cnt +1'b1;
192
193 wire sck_plus;
194 assign sck_plus = (divider_cnt ==CNT_MAX - 1);
195 //一个四位数码管需要发送16位数据(8位sel位选,8位seg选),两个四位数码管需要32位数据
196 reg [5:0] SHCP_EDGE_CNT;
197 always@(posedge clk or negedge reset_n)
198 if(!reset_n)
199 SHCP_EDGE_CNT <= 0;
200 else if(sck_plus)begin
201 if(SHCP_EDGE_CNT == 6'd32)
202 SHCP_EDGE_CNT <= 0;
203 else
204 SHCP_EDGE_CNT <= SHCP_EDGE_CNT + 1'b1;
205 end
206
207 always@(posedge clk or negedge reset_n)
208 if(!reset_n)begin
209 SH_CP <= 0;
210 ST_CP <= 0;
211 DS <= 0;
212 end
213 else begin
214 case(SHCP_EDGE_CNT)
215 0:begin SH_CP <= 0;ST_CP <= 0; DS <= r_data[15]; end
216 1:SH_CP <= 1;
217 2:begin SH_CP <= 0; DS <= r_data[14];end
218 3:SH_CP <= 1;
219 4:begin SH_CP <= 0; DS <= r_data[13];end
220 5:SH_CP <= 1;
221 6:begin SH_CP <= 0; DS <= r_data[12];end
222 7:SH_CP <= 1;
223 8:begin SH_CP <= 0; DS <= r_data[11];end
224 9:SH_CP <= 1;
225 10:begin SH_CP <= 0; DS <= r_data[10];end
226 11:SH_CP <= 1;
227 12:begin SH_CP <= 0; DS <= r_data[9];end
228 13:SH_CP <= 1;
229 14:begin SH_CP <= 0; DS <= r_data[8];end
230 15:SH_CP <= 1;
231 16:begin SH_CP <= 0; DS <= r_data[7];end
232 17:SH_CP <= 1;
233 18:begin SH_CP <= 0; DS <= r_data[6];end
234 19:SH_CP <= 1;
235 20:begin SH_CP <= 0; DS <= r_data[5];end
236 21:SH_CP <= 1;
237 22:begin SH_CP <= 0; DS <= r_data[4];end
238 23:SH_CP <= 1;
239 24:begin SH_CP <= 0; DS <= r_data[3];end
240 25:SH_CP <= 1;
241 26:begin SH_CP <= 0; DS <= r_data[2];end
242 27:SH_CP <= 1;
243 28:begin SH_CP <= 0; DS <= r_data[1];end
244 29:SH_CP <= 1;
245 30:begin SH_CP <= 0; DS <= r_data[0];end
246 31:SH_CP <= 1;
247 32:ST_CP <= 1;
248 default:
249 begin
250 SH_CP <= 0;
251 ST_CP <= 0;
252 DS <= 0;
253 end
254 endcase
255 end
256
257
258 endmodule
259
260 //hex8_test.xdc文件
261 set_property PACKAGE_PIN R17 [get_ports {sel[7]}]
262 set_property PACKAGE_PIN P17 [get_ports {sel[6]}]
263 set_property PACKAGE_PIN P2 [get_ports {seg[7]}]
264 set_property PACKAGE_PIN P5 [get_ports {seg[6]}]
265 set_property PACKAGE_PIN P6 [get_ports {seg[5]}]
266 set_property PACKAGE_PIN N5 [get_ports {seg[4]}]
267 set_property PACKAGE_PIN N4 [get_ports {seg[3]}]
268 set_property PACKAGE_PIN N3 [get_ports {seg[2]}]
269 set_property PACKAGE_PIN P4 [get_ports {seg[1]}]
270 set_property PACKAGE_PIN M6 [get_ports {seg[0]}]
271 set_property PACKAGE_PIN P14 [get_ports {sel[5]}]
272 set_property PACKAGE_PIN R16 [get_ports {sel[4]}]
273 set_property PACKAGE_PIN K6 [get_ports {sel[3]}]
274 set_property PACKAGE_PIN J5 [get_ports {sel[2]}]
275 set_property PACKAGE_PIN M5 [get_ports {sel[1]}]
276 set_property PACKAGE_PIN L6 [get_ports {sel[0]}]
277 set_property IOSTANDARD LVCMOS33 [get_ports {seg[7]}]
278 set_property IOSTANDARD LVCMOS33 [get_ports {seg[6]}]
279 set_property IOSTANDARD LVCMOS33 [get_ports {seg[5]}]
280 set_property IOSTANDARD LVCMOS33 [get_ports {seg[4]}]
281 set_property IOSTANDARD LVCMOS33 [get_ports {seg[3]}]
282 set_property IOSTANDARD LVCMOS33 [get_ports {seg[2]}]
283 set_property IOSTANDARD LVCMOS33 [get_ports {seg[1]}]
284 set_property IOSTANDARD LVCMOS33 [get_ports {seg[0]}]
285 set_property IOSTANDARD LVCMOS33 [get_ports {sel[7]}]
286 set_property IOSTANDARD LVCMOS33 [get_ports {sel[6]}]
287 set_property IOSTANDARD LVCMOS33 [get_ports {sel[5]}]
288 set_property IOSTANDARD LVCMOS33 [get_ports {sel[4]}]
289 set_property IOSTANDARD LVCMOS33 [get_ports {sel[3]}]
290 set_property IOSTANDARD LVCMOS33 [get_ports {sel[2]}]
291 set_property IOSTANDARD LVCMOS33 [get_ports {sel[1]}]
292 set_property IOSTANDARD LVCMOS33 [get_ports {sel[0]}]
293 set_property IOSTANDARD LVCMOS33 [get_ports clk]
294 set_property IOSTANDARD LVCMOS33 [get_ports DS]
295 set_property IOSTANDARD LVCMOS33 [get_ports reset_n]
296 set_property IOSTANDARD LVCMOS33 [get_ports SH_CP]
297 set_property IOSTANDARD LVCMOS33 [get_ports ST_CP]
298 set_property PACKAGE_PIN Y18 [get_ports clk]
299 set_property PACKAGE_PIN B21 [get_ports reset_n]
300 set_property PACKAGE_PIN M18 [get_ports DS]
301 set_property PACKAGE_PIN F4 [get_ports SH_CP]
302 set_property PACKAGE_PIN C2 [get_ports ST_CP]
303
304 //hc95——driver_tb仿真文件
305
306 `timescale 1ns / 1ps
307 module hc595_driver_tb();
308 reg clk;
309 reg reset_n;
310 reg [15:0]data;
311 reg s_en;
312 wire SH_CP;
313 wire ST_CP;
314 wire DS;
315 hc595_driver hc595_driver_inst0(
316 clk,
317 reset_n,
318 data,
319 s_en,
320 SH_CP,
321 ST_CP,
322 DS
323 );
324
325 initial clk = 1;
326 always #10 clk = !clk;
327
328 initial begin
329 reset_n = 0;
330 data = 16'h0000;
331 s_en = 0;
332 #201;
333 reset_n = 1;
334 #500
335 data = 16'h47a9;
336 s_en = 1;
337 #20;
338 s_en = 0;
339 #4000;
340
341 data = 16'h5832;
342 s_en = 1;
343 #20;
344 s_en = 0;
345 #4000;
346 $stop;
347 end
348 endmodule
2023-03-29 17:24:35
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人