笔试题-1
根据输入信号din_b的值来控制调整输出信号dout_a的值,使能信号有效时,该模块每隔8个周期
读取din_b的值,其中din_b为4bit数据;当读取值小于7时,输出信号dout_a需自加1,当读取值大于11
时,dout_a需自减1,其中dout_a为6bit数据,增加或减少到边界时不能有溢出。画出state machine,并
用RTL描述state machine。----(欢迎讨论)
module t_6( input clk, input rst, input en, input [3:0]din_b, output wire [5:0]dout_a ); parameter s0 = 2'b00;//输入为7-11之间的保持状态 parameter s1 = 2'b01;//输入为0-6之间的加1状态 parameter s2 = 2'b10;//输入为8-15之间的减1状态 reg [3:0]cnt; always @(posedge clk or negedge rst) begin if(!rst) begin cnt <= 'b0; end else if (cnt == 4'd7) begin cnt <= 'b0; end else begin cnt <= cnt + 1'b1; end end //wire din_b_1; reg en_a; //assign din_b_1 = (cnt == 4'd7)?din_b:4'd7; reg [3:0]din_b_1; wire [3:0]din_b_2; always @(posedge clk or negedge rst) begin if(!rst) begin din_b_1 <= 'd7; end else if(cnt == 4'd7)begin din_b_1 <= din_b; end else begin din_b_1 <= 'd7; end end assign din_b_2 = din_b_1; reg [1:0]a; always @(*) begin //使能信号有效时,根据要求对输入数据进行归类,加、不变、减 if((en == 1'b1)&&(~en_a))begin case(din_b_1) 4'd0,4'd1,4'd2,4'd3,4'd4,4'd5,4'd6: a =2'b00; 4'd7,4'd8,4'd9,4'd10,4'd11: a = 2'b01; 4'd12,4'd13,4'd14,4'd15: a = 2'b10; default : a = 2'b01; endcase end else begin a = 'b01; end end reg [1:0]state,nstate;//the first state always @(posedge clk or negedge rst) begin if(!rst) begin state <= s0; end else begin state <= nstate; end end always @(*) begin //the second state nstate = 2'bx; case(state) s0:begin if(a==2'b0) begin nstate = s1; end else if (a == 2'b10) begin nstate = s2; end else begin nstate = s0; end end s1: begin if(a==2'b0) begin nstate = s1; end else if (a==2'b10) begin nstate = s2; end else begin nstate = s0; end end s2: begin if(a==2'b0) begin nstate = s1; end else if(a==2'b10)begin nstate = s2; end else begin nstate = s0; end end default:nstate = s0; endcase end reg [5:0]dout_a_1;//the three state always @(posedge clk or negedge rst) begin if(!rst) begin dout_a_1 <= 6'd7; end else if (en_a == 1'b1) begin dout_a_1 <= 6'd7; end else begin case(nstate) s0: begin dout_a_1 <= dout_a_1; end s1: begin dout_a_1 <= dout_a_1 + 1'b1; end s2: begin dout_a_1 <= dout_a_1 - 1'b1; end default: dout_a_1 <= dout_a_1; endcase end end assign dout_a = dout_a_1; //reg en_a; always @(posedge clk or negedge rst) begin//the boundary check if(!rst) begin en_a <= 1'b0; end else if ((dout_a_1 == 6'd63) || (dout_a_1 == 6'd0)) begin en_a <= 1'b1; end else begin en_a <= 1'b0; end end endmodule
`timescale 1ns/10ps module t_6_tb; reg clk; reg rst; reg en; reg [3:0]din_b; wire [5:0]dout_a; t_6 u1( .clk(clk), .rst(rst), .en(en), .din_b(din_b), .dout_a(dout_a) ); initial begin clk = 'b1; rst = 'b0; en = 'b0; #6; rst = 'b1; en = 'b1; end always #5 clk = ~clk; initial begin #10; repeat(1000) begin din_b = {$random}%16; #10; end end endmodule