012 HDLBits

Posted SilentLittleCat

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了012 HDLBits相关的知识,希望对你有一定的参考价值。

大部分还是挺简单的哈,后面的一些题挺难的

256-to-1 4-bit multiplexer

https://hdlbits.01xz.net/wiki/Mux256to1v

256选1复用器

module top_module( 
    input [1023:0] in,
    input [7:0] sel,
    output [3:0] out );

错误答案

module top_module( 
    input [1023:0] in,
    input [7:0] sel,
    output [3:0] out );
    // 最开始想这样写,报错,因为两个范围都是变量,解释器没有那么智能
    assign out = in[sel * 4 + 3 : sel * 4];
endmodule

正确

module top_module (
	input [1023:0] in,
	input [7:0] sel,
	output [3:0] out
);

	// We can't part-select multiple bits without an error, but we can select one bit at a time,
	// four times, then concatenate them together.
	assign out = in[sel*4+3], in[sel*4+2], in[sel*4+1], in[sel*4+0];

	// 也可用"indexed vector part select",后面那个数必须是常数
	// assign out = in[sel*4 +: 4];	
	// assign out = in[sel*4+3 -: 4];

endmodule

Signed addition overflow

https://hdlbits.01xz.net/wiki/Exams/ece241_2014_q1c

a,b为补码表示,s为a+b的和,overflow表示符号位是否进位

module top_module (
    input [7:0] a,
    input [7:0] b,
    output [7:0] s,
    output overflow
); 

overflow发生在两个负数相加产生正数,或者两个正数相加产生负数的时候

module top_module (
    input [7:0] a,
    input [7:0] b,
    output [7:0] s,
    output overflow
); //
 
    assign s = a + b;
    assign overflow = (s[7] && (~a[7]) && (~b[7])) || (~s[7] && (a[7] && b[7]));

endmodule

还有一种思路是捕获n-1到n的进位

Edge capture register

https://hdlbits.01xz.net/wiki/Edgecapture

这道题我觉得自己解的还可以哈,没有写子模块

module top_module (
    input clk,
    input reset,
    input [31:0] in,
    output [31:0] out
);
    
    reg[31:0] d1, d2, out_tmp2;
    
    assign out = out_tmp2;
    always@(posedge clk) begin
    	d1 <= in;
    end
    
    wire[31:0] out_tmp;
    
    assign out_tmp = d1 & (~in);
    
    always@(posedge clk) begin
        if(reset) out_tmp2 <= 32'd0;
        else out_tmp2 <= out_tmp2 | out_tmp;
    end
endmodule

Dual-edge triggered flip-flop

https://hdlbits.01xz.net/wiki/Dualedge

双边沿触发,感觉挺简单哈

module top_module (
    input clk,
    input d,
    output q
);
    always@(posedge clk or negedge clk) begin
    	q <= d;
    end
endmodule

但是posedge clk or negedge clk是不合法的敏感触发!!!
然后想捕获上边沿下边沿,搞了半天也没搞定
hint说这不是code问题,而是circuit问题,本想暴力搞定,然后看看答案,但搞了半天没搞定,去吃了个饭,双边沿触发就是每半个周期就把d传给q,所以这样解决

module top_module (
    input clk,
    input d,
    output q
);
	reg d1, d2;
    always@(posedge clk) begin
    	d1 <= d; q <= d2;
    end
    always@(negedge clk) begin
    	d2 <= d; q <= d1;
    end 
endmodule

意料之中的multi driver,多驱动
简单改下

module top_module (
    input clk,
    input d,
    output q
);
	reg d1, d2;
    always@(posedge clk) begin
    	d1 <= d;
    end
    always@(negedge clk) begin
    	d2 <= d;
    end
    
    assign q = clk ? d1 : d2;
endmodule

搞定,看下答案是这样写的,厉害了

module top_module(
	input clk,
	input d,
	output q);
	
	reg p, n;
	
	// A positive-edge triggered flip-flop
    always @(posedge clk)
        p <= d ^ n;
        
    // A negative-edge triggered flip-flop
    always @(negedge clk)
        n <= d ^ p;
    
    // Why does this work? 
    // After posedge clk, p changes to d^n. Thus q = (p^n) = (d^n^n) = d.
    // After negedge clk, n changes to p^n. Thus q = (p^n) = (p^p^n) = d.
    // At each (positive or negative) clock edge, p and n FFs alternately
    // load a value that will cancel out the other and cause the new value of d to remain.
    assign q = p ^ n;
    
    
	// Can't synthesize this.
	/*always @(posedge clk, negedge clk) begin
		q <= d;
	end*/
endmodule

Conway’s Game of Life 16 * 16

https://hdlbits.01xz.net/wiki/Conwaylife

用c写其实很简单,但是翻译成Verilog稍微有点麻烦

module top_module(
    input clk,
    input load,
    input [255:0] data,
    output [255:0] q ); 
    
    int tmp[255:0];
    reg val;

    always@(posedge clk) begin
        if(load) q <= data;
        else begin
            for(int i = 0; i < 256; i = i + 1) begin
                tmp[i] = 0;
                for(int j = -1; j < 2; j = j + 1) begin
                    for(int k = -1; k < 2; k = k + 1) begin
                        if(!(j == 0 && k == 0)) begin
                            if(get_val(q, i, j, k))
                                tmp[i] = tmp[i] + 1;
                        end
                    end
                end
                case(tmp[i])
                    0, 1: q[i] <= 1'b0;
                    2: q[i] <= q[i];
                    3: q[i] <= 1'b1;
                    default: q[i] <= 1'b0;
                endcase
            end
        end
    end
    
    function get_val(input[255:0] q, int i, int j, int k);
        int row, col, nrow, ncol;
        
        begin
            row = i >> 4;
            col = i % 16;
            nrow = (row + j + 16) % 16;
            ncol = (col + k + 16) % 16;
            get_val = q[nrow * 16 + ncol];
        end
    endfunction
endmodule
    

Design a Moore FSM

https://hdlbits.01xz.net/wiki/Exams/ece241_2013_q4

上答案吧,我写的有点乱

module top_module (
	input clk,
	input reset,
	input [3:1] s,
	output reg fr3,
	output reg fr2,
	output reg fr1,
	output reg dfr
);


	// Give state names and assignments. I'm lazy, so I like to use decimal numbers.
	// It doesn't really matter what assignment is used, as long as they're unique.
	// We have 6 states here.
	parameter A2=0, B1=1, B2=2, C1=3, C2=4, D1=5;
	reg [2:0] state, next;		// Make sure these are big enough to hold the state encodings.
	


    // Edge-triggered always block (DFFs) for state flip-flops. Synchronous reset.	
	always @(posedge clk) begin
		if (reset) state <= A2;
		else state <= next;
	end



    // Combinational always block for state transition logic. Given the current state and inputs,
    // what should be next state be?
    // Combinational always block: Use blocking assignments.    
	always@(*) begin
		case (state)
			A2: next = s[1] ? B1 : A2;
			B1: next = s[2] ? C1 : (s[1] ? B1 : A2);
			B2: next = s[2] ? C1 : (s[1] ? B2 : A2);
			C1: next = s[3] ? D1 : (s[2] ? C1 : B2);
			C2: next = s[3] ? D1 : (s[2] ? C2 : B2);
			D1: next = s[3] ? D1 : C2;
			default: next = 'x;
		endcase
	end
	
	
	
	// Combinational output logic. In this problem, a procedural block (combinational always block) 
	// is more convenient. Be careful not to create a latch.
	always@(*) begin
		case (state)
			A2: fr3, fr2, fr1, dfr = 4'b1111;
			B1: fr3, fr2, fr1, dfr = 4'b0110;
			B2: fr3, fr2, fr1, dfr = 4'b0111;
			C1: fr3, fr2, fr1, dfr = 4'b0010;
			C2: fr3, fr2, fr1, dfr = 4'b0011;
			D1: fr3, fr2, fr1, dfr = 4'b0000;
			default: fr3, fr2, fr1, dfr = 'x;
		endcase
	end
	
endmodule

One-hot FSM

https://hdlbits.01xz.net/wiki/Fsm_onehot

使用one-hot编码实现下面的状态机

本来想的是

localparam S0 = 10'b00_0000_0001;
localparam S1 = 10'b00_0000_0010;
...
localparam S9 = 10'b10_0000_0000;

always@(*) begin
	case(state)
		S0: next_state = in ? S1 : state;
		....
	endcase
end

The testbench will test with non-one hot inputs to make sure you’re not trying to do something more complicated

但是测试数据里state可能不是one-hot,也就是说我们写复杂了

Suppose this state machine uses one-hot encoding, where state[0] through state[9] correspond to the states S0 though S9

也就说state[0] -> S0,state[9] -> S9,所以是每一位代表一个状态,而不是10位代表一个状态

module top_module(
    input in,
    input [9:0] state,
    output [9:0] next_state,
    output out1,
    output out2);

    assign next_state = in ? 2'b0, state[7] || state[6], state[5:1], state[9] || state[8] || state[0], 1'b0
        : state[6], state[5], 1'b0, 6'd0, (|state[4:0]) || (|state[9:7]);
    assign out1 = state[8] || state[9];
    assign out2 = state[7] || state[9];
endmodule

Sequential circuit 10

https://hdlbits.01xz.net/wiki/Sim/circuit10

想了很久,暴力解决了

module top_module (
    input clk,
    input a,
    input b,
    output q,
    output state  );

    reg a_last, b_last;
    always@(posedge clk) begin
        a_last <= a; b_last <= b;
    end
    
    always@(*) begin
        case(a_last, b_last, a, b)
            4'b0000, 4'b0011, 4'b1011, 4'b1000: begin
            	q = 1'b0; state = 1'b0;
            end
            4'b0001, 4'b0110, 4'b0010: begin
            	q = 1'b1; state = 1'b0;
            end
            4'b1100, 4'b1111, 4'b0100: begin
            	q = 1'b1; state = 1'b1;
            end
            4'b1110, 4'b1001: begin
            	q = 1'b0; state = 1'b1;
            end
        endcase
    end
    
endmodule

178道题搞定

以上是关于012 HDLBits的主要内容,如果未能解决你的问题,请参考以下文章

HDLBits——Getting Started & Basics

HDLBits——Vectors

HDLBits——Modules

HDLBits——Procedures

HDLBits——Basic Gates

HDLBits——More Verilog Features