8421BCD编码介绍:8421bcd码是最常用的BCD码,是十进制代码中最常用的一种。8421码适合于计算机处理。
运用介绍:8421BCD码中的“8421”表示从高到低各位二进制位对应的权值分别为8、4、2、1,将各二进制位与权值相乘,并将乘积相加就得相应的十进制数。
例如,8421BCD码“0111”,0×8+1×4+1×2+1×1=7D,其中D表示十进制
编码示意图:
模块框图:
bcd_8421模块代码(该代码参考了野火的8421bcd编码)
链接:数码管的动态显示 — [野火]FPGA Verilog开发实战指南——基于Altera EP4CE10 征途Mini开发板 文档 (embedfire.com)
module bcd_8421
(
input wire clk_50Mhz, //系统时钟50Mhz
input wire rst_n, //全局复位
input wire [26:0] data, //待编码数据
output wire [31:0] bcd_data //编码后的数据
);
//parameter define
parameter CNT_SHIFT_NUM = 7'd27; // 由data的位宽决定
//reg define
reg [6:0] cnt_shift; // 移位判断计数器
reg [58:0] data_shift; // 移位判断数据寄存器,
reg shift_flag; // 移位判断标志信号
reg [3:0] unit ; // 个位BCD码
reg [3:0] ten ; // 十位BCD码
reg [3:0] hun ; // 百位BCD码
reg [3:0] tho ; // 千位BCD码
reg [3:0] t_tho ; // 万位BCD码
reg [3:0] h_hun ; // 十万位BCD码
reg [3:0] hundred_tho ; // 百万位BCD码
reg [3:0] million ; // 千万位BCD码
assign bcd_data = {million,hundred_tho,h_hun,t_tho,tho,hun,ten,unit};
//cnt_shift计数
always @(posedge clk_50Mhz or negedge rst_n) begin
if (rst_n==1'b0) begin
cnt_shift <= 7'd0;
end
else if ((cnt_shift == CNT_SHIFT_NUM + 1) && (shift_flag)) begin
cnt_shift <= 7'd0;
end
else if (shift_flag) begin
cnt_shift <= cnt_shift + 1'b1;
end
else begin
cnt_shift <= cnt_shift;
end
end
//data_shift 计数器为0时赋初值,计数器为1~CNT_SHIFT_NUM时进行移位操作
always @(posedge clk_50Mhz or negedge rst_n) begin
if (rst_n==1'b0) begin
data_shift <= 59'd0;
end
else if (cnt_shift == 7'd0) begin
data_shift <= {32'b0, data};
end
else if ((cnt_shift <= CNT_SHIFT_NUM) && (!shift_flag)) begin
data_shift[30:27] <= (data_shift[30:27] > 4) ? (data_shift[30:27] + 4'b0011) : (data_shift[30:27]);
data_shift[34:31] <= (data_shift[34:31] > 4) ? (data_shift[34:31] + 4'b0011) : (data_shift[34:31]);
data_shift[38:35] <= (data_shift[38:35] > 4) ? (data_shift[38:35] + 4'b0011) : (data_shift[38:35]);
data_shift[42:39] <= (data_shift[42:39] > 4) ? (data_shift[42:39] + 4'b0011) : (data_shift[42:39]);
data_shift[46:43] <= (data_shift[46:43] > 4) ? (data_shift[46:43] + 4'b0011) : (data_shift[46:43]);
data_shift[50:47] <= (data_shift[50:47] > 4) ? (data_shift[50:47] + 4'b0011) : (data_shift[50:47]);
data_shift[54:51] <= (data_shift[54:51] > 4) ? (data_shift[54:51] + 4'b0011) : (data_shift[54:51]);
data_shift[58:55] <= (data_shift[58:55] > 4) ? (data_shift[58:55] + 4'b0011) : (data_shift[58:55]);
end
else if ((cnt_shift <= CNT_SHIFT_NUM) && (shift_flag)) begin
data_shift <= data_shift << 1;
end
else begin
data_shift <= data_shift;
end
end
//shift_flag 移位判断标志信号,用于控制移位判断的先后顺序
always @(posedge clk_50Mhz or negedge rst_n) begin
if (rst_n==1'b0) begin
shift_flag <= 1'b0;
end
else begin
shift_flag <= ~shift_flag;
end
end
// 当计数器等于26时,移位判断操作完成,对各个位数的BCD码进行赋值
always @(posedge clk_50Mhz or negedge rst_n) begin
if (rst_n == 1'b0) begin
unit <= 4'b0;
ten <= 4'b0;
hun <= 4'b0;
tho <= 4'b0;
t_tho <= 4'b0;
h_hun <= 4'b0;
hundred_tho <= 4'b0;
million <= 4'b0;
end
else if (cnt_shift == CNT_SHIFT_NUM + 1) begin
unit <= data_shift[30:27];
ten <= data_shift[34:31];
hun <= data_shift[38:35];
tho <= data_shift[42:39];
t_tho <= data_shift[46:43];
h_hun <= data_shift[50:47];
hundred_tho <= data_shift[54:51];
million <= data_shift[58:55];
end
end
endmodule