FPGA学习系列:19. rom到数码管显示设计

FPGA学习交流 发表于 2018-06-18 19:24:11 收藏 已收藏
赞(0) •  评论(0

FPGA学习系列:19. rom到数码管显示设计

FPGA学习交流 发表于 2018-06-18 19:24:11

设计背景:

rom是读写的的静态存储单元,在我们的设计中我们会经常用到,数码管模块同样的大大小小的设计还是工程应用中都有这至关重要的作用。

 

设计原理: 

前几节我们学习了rom存储器的设计,还有数码管模块的设计,为了我们联系这两个模块的应用我们今天将设计一个按键来控制读取rom中的数据,来显示到数码管上。

因为我们的数码管模块的显示频率是10K,所以我们应该小于10K的频率给一个rom地址,从而出一个数据,我们的设计是0.5s出一个数据,这样我们就能在数码管上显示随着地址的增加,数据同样也在变化。

第一步我们要先设计我们的.mif文件,我们在前10个地址是上写入0 -- 10,然后建立一个rom 的ip核,添加进去从而便于后面的例化。

设计模块,我们前面讲过数码管模块,这样就可以直接拿过来用了,今天我们将主要给大家展示我们的rom控制模块。

设计架构图:

 image.png

设计代码:

顶层模块

0 module rom_seg (clk, rst_n, key, sel, seg_n);

1 

2  input clk, rst_n;

3  input key;

4  output [7:0] seg_n;  //段选信号

5  output [2:0] sel;   //位选信号

6 

7  wire [3:0] data;

8  wire [23:0] hex;

9 

10 //6个数码管上显示同样的数据

11 assign hex[23:0] =   {data[3:0],data[3:0],data[3:0],data[3:0],data[3:0],data[3:0]};

12

13 rom rom_inst (   //rom控制模块的例化

14  .key(key), 

15  .clk(clk), 

16  .rst_n(rst_n),

17  .data(data)

18 );

19

20

21 seg SEG(    //数码管模块的裂化

22  .clk(clk),

23  .rst_n(rst_n),

24  .sel(sel),

25  .seg7(seg_n),

26  .data_in(hex)

27 );

28

29

30 endmodule

 

设计模块

0 module rd_rom (key, clk, rst_n, addr);

1 

2  input clk; //输入系统时钟

3  input rst_n; //输入系统复位

4  input key; //按键控制

5 

6  output reg [3:0] addr;

7  reg [31:0] cnt;

8 

9  always @ (posedge clk or negedge rst_n)

10 begin

11  if(!rst_n)  //异步复位

12   addr <= 0;

13  else if (addr < 15 && key == 0 && cnt == 50000000/2 - 1)  

14   addr <= addr + 1'b1;  //地址加1

15  else 

16   addr <= addr;

17 end 

18

19 always @ (posedge clk or negedge rst_n)

20 begin

21  if(!rst_n)

22   begin

23    cnt<=0;

24   end

25  else

26   begin 

27    if(cnt < 50000000/2 - 1)  // 50000000/10000/2 1hz的一 28     cnt <=cnt + 1;

29    else

30     cnt <= 0;

31    end

32  end

33 endmodule 

 

测试模块

0 `timescale 1ns/1ps

1 

2 module rom_seg_tb;

3 

4  reg clk;

5  reg rst_n;

6  reg key;

7 

8  wire [2:0] sel;

9  wire [7:0] seg_n;

10

11 initial begin

12   clk = 0;

13   rst_n = 0;

14   key = 1;

15

16   #200.1 rst_n=1;

17   #200 

18   forever

19    begin

20     #50 key = 1;  //模拟按键

21     #50 key = 0;

22    end

23   end

24   

25 always #10 clk = ~clk;

26

27 rom_seg rom_seg_dut(   //例化顶层模块

28   .clk(clk),

29   .rst_n(rst_n),

30   .key(key),

31   .sel(sel),

32   .seg_n(seg_n)

33  );

34

35 endmodule

 

仿真图:

image.png

在设计我们可以看到我们读出了第一个数,然后下面的数我们可以调整我们的计数单元来通过显示。

数码管模块我们可以用我们以前的 或者下面的:

 

0  module seg(clk,rst_n,sel,seg7,data_in); //端口定义

1  

2   input clk;

3   input rst_n;

4   input [23:0] data_in;   //输入6个灯的数据

5  

6   output reg [2:0] sel;  

7   output reg [7:0] seg7;

8  

9   parameter s0 = 3'b000;

10  parameter s1 = 3'b001;

11  parameter s2 = 3'b010;

12  parameter s3 = 3'b011;

13  parameter s4 = 3'b100;

14  parameter s5 = 3'b101;

15 

16  //`define T1ms  50_000  //定义1k的计数值

17  `define T1ms  5

18  reg [15:0] count;

19  wire flag;

20  always @ (posedge clk or negedge rst_n)

21   if(!rst_n)

22    begin

23     count <= 15'b0;

24    end

25   else

26    if(count == `T1ms - 1)  //计数到1MS

