verilog实现b码解码
时序图和状态转换图
代码
b_decoder.v
module b_decoder (
input wire clk,
input wire rst_n,
input wire irig_b,
output wire [6:0]second_out,
output wire [6:0]minute_out,
output wire [6:0]hour_out,
output wire [9:0]day_out,
output wire [7:0]year_out
);
parameter MAX_8MS = 999_999;
parameter MAX_5MS = 624_999;
parameter MAX_2MS = 249_999;
parameter MAX_1S = 99;
parameter IDLE = 4'b0000;
parameter P = 4'b0001;
parameter SEC = 4'b0011;
parameter MIN = 4'b0010;
parameter HOUR = 4'b0110;
parameter DAY1 = 4'b0111;
parameter DAY2 = 4'b0101;
parameter YEAR = 4'b0100;
parameter S0 = 4'b1100;
parameter S1 = 4'b1101;
parameter S2 = 4'b1111;
parameter S3 = 4'b1110;
reg irig_b_r1;
reg [19:0]cnt_pos;
reg [1:0]decode;
reg [3:0]state;
reg [6:0]cnt_1s;
reg [6:0]second;
reg [6:0]minute;
reg [5:0]hour;
reg [9:0]day;
reg [7:0]year;
//下降沿和上升沿判断
//延迟一拍的输入波形
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
irig_b_r1 <= 1'b0;
end
else begin
irig_b_r1 <= irig_b;
end
end
assign edge_pos = irig_b & ~irig_b_r1;//上升沿
assign edge_neg = ~irig_b & irig_b_r1;//下降沿
//b码高电平计数
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
cnt_pos <= 20'd0;
end
else if (edge_pos) begin
cnt_pos <= 20'd1;
end
else if (irig_b) begin
cnt_pos <= cnt_pos +20'b1;
end
else begin
cnt_pos <= cnt_pos;
end
end
//下降沿判断,波形编码
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
decode <= 2'b00;
end
else if (cnt_pos == MAX_8MS + 1 && edge_neg) begin
decode <= 2'b11;
end
else if (cnt_pos == MAX_5MS + 1 && edge_neg) begin
decode <= 2'b01;
end
else if (cnt_pos == MAX_2MS + 1 && edge_neg) begin
decode <= 2'b00;
end
end
//状态机
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
state <= IDLE;
end
else case (state)
IDLE : begin
if (decode == 2'b11 && edge_pos) begin
state <= P;
end
else begin
state <= state;
end
end
P : begin
if (decode == 2'b11 && edge_pos) begin
state <= SEC;
end
else if ((decode == 2'b00 && edge_pos)||(decode == 2'b00 && edge_pos)) begin
state <= IDLE;
end
else begin
state <= state;
end
end
SEC : begin
if (decode == 2'b11 && edge_pos) begin
state <= MIN;
end
else begin
state <= state;
end
end
MIN : begin
if (decode == 2'b11 && edge_pos) begin
state <= HOUR;
end
else begin
state <= state;
end
end
HOUR : begin
if (decode == 2'b11 && edge_pos) begin
state <= DAY1;
end
else begin
state <= state;
end
end
DAY1 : begin
if (decode == 2'b11 && edge_pos) begin
state <= DAY2;
end
else begin
state <= state;
end
end
DAY2 : begin
if (decode == 2'b11 && edge_pos) begin
state <= YEAR;
end
else begin
state <= state;
end
end
YEAR : begin
if (decode == 2'b11 && edge_pos) begin
state <= S0;
end
else begin
state <= state;
end
end
S0 : begin
if (decode == 2'b11 && edge_pos) begin
state <= S1;
end
else begin
state <= state;
end
end
S1 : begin
if (decode == 2'b11 && edge_pos) begin
state <= S2;
end
else begin
state <= state;
end
end
S2 : begin
if (decode == 2'b11 && edge_pos) begin
state <= S3;
end
else begin
state <= state;
end
end
S3 : begin
if (decode == 2'b11 && edge_pos) begin
state <= P;
end
else begin
state <= state;
end
end
default: state <= state;
endcase
end
// 根据状态机控制cnt_1s计数
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
cnt_1s <= 7'd0;
end
else if (cnt_1s == MAX_1S && edge_pos) begin
cnt_1s <= 7'd0;
end
else if (state == P && edge_pos) begin
cnt_1s <= 7'd1;
end
else if (edge_pos) begin
cnt_1s <= cnt_1s + 7'd1;
end
else begin
cnt_1s <= cnt_1s;
end
end
//赋值
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
second <= 7'b0;
end
else if (cnt_1s == 8'd1) begin
second[0] <= decode[0];
end
else if (cnt_1s == 8'd2) begin
second[1] <= decode[0];
end
else if (cnt_1s == 8'd3) begin
second[2] <= decode[0];
end
else if (cnt_1s == 8'd4) begin
second[3] <= decode[0];
end
else if (cnt_1s == 8'd6) begin
second[4] <= decode[0];
end
else if (cnt_1s == 8'd7) begin
second[5] <= decode[0];
end
else if (cnt_1s == 8'd8) begin
second[6] <= decode[0];
end
else begin
second <= second;
end
end
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
minute <= 7'b0;
end
else if (cnt_1s == 8'd10) begin
minute[0] <= decode[0];
end
else if (cnt_1s == 8'd111) begin
minute[1] <= decode[0];
end
else if (cnt_1s == 8'd12) begin
minute[2] <=decode[0];
end
else if (cnt_1s == 8'd13) begin
minute[3] <= decode[0];
end
else if (cnt_1s == 8'd15) begin
minute[4] <= decode[0];
end
else if (cnt_1s == 8'd16) begin
minute[5] <= decode[0];
end
else if (cnt_1s == 8'd17) begin
minute[6] <= decode[0];
end
else begin
minute <= minute;
end
end
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
hour <= 6'b0;
end
else if (cnt_1s == 8'd20) begin
hour[0] <= decode[0];
end
else if (cnt_1s == 8'd21) begin
hour[1] <= decode[0];
end
else if (cnt_1s == 8'd22) begin
hour[2] <= decode[0];
end
else if (cnt_1s == 8'd23) begin
hour[3] <= decode[0];
end
else if (cnt_1s == 8'd25) begin
hour[4] <= decode[0];
end
else if (cnt_1s == 8'd26) begin
hour[5] <= decode[0];
end
else begin
hour <= hour;
end
end
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
day <= 10'b0;
end
else if (cnt_1s == 8'd30) begin
day[0] <= decode[0];
end
else if (cnt_1s == 8'd31) begin
day[1] <= decode[0];
end
else if (cnt_1s == 8'd32) begin
day[2] <= decode[0];
end
else if (cnt_1s == 8'd33) begin
day[3] <= decode[0];
end
else if (cnt_1s == 8'd35) begin
day[4] <= decode[0];
end
else if (cnt_1s == 8'd36) begin
day[5] <= decode[0];
end
else if (cnt_1s == 8'd37) begin
day[6] <= decode[0];
end
else if (cnt_1s == 8'd38) begin
day[7] <= decode[0];
end
else if (cnt_1s == 8'd40) begin
day[8] <= decode[0];
end
else if (cnt_1s == 8'd41) begin
day[9] <= decode[0];
end
else begin
day <= day;
end
end
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
year <= 6'b0;
end
else if (cnt_1s == 8'd50) begin
year[0] <= decode[0];
end
else if (cnt_1s == 8'd51) begin
year[1] <= decode[0];
end
else if (cnt_1s == 8'd52) begin
year[2] <= decode[0];
end
else if (cnt_1s == 8'd53) begin
year[3] <= decode[0];
end
else if (cnt_1s == 8'd55) begin
year[4] <= decode[0];
end
else if (cnt_1s == 8'd56) begin
year[5] <= decode[0];
end
else if (cnt_1s == 8'd57) begin
year[6] <= decode[0];
end
else if (cnt_1s == 8'd58) begin
year[7] <= decode[0];
end
else begin
year <= year;
end
end
assign second_out = second[6:4]*10 + second[3:0];
assign minute_out = minute[6:4]*10 + minute[3:0];
assign hour_out = hour[5:4]*10 + hour[3:0];
assign day_out = day[9:8]*100 + day[7:4]*10 + day[3:0];
assign year_out = year[7:4]*10 + year[3:0];
endmodule
tb文件
`timescale 1ns/1ps
module b_decoder_tb ();
reg clk;
reg rst_n;
reg irig_b;
wire [6:0]second_out;
wire [6:0]minute_out;
wire [6:0]hour_out;
wire [9:0]day_out;
wire [7:0]year_out;
initial begin
rst_n = 1'b0;
clk = 1'b0;
#2
rst_n = 1'b1;
end
always #4 clk = ~clk;
wire [7:0]mem[1:100];
assign mem[1] = 8'h70; P
assign mem[2] = 8'h30; 0
assign mem[3] = 8'h30; 0
assign mem[4] = 8'h30; 0
assign mem[5] = 8'h31; 1
assign mem[6] = 8'h30; 0
assign mem[7] = 8'h30; 0
assign mem[8] = 8'h30; 0
assign mem[9] = 8'h30; 0
assign mem[10] = 8'h70; P
assign mem[11] = 8'h30; 0
assign mem[12] = 8'h30; 0
assign mem[13] = 8'h30; 0
assign mem[14] = 8'h31; 1
assign mem[15] = 8'h30; 0
assign mem[16] = 8'h30; 0
assign mem[17] = 8'h30; 0
assign mem[18] = 8'h31; 1
assign mem[19] = 8'h30; 0
assign mem[20] = 8'h70; P
assign mem[21] = 8'h31; 1
assign mem[22] = 8'h30; 0
assign mem[23] = 8'h30; 0
assign mem[24] = 8'h30; 0
assign mem[25] = 8'h30; 0
assign mem[26] = 8'h30; 0
assign mem[27] = 8'h30; 0
assign mem[28] = 8'h30; 0
assign mem[29] = 8'h30; 0
assign mem[30] = 8'h70; P
assign mem[31] = 8'h31; 1
assign mem[32] = 8'h30; 0
assign mem[33] = 8'h30; 0
assign mem[34] = 8'h30; 0
assign mem[35] = 8'h30; 0
assign mem[36] = 8'h31; 1
assign mem[37] = 8'h30; 0
assign mem[38] = 8'h31; 1
assign mem[39] = 8'h30; 0
assign mem[40] = 8'h70; P
assign mem[41] = 8'h30; 0
assign mem[42] = 8'h31; 1
assign mem[43] = 8'h30; 0
assign mem[44] = 8'h30; 0
assign mem[45] = 8'h30; 0
assign mem[46] = 8'h30; 0
assign mem[47] = 8'h30; 0
assign mem[48] = 8'h30; 0
assign mem[49] = 8'h30; 0
assign mem[50] = 8'h70; P
assign mem[51] = 8'h31; 1
assign mem[52] = 8'h30; 0
assign mem[53] = 8'h30; 0
assign mem[54] = 8'h30; 0
assign mem[55] = 8'h30; 0
assign mem[56] = 8'h30; 0
assign mem[57] = 8'h31; 1
assign mem[58] = 8'h30; 0
assign mem[59] = 8'h30; 0
assign mem[60] = 8'h70; P
assign mem[61] = 8'h30; 0
assign mem[62] = 8'h30; 0
assign mem[63] = 8'h30; 0
assign mem[64] = 8'h30; 0
assign mem[65] = 8'h30; 0
assign mem[66] = 8'h30; 0
assign mem[67] = 8'h30; 0
assign mem[68] = 8'h30; 0
assign mem[69] = 8'h30; 0
assign mem[70] = 8'h70; P
assign mem[71] = 8'h30; 0
assign mem[72] = 8'h30; 0
assign mem[73] = 8'h30; 0
assign mem[74] = 8'h30; 0
assign mem[75] = 8'h30; 0
assign mem[76] = 8'h31; 1
assign mem[77] = 8'h30; 0
assign mem[78] = 8'h30; 0
assign mem[79] = 8'h30; 0
assign mem[80] = 8'h70; P
assign mem[81] = 8'h30; 0
assign mem[82] = 8'h30; 0
assign mem[83] = 8'h30; 0
assign mem[84] = 8'h31; 1
assign mem[85] = 8'h31; 1
assign mem[86] = 8'h30; 0
assign mem[87] = 8'h31; 1
assign mem[88] = 8'h30; 0
assign mem[89] = 8'h31; 1
assign mem[90] = 8'h70; P
assign mem[91] = 8'h30; 0
assign mem[92] = 8'h30; 0
assign mem[93] = 8'h31; 1
assign mem[94] = 8'h31; 1
assign mem[95] = 8'h30; 0
assign mem[96] = 8'h30; 0
assign mem[97] = 8'h30; 0
assign mem[98] = 8'h30; 0
assign mem[99] = 8'h30; 0
assign mem[100] = 8'h70; P
reg [6:0]cnt_1s;
reg [20:0]cnt_10ms;
reg [2:0]state;
parameter IDLE = 3'd0;
parameter S0 = 3'd1;
parameter S1 = 3'd2;
parameter S2 = 3'd3;
parameter S3 = 3'd4;
parameter MAX_10MS = 1249999;
parameter MAX_8MS = 999_999;
parameter MAX_5MS = 624_999;
parameter MAX_2MS = 249_999;
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
state <= IDLE;
cnt_10ms <= 21'd0;
cnt_1s <= 7'd1;
end
else case (state)
IDLE : begin
if (mem[cnt_1s] == 8'h70) begin
state <= S0;
cnt_10ms <= 21'd0;
end
else if (mem[cnt_1s] == 8'h31) begin
state <= S1;
cnt_10ms <= 21'd0;
end
else if (mem[cnt_1s] == 8'h30) begin
state <= S2;
cnt_10ms <= 21'd0;
end
end
S0: begin
if (cnt_10ms == MAX_10MS - 2) begin
state <= S3;
cnt_10ms <= 21'd0;
end
else begin
cnt_10ms <= cnt_10ms + 21'd1;
end
if(cnt_10ms <= MAX_8MS)begin
irig_b <= 1'b1;
end
else begin
irig_b <= 1'b0;
end
end
S1: begin
if (cnt_10ms == MAX_10MS - 2) begin
state <= S3;
cnt_10ms <= 21'd0;
end
else begin
cnt_10ms <= cnt_10ms + 21'd1;
end
if(cnt_10ms <= MAX_5MS)begin
irig_b <= 1'b1;
end
else begin
irig_b <= 1'b0;
end
end
S2: begin
if (cnt_10ms == MAX_10MS - 2) begin
state <= S3;
cnt_10ms <= 21'd0;
end
else begin
cnt_10ms <= cnt_10ms + 21'd1;
end
if(cnt_10ms <= MAX_2MS)begin
irig_b <= 1'b1;
end
else begin
irig_b <= 1'b0;
end
end
S3 : begin
state <= IDLE;
if (cnt_1s == 7'd100) begin
cnt_1s <= 7'd1;
end
else begin
cnt_1s <= cnt_1s + 7'd1;
end
end
endcase
end
b_decoder b_decoder_1 (
.clk(clk),
.rst_n(rst_n),
.irig_b(irig_b),
.second_out(second_out),
.minute_out(minute_out),
.hour_out(hour_out),
.day_out(day_out),
.year_out(year_out)
);
endmodule
这个tb文件本质上是一个编码器。
仿真
连续两个p开始计数
cnt_1s为68时,年的数据识别完成。