Verilog小电路(1)

  • 1 存储器建模
  • 2 三分频时钟,占空比50%
  • 3 普通分频–2分频 4分频
  • 4 同步复位/异步复位/异步复位同步释放
  • 5 串并转化电路

1. 存储器建模

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 module ram_basic (clk, CS, WR, addr, data_in, data_out, en);
input clk;
input CS; //CS = 1, RAM enable
input WR; //WR =1 then WRite enable; WR = 0 then read enable
input en; //data_out enable, convert the data sequency
input [5:0] addr;
input [7:0] data_in;
output [7:0] data_out;

reg [7:0] RAM8x64 [0:63];
reg [7:0] mem_data;

always @ (posedge clk)
if (WR && CS) //WRite
RAM8x64 [addr] <= data_in [7:0];
else if (~WR && CS ) // read
mem_data <= RAM8x64 [addr];

assign data_out = (en)? mem_data[7:0] : {~mem_data[7], mem_data[6:0]};

endmodule

2. 三分频时钟,占空比50%

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 module clk_3div (clk,reset,clk_out);

input clk, reset;
output clk_out;
reg[1:0] state;
reg clk1;
always @(posedge clk or negedge reset)
if(!reset)
state<=2'b00;
else
case(state)
2'b00:state<=2'b01;
2'b01:state<=2'b11;
2'b11:state<=2'b00;
default:state<=2'b00;
endcase

always @(negedge clk or negedge reset)
if(!reset)
clk1<=1'b0;
else
clk1<=state[0];

assign clk_out=state[0]&clk1;
endmodule

3. 普通分频–2分频 4分频

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
module clk_div_phase (rst, clk_200K, clk_100K, clk_50K, clk_25K);

input clk_200K;
input rst;
output clk_100K, clk_50K, clk_25K;
wire clk_100K, clk_50K, clk_25K;

reg [2:0] cnt;

always @ (posedge clk_200K or negedge rst)
if (!rst)
cnt <= 3'b000;
else
cnt <= cnt + 1;

assign clk_100K = ~cnt [0];
assign clk_50K = ~cnt [1];
assign clk_25K = ~cnt [2];

endmodule

4. 同步复位/异步复位/异步复位同步释放

大多数的PLD和ASIC库中的触发器包含异步复位端口。自己考到的RTL大多是异步复位。

1
always @(posedge clk or negedge rst_n)

无论异步还是同步都有优缺点,推荐采用异步复位同步释放的方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 module asyn_rst_syn_release(clk, rst_, cnt1, cnt2);

input clk;
input rst_;
output [4:0] cnt1 , cnt2;
reg [4:0] cnt1 , cnt2;

// reset release circuit
reg reset_reg;
always @ (posedge clk)
reset_reg <= rst_;
always @ (posedge clk or negedge reset_reg)
if (!rst_)
begin
cnt1 <= 4'b0;
cnt2 <= 4'b0;
end
else
begin
if (cnt1 < 2'b11)
cnt1 <= cnt1 + 1;
else
cnt1 <= cnt1;
cnt2 <= cnt1 - 1;
end


endmodule

5. 串并转化电路

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 //串转并
//这里的时钟是串口的时钟(串口时钟频率高)
module srl2pal (clk, rst, srl_in, pal_out);

input clk;
input rst;
input srl_in;
output [7:0] pal_out;
reg [7:0] pal_out;

always @ (posedge clk or negedge rst)
if (!rst)
pal_out <= 8'b0;
else
pal_out <= {pal_out,srl_in};


endmodule
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//并转串
//这里的时钟也是串口的时钟(串口时钟频率高)
module pal2srl(clk,rst,pal_in,srl_out);
input clk,rst;
input [7:0] pal_in;
output srl_out;

reg d_o;
reg[2:0] index;
always@(posedge clk or negedge rst) begin
if(!rst) begin
index <= 3'b000;
end
else begin
case(index)
3'b000:index <= 3'b001;
3'b001:index <= 3'b010;
3'b010:index <= 3'b011;
3'b011:index <= 3'b100;
3'b100:index <= 3'b101;
3'b101:index <= 3'b110;
3'b110:index <= 3'b111;
3'b111:index <= 3'b000;
default:index <= 3'b000;
endcase
end
end
always@(posedge clk or negedge rst) begin
if(!rst) begin
srl_out <= 1'b0;
end
else begin
d_o <= pal_in[index];
end
end
assign srl_out = d_o;
endmodule

串并转换也可以通过移位寄存器来实现

下图是串行转并行

如果是并行转串行,就是同时将四位数据置入移位寄存器的四个触发器中,然后加入四个移位脉冲(clk),数据串行地从D0输出。

6. 不用下降沿触发的11分频电路

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
`timescale 1ns/1ps

//11分频电路
module test(
input clk,
input rst_n,
output clk_div11
);
reg [3:0] cnt;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt<=4'd0;
end
else begin
if(cnt<4'd10)begin
cnt<=cnt+1'b1;
end
else begin
cnt<=4'd0;
end
end
end
// 在波形中观察比较清楚
assign clk_div11= (cnt<4'd5)?1'b1:((cnt>4'd5)?1'b0:clk);

endmodule

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!