27     begin

28      count <= 15'b0;

29     end

30    else

31     begin

32      count <= count + 1'b1;

33     end

34 

35  assign flag =(count == `T1ms  - 1) ? 1'b1 : 1'b0; //标志位赋值

36 

37  reg [2:0] state; 

38  reg [3:0] num;

39  always @ (posedge clk or negedge rst_n)

40   if(!rst_n)

41    begin

42     sel <= 3'b0;

43     state <= 3'b0;

44     num <= 4'b0;

45    end

46   else

47    begin

48     case (state)

49      s0:begin

50        if(flag)

51         state <= s1;   //亮第一个灯,给24位数据的 4

52        else

53         begin

54          sel <= 3'b000;

55          num <= data_in[23:20];

56         end

57       end

58      s1:begin

59        if(flag)   ////亮第2个灯,给24位数据 4

60         state <= s2;

61        else

62         begin

63          sel <= 3'b001;

64          num <= data_in[19:16];

65         end

66       end

67      s2:begin

68        if(flag)   //亮第3个灯,给24位数据的 4

69         state <= s3;

70        else

71         begin

72          sel <= 3'b010;

73          num <= data_in[15:12];

74         end

75       end

76      s3:begin

77        if(flag) //亮第4个灯,给24位数据的4

78         state <= s4;

79        else

80         begin

81          sel <= 3'b011;

82          num <= data_in[11:8];

83         end

84       end

85      s4:begin

86        if(flag)  //亮第5个灯,给24位数据的4

87         state <= s5;

88        else

89         begin

90          sel <= 3'b100;

91          num <= data_in[7:4];

92         end

93       end

94      s5:begin

95        if(flag)  //亮第6个灯,给24位数据的4

96         state <= s0;

97        else

98         begin

99          sel <= 3'b101;

100         num <= data_in[3:0];

101        end

102      end

103     default:state <= s0;

104    endcase

105   end

106

107 always @ (*)   //数码管的译码模块

108   begin

109    case (num)

110     0:seg7 = 8'b1100_0000;

111     1:seg7 = 8'b1111_1001;

112     2:seg7 = 8'b1010_0100;

113     3:seg7 = 8'b1011_0000;

114     4:seg7 = 8'b1001_1001;

115     5:seg7 = 8'b1001_0010;

116     6:seg7 = 8'b1000_0010;

117     7:seg7 = 8'b1111_1000;

118     8:seg7 = 8'b1000_0000;

119     9:seg7 = 8'b1001_0000;

120     10:seg7 = 8'b1000_1000;

121     11:seg7 = 8'b1000_0011;

122     12:seg7 = 8'b1100_0110;

123     13:seg7 = 8'b1010_0001;

124     14:seg7 = 8'b1000_0110;

125     15:seg7 = 8'b1000_1110;

126     default:;

127    endcase

128   end

129 endmodule 


 

收藏

相关话题
文章来源专栏

评论(0)

加载更多评论

参与评论

相关文章

分享到

QQ空间 QQ好友 微博
取消