二进制码转BCD码的实现可以通过一个特殊的4位移位处理来实现,该实现机制是,判断该移位器中的数字是否大于4,是的话则加3再左移,否则直接左移。可以这样考虑,在BCD码中,如果一个数大于9,则需要减去10然后想前进一位,因而可以通过“加3再左移”来实现,即先调整再移位,这样方便实现。
注:加3左移的由来,BCD码的每4个单位比特是小于等于9的,假设一个4比特单位BCD码将要做左移操作,且移位前大于4,则移位后必定大于9,BCD码的移位操作为16+(2a-10),a为移位前的数,即BCD移位后的结果为2(a+3),否则按正常2进制移位即可
假定输入二进制码为9位,输出为12位。
实现代码
module bin2bcd( input wire clk, nrst, input wire start, input wire [8:0] bin, output reg [11:0] bcd, output reg valid ); reg [8:0] bin_in; reg op; reg [3:0] cnt; always @(posedge clk or negedge nrst) begin if(nrst == 0) bin_in <= 0; else if(start) bin_in <= bin; end always @(posedge clk or negedge nrst) begin if(nrst == 0) op <= 0; else if(start) op <= 1; else if(cnt == 9 - 1) op <= 0; end always @(posedge clk or negedge nrst) begin if(nrst == 0) cnt <= 0; else if(op) cnt <= cnt + 1'b1; else cnt <= 0; end function [3:0] fout(input reg [3:0] fin); fout = (fin > 4) ? fin + 4'd3 : fin; endfunction always @(posedge clk or negedge nrst) begin if(nrst == 0) bcd <= 0; else if(op) begin bcd[0] <= bin_in[8-cnt]; bcd[4:1] <= fout(bcd[3:0]); bcd[8:5] <= fout(bcd[7:4]); bcd[11:9] <= fout(bcd[11:8]); end else bcd <= 0; end always @(posedge clk or negedge nrst) begin if(nrst == 0) valid <= 0; else if(cnt == 9 - 1) valid <= 1; else valid <= 0; end endmodule
测试平台代码
`timescale 1ns/10ps module bin2bcd_tb; // parameter localparam T = 20; // declaration reg clk, nrst; reg [8:0] bin; reg start; wire [11:0] bcd; wire valid; // instantiation bin2bcd uut( .clk (clk ), .nrst (nrst ), .start (start ), .bin (bin ), .bcd (bcd ), .valid (valid ) ); // clock initial begin clk = 1; forever # (T/2) clk = ~clk; end // reset initial begin nrst = 1; @(negedge clk) nrst = 0; @(negedge clk) nrst = 1; end // test 4 instance initial begin // initiate bin = 0; start = 0; // wait for reset repeat(2) @(negedge clk); // test 0 @(negedge clk) bin = 0; start = 1; @(negedge clk) bin = 0; start = 0; repeat(15) @(negedge clk); // test 0b1001 @(negedge clk) bin = 9'b1001; start = 1; @(negedge clk) bin = 0; start = 0; repeat(15) @(negedge clk); // test 0b1111 @(negedge clk) bin = 9'b1111; start = 1; @(negedge clk) bin = 0; start = 0; repeat(15) @(negedge clk); // test 0b1_0000 @(negedge clk) bin = 9'b1_0000; start = 1; @(negedge clk) bin = 0; start = 0; repeat(15) @(negedge clk); // test 0b1_1111_1111 @(negedge clk) bin = 9'b1_1111_1111; start = 1; @(negedge clk) bin = 0; start = 0; repeat(15) @(negedge clk); // stop $stop; end endmodule
参考图书《基于Nios II的嵌入数SoPC系统设计与Verilog开发实例》