有必要仔细阐述这一节,目前就是用在数码管显示,在单片机使用时,我们通常是将十进制数字进行/和%运算,得到每个位置的十进制数字,在这里可能是为了节省使用存储器的量,运用的是加三移位法具体其实就是将每个数字不顾位置,各自转换为二进制形式
例如:
255 变成 0010 _0101_0101 的过程
移位的次数一定是该数字的二进制位数,加三不确定(加三也是要判断每4位的二进制大于4才加三,所以是每次移位以后都要判断)
module bcd_8421(
input wire sys_clk,
input wire sys_rst,
input wire [19:0] data,
output reg [3:0] ge,
output reg [3:0] shi,
output reg [3:0] bai,
output reg [3:0] qian,
output reg [3:0] wan,
output reg [3:0] shi_wan
);
reg [4:0] cnt_shift; //移位判断计数器
reg [43:0] data_shift; //移位判断数据寄存器
reg shift_flag; //移位判断标志信号
always @(posedge sys_clk or negedge sys_rst) //0到21的循环计数(移位加三的方式实现的话,首位各加一个,999_999十进制换算到二进制有20位)
if(!sys_rst )
cnt_shift <= 5'd0;
else if ((cnt_shift==5'd21) && (shift_flag == 1'b1))
cnt_shift <= 5'd0;
else if (shift_flag == 1'b1)
cnt_shift <= cnt_shift + 1'b1;
else
cnt_shift <= cnt_shift;
always @(posedge sys_clk or negedge sys_rst) //移位判断标志信号,控制移位判断的先后顺序
if(!sys_rst )
shift_flag <= 1'b0;
else
shift_flag <= ~shift_flag;
always @(posedge sys_clk or negedge sys_rst) //data_shift有44位,其中高24位是999_999形成的BCD码需要24位,低20位是999_999的二进制形式是20位
if(!sys_rst )
data_shift <=44'b0;
else if (cnt_shift == 5'd0)
data_shift <= {24'b0, data };
else if ((cnt_shift <= 5'd20)&&(shift_flag==1'b0)) //cnt_shift=0时,还是上次的,因为六位数最大变成二进制有20位,所以考虑有20次判断和移位操作,21次稳定,将它输出,
begin
data_shift[23:20] <= (data_shift[23:20]>4) ? (data_shift[23:20]+2'd3) : (data_shift[23:20]);
data_shift[27:24] <= (data_shift[27:24]>4) ? (data_shift[27:24]+2'd3) : (data_shift[27:24]);
data_shift[31:28] <= (data_shift[31:28]>4) ? (data_shift[31:28]+2'd3) : (data_shift[31:28]);
data_shift[35:32] <= (data_shift[35:32]>4) ? (data_shift[35:32]+2'd3) : (data_shift[35:32]);
data_shift[39:36] <= (data_shift[39:36]>4) ? (data_shift[39:36]+2'd3) : (data_shift[39:36]);
data_shift[43:40] <= (data_shift[43:40]>4) ? (data_shift[43:40]+2'd3) : (data_shift[43:40]);
end
else if ((cnt_shift <= 5'd20)&&(shift_flag==1'b1))
data_shift <= data_shift << 1;
else
data_shift <= data_shift;
always @(posedge sys_clk or negedge sys_rst) //当计数器等于20时,对各位置的赋值(BCD)
if(!sys_rst )
begin
ge <= 4'b0;
shi <= 4'b0;
bai <= 4'b0;
qian <= 4'b0;
wan <= 4'b0;
shi_wan <= 4'b0;
end
else if (cnt_shift == 5'd21)
begin
ge <= data_shift[23:20];
shi <= data_shift[27:24];
bai <= data_shift[31:28];
qian <= data_shift[35:32];
wan <= data_shift[39:36];
shi_wan <= data_shift[43:40];
end
else
begin
ge <= ge ;
shi <= shi ;
bai <= bai ;
qian <= qian ;
wan <= wan ;
shi_wan <= shi_wan ;
end
endmodule
module vtf;
// Inputs
reg sys_clk;
reg sys_rst;
reg [19:0] data;
// Outputs
wire [3:0] ge;
wire [3:0] shi;
wire [3:0] bai;
wire [3:0] qian;
wire [3:0] wan;
wire [3:0] shi_wan;
// Instantiate the Unit Under Test (UUT)
bcd_8421 uut (
.sys_clk(sys_clk),
.sys_rst(sys_rst),
.data(data),
.ge(ge),
.shi(shi),
.bai(bai),
.qian(qian),
.wan(wan),
.shi_wan(shi_wan)
);
initial begin
// Initialize Inputs
sys_clk = 0;
sys_rst = 0;
data = 0;
// Wait 100 ns for global reset to finish
#100;
sys_rst <= 1'b1;
data <= 20'd0;
#100000;
data <= 20'd123_456;
#100000;
data <= 20'd999_999;
#100000;
data <= 20'd123_895;
#100000;
data <= 20'd456_789;
#100000;
data <= 20'd999_999;
#100000;
data <= 20'd456_789;
// Add stimulus here
end
always # 10 sys_clk = ~sys_clk;
endmodule