九、电气装置的遥控器发射频率为38KHz的间歇红外波,需要一个脉冲调制信号,对于待发射的码序列中的“1”信号,脉冲调制信号的脉宽为4个时钟周期,占空比为1/8;对于“0”信号,脉冲调制信号的脉宽为2个时钟周期,占空比为1/4。如图6所示(所看到题目没图)。待发射的固定码序列存于移位寄存器中,以Reset信号启动一个电路模块,当Reset=1时,脉宽调制信号输出保持高电平;当Reset变为低电平时,电路模块按照移位寄存器最后一位的数码产生相应的脉宽调制信号,并发给移位寄存器一个时钟脉冲使之移位,继而产生脉宽调制信号序列。如图7所示。用硬件描述语言描述电路。
按题意可以分为移位寄存器描述模块和电路模块,其中电路模块包含两个分频模块,分别为4倍分频占空比为1/8,2倍分频占空比为1/4模块。下面分别是各个模块的描述。
1 // 移位寄存描述,这里在复位时寄存器有固定值
2 module shift_reg (clk_in,data_out,rst);
3 input clk_in,rst;
4 output data_out;
5
6 reg m1,m2,m3,m4,m5,data_out;
7
8 always @( posedge rst or posedge clk_in)
9 if (rst)
10 begin
11 m1 <= 1 ;
12 m2 <= 0 ;
13 m3 <= 0 ;
14 m4 <= 1 ;
15 m5 <= 0 ;
16 data_out <= 0 ;
17 end
18 else
19 begin
20 m2 <= m1;
21 m3 <= m2;
22 m4 <= m3;
23 m5 <= m4;
24 data_out <= m5;
25 end
26 endmodule
27
28
1 // 这里用时钟的上下跳变来产生1/4占空比
2 // 很多书都讲不要同时用上下跳变,但那是指不要在同一个
3 // always模块,这里是在不同always模块不同计数器中
4 module div_2(clk_in,rst,out2);
5 input clk_in,rst;
6 output out2;
7
8 reg [ 1 : 0 ] counter1,counter2;
9
10
11 always @( posedge rst or posedge clk_in)
12 begin
13 if (rst == 1 )
14 begin
15 counter1 <= 0 ;
16 counter2 <= 0 ;
17 end
18 else begin
19 if (counter1 == 1 )
20 begin
21 counter1 <= 0 ;
22 end
23 else begin
24 counter1 <= counter1 + 1 ;
25 end
26 end
27 end
28
29 always @( negedge clk_in)
30 if (counter2 == 1 )
31 counter2 <= 0 ;
32 else counter2 <= counter2 + 1 ;
33
34 assign out2 = counter1[ 0 ] & counter2[ 0 ];
35 endmodule
36
37
38
1 module test_div_2;
2 reg clk_in,rst;
3 wire out2;
4
5 initial begin clk_in <= 0 ;
6 rst <= 0 ;
7 # 10 rst <= 1 ;
8 # 10 rst <= 0 ;
9 end
10 always # 30 clk_in <=~ clk_in;
11
12 div_2 U (.clk_in(clk_in),.rst(rst),.out2(out2));
13 endmodule
14
测试结果图形:
module div_4(clk_in,rst,out1);
input clk_in,rst;
output out1;
reg [ 1 : 0 ] counter1,counter2;
always @( posedge rst or posedge clk_in)
begin
if (rst == 1 )
begin
counter1 <= 0 ;
counter2 <= 0 ;
end
else begin
if (counter1 == 3 )
begin
counter1 <= 0 ;
end
else begin
counter1 <= counter1 + 1 ;
end
end
end
always @( negedge clk_in)
if (counter2 == 3 )
counter2 <= 0 ;
else counter2 <= counter2 + 1 ;
assign out1 = counter1[ 0 ] & counter1[ 1 ] & counter2[ 0 ] & counter2[ 1 ];
endmodule
module test_div_4;
reg clk_in,rst;
wire out1;
initial begin clk_in <= 0 ;
rst <= 0 ;
# 10 rst <= 1 ;
# 10 rst <= 0 ;
end
always # 30 clk_in <=~ clk_in;
div_4 U (.clk_in(clk_in),.rst(rst),.out1(out1));
endmodule
测试结果:
1 // data是移位寄存的输出数据,clk_out是输入移位寄存器的时钟
2 // out是电路模块的输出
3 module transmit(data,clk_in,rst,out,clk_out);
4 input data,clk_in,rst;
5 output out,clk_out;
6
7 reg [ 1 : 0 ] counter1;
8 reg [ 1 : 0 ] counter2;
9 wire out1,out2;
10 reg clk_out;
11
12 div_4 U1(.clk_in(clk_in),.rst(rst),.out1(out1));
13 div_2 U2(.clk_in(clk_in),.rst(rst),.out2(out2));
14
15 always @( posedge rst or posedge clk_in)
16 if (rst == 1 )
17 begin
18 counter1 <= 0 ;
19 counter2 <= 0 ;
20 clk_out <= 0 ;
21 end
22 else begin
23 if (data)
24 begin
25 if (counter1 == 3 )
26 begin
27 clk_out <= 1 ;
28 counter1 <= 0 ;
29 end
30 else begin
31 counter1 <= counter1 + 1 ;
32 clk_out <= 0 ;
33 end
34 end
35 else
36 begin
37 if (counter2 == 1 )
38 begin
39 clk_out <= 1 ;
40 counter2 <= 0 ;
41 end
42 else begin
43 counter2 <= counter2 + 1 ;
44 clk_out <= 0 ;
45 end
46 end
47 end
48
49 assign out = data ? out1:out2;
50 endmodule
1 // 其中data_out及clk_out是为了观测相应的数据方便才写在输出端口
2 module transmit_shift(rst,clk_in,out,data_out,clk_out);
3 input rst,clk_in;
4 output out,data_out,clk_out;
5
6 wire clk_out,data_out;
7
8 transmit U1 (.rst(rst),.clk_in(clk_in),.out(out),.clk_out(clk_out),
9 .data(data_out));
10 shift_reg U2 (.rst(rst),.clk_in(clk_out),.data_out(data_out));
11
12 endmodule
13
14
15 module test_transmit_shift;
16 reg clk_in,rst;
17 wire out,data_out,clk_out;
18
19 initial begin clk_in <= 0 ;
20 rst <= 0 ;
21 # 10 rst <= 1 ;
22 # 10 rst <= 0 ;
23 end
24
25 always # 30 clk_in <=~ clk_in;
26
27 transmit_shift C (.rst(rst),.clk_in(clk_in),.out(out),
28 .data_out(data_out),.clk_out(clk_out));
29 endmodule
30
测试结果:
这道题总体难度不大,但要在很短时间内完成还是有点难度,难点在于两个分频模块的编写。这里都是用时钟的上下跳变来计数,然后通过与来得到占空比不为50%的分频电路。