从黑金FPGA的文档资料里面摘抄出了会用使用到的东西,便于查阅。

1 数据类型

1.1 常量

整数:二进制(b或B)、八进制(o或O)、十进制(d或D)、十六进制(h或H)。

8’b00001111 //八位二进制

X和Z:X代表不定值、Z代表高阻值。

下划线:在位数过长时,可用来分割,提高程序可读性。

参数 parameter:可用来定义常量。

parameter width = 8; //定义了一个常量为8

localparam:只能用于本模块内使用,不能用于参数传递。

1.2 变量

wire:网络类型变量,必须用assign进行赋值,用来表示实体之间的连接。

Reg:寄存器变量,可用来存储值,必须在always语句中使用。

1.3 Memory类型

定义RAM、ROM等存储器。

reg [7:0] ram [255:0] //定义了256个8位寄存器,256为存储器的深度,8为数据的宽度。

2 运算符

2.1 算术运算符

+ //加
- //减
* //乘
/ //整除
% //取模

2.2 赋值运算符

=  //阻塞(Blocking)赋值,执行完一条赋值语句后立即执行
<= //非阻塞(Nonblocking)赋值,并行执行,不考虑顺序,在always块语句执行完成后,才进行赋值

一般情况下,在时序逻辑电路中使用非阻塞赋值,可避免仿真时出现竞争冒险现象;在组合逻辑中使用阻塞赋值,执行赋值语句后立即改变;在 assign 语句中必须用阻塞赋值

2.3 关系运算符

用于表示两个操作数之间的关系,如 a>b

2.4 逻辑运算符

&& //两个操作数逻辑与
|| //两个操作数逻辑或
!  //单个操作数逻辑非

2.5 条件运算符

?: 用法类似于三目运算符。

assign a = (i>8)?1’b1:1’b0 

2.6 位运算符

~ //按位取反
| //按位或,
^ //按位异或,
& //按位与,
^ //按位同或,

2.7 移位运算符

<< //左移位运算符
>> //右移位运算符

2.8 拼接运算符

{a[3:0], b[1:0]} //将a的低4位,b的低2位拼接成6位数据,类似MATLAB

2.9 优先级别

3 组合逻辑

3.1 与门

module top(a, b, c) ;
input a ;
input b ;
output c ;
assign c = a & b ;
endmodule

3.2 或门

module top(a, b, c) ;
input a ;
input b ;
output c ;
assign c = a | b ;
endmodule

3.3 非门

module top(a, b) ;
input a ;
output b ;
assign b = ~a ;
endmodule

3.4 异或

module top(a, b, c) ;
input a ;
input b ;
output c ;
assign c = a ^ b ;
endmodule

3.5 比较器

module top(a, b, c) ;
input a ;
input b ;
output c ;
assign c = a > b ;
endmodule

3.6 半加器&全加器

module top(a, b, sum, count) ;
input a ;
input b ;
output sum ;
output count ;
assign sum = a ^ b ;
assign count = a & b ;
endmodule
module top(cin, a, b, sum, count) ;
input cin ;
input a ;
input b ;
output sum ;
output count ;
assign {count,sum} = a + b + cin ;
endmodule

3.7 乘法器

module top(a, b, c) ;
input [1:0] a ;
input [1:0] b ;
output [3:0] c ;
assign c = a * b ;
endmodule

3.8 数据选择器

module top(a, b, c, d, sel, Mux) ;
input a ;
input b ;
input c ;
input d ;
input [1:0] sel ;
output reg Mux ;
always @(sel or a or b or c or d)
begin
 case(sel)
 2'b00 : Mux = a ;
 2'b01 : Mux = b ;
 2'b10 : Mux = c ;
 2'b11 : Mux = d ;
 endcase
end
endmodule

3.9 3-8译码器

module top(addr, decoder) ;
input [2:0] addr ;
output reg [7:0] decoder ;
always @(addr)
begin
 case(addr)
 3'b000 : decoder = 8'b1111_1110 ;
 3'b001 : decoder = 8'b1111_1101 ;
 3'b010 : decoder = 8'b1111_1011 ;
 3'b011 : decoder = 8'b1111_0111 ;
 3'b100 : decoder = 8'b1110_1111 ;
 3'b101 : decoder = 8'b1101_1111 ;
 3'b110 : decoder = 8'b1011_1111 ;
 3'b111 : decoder = 8'b0111_1111 ; 
 endcase
