HDLBit 个人记录
文章目录
- HDLBit 个人记录
- Verilog Languages
- More verilog features
- Vectors
- Circuits
- Combinational logic
- Multiplexers
- Sequential logic
- lateches and Flip-Flops
- Counter
- Shift registers
- More circuits
- Finite state machine
HDLBit 个人记录
HDLBit网站上有时候会用system verilog
的语法,和verlog2001
的语法标准有区别。可以注册账号,写的代码就可以保存在云端了。
Verilog Languages
More verilog features
Generate for-loops: 100 BCD adders
: 将第一个addder特殊处理
module top_module( input [399:0] a, b,input cin,output cout,output [399:0] sum );wire[99:0] c;bcd_fadd f(a[3:0], b[3:0], cin, c[0], sum[3:0]);genvar i;generatefor(i=1; i<100; i=i+1) begin: adderbcd_fadd f1(a[(4*i+3):(4*i)], b[(4*i+3):(4*i)], c[i-1], c[i], sum[(4*i+3):(4*i)]);endendgenerateassign cout = c[99];
endmodule
Vectors
- More Replication: 使用复制写法
module top_module (input a, b, c, d, e,output [24:0] out );//// The output is XNOR of two vectors created by // concatenating and replicating the five inputs.// assign out = ~{ ... } ^ { ... };assign out = ~{5{a, b, c, d ,e}} ^ {{5{a}}, {5{b}}, {5{c}}, {5{d}}, {5{e}}};
endmodule
Circuits
Combinational logic
Multiplexers
256-to-1 multiplexer.
:verilog2001
中有part select
语法
module top_module( input [1023:0] in,input [7:0] sel,output [3:0] out );assign out = in[sel*4 +:4];
endmodule
Sequential logic
lateches and Flip-Flops
Dual edge
:这个我没想出来,看了解析,利用了异或的特性x=x^y^y
module top_module (input clk,input d,output q
);reg q1, q2;always @(posedge clk) beginq1 <= d ^ q2;endalways @(negedge clk) beginq2 <= d ^ q1;endassign q = q1 ^ q2;
endmodule
Counter
12-hour clock
:时分秒的判断逻辑,此外reset
和ena
互斥。
module top_module(input clk,input reset,input ena,output pm,output [7:0] hh,output [7:0] mm,output [7:0] ss); always @(posedge clk) beginif(reset) beginpm <= 0;ss <= 0;mm <= 0;hh <= 'h12;endelse if (ena) beginss <= (ss[3:0]==9)? {ss[7:4]+1,4'b0}: ss+1;if(ss=='h59)beginss <= 0;mm <= mm[3:0]==9? {mm[7:4]+1,4'b0}: mm+1;if(mm=='h59) beginmm <= 0;hh <= hh[3:0]==9? {hh[7:4]+1,4'b0}: hh+1;if(hh=='h11) pm <= ~pm;if(hh=='h12) hh <= 'h01;endendendend
endmodule
Shift registers
5bit LFSR
:5比特线性反馈移位器,我将组合逻辑直接放在了always
时序逻辑块里,网站提供了参考答案将这部分组合逻辑剥离到另一个always
组合逻辑块里。
module top_module(input clk,input reset, // Active-high synchronous reset to 5'h1output [4:0] q
); always @(posedge clk) beginif (reset ) q<=5'd1;else beginq <= {q[0], q[4], q[3] ^ q[0], q[2], q[1]};endend
endmodule
shift registers
:使用generate
生成同一种器件。
module top_module (input [3:0] SW,input [3:0] KEY,output [3:0] LEDR
); //wire[3:0] ws;assign ws[3] = KEY[3];assign ws[2] = LEDR[3];assign ws[1] = LEDR[2];assign ws[0] = LEDR[1];genvar i;generatefor(i=0; i<4; i++) begin: mMUXDFF mu(KEY[0], ws[i], SW[i], KEY[1], KEY[2],LEDR[i]);endendgenerate
endmodulemodule MUXDFF (input clk,input w, R, E, L,output Q);always @(posedge clk) beginQ <= L? R : (E? w:Q);end
endmodule
3 input LUT
:Z赋值时需要在always
块外部,才能构造组合逻辑,否则在块内部会综合出寄存器,导致输出延迟一个周期。
module top_module (input clk,input enable,input S,input A, B, C,output Z ); reg[7:0] Q;always @(posedge clk) beginif (enable) Q <= {Q[6:0], S};endassign Z = Q[{A, B, C}];
endmodule
More circuits
Rule90
:按照题目提供的规律,构造异或组合逻辑。
module top_module(input clk,input load,input [511:0] data,output [511:0] q ); always @(posedge clk) beginif(load) q <= data;else q <= {1'b0, q[511:1]} ^ {q[510:0], 1'b0};end
endmodule
Rule110
:观察规律,发现0值的情况仅有3种,用0值写出组合逻辑。
module top_module(input clk,input load,input [511:0] data,output [511:0] q
); wire[511:0] q1, q2;assign q1 = {1'b0, q[511:1]};assign q2 = {q[510:0], 1'b0};always @(posedge clk) beginif(load) q<=data;else beginq <= ~((q1 & q & q2) | ~(q | q2));endend
endmodule
Conway's Game of Life
:利用过程赋值中的阻塞赋值构建组合电路。
module top_module(input clk,input load,input [255:0] data,output [255:0] q ); always @(posedge clk) beginif(load) q <= data;else begininteger i, j;for(i=0; i<16; i=i+1) beginfor(j=0; j< 16; j=j+1) begininteger i1, i2, j1, j2, n;i1 = (i+15)%16;i2 = (i+1)%16;j1 = (j+15)%16;j2 = (j+1)%16;n = q[i1*16+j1] + q[i1*16+j] + q[i1*16+j2] + q[i2*16+j1] + q[i2*16+j] + q[i2*16+j2] + q[i*16+j1] + q[i*16+j2];case(n)2: q[i*16+j] <= q[i*16+j];3: q[i*16+j] <= 1'b1;default: q[i*16+j] <= 1'b0;endcaseendendendend
endmodule
Finite state machine
Simple FSM1: synchronous reset.
:给的示例程序将组合逻辑混入了时序逻辑块里,极易出错。
// Note the Verilog-1995 module declaration syntax here:
module top_module(clk, reset, in, out);input clk;input reset; // Synchronous reset to state Binput in;output out;// reg out;// Fill in state name declarationsparameter A=0, B=1;reg present_state, next_state;always @(posedge clk) beginif (reset) begin // Fill in reset logicpresent_state <= B;out <= B;end else begincase (present_state)// Fill in state transition logicA: next_state = in? A : B; // 这里不可用<=赋值,会使得赋值出现在present_state = next_state; 之后,B: next_state = in? B : A; // gemini说这种写法极易出现错误,建议使用3段式endcase// State flip-flopspresent_state = next_state; case (present_state)// Fill in output logicA: out <= A;B: out <= B;endcaseendendendmodule
Designing a Moore FSM
:水位状态可以直接从s
由组合逻辑给出,只有dfr
需要记录前序状态,但是debugdfr
花了很久时间,参考了网上的解答才发现要初始化,其实题目最后一句提到了dfr在reset要被赋值,但是被我忽略了。此外,网站给的解答是将中间两个水位结合dfr
组成新的状态,上下两个水位dfr
固定。
module top_module (input clk,input reset,input [3:1] s,output fr3,output fr2,output fr1,output dfr
); parameter OFF=0, ON=1;reg state, next_state;reg[3:1] s_pre;/* 这种组合赋值没有延迟,不符合测例要求assign fr3 = ~s[1];assign fr2 = ~s[2]; assign fr1 = ~s[3];*/always @(*) beginnext_state = s > s_pre? OFF: (s<s_pre? ON: state);endalways @(posedge clk) beginif(reset) beginstate<=ON;s_pre <= 0; //非常重要,这个设定的初值用于判断后续对的dfr初值。{fr1, fr2, fr3} <= {3{1'b1}};endelse begins_pre <= s;state<=next_state;{fr1, fr2, fr3} <= ~s;endendassign dfr = state;
endmodule