end

endmodule

3.10 三态门

module top(en, din, dout, bio) ;
input din ;
input en ;
output dout ;
inout bio ;
assign bio = en? din : 1'bz ;
assign dout = bio ;

endmodule

4 时序逻辑

4.1 D触发器

module top(d, clk, q) ;
input d ;
input clk ;
output reg q ;
always @(posedge clk)
begin
 q <= d ;
end
endmodule

4.2 两级D触发器

module top(d, clk, q, q1) ;
input d ;
input clk ;
output reg q ;
output reg q1 ;
always @(posedge clk)
begin
 q <= d ;
end
always @(posedge clk)
begin
 q1 <= q ;
end
endmodule

4.3 带异步复位的D触发器

module top(d, rst, clk, q) ;
input d ;
input rst ;
input clk ;
output reg q ;
always @(posedge clk or negedge rst)
begin
 if (rst == 1'b0)
 q <= 0 ;
 else
 q <= d ;
end
endmodule

4.4 带异步复位同步清零的 D 触发器

module top(d, rst, clr, clk, q) ;
input d ;
input rst ;
input clr ;
input clk ;
output reg q ;
always @(posedge clk or negedge rst)
begin
 if (rst == 1'b0)
 q <= 0 ;
 else if (clr == 1'b1)
 q <= 0 ;
 else
 q <= d ;
end
endmodule

4.5 移位寄存器

module top(d, rst, clk, q) ;
input d ;
input rst ;
input clk ;
output reg [7:0] q ;
always @(posedge clk or negedge rst)
begin
 if (rst == 1'b0)
 q <= 0 ;
 else
 q <= {q[6:0], d} ; //向左移位
 //q <= {d, q[7:1]} ; //向右移位
end
endmodule

4.6 单口RAM

写地址与读地址公用一个地址,延迟一周将数据送出。

module top 
(
 input [7:0] data,
 input [5:0] addr,
 input wr,
 input clk,
 output [7:0] q 
);
reg [7:0] ram[63:0]; //declare ram 
reg [5:0] addr_reg; //addr register 
always @ (posedge clk)
begin
 if (wr) //write 
 ram[addr] <= data;
 addr_reg <= addr;
end
assign q = ram[addr_reg]; //read data 
endmodule

4.7 伪双口RAM

读写地址独立,可以随机选择写或读地址,同时进行读写操作。

module top 
(
 input [7:0] data,
 input [5:0] write_addr,
 input [5:0] read_addr, 
 input wr,
 input rd,
 input clk,
 output reg [7:0] q 
);
reg [7:0] ram[63:0]; //declare ram 
reg [5:0] addr_reg; //addr register 
always @ (posedge clk)
begin
 if (wr) //write 
 ram[write_addr] <= data;
 if (rd) //read 
 q <= ram[read_addr];
end
endmodule

4.8 真双口RAM

具有两套控制线,允许两个系统对其进行读写操作。

module top 
(
 input [7:0] data_a, data_b,
 input [5:0] addr_a, addr_b,
 input wr_a, wr_b,
 input rd_a, rd_b,
 input clk,
 output reg [7:0] q_a, q_b 
);
reg [7:0] ram[63:0]; //declare ram 

    //Port A 
always @ (posedge clk)
begin
 if (wr_a) //write 
 begin
 ram[addr_a] <= data_a;
 q_a <= data_a ;
 end
 if (rd_a) 
//read 
 q_a <= ram[addr_a];
end

    //Port B 
always @ (posedge clk)
begin
 if (wr_b) //write 
 begin
 ram[addr_b] <= data_b;
 q_b <= data_b ;
 end
 if (rd_b) 
//read 
 q_b <= ram[addr_b];
end
endmodule

4.9 单口ROM

ROM用来存储数据,可以使用下面的代码进行对ROM的初始化,推荐使用FPGA现成的IP核实现。

module top 
(
 input [3:0] addr,
 input clk,
 output reg [7:0] q 
);
reg [7:0] rom [15:0] ; //declare rom 
always @(addr)
begin
 case(addr)
 4'd0 : rom[addr] = 8'd15 ;
 4'd1 : rom[addr] = 8'd24 ;
 4'd2 : rom[addr] = 8'd100 ;
 4'd3 : rom[addr] = 8'd78 ;
 4'd4 : rom[addr] = 8'd98 ;
 4'd5 : rom[addr] = 8'd105 ;
 4'd6 : rom[addr] = 8'd86 ;
 4'd7 : rom[addr] = 8'd254 ;
 4'd8 : rom[addr] = 8'd76 ;
 4'd9 : rom[addr] = 8'd35 ;
 4'd10 : rom[addr] = 8'd120 ;
 4'd11 : rom[addr] = 8'd85 ;
 4'd12 : rom[addr] = 8'd37 ;
 4'd13 : rom[addr] = 8'd19 ;
 4'd14 : rom[addr] = 8'd22 ;
 4'd15 : rom[addr] = 8'd67 ;
 endcase
end
always @(posedge clk)
begin
 q <= rom[addr] ;
end
endmodule

4.10 有限状态机

4.10.1 Mealy型有限状态机

输出和当前状态和以及输入信号有关。

module top 
(
 input shift_start,
 input shift_stop,
 input rst,
 input clk,
 input d,
 output reg [7:0] q 
);
parameter Idle = 2'd0 ; //Idle state 
parameter Start = 2'd1 ; //Start state 
parameter Run = 2'd2 ; //Run state 
parameter Stop = 2'd3 ; //Stop state 

reg [1:0] state ; //statement 
reg [4:0] delay_cnt ; //delay counter 
always @(posedge clk or negedge rst)
begin
 if (!rst)
     begin
         state <= Idle ;
         delay_cnt <= 0 ;
         q <= 0 ;
     end
 else
     case(state)
     Idle : begin
         if (shift_start)
         state <= Start ;
     end
     Start : begin
         if (delay_cnt == 5'd99)
            begin
            delay_cnt <= 0 ;
            state <= Run ;
            end
         else
            delay_cnt <= delay_cnt + 1'b1 ;
     end
     Run : begin
     if (shift_stop)
        state <= Stop ;
     else
        q <= {q[6:0], d} ;
     end
     Stop : begin
         q <= 0 ;
         state <= Idle ;
     end
        default: state <= Idle ;
     endcase
     end 
endmodule

4.10.2 Moore型有限状态机

Moore 有限状态机,输出只与当前状态有关,与输入信号无关,输入信号只影响状态的改变, 不影响输出。

module top 
(
 input shift_start,
 input shift_stop,
 input rst,
 input clk,
 input d,
 output reg [7:0] q 
);
parameter Idle = 2'd0 ; //Idle state 
parameter Start = 2'd1 ; //Start state 
parameter Run = 2'd2 ; //Run state 
parameter Stop = 2'd3 ; //Stop state 

reg [1:0] current_state ; //statement 
reg [1:0] next_state ;
reg [4:0] delay_cnt ; //delay counter 
//First part: statement transition 
always @(posedge clk or negedge rst)
begin
     if (!rst)
     current_state <= Idle ;
     else
     current_state <= next_state ;
end
//Second part: combination logic, judge statement transition condition 
always @(*)
begin
 case(current_state)
     Idle : begin
         if (shift_start)
         next_state <= Start ;
         else
         next_state <= Idle ;
         end
     Start : begin
         if (delay_cnt == 5'd99)
         next_state <= Run ;
         else
         next_state <= Start ;
         end
     Run : begin
         if (shift_stop)
         next_state <= Stop ;
         else
         next_state <= Run ;
         end
         Stop : next_state <= Idle ;
     default: next_state <= Idle ;
     endcase
    end
//Last part: output data 
always @(posedge clk or negedge rst)
begin
 if (!rst)
    delay_cnt <= 0 ;
 else if (current_state == Start)
    delay_cnt <= delay_cnt + 1'b1 ;
 else
    delay_cnt <= 0 ;
end
always @(posedge clk or negedge rst)
begin
 if (!rst)
    q <= 0 ;
 else if (current_state == Run)
    q <= {q[6:0], d} ;
 else
    q <= 0 ;
end 

endmodule
  • alipay_img
  • wechat_img
危ねえだろうが!前見て歩け!
最后更新于 2024-04